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 <arpa/inet.h>
35 #include <netinet/in.h>
44 lxc_log_define(lxc_confile
, lxc
);
46 static int config_pts(const char *, char *, struct lxc_conf
*);
47 static int config_tty(const char *, char *, struct lxc_conf
*);
48 static int config_cgroup(const char *, char *, struct lxc_conf
*);
49 static int config_mount(const char *, char *, struct lxc_conf
*);
50 static int config_rootfs(const char *, char *, struct lxc_conf
*);
51 static int config_pivotdir(const char *, char *, struct lxc_conf
*);
52 static int config_utsname(const char *, char *, struct lxc_conf
*);
53 static int config_network_type(const char *, char *, struct lxc_conf
*);
54 static int config_network_flags(const char *, char *, struct lxc_conf
*);
55 static int config_network_link(const char *, char *, struct lxc_conf
*);
56 static int config_network_name(const char *, char *, struct lxc_conf
*);
57 static int config_network_veth_pair(const char *, char *, struct lxc_conf
*);
58 static int config_network_macvlan_mode(const char *, char *, struct lxc_conf
*);
59 static int config_network_hwaddr(const char *, char *, struct lxc_conf
*);
60 static int config_network_vlan_id(const char *, char *, struct lxc_conf
*);
61 static int config_network_mtu(const char *, char *, struct lxc_conf
*);
62 static int config_network_ipv4(const char *, char *, struct lxc_conf
*);
63 static int config_network_ipv6(const char *, char *, struct lxc_conf
*);
64 static int config_cap_drop(const char *, char *, struct lxc_conf
*);
65 static int config_console(const char *, char *, struct lxc_conf
*);
67 typedef int (*config_cb
)(const char *, char *, struct lxc_conf
*);
74 static struct config config
[] = {
76 { "lxc.pts", config_pts
},
77 { "lxc.tty", config_tty
},
78 { "lxc.cgroup", config_cgroup
},
79 { "lxc.mount", config_mount
},
80 { "lxc.rootfs", config_rootfs
},
81 { "lxc.pivotdir", config_pivotdir
},
82 { "lxc.utsname", config_utsname
},
83 { "lxc.network.type", config_network_type
},
84 { "lxc.network.flags", config_network_flags
},
85 { "lxc.network.link", config_network_link
},
86 { "lxc.network.name", config_network_name
},
87 { "lxc.network.macvlan.mode", config_network_macvlan_mode
},
88 { "lxc.network.veth.pair", config_network_veth_pair
},
89 { "lxc.network.hwaddr", config_network_hwaddr
},
90 { "lxc.network.mtu", config_network_mtu
},
91 { "lxc.network.vlan.id", config_network_vlan_id
},
92 { "lxc.network.ipv4", config_network_ipv4
},
93 { "lxc.network.ipv6", config_network_ipv6
},
94 { "lxc.cap.drop", config_cap_drop
},
95 { "lxc.console", config_console
},
98 static const size_t config_size
= sizeof(config
)/sizeof(struct config
);
100 static struct config
*getconfig(const char *key
)
104 for (i
= 0; i
< config_size
; i
++)
105 if (!strncmp(config
[i
].name
, key
,
106 strlen(config
[i
].name
)))
111 static int config_network_type(const char *key
, char *value
,
112 struct lxc_conf
*lxc_conf
)
114 struct lxc_list
*network
= &lxc_conf
->network
;
115 struct lxc_netdev
*netdev
;
116 struct lxc_list
*list
;
118 netdev
= malloc(sizeof(*netdev
));
120 SYSERROR("failed to allocate memory");
124 memset(netdev
, 0, sizeof(*netdev
));
125 lxc_list_init(&netdev
->ipv4
);
126 lxc_list_init(&netdev
->ipv6
);
128 list
= malloc(sizeof(*list
));
130 SYSERROR("failed to allocate memory");
137 lxc_list_add(network
, list
);
139 if (!strcmp(value
, "veth"))
140 netdev
->type
= LXC_NET_VETH
;
141 else if (!strcmp(value
, "macvlan"))
142 netdev
->type
= LXC_NET_MACVLAN
;
143 else if (!strcmp(value
, "vlan"))
144 netdev
->type
= LXC_NET_VLAN
;
145 else if (!strcmp(value
, "phys"))
146 netdev
->type
= LXC_NET_PHYS
;
147 else if (!strcmp(value
, "empty"))
148 netdev
->type
= LXC_NET_EMPTY
;
150 ERROR("invalid network type %s", value
);
156 static int config_ip_prefix(struct in_addr
*addr
)
158 if (IN_CLASSA(addr
->s_addr
))
159 return 32 - IN_CLASSA_NSHIFT
;
160 if (IN_CLASSB(addr
->s_addr
))
161 return 32 - IN_CLASSB_NSHIFT
;
162 if (IN_CLASSC(addr
->s_addr
))
163 return 32 - IN_CLASSC_NSHIFT
;
168 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
169 struct lxc_list
*network
)
171 struct lxc_netdev
*netdev
;
173 if (lxc_list_empty(network
)) {
174 ERROR("network is not created for '%s' = '%s' option",
179 netdev
= lxc_list_first_elem(network
);
181 ERROR("no network device defined for '%s' = '%s' option",
189 static int network_ifname(char **valuep
, char *value
)
191 if (strlen(value
) > IFNAMSIZ
) {
192 ERROR("invalid interface name: %s", value
);
196 *valuep
= strdup(value
);
198 ERROR("failed to dup string '%s'", value
);
205 #ifndef MACVLAN_MODE_PRIVATE
206 # define MACVLAN_MODE_PRIVATE 1
209 #ifndef MACVLAN_MODE_VEPA
210 # define MACVLAN_MODE_VEPA 2
213 #ifndef MACVLAN_MODE_BRIDGE
214 # define MACVLAN_MODE_BRIDGE 4
217 static int macvlan_mode(int *valuep
, char *value
)
223 { "private", MACVLAN_MODE_PRIVATE
},
224 { "vepa", MACVLAN_MODE_VEPA
},
225 { "bridge", MACVLAN_MODE_BRIDGE
},
230 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
231 if (strcmp(m
[i
].name
, value
))
241 static int config_network_flags(const char *key
, char *value
,
242 struct lxc_conf
*lxc_conf
)
244 struct lxc_netdev
*netdev
;
246 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
250 netdev
->flags
|= IFF_UP
;
255 static int config_network_link(const char *key
, char *value
,
256 struct lxc_conf
*lxc_conf
)
258 struct lxc_netdev
*netdev
;
260 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
264 return network_ifname(&netdev
->link
, value
);
267 static int config_network_name(const char *key
, char *value
,
268 struct lxc_conf
*lxc_conf
)
270 struct lxc_netdev
*netdev
;
272 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
276 return network_ifname(&netdev
->name
, value
);
279 static int config_network_veth_pair(const char *key
, char *value
,
280 struct lxc_conf
*lxc_conf
)
282 struct lxc_netdev
*netdev
;
284 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
288 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
291 static int config_network_macvlan_mode(const char *key
, char *value
,
292 struct lxc_conf
*lxc_conf
)
294 struct lxc_netdev
*netdev
;
296 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
300 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
303 static int config_network_hwaddr(const char *key
, char *value
,
304 struct lxc_conf
*lxc_conf
)
306 struct lxc_netdev
*netdev
;
308 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
312 netdev
->hwaddr
= strdup(value
);
313 if (!netdev
->hwaddr
) {
314 SYSERROR("failed to dup string '%s'", value
);
321 static int config_network_vlan_id(const char *key
, char *value
,
322 struct lxc_conf
*lxc_conf
)
324 struct lxc_netdev
*netdev
;
326 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
330 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
336 static int config_network_mtu(const char *key
, char *value
,
337 struct lxc_conf
*lxc_conf
)
339 struct lxc_netdev
*netdev
;
341 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
345 netdev
->mtu
= strdup(value
);
347 SYSERROR("failed to dup string '%s'", value
);
354 static int config_network_ipv4(const char *key
, char *value
,
355 struct lxc_conf
*lxc_conf
)
357 struct lxc_netdev
*netdev
;
358 struct lxc_inetdev
*inetdev
;
359 struct lxc_list
*list
;
360 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
362 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
366 inetdev
= malloc(sizeof(*inetdev
));
368 SYSERROR("failed to allocate ipv4 address");
371 memset(inetdev
, 0, sizeof(*inetdev
));
373 list
= malloc(sizeof(*list
));
375 SYSERROR("failed to allocate memory");
380 list
->elem
= inetdev
;
384 cursor
= strstr(addr
, " ");
390 slash
= strstr(addr
, "/");
397 ERROR("no address specified");
401 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
402 SYSERROR("invalid ipv4 address: %s", value
);
407 if (!inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
408 SYSERROR("invalid ipv4 address: %s", value
);
412 /* no prefix specified, determine it from the network class */
413 inetdev
->prefix
= prefix
? atoi(prefix
) :
414 config_ip_prefix(&inetdev
->addr
);
417 lxc_list_add(&netdev
->ipv4
, list
);
422 static int config_network_ipv6(const char *key
, char *value
,
423 struct lxc_conf
*lxc_conf
)
425 struct lxc_netdev
*netdev
;
426 struct lxc_inet6dev
*inet6dev
;
427 struct lxc_list
*list
;
431 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
435 inet6dev
= malloc(sizeof(*inet6dev
));
437 SYSERROR("failed to allocate ipv6 address");
440 memset(inet6dev
, 0, sizeof(*inet6dev
));
442 list
= malloc(sizeof(*list
));
444 SYSERROR("failed to allocate memory");
449 list
->elem
= inet6dev
;
451 inet6dev
->prefix
= 64;
452 slash
= strstr(value
, "/");
456 inet6dev
->prefix
= atoi(netmask
);
459 if (!inet_pton(AF_INET6
, value
, &inet6dev
->addr
)) {
460 SYSERROR("invalid ipv6 address: %s", value
);
464 lxc_list_add(&netdev
->ipv6
, list
);
469 static int config_pts(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
471 int maxpts
= atoi(value
);
473 lxc_conf
->pts
= maxpts
;
478 static int config_tty(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
480 int nbtty
= atoi(value
);
482 lxc_conf
->tty
= nbtty
;
487 static int config_cgroup(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
489 char *token
= "lxc.cgroup.";
491 struct lxc_list
*cglist
;
492 struct lxc_cgroup
*cgelem
;
494 subkey
= strstr(key
, token
);
502 if (strlen(subkey
) == strlen(token
))
505 subkey
+= strlen(token
);
507 cglist
= malloc(sizeof(*cglist
));
511 cgelem
= malloc(sizeof(*cgelem
));
517 cgelem
->subsystem
= strdup(subkey
);
518 cgelem
->value
= strdup(value
);
519 cglist
->elem
= cgelem
;
521 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
526 static int config_fstab(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
528 if (strlen(value
) >= MAXPATHLEN
) {
529 ERROR("%s path is too long", value
);
533 lxc_conf
->fstab
= strdup(value
);
534 if (!lxc_conf
->fstab
) {
535 SYSERROR("failed to duplicate string %s", value
);
542 static int config_mount(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
544 char *fstab_token
= "lxc.mount";
545 char *token
= "lxc.mount.entry";
548 struct lxc_list
*mntlist
;
550 subkey
= strstr(key
, token
);
553 subkey
= strstr(key
, fstab_token
);
558 return config_fstab(key
, value
, lxc_conf
);
564 mntlist
= malloc(sizeof(*mntlist
));
568 mntelem
= strdup(value
);
569 mntlist
->elem
= mntelem
;
571 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
576 static int config_cap_drop(const char *key
, char *value
,
577 struct lxc_conf
*lxc_conf
)
579 char *dropcaps
, *sptr
, *token
;
580 struct lxc_list
*droplist
;
586 dropcaps
= strdup(value
);
588 SYSERROR("failed to dup '%s'", value
);
592 /* in case several capability drop is specified in a single line
593 * split these caps in a single element for the list */
595 token
= strtok_r(dropcaps
, " \t", &sptr
);
602 droplist
= malloc(sizeof(*droplist
));
604 SYSERROR("failed to allocate drop list");
608 droplist
->elem
= strdup(token
);
609 if (!droplist
->elem
) {
610 SYSERROR("failed to dup '%s'", token
);
615 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
623 static int config_console(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
627 fd
= open(value
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600);
629 SYSERROR("failed to open '%s'", value
);
633 lxc_conf
->console
.peer
= fd
;
638 static int config_rootfs(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
640 if (strlen(value
) >= MAXPATHLEN
) {
641 ERROR("%s path is too long", value
);
645 lxc_conf
->rootfs
= strdup(value
);
646 if (!lxc_conf
->rootfs
) {
647 SYSERROR("failed to duplicate string %s", value
);
654 static int config_pivotdir(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
656 if (strlen(value
) >= MAXPATHLEN
) {
657 ERROR("%s path is too long", value
);
661 lxc_conf
->pivotdir
= strdup(value
);
662 if (!lxc_conf
->pivotdir
) {
663 SYSERROR("failed to duplicate string %s", value
);
670 static int config_utsname(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
672 struct utsname
*utsname
;
674 utsname
= malloc(sizeof(*utsname
));
676 SYSERROR("failed to allocate memory");
680 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
681 ERROR("node name '%s' is too long",
686 strcpy(utsname
->nodename
, value
);
687 lxc_conf
->utsname
= utsname
;
692 static int parse_line(char *buffer
, void *data
)
694 struct config
*config
;
700 if (lxc_is_line_empty(line
))
703 line
+= lxc_char_left_gc(line
, strlen(line
));
707 dot
= strstr(line
, "=");
709 ERROR("invalid configuration line: %s", line
);
717 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
719 value
+= lxc_char_left_gc(value
, strlen(value
));
720 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
722 config
= getconfig(key
);
724 ERROR("unknow key %s", key
);
728 return config
->cb(key
, value
, data
);
731 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
733 return parse_line(buffer
, conf
);
736 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
738 return lxc_file_for_each_line(file
, parse_line
, conf
);
741 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
743 struct lxc_list
*dent
;
745 dent
= malloc(sizeof(struct lxc_list
));
750 lxc_list_add_tail(defines
, dent
);
754 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
759 lxc_list_for_each(it
, defines
) {
760 ret
= lxc_config_readline(it
->elem
, conf
);
765 lxc_list_for_each(it
, defines
) {