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
);
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
)
968 static int config_lsm_aa_profile(const char *key
, const char *value
,
969 struct lxc_conf
*lxc_conf
)
973 if (!value
|| strlen(value
) == 0)
975 path
= strdup(value
);
977 SYSERROR("failed to strdup '%s': %m", value
);
981 if (lxc_conf
->lsm_aa_profile
)
982 free(lxc_conf
->lsm_aa_profile
);
983 lxc_conf
->lsm_aa_profile
= path
;
988 static int config_lsm_se_context(const char *key
, const char *value
,
989 struct lxc_conf
*lxc_conf
)
993 if (!value
|| strlen(value
) == 0)
995 path
= strdup(value
);
997 SYSERROR("failed to strdup '%s': %m", value
);
1001 if (lxc_conf
->lsm_se_context
)
1002 free(lxc_conf
->lsm_se_context
);
1003 lxc_conf
->lsm_se_context
= path
;
1008 static int config_logfile(const char *key
, const char *value
,
1009 struct lxc_conf
*lxc_conf
)
1011 // store these values in the lxc_conf, and then try to set for
1012 // actual current logging.
1013 if (lxc_conf
->logfile
)
1014 free(lxc_conf
->logfile
);
1015 lxc_conf
->logfile
= strdup(value
);
1016 return lxc_log_set_file(value
);
1019 static int config_loglevel(const char *key
, const char *value
,
1020 struct lxc_conf
*lxc_conf
)
1024 if (!value
|| strlen(value
) == 0)
1027 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET
) {
1028 DEBUG("Log level already set - ignoring new value");
1031 if (value
[0] >= '0' && value
[0] <= '9')
1032 newlevel
= atoi(value
);
1034 newlevel
= lxc_log_priority_to_int(value
);
1035 // store these values in the lxc_conf, and then try to set for
1036 // actual current logging.
1037 lxc_conf
->loglevel
= newlevel
;
1038 return lxc_log_set_level(newlevel
);
1041 static int config_autodev(const char *key
, const char *value
,
1042 struct lxc_conf
*lxc_conf
)
1044 int v
= atoi(value
);
1046 lxc_conf
->autodev
= v
;
1051 static int sig_num(const char *sig
)
1057 n
= strtol(sig
, &endp
, 10);
1058 if (sig
== endp
|| n
< 0 || errno
!= 0)
1063 static int rt_sig_num(const char *signame
)
1068 if (strncasecmp(signame
, "max-", 4) == 0) {
1072 if (!isdigit(*signame
))
1074 sig_n
= sig_num(signame
);
1075 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1076 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1081 static int sig_parse(const char *signame
) {
1084 if (isdigit(*signame
)) {
1085 return sig_num(signame
);
1086 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1088 if (strncasecmp(signame
, "rt", 2) == 0)
1089 return rt_sig_num(signame
+ 2);
1090 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1091 if (strcasecmp (signames
[n
].name
, signame
) == 0)
1092 return signames
[n
].num
;
1098 static int config_stopsignal(const char *key
, const char *value
,
1099 struct lxc_conf
*lxc_conf
)
1101 int sig_n
= sig_parse(value
);
1105 lxc_conf
->stopsignal
= sig_n
;
1110 static int config_cgroup(const char *key
, const char *value
,
1111 struct lxc_conf
*lxc_conf
)
1113 char *token
= "lxc.cgroup.";
1115 struct lxc_list
*cglist
= NULL
;
1116 struct lxc_cgroup
*cgelem
= NULL
;
1118 subkey
= strstr(key
, token
);
1123 if (!strlen(subkey
))
1126 if (strlen(subkey
) == strlen(token
))
1129 subkey
+= strlen(token
);
1131 cglist
= malloc(sizeof(*cglist
));
1135 cgelem
= malloc(sizeof(*cgelem
));
1138 memset(cgelem
, 0, sizeof(*cgelem
));
1140 cgelem
->subsystem
= strdup(subkey
);
1141 cgelem
->value
= strdup(value
);
1143 if (!cgelem
->subsystem
|| !cgelem
->value
)
1146 cglist
->elem
= cgelem
;
1148 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1157 if (cgelem
->subsystem
)
1158 free(cgelem
->subsystem
);
1161 free(cgelem
->value
);
1169 static int config_idmap(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
1171 char *token
= "lxc.id_map";
1173 struct lxc_list
*idmaplist
= NULL
;
1174 struct id_map
*idmap
= NULL
;
1175 unsigned long hostid
, nsid
, range
;
1179 subkey
= strstr(key
, token
);
1184 if (!strlen(subkey
))
1187 idmaplist
= malloc(sizeof(*idmaplist
));
1191 idmap
= malloc(sizeof(*idmap
));
1194 memset(idmap
, 0, sizeof(*idmap
));
1196 idmaplist
->elem
= idmap
;
1198 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1200 ret
= sscanf(value
, "%c %lu %lu %lu", &type
, &nsid
, &hostid
, &range
);
1203 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1205 idmap
->idtype
= ID_TYPE_UID
;
1206 else if (type
== 'g')
1207 idmap
->idtype
= ID_TYPE_GID
;
1210 idmap
->hostid
= hostid
;
1212 idmap
->range
= range
;
1227 static int config_path_item(const char *key
, const char *value
,
1228 struct lxc_conf
*lxc_conf
, char **conf_item
)
1231 if (strlen(value
) >= MAXPATHLEN
) {
1232 ERROR("%s path is too long", value
);
1236 valdup
= strdup(value
);
1238 SYSERROR("failed to duplicate string %s", value
);
1243 *conf_item
= valdup
;
1248 static int config_fstab(const char *key
, const char *value
,
1249 struct lxc_conf
*lxc_conf
)
1251 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->fstab
);
1254 static int config_mount_auto(const char *key
, const char *value
,
1255 struct lxc_conf
*lxc_conf
)
1257 char *autos
, *autoptr
, *sptr
, *token
;
1258 static struct { const char *token
; int mask
; int flag
; } allowed_auto_mounts
[] = {
1259 { "proc", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
1260 { "proc:mixed", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
1261 { "proc:rw", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_RW
},
1262 { "sys", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
1263 { "sys:ro", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
1264 { "sys:rw", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RW
},
1265 { "cgroup", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
1266 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
1267 { "cgroup:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RO
},
1268 { "cgroup:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RW
},
1269 { "cgroup-full", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
1270 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
1271 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RO
},
1272 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RW
},
1273 /* NB: For adding anything that ist just a single on/off, but has
1274 * no options: keep mask and flag identical and just define the
1275 * enum value as an unused bit so far
1285 autos
= strdup(value
);
1287 SYSERROR("failed to dup '%s'", value
);
1291 for (autoptr
= autos
; ; autoptr
= NULL
) {
1292 token
= strtok_r(autoptr
, " \t", &sptr
);
1298 for (i
= 0; allowed_auto_mounts
[i
].token
; i
++) {
1299 if (!strcmp(allowed_auto_mounts
[i
].token
, token
))
1303 if (!allowed_auto_mounts
[i
].token
) {
1304 ERROR("Invalid filesystem to automount: %s", token
);
1308 lxc_conf
->auto_mounts
&= ~allowed_auto_mounts
[i
].mask
;
1309 lxc_conf
->auto_mounts
|= allowed_auto_mounts
[i
].flag
;
1317 static int config_mount(const char *key
, const char *value
,
1318 struct lxc_conf
*lxc_conf
)
1320 char *fstab_token
= "lxc.mount";
1321 char *token
= "lxc.mount.entry";
1322 char *auto_token
= "lxc.mount.auto";
1325 struct lxc_list
*mntlist
;
1327 subkey
= strstr(key
, token
);
1330 subkey
= strstr(key
, auto_token
);
1333 subkey
= strstr(key
, fstab_token
);
1338 return config_fstab(key
, value
, lxc_conf
);
1341 return config_mount_auto(key
, value
, lxc_conf
);
1344 if (!strlen(subkey
))
1347 mntlist
= malloc(sizeof(*mntlist
));
1351 mntelem
= strdup(value
);
1356 mntlist
->elem
= mntelem
;
1358 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1363 static int config_cap_keep(const char *key
, const char *value
,
1364 struct lxc_conf
*lxc_conf
)
1366 char *keepcaps
, *keepptr
, *sptr
, *token
;
1367 struct lxc_list
*keeplist
;
1373 keepcaps
= strdup(value
);
1375 SYSERROR("failed to dup '%s'", value
);
1379 /* in case several capability keep is specified in a single line
1380 * split these caps in a single element for the list */
1381 for (keepptr
= keepcaps
;;keepptr
= NULL
) {
1382 token
= strtok_r(keepptr
, " \t", &sptr
);
1388 keeplist
= malloc(sizeof(*keeplist
));
1390 SYSERROR("failed to allocate keepcap list");
1394 keeplist
->elem
= strdup(token
);
1395 if (!keeplist
->elem
) {
1396 SYSERROR("failed to dup '%s'", token
);
1401 lxc_list_add_tail(&lxc_conf
->keepcaps
, keeplist
);
1409 static int config_cap_drop(const char *key
, const char *value
,
1410 struct lxc_conf
*lxc_conf
)
1412 char *dropcaps
, *dropptr
, *sptr
, *token
;
1413 struct lxc_list
*droplist
;
1419 dropcaps
= strdup(value
);
1421 SYSERROR("failed to dup '%s'", value
);
1425 /* in case several capability drop is specified in a single line
1426 * split these caps in a single element for the list */
1427 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
1428 token
= strtok_r(dropptr
, " \t", &sptr
);
1434 droplist
= malloc(sizeof(*droplist
));
1436 SYSERROR("failed to allocate drop list");
1440 droplist
->elem
= strdup(token
);
1441 if (!droplist
->elem
) {
1442 SYSERROR("failed to dup '%s'", token
);
1447 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1455 static int config_console(const char *key
, const char *value
,
1456 struct lxc_conf
*lxc_conf
)
1460 path
= strdup(value
);
1462 SYSERROR("failed to strdup '%s': %m", value
);
1466 if (lxc_conf
->console
.path
)
1467 free(lxc_conf
->console
.path
);
1468 lxc_conf
->console
.path
= path
;
1473 static int config_includefile(const char *key
, const char *value
,
1474 struct lxc_conf
*lxc_conf
)
1476 return lxc_config_read(value
, lxc_conf
);
1479 static int config_rootfs(const char *key
, const char *value
,
1480 struct lxc_conf
*lxc_conf
)
1482 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.path
);
1485 static int config_rootfs_mount(const char *key
, const char *value
,
1486 struct lxc_conf
*lxc_conf
)
1488 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.mount
);
1491 static int config_pivotdir(const char *key
, const char *value
,
1492 struct lxc_conf
*lxc_conf
)
1494 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.pivot
);
1497 static int config_utsname(const char *key
, const char *value
,
1498 struct lxc_conf
*lxc_conf
)
1500 struct utsname
*utsname
;
1502 utsname
= malloc(sizeof(*utsname
));
1504 SYSERROR("failed to allocate memory");
1508 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1509 ERROR("node name '%s' is too long",
1515 strcpy(utsname
->nodename
, value
);
1516 if (lxc_conf
->utsname
)
1517 free(lxc_conf
->utsname
);
1518 lxc_conf
->utsname
= utsname
;
1523 static int parse_line(char *buffer
, void *data
)
1525 struct lxc_config_t
*config
;
1532 if (lxc_is_line_empty(buffer
))
1535 /* we have to dup the buffer otherwise, at the re-exec for
1536 * reboot we modified the original string on the stack by
1537 * replacing '=' by '\0' below
1539 linep
= line
= strdup(buffer
);
1541 SYSERROR("failed to allocate memory for '%s'", buffer
);
1545 line
+= lxc_char_left_gc(line
, strlen(line
));
1547 /* martian option - ignoring it, the commented lines beginning by '#'
1550 if (strncmp(line
, "lxc.", 4))
1555 dot
= strstr(line
, "=");
1557 ERROR("invalid configuration line: %s", line
);
1565 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1567 value
+= lxc_char_left_gc(value
, strlen(value
));
1568 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1570 config
= lxc_getconfig(key
);
1572 ERROR("unknown key %s", key
);
1576 ret
= config
->cb(key
, value
, data
);
1583 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1585 return parse_line(buffer
, conf
);
1588 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1590 if( access(file
, R_OK
) == -1 ) {
1593 /* Catch only the top level config file name in the structure */
1594 if( ! conf
->rcfile
) {
1595 conf
->rcfile
= strdup( file
);
1597 return lxc_file_for_each_line(file
, parse_line
, conf
);
1600 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1602 struct lxc_list
*dent
;
1604 dent
= malloc(sizeof(struct lxc_list
));
1609 lxc_list_add_tail(defines
, dent
);
1613 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1615 struct lxc_list
*it
,*next
;
1618 lxc_list_for_each(it
, defines
) {
1619 ret
= lxc_config_readline(it
->elem
, conf
);
1624 lxc_list_for_each_safe(it
, defines
, next
) {
1632 signed long lxc_config_parse_arch(const char *arch
)
1634 #if HAVE_SYS_PERSONALITY_H
1639 { "x86", PER_LINUX32
},
1640 { "i686", PER_LINUX32
},
1641 { "x86_64", PER_LINUX
},
1642 { "amd64", PER_LINUX
},
1644 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1648 for (i
= 0; i
< len
; i
++) {
1649 if (!strcmp(pername
[i
].name
, arch
))
1650 return pername
[i
].per
;
1657 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
1662 memset(retv
, 0, inlen
);
1663 return snprintf(retv
, inlen
, "%d", v
);
1666 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
1673 memset(retv
, 0, inlen
);
1675 #if HAVE_SYS_PERSONALITY_H
1678 switch(c
->personality
) {
1679 case PER_LINUX32
: strprint(retv
, inlen
, "x86"); break;
1680 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
1689 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1690 * then just the value(s) will be printed. Since there still could be
1691 * more than one, it is newline-separated.
1692 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1693 * already have newlines?)
1694 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1695 * in 'lxc.cgroup.subsystem.key = value' format.
1697 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
1700 int fulllen
= 0, len
;
1702 struct lxc_list
*it
;
1707 memset(retv
, 0, inlen
);
1709 if (strcmp(key
, "all") == 0)
1712 lxc_list_for_each(it
, &c
->cgroup
) {
1713 struct lxc_cgroup
*cg
= it
->elem
;
1715 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1716 } else if (strcmp(cg
->subsystem
, key
) == 0) {
1717 strprint(retv
, inlen
, "%s\n", cg
->value
);
1723 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
1727 int len
, fulllen
= 0, found
= -1;
1728 struct lxc_list
*it
;
1731 /* "lxc.hook.mount" */
1732 subkey
= index(key
, '.');
1733 if (subkey
) subkey
= index(subkey
+1, '.');
1739 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1740 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
1751 memset(retv
, 0, inlen
);
1753 lxc_list_for_each(it
, &c
->hooks
[found
]) {
1754 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1759 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
1761 int len
, fulllen
= 0;
1762 struct lxc_list
*it
;
1767 memset(retv
, 0, inlen
);
1769 lxc_list_for_each(it
, &c
->caps
) {
1770 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1775 static int lxc_get_item_cap_keep(struct lxc_conf
*c
, char *retv
, int inlen
)
1777 int len
, fulllen
= 0;
1778 struct lxc_list
*it
;
1783 memset(retv
, 0, inlen
);
1785 lxc_list_for_each(it
, &c
->keepcaps
) {
1786 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1791 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
1793 int len
, fulllen
= 0;
1794 struct lxc_list
*it
;
1799 memset(retv
, 0, inlen
);
1801 lxc_list_for_each(it
, &c
->mount_list
) {
1802 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1808 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1809 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1810 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1811 * of an address. ipv4 and ipv6 return lists (newline-separated).
1812 * things like veth.pair return '' if invalid (i.e. if called for vlan
1815 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
1819 int len
, fulllen
= 0;
1820 struct lxc_netdev
*netdev
;
1825 memset(retv
, 0, inlen
);
1827 p1
= index(key
, '.');
1828 if (!p1
|| *(p1
+1) == '\0') return -1;
1831 netdev
= get_netdev_from_key(key
, &c
->network
);
1834 if (strcmp(p1
, "name") == 0) {
1836 strprint(retv
, inlen
, "%s", netdev
->name
);
1837 } else if (strcmp(p1
, "type") == 0) {
1838 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
1839 } else if (strcmp(p1
, "link") == 0) {
1841 strprint(retv
, inlen
, "%s", netdev
->link
);
1842 } else if (strcmp(p1
, "flags") == 0) {
1843 if (netdev
->flags
& IFF_UP
)
1844 strprint(retv
, inlen
, "up");
1845 } else if (strcmp(p1
, "upscript") == 0) {
1846 if (netdev
->upscript
)
1847 strprint(retv
, inlen
, "%s", netdev
->upscript
);
1848 } else if (strcmp(p1
, "hwaddr") == 0) {
1850 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
1851 } else if (strcmp(p1
, "mtu") == 0) {
1853 strprint(retv
, inlen
, "%s", netdev
->mtu
);
1854 } else if (strcmp(p1
, "macvlan.mode") == 0) {
1855 if (netdev
->type
== LXC_NET_MACVLAN
) {
1857 switch (netdev
->priv
.macvlan_attr
.mode
) {
1858 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1859 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1860 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1861 default: mode
= "(invalid)"; break;
1863 strprint(retv
, inlen
, "%s", mode
);
1865 } else if (strcmp(p1
, "veth.pair") == 0) {
1866 if (netdev
->type
== LXC_NET_VETH
) {
1867 strprint(retv
, inlen
, "%s",
1868 netdev
->priv
.veth_attr
.pair
?
1869 netdev
->priv
.veth_attr
.pair
:
1870 netdev
->priv
.veth_attr
.veth1
);
1872 } else if (strcmp(p1
, "vlan") == 0) {
1873 if (netdev
->type
== LXC_NET_VLAN
) {
1874 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
1876 } else if (strcmp(p1
, "ipv4_gateway") == 0) {
1877 if (netdev
->ipv4_gateway_auto
) {
1878 strprint(retv
, inlen
, "auto");
1879 } else if (netdev
->ipv4_gateway
) {
1880 char buf
[INET_ADDRSTRLEN
];
1881 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
1882 strprint(retv
, inlen
, "%s", buf
);
1884 } else if (strcmp(p1
, "ipv4") == 0) {
1885 struct lxc_list
*it2
;
1886 lxc_list_for_each(it2
, &netdev
->ipv4
) {
1887 struct lxc_inetdev
*i
= it2
->elem
;
1888 char buf
[INET_ADDRSTRLEN
];
1889 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1890 strprint(retv
, inlen
, "%s\n", buf
);
1892 } else if (strcmp(p1
, "ipv6_gateway") == 0) {
1893 if (netdev
->ipv6_gateway_auto
) {
1894 strprint(retv
, inlen
, "auto");
1895 } else if (netdev
->ipv6_gateway
) {
1896 char buf
[INET_ADDRSTRLEN
];
1897 inet_ntop(AF_INET
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
1898 strprint(retv
, inlen
, "%s", buf
);
1900 } else if (strcmp(p1
, "ipv6") == 0) {
1901 struct lxc_list
*it2
;
1902 lxc_list_for_each(it2
, &netdev
->ipv6
) {
1903 struct lxc_inetdev
*i
= it2
->elem
;
1904 char buf
[INET_ADDRSTRLEN
];
1905 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
1906 strprint(retv
, inlen
, "%s\n", buf
);
1912 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
1914 int len
, fulllen
= 0;
1915 struct lxc_list
*it
;
1920 memset(retv
, 0, inlen
);
1922 lxc_list_for_each(it
, &c
->network
) {
1923 struct lxc_netdev
*n
= it
->elem
;
1924 const char *t
= lxc_net_type_to_str(n
->type
);
1925 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
1930 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
1933 const char *v
= NULL
;
1935 if (strcmp(key
, "lxc.mount.entry") == 0)
1936 return lxc_get_mount_entries(c
, retv
, inlen
);
1937 else if (strcmp(key
, "lxc.mount") == 0)
1939 else if (strcmp(key
, "lxc.tty") == 0)
1940 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
1941 else if (strcmp(key
, "lxc.pts") == 0)
1942 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
1943 else if (strcmp(key
, "lxc.devttydir") == 0)
1945 else if (strcmp(key
, "lxc.arch") == 0)
1946 return lxc_get_arch_entry(c
, retv
, inlen
);
1947 else if (strcmp(key
, "lxc.aa_profile") == 0)
1948 v
= c
->lsm_aa_profile
;
1949 else if (strcmp(key
, "lxc.se_context") == 0)
1950 v
= c
->lsm_se_context
;
1951 else if (strcmp(key
, "lxc.logfile") == 0)
1952 v
= lxc_log_get_file();
1953 else if (strcmp(key
, "lxc.loglevel") == 0)
1954 v
= lxc_log_priority_to_string(lxc_log_get_level());
1955 else if (strcmp(key
, "lxc.cgroup") == 0) // all cgroup info
1956 return lxc_get_cgroup_entry(c
, retv
, inlen
, "all");
1957 else if (strncmp(key
, "lxc.cgroup.", 11) == 0) // specific cgroup info
1958 return lxc_get_cgroup_entry(c
, retv
, inlen
, key
+ 11);
1959 else if (strcmp(key
, "lxc.utsname") == 0)
1960 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
1961 else if (strcmp(key
, "lxc.console") == 0)
1962 v
= c
->console
.path
;
1963 else if (strcmp(key
, "lxc.rootfs.mount") == 0)
1964 v
= c
->rootfs
.mount
;
1965 else if (strcmp(key
, "lxc.rootfs") == 0)
1967 else if (strcmp(key
, "lxc.pivotdir") == 0)
1968 v
= c
->rootfs
.pivot
;
1969 else if (strcmp(key
, "lxc.cap.drop") == 0)
1970 return lxc_get_item_cap_drop(c
, retv
, inlen
);
1971 else if (strcmp(key
, "lxc.cap.keep") == 0)
1972 return lxc_get_item_cap_keep(c
, retv
, inlen
);
1973 else if (strncmp(key
, "lxc.hook", 8) == 0)
1974 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
1975 else if (strcmp(key
, "lxc.network") == 0)
1976 return lxc_get_item_network(c
, retv
, inlen
);
1977 else if (strncmp(key
, "lxc.network.", 12) == 0)
1978 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
1983 if (retv
&& inlen
>= strlen(v
) + 1)
1984 strncpy(retv
, v
, strlen(v
)+1);
1988 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
1990 if (strcmp(key
, "lxc.network") == 0)
1991 return lxc_clear_config_network(c
);
1992 else if (strncmp(key
, "lxc.network.", 12) == 0)
1993 return lxc_clear_nic(c
, key
+ 12);
1994 else if (strcmp(key
, "lxc.cap.drop") == 0)
1995 return lxc_clear_config_caps(c
);
1996 else if (strcmp(key
, "lxc.cap.keep") == 0)
1997 return lxc_clear_config_keepcaps(c
);
1998 else if (strncmp(key
, "lxc.cgroup", 10) == 0)
1999 return lxc_clear_cgroups(c
, key
);
2000 else if (strcmp(key
, "lxc.mount.entries") == 0)
2001 return lxc_clear_mount_entries(c
);
2002 else if (strncmp(key
, "lxc.hook", 8) == 0)
2003 return lxc_clear_hooks(c
, key
);
2009 * writing out a confile.
2011 void write_config(FILE *fout
, struct lxc_conf
*c
)
2013 struct lxc_list
*it
;
2017 fprintf(fout
, "lxc.mount = %s\n", c
->fstab
);
2018 lxc_list_for_each(it
, &c
->mount_list
) {
2019 fprintf(fout
, "lxc.mount.entry = %s\n", (char *)it
->elem
);
2021 if (c
->auto_mounts
& LXC_AUTO_ALL_MASK
) {
2022 fprintf(fout
, "lxc.mount.auto =");
2023 switch (c
->auto_mounts
& LXC_AUTO_PROC_MASK
) {
2024 case LXC_AUTO_PROC_MIXED
: fprintf(fout
, " proc:mixed"); break;
2025 case LXC_AUTO_PROC_RW
: fprintf(fout
, " proc:rw"); break;
2028 switch (c
->auto_mounts
& LXC_AUTO_SYS_MASK
) {
2029 case LXC_AUTO_SYS_RO
: fprintf(fout
, " sys:ro"); break;
2030 case LXC_AUTO_SYS_RW
: fprintf(fout
, " sys:rw"); break;
2033 switch (c
->auto_mounts
& LXC_AUTO_CGROUP_MASK
) {
2034 case LXC_AUTO_CGROUP_MIXED
: fprintf(fout
, " cgroup:mixed"); break;
2035 case LXC_AUTO_CGROUP_RO
: fprintf(fout
, " cgroup:ro"); break;
2036 case LXC_AUTO_CGROUP_RW
: fprintf(fout
, " cgroup:rw"); break;
2037 case LXC_AUTO_CGROUP_FULL_MIXED
: fprintf(fout
, " cgroup-full:mixed"); break;
2038 case LXC_AUTO_CGROUP_FULL_RO
: fprintf(fout
, " cgroup-full:ro"); break;
2039 case LXC_AUTO_CGROUP_FULL_RW
: fprintf(fout
, " cgroup-full:rw"); break;
2042 fprintf(fout
, "\n");
2045 fprintf(fout
, "lxc.tty = %d\n", c
->tty
);
2047 fprintf(fout
, "lxc.pts = %d\n", c
->pts
);
2049 fprintf(fout
, "lxc.devttydir = %s\n", c
->ttydir
);
2050 #if HAVE_SYS_PERSONALITY_H
2051 switch(c
->personality
) {
2052 case PER_LINUX32
: fprintf(fout
, "lxc.arch = x86\n"); break;
2053 case PER_LINUX
: fprintf(fout
, "lxc.arch = x86_64\n"); break;
2057 if (c
->lsm_aa_profile
)
2058 fprintf(fout
, "lxc.aa_profile = %s\n", c
->lsm_aa_profile
);
2059 if (c
->lsm_se_context
)
2060 fprintf(fout
, "lxc.se_context = %s\n", c
->lsm_se_context
);
2061 if (c
->loglevel
!= LXC_LOG_PRIORITY_NOTSET
)
2062 fprintf(fout
, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c
->loglevel
));
2064 fprintf(fout
, "lxc.logfile = %s\n", c
->logfile
);
2065 lxc_list_for_each(it
, &c
->cgroup
) {
2066 struct lxc_cgroup
*cg
= it
->elem
;
2067 fprintf(fout
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
2070 fprintf(fout
, "lxc.utsname = %s\n", c
->utsname
->nodename
);
2071 lxc_list_for_each(it
, &c
->network
) {
2072 struct lxc_netdev
*n
= it
->elem
;
2073 const char *t
= lxc_net_type_to_str(n
->type
);
2074 struct lxc_list
*it2
;
2075 fprintf(fout
, "lxc.network.type = %s\n", t
? t
: "(invalid)");
2076 if (n
->flags
& IFF_UP
)
2077 fprintf(fout
, "lxc.network.flags = up\n");
2079 fprintf(fout
, "lxc.network.link = %s\n", n
->link
);
2081 fprintf(fout
, "lxc.network.name = %s\n", n
->name
);
2082 if (n
->type
== LXC_NET_MACVLAN
) {
2084 switch (n
->priv
.macvlan_attr
.mode
) {
2085 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
2086 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
2087 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
2088 default: mode
= "(invalid)"; break;
2090 fprintf(fout
, "lxc.network.macvlan.mode = %s\n", mode
);
2091 } else if (n
->type
== LXC_NET_VETH
) {
2092 if (n
->priv
.veth_attr
.pair
)
2093 fprintf(fout
, "lxc.network.veth.pair = %s\n",
2094 n
->priv
.veth_attr
.pair
);
2095 } else if (n
->type
== LXC_NET_VLAN
) {
2096 fprintf(fout
, "lxc.network.vlan.id = %d\n", n
->priv
.vlan_attr
.vid
);
2099 fprintf(fout
, "lxc.network.script.up = %s\n", n
->upscript
);
2101 fprintf(fout
, "lxc.network.hwaddr = %s\n", n
->hwaddr
);
2103 fprintf(fout
, "lxc.network.mtu = %s\n", n
->mtu
);
2104 if (n
->ipv4_gateway_auto
)
2105 fprintf(fout
, "lxc.network.ipv4.gateway = auto\n");
2106 else if (n
->ipv4_gateway
) {
2107 char buf
[INET_ADDRSTRLEN
];
2108 inet_ntop(AF_INET
, n
->ipv4_gateway
, buf
, sizeof(buf
));
2109 fprintf(fout
, "lxc.network.ipv4.gateway = %s\n", buf
);
2111 lxc_list_for_each(it2
, &n
->ipv4
) {
2112 struct lxc_inetdev
*i
= it2
->elem
;
2113 char buf
[INET_ADDRSTRLEN
];
2114 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
2115 fprintf(fout
, "lxc.network.ipv4 = %s\n", buf
);
2117 if (n
->ipv6_gateway_auto
)
2118 fprintf(fout
, "lxc.network.ipv6.gateway = auto\n");
2119 else if (n
->ipv6_gateway
) {
2120 char buf
[INET6_ADDRSTRLEN
];
2121 inet_ntop(AF_INET6
, n
->ipv6_gateway
, buf
, sizeof(buf
));
2122 fprintf(fout
, "lxc.network.ipv6.gateway = %s\n", buf
);
2124 lxc_list_for_each(it2
, &n
->ipv6
) {
2125 struct lxc_inet6dev
*i
= it2
->elem
;
2126 char buf
[INET6_ADDRSTRLEN
];
2127 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
2128 fprintf(fout
, "lxc.network.ipv6 = %s\n", buf
);
2131 lxc_list_for_each(it
, &c
->caps
)
2132 fprintf(fout
, "lxc.cap.drop = %s\n", (char *)it
->elem
);
2133 lxc_list_for_each(it
, &c
->keepcaps
)
2134 fprintf(fout
, "lxc.cap.keep = %s\n", (char *)it
->elem
);
2135 lxc_list_for_each(it
, &c
->id_map
) {
2136 struct id_map
*idmap
= it
->elem
;
2137 fprintf(fout
, "lxc.id_map = %c %lu %lu %lu\n",
2138 idmap
->idtype
== ID_TYPE_UID
? 'u' : 'g', idmap
->nsid
,
2139 idmap
->hostid
, idmap
->range
);
2141 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
2142 lxc_list_for_each(it
, &c
->hooks
[i
])
2143 fprintf(fout
, "lxc.hook.%s = %s\n",
2144 lxchook_names
[i
], (char *)it
->elem
);
2146 if (c
->console
.path
)
2147 fprintf(fout
, "lxc.console = %s\n", c
->console
.path
);
2149 fprintf(fout
, "lxc.rootfs = %s\n", c
->rootfs
.path
);
2150 if (c
->rootfs
.mount
&& strcmp(c
->rootfs
.mount
, LXCROOTFSMOUNT
) != 0)
2151 fprintf(fout
, "lxc.rootfs.mount = %s\n", c
->rootfs
.mount
);
2152 if (c
->rootfs
.pivot
)
2153 fprintf(fout
, "lxc.pivotdir = %s\n", c
->rootfs
.pivot
);