2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/utsname.h>
34 #include <sys/personality.h>
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
47 lxc_log_define(lxc_confile
, lxc
);
49 static int config_personality(const char *, char *, struct lxc_conf
*);
50 static int config_pts(const char *, char *, struct lxc_conf
*);
51 static int config_tty(const char *, char *, struct lxc_conf
*);
52 static int config_ttydir(const char *, char *, struct lxc_conf
*);
54 static int config_aa_profile(const char *, char *, struct lxc_conf
*);
56 static int config_cgroup(const char *, char *, struct lxc_conf
*);
57 static int config_mount(const char *, char *, struct lxc_conf
*);
58 static int config_rootfs(const char *, char *, struct lxc_conf
*);
59 static int config_rootfs_mount(const char *, char *, struct lxc_conf
*);
60 static int config_pivotdir(const char *, char *, struct lxc_conf
*);
61 static int config_utsname(const char *, char *, struct lxc_conf
*);
62 static int config_hook(const char *key
, char *value
, struct lxc_conf
*lxc_conf
);
63 static int config_network_type(const char *, char *, struct lxc_conf
*);
64 static int config_network_flags(const char *, char *, struct lxc_conf
*);
65 static int config_network_link(const char *, char *, struct lxc_conf
*);
66 static int config_network_name(const char *, char *, struct lxc_conf
*);
67 static int config_network_veth_pair(const char *, char *, struct lxc_conf
*);
68 static int config_network_macvlan_mode(const char *, char *, struct lxc_conf
*);
69 static int config_network_hwaddr(const char *, char *, struct lxc_conf
*);
70 static int config_network_vlan_id(const char *, char *, struct lxc_conf
*);
71 static int config_network_mtu(const char *, char *, struct lxc_conf
*);
72 static int config_network_ipv4(const char *, char *, struct lxc_conf
*);
73 static int config_network_ipv4_gateway(const char *, char *, struct lxc_conf
*);
74 static int config_network_script(const char *, char *, struct lxc_conf
*);
75 static int config_network_ipv6(const char *, char *, struct lxc_conf
*);
76 static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf
*);
77 static int config_cap_drop(const char *, char *, struct lxc_conf
*);
78 static int config_console(const char *, char *, struct lxc_conf
*);
79 static int config_seccomp(const char *, char *, struct lxc_conf
*);
80 static int config_includefile(const char *, char *, struct lxc_conf
*);
81 static int config_network_nic(const char *, char *, struct lxc_conf
*);
82 static int config_autodev(const char *, char *, struct lxc_conf
*);
84 static struct lxc_config_t config
[] = {
86 { "lxc.arch", config_personality
},
87 { "lxc.pts", config_pts
},
88 { "lxc.tty", config_tty
},
89 { "lxc.devttydir", config_ttydir
},
91 { "lxc.aa_profile", config_aa_profile
},
93 { "lxc.cgroup", config_cgroup
},
94 { "lxc.mount", config_mount
},
95 { "lxc.rootfs.mount", config_rootfs_mount
},
96 { "lxc.rootfs", config_rootfs
},
97 { "lxc.pivotdir", config_pivotdir
},
98 { "lxc.utsname", config_utsname
},
99 { "lxc.hook.pre-start", config_hook
},
100 { "lxc.hook.pre-mount", config_hook
},
101 { "lxc.hook.mount", config_hook
},
102 { "lxc.hook.start", config_hook
},
103 { "lxc.hook.post-stop", config_hook
},
104 { "lxc.network.type", config_network_type
},
105 { "lxc.network.flags", config_network_flags
},
106 { "lxc.network.link", config_network_link
},
107 { "lxc.network.name", config_network_name
},
108 { "lxc.network.macvlan.mode", config_network_macvlan_mode
},
109 { "lxc.network.veth.pair", config_network_veth_pair
},
110 { "lxc.network.script.up", config_network_script
},
111 { "lxc.network.script.down", config_network_script
},
112 { "lxc.network.hwaddr", config_network_hwaddr
},
113 { "lxc.network.mtu", config_network_mtu
},
114 { "lxc.network.vlan.id", config_network_vlan_id
},
115 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway
},
116 { "lxc.network.ipv4", config_network_ipv4
},
117 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway
},
118 { "lxc.network.ipv6", config_network_ipv6
},
119 /* config_network_nic must come after all other 'lxc.network.*' entries */
120 { "lxc.network.", config_network_nic
},
121 { "lxc.cap.drop", config_cap_drop
},
122 { "lxc.console", config_console
},
123 { "lxc.seccomp", config_seccomp
},
124 { "lxc.include", config_includefile
},
125 { "lxc.autodev", config_autodev
},
128 static const size_t config_size
= sizeof(config
)/sizeof(struct lxc_config_t
);
130 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
134 for (i
= 0; i
< config_size
; i
++)
135 if (!strncmp(config
[i
].name
, key
,
136 strlen(config
[i
].name
)))
141 #define strprint(str, inlen, ...) \
143 len = snprintf(str, inlen, ##__VA_ARGS__); \
144 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
147 if (str) str += len; \
149 if (inlen < 0) inlen = 0; \
153 int lxc_listconfigs(char *retv
, int inlen
)
155 int i
, fulllen
= 0, len
;
160 memset(retv
, 0, inlen
);
161 for (i
= 0; i
< config_size
; i
++) {
162 char *s
= config
[i
].name
;
163 if (s
[strlen(s
)-1] == '.')
165 strprint(retv
, inlen
, "%s\n", s
);
171 * config entry is something like "lxc.network.0.ipv4"
172 * the key 'lxc.network.' was found. So we make sure next
173 * comes an integer, find the right callback (by rewriting
174 * the key), and call it.
176 static int config_network_nic(const char *key
, char *value
,
177 struct lxc_conf
*lxc_conf
)
179 char *copy
= strdup(key
), *p
;
181 struct lxc_config_t
*config
;
184 SYSERROR("failed to allocate memory");
188 * ok we know that to get here we've got "lxc.network."
189 * and it isn't any of the other network entries. So
190 * after the second . should come an integer (# of defined
191 * nic) followed by a valid entry.
193 if (*(key
+12) < '0' || *(key
+12) > '9')
195 p
= index(key
+12, '.');
198 strcpy(copy
+12, p
+1);
199 config
= lxc_getconfig(copy
);
201 ERROR("unknown key %s", key
);
204 ret
= config
->cb(key
, value
, lxc_conf
);
211 static int config_network_type(const char *key
, char *value
,
212 struct lxc_conf
*lxc_conf
)
214 struct lxc_list
*network
= &lxc_conf
->network
;
215 struct lxc_netdev
*netdev
;
216 struct lxc_list
*list
;
218 netdev
= malloc(sizeof(*netdev
));
220 SYSERROR("failed to allocate memory");
224 memset(netdev
, 0, sizeof(*netdev
));
225 lxc_list_init(&netdev
->ipv4
);
226 lxc_list_init(&netdev
->ipv6
);
228 list
= malloc(sizeof(*list
));
230 SYSERROR("failed to allocate memory");
237 lxc_list_add_tail(network
, list
);
239 if (!strcmp(value
, "veth"))
240 netdev
->type
= LXC_NET_VETH
;
241 else if (!strcmp(value
, "macvlan"))
242 netdev
->type
= LXC_NET_MACVLAN
;
243 else if (!strcmp(value
, "vlan"))
244 netdev
->type
= LXC_NET_VLAN
;
245 else if (!strcmp(value
, "phys"))
246 netdev
->type
= LXC_NET_PHYS
;
247 else if (!strcmp(value
, "empty"))
248 netdev
->type
= LXC_NET_EMPTY
;
250 ERROR("invalid network type %s", value
);
256 static int config_ip_prefix(struct in_addr
*addr
)
258 if (IN_CLASSA(addr
->s_addr
))
259 return 32 - IN_CLASSA_NSHIFT
;
260 if (IN_CLASSB(addr
->s_addr
))
261 return 32 - IN_CLASSB_NSHIFT
;
262 if (IN_CLASSC(addr
->s_addr
))
263 return 32 - IN_CLASSC_NSHIFT
;
269 * if you have p="lxc.network.0.link", pass it p+12
270 * to get back '0' (the index of the nic)
272 static int get_network_netdev_idx(const char *key
)
276 if (*key
< '0' || *key
> '9')
278 ret
= sscanf(key
, "%d", &idx
);
285 * if you have p="lxc.network.0", pass this p+12 and it will return
286 * the netdev of the first configured nic
288 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
289 struct lxc_list
*network
)
291 int i
= 0, idx
= get_network_netdev_idx(key
);
292 struct lxc_netdev
*netdev
= NULL
;
296 lxc_list_for_each(it
, network
) {
305 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, char *key
, char *retv
, int inlen
)
307 struct lxc_netdev
*netdev
;
308 int fulllen
= 0, len
;
310 netdev
= get_netdev_from_key(key
+12, &c
->network
);
317 memset(retv
, 0, inlen
);
319 strprint(retv
, inlen
, "script.up\n");
320 if (netdev
->type
!= LXC_NET_EMPTY
) {
321 strprint(retv
, inlen
, "flags\n");
322 strprint(retv
, inlen
, "link\n");
323 strprint(retv
, inlen
, "name\n");
324 strprint(retv
, inlen
, "hwaddr\n");
325 strprint(retv
, inlen
, "mtu\n");
326 strprint(retv
, inlen
, "ipv6\n");
327 strprint(retv
, inlen
, "ipv6_gateway\n");
328 strprint(retv
, inlen
, "ipv4\n");
329 strprint(retv
, inlen
, "ipv4_gateway\n");
331 switch(netdev
->type
) {
333 strprint(retv
, inlen
, "veth.pair\n");
335 case LXC_NET_MACVLAN
:
336 strprint(retv
, inlen
, "macvlan.mode\n");
339 strprint(retv
, inlen
, "vlan.id\n");
347 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
348 struct lxc_list
*network
)
350 struct lxc_netdev
*netdev
= NULL
;
352 if (lxc_list_empty(network
)) {
353 ERROR("network is not created for '%s' = '%s' option",
358 if (get_network_netdev_idx(key
+12) == -1)
359 netdev
= lxc_list_last_elem(network
);
361 netdev
= get_netdev_from_key(key
+12, network
);
364 ERROR("no network device defined for '%s' = '%s' option",
372 static int network_ifname(char **valuep
, char *value
)
374 if (strlen(value
) >= IFNAMSIZ
) {
375 ERROR("interface name '%s' too long (>%d)\n",
376 value
, IFNAMSIZ
- 1);
380 *valuep
= strdup(value
);
382 ERROR("failed to dup string '%s'", value
);
389 #ifndef MACVLAN_MODE_PRIVATE
390 # define MACVLAN_MODE_PRIVATE 1
393 #ifndef MACVLAN_MODE_VEPA
394 # define MACVLAN_MODE_VEPA 2
397 #ifndef MACVLAN_MODE_BRIDGE
398 # define MACVLAN_MODE_BRIDGE 4
401 static int macvlan_mode(int *valuep
, char *value
)
407 { "private", MACVLAN_MODE_PRIVATE
},
408 { "vepa", MACVLAN_MODE_VEPA
},
409 { "bridge", MACVLAN_MODE_BRIDGE
},
414 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
415 if (strcmp(m
[i
].name
, value
))
425 static int config_network_flags(const char *key
, char *value
,
426 struct lxc_conf
*lxc_conf
)
428 struct lxc_netdev
*netdev
;
430 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
434 netdev
->flags
|= IFF_UP
;
439 static int config_network_link(const char *key
, char *value
,
440 struct lxc_conf
*lxc_conf
)
442 struct lxc_netdev
*netdev
;
444 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
448 return network_ifname(&netdev
->link
, value
);
451 static int config_network_name(const char *key
, char *value
,
452 struct lxc_conf
*lxc_conf
)
454 struct lxc_netdev
*netdev
;
456 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
460 return network_ifname(&netdev
->name
, value
);
463 static int config_network_veth_pair(const char *key
, char *value
,
464 struct lxc_conf
*lxc_conf
)
466 struct lxc_netdev
*netdev
;
468 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
472 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
475 static int config_network_macvlan_mode(const char *key
, char *value
,
476 struct lxc_conf
*lxc_conf
)
478 struct lxc_netdev
*netdev
;
480 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
484 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
487 static int config_network_hwaddr(const char *key
, char *value
,
488 struct lxc_conf
*lxc_conf
)
490 struct lxc_netdev
*netdev
;
493 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
497 hwaddr
= strdup(value
);
499 SYSERROR("failed to dup string '%s'", value
);
504 free(netdev
->hwaddr
);
505 netdev
->hwaddr
= hwaddr
;
509 static int config_network_vlan_id(const char *key
, char *value
,
510 struct lxc_conf
*lxc_conf
)
512 struct lxc_netdev
*netdev
;
514 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
518 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
524 static int config_network_mtu(const char *key
, char *value
,
525 struct lxc_conf
*lxc_conf
)
527 struct lxc_netdev
*netdev
;
530 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
536 SYSERROR("failed to dup string '%s'", value
);
546 static int config_network_ipv4(const char *key
, char *value
,
547 struct lxc_conf
*lxc_conf
)
549 struct lxc_netdev
*netdev
;
550 struct lxc_inetdev
*inetdev
;
551 struct lxc_list
*list
;
552 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
554 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
558 inetdev
= malloc(sizeof(*inetdev
));
560 SYSERROR("failed to allocate ipv4 address");
563 memset(inetdev
, 0, sizeof(*inetdev
));
565 list
= malloc(sizeof(*list
));
567 SYSERROR("failed to allocate memory");
572 list
->elem
= inetdev
;
576 cursor
= strstr(addr
, " ");
582 slash
= strstr(addr
, "/");
589 ERROR("no address specified");
593 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
594 SYSERROR("invalid ipv4 address: %s", value
);
598 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
599 SYSERROR("invalid ipv4 broadcast address: %s", value
);
603 /* no prefix specified, determine it from the network class */
604 inetdev
->prefix
= prefix
? atoi(prefix
) :
605 config_ip_prefix(&inetdev
->addr
);
607 /* if no broadcast address, let compute one from the
611 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
612 inetdev
->bcast
.s_addr
|=
613 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
616 lxc_list_add(&netdev
->ipv4
, list
);
621 static int config_network_ipv4_gateway(const char *key
, char *value
,
622 struct lxc_conf
*lxc_conf
)
624 struct lxc_netdev
*netdev
;
627 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
631 gw
= malloc(sizeof(*gw
));
633 SYSERROR("failed to allocate ipv4 gateway address");
638 ERROR("no ipv4 gateway address specified");
642 if (!strcmp(value
, "auto")) {
643 netdev
->ipv4_gateway
= NULL
;
644 netdev
->ipv4_gateway_auto
= true;
646 if (!inet_pton(AF_INET
, value
, gw
)) {
647 SYSERROR("invalid ipv4 gateway address: %s", value
);
651 netdev
->ipv4_gateway
= gw
;
652 netdev
->ipv4_gateway_auto
= false;
658 static int config_network_ipv6(const char *key
, char *value
,
659 struct lxc_conf
*lxc_conf
)
661 struct lxc_netdev
*netdev
;
662 struct lxc_inet6dev
*inet6dev
;
663 struct lxc_list
*list
;
667 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
671 inet6dev
= malloc(sizeof(*inet6dev
));
673 SYSERROR("failed to allocate ipv6 address");
676 memset(inet6dev
, 0, sizeof(*inet6dev
));
678 list
= malloc(sizeof(*list
));
680 SYSERROR("failed to allocate memory");
685 list
->elem
= inet6dev
;
687 inet6dev
->prefix
= 64;
688 slash
= strstr(value
, "/");
692 inet6dev
->prefix
= atoi(netmask
);
695 if (!inet_pton(AF_INET6
, value
, &inet6dev
->addr
)) {
696 SYSERROR("invalid ipv6 address: %s", value
);
700 lxc_list_add(&netdev
->ipv6
, list
);
705 static int config_network_ipv6_gateway(const char *key
, char *value
,
706 struct lxc_conf
*lxc_conf
)
708 struct lxc_netdev
*netdev
;
711 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
715 gw
= malloc(sizeof(*gw
));
717 SYSERROR("failed to allocate ipv6 gateway address");
722 ERROR("no ipv6 gateway address specified");
726 if (!strcmp(value
, "auto")) {
727 netdev
->ipv6_gateway
= NULL
;
728 netdev
->ipv6_gateway_auto
= true;
730 if (!inet_pton(AF_INET6
, value
, gw
)) {
731 SYSERROR("invalid ipv6 gateway address: %s", value
);
735 netdev
->ipv6_gateway
= gw
;
736 netdev
->ipv6_gateway_auto
= false;
742 static int config_network_script(const char *key
, char *value
,
743 struct lxc_conf
*lxc_conf
)
745 struct lxc_netdev
*netdev
;
747 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
751 char *copy
= strdup(value
);
753 SYSERROR("failed to dup string '%s'", value
);
756 if (strstr(key
, "script.up") != NULL
) {
757 netdev
->upscript
= copy
;
760 if (strcmp(key
, "lxc.network.script.down") == 0) {
761 netdev
->downscript
= copy
;
764 SYSERROR("Unknown key: %s", key
);
769 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
771 struct lxc_list
*hooklist
;
773 hooklist
= malloc(sizeof(*hooklist
));
778 hooklist
->elem
= hook
;
779 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
783 static int config_seccomp(const char *key
, char *value
,
784 struct lxc_conf
*lxc_conf
)
788 if (lxc_conf
->seccomp
) {
789 ERROR("seccomp already defined");
792 path
= strdup(value
);
794 SYSERROR("failed to strdup '%s': %m", value
);
798 if (lxc_conf
->seccomp
)
799 free(lxc_conf
->seccomp
);
800 lxc_conf
->seccomp
= path
;
805 static int config_hook(const char *key
, char *value
,
806 struct lxc_conf
*lxc_conf
)
808 char *copy
= strdup(value
);
810 SYSERROR("failed to dup string '%s'", value
);
813 if (strcmp(key
, "lxc.hook.pre-start") == 0)
814 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
815 else if (strcmp(key
, "lxc.hook.pre-mount") == 0)
816 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
817 else if (strcmp(key
, "lxc.hook.mount") == 0)
818 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
819 else if (strcmp(key
, "lxc.hook.start") == 0)
820 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
821 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
822 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
823 SYSERROR("Unknown key: %s", key
);
828 static int config_personality(const char *key
, char *value
,
829 struct lxc_conf
*lxc_conf
)
831 signed long personality
= lxc_config_parse_arch(value
);
833 if (personality
>= 0)
834 lxc_conf
->personality
= personality
;
836 WARN("unsupported personality '%s'", value
);
841 static int config_pts(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
843 int maxpts
= atoi(value
);
845 lxc_conf
->pts
= maxpts
;
850 static int config_tty(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
852 int nbtty
= atoi(value
);
854 lxc_conf
->tty
= nbtty
;
859 static int config_ttydir(const char *key
, char *value
,
860 struct lxc_conf
*lxc_conf
)
864 if (!value
|| strlen(value
) == 0)
866 path
= strdup(value
);
868 SYSERROR("failed to strdup '%s': %m", value
);
872 if (lxc_conf
->ttydir
)
873 free(lxc_conf
->ttydir
);
874 lxc_conf
->ttydir
= path
;
880 static int config_aa_profile(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
884 if (!value
|| strlen(value
) == 0)
886 path
= strdup(value
);
888 SYSERROR("failed to strdup '%s': %m", value
);
892 if (lxc_conf
->aa_profile
)
893 free(lxc_conf
->aa_profile
);
894 lxc_conf
->aa_profile
= path
;
900 static int config_autodev(const char *key
, char *value
,
901 struct lxc_conf
*lxc_conf
)
905 lxc_conf
->autodev
= v
;
910 static int config_cgroup(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
912 char *token
= "lxc.cgroup.";
914 struct lxc_list
*cglist
= NULL
;
915 struct lxc_cgroup
*cgelem
= NULL
;
917 subkey
= strstr(key
, token
);
925 if (strlen(subkey
) == strlen(token
))
928 subkey
+= strlen(token
);
930 cglist
= malloc(sizeof(*cglist
));
934 cgelem
= malloc(sizeof(*cgelem
));
937 memset(cgelem
, 0, sizeof(*cgelem
));
939 cgelem
->subsystem
= strdup(subkey
);
940 cgelem
->value
= strdup(value
);
942 if (!cgelem
->subsystem
|| !cgelem
->value
)
945 cglist
->elem
= cgelem
;
947 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
956 if (cgelem
->subsystem
)
957 free(cgelem
->subsystem
);
968 static int config_path_item(const char *key
, const char *value
,
969 struct lxc_conf
*lxc_conf
, char **conf_item
)
972 if (strlen(value
) >= MAXPATHLEN
) {
973 ERROR("%s path is too long", value
);
977 valdup
= strdup(value
);
979 SYSERROR("failed to duplicate string %s", value
);
989 static int config_fstab(const char *key
, const char *value
,
990 struct lxc_conf
*lxc_conf
)
992 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->fstab
);
995 static int config_mount(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
997 char *fstab_token
= "lxc.mount";
998 char *token
= "lxc.mount.entry";
1001 struct lxc_list
*mntlist
;
1003 subkey
= strstr(key
, token
);
1006 subkey
= strstr(key
, fstab_token
);
1011 return config_fstab(key
, value
, lxc_conf
);
1014 if (!strlen(subkey
))
1017 mntlist
= malloc(sizeof(*mntlist
));
1021 mntelem
= strdup(value
);
1024 mntlist
->elem
= mntelem
;
1026 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1031 static int config_cap_drop(const char *key
, char *value
,
1032 struct lxc_conf
*lxc_conf
)
1034 char *dropcaps
, *dropptr
, *sptr
, *token
;
1035 struct lxc_list
*droplist
;
1041 dropcaps
= strdup(value
);
1043 SYSERROR("failed to dup '%s'", value
);
1047 /* in case several capability drop is specified in a single line
1048 * split these caps in a single element for the list */
1049 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
1050 token
= strtok_r(dropptr
, " \t", &sptr
);
1056 droplist
= malloc(sizeof(*droplist
));
1058 SYSERROR("failed to allocate drop list");
1062 droplist
->elem
= strdup(token
);
1063 if (!droplist
->elem
) {
1064 SYSERROR("failed to dup '%s'", token
);
1069 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1077 static int config_console(const char *key
, char *value
,
1078 struct lxc_conf
*lxc_conf
)
1082 path
= strdup(value
);
1084 SYSERROR("failed to strdup '%s': %m", value
);
1088 if (lxc_conf
->console
.path
)
1089 free(lxc_conf
->console
.path
);
1090 lxc_conf
->console
.path
= path
;
1095 static int config_includefile(const char *key
, char *value
,
1096 struct lxc_conf
*lxc_conf
)
1098 return lxc_config_read(value
, lxc_conf
);
1101 static int config_rootfs(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
1103 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.path
);
1106 static int config_rootfs_mount(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
1108 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.mount
);
1111 static int config_pivotdir(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
1113 return config_path_item(key
, value
, lxc_conf
, &lxc_conf
->rootfs
.pivot
);
1116 static int config_utsname(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
1118 struct utsname
*utsname
;
1120 utsname
= malloc(sizeof(*utsname
));
1122 SYSERROR("failed to allocate memory");
1126 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1127 ERROR("node name '%s' is too long",
1132 strcpy(utsname
->nodename
, value
);
1133 if (lxc_conf
->utsname
)
1134 free(lxc_conf
->utsname
);
1135 lxc_conf
->utsname
= utsname
;
1140 static int parse_line(char *buffer
, void *data
)
1142 struct lxc_config_t
*config
;
1149 if (lxc_is_line_empty(buffer
))
1152 /* we have to dup the buffer otherwise, at the re-exec for
1153 * reboot we modified the original string on the stack by
1154 * replacing '=' by '\0' below
1156 linep
= line
= strdup(buffer
);
1158 SYSERROR("failed to allocate memory for '%s'", buffer
);
1162 line
+= lxc_char_left_gc(line
, strlen(line
));
1164 /* martian option - ignoring it, the commented lines beginning by '#'
1167 if (strncmp(line
, "lxc.", 4))
1172 dot
= strstr(line
, "=");
1174 ERROR("invalid configuration line: %s", line
);
1182 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1184 value
+= lxc_char_left_gc(value
, strlen(value
));
1185 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1187 config
= lxc_getconfig(key
);
1189 ERROR("unknown key %s", key
);
1193 ret
= config
->cb(key
, value
, data
);
1200 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1202 return parse_line(buffer
, conf
);
1205 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1207 return lxc_file_for_each_line(file
, parse_line
, conf
);
1210 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1212 struct lxc_list
*dent
;
1214 dent
= malloc(sizeof(struct lxc_list
));
1219 lxc_list_add_tail(defines
, dent
);
1223 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1225 struct lxc_list
*it
,*next
;
1228 lxc_list_for_each(it
, defines
) {
1229 ret
= lxc_config_readline(it
->elem
, conf
);
1234 lxc_list_for_each_safe(it
, defines
, next
) {
1242 signed long lxc_config_parse_arch(const char *arch
)
1248 { "x86", PER_LINUX32
},
1249 { "i686", PER_LINUX32
},
1250 { "x86_64", PER_LINUX
},
1251 { "amd64", PER_LINUX
},
1253 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1257 for (i
= 0; i
< len
; i
++) {
1258 if (!strcmp(pername
[i
].name
, arch
))
1259 return pername
[i
].per
;
1265 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
1270 memset(retv
, 0, inlen
);
1271 return snprintf(retv
, inlen
, "%d", v
);
1274 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
1276 int len
, fulllen
= 0;
1281 memset(retv
, 0, inlen
);
1283 switch(c
->personality
) {
1284 case PER_LINUX32
: strprint(retv
, inlen
, "x86"); break;
1285 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
1293 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1294 * then just the value(s) will be printed. Since there still could be
1295 * more than one, it is newline-separated.
1296 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1297 * already have newlines?)
1298 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1299 * in 'lxc.cgroup.subsystem.key = value' format.
1301 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
, char *key
)
1303 int fulllen
= 0, len
;
1305 struct lxc_list
*it
;
1310 memset(retv
, 0, inlen
);
1312 if (strcmp(key
, "all") == 0)
1315 lxc_list_for_each(it
, &c
->cgroup
) {
1316 struct lxc_cgroup
*cg
= it
->elem
;
1318 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1319 } else if (strcmp(cg
->subsystem
, key
) == 0) {
1320 strprint(retv
, inlen
, "%s\n", cg
->value
);
1326 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
, char *key
)
1329 int len
, fulllen
= 0, found
= -1;
1330 struct lxc_list
*it
;
1333 /* "lxc.hook.mount" */
1334 subkey
= index(key
, '.');
1335 if (subkey
) subkey
= index(subkey
+1, '.');
1341 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1342 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
1353 memset(retv
, 0, inlen
);
1355 lxc_list_for_each(it
, &c
->hooks
[found
]) {
1356 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1361 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
1363 int len
, fulllen
= 0;
1364 struct lxc_list
*it
;
1369 memset(retv
, 0, inlen
);
1371 lxc_list_for_each(it
, &c
->caps
) {
1372 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1377 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
1379 int len
, fulllen
= 0;
1380 struct lxc_list
*it
;
1385 memset(retv
, 0, inlen
);
1387 lxc_list_for_each(it
, &c
->mount_list
) {
1388 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
1394 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1395 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1396 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1397 * of an address. ipv4 and ipv6 return lists (newline-separated).
1398 * things like veth.pair return '' if invalid (i.e. if called for vlan
1401 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
, char *key
)
1404 int len
, fulllen
= 0;
1405 struct lxc_netdev
*netdev
;
1410 memset(retv
, 0, inlen
);
1412 p1
= index(key
, '.');
1413 if (!p1
|| *(p1
+1) == '\0') return -1;
1416 netdev
= get_netdev_from_key(key
, &c
->network
);
1419 if (strcmp(p1
, "name") == 0) {
1421 strprint(retv
, inlen
, "%s", netdev
->name
);
1422 } else if (strcmp(p1
, "type") == 0) {
1423 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
1424 } else if (strcmp(p1
, "link") == 0) {
1426 strprint(retv
, inlen
, "%s", netdev
->link
);
1427 } else if (strcmp(p1
, "flags") == 0) {
1428 if (netdev
->flags
& IFF_UP
)
1429 strprint(retv
, inlen
, "up");
1430 } else if (strcmp(p1
, "upscript") == 0) {
1431 if (netdev
->upscript
)
1432 strprint(retv
, inlen
, "%s", netdev
->upscript
);
1433 } else if (strcmp(p1
, "hwaddr") == 0) {
1435 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
1436 } else if (strcmp(p1
, "mtu") == 0) {
1438 strprint(retv
, inlen
, "%s", netdev
->mtu
);
1439 } else if (strcmp(p1
, "macvlan.mode") == 0) {
1440 if (netdev
->type
== LXC_NET_MACVLAN
) {
1442 switch (netdev
->priv
.macvlan_attr
.mode
) {
1443 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1444 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1445 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1446 default: mode
= "(invalid)"; break;
1448 strprint(retv
, inlen
, "%s", mode
);
1450 } else if (strcmp(p1
, "veth.pair") == 0) {
1451 if (netdev
->type
== LXC_NET_VETH
&& netdev
->priv
.veth_attr
.pair
)
1452 strprint(retv
, inlen
, "%s", netdev
->priv
.veth_attr
.pair
);
1453 } else if (strcmp(p1
, "vlan") == 0) {
1454 if (netdev
->type
== LXC_NET_VLAN
) {
1455 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
1457 } else if (strcmp(p1
, "ipv4_gateway") == 0) {
1458 if (netdev
->ipv4_gateway_auto
) {
1459 strprint(retv
, inlen
, "auto");
1460 } else if (netdev
->ipv4_gateway
) {
1461 char buf
[INET_ADDRSTRLEN
];
1462 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
1463 strprint(retv
, inlen
, "%s", buf
);
1465 } else if (strcmp(p1
, "ipv4") == 0) {
1466 struct lxc_list
*it2
;
1467 lxc_list_for_each(it2
, &netdev
->ipv4
) {
1468 struct lxc_inetdev
*i
= it2
->elem
;
1469 char buf
[INET_ADDRSTRLEN
];
1470 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1471 strprint(retv
, inlen
, "%s\n", buf
);
1473 } else if (strcmp(p1
, "ipv6_gateway") == 0) {
1474 if (netdev
->ipv6_gateway_auto
) {
1475 strprint(retv
, inlen
, "auto");
1476 } else if (netdev
->ipv6_gateway
) {
1477 char buf
[INET_ADDRSTRLEN
];
1478 inet_ntop(AF_INET
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
1479 strprint(retv
, inlen
, "%s", buf
);
1481 } else if (strcmp(p1
, "ipv6") == 0) {
1482 struct lxc_list
*it2
;
1483 lxc_list_for_each(it2
, &netdev
->ipv6
) {
1484 struct lxc_inetdev
*i
= it2
->elem
;
1485 char buf
[INET_ADDRSTRLEN
];
1486 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
1487 strprint(retv
, inlen
, "%s\n", buf
);
1493 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
1495 int len
, fulllen
= 0;
1496 struct lxc_list
*it
;
1501 memset(retv
, 0, inlen
);
1503 lxc_list_for_each(it
, &c
->network
) {
1504 struct lxc_netdev
*n
= it
->elem
;
1505 const char *t
= lxc_net_type_to_str(n
->type
);
1506 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
1511 int lxc_get_config_item(struct lxc_conf
*c
, char *key
, char *retv
, int inlen
)
1515 if (strcmp(key
, "lxc.mount.entry") == 0)
1516 return lxc_get_mount_entries(c
, retv
, inlen
);
1517 else if (strcmp(key
, "lxc.mount") == 0)
1519 else if (strcmp(key
, "lxc.tty") == 0)
1520 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
1521 else if (strcmp(key
, "lxc.pts") == 0)
1522 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
1523 else if (strcmp(key
, "lxc.devttydir") == 0)
1525 else if (strcmp(key
, "lxc.arch") == 0)
1526 return lxc_get_arch_entry(c
, retv
, inlen
);
1528 else if (strcmp(key
, "lxc.aa_profile") == 0)
1531 else if (strcmp(key
, "lxc.cgroup") == 0) // all cgroup info
1532 return lxc_get_cgroup_entry(c
, retv
, inlen
, "all");
1533 else if (strncmp(key
, "lxc.cgroup.", 11) == 0) // specific cgroup info
1534 return lxc_get_cgroup_entry(c
, retv
, inlen
, key
+ 11);
1535 else if (strcmp(key
, "lxc.utsname") == 0)
1536 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
1537 else if (strcmp(key
, "lxc.console") == 0)
1538 v
= c
->console
.path
;
1539 else if (strcmp(key
, "lxc.rootfs.mount") == 0)
1540 v
= c
->rootfs
.mount
;
1541 else if (strcmp(key
, "lxc.rootfs") == 0)
1543 else if (strcmp(key
, "lxc.pivotdir") == 0)
1544 v
= c
->rootfs
.pivot
;
1545 else if (strcmp(key
, "lxc.cap.drop") == 0)
1546 return lxc_get_item_cap_drop(c
, retv
, inlen
);
1547 else if (strncmp(key
, "lxc.hook", 8) == 0)
1548 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
1549 else if (strcmp(key
, "lxc.network") == 0)
1550 return lxc_get_item_network(c
, retv
, inlen
);
1551 else if (strncmp(key
, "lxc.network.", 12) == 0)
1552 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
1557 if (retv
&& inlen
>= strlen(v
) + 1)
1558 strncpy(retv
, v
, strlen(v
)+1);
1562 int lxc_clear_config_item(struct lxc_conf
*c
, char *key
)
1564 if (strcmp(key
, "lxc.network") == 0)
1565 return lxc_clear_config_network(c
);
1566 else if (strncmp(key
, "lxc.network.", 12) == 0)
1567 return lxc_clear_nic(c
, key
+ 12);
1568 else if (strcmp(key
, "lxc.cap.drop") == 0)
1569 return lxc_clear_config_caps(c
);
1570 else if (strncmp(key
, "lxc.cgroup", 10) == 0)
1571 return lxc_clear_cgroups(c
, key
);
1572 else if (strcmp(key
, "lxc.mount.entries") == 0)
1573 return lxc_clear_mount_entries(c
);
1574 else if (strncmp(key
, "lxc.hook", 8) == 0)
1575 return lxc_clear_hooks(c
, key
);
1581 * writing out a confile.
1583 void write_config(FILE *fout
, struct lxc_conf
*c
)
1585 struct lxc_list
*it
;
1589 fprintf(fout
, "lxc.mount = %s\n", c
->fstab
);
1590 lxc_list_for_each(it
, &c
->mount_list
) {
1591 fprintf(fout
, "lxc.mount.entry = %s\n", (char *)it
->elem
);
1594 fprintf(fout
, "lxc.tty = %d\n", c
->tty
);
1596 fprintf(fout
, "lxc.pts = %d\n", c
->pts
);
1598 fprintf(fout
, "lxc.devttydir = %s\n", c
->ttydir
);
1599 switch(c
->personality
) {
1600 case PER_LINUX32
: fprintf(fout
, "lxc.arch = x86\n"); break;
1601 case PER_LINUX
: fprintf(fout
, "lxc.arch = x86_64\n"); break;
1606 fprintf(fout
, "lxc.aa_profile = %s\n", c
->aa_profile
);
1608 lxc_list_for_each(it
, &c
->cgroup
) {
1609 struct lxc_cgroup
*cg
= it
->elem
;
1610 fprintf(fout
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
1613 fprintf(fout
, "lxc.utsname = %s\n", c
->utsname
->nodename
);
1614 lxc_list_for_each(it
, &c
->network
) {
1615 struct lxc_netdev
*n
= it
->elem
;
1616 const char *t
= lxc_net_type_to_str(n
->type
);
1617 struct lxc_list
*it2
;
1618 fprintf(fout
, "lxc.network.type = %s\n", t
? t
: "(invalid)");
1619 if (n
->flags
& IFF_UP
)
1620 fprintf(fout
, "lxc.network.flags = up\n");
1622 fprintf(fout
, "lxc.network.link = %s\n", n
->link
);
1624 fprintf(fout
, "lxc.network.name = %s\n", n
->name
);
1625 if (n
->type
== LXC_NET_MACVLAN
) {
1627 switch (n
->priv
.macvlan_attr
.mode
) {
1628 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
1629 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
1630 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
1631 default: mode
= "(invalid)"; break;
1633 fprintf(fout
, "lxc.network.macvlan.mode = %s\n", mode
);
1634 } else if (n
->type
== LXC_NET_VETH
) {
1635 if (n
->priv
.veth_attr
.pair
)
1636 fprintf(fout
, "lxc.network.veth.pair = %s\n",
1637 n
->priv
.veth_attr
.pair
);
1638 } else if (n
->type
== LXC_NET_VLAN
) {
1639 fprintf(fout
, "lxc.network.vlan.id = %d\n", n
->priv
.vlan_attr
.vid
);
1642 fprintf(fout
, "lxc.network.script.up = %s\n", n
->upscript
);
1644 fprintf(fout
, "lxc.network.hwaddr = %s\n", n
->hwaddr
);
1646 fprintf(fout
, "lxc.network.mtu = %s\n", n
->mtu
);
1647 if (n
->ipv4_gateway_auto
)
1648 fprintf(fout
, "lxc.network.ipv4.gateway = auto\n");
1649 else if (n
->ipv4_gateway
) {
1650 char buf
[INET_ADDRSTRLEN
];
1651 inet_ntop(AF_INET
, n
->ipv4_gateway
, buf
, sizeof(buf
));
1652 fprintf(fout
, "lxc.network.ipv4.gateway = %s\n", buf
);
1654 lxc_list_for_each(it2
, &n
->ipv4
) {
1655 struct lxc_inetdev
*i
= it2
->elem
;
1656 char buf
[INET_ADDRSTRLEN
];
1657 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1658 fprintf(fout
, "lxc.network.ipv4 = %s\n", buf
);
1660 if (n
->ipv6_gateway_auto
)
1661 fprintf(fout
, "lxc.network.ipv6.gateway = auto\n");
1662 else if (n
->ipv6_gateway
) {
1663 char buf
[INET6_ADDRSTRLEN
];
1664 inet_ntop(AF_INET6
, n
->ipv6_gateway
, buf
, sizeof(buf
));
1665 fprintf(fout
, "lxc.network.ipv6.gateway = %s\n", buf
);
1667 lxc_list_for_each(it2
, &n
->ipv6
) {
1668 struct lxc_inet6dev
*i
= it2
->elem
;
1669 char buf
[INET6_ADDRSTRLEN
];
1670 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
1671 fprintf(fout
, "lxc.network.ipv6 = %s\n", buf
);
1674 lxc_list_for_each(it
, &c
->caps
)
1675 fprintf(fout
, "lxc.cap.drop = %s\n", (char *)it
->elem
);
1676 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
1677 lxc_list_for_each(it
, &c
->hooks
[i
])
1678 fprintf(fout
, "lxc.hook.%s = %s\n",
1679 lxchook_names
[i
], (char *)it
->elem
);
1681 if (c
->console
.path
)
1682 fprintf(fout
, "lxc.console = %s\n", c
->console
.path
);
1684 fprintf(fout
, "lxc.rootfs = %s\n", c
->rootfs
.path
);
1685 if (c
->rootfs
.mount
&& strcmp(c
->rootfs
.mount
, LXCROOTFSMOUNT
) != 0)
1686 fprintf(fout
, "lxc.rootfs.mount = %s\n", c
->rootfs
.mount
);
1687 if (c
->rootfs
.pivot
)
1688 fprintf(fout
, "lxc.pivotdir = %s\n", c
->rootfs
.pivot
);