2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/utsname.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
49 #if HAVE_SYS_PERSONALITY_H
50 #include <sys/personality.h>
53 lxc_log_define(lxc_confile
, lxc
);
55 static int config_personality(const char *, const char *, struct lxc_conf
*);
56 static int config_pts(const char *, const char *, struct lxc_conf
*);
57 static int config_tty(const char *, const char *, struct lxc_conf
*);
58 static int config_ttydir(const char *, const char *, struct lxc_conf
*);
59 static int config_kmsg(const char *, const char *, struct lxc_conf
*);
61 static int config_aa_profile(const char *, const char *, struct lxc_conf
*);
63 static int config_cgroup(const char *, const char *, struct lxc_conf
*);
64 static int config_idmap(const char *, const char *, struct lxc_conf
*);
65 static int config_loglevel(const char *, const char *, struct lxc_conf
*);
66 static int config_logfile(const char *, const char *, struct lxc_conf
*);
67 static int config_mount(const char *, const char *, struct lxc_conf
*);
68 static int config_rootfs(const char *, const char *, struct lxc_conf
*);
69 static int config_rootfs_mount(const char *, const char *, struct lxc_conf
*);
70 static int config_pivotdir(const char *, const char *, struct lxc_conf
*);
71 static int config_utsname(const char *, const char *, struct lxc_conf
*);
72 static int config_hook(const char *, const char *, struct lxc_conf
*lxc_conf
);
73 static int config_network_type(const char *, const char *, struct lxc_conf
*);
74 static int config_network_flags(const char *, const char *, struct lxc_conf
*);
75 static int config_network_link(const char *, const char *, struct lxc_conf
*);
76 static int config_network_name(const char *, const char *, struct lxc_conf
*);
77 static int config_network_veth_pair(const char *, const char *, struct lxc_conf
*);
78 static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf
*);
79 static int config_network_hwaddr(const char *, const char *, struct lxc_conf
*);
80 static int config_network_vlan_id(const char *, const char *, struct lxc_conf
*);
81 static int config_network_mtu(const char *, const char *, struct lxc_conf
*);
82 static int config_network_ipv4(const char *, const char *, struct lxc_conf
*);
83 static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf
*);
84 static int config_network_script(const char *, const char *, struct lxc_conf
*);
85 static int config_network_ipv6(const char *, const char *, struct lxc_conf
*);
86 static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf
*);
87 static int config_cap_drop(const char *, const char *, struct lxc_conf
*);
88 static int config_console(const char *, const char *, struct lxc_conf
*);
89 static int config_seccomp(const char *, const char *, struct lxc_conf
*);
90 static int config_includefile(const char *, const char *, struct lxc_conf
*);
91 static int config_network_nic(const char *, const char *, struct lxc_conf
*);
92 static int config_autodev(const char *, const char *, struct lxc_conf
*);
93 static int config_stopsignal(const char *, const char *, struct lxc_conf
*);
95 static struct lxc_config_t config
[] = {
97 { "lxc.arch", config_personality
},
98 { "lxc.pts", config_pts
},
99 { "lxc.tty", config_tty
},
100 { "lxc.devttydir", config_ttydir
},
101 { "lxc.kmsg", config_kmsg
},
103 { "lxc.aa_profile", config_aa_profile
},
105 { "lxc.cgroup", config_cgroup
},
106 { "lxc.id_map", config_idmap
},
107 { "lxc.loglevel", config_loglevel
},
108 { "lxc.logfile", config_logfile
},
109 { "lxc.mount", config_mount
},
110 { "lxc.rootfs.mount", config_rootfs_mount
},
111 { "lxc.rootfs", config_rootfs
},
112 { "lxc.pivotdir", config_pivotdir
},
113 { "lxc.utsname", config_utsname
},
114 { "lxc.hook.pre-start", config_hook
},
115 { "lxc.hook.pre-mount", config_hook
},
116 { "lxc.hook.mount", config_hook
},
117 { "lxc.hook.autodev", config_hook
},
118 { "lxc.hook.start", config_hook
},
119 { "lxc.hook.post-stop", config_hook
},
120 { "lxc.network.type", config_network_type
},
121 { "lxc.network.flags", config_network_flags
},
122 { "lxc.network.link", config_network_link
},
123 { "lxc.network.name", config_network_name
},
124 { "lxc.network.macvlan.mode", config_network_macvlan_mode
},
125 { "lxc.network.veth.pair", config_network_veth_pair
},
126 { "lxc.network.script.up", config_network_script
},
127 { "lxc.network.script.down", config_network_script
},
128 { "lxc.network.hwaddr", config_network_hwaddr
},
129 { "lxc.network.mtu", config_network_mtu
},
130 { "lxc.network.vlan.id", config_network_vlan_id
},
131 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway
},
132 { "lxc.network.ipv4", config_network_ipv4
},
133 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway
},
134 { "lxc.network.ipv6", config_network_ipv6
},
135 /* config_network_nic must come after all other 'lxc.network.*' entries */
136 { "lxc.network.", config_network_nic
},
137 { "lxc.cap.drop", config_cap_drop
},
138 { "lxc.console", config_console
},
139 { "lxc.seccomp", config_seccomp
},
140 { "lxc.include", config_includefile
},
141 { "lxc.autodev", config_autodev
},
142 { "lxc.stopsignal", config_stopsignal
},
150 struct signame signames
[] = {
172 static const size_t config_size
= sizeof(config
)/sizeof(struct lxc_config_t
);
174 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
178 for (i
= 0; i
< config_size
; i
++)
179 if (!strncmp(config
[i
].name
, key
,
180 strlen(config
[i
].name
)))
185 #define strprint(str, inlen, ...) \
187 len = snprintf(str, inlen, ##__VA_ARGS__); \
188 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
191 if (str) str += len; \
193 if (inlen < 0) inlen = 0; \
197 int lxc_listconfigs(char *retv
, int inlen
)
199 int i
, fulllen
= 0, len
;
204 memset(retv
, 0, inlen
);
205 for (i
= 0; i
< config_size
; i
++) {
206 char *s
= config
[i
].name
;
207 if (s
[strlen(s
)-1] == '.')
209 strprint(retv
, inlen
, "%s\n", s
);
215 * config entry is something like "lxc.network.0.ipv4"
216 * the key 'lxc.network.' was found. So we make sure next
217 * comes an integer, find the right callback (by rewriting
218 * the key), and call it.
220 static int config_network_nic(const char *key
, const char *value
,
221 struct lxc_conf
*lxc_conf
)
223 char *copy
= strdup(key
), *p
;
225 struct lxc_config_t
*config
;
228 SYSERROR("failed to allocate memory");
232 * ok we know that to get here we've got "lxc.network."
233 * and it isn't any of the other network entries. So
234 * after the second . should come an integer (# of defined
235 * nic) followed by a valid entry.
237 if (*(key
+12) < '0' || *(key
+12) > '9')
239 p
= index(key
+12, '.');
242 strcpy(copy
+12, p
+1);
243 config
= lxc_getconfig(copy
);
245 ERROR("unknown key %s", key
);
248 ret
= config
->cb(key
, value
, lxc_conf
);
255 static int config_network_type(const char *key
, const char *value
,
256 struct lxc_conf
*lxc_conf
)
258 struct lxc_list
*network
= &lxc_conf
->network
;
259 struct lxc_netdev
*netdev
;
260 struct lxc_list
*list
;
262 netdev
= malloc(sizeof(*netdev
));
264 SYSERROR("failed to allocate memory");
268 memset(netdev
, 0, sizeof(*netdev
));
269 lxc_list_init(&netdev
->ipv4
);
270 lxc_list_init(&netdev
->ipv6
);
272 list
= malloc(sizeof(*list
));
274 SYSERROR("failed to allocate memory");
282 lxc_list_add_tail(network
, list
);
284 if (!strcmp(value
, "veth"))
285 netdev
->type
= LXC_NET_VETH
;
286 else if (!strcmp(value
, "macvlan"))
287 netdev
->type
= LXC_NET_MACVLAN
;
288 else if (!strcmp(value
, "vlan"))
289 netdev
->type
= LXC_NET_VLAN
;
290 else if (!strcmp(value
, "phys"))
291 netdev
->type
= LXC_NET_PHYS
;
292 else if (!strcmp(value
, "empty"))
293 netdev
->type
= LXC_NET_EMPTY
;
295 ERROR("invalid network type %s", value
);
301 static int config_ip_prefix(struct in_addr
*addr
)
303 if (IN_CLASSA(addr
->s_addr
))
304 return 32 - IN_CLASSA_NSHIFT
;
305 if (IN_CLASSB(addr
->s_addr
))
306 return 32 - IN_CLASSB_NSHIFT
;
307 if (IN_CLASSC(addr
->s_addr
))
308 return 32 - IN_CLASSC_NSHIFT
;
314 * if you have p="lxc.network.0.link", pass it p+12
315 * to get back '0' (the index of the nic)
317 static int get_network_netdev_idx(const char *key
)
321 if (*key
< '0' || *key
> '9')
323 ret
= sscanf(key
, "%d", &idx
);
330 * if you have p="lxc.network.0", pass this p+12 and it will return
331 * the netdev of the first configured nic
333 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
334 struct lxc_list
*network
)
336 int i
= 0, idx
= get_network_netdev_idx(key
);
337 struct lxc_netdev
*netdev
= NULL
;
341 lxc_list_for_each(it
, network
) {
350 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
,
351 char *retv
, int inlen
)
353 struct lxc_netdev
*netdev
;
354 int fulllen
= 0, len
;
356 netdev
= get_netdev_from_key(key
+12, &c
->network
);
363 memset(retv
, 0, inlen
);
365 strprint(retv
, inlen
, "script.up\n");
366 if (netdev
->type
!= LXC_NET_EMPTY
) {
367 strprint(retv
, inlen
, "flags\n");
368 strprint(retv
, inlen
, "link\n");
369 strprint(retv
, inlen
, "name\n");
370 strprint(retv
, inlen
, "hwaddr\n");
371 strprint(retv
, inlen
, "mtu\n");
372 strprint(retv
, inlen
, "ipv6\n");
373 strprint(retv
, inlen
, "ipv6_gateway\n");
374 strprint(retv
, inlen
, "ipv4\n");
375 strprint(retv
, inlen
, "ipv4_gateway\n");
377 switch(netdev
->type
) {
379 strprint(retv
, inlen
, "veth.pair\n");
381 case LXC_NET_MACVLAN
:
382 strprint(retv
, inlen
, "macvlan.mode\n");
385 strprint(retv
, inlen
, "vlan.id\n");
393 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
394 struct lxc_list
*network
)
396 struct lxc_netdev
*netdev
= NULL
;
398 if (lxc_list_empty(network
)) {
399 ERROR("network is not created for '%s' = '%s' option",
404 if (get_network_netdev_idx(key
+12) == -1)
405 netdev
= lxc_list_last_elem(network
);
407 netdev
= get_netdev_from_key(key
+12, network
);
410 ERROR("no network device defined for '%s' = '%s' option",
418 static int network_ifname(char **valuep
, const char *value
)
420 if (strlen(value
) >= IFNAMSIZ
) {
421 ERROR("interface name '%s' too long (>%d)\n",
422 value
, IFNAMSIZ
- 1);
426 *valuep
= strdup(value
);
428 ERROR("failed to dup string '%s'", value
);
435 #ifndef MACVLAN_MODE_PRIVATE
436 # define MACVLAN_MODE_PRIVATE 1
439 #ifndef MACVLAN_MODE_VEPA
440 # define MACVLAN_MODE_VEPA 2
443 #ifndef MACVLAN_MODE_BRIDGE
444 # define MACVLAN_MODE_BRIDGE 4
447 static int macvlan_mode(int *valuep
, const char *value
)
453 { "private", MACVLAN_MODE_PRIVATE
},
454 { "vepa", MACVLAN_MODE_VEPA
},
455 { "bridge", MACVLAN_MODE_BRIDGE
},
460 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
461 if (strcmp(m
[i
].name
, value
))
471 static int config_network_flags(const char *key
, const char *value
,
472 struct lxc_conf
*lxc_conf
)
474 struct lxc_netdev
*netdev
;
476 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
480 netdev
->flags
|= IFF_UP
;
485 static int config_network_link(const char *key
, const char *value
,
486 struct lxc_conf
*lxc_conf
)
488 struct lxc_netdev
*netdev
;
490 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
494 return network_ifname(&netdev
->link
, value
);
497 static int config_network_name(const char *key
, const char *value
,
498 struct lxc_conf
*lxc_conf
)
500 struct lxc_netdev
*netdev
;
502 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
506 return network_ifname(&netdev
->name
, value
);
509 static int config_network_veth_pair(const char *key
, const char *value
,
510 struct lxc_conf
*lxc_conf
)
512 struct lxc_netdev
*netdev
;
514 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
518 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
521 static int config_network_macvlan_mode(const char *key
, const char *value
,
522 struct lxc_conf
*lxc_conf
)
524 struct lxc_netdev
*netdev
;
526 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
530 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
533 static int config_network_hwaddr(const char *key
, const char *value
,
534 struct lxc_conf
*lxc_conf
)
536 struct lxc_netdev
*netdev
;
539 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
543 hwaddr
= strdup(value
);
545 SYSERROR("failed to dup string '%s'", value
);
550 free(netdev
->hwaddr
);
551 netdev
->hwaddr
= hwaddr
;
555 static int config_network_vlan_id(const char *key
, const char *value
,
556 struct lxc_conf
*lxc_conf
)
558 struct lxc_netdev
*netdev
;
560 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
564 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
570 static int config_network_mtu(const char *key
, const char *value
,
571 struct lxc_conf
*lxc_conf
)
573 struct lxc_netdev
*netdev
;
576 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
582 SYSERROR("failed to dup string '%s'", value
);
592 static int config_network_ipv4(const char *key
, const char *value
,
593 struct lxc_conf
*lxc_conf
)
595 struct lxc_netdev
*netdev
;
596 struct lxc_inetdev
*inetdev
;
597 struct lxc_list
*list
;
598 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
600 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
604 inetdev
= malloc(sizeof(*inetdev
));
606 SYSERROR("failed to allocate ipv4 address");
609 memset(inetdev
, 0, sizeof(*inetdev
));
611 list
= malloc(sizeof(*list
));
613 SYSERROR("failed to allocate memory");
619 list
->elem
= inetdev
;
621 addr
= strdup(value
);
623 ERROR("no address specified");
629 cursor
= strstr(addr
, " ");
635 slash
= strstr(addr
, "/");
641 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
642 SYSERROR("invalid ipv4 address: %s", value
);
649 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
650 SYSERROR("invalid ipv4 broadcast address: %s", value
);
657 /* no prefix specified, determine it from the network class */
658 inetdev
->prefix
= prefix
? atoi(prefix
) :
659 config_ip_prefix(&inetdev
->addr
);
661 /* if no broadcast address, let compute one from the
665 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
666 inetdev
->bcast
.s_addr
|=
667 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
670 lxc_list_add_tail(&netdev
->ipv4
, list
);
676 static int config_network_ipv4_gateway(const char *key
, const char *value
,
677 struct lxc_conf
*lxc_conf
)
679 struct lxc_netdev
*netdev
;
682 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
686 gw
= malloc(sizeof(*gw
));
688 SYSERROR("failed to allocate ipv4 gateway address");
693 ERROR("no ipv4 gateway address specified");
698 if (!strcmp(value
, "auto")) {
699 netdev
->ipv4_gateway
= NULL
;
700 netdev
->ipv4_gateway_auto
= true;
702 if (!inet_pton(AF_INET
, value
, gw
)) {
703 SYSERROR("invalid ipv4 gateway address: %s", value
);
708 netdev
->ipv4_gateway
= gw
;
709 netdev
->ipv4_gateway_auto
= false;
715 static int config_network_ipv6(const char *key
, const char *value
,
716 struct lxc_conf
*lxc_conf
)
718 struct lxc_netdev
*netdev
;
719 struct lxc_inet6dev
*inet6dev
;
720 struct lxc_list
*list
;
724 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
728 inet6dev
= malloc(sizeof(*inet6dev
));
730 SYSERROR("failed to allocate ipv6 address");
733 memset(inet6dev
, 0, sizeof(*inet6dev
));
735 list
= malloc(sizeof(*list
));
737 SYSERROR("failed to allocate memory");
743 list
->elem
= inet6dev
;
745 valdup
= strdup(value
);
747 ERROR("no address specified");
753 inet6dev
->prefix
= 64;
754 slash
= strstr(valdup
, "/");
758 inet6dev
->prefix
= atoi(netmask
);
761 if (!inet_pton(AF_INET6
, value
, &inet6dev
->addr
)) {
762 SYSERROR("invalid ipv6 address: %s", value
);
769 lxc_list_add_tail(&netdev
->ipv6
, list
);
775 static int config_network_ipv6_gateway(const char *key
, const char *value
,
776 struct lxc_conf
*lxc_conf
)
778 struct lxc_netdev
*netdev
;
781 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
785 gw
= malloc(sizeof(*gw
));
787 SYSERROR("failed to allocate ipv6 gateway address");
792 ERROR("no ipv6 gateway address specified");
796 if (!strcmp(value
, "auto")) {
797 netdev
->ipv6_gateway
= NULL
;
798 netdev
->ipv6_gateway_auto
= true;
800 if (!inet_pton(AF_INET6
, value
, gw
)) {
801 SYSERROR("invalid ipv6 gateway address: %s", value
);
806 netdev
->ipv6_gateway
= gw
;
807 netdev
->ipv6_gateway_auto
= false;
813 static int config_network_script(const char *key
, const char *value
,
814 struct lxc_conf
*lxc_conf
)
816 struct lxc_netdev
*netdev
;
818 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
822 char *copy
= strdup(value
);
824 SYSERROR("failed to dup string '%s'", value
);
827 if (strstr(key
, "script.up") != NULL
) {
828 netdev
->upscript
= copy
;
831 if (strcmp(key
, "lxc.network.script.down") == 0) {
832 netdev
->downscript
= copy
;
835 SYSERROR("Unknown key: %s", key
);
840 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
842 struct lxc_list
*hooklist
;
844 hooklist
= malloc(sizeof(*hooklist
));
849 hooklist
->elem
= hook
;
850 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
854 static int config_seccomp(const char *key
, const char *value
,
855 struct lxc_conf
*lxc_conf
)
859 if (lxc_conf
->seccomp
) {
860 ERROR("seccomp already defined");
863 path
= strdup(value
);
865 SYSERROR("failed to strdup '%s': %m", value
);
869 if (lxc_conf
->seccomp
)
870 free(lxc_conf
->seccomp
);
871 lxc_conf
->seccomp
= path
;
876 static int config_hook(const char *key
, const char *value
,
877 struct lxc_conf
*lxc_conf
)
879 char *copy
= strdup(value
);
881 SYSERROR("failed to dup string '%s'", value
);
884 if (strcmp(key
, "lxc.hook.pre-start") == 0)
885 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
886 else if (strcmp(key
, "lxc.hook.pre-mount") == 0)
887 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
888 else if (strcmp(key
, "lxc.hook.autodev") == 0)
889 return add_hook(lxc_conf
, LXCHOOK_AUTODEV
, copy
);
890 else if (strcmp(key
, "lxc.hook.mount") == 0)
891 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
892 else if (strcmp(key
, "lxc.hook.start") == 0)
893 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
894 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
895 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
896 SYSERROR("Unknown key: %s", key
);
901 static int config_personality(const char *key
, const const char *value
,
902 struct lxc_conf
*lxc_conf
)
904 signed long personality
= lxc_config_parse_arch(value
);
906 if (personality
>= 0)
907 lxc_conf
->personality
= personality
;
909 WARN("unsupported personality '%s'", value
);
914 static int config_pts(const char *key
, const char *value
,
915 struct lxc_conf
*lxc_conf
)
917 int maxpts
= atoi(value
);
919 lxc_conf
->pts
= maxpts
;
924 static int config_tty(const char *key
, const char *value
,
925 struct lxc_conf
*lxc_conf
)
927 int nbtty
= atoi(value
);
929 lxc_conf
->tty
= nbtty
;
934 static int config_ttydir(const char *key
, const char *value
,
935 struct lxc_conf
*lxc_conf
)
939 if (!value
|| strlen(value
) == 0)
941 path
= strdup(value
);
943 SYSERROR("failed to strdup '%s': %m", value
);
947 if (lxc_conf
->ttydir
)
948 free(lxc_conf
->ttydir
);
949 lxc_conf
->ttydir
= path
;
954 static int config_kmsg(const char *key
, const char *value
,
955 struct lxc_conf
*lxc_conf
)
965 static int config_aa_profile(const char *key
, const char *value
,
966 struct lxc_conf
*lxc_conf
)
970 if (!value
|| strlen(value
) == 0)
972 path
= strdup(value
);
974 SYSERROR("failed to strdup '%s': %m", value
);
978 if (lxc_conf
->aa_profile
)
979 free(lxc_conf
->aa_profile
);
980 lxc_conf
->aa_profile
= path
;
986 static int config_logfile(const char *key
, const char *value
,
987 struct lxc_conf
*lxc_conf
)
989 return lxc_log_set_file(value
);
992 static int config_loglevel(const char *key
, const char *value
,
993 struct lxc_conf
*lxc_conf
)
997 if (!value
|| strlen(value
) == 0)
1000 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET
) {
1001 DEBUG("Log level already set - ignoring new value");
1004 if (value
[0] >= '0' && value
[0] <= '9')
1005 newlevel
= atoi(value
);
1007 newlevel
= lxc_log_priority_to_int(value
);
1008 return lxc_log_set_level(newlevel
);
1011 static int config_autodev(const char *key
, const char *value
,
1012 struct lxc_conf
*lxc_conf
)
1014 int v
= atoi(value
);
1016 lxc_conf
->autodev
= v
;
1021 static int sig_num(const char *sig
)
1027 n
= strtol(sig
, &endp
, 10);
1028 if (sig
== endp
|| n
< 0 || errno
!= 0)
1033 static int rt_sig_num(const char *signame
)
1038 if (strncasecmp(signame
, "max-", 4) == 0) {
1042 if (!isdigit(*signame
))
1044 sig_n
= sig_num(signame
);
1045 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1046 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1051 static int sig_parse(const char *signame
) {
1054 if (isdigit(*signame
)) {
1055 return sig_num(signame
);
1056 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1058 if (strncasecmp(signame
, "rt", 2) == 0)
1059 return rt_sig_num(signame
+ 2);
1060 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1061 if (strcasecmp (signames
[n
].name
, signame
) == 0)
1062 return signames
[n
].num
;
1068 static int config_stopsignal(const char *key
, const char *value
,
1069 struct lxc_conf
*lxc_conf
)
1071 int sig_n
= sig_parse(value
);
1075 lxc_conf
->stopsignal
= sig_n
;
1080 static int config_cgroup(const char *key
, const char *value
,
1081 struct lxc_conf
*lxc_conf
)
1083 char *token
= "lxc.cgroup.";
1085 struct lxc_list
*cglist
= NULL
;
1086 struct lxc_cgroup
*cgelem
= NULL
;
1088 subkey
= strstr(key
, token
);
1093 if (!strlen(subkey
))
1096 if (strlen(subkey
) == strlen(token
))
1099 subkey
+= strlen(token
);
1101 cglist
= malloc(sizeof(*cglist
));
1105 cgelem
= malloc(sizeof(*cgelem
));
1108 memset(cgelem
, 0, sizeof(*cgelem
));
1110 cgelem
->subsystem
= strdup(subkey
);
1111 cgelem
->value
= strdup(value
);
1113 if (!cgelem
->subsystem
|| !cgelem
->value
)
1116 cglist
->elem
= cgelem
;
1118 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1127 if (cgelem
->subsystem
)
1128 free(cgelem
->subsystem
);
1131 free(cgelem
->value
);
1139 static int config_idmap(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
1141 char *token
= "lxc.id_map";
1143 struct lxc_list
*idmaplist
= NULL
;
1144 struct id_map
*idmap
= NULL
;
1145 unsigned long hostid
, nsid
, range
;
1149 subkey
= strstr(key
, token
);
1154 if (!strlen(subkey
))
1157 idmaplist
= malloc(sizeof(*idmaplist
));
1161 idmap
= malloc(sizeof(*idmap
));
1164 memset(idmap
, 0, sizeof(*idmap
));
1166 idmaplist
->elem
= idmap
;
1168 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1170 ret
= sscanf(value
, "%c %lu %lu %lu", &type
, &nsid
, &hostid
, &range
);
1173 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1175 idmap
->idtype
= ID_TYPE_UID
;
1176 else if (type
== 'g')
1177 idmap
->idtype
= ID_TYPE_GID
;
1180 idmap
->hostid
= hostid
;
1182 idmap
->range
= range
;
1197 static int config_path_item(const char *key
, const char *value
,
1198 struct lxc_conf
*lxc_conf
, char **conf_item
)
1201 if (strlen(value
) >= MAXPATHLEN
) {
1202 ERROR("%s path is too long", value
);
1206 valdup
= strdup(value
);
1208 SYSERROR("failed to duplicate string %s", value
);
1213 *conf_item
= valdup
;
1218 static int config_fstab(const char *key
, const char *value
,
1219 struct lxc_conf
*lxc_conf
)
1221 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->fstab
);
1224 static int config_mount(const char *key
, const char *value
,
1225 struct lxc_conf
*lxc_conf
)
1227 char *fstab_token
= "lxc.mount";
1228 char *token
= "lxc.mount.entry";
1231 struct lxc_list
*mntlist
;
1233 subkey
= strstr(key
, token
);
1236 subkey
= strstr(key
, fstab_token
);
1241 return config_fstab(key
, value
, lxc_conf
);
1244 if (!strlen(subkey
))
1247 mntlist
= malloc(sizeof(*mntlist
));
1251 mntelem
= strdup(value
);
1256 mntlist
->elem
= mntelem
;
1258 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1263 static int config_cap_drop(const char *key
, const char *value
,
1264 struct lxc_conf
*lxc_conf
)
1266 char *dropcaps
, *dropptr
, *sptr
, *token
;
1267 struct lxc_list
*droplist
;
1273 dropcaps
= strdup(value
);
1275 SYSERROR("failed to dup '%s'", value
);
1279 /* in case several capability drop is specified in a single line
1280 * split these caps in a single element for the list */
1281 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
1282 token
= strtok_r(dropptr
, " \t", &sptr
);
1288 droplist
= malloc(sizeof(*droplist
));
1290 SYSERROR("failed to allocate drop list");
1294 droplist
->elem
= strdup(token
);
1295 if (!droplist
->elem
) {
1296 SYSERROR("failed to dup '%s'", token
);
1301 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1309 static int config_console(const char *key
, const char *value
,
1310 struct lxc_conf
*lxc_conf
)
1314 path
= strdup(value
);
1316 SYSERROR("failed to strdup '%s': %m", value
);
1320 if (lxc_conf
->console
.path
)
1321 free(lxc_conf
->console
.path
);
1322 lxc_conf
->console
.path
= path
;
1327 static int config_includefile(const char *key
, const char *value
,
1328 struct lxc_conf
*lxc_conf
)
1330 return lxc_config_read(value
, lxc_conf
);
1333 static int config_rootfs(const char *key
, const char *value
,
1334 struct lxc_conf
*lxc_conf
)
1336 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.path
);
1339 static int config_rootfs_mount(const char *key
, const char *value
,
1340 struct lxc_conf
*lxc_conf
)
1342 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.mount
);
1345 static int config_pivotdir(const char *key
, const char *value
,
1346 struct lxc_conf
*lxc_conf
)
1348 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.pivot
);
1351 static int config_utsname(const char *key
, const char *value
,
1352 struct lxc_conf
*lxc_conf
)
1354 struct utsname
*utsname
;
1356 utsname
= malloc(sizeof(*utsname
));
1358 SYSERROR("failed to allocate memory");
1362 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1363 ERROR("node name '%s' is too long",
1369 strcpy(utsname
->nodename
, value
);
1370 if (lxc_conf
->utsname
)
1371 free(lxc_conf
->utsname
);
1372 lxc_conf
->utsname
= utsname
;
1377 static int parse_line(char *buffer
, void *data
)
1379 struct lxc_config_t
*config
;
1386 if (lxc_is_line_empty(buffer
))
1389 /* we have to dup the buffer otherwise, at the re-exec for
1390 * reboot we modified the original string on the stack by
1391 * replacing '=' by '\0' below
1393 linep
= line
= strdup(buffer
);
1395 SYSERROR("failed to allocate memory for '%s'", buffer
);
1399 line
+= lxc_char_left_gc(line
, strlen(line
));
1401 /* martian option - ignoring it, the commented lines beginning by '#'
1404 if (strncmp(line
, "lxc.", 4))
1409 dot
= strstr(line
, "=");
1411 ERROR("invalid configuration line: %s", line
);
1419 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1421 value
+= lxc_char_left_gc(value
, strlen(value
));
1422 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1424 config
= lxc_getconfig(key
);
1426 ERROR("unknown key %s", key
);
1430 ret
= config
->cb(key
, value
, data
);
1437 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1439 return parse_line(buffer
, conf
);
1442 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1444 if( access(file
, R_OK
) == -1 ) {
1447 /* Catch only the top level config file name in the structure */
1448 if( ! conf
->rcfile
) {
1449 conf
->rcfile
= strdup( file
);
1451 return lxc_file_for_each_line(file
, parse_line
, conf
);
1454 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1456 struct lxc_list
*dent
;
1458 dent
= malloc(sizeof(struct lxc_list
));
1463 lxc_list_add_tail(defines
, dent
);
1467 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1469 struct lxc_list
*it
,*next
;
1472 lxc_list_for_each(it
, defines
) {
1473 ret
= lxc_config_readline(it
->elem
, conf
);
1478 lxc_list_for_each_safe(it
, defines
, next
) {
1486 signed long lxc_config_parse_arch(const char *arch
)
1488 #if HAVE_SYS_PERSONALITY_H
1493 { "x86", PER_LINUX32
},
1494 { "i686", PER_LINUX32
},
1495 { "x86_64", PER_LINUX
},
1496 { "amd64", PER_LINUX
},
1498 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1502 for (i
= 0; i
< len
; i
++) {
1503 if (!strcmp(pername
[i
].name
, arch
))
1504 return pername
[i
].per
;
1511 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
1516 memset(retv
, 0, inlen
);
1517 return snprintf(retv
, inlen
, "%d", v
);
1520 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
1527 memset(retv
, 0, inlen
);
1529 #if HAVE_SYS_PERSONALITY_H
1532 switch(c
->personality
) {
1533 case PER_LINUX32
: strprint(retv
, inlen
, "x86"); break;
1534 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
1543 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1544 * then just the value(s) will be printed. Since there still could be
1545 * more than one, it is newline-separated.
1546 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1547 * already have newlines?)
1548 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1549 * in 'lxc.cgroup.subsystem.key = value' format.
1551 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
1554 int fulllen
= 0, len
;
1556 struct lxc_list
*it
;
1561 memset(retv
, 0, inlen
);
1563 if (strcmp(key
, "all") == 0)
1566 lxc_list_for_each(it
, &c
->cgroup
) {
1567 struct lxc_cgroup
*cg
= it
->elem
;
1569 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1570 } else if (strcmp(cg
->subsystem
, key
) == 0) {
1571 strprint(retv
, inlen
, "%s\n", cg
->value
);
1577 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
1581 int len
, fulllen
= 0, found
= -1;
1582 struct lxc_list
*it
;
1585 /* "lxc.hook.mount" */
1586 subkey
= index(key
, '.');
1587 if (subkey
) subkey
= index(subkey
+1, '.');
1593 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1594 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
1605 memset(retv
, 0, inlen
);
1607 lxc_list_for_each(it
, &c
->hooks
[found
]) {
1608 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1613 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
1615 int len
, fulllen
= 0;
1616 struct lxc_list
*it
;
1621 memset(retv
, 0, inlen
);
1623 lxc_list_for_each(it
, &c
->caps
) {
1624 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1629 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
1631 int len
, fulllen
= 0;
1632 struct lxc_list
*it
;
1637 memset(retv
, 0, inlen
);
1639 lxc_list_for_each(it
, &c
->mount_list
) {
1640 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1646 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1647 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1648 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1649 * of an address. ipv4 and ipv6 return lists (newline-separated).
1650 * things like veth.pair return '' if invalid (i.e. if called for vlan
1653 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
1657 int len
, fulllen
= 0;
1658 struct lxc_netdev
*netdev
;
1663 memset(retv
, 0, inlen
);
1665 p1
= index(key
, '.');
1666 if (!p1
|| *(p1
+1) == '\0') return -1;
1669 netdev
= get_netdev_from_key(key
, &c
->network
);
1672 if (strcmp(p1
, "name") == 0) {
1674 strprint(retv
, inlen
, "%s", netdev
->name
);
1675 } else if (strcmp(p1
, "type") == 0) {
1676 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
1677 } else if (strcmp(p1
, "link") == 0) {
1679 strprint(retv
, inlen
, "%s", netdev
->link
);
1680 } else if (strcmp(p1
, "flags") == 0) {
1681 if (netdev
->flags
& IFF_UP
)
1682 strprint(retv
, inlen
, "up");
1683 } else if (strcmp(p1
, "upscript") == 0) {
1684 if (netdev
->upscript
)
1685 strprint(retv
, inlen
, "%s", netdev
->upscript
);
1686 } else if (strcmp(p1
, "hwaddr") == 0) {
1688 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
1689 } else if (strcmp(p1
, "mtu") == 0) {
1691 strprint(retv
, inlen
, "%s", netdev
->mtu
);
1692 } else if (strcmp(p1
, "macvlan.mode") == 0) {
1693 if (netdev
->type
== LXC_NET_MACVLAN
) {
1695 switch (netdev
->priv
.macvlan_attr
.mode
) {
1696 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1697 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1698 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1699 default: mode
= "(invalid)"; break;
1701 strprint(retv
, inlen
, "%s", mode
);
1703 } else if (strcmp(p1
, "veth.pair") == 0) {
1704 if (netdev
->type
== LXC_NET_VETH
&& netdev
->priv
.veth_attr
.pair
)
1705 strprint(retv
, inlen
, "%s", netdev
->priv
.veth_attr
.pair
);
1706 } else if (strcmp(p1
, "vlan") == 0) {
1707 if (netdev
->type
== LXC_NET_VLAN
) {
1708 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
1710 } else if (strcmp(p1
, "ipv4_gateway") == 0) {
1711 if (netdev
->ipv4_gateway_auto
) {
1712 strprint(retv
, inlen
, "auto");
1713 } else if (netdev
->ipv4_gateway
) {
1714 char buf
[INET_ADDRSTRLEN
];
1715 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
1716 strprint(retv
, inlen
, "%s", buf
);
1718 } else if (strcmp(p1
, "ipv4") == 0) {
1719 struct lxc_list
*it2
;
1720 lxc_list_for_each(it2
, &netdev
->ipv4
) {
1721 struct lxc_inetdev
*i
= it2
->elem
;
1722 char buf
[INET_ADDRSTRLEN
];
1723 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1724 strprint(retv
, inlen
, "%s\n", buf
);
1726 } else if (strcmp(p1
, "ipv6_gateway") == 0) {
1727 if (netdev
->ipv6_gateway_auto
) {
1728 strprint(retv
, inlen
, "auto");
1729 } else if (netdev
->ipv6_gateway
) {
1730 char buf
[INET_ADDRSTRLEN
];
1731 inet_ntop(AF_INET
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
1732 strprint(retv
, inlen
, "%s", buf
);
1734 } else if (strcmp(p1
, "ipv6") == 0) {
1735 struct lxc_list
*it2
;
1736 lxc_list_for_each(it2
, &netdev
->ipv6
) {
1737 struct lxc_inetdev
*i
= it2
->elem
;
1738 char buf
[INET_ADDRSTRLEN
];
1739 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
1740 strprint(retv
, inlen
, "%s\n", buf
);
1746 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
1748 int len
, fulllen
= 0;
1749 struct lxc_list
*it
;
1754 memset(retv
, 0, inlen
);
1756 lxc_list_for_each(it
, &c
->network
) {
1757 struct lxc_netdev
*n
= it
->elem
;
1758 const char *t
= lxc_net_type_to_str(n
->type
);
1759 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
1764 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
1767 const char *v
= NULL
;
1769 if (strcmp(key
, "lxc.mount.entry") == 0)
1770 return lxc_get_mount_entries(c
, retv
, inlen
);
1771 else if (strcmp(key
, "lxc.mount") == 0)
1773 else if (strcmp(key
, "lxc.tty") == 0)
1774 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
1775 else if (strcmp(key
, "lxc.pts") == 0)
1776 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
1777 else if (strcmp(key
, "lxc.devttydir") == 0)
1779 else if (strcmp(key
, "lxc.arch") == 0)
1780 return lxc_get_arch_entry(c
, retv
, inlen
);
1782 else if (strcmp(key
, "lxc.aa_profile") == 0)
1785 else if (strcmp(key
, "lxc.logfile") == 0)
1786 v
= lxc_log_get_file();
1787 else if (strcmp(key
, "lxc.loglevel") == 0)
1788 v
= lxc_log_priority_to_string(lxc_log_get_level());
1789 else if (strcmp(key
, "lxc.cgroup") == 0) // all cgroup info
1790 return lxc_get_cgroup_entry(c
, retv
, inlen
, "all");
1791 else if (strncmp(key
, "lxc.cgroup.", 11) == 0) // specific cgroup info
1792 return lxc_get_cgroup_entry(c
, retv
, inlen
, key
+ 11);
1793 else if (strcmp(key
, "lxc.utsname") == 0)
1794 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
1795 else if (strcmp(key
, "lxc.console") == 0)
1796 v
= c
->console
.path
;
1797 else if (strcmp(key
, "lxc.rootfs.mount") == 0)
1798 v
= c
->rootfs
.mount
;
1799 else if (strcmp(key
, "lxc.rootfs") == 0)
1801 else if (strcmp(key
, "lxc.pivotdir") == 0)
1802 v
= c
->rootfs
.pivot
;
1803 else if (strcmp(key
, "lxc.cap.drop") == 0)
1804 return lxc_get_item_cap_drop(c
, retv
, inlen
);
1805 else if (strncmp(key
, "lxc.hook", 8) == 0)
1806 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
1807 else if (strcmp(key
, "lxc.network") == 0)
1808 return lxc_get_item_network(c
, retv
, inlen
);
1809 else if (strncmp(key
, "lxc.network.", 12) == 0)
1810 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
1815 if (retv
&& inlen
>= strlen(v
) + 1)
1816 strncpy(retv
, v
, strlen(v
)+1);
1820 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
1822 if (strcmp(key
, "lxc.network") == 0)
1823 return lxc_clear_config_network(c
);
1824 else if (strncmp(key
, "lxc.network.", 12) == 0)
1825 return lxc_clear_nic(c
, key
+ 12);
1826 else if (strcmp(key
, "lxc.cap.drop") == 0)
1827 return lxc_clear_config_caps(c
);
1828 else if (strncmp(key
, "lxc.cgroup", 10) == 0)
1829 return lxc_clear_cgroups(c
, key
);
1830 else if (strcmp(key
, "lxc.mount.entries") == 0)
1831 return lxc_clear_mount_entries(c
);
1832 else if (strncmp(key
, "lxc.hook", 8) == 0)
1833 return lxc_clear_hooks(c
, key
);
1839 * writing out a confile.
1841 void write_config(FILE *fout
, struct lxc_conf
*c
)
1843 struct lxc_list
*it
;
1847 fprintf(fout
, "lxc.mount = %s\n", c
->fstab
);
1848 lxc_list_for_each(it
, &c
->mount_list
) {
1849 fprintf(fout
, "lxc.mount.entry = %s\n", (char *)it
->elem
);
1852 fprintf(fout
, "lxc.tty = %d\n", c
->tty
);
1854 fprintf(fout
, "lxc.pts = %d\n", c
->pts
);
1856 fprintf(fout
, "lxc.devttydir = %s\n", c
->ttydir
);
1857 #if HAVE_SYS_PERSONALITY_H
1858 switch(c
->personality
) {
1859 case PER_LINUX32
: fprintf(fout
, "lxc.arch = x86\n"); break;
1860 case PER_LINUX
: fprintf(fout
, "lxc.arch = x86_64\n"); break;
1866 fprintf(fout
, "lxc.aa_profile = %s\n", c
->aa_profile
);
1868 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET
)
1869 fprintf(fout
, "lxc.loglevel = %s\n", lxc_log_priority_to_string(lxc_log_get_level()));
1870 if (lxc_log_get_file())
1871 fprintf(fout
, "lxc.logfile = %s\n", lxc_log_get_file());
1872 lxc_list_for_each(it
, &c
->cgroup
) {
1873 struct lxc_cgroup
*cg
= it
->elem
;
1874 fprintf(fout
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1877 fprintf(fout
, "lxc.utsname = %s\n", c
->utsname
->nodename
);
1878 lxc_list_for_each(it
, &c
->network
) {
1879 struct lxc_netdev
*n
= it
->elem
;
1880 const char *t
= lxc_net_type_to_str(n
->type
);
1881 struct lxc_list
*it2
;
1882 fprintf(fout
, "lxc.network.type = %s\n", t
? t
: "(invalid)");
1883 if (n
->flags
& IFF_UP
)
1884 fprintf(fout
, "lxc.network.flags = up\n");
1886 fprintf(fout
, "lxc.network.link = %s\n", n
->link
);
1888 fprintf(fout
, "lxc.network.name = %s\n", n
->name
);
1889 if (n
->type
== LXC_NET_MACVLAN
) {
1891 switch (n
->priv
.macvlan_attr
.mode
) {
1892 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1893 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1894 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1895 default: mode
= "(invalid)"; break;
1897 fprintf(fout
, "lxc.network.macvlan.mode = %s\n", mode
);
1898 } else if (n
->type
== LXC_NET_VETH
) {
1899 if (n
->priv
.veth_attr
.pair
)
1900 fprintf(fout
, "lxc.network.veth.pair = %s\n",
1901 n
->priv
.veth_attr
.pair
);
1902 } else if (n
->type
== LXC_NET_VLAN
) {
1903 fprintf(fout
, "lxc.network.vlan.id = %d\n", n
->priv
.vlan_attr
.vid
);
1906 fprintf(fout
, "lxc.network.script.up = %s\n", n
->upscript
);
1908 fprintf(fout
, "lxc.network.hwaddr = %s\n", n
->hwaddr
);
1910 fprintf(fout
, "lxc.network.mtu = %s\n", n
->mtu
);
1911 if (n
->ipv4_gateway_auto
)
1912 fprintf(fout
, "lxc.network.ipv4.gateway = auto\n");
1913 else if (n
->ipv4_gateway
) {
1914 char buf
[INET_ADDRSTRLEN
];
1915 inet_ntop(AF_INET
, n
->ipv4_gateway
, buf
, sizeof(buf
));
1916 fprintf(fout
, "lxc.network.ipv4.gateway = %s\n", buf
);
1918 lxc_list_for_each(it2
, &n
->ipv4
) {
1919 struct lxc_inetdev
*i
= it2
->elem
;
1920 char buf
[INET_ADDRSTRLEN
];
1921 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1922 fprintf(fout
, "lxc.network.ipv4 = %s\n", buf
);
1924 if (n
->ipv6_gateway_auto
)
1925 fprintf(fout
, "lxc.network.ipv6.gateway = auto\n");
1926 else if (n
->ipv6_gateway
) {
1927 char buf
[INET6_ADDRSTRLEN
];
1928 inet_ntop(AF_INET6
, n
->ipv6_gateway
, buf
, sizeof(buf
));
1929 fprintf(fout
, "lxc.network.ipv6.gateway = %s\n", buf
);
1931 lxc_list_for_each(it2
, &n
->ipv6
) {
1932 struct lxc_inet6dev
*i
= it2
->elem
;
1933 char buf
[INET6_ADDRSTRLEN
];
1934 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1935 fprintf(fout
, "lxc.network.ipv6 = %s\n", buf
);
1938 lxc_list_for_each(it
, &c
->caps
)
1939 fprintf(fout
, "lxc.cap.drop = %s\n", (char *)it
->elem
);
1940 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1941 lxc_list_for_each(it
, &c
->hooks
[i
])
1942 fprintf(fout
, "lxc.hook.%s = %s\n",
1943 lxchook_names
[i
], (char *)it
->elem
);
1945 if (c
->console
.path
)
1946 fprintf(fout
, "lxc.console = %s\n", c
->console
.path
);
1948 fprintf(fout
, "lxc.rootfs = %s\n", c
->rootfs
.path
);
1949 if (c
->rootfs
.mount
&& strcmp(c
->rootfs
.mount
, LXCROOTFSMOUNT
) != 0)
1950 fprintf(fout
, "lxc.rootfs.mount = %s\n", c
->rootfs
.mount
);
1951 if (c
->rootfs
.pivot
)
1952 fprintf(fout
, "lxc.pivotdir = %s\n", c
->rootfs
.pivot
);