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
*);
60 static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf
*);
61 static int config_lsm_se_context(const char *, const char *, struct lxc_conf
*);
62 static int config_cgroup(const char *, const char *, struct lxc_conf
*);
63 static int config_idmap(const char *, const char *, struct lxc_conf
*);
64 static int config_loglevel(const char *, const char *, struct lxc_conf
*);
65 static int config_logfile(const char *, const char *, struct lxc_conf
*);
66 static int config_mount(const char *, const char *, struct lxc_conf
*);
67 static int config_rootfs(const char *, const char *, struct lxc_conf
*);
68 static int config_rootfs_mount(const char *, const char *, struct lxc_conf
*);
69 static int config_pivotdir(const char *, const char *, struct lxc_conf
*);
70 static int config_utsname(const char *, const char *, struct lxc_conf
*);
71 static int config_hook(const char *, const char *, struct lxc_conf
*lxc_conf
);
72 static int config_network_type(const char *, const char *, struct lxc_conf
*);
73 static int config_network_flags(const char *, const char *, struct lxc_conf
*);
74 static int config_network_link(const char *, const char *, struct lxc_conf
*);
75 static int config_network_name(const char *, const char *, struct lxc_conf
*);
76 static int config_network_veth_pair(const char *, const char *, struct lxc_conf
*);
77 static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf
*);
78 static int config_network_hwaddr(const char *, const char *, struct lxc_conf
*);
79 static int config_network_vlan_id(const char *, const char *, struct lxc_conf
*);
80 static int config_network_mtu(const char *, const char *, struct lxc_conf
*);
81 static int config_network_ipv4(const char *, const char *, struct lxc_conf
*);
82 static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf
*);
83 static int config_network_script(const char *, const char *, struct lxc_conf
*);
84 static int config_network_ipv6(const char *, const char *, struct lxc_conf
*);
85 static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf
*);
86 static int config_cap_drop(const char *, const char *, struct lxc_conf
*);
87 static int config_cap_keep(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
},
102 { "lxc.aa_profile", config_lsm_aa_profile
},
103 { "lxc.se_context", config_lsm_se_context
},
104 { "lxc.cgroup", config_cgroup
},
105 { "lxc.id_map", config_idmap
},
106 { "lxc.loglevel", config_loglevel
},
107 { "lxc.logfile", config_logfile
},
108 { "lxc.mount", config_mount
},
109 { "lxc.rootfs.mount", config_rootfs_mount
},
110 { "lxc.rootfs", config_rootfs
},
111 { "lxc.pivotdir", config_pivotdir
},
112 { "lxc.utsname", config_utsname
},
113 { "lxc.hook.pre-start", config_hook
},
114 { "lxc.hook.pre-mount", config_hook
},
115 { "lxc.hook.mount", config_hook
},
116 { "lxc.hook.autodev", config_hook
},
117 { "lxc.hook.start", config_hook
},
118 { "lxc.hook.post-stop", config_hook
},
119 { "lxc.hook.clone", 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.cap.keep", config_cap_keep
},
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
);
215 static int config_string_item(char **conf_item
, const char *value
)
219 if (!value
|| strlen(value
) == 0)
222 new_value
= strdup(value
);
224 SYSERROR("failed to strdup '%s': %m", value
);
230 *conf_item
= new_value
;
234 static int config_string_item_max(char **conf_item
, const char *value
,
237 if (strlen(value
) >= max
) {
238 ERROR("%s is too long (>= %lu)", value
, max
);
242 return config_string_item(conf_item
, value
);
245 static int config_path_item(char **conf_item
, const char *value
)
247 return config_string_item_max(conf_item
, value
, PATH_MAX
);
251 * config entry is something like "lxc.network.0.ipv4"
252 * the key 'lxc.network.' was found. So we make sure next
253 * comes an integer, find the right callback (by rewriting
254 * the key), and call it.
256 static int config_network_nic(const char *key
, const char *value
,
257 struct lxc_conf
*lxc_conf
)
259 char *copy
= strdup(key
), *p
;
261 struct lxc_config_t
*config
;
264 SYSERROR("failed to allocate memory");
268 * ok we know that to get here we've got "lxc.network."
269 * and it isn't any of the other network entries. So
270 * after the second . should come an integer (# of defined
271 * nic) followed by a valid entry.
273 if (*(key
+12) < '0' || *(key
+12) > '9')
275 p
= index(key
+12, '.');
278 strcpy(copy
+12, p
+1);
279 config
= lxc_getconfig(copy
);
281 ERROR("unknown key %s", key
);
284 ret
= config
->cb(key
, value
, lxc_conf
);
291 static int config_network_type(const char *key
, const char *value
,
292 struct lxc_conf
*lxc_conf
)
294 struct lxc_list
*network
= &lxc_conf
->network
;
295 struct lxc_netdev
*netdev
;
296 struct lxc_list
*list
;
298 netdev
= malloc(sizeof(*netdev
));
300 SYSERROR("failed to allocate memory");
304 memset(netdev
, 0, sizeof(*netdev
));
305 lxc_list_init(&netdev
->ipv4
);
306 lxc_list_init(&netdev
->ipv6
);
308 list
= malloc(sizeof(*list
));
310 SYSERROR("failed to allocate memory");
318 lxc_list_add_tail(network
, list
);
320 if (!strcmp(value
, "veth"))
321 netdev
->type
= LXC_NET_VETH
;
322 else if (!strcmp(value
, "macvlan"))
323 netdev
->type
= LXC_NET_MACVLAN
;
324 else if (!strcmp(value
, "vlan"))
325 netdev
->type
= LXC_NET_VLAN
;
326 else if (!strcmp(value
, "phys"))
327 netdev
->type
= LXC_NET_PHYS
;
328 else if (!strcmp(value
, "empty"))
329 netdev
->type
= LXC_NET_EMPTY
;
331 ERROR("invalid network type %s", value
);
337 static int config_ip_prefix(struct in_addr
*addr
)
339 if (IN_CLASSA(addr
->s_addr
))
340 return 32 - IN_CLASSA_NSHIFT
;
341 if (IN_CLASSB(addr
->s_addr
))
342 return 32 - IN_CLASSB_NSHIFT
;
343 if (IN_CLASSC(addr
->s_addr
))
344 return 32 - IN_CLASSC_NSHIFT
;
350 * if you have p="lxc.network.0.link", pass it p+12
351 * to get back '0' (the index of the nic)
353 static int get_network_netdev_idx(const char *key
)
357 if (*key
< '0' || *key
> '9')
359 ret
= sscanf(key
, "%d", &idx
);
366 * if you have p="lxc.network.0", pass this p+12 and it will return
367 * the netdev of the first configured nic
369 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
370 struct lxc_list
*network
)
372 int i
= 0, idx
= get_network_netdev_idx(key
);
373 struct lxc_netdev
*netdev
= NULL
;
377 lxc_list_for_each(it
, network
) {
386 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
,
387 char *retv
, int inlen
)
389 struct lxc_netdev
*netdev
;
390 int fulllen
= 0, len
;
392 netdev
= get_netdev_from_key(key
+12, &c
->network
);
399 memset(retv
, 0, inlen
);
401 strprint(retv
, inlen
, "script.up\n");
402 if (netdev
->type
!= LXC_NET_EMPTY
) {
403 strprint(retv
, inlen
, "flags\n");
404 strprint(retv
, inlen
, "link\n");
405 strprint(retv
, inlen
, "name\n");
406 strprint(retv
, inlen
, "hwaddr\n");
407 strprint(retv
, inlen
, "mtu\n");
408 strprint(retv
, inlen
, "ipv6\n");
409 strprint(retv
, inlen
, "ipv6_gateway\n");
410 strprint(retv
, inlen
, "ipv4\n");
411 strprint(retv
, inlen
, "ipv4_gateway\n");
413 switch(netdev
->type
) {
415 strprint(retv
, inlen
, "veth.pair\n");
417 case LXC_NET_MACVLAN
:
418 strprint(retv
, inlen
, "macvlan.mode\n");
421 strprint(retv
, inlen
, "vlan.id\n");
429 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
430 struct lxc_list
*network
)
432 struct lxc_netdev
*netdev
= NULL
;
434 if (lxc_list_empty(network
)) {
435 ERROR("network is not created for '%s' = '%s' option",
440 if (get_network_netdev_idx(key
+12) == -1)
441 netdev
= lxc_list_last_elem(network
);
443 netdev
= get_netdev_from_key(key
+12, network
);
446 ERROR("no network device defined for '%s' = '%s' option",
454 static int network_ifname(char **valuep
, const char *value
)
456 if (strlen(value
) >= IFNAMSIZ
) {
457 ERROR("interface name '%s' too long (>%d)\n",
458 value
, IFNAMSIZ
- 1);
462 *valuep
= strdup(value
);
464 ERROR("failed to dup string '%s'", value
);
471 #ifndef MACVLAN_MODE_PRIVATE
472 # define MACVLAN_MODE_PRIVATE 1
475 #ifndef MACVLAN_MODE_VEPA
476 # define MACVLAN_MODE_VEPA 2
479 #ifndef MACVLAN_MODE_BRIDGE
480 # define MACVLAN_MODE_BRIDGE 4
483 static int macvlan_mode(int *valuep
, const char *value
)
489 { "private", MACVLAN_MODE_PRIVATE
},
490 { "vepa", MACVLAN_MODE_VEPA
},
491 { "bridge", MACVLAN_MODE_BRIDGE
},
496 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
497 if (strcmp(m
[i
].name
, value
))
507 static int config_network_flags(const char *key
, const char *value
,
508 struct lxc_conf
*lxc_conf
)
510 struct lxc_netdev
*netdev
;
512 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
516 netdev
->flags
|= IFF_UP
;
521 static int config_network_link(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 network_ifname(&netdev
->link
, value
);
533 static int config_network_name(const char *key
, const char *value
,
534 struct lxc_conf
*lxc_conf
)
536 struct lxc_netdev
*netdev
;
538 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
542 return network_ifname(&netdev
->name
, value
);
545 static int config_network_veth_pair(const char *key
, const char *value
,
546 struct lxc_conf
*lxc_conf
)
548 struct lxc_netdev
*netdev
;
550 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
554 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
557 static int config_network_macvlan_mode(const char *key
, const char *value
,
558 struct lxc_conf
*lxc_conf
)
560 struct lxc_netdev
*netdev
;
562 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
566 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
569 static int config_network_hwaddr(const char *key
, const char *value
,
570 struct lxc_conf
*lxc_conf
)
572 struct lxc_netdev
*netdev
;
574 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
578 return config_string_item(&netdev
->hwaddr
, value
);
581 static int config_network_vlan_id(const char *key
, const char *value
,
582 struct lxc_conf
*lxc_conf
)
584 struct lxc_netdev
*netdev
;
586 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
590 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
596 static int config_network_mtu(const char *key
, const char *value
,
597 struct lxc_conf
*lxc_conf
)
599 struct lxc_netdev
*netdev
;
601 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
605 return config_string_item(&netdev
->mtu
, value
);
608 static int config_network_ipv4(const char *key
, const char *value
,
609 struct lxc_conf
*lxc_conf
)
611 struct lxc_netdev
*netdev
;
612 struct lxc_inetdev
*inetdev
;
613 struct lxc_list
*list
;
614 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
616 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
620 inetdev
= malloc(sizeof(*inetdev
));
622 SYSERROR("failed to allocate ipv4 address");
625 memset(inetdev
, 0, sizeof(*inetdev
));
627 list
= malloc(sizeof(*list
));
629 SYSERROR("failed to allocate memory");
635 list
->elem
= inetdev
;
637 addr
= strdup(value
);
639 ERROR("no address specified");
645 cursor
= strstr(addr
, " ");
651 slash
= strstr(addr
, "/");
657 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
658 SYSERROR("invalid ipv4 address: %s", value
);
665 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
666 SYSERROR("invalid ipv4 broadcast address: %s", value
);
673 /* no prefix specified, determine it from the network class */
674 inetdev
->prefix
= prefix
? atoi(prefix
) :
675 config_ip_prefix(&inetdev
->addr
);
677 /* if no broadcast address, let compute one from the
681 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
682 inetdev
->bcast
.s_addr
|=
683 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
686 lxc_list_add_tail(&netdev
->ipv4
, list
);
692 static int config_network_ipv4_gateway(const char *key
, const char *value
,
693 struct lxc_conf
*lxc_conf
)
695 struct lxc_netdev
*netdev
;
698 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
702 gw
= malloc(sizeof(*gw
));
704 SYSERROR("failed to allocate ipv4 gateway address");
709 ERROR("no ipv4 gateway address specified");
714 if (!strcmp(value
, "auto")) {
715 netdev
->ipv4_gateway
= NULL
;
716 netdev
->ipv4_gateway_auto
= true;
718 if (!inet_pton(AF_INET
, value
, gw
)) {
719 SYSERROR("invalid ipv4 gateway address: %s", value
);
724 netdev
->ipv4_gateway
= gw
;
725 netdev
->ipv4_gateway_auto
= false;
731 static int config_network_ipv6(const char *key
, const char *value
,
732 struct lxc_conf
*lxc_conf
)
734 struct lxc_netdev
*netdev
;
735 struct lxc_inet6dev
*inet6dev
;
736 struct lxc_list
*list
;
740 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
744 inet6dev
= malloc(sizeof(*inet6dev
));
746 SYSERROR("failed to allocate ipv6 address");
749 memset(inet6dev
, 0, sizeof(*inet6dev
));
751 list
= malloc(sizeof(*list
));
753 SYSERROR("failed to allocate memory");
759 list
->elem
= inet6dev
;
761 valdup
= strdup(value
);
763 ERROR("no address specified");
769 inet6dev
->prefix
= 64;
770 slash
= strstr(valdup
, "/");
774 inet6dev
->prefix
= atoi(netmask
);
777 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
778 SYSERROR("invalid ipv6 address: %s", valdup
);
785 lxc_list_add_tail(&netdev
->ipv6
, list
);
791 static int config_network_ipv6_gateway(const char *key
, const char *value
,
792 struct lxc_conf
*lxc_conf
)
794 struct lxc_netdev
*netdev
;
796 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
801 ERROR("no ipv6 gateway address specified");
805 if (!strcmp(value
, "auto")) {
806 netdev
->ipv6_gateway
= NULL
;
807 netdev
->ipv6_gateway_auto
= true;
811 gw
= malloc(sizeof(*gw
));
813 SYSERROR("failed to allocate ipv6 gateway address");
817 if (!inet_pton(AF_INET6
, value
, gw
)) {
818 SYSERROR("invalid ipv6 gateway address: %s", value
);
823 netdev
->ipv6_gateway
= gw
;
824 netdev
->ipv6_gateway_auto
= false;
830 static int config_network_script(const char *key
, const char *value
,
831 struct lxc_conf
*lxc_conf
)
833 struct lxc_netdev
*netdev
;
835 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
839 char *copy
= strdup(value
);
841 SYSERROR("failed to dup string '%s'", value
);
844 if (strstr(key
, "script.up") != NULL
) {
845 netdev
->upscript
= copy
;
848 if (strcmp(key
, "lxc.network.script.down") == 0) {
849 netdev
->downscript
= copy
;
852 SYSERROR("Unknown key: %s", key
);
857 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
859 struct lxc_list
*hooklist
;
861 hooklist
= malloc(sizeof(*hooklist
));
866 hooklist
->elem
= hook
;
867 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
871 static int config_seccomp(const char *key
, const char *value
,
872 struct lxc_conf
*lxc_conf
)
874 return config_path_item(&lxc_conf
->seccomp
, value
);
877 static int config_hook(const char *key
, const char *value
,
878 struct lxc_conf
*lxc_conf
)
880 char *copy
= strdup(value
);
882 SYSERROR("failed to dup string '%s'", value
);
885 if (strcmp(key
, "lxc.hook.pre-start") == 0)
886 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
887 else if (strcmp(key
, "lxc.hook.pre-mount") == 0)
888 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
889 else if (strcmp(key
, "lxc.hook.autodev") == 0)
890 return add_hook(lxc_conf
, LXCHOOK_AUTODEV
, copy
);
891 else if (strcmp(key
, "lxc.hook.mount") == 0)
892 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
893 else if (strcmp(key
, "lxc.hook.start") == 0)
894 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
895 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
896 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
897 else if (strcmp(key
, "lxc.hook.clone") == 0)
898 return add_hook(lxc_conf
, LXCHOOK_CLONE
, copy
);
899 SYSERROR("Unknown key: %s", key
);
904 static int config_personality(const char *key
, const const char *value
,
905 struct lxc_conf
*lxc_conf
)
907 signed long personality
= lxc_config_parse_arch(value
);
909 if (personality
>= 0)
910 lxc_conf
->personality
= personality
;
912 WARN("unsupported personality '%s'", value
);
917 static int config_pts(const char *key
, const char *value
,
918 struct lxc_conf
*lxc_conf
)
920 int maxpts
= atoi(value
);
922 lxc_conf
->pts
= maxpts
;
927 static int config_tty(const char *key
, const char *value
,
928 struct lxc_conf
*lxc_conf
)
930 int nbtty
= atoi(value
);
932 lxc_conf
->tty
= nbtty
;
937 static int config_ttydir(const char *key
, const char *value
,
938 struct lxc_conf
*lxc_conf
)
940 return config_string_item_max(&lxc_conf
->ttydir
, value
, NAME_MAX
+1);
943 static int config_kmsg(const char *key
, const char *value
,
944 struct lxc_conf
*lxc_conf
)
953 static int config_lsm_aa_profile(const char *key
, const char *value
,
954 struct lxc_conf
*lxc_conf
)
956 return config_string_item(&lxc_conf
->lsm_aa_profile
, value
);
959 static int config_lsm_se_context(const char *key
, const char *value
,
960 struct lxc_conf
*lxc_conf
)
962 return config_string_item(&lxc_conf
->lsm_se_context
, value
);
965 static int config_logfile(const char *key
, const char *value
,
966 struct lxc_conf
*lxc_conf
)
970 // store these values in the lxc_conf, and then try to set for
971 // actual current logging.
972 ret
= config_path_item(&lxc_conf
->logfile
, value
);
974 ret
= lxc_log_set_file(lxc_conf
->logfile
);
978 static int config_loglevel(const char *key
, const char *value
,
979 struct lxc_conf
*lxc_conf
)
983 if (!value
|| strlen(value
) == 0)
986 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET
) {
987 DEBUG("Log level already set - ignoring new value");
990 if (value
[0] >= '0' && value
[0] <= '9')
991 newlevel
= atoi(value
);
993 newlevel
= lxc_log_priority_to_int(value
);
994 // store these values in the lxc_conf, and then try to set for
995 // actual current logging.
996 lxc_conf
->loglevel
= newlevel
;
997 return lxc_log_set_level(newlevel
);
1000 static int config_autodev(const char *key
, const char *value
,
1001 struct lxc_conf
*lxc_conf
)
1003 int v
= atoi(value
);
1005 lxc_conf
->autodev
= v
;
1010 static int sig_num(const char *sig
)
1016 n
= strtol(sig
, &endp
, 10);
1017 if (sig
== endp
|| n
< 0 || errno
!= 0)
1022 static int rt_sig_num(const char *signame
)
1027 if (strncasecmp(signame
, "max-", 4) == 0) {
1031 if (!isdigit(*signame
))
1033 sig_n
= sig_num(signame
);
1034 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1035 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1040 static int sig_parse(const char *signame
) {
1043 if (isdigit(*signame
)) {
1044 return sig_num(signame
);
1045 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1047 if (strncasecmp(signame
, "rt", 2) == 0)
1048 return rt_sig_num(signame
+ 2);
1049 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1050 if (strcasecmp (signames
[n
].name
, signame
) == 0)
1051 return signames
[n
].num
;
1057 static int config_stopsignal(const char *key
, const char *value
,
1058 struct lxc_conf
*lxc_conf
)
1060 int sig_n
= sig_parse(value
);
1064 lxc_conf
->stopsignal
= sig_n
;
1069 static int config_cgroup(const char *key
, const char *value
,
1070 struct lxc_conf
*lxc_conf
)
1072 char *token
= "lxc.cgroup.";
1074 struct lxc_list
*cglist
= NULL
;
1075 struct lxc_cgroup
*cgelem
= NULL
;
1077 subkey
= strstr(key
, token
);
1082 if (!strlen(subkey
))
1085 if (strlen(subkey
) == strlen(token
))
1088 subkey
+= strlen(token
);
1090 cglist
= malloc(sizeof(*cglist
));
1094 cgelem
= malloc(sizeof(*cgelem
));
1097 memset(cgelem
, 0, sizeof(*cgelem
));
1099 cgelem
->subsystem
= strdup(subkey
);
1100 cgelem
->value
= strdup(value
);
1102 if (!cgelem
->subsystem
|| !cgelem
->value
)
1105 cglist
->elem
= cgelem
;
1107 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1116 if (cgelem
->subsystem
)
1117 free(cgelem
->subsystem
);
1120 free(cgelem
->value
);
1128 static int config_idmap(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
1130 char *token
= "lxc.id_map";
1132 struct lxc_list
*idmaplist
= NULL
;
1133 struct id_map
*idmap
= NULL
;
1134 unsigned long hostid
, nsid
, range
;
1138 subkey
= strstr(key
, token
);
1143 if (!strlen(subkey
))
1146 idmaplist
= malloc(sizeof(*idmaplist
));
1150 idmap
= malloc(sizeof(*idmap
));
1153 memset(idmap
, 0, sizeof(*idmap
));
1155 idmaplist
->elem
= idmap
;
1157 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1159 ret
= sscanf(value
, "%c %lu %lu %lu", &type
, &nsid
, &hostid
, &range
);
1162 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1164 idmap
->idtype
= ID_TYPE_UID
;
1165 else if (type
== 'g')
1166 idmap
->idtype
= ID_TYPE_GID
;
1169 idmap
->hostid
= hostid
;
1171 idmap
->range
= range
;
1186 static int config_fstab(const char *key
, const char *value
,
1187 struct lxc_conf
*lxc_conf
)
1189 return config_path_item(&lxc_conf
->fstab
, value
);
1192 static int config_mount_auto(const char *key
, const char *value
,
1193 struct lxc_conf
*lxc_conf
)
1195 char *autos
, *autoptr
, *sptr
, *token
;
1196 static struct { const char *token
; int mask
; int flag
; } allowed_auto_mounts
[] = {
1197 { "proc", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
1198 { "proc:mixed", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
1199 { "proc:rw", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_RW
},
1200 { "sys", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
1201 { "sys:ro", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
1202 { "sys:rw", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RW
},
1203 { "cgroup", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
1204 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
1205 { "cgroup:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RO
},
1206 { "cgroup:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RW
},
1207 { "cgroup-full", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
1208 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
1209 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RO
},
1210 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RW
},
1211 /* NB: For adding anything that ist just a single on/off, but has
1212 * no options: keep mask and flag identical and just define the
1213 * enum value as an unused bit so far
1223 autos
= strdup(value
);
1225 SYSERROR("failed to dup '%s'", value
);
1229 for (autoptr
= autos
; ; autoptr
= NULL
) {
1230 token
= strtok_r(autoptr
, " \t", &sptr
);
1236 for (i
= 0; allowed_auto_mounts
[i
].token
; i
++) {
1237 if (!strcmp(allowed_auto_mounts
[i
].token
, token
))
1241 if (!allowed_auto_mounts
[i
].token
) {
1242 ERROR("Invalid filesystem to automount: %s", token
);
1246 lxc_conf
->auto_mounts
&= ~allowed_auto_mounts
[i
].mask
;
1247 lxc_conf
->auto_mounts
|= allowed_auto_mounts
[i
].flag
;
1255 static int config_mount(const char *key
, const char *value
,
1256 struct lxc_conf
*lxc_conf
)
1258 char *fstab_token
= "lxc.mount";
1259 char *token
= "lxc.mount.entry";
1260 char *auto_token
= "lxc.mount.auto";
1263 struct lxc_list
*mntlist
;
1265 subkey
= strstr(key
, token
);
1268 subkey
= strstr(key
, auto_token
);
1271 subkey
= strstr(key
, fstab_token
);
1276 return config_fstab(key
, value
, lxc_conf
);
1279 return config_mount_auto(key
, value
, lxc_conf
);
1282 if (!strlen(subkey
))
1285 mntlist
= malloc(sizeof(*mntlist
));
1289 mntelem
= strdup(value
);
1294 mntlist
->elem
= mntelem
;
1296 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1301 static int config_cap_keep(const char *key
, const char *value
,
1302 struct lxc_conf
*lxc_conf
)
1304 char *keepcaps
, *keepptr
, *sptr
, *token
;
1305 struct lxc_list
*keeplist
;
1311 keepcaps
= strdup(value
);
1313 SYSERROR("failed to dup '%s'", value
);
1317 /* in case several capability keep is specified in a single line
1318 * split these caps in a single element for the list */
1319 for (keepptr
= keepcaps
;;keepptr
= NULL
) {
1320 token
= strtok_r(keepptr
, " \t", &sptr
);
1326 keeplist
= malloc(sizeof(*keeplist
));
1328 SYSERROR("failed to allocate keepcap list");
1332 keeplist
->elem
= strdup(token
);
1333 if (!keeplist
->elem
) {
1334 SYSERROR("failed to dup '%s'", token
);
1339 lxc_list_add_tail(&lxc_conf
->keepcaps
, keeplist
);
1347 static int config_cap_drop(const char *key
, const char *value
,
1348 struct lxc_conf
*lxc_conf
)
1350 char *dropcaps
, *dropptr
, *sptr
, *token
;
1351 struct lxc_list
*droplist
;
1357 dropcaps
= strdup(value
);
1359 SYSERROR("failed to dup '%s'", value
);
1363 /* in case several capability drop is specified in a single line
1364 * split these caps in a single element for the list */
1365 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
1366 token
= strtok_r(dropptr
, " \t", &sptr
);
1372 droplist
= malloc(sizeof(*droplist
));
1374 SYSERROR("failed to allocate drop list");
1378 droplist
->elem
= strdup(token
);
1379 if (!droplist
->elem
) {
1380 SYSERROR("failed to dup '%s'", token
);
1385 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1393 static int config_console(const char *key
, const char *value
,
1394 struct lxc_conf
*lxc_conf
)
1396 return config_path_item(&lxc_conf
->console
.path
, value
);
1399 static int config_includefile(const char *key
, const char *value
,
1400 struct lxc_conf
*lxc_conf
)
1402 return lxc_config_read(value
, lxc_conf
);
1405 static int config_rootfs(const char *key
, const char *value
,
1406 struct lxc_conf
*lxc_conf
)
1408 return config_path_item(&lxc_conf
->rootfs
.path
, value
);
1411 static int config_rootfs_mount(const char *key
, const char *value
,
1412 struct lxc_conf
*lxc_conf
)
1414 return config_path_item(&lxc_conf
->rootfs
.mount
, value
);
1417 static int config_pivotdir(const char *key
, const char *value
,
1418 struct lxc_conf
*lxc_conf
)
1420 return config_path_item(&lxc_conf
->rootfs
.pivot
, value
);
1423 static int config_utsname(const char *key
, const char *value
,
1424 struct lxc_conf
*lxc_conf
)
1426 struct utsname
*utsname
;
1428 utsname
= malloc(sizeof(*utsname
));
1430 SYSERROR("failed to allocate memory");
1434 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1435 ERROR("node name '%s' is too long",
1441 strcpy(utsname
->nodename
, value
);
1442 if (lxc_conf
->utsname
)
1443 free(lxc_conf
->utsname
);
1444 lxc_conf
->utsname
= utsname
;
1449 static int parse_line(char *buffer
, void *data
)
1451 struct lxc_config_t
*config
;
1458 if (lxc_is_line_empty(buffer
))
1461 /* we have to dup the buffer otherwise, at the re-exec for
1462 * reboot we modified the original string on the stack by
1463 * replacing '=' by '\0' below
1465 linep
= line
= strdup(buffer
);
1467 SYSERROR("failed to allocate memory for '%s'", buffer
);
1471 line
+= lxc_char_left_gc(line
, strlen(line
));
1473 /* martian option - ignoring it, the commented lines beginning by '#'
1476 if (strncmp(line
, "lxc.", 4))
1481 dot
= strstr(line
, "=");
1483 ERROR("invalid configuration line: %s", line
);
1491 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1493 value
+= lxc_char_left_gc(value
, strlen(value
));
1494 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1496 config
= lxc_getconfig(key
);
1498 ERROR("unknown key %s", key
);
1502 ret
= config
->cb(key
, value
, data
);
1509 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1511 return parse_line(buffer
, conf
);
1514 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1516 if( access(file
, R_OK
) == -1 ) {
1519 /* Catch only the top level config file name in the structure */
1520 if( ! conf
->rcfile
) {
1521 conf
->rcfile
= strdup( file
);
1523 return lxc_file_for_each_line(file
, parse_line
, conf
);
1526 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1528 struct lxc_list
*dent
;
1530 dent
= malloc(sizeof(struct lxc_list
));
1535 lxc_list_add_tail(defines
, dent
);
1539 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1541 struct lxc_list
*it
,*next
;
1544 lxc_list_for_each(it
, defines
) {
1545 ret
= lxc_config_readline(it
->elem
, conf
);
1550 lxc_list_for_each_safe(it
, defines
, next
) {
1558 signed long lxc_config_parse_arch(const char *arch
)
1560 #if HAVE_SYS_PERSONALITY_H
1565 { "x86", PER_LINUX32
},
1566 { "i686", PER_LINUX32
},
1567 { "x86_64", PER_LINUX
},
1568 { "amd64", PER_LINUX
},
1570 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1574 for (i
= 0; i
< len
; i
++) {
1575 if (!strcmp(pername
[i
].name
, arch
))
1576 return pername
[i
].per
;
1583 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
1588 memset(retv
, 0, inlen
);
1589 return snprintf(retv
, inlen
, "%d", v
);
1592 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
1599 memset(retv
, 0, inlen
);
1601 #if HAVE_SYS_PERSONALITY_H
1604 switch(c
->personality
) {
1605 case PER_LINUX32
: strprint(retv
, inlen
, "x86"); break;
1606 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
1615 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1616 * then just the value(s) will be printed. Since there still could be
1617 * more than one, it is newline-separated.
1618 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1619 * already have newlines?)
1620 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1621 * in 'lxc.cgroup.subsystem.key = value' format.
1623 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
1626 int fulllen
= 0, len
;
1628 struct lxc_list
*it
;
1633 memset(retv
, 0, inlen
);
1635 if (strcmp(key
, "all") == 0)
1638 lxc_list_for_each(it
, &c
->cgroup
) {
1639 struct lxc_cgroup
*cg
= it
->elem
;
1641 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1642 } else if (strcmp(cg
->subsystem
, key
) == 0) {
1643 strprint(retv
, inlen
, "%s\n", cg
->value
);
1649 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
1653 int len
, fulllen
= 0, found
= -1;
1654 struct lxc_list
*it
;
1657 /* "lxc.hook.mount" */
1658 subkey
= index(key
, '.');
1659 if (subkey
) subkey
= index(subkey
+1, '.');
1665 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1666 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
1677 memset(retv
, 0, inlen
);
1679 lxc_list_for_each(it
, &c
->hooks
[found
]) {
1680 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1685 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
1687 int len
, fulllen
= 0;
1688 struct lxc_list
*it
;
1693 memset(retv
, 0, inlen
);
1695 lxc_list_for_each(it
, &c
->caps
) {
1696 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1701 static int lxc_get_item_cap_keep(struct lxc_conf
*c
, char *retv
, int inlen
)
1703 int len
, fulllen
= 0;
1704 struct lxc_list
*it
;
1709 memset(retv
, 0, inlen
);
1711 lxc_list_for_each(it
, &c
->keepcaps
) {
1712 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1717 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
1719 int len
, fulllen
= 0;
1720 struct lxc_list
*it
;
1725 memset(retv
, 0, inlen
);
1727 lxc_list_for_each(it
, &c
->mount_list
) {
1728 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1734 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1735 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1736 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1737 * of an address. ipv4 and ipv6 return lists (newline-separated).
1738 * things like veth.pair return '' if invalid (i.e. if called for vlan
1741 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
1745 int len
, fulllen
= 0;
1746 struct lxc_netdev
*netdev
;
1751 memset(retv
, 0, inlen
);
1753 p1
= index(key
, '.');
1754 if (!p1
|| *(p1
+1) == '\0') return -1;
1757 netdev
= get_netdev_from_key(key
, &c
->network
);
1760 if (strcmp(p1
, "name") == 0) {
1762 strprint(retv
, inlen
, "%s", netdev
->name
);
1763 } else if (strcmp(p1
, "type") == 0) {
1764 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
1765 } else if (strcmp(p1
, "link") == 0) {
1767 strprint(retv
, inlen
, "%s", netdev
->link
);
1768 } else if (strcmp(p1
, "flags") == 0) {
1769 if (netdev
->flags
& IFF_UP
)
1770 strprint(retv
, inlen
, "up");
1771 } else if (strcmp(p1
, "upscript") == 0) {
1772 if (netdev
->upscript
)
1773 strprint(retv
, inlen
, "%s", netdev
->upscript
);
1774 } else if (strcmp(p1
, "hwaddr") == 0) {
1776 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
1777 } else if (strcmp(p1
, "mtu") == 0) {
1779 strprint(retv
, inlen
, "%s", netdev
->mtu
);
1780 } else if (strcmp(p1
, "macvlan.mode") == 0) {
1781 if (netdev
->type
== LXC_NET_MACVLAN
) {
1783 switch (netdev
->priv
.macvlan_attr
.mode
) {
1784 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1785 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1786 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1787 default: mode
= "(invalid)"; break;
1789 strprint(retv
, inlen
, "%s", mode
);
1791 } else if (strcmp(p1
, "veth.pair") == 0) {
1792 if (netdev
->type
== LXC_NET_VETH
) {
1793 strprint(retv
, inlen
, "%s",
1794 netdev
->priv
.veth_attr
.pair
?
1795 netdev
->priv
.veth_attr
.pair
:
1796 netdev
->priv
.veth_attr
.veth1
);
1798 } else if (strcmp(p1
, "vlan") == 0) {
1799 if (netdev
->type
== LXC_NET_VLAN
) {
1800 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
1802 } else if (strcmp(p1
, "ipv4_gateway") == 0) {
1803 if (netdev
->ipv4_gateway_auto
) {
1804 strprint(retv
, inlen
, "auto");
1805 } else if (netdev
->ipv4_gateway
) {
1806 char buf
[INET_ADDRSTRLEN
];
1807 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
1808 strprint(retv
, inlen
, "%s", buf
);
1810 } else if (strcmp(p1
, "ipv4") == 0) {
1811 struct lxc_list
*it2
;
1812 lxc_list_for_each(it2
, &netdev
->ipv4
) {
1813 struct lxc_inetdev
*i
= it2
->elem
;
1814 char buf
[INET_ADDRSTRLEN
];
1815 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1816 strprint(retv
, inlen
, "%s\n", buf
);
1818 } else if (strcmp(p1
, "ipv6_gateway") == 0) {
1819 if (netdev
->ipv6_gateway_auto
) {
1820 strprint(retv
, inlen
, "auto");
1821 } else if (netdev
->ipv6_gateway
) {
1822 char buf
[INET_ADDRSTRLEN
];
1823 inet_ntop(AF_INET
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
1824 strprint(retv
, inlen
, "%s", buf
);
1826 } else if (strcmp(p1
, "ipv6") == 0) {
1827 struct lxc_list
*it2
;
1828 lxc_list_for_each(it2
, &netdev
->ipv6
) {
1829 struct lxc_inetdev
*i
= it2
->elem
;
1830 char buf
[INET_ADDRSTRLEN
];
1831 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
1832 strprint(retv
, inlen
, "%s\n", buf
);
1838 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
1840 int len
, fulllen
= 0;
1841 struct lxc_list
*it
;
1846 memset(retv
, 0, inlen
);
1848 lxc_list_for_each(it
, &c
->network
) {
1849 struct lxc_netdev
*n
= it
->elem
;
1850 const char *t
= lxc_net_type_to_str(n
->type
);
1851 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
1856 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
1859 const char *v
= NULL
;
1861 if (strcmp(key
, "lxc.mount.entry") == 0)
1862 return lxc_get_mount_entries(c
, retv
, inlen
);
1863 else if (strcmp(key
, "lxc.mount") == 0)
1865 else if (strcmp(key
, "lxc.tty") == 0)
1866 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
1867 else if (strcmp(key
, "lxc.pts") == 0)
1868 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
1869 else if (strcmp(key
, "lxc.devttydir") == 0)
1871 else if (strcmp(key
, "lxc.arch") == 0)
1872 return lxc_get_arch_entry(c
, retv
, inlen
);
1873 else if (strcmp(key
, "lxc.aa_profile") == 0)
1874 v
= c
->lsm_aa_profile
;
1875 else if (strcmp(key
, "lxc.se_context") == 0)
1876 v
= c
->lsm_se_context
;
1877 else if (strcmp(key
, "lxc.logfile") == 0)
1878 v
= lxc_log_get_file();
1879 else if (strcmp(key
, "lxc.loglevel") == 0)
1880 v
= lxc_log_priority_to_string(lxc_log_get_level());
1881 else if (strcmp(key
, "lxc.cgroup") == 0) // all cgroup info
1882 return lxc_get_cgroup_entry(c
, retv
, inlen
, "all");
1883 else if (strncmp(key
, "lxc.cgroup.", 11) == 0) // specific cgroup info
1884 return lxc_get_cgroup_entry(c
, retv
, inlen
, key
+ 11);
1885 else if (strcmp(key
, "lxc.utsname") == 0)
1886 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
1887 else if (strcmp(key
, "lxc.console") == 0)
1888 v
= c
->console
.path
;
1889 else if (strcmp(key
, "lxc.rootfs.mount") == 0)
1890 v
= c
->rootfs
.mount
;
1891 else if (strcmp(key
, "lxc.rootfs") == 0)
1893 else if (strcmp(key
, "lxc.pivotdir") == 0)
1894 v
= c
->rootfs
.pivot
;
1895 else if (strcmp(key
, "lxc.cap.drop") == 0)
1896 return lxc_get_item_cap_drop(c
, retv
, inlen
);
1897 else if (strcmp(key
, "lxc.cap.keep") == 0)
1898 return lxc_get_item_cap_keep(c
, retv
, inlen
);
1899 else if (strncmp(key
, "lxc.hook", 8) == 0)
1900 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
1901 else if (strcmp(key
, "lxc.network") == 0)
1902 return lxc_get_item_network(c
, retv
, inlen
);
1903 else if (strncmp(key
, "lxc.network.", 12) == 0)
1904 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
1909 if (retv
&& inlen
>= strlen(v
) + 1)
1910 strncpy(retv
, v
, strlen(v
)+1);
1914 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
1916 if (strcmp(key
, "lxc.network") == 0)
1917 return lxc_clear_config_network(c
);
1918 else if (strncmp(key
, "lxc.network.", 12) == 0)
1919 return lxc_clear_nic(c
, key
+ 12);
1920 else if (strcmp(key
, "lxc.cap.drop") == 0)
1921 return lxc_clear_config_caps(c
);
1922 else if (strcmp(key
, "lxc.cap.keep") == 0)
1923 return lxc_clear_config_keepcaps(c
);
1924 else if (strncmp(key
, "lxc.cgroup", 10) == 0)
1925 return lxc_clear_cgroups(c
, key
);
1926 else if (strcmp(key
, "lxc.mount.entries") == 0)
1927 return lxc_clear_mount_entries(c
);
1928 else if (strncmp(key
, "lxc.hook", 8) == 0)
1929 return lxc_clear_hooks(c
, key
);
1935 * writing out a confile.
1937 void write_config(FILE *fout
, struct lxc_conf
*c
)
1939 struct lxc_list
*it
;
1943 fprintf(fout
, "lxc.mount = %s\n", c
->fstab
);
1944 lxc_list_for_each(it
, &c
->mount_list
) {
1945 fprintf(fout
, "lxc.mount.entry = %s\n", (char *)it
->elem
);
1947 if (c
->auto_mounts
& LXC_AUTO_ALL_MASK
) {
1948 fprintf(fout
, "lxc.mount.auto =");
1949 switch (c
->auto_mounts
& LXC_AUTO_PROC_MASK
) {
1950 case LXC_AUTO_PROC_MIXED
: fprintf(fout
, " proc:mixed"); break;
1951 case LXC_AUTO_PROC_RW
: fprintf(fout
, " proc:rw"); break;
1954 switch (c
->auto_mounts
& LXC_AUTO_SYS_MASK
) {
1955 case LXC_AUTO_SYS_RO
: fprintf(fout
, " sys:ro"); break;
1956 case LXC_AUTO_SYS_RW
: fprintf(fout
, " sys:rw"); break;
1959 switch (c
->auto_mounts
& LXC_AUTO_CGROUP_MASK
) {
1960 case LXC_AUTO_CGROUP_MIXED
: fprintf(fout
, " cgroup:mixed"); break;
1961 case LXC_AUTO_CGROUP_RO
: fprintf(fout
, " cgroup:ro"); break;
1962 case LXC_AUTO_CGROUP_RW
: fprintf(fout
, " cgroup:rw"); break;
1963 case LXC_AUTO_CGROUP_FULL_MIXED
: fprintf(fout
, " cgroup-full:mixed"); break;
1964 case LXC_AUTO_CGROUP_FULL_RO
: fprintf(fout
, " cgroup-full:ro"); break;
1965 case LXC_AUTO_CGROUP_FULL_RW
: fprintf(fout
, " cgroup-full:rw"); break;
1968 fprintf(fout
, "\n");
1971 fprintf(fout
, "lxc.tty = %d\n", c
->tty
);
1973 fprintf(fout
, "lxc.pts = %d\n", c
->pts
);
1975 fprintf(fout
, "lxc.devttydir = %s\n", c
->ttydir
);
1976 #if HAVE_SYS_PERSONALITY_H
1977 switch(c
->personality
) {
1978 case PER_LINUX32
: fprintf(fout
, "lxc.arch = x86\n"); break;
1979 case PER_LINUX
: fprintf(fout
, "lxc.arch = x86_64\n"); break;
1983 if (c
->lsm_aa_profile
)
1984 fprintf(fout
, "lxc.aa_profile = %s\n", c
->lsm_aa_profile
);
1985 if (c
->lsm_se_context
)
1986 fprintf(fout
, "lxc.se_context = %s\n", c
->lsm_se_context
);
1987 if (c
->loglevel
!= LXC_LOG_PRIORITY_NOTSET
)
1988 fprintf(fout
, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c
->loglevel
));
1990 fprintf(fout
, "lxc.logfile = %s\n", c
->logfile
);
1991 lxc_list_for_each(it
, &c
->cgroup
) {
1992 struct lxc_cgroup
*cg
= it
->elem
;
1993 fprintf(fout
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1996 fprintf(fout
, "lxc.utsname = %s\n", c
->utsname
->nodename
);
1997 lxc_list_for_each(it
, &c
->network
) {
1998 struct lxc_netdev
*n
= it
->elem
;
1999 const char *t
= lxc_net_type_to_str(n
->type
);
2000 struct lxc_list
*it2
;
2001 fprintf(fout
, "lxc.network.type = %s\n", t
? t
: "(invalid)");
2002 if (n
->flags
& IFF_UP
)
2003 fprintf(fout
, "lxc.network.flags = up\n");
2005 fprintf(fout
, "lxc.network.link = %s\n", n
->link
);
2007 fprintf(fout
, "lxc.network.name = %s\n", n
->name
);
2008 if (n
->type
== LXC_NET_MACVLAN
) {
2010 switch (n
->priv
.macvlan_attr
.mode
) {
2011 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
2012 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
2013 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
2014 default: mode
= "(invalid)"; break;
2016 fprintf(fout
, "lxc.network.macvlan.mode = %s\n", mode
);
2017 } else if (n
->type
== LXC_NET_VETH
) {
2018 if (n
->priv
.veth_attr
.pair
)
2019 fprintf(fout
, "lxc.network.veth.pair = %s\n",
2020 n
->priv
.veth_attr
.pair
);
2021 } else if (n
->type
== LXC_NET_VLAN
) {
2022 fprintf(fout
, "lxc.network.vlan.id = %d\n", n
->priv
.vlan_attr
.vid
);
2025 fprintf(fout
, "lxc.network.script.up = %s\n", n
->upscript
);
2027 fprintf(fout
, "lxc.network.hwaddr = %s\n", n
->hwaddr
);
2029 fprintf(fout
, "lxc.network.mtu = %s\n", n
->mtu
);
2030 if (n
->ipv4_gateway_auto
)
2031 fprintf(fout
, "lxc.network.ipv4.gateway = auto\n");
2032 else if (n
->ipv4_gateway
) {
2033 char buf
[INET_ADDRSTRLEN
];
2034 inet_ntop(AF_INET
, n
->ipv4_gateway
, buf
, sizeof(buf
));
2035 fprintf(fout
, "lxc.network.ipv4.gateway = %s\n", buf
);
2037 lxc_list_for_each(it2
, &n
->ipv4
) {
2038 struct lxc_inetdev
*i
= it2
->elem
;
2039 char buf
[INET_ADDRSTRLEN
];
2040 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
2041 fprintf(fout
, "lxc.network.ipv4 = %s\n", buf
);
2043 if (n
->ipv6_gateway_auto
)
2044 fprintf(fout
, "lxc.network.ipv6.gateway = auto\n");
2045 else if (n
->ipv6_gateway
) {
2046 char buf
[INET6_ADDRSTRLEN
];
2047 inet_ntop(AF_INET6
, n
->ipv6_gateway
, buf
, sizeof(buf
));
2048 fprintf(fout
, "lxc.network.ipv6.gateway = %s\n", buf
);
2050 lxc_list_for_each(it2
, &n
->ipv6
) {
2051 struct lxc_inet6dev
*i
= it2
->elem
;
2052 char buf
[INET6_ADDRSTRLEN
];
2053 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
2054 fprintf(fout
, "lxc.network.ipv6 = %s\n", buf
);
2057 lxc_list_for_each(it
, &c
->caps
)
2058 fprintf(fout
, "lxc.cap.drop = %s\n", (char *)it
->elem
);
2059 lxc_list_for_each(it
, &c
->keepcaps
)
2060 fprintf(fout
, "lxc.cap.keep = %s\n", (char *)it
->elem
);
2061 lxc_list_for_each(it
, &c
->id_map
) {
2062 struct id_map
*idmap
= it
->elem
;
2063 fprintf(fout
, "lxc.id_map = %c %lu %lu %lu\n",
2064 idmap
->idtype
== ID_TYPE_UID
? 'u' : 'g', idmap
->nsid
,
2065 idmap
->hostid
, idmap
->range
);
2067 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
2068 lxc_list_for_each(it
, &c
->hooks
[i
])
2069 fprintf(fout
, "lxc.hook.%s = %s\n",
2070 lxchook_names
[i
], (char *)it
->elem
);
2072 if (c
->console
.path
)
2073 fprintf(fout
, "lxc.console = %s\n", c
->console
.path
);
2075 fprintf(fout
, "lxc.rootfs = %s\n", c
->rootfs
.path
);
2076 if (c
->rootfs
.mount
&& strcmp(c
->rootfs
.mount
, LXCROOTFSMOUNT
) != 0)
2077 fprintf(fout
, "lxc.rootfs.mount = %s\n", c
->rootfs
.mount
);
2078 if (c
->rootfs
.pivot
)
2079 fprintf(fout
, "lxc.pivotdir = %s\n", c
->rootfs
.pivot
);