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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.hook.clone", config_hook
},
121 { "lxc.network.type", config_network_type
},
122 { "lxc.network.flags", config_network_flags
},
123 { "lxc.network.link", config_network_link
},
124 { "lxc.network.name", config_network_name
},
125 { "lxc.network.macvlan.mode", config_network_macvlan_mode
},
126 { "lxc.network.veth.pair", config_network_veth_pair
},
127 { "lxc.network.script.up", config_network_script
},
128 { "lxc.network.script.down", config_network_script
},
129 { "lxc.network.hwaddr", config_network_hwaddr
},
130 { "lxc.network.mtu", config_network_mtu
},
131 { "lxc.network.vlan.id", config_network_vlan_id
},
132 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway
},
133 { "lxc.network.ipv4", config_network_ipv4
},
134 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway
},
135 { "lxc.network.ipv6", config_network_ipv6
},
136 /* config_network_nic must come after all other 'lxc.network.*' entries */
137 { "lxc.network.", config_network_nic
},
138 { "lxc.cap.drop", config_cap_drop
},
139 { "lxc.console", config_console
},
140 { "lxc.seccomp", config_seccomp
},
141 { "lxc.include", config_includefile
},
142 { "lxc.autodev", config_autodev
},
143 { "lxc.stopsignal", config_stopsignal
},
151 struct signame signames
[] = {
173 static const size_t config_size
= sizeof(config
)/sizeof(struct lxc_config_t
);
175 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
179 for (i
= 0; i
< config_size
; i
++)
180 if (!strncmp(config
[i
].name
, key
,
181 strlen(config
[i
].name
)))
186 #define strprint(str, inlen, ...) \
188 len = snprintf(str, inlen, ##__VA_ARGS__); \
189 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
192 if (str) str += len; \
194 if (inlen < 0) inlen = 0; \
198 int lxc_listconfigs(char *retv
, int inlen
)
200 int i
, fulllen
= 0, len
;
205 memset(retv
, 0, inlen
);
206 for (i
= 0; i
< config_size
; i
++) {
207 char *s
= config
[i
].name
;
208 if (s
[strlen(s
)-1] == '.')
210 strprint(retv
, inlen
, "%s\n", s
);
216 * config entry is something like "lxc.network.0.ipv4"
217 * the key 'lxc.network.' was found. So we make sure next
218 * comes an integer, find the right callback (by rewriting
219 * the key), and call it.
221 static int config_network_nic(const char *key
, const char *value
,
222 struct lxc_conf
*lxc_conf
)
224 char *copy
= strdup(key
), *p
;
226 struct lxc_config_t
*config
;
229 SYSERROR("failed to allocate memory");
233 * ok we know that to get here we've got "lxc.network."
234 * and it isn't any of the other network entries. So
235 * after the second . should come an integer (# of defined
236 * nic) followed by a valid entry.
238 if (*(key
+12) < '0' || *(key
+12) > '9')
240 p
= index(key
+12, '.');
243 strcpy(copy
+12, p
+1);
244 config
= lxc_getconfig(copy
);
246 ERROR("unknown key %s", key
);
249 ret
= config
->cb(key
, value
, lxc_conf
);
256 static int config_network_type(const char *key
, const char *value
,
257 struct lxc_conf
*lxc_conf
)
259 struct lxc_list
*network
= &lxc_conf
->network
;
260 struct lxc_netdev
*netdev
;
261 struct lxc_list
*list
;
263 netdev
= malloc(sizeof(*netdev
));
265 SYSERROR("failed to allocate memory");
269 memset(netdev
, 0, sizeof(*netdev
));
270 lxc_list_init(&netdev
->ipv4
);
271 lxc_list_init(&netdev
->ipv6
);
273 list
= malloc(sizeof(*list
));
275 SYSERROR("failed to allocate memory");
283 lxc_list_add_tail(network
, list
);
285 if (!strcmp(value
, "veth"))
286 netdev
->type
= LXC_NET_VETH
;
287 else if (!strcmp(value
, "macvlan"))
288 netdev
->type
= LXC_NET_MACVLAN
;
289 else if (!strcmp(value
, "vlan"))
290 netdev
->type
= LXC_NET_VLAN
;
291 else if (!strcmp(value
, "phys"))
292 netdev
->type
= LXC_NET_PHYS
;
293 else if (!strcmp(value
, "empty"))
294 netdev
->type
= LXC_NET_EMPTY
;
296 ERROR("invalid network type %s", value
);
302 static int config_ip_prefix(struct in_addr
*addr
)
304 if (IN_CLASSA(addr
->s_addr
))
305 return 32 - IN_CLASSA_NSHIFT
;
306 if (IN_CLASSB(addr
->s_addr
))
307 return 32 - IN_CLASSB_NSHIFT
;
308 if (IN_CLASSC(addr
->s_addr
))
309 return 32 - IN_CLASSC_NSHIFT
;
315 * if you have p="lxc.network.0.link", pass it p+12
316 * to get back '0' (the index of the nic)
318 static int get_network_netdev_idx(const char *key
)
322 if (*key
< '0' || *key
> '9')
324 ret
= sscanf(key
, "%d", &idx
);
331 * if you have p="lxc.network.0", pass this p+12 and it will return
332 * the netdev of the first configured nic
334 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
335 struct lxc_list
*network
)
337 int i
= 0, idx
= get_network_netdev_idx(key
);
338 struct lxc_netdev
*netdev
= NULL
;
342 lxc_list_for_each(it
, network
) {
351 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
,
352 char *retv
, int inlen
)
354 struct lxc_netdev
*netdev
;
355 int fulllen
= 0, len
;
357 netdev
= get_netdev_from_key(key
+12, &c
->network
);
364 memset(retv
, 0, inlen
);
366 strprint(retv
, inlen
, "script.up\n");
367 if (netdev
->type
!= LXC_NET_EMPTY
) {
368 strprint(retv
, inlen
, "flags\n");
369 strprint(retv
, inlen
, "link\n");
370 strprint(retv
, inlen
, "name\n");
371 strprint(retv
, inlen
, "hwaddr\n");
372 strprint(retv
, inlen
, "mtu\n");
373 strprint(retv
, inlen
, "ipv6\n");
374 strprint(retv
, inlen
, "ipv6_gateway\n");
375 strprint(retv
, inlen
, "ipv4\n");
376 strprint(retv
, inlen
, "ipv4_gateway\n");
378 switch(netdev
->type
) {
380 strprint(retv
, inlen
, "veth.pair\n");
382 case LXC_NET_MACVLAN
:
383 strprint(retv
, inlen
, "macvlan.mode\n");
386 strprint(retv
, inlen
, "vlan.id\n");
394 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
395 struct lxc_list
*network
)
397 struct lxc_netdev
*netdev
= NULL
;
399 if (lxc_list_empty(network
)) {
400 ERROR("network is not created for '%s' = '%s' option",
405 if (get_network_netdev_idx(key
+12) == -1)
406 netdev
= lxc_list_last_elem(network
);
408 netdev
= get_netdev_from_key(key
+12, network
);
411 ERROR("no network device defined for '%s' = '%s' option",
419 static int network_ifname(char **valuep
, const char *value
)
421 if (strlen(value
) >= IFNAMSIZ
) {
422 ERROR("interface name '%s' too long (>%d)\n",
423 value
, IFNAMSIZ
- 1);
427 *valuep
= strdup(value
);
429 ERROR("failed to dup string '%s'", value
);
436 #ifndef MACVLAN_MODE_PRIVATE
437 # define MACVLAN_MODE_PRIVATE 1
440 #ifndef MACVLAN_MODE_VEPA
441 # define MACVLAN_MODE_VEPA 2
444 #ifndef MACVLAN_MODE_BRIDGE
445 # define MACVLAN_MODE_BRIDGE 4
448 static int macvlan_mode(int *valuep
, const char *value
)
454 { "private", MACVLAN_MODE_PRIVATE
},
455 { "vepa", MACVLAN_MODE_VEPA
},
456 { "bridge", MACVLAN_MODE_BRIDGE
},
461 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
462 if (strcmp(m
[i
].name
, value
))
472 static int config_network_flags(const char *key
, const char *value
,
473 struct lxc_conf
*lxc_conf
)
475 struct lxc_netdev
*netdev
;
477 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
481 netdev
->flags
|= IFF_UP
;
486 static int config_network_link(const char *key
, const char *value
,
487 struct lxc_conf
*lxc_conf
)
489 struct lxc_netdev
*netdev
;
491 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
495 return network_ifname(&netdev
->link
, value
);
498 static int config_network_name(const char *key
, const char *value
,
499 struct lxc_conf
*lxc_conf
)
501 struct lxc_netdev
*netdev
;
503 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
507 return network_ifname(&netdev
->name
, value
);
510 static int config_network_veth_pair(const char *key
, const char *value
,
511 struct lxc_conf
*lxc_conf
)
513 struct lxc_netdev
*netdev
;
515 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
519 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
522 static int config_network_macvlan_mode(const char *key
, const char *value
,
523 struct lxc_conf
*lxc_conf
)
525 struct lxc_netdev
*netdev
;
527 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
531 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
534 static int config_network_hwaddr(const char *key
, const char *value
,
535 struct lxc_conf
*lxc_conf
)
537 struct lxc_netdev
*netdev
;
540 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
544 hwaddr
= strdup(value
);
546 SYSERROR("failed to dup string '%s'", value
);
551 free(netdev
->hwaddr
);
552 netdev
->hwaddr
= hwaddr
;
556 static int config_network_vlan_id(const char *key
, const char *value
,
557 struct lxc_conf
*lxc_conf
)
559 struct lxc_netdev
*netdev
;
561 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
565 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
571 static int config_network_mtu(const char *key
, const char *value
,
572 struct lxc_conf
*lxc_conf
)
574 struct lxc_netdev
*netdev
;
577 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
583 SYSERROR("failed to dup string '%s'", value
);
593 static int config_network_ipv4(const char *key
, const char *value
,
594 struct lxc_conf
*lxc_conf
)
596 struct lxc_netdev
*netdev
;
597 struct lxc_inetdev
*inetdev
;
598 struct lxc_list
*list
;
599 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
601 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
605 inetdev
= malloc(sizeof(*inetdev
));
607 SYSERROR("failed to allocate ipv4 address");
610 memset(inetdev
, 0, sizeof(*inetdev
));
612 list
= malloc(sizeof(*list
));
614 SYSERROR("failed to allocate memory");
620 list
->elem
= inetdev
;
622 addr
= strdup(value
);
624 ERROR("no address specified");
630 cursor
= strstr(addr
, " ");
636 slash
= strstr(addr
, "/");
642 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
643 SYSERROR("invalid ipv4 address: %s", value
);
650 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
651 SYSERROR("invalid ipv4 broadcast address: %s", value
);
658 /* no prefix specified, determine it from the network class */
659 inetdev
->prefix
= prefix
? atoi(prefix
) :
660 config_ip_prefix(&inetdev
->addr
);
662 /* if no broadcast address, let compute one from the
666 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
667 inetdev
->bcast
.s_addr
|=
668 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
671 lxc_list_add_tail(&netdev
->ipv4
, list
);
677 static int config_network_ipv4_gateway(const char *key
, const char *value
,
678 struct lxc_conf
*lxc_conf
)
680 struct lxc_netdev
*netdev
;
683 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
687 gw
= malloc(sizeof(*gw
));
689 SYSERROR("failed to allocate ipv4 gateway address");
694 ERROR("no ipv4 gateway address specified");
699 if (!strcmp(value
, "auto")) {
700 netdev
->ipv4_gateway
= NULL
;
701 netdev
->ipv4_gateway_auto
= true;
703 if (!inet_pton(AF_INET
, value
, gw
)) {
704 SYSERROR("invalid ipv4 gateway address: %s", value
);
709 netdev
->ipv4_gateway
= gw
;
710 netdev
->ipv4_gateway_auto
= false;
716 static int config_network_ipv6(const char *key
, const char *value
,
717 struct lxc_conf
*lxc_conf
)
719 struct lxc_netdev
*netdev
;
720 struct lxc_inet6dev
*inet6dev
;
721 struct lxc_list
*list
;
725 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
729 inet6dev
= malloc(sizeof(*inet6dev
));
731 SYSERROR("failed to allocate ipv6 address");
734 memset(inet6dev
, 0, sizeof(*inet6dev
));
736 list
= malloc(sizeof(*list
));
738 SYSERROR("failed to allocate memory");
744 list
->elem
= inet6dev
;
746 valdup
= strdup(value
);
748 ERROR("no address specified");
754 inet6dev
->prefix
= 64;
755 slash
= strstr(valdup
, "/");
759 inet6dev
->prefix
= atoi(netmask
);
762 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
763 SYSERROR("invalid ipv6 address: %s", valdup
);
770 lxc_list_add_tail(&netdev
->ipv6
, list
);
776 static int config_network_ipv6_gateway(const char *key
, const char *value
,
777 struct lxc_conf
*lxc_conf
)
779 struct lxc_netdev
*netdev
;
781 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
786 ERROR("no ipv6 gateway address specified");
790 if (!strcmp(value
, "auto")) {
791 netdev
->ipv6_gateway
= NULL
;
792 netdev
->ipv6_gateway_auto
= true;
796 gw
= malloc(sizeof(*gw
));
798 SYSERROR("failed to allocate ipv6 gateway address");
802 if (!inet_pton(AF_INET6
, value
, gw
)) {
803 SYSERROR("invalid ipv6 gateway address: %s", value
);
808 netdev
->ipv6_gateway
= gw
;
809 netdev
->ipv6_gateway_auto
= false;
815 static int config_network_script(const char *key
, const char *value
,
816 struct lxc_conf
*lxc_conf
)
818 struct lxc_netdev
*netdev
;
820 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
824 char *copy
= strdup(value
);
826 SYSERROR("failed to dup string '%s'", value
);
829 if (strstr(key
, "script.up") != NULL
) {
830 netdev
->upscript
= copy
;
833 if (strcmp(key
, "lxc.network.script.down") == 0) {
834 netdev
->downscript
= copy
;
837 SYSERROR("Unknown key: %s", key
);
842 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
844 struct lxc_list
*hooklist
;
846 hooklist
= malloc(sizeof(*hooklist
));
851 hooklist
->elem
= hook
;
852 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
856 static int config_seccomp(const char *key
, const char *value
,
857 struct lxc_conf
*lxc_conf
)
861 if (lxc_conf
->seccomp
) {
862 ERROR("seccomp already defined");
865 path
= strdup(value
);
867 SYSERROR("failed to strdup '%s': %m", value
);
871 if (lxc_conf
->seccomp
)
872 free(lxc_conf
->seccomp
);
873 lxc_conf
->seccomp
= path
;
878 static int config_hook(const char *key
, const char *value
,
879 struct lxc_conf
*lxc_conf
)
881 char *copy
= strdup(value
);
883 SYSERROR("failed to dup string '%s'", value
);
886 if (strcmp(key
, "lxc.hook.pre-start") == 0)
887 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
888 else if (strcmp(key
, "lxc.hook.pre-mount") == 0)
889 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
890 else if (strcmp(key
, "lxc.hook.autodev") == 0)
891 return add_hook(lxc_conf
, LXCHOOK_AUTODEV
, copy
);
892 else if (strcmp(key
, "lxc.hook.mount") == 0)
893 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
894 else if (strcmp(key
, "lxc.hook.start") == 0)
895 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
896 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
897 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
898 else if (strcmp(key
, "lxc.hook.clone") == 0)
899 return add_hook(lxc_conf
, LXCHOOK_CLONE
, copy
);
900 SYSERROR("Unknown key: %s", key
);
905 static int config_personality(const char *key
, const const char *value
,
906 struct lxc_conf
*lxc_conf
)
908 signed long personality
= lxc_config_parse_arch(value
);
910 if (personality
>= 0)
911 lxc_conf
->personality
= personality
;
913 WARN("unsupported personality '%s'", value
);
918 static int config_pts(const char *key
, const char *value
,
919 struct lxc_conf
*lxc_conf
)
921 int maxpts
= atoi(value
);
923 lxc_conf
->pts
= maxpts
;
928 static int config_tty(const char *key
, const char *value
,
929 struct lxc_conf
*lxc_conf
)
931 int nbtty
= atoi(value
);
933 lxc_conf
->tty
= nbtty
;
938 static int config_ttydir(const char *key
, const char *value
,
939 struct lxc_conf
*lxc_conf
)
943 if (!value
|| strlen(value
) == 0)
945 path
= strdup(value
);
947 SYSERROR("failed to strdup '%s': %m", value
);
951 if (lxc_conf
->ttydir
)
952 free(lxc_conf
->ttydir
);
953 lxc_conf
->ttydir
= path
;
958 static int config_kmsg(const char *key
, const char *value
,
959 struct lxc_conf
*lxc_conf
)
969 static int config_aa_profile(const char *key
, const char *value
,
970 struct lxc_conf
*lxc_conf
)
974 if (!value
|| strlen(value
) == 0)
976 path
= strdup(value
);
978 SYSERROR("failed to strdup '%s': %m", value
);
982 if (lxc_conf
->aa_profile
)
983 free(lxc_conf
->aa_profile
);
984 lxc_conf
->aa_profile
= path
;
990 static int config_logfile(const char *key
, const char *value
,
991 struct lxc_conf
*lxc_conf
)
993 // store these values in the lxc_conf, and then try to set for
994 // actual current logging.
995 if (lxc_conf
->logfile
)
996 free(lxc_conf
->logfile
);
997 lxc_conf
->logfile
= strdup(value
);
998 return lxc_log_set_file(value
);
1001 static int config_loglevel(const char *key
, const char *value
,
1002 struct lxc_conf
*lxc_conf
)
1006 if (!value
|| strlen(value
) == 0)
1009 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET
) {
1010 DEBUG("Log level already set - ignoring new value");
1013 if (value
[0] >= '0' && value
[0] <= '9')
1014 newlevel
= atoi(value
);
1016 newlevel
= lxc_log_priority_to_int(value
);
1017 // store these values in the lxc_conf, and then try to set for
1018 // actual current logging.
1019 lxc_conf
->loglevel
= newlevel
;
1020 return lxc_log_set_level(newlevel
);
1023 static int config_autodev(const char *key
, const char *value
,
1024 struct lxc_conf
*lxc_conf
)
1026 int v
= atoi(value
);
1028 lxc_conf
->autodev
= v
;
1033 static int sig_num(const char *sig
)
1039 n
= strtol(sig
, &endp
, 10);
1040 if (sig
== endp
|| n
< 0 || errno
!= 0)
1045 static int rt_sig_num(const char *signame
)
1050 if (strncasecmp(signame
, "max-", 4) == 0) {
1054 if (!isdigit(*signame
))
1056 sig_n
= sig_num(signame
);
1057 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1058 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1063 static int sig_parse(const char *signame
) {
1066 if (isdigit(*signame
)) {
1067 return sig_num(signame
);
1068 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1070 if (strncasecmp(signame
, "rt", 2) == 0)
1071 return rt_sig_num(signame
+ 2);
1072 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1073 if (strcasecmp (signames
[n
].name
, signame
) == 0)
1074 return signames
[n
].num
;
1080 static int config_stopsignal(const char *key
, const char *value
,
1081 struct lxc_conf
*lxc_conf
)
1083 int sig_n
= sig_parse(value
);
1087 lxc_conf
->stopsignal
= sig_n
;
1092 static int config_cgroup(const char *key
, const char *value
,
1093 struct lxc_conf
*lxc_conf
)
1095 char *token
= "lxc.cgroup.";
1097 struct lxc_list
*cglist
= NULL
;
1098 struct lxc_cgroup
*cgelem
= NULL
;
1100 subkey
= strstr(key
, token
);
1105 if (!strlen(subkey
))
1108 if (strlen(subkey
) == strlen(token
))
1111 subkey
+= strlen(token
);
1113 cglist
= malloc(sizeof(*cglist
));
1117 cgelem
= malloc(sizeof(*cgelem
));
1120 memset(cgelem
, 0, sizeof(*cgelem
));
1122 cgelem
->subsystem
= strdup(subkey
);
1123 cgelem
->value
= strdup(value
);
1125 if (!cgelem
->subsystem
|| !cgelem
->value
)
1128 cglist
->elem
= cgelem
;
1130 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1139 if (cgelem
->subsystem
)
1140 free(cgelem
->subsystem
);
1143 free(cgelem
->value
);
1151 static int config_idmap(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
1153 char *token
= "lxc.id_map";
1155 struct lxc_list
*idmaplist
= NULL
;
1156 struct id_map
*idmap
= NULL
;
1157 unsigned long hostid
, nsid
, range
;
1161 subkey
= strstr(key
, token
);
1166 if (!strlen(subkey
))
1169 idmaplist
= malloc(sizeof(*idmaplist
));
1173 idmap
= malloc(sizeof(*idmap
));
1176 memset(idmap
, 0, sizeof(*idmap
));
1178 idmaplist
->elem
= idmap
;
1180 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1182 ret
= sscanf(value
, "%c %lu %lu %lu", &type
, &nsid
, &hostid
, &range
);
1185 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1187 idmap
->idtype
= ID_TYPE_UID
;
1188 else if (type
== 'g')
1189 idmap
->idtype
= ID_TYPE_GID
;
1192 idmap
->hostid
= hostid
;
1194 idmap
->range
= range
;
1209 static int config_path_item(const char *key
, const char *value
,
1210 struct lxc_conf
*lxc_conf
, char **conf_item
)
1213 if (strlen(value
) >= MAXPATHLEN
) {
1214 ERROR("%s path is too long", value
);
1218 valdup
= strdup(value
);
1220 SYSERROR("failed to duplicate string %s", value
);
1225 *conf_item
= valdup
;
1230 static int config_fstab(const char *key
, const char *value
,
1231 struct lxc_conf
*lxc_conf
)
1233 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->fstab
);
1236 static int config_mount(const char *key
, const char *value
,
1237 struct lxc_conf
*lxc_conf
)
1239 char *fstab_token
= "lxc.mount";
1240 char *token
= "lxc.mount.entry";
1243 struct lxc_list
*mntlist
;
1245 subkey
= strstr(key
, token
);
1248 subkey
= strstr(key
, fstab_token
);
1253 return config_fstab(key
, value
, lxc_conf
);
1256 if (!strlen(subkey
))
1259 mntlist
= malloc(sizeof(*mntlist
));
1263 mntelem
= strdup(value
);
1268 mntlist
->elem
= mntelem
;
1270 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1275 static int config_cap_drop(const char *key
, const char *value
,
1276 struct lxc_conf
*lxc_conf
)
1278 char *dropcaps
, *dropptr
, *sptr
, *token
;
1279 struct lxc_list
*droplist
;
1285 dropcaps
= strdup(value
);
1287 SYSERROR("failed to dup '%s'", value
);
1291 /* in case several capability drop is specified in a single line
1292 * split these caps in a single element for the list */
1293 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
1294 token
= strtok_r(dropptr
, " \t", &sptr
);
1300 droplist
= malloc(sizeof(*droplist
));
1302 SYSERROR("failed to allocate drop list");
1306 droplist
->elem
= strdup(token
);
1307 if (!droplist
->elem
) {
1308 SYSERROR("failed to dup '%s'", token
);
1313 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1321 static int config_console(const char *key
, const char *value
,
1322 struct lxc_conf
*lxc_conf
)
1326 path
= strdup(value
);
1328 SYSERROR("failed to strdup '%s': %m", value
);
1332 if (lxc_conf
->console
.path
)
1333 free(lxc_conf
->console
.path
);
1334 lxc_conf
->console
.path
= path
;
1339 static int config_includefile(const char *key
, const char *value
,
1340 struct lxc_conf
*lxc_conf
)
1342 return lxc_config_read(value
, lxc_conf
);
1345 static int config_rootfs(const char *key
, const char *value
,
1346 struct lxc_conf
*lxc_conf
)
1348 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.path
);
1351 static int config_rootfs_mount(const char *key
, const char *value
,
1352 struct lxc_conf
*lxc_conf
)
1354 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.mount
);
1357 static int config_pivotdir(const char *key
, const char *value
,
1358 struct lxc_conf
*lxc_conf
)
1360 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.pivot
);
1363 static int config_utsname(const char *key
, const char *value
,
1364 struct lxc_conf
*lxc_conf
)
1366 struct utsname
*utsname
;
1368 utsname
= malloc(sizeof(*utsname
));
1370 SYSERROR("failed to allocate memory");
1374 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1375 ERROR("node name '%s' is too long",
1381 strcpy(utsname
->nodename
, value
);
1382 if (lxc_conf
->utsname
)
1383 free(lxc_conf
->utsname
);
1384 lxc_conf
->utsname
= utsname
;
1389 static int parse_line(char *buffer
, void *data
)
1391 struct lxc_config_t
*config
;
1398 if (lxc_is_line_empty(buffer
))
1401 /* we have to dup the buffer otherwise, at the re-exec for
1402 * reboot we modified the original string on the stack by
1403 * replacing '=' by '\0' below
1405 linep
= line
= strdup(buffer
);
1407 SYSERROR("failed to allocate memory for '%s'", buffer
);
1411 line
+= lxc_char_left_gc(line
, strlen(line
));
1413 /* martian option - ignoring it, the commented lines beginning by '#'
1416 if (strncmp(line
, "lxc.", 4))
1421 dot
= strstr(line
, "=");
1423 ERROR("invalid configuration line: %s", line
);
1431 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1433 value
+= lxc_char_left_gc(value
, strlen(value
));
1434 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1436 config
= lxc_getconfig(key
);
1438 ERROR("unknown key %s", key
);
1442 ret
= config
->cb(key
, value
, data
);
1449 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1451 return parse_line(buffer
, conf
);
1454 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1456 if( access(file
, R_OK
) == -1 ) {
1459 /* Catch only the top level config file name in the structure */
1460 if( ! conf
->rcfile
) {
1461 conf
->rcfile
= strdup( file
);
1463 return lxc_file_for_each_line(file
, parse_line
, conf
);
1466 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1468 struct lxc_list
*dent
;
1470 dent
= malloc(sizeof(struct lxc_list
));
1475 lxc_list_add_tail(defines
, dent
);
1479 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1481 struct lxc_list
*it
,*next
;
1484 lxc_list_for_each(it
, defines
) {
1485 ret
= lxc_config_readline(it
->elem
, conf
);
1490 lxc_list_for_each_safe(it
, defines
, next
) {
1498 signed long lxc_config_parse_arch(const char *arch
)
1500 #if HAVE_SYS_PERSONALITY_H
1505 { "x86", PER_LINUX32
},
1506 { "i686", PER_LINUX32
},
1507 { "x86_64", PER_LINUX
},
1508 { "amd64", PER_LINUX
},
1510 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1514 for (i
= 0; i
< len
; i
++) {
1515 if (!strcmp(pername
[i
].name
, arch
))
1516 return pername
[i
].per
;
1523 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
1528 memset(retv
, 0, inlen
);
1529 return snprintf(retv
, inlen
, "%d", v
);
1532 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
1539 memset(retv
, 0, inlen
);
1541 #if HAVE_SYS_PERSONALITY_H
1544 switch(c
->personality
) {
1545 case PER_LINUX32
: strprint(retv
, inlen
, "x86"); break;
1546 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
1555 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1556 * then just the value(s) will be printed. Since there still could be
1557 * more than one, it is newline-separated.
1558 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1559 * already have newlines?)
1560 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1561 * in 'lxc.cgroup.subsystem.key = value' format.
1563 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
1566 int fulllen
= 0, len
;
1568 struct lxc_list
*it
;
1573 memset(retv
, 0, inlen
);
1575 if (strcmp(key
, "all") == 0)
1578 lxc_list_for_each(it
, &c
->cgroup
) {
1579 struct lxc_cgroup
*cg
= it
->elem
;
1581 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1582 } else if (strcmp(cg
->subsystem
, key
) == 0) {
1583 strprint(retv
, inlen
, "%s\n", cg
->value
);
1589 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
1593 int len
, fulllen
= 0, found
= -1;
1594 struct lxc_list
*it
;
1597 /* "lxc.hook.mount" */
1598 subkey
= index(key
, '.');
1599 if (subkey
) subkey
= index(subkey
+1, '.');
1605 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1606 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
1617 memset(retv
, 0, inlen
);
1619 lxc_list_for_each(it
, &c
->hooks
[found
]) {
1620 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1625 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
1627 int len
, fulllen
= 0;
1628 struct lxc_list
*it
;
1633 memset(retv
, 0, inlen
);
1635 lxc_list_for_each(it
, &c
->caps
) {
1636 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1641 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
1643 int len
, fulllen
= 0;
1644 struct lxc_list
*it
;
1649 memset(retv
, 0, inlen
);
1651 lxc_list_for_each(it
, &c
->mount_list
) {
1652 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1658 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1659 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1660 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1661 * of an address. ipv4 and ipv6 return lists (newline-separated).
1662 * things like veth.pair return '' if invalid (i.e. if called for vlan
1665 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
1669 int len
, fulllen
= 0;
1670 struct lxc_netdev
*netdev
;
1675 memset(retv
, 0, inlen
);
1677 p1
= index(key
, '.');
1678 if (!p1
|| *(p1
+1) == '\0') return -1;
1681 netdev
= get_netdev_from_key(key
, &c
->network
);
1684 if (strcmp(p1
, "name") == 0) {
1686 strprint(retv
, inlen
, "%s", netdev
->name
);
1687 } else if (strcmp(p1
, "type") == 0) {
1688 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
1689 } else if (strcmp(p1
, "link") == 0) {
1691 strprint(retv
, inlen
, "%s", netdev
->link
);
1692 } else if (strcmp(p1
, "flags") == 0) {
1693 if (netdev
->flags
& IFF_UP
)
1694 strprint(retv
, inlen
, "up");
1695 } else if (strcmp(p1
, "upscript") == 0) {
1696 if (netdev
->upscript
)
1697 strprint(retv
, inlen
, "%s", netdev
->upscript
);
1698 } else if (strcmp(p1
, "hwaddr") == 0) {
1700 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
1701 } else if (strcmp(p1
, "mtu") == 0) {
1703 strprint(retv
, inlen
, "%s", netdev
->mtu
);
1704 } else if (strcmp(p1
, "macvlan.mode") == 0) {
1705 if (netdev
->type
== LXC_NET_MACVLAN
) {
1707 switch (netdev
->priv
.macvlan_attr
.mode
) {
1708 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1709 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1710 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1711 default: mode
= "(invalid)"; break;
1713 strprint(retv
, inlen
, "%s", mode
);
1715 } else if (strcmp(p1
, "veth.pair") == 0) {
1716 if (netdev
->type
== LXC_NET_VETH
) {
1717 strprint(retv
, inlen
, "%s",
1718 netdev
->priv
.veth_attr
.pair
?
1719 netdev
->priv
.veth_attr
.pair
:
1720 netdev
->priv
.veth_attr
.veth1
);
1722 } else if (strcmp(p1
, "vlan") == 0) {
1723 if (netdev
->type
== LXC_NET_VLAN
) {
1724 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
1726 } else if (strcmp(p1
, "ipv4_gateway") == 0) {
1727 if (netdev
->ipv4_gateway_auto
) {
1728 strprint(retv
, inlen
, "auto");
1729 } else if (netdev
->ipv4_gateway
) {
1730 char buf
[INET_ADDRSTRLEN
];
1731 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
1732 strprint(retv
, inlen
, "%s", buf
);
1734 } else if (strcmp(p1
, "ipv4") == 0) {
1735 struct lxc_list
*it2
;
1736 lxc_list_for_each(it2
, &netdev
->ipv4
) {
1737 struct lxc_inetdev
*i
= it2
->elem
;
1738 char buf
[INET_ADDRSTRLEN
];
1739 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1740 strprint(retv
, inlen
, "%s\n", buf
);
1742 } else if (strcmp(p1
, "ipv6_gateway") == 0) {
1743 if (netdev
->ipv6_gateway_auto
) {
1744 strprint(retv
, inlen
, "auto");
1745 } else if (netdev
->ipv6_gateway
) {
1746 char buf
[INET_ADDRSTRLEN
];
1747 inet_ntop(AF_INET
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
1748 strprint(retv
, inlen
, "%s", buf
);
1750 } else if (strcmp(p1
, "ipv6") == 0) {
1751 struct lxc_list
*it2
;
1752 lxc_list_for_each(it2
, &netdev
->ipv6
) {
1753 struct lxc_inetdev
*i
= it2
->elem
;
1754 char buf
[INET_ADDRSTRLEN
];
1755 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
1756 strprint(retv
, inlen
, "%s\n", buf
);
1762 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
1764 int len
, fulllen
= 0;
1765 struct lxc_list
*it
;
1770 memset(retv
, 0, inlen
);
1772 lxc_list_for_each(it
, &c
->network
) {
1773 struct lxc_netdev
*n
= it
->elem
;
1774 const char *t
= lxc_net_type_to_str(n
->type
);
1775 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
1780 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
1783 const char *v
= NULL
;
1785 if (strcmp(key
, "lxc.mount.entry") == 0)
1786 return lxc_get_mount_entries(c
, retv
, inlen
);
1787 else if (strcmp(key
, "lxc.mount") == 0)
1789 else if (strcmp(key
, "lxc.tty") == 0)
1790 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
1791 else if (strcmp(key
, "lxc.pts") == 0)
1792 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
1793 else if (strcmp(key
, "lxc.devttydir") == 0)
1795 else if (strcmp(key
, "lxc.arch") == 0)
1796 return lxc_get_arch_entry(c
, retv
, inlen
);
1798 else if (strcmp(key
, "lxc.aa_profile") == 0)
1801 else if (strcmp(key
, "lxc.logfile") == 0)
1802 v
= lxc_log_get_file();
1803 else if (strcmp(key
, "lxc.loglevel") == 0)
1804 v
= lxc_log_priority_to_string(lxc_log_get_level());
1805 else if (strcmp(key
, "lxc.cgroup") == 0) // all cgroup info
1806 return lxc_get_cgroup_entry(c
, retv
, inlen
, "all");
1807 else if (strncmp(key
, "lxc.cgroup.", 11) == 0) // specific cgroup info
1808 return lxc_get_cgroup_entry(c
, retv
, inlen
, key
+ 11);
1809 else if (strcmp(key
, "lxc.utsname") == 0)
1810 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
1811 else if (strcmp(key
, "lxc.console") == 0)
1812 v
= c
->console
.path
;
1813 else if (strcmp(key
, "lxc.rootfs.mount") == 0)
1814 v
= c
->rootfs
.mount
;
1815 else if (strcmp(key
, "lxc.rootfs") == 0)
1817 else if (strcmp(key
, "lxc.pivotdir") == 0)
1818 v
= c
->rootfs
.pivot
;
1819 else if (strcmp(key
, "lxc.cap.drop") == 0)
1820 return lxc_get_item_cap_drop(c
, retv
, inlen
);
1821 else if (strncmp(key
, "lxc.hook", 8) == 0)
1822 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
1823 else if (strcmp(key
, "lxc.network") == 0)
1824 return lxc_get_item_network(c
, retv
, inlen
);
1825 else if (strncmp(key
, "lxc.network.", 12) == 0)
1826 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
1831 if (retv
&& inlen
>= strlen(v
) + 1)
1832 strncpy(retv
, v
, strlen(v
)+1);
1836 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
1838 if (strcmp(key
, "lxc.network") == 0)
1839 return lxc_clear_config_network(c
);
1840 else if (strncmp(key
, "lxc.network.", 12) == 0)
1841 return lxc_clear_nic(c
, key
+ 12);
1842 else if (strcmp(key
, "lxc.cap.drop") == 0)
1843 return lxc_clear_config_caps(c
);
1844 else if (strncmp(key
, "lxc.cgroup", 10) == 0)
1845 return lxc_clear_cgroups(c
, key
);
1846 else if (strcmp(key
, "lxc.mount.entries") == 0)
1847 return lxc_clear_mount_entries(c
);
1848 else if (strncmp(key
, "lxc.hook", 8) == 0)
1849 return lxc_clear_hooks(c
, key
);
1855 * writing out a confile.
1857 void write_config(FILE *fout
, struct lxc_conf
*c
)
1859 struct lxc_list
*it
;
1863 fprintf(fout
, "lxc.mount = %s\n", c
->fstab
);
1864 lxc_list_for_each(it
, &c
->mount_list
) {
1865 fprintf(fout
, "lxc.mount.entry = %s\n", (char *)it
->elem
);
1868 fprintf(fout
, "lxc.tty = %d\n", c
->tty
);
1870 fprintf(fout
, "lxc.pts = %d\n", c
->pts
);
1872 fprintf(fout
, "lxc.devttydir = %s\n", c
->ttydir
);
1873 #if HAVE_SYS_PERSONALITY_H
1874 switch(c
->personality
) {
1875 case PER_LINUX32
: fprintf(fout
, "lxc.arch = x86\n"); break;
1876 case PER_LINUX
: fprintf(fout
, "lxc.arch = x86_64\n"); break;
1882 fprintf(fout
, "lxc.aa_profile = %s\n", c
->aa_profile
);
1884 if (c
->loglevel
!= LXC_LOG_PRIORITY_NOTSET
)
1885 fprintf(fout
, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c
->loglevel
));
1887 fprintf(fout
, "lxc.logfile = %s\n", c
->logfile
);
1888 lxc_list_for_each(it
, &c
->cgroup
) {
1889 struct lxc_cgroup
*cg
= it
->elem
;
1890 fprintf(fout
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1893 fprintf(fout
, "lxc.utsname = %s\n", c
->utsname
->nodename
);
1894 lxc_list_for_each(it
, &c
->network
) {
1895 struct lxc_netdev
*n
= it
->elem
;
1896 const char *t
= lxc_net_type_to_str(n
->type
);
1897 struct lxc_list
*it2
;
1898 fprintf(fout
, "lxc.network.type = %s\n", t
? t
: "(invalid)");
1899 if (n
->flags
& IFF_UP
)
1900 fprintf(fout
, "lxc.network.flags = up\n");
1902 fprintf(fout
, "lxc.network.link = %s\n", n
->link
);
1904 fprintf(fout
, "lxc.network.name = %s\n", n
->name
);
1905 if (n
->type
== LXC_NET_MACVLAN
) {
1907 switch (n
->priv
.macvlan_attr
.mode
) {
1908 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1909 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1910 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1911 default: mode
= "(invalid)"; break;
1913 fprintf(fout
, "lxc.network.macvlan.mode = %s\n", mode
);
1914 } else if (n
->type
== LXC_NET_VETH
) {
1915 if (n
->priv
.veth_attr
.pair
)
1916 fprintf(fout
, "lxc.network.veth.pair = %s\n",
1917 n
->priv
.veth_attr
.pair
);
1918 } else if (n
->type
== LXC_NET_VLAN
) {
1919 fprintf(fout
, "lxc.network.vlan.id = %d\n", n
->priv
.vlan_attr
.vid
);
1922 fprintf(fout
, "lxc.network.script.up = %s\n", n
->upscript
);
1924 fprintf(fout
, "lxc.network.hwaddr = %s\n", n
->hwaddr
);
1926 fprintf(fout
, "lxc.network.mtu = %s\n", n
->mtu
);
1927 if (n
->ipv4_gateway_auto
)
1928 fprintf(fout
, "lxc.network.ipv4.gateway = auto\n");
1929 else if (n
->ipv4_gateway
) {
1930 char buf
[INET_ADDRSTRLEN
];
1931 inet_ntop(AF_INET
, n
->ipv4_gateway
, buf
, sizeof(buf
));
1932 fprintf(fout
, "lxc.network.ipv4.gateway = %s\n", buf
);
1934 lxc_list_for_each(it2
, &n
->ipv4
) {
1935 struct lxc_inetdev
*i
= it2
->elem
;
1936 char buf
[INET_ADDRSTRLEN
];
1937 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1938 fprintf(fout
, "lxc.network.ipv4 = %s\n", buf
);
1940 if (n
->ipv6_gateway_auto
)
1941 fprintf(fout
, "lxc.network.ipv6.gateway = auto\n");
1942 else if (n
->ipv6_gateway
) {
1943 char buf
[INET6_ADDRSTRLEN
];
1944 inet_ntop(AF_INET6
, n
->ipv6_gateway
, buf
, sizeof(buf
));
1945 fprintf(fout
, "lxc.network.ipv6.gateway = %s\n", buf
);
1947 lxc_list_for_each(it2
, &n
->ipv6
) {
1948 struct lxc_inet6dev
*i
= it2
->elem
;
1949 char buf
[INET6_ADDRSTRLEN
];
1950 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1951 fprintf(fout
, "lxc.network.ipv6 = %s\n", buf
);
1954 lxc_list_for_each(it
, &c
->caps
)
1955 fprintf(fout
, "lxc.cap.drop = %s\n", (char *)it
->elem
);
1956 lxc_list_for_each(it
, &c
->id_map
) {
1957 struct id_map
*idmap
= it
->elem
;
1958 fprintf(fout
, "lxc.id_map = %c %lu %lu %lu\n",
1959 idmap
->idtype
== ID_TYPE_UID
? 'u' : 'g', idmap
->nsid
,
1960 idmap
->hostid
, idmap
->range
);
1962 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1963 lxc_list_for_each(it
, &c
->hooks
[i
])
1964 fprintf(fout
, "lxc.hook.%s = %s\n",
1965 lxchook_names
[i
], (char *)it
->elem
);
1967 if (c
->console
.path
)
1968 fprintf(fout
, "lxc.console = %s\n", c
->console
.path
);
1970 fprintf(fout
, "lxc.rootfs = %s\n", c
->rootfs
.path
);
1971 if (c
->rootfs
.mount
&& strcmp(c
->rootfs
.mount
, LXCROOTFSMOUNT
) != 0)
1972 fprintf(fout
, "lxc.rootfs.mount = %s\n", c
->rootfs
.mount
);
1973 if (c
->rootfs
.pivot
)
1974 fprintf(fout
, "lxc.pivotdir = %s\n", c
->rootfs
.pivot
);