]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile_legacy.c
2 * lxc: linux Container library
3 * (C) Copyright IBM Corp. 2007, 2008
6 * Daniel Lezcano <daniel.lezcano at free.fr>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
31 #include <inttypes.h> /* Required for PRIu64 to work. */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/utsname.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
47 #include "confile_utils.h"
48 #include "confile_legacy.h"
53 #include "lxcseccomp.h"
59 #include <../include/ifaddrs.h>
62 lxc_log_define(lxc_confile_legacy
, lxc
);
65 * Config entry is something like "lxc.network.0.ipv4" the key 'lxc.network.'
66 * was found. So we make sure next comes an integer, find the right callback
67 * (by rewriting the key), and call it.
69 int set_config_network_legacy_nic(const char *key
, const char *value
,
70 struct lxc_conf
*lxc_conf
, void *data
)
72 char *copy
= strdup(key
), *p
;
74 struct lxc_config_t
*config
;
77 SYSERROR("failed to allocate memory");
81 * Ok we know that to get here we've got "lxc.network."
82 * and it isn't any of the other network entries. So
83 * after the second . Should come an integer (# of defined
84 * nic) followed by a valid entry.
86 if (*(key
+ 12) < '0' || *(key
+ 12) > '9')
89 p
= strchr(key
+ 12, '.');
93 strcpy(copy
+ 12, p
+ 1);
94 config
= lxc_get_config(copy
);
96 ERROR("unknown key %s", key
);
99 ret
= config
->set(key
, value
, lxc_conf
, NULL
);
106 static void lxc_remove_nic(struct lxc_list
*it
)
108 struct lxc_netdev
*netdev
= it
->elem
;
109 struct lxc_list
*it2
,*next
;
113 free(netdev
->upscript
);
114 free(netdev
->downscript
);
115 free(netdev
->hwaddr
);
117 free(netdev
->ipv4_gateway
);
118 free(netdev
->ipv6_gateway
);
119 lxc_list_for_each_safe(it2
, &netdev
->ipv4
, next
) {
124 lxc_list_for_each_safe(it2
, &netdev
->ipv6
, next
) {
133 static int lxc_clear_config_network(struct lxc_conf
*c
)
135 struct lxc_list
*it
,*next
;
136 lxc_list_for_each_safe(it
, &c
->network
, next
) {
142 int set_config_network_legacy(const char *key
, const char *value
,
143 struct lxc_conf
*lxc_conf
, void *data
)
145 if (!lxc_config_value_empty(value
)) {
146 ERROR("lxc.network must not have a value");
150 return lxc_clear_config_network(lxc_conf
);
153 int set_config_network_legacy_type(const char *key
, const char *value
,
154 struct lxc_conf
*lxc_conf
, void *data
)
156 struct lxc_list
*network
= &lxc_conf
->network
;
157 struct lxc_netdev
*netdev
, *prevnetdev
;
158 struct lxc_list
*list
;
160 if (lxc_config_value_empty(value
))
161 return lxc_clear_config_network(lxc_conf
);
163 netdev
= malloc(sizeof(*netdev
));
165 SYSERROR("failed to allocate memory");
169 memset(netdev
, 0, sizeof(*netdev
));
170 lxc_list_init(&netdev
->ipv4
);
171 lxc_list_init(&netdev
->ipv6
);
173 list
= malloc(sizeof(*list
));
175 SYSERROR("failed to allocate memory");
183 /* We maintain a negative count for legacy networks. */
185 if (!lxc_list_empty(network
)) {
186 prevnetdev
= lxc_list_last_elem(network
);
187 netdev
->idx
= prevnetdev
->idx
;
188 if (netdev
->idx
== INT_MIN
) {
189 ERROR("number of requested networks would underflow "
198 lxc_list_add_tail(network
, list
);
200 if (!strcmp(value
, "veth"))
201 netdev
->type
= LXC_NET_VETH
;
202 else if (!strcmp(value
, "macvlan")) {
203 netdev
->type
= LXC_NET_MACVLAN
;
204 lxc_macvlan_mode_to_flag(&netdev
->priv
.macvlan_attr
.mode
, "private");
205 } else if (!strcmp(value
, "vlan"))
206 netdev
->type
= LXC_NET_VLAN
;
207 else if (!strcmp(value
, "phys"))
208 netdev
->type
= LXC_NET_PHYS
;
209 else if (!strcmp(value
, "empty"))
210 netdev
->type
= LXC_NET_EMPTY
;
211 else if (!strcmp(value
, "none"))
212 netdev
->type
= LXC_NET_NONE
;
214 ERROR("invalid network type %s", value
);
221 * If you have p="lxc.network.0.link", pass it p+12
222 * to get back '0' (the index of the nic).
224 static int get_network_netdev_idx(const char *key
)
228 if (*key
< '0' || *key
> '9')
231 ret
= sscanf(key
, "%d", &idx
);
235 /* Since we've implemented the new network parser legacy networks are
236 * recorded using a negative index starting from -1. To preserve the old
237 * behavior we need this function to return the appropriate negative
244 * If you have p="lxc.network.0", pass this p+12 and it will return
245 * the netdev of the first configured nic.
247 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
248 struct lxc_list
*network
)
252 struct lxc_netdev
*netdev
= NULL
;
254 idx
= get_network_netdev_idx(key
);
258 lxc_list_for_each(it
, network
) {
260 if (idx
== netdev
->idx
)
267 int lxc_list_nicconfigs_legacy(struct lxc_conf
*c
, const char *key
, char *retv
,
270 struct lxc_netdev
*netdev
;
274 netdev
= get_netdev_from_key(key
+ 12, &c
->network
);
281 memset(retv
, 0, inlen
);
283 strprint(retv
, inlen
, "type\n");
284 strprint(retv
, inlen
, "script.up\n");
285 strprint(retv
, inlen
, "script.down\n");
286 if (netdev
->type
!= LXC_NET_EMPTY
) {
287 strprint(retv
, inlen
, "flags\n");
288 strprint(retv
, inlen
, "link\n");
289 strprint(retv
, inlen
, "name\n");
290 strprint(retv
, inlen
, "hwaddr\n");
291 strprint(retv
, inlen
, "mtu\n");
292 strprint(retv
, inlen
, "ipv6\n");
293 strprint(retv
, inlen
, "ipv6.gateway\n");
294 strprint(retv
, inlen
, "ipv4\n");
295 strprint(retv
, inlen
, "ipv4.gateway\n");
298 switch (netdev
->type
) {
300 strprint(retv
, inlen
, "veth.pair\n");
302 case LXC_NET_MACVLAN
:
303 strprint(retv
, inlen
, "macvlan.mode\n");
306 strprint(retv
, inlen
, "vlan.id\n");
315 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
316 struct lxc_list
*network
)
318 struct lxc_netdev
*netdev
= NULL
;
320 if (lxc_list_empty(network
)) {
321 ERROR("network is not created for '%s' = '%s' option", key
,
326 if (get_network_netdev_idx(key
+ 12) == EINVAL
)
327 netdev
= lxc_list_last_elem(network
);
329 netdev
= get_netdev_from_key(key
+ 12, network
);
332 ERROR("no network device defined for '%s' = '%s' option", key
,
340 int set_config_network_legacy_flags(const char *key
, const char *value
,
341 struct lxc_conf
*lxc_conf
, void *data
)
343 struct lxc_netdev
*netdev
;
345 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
349 netdev
->flags
|= IFF_UP
;
354 static int create_matched_ifnames(const char *value
, struct lxc_conf
*lxc_conf
,
355 struct lxc_netdev
*netdev
)
357 struct ifaddrs
*ifaddr
, *ifa
;
360 const char *type_key
= "lxc.network.type";
361 const char *link_key
= "lxc.network.link";
362 const char *tmpvalue
= "phys";
364 if (getifaddrs(&ifaddr
) == -1) {
365 SYSERROR("Get network interfaces failed");
369 for (ifa
= ifaddr
, n
= 0; ifa
!= NULL
; ifa
= ifa
->ifa_next
, n
++) {
372 if (ifa
->ifa_addr
->sa_family
!= AF_PACKET
)
375 if (!strncmp(value
, ifa
->ifa_name
, strlen(value
) - 1)) {
376 ret
= set_config_network_legacy_type(type_key
, tmpvalue
,
379 ret
= set_config_network_legacy_link(
380 link_key
, ifa
->ifa_name
, lxc_conf
, netdev
);
382 ERROR("failed to create matched ifnames");
386 ERROR("failed to create matched ifnames");
398 int set_config_network_legacy_link(const char *key
, const char *value
,
399 struct lxc_conf
*lxc_conf
, void *data
)
401 struct lxc_netdev
*netdev
;
405 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
409 if (value
[strlen(value
) - 1] == '+' && netdev
->type
== LXC_NET_PHYS
) {
410 /* Get the last network list and remove it. */
411 it
= lxc_conf
->network
.prev
;
412 if (((struct lxc_netdev
*)(it
->elem
))->type
!= LXC_NET_PHYS
) {
413 ERROR("lxc config cannot support string pattern "
414 "matching for this link type");
420 ret
= create_matched_ifnames(value
, lxc_conf
, NULL
);
422 ret
= network_ifname(netdev
->link
, value
);
428 int set_config_network_legacy_name(const char *key
, const char *value
,
429 struct lxc_conf
*lxc_conf
, void *data
)
431 struct lxc_netdev
*netdev
;
433 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
437 return network_ifname(netdev
->name
, value
);
440 int set_config_network_legacy_veth_pair(const char *key
, const char *value
,
441 struct lxc_conf
*lxc_conf
, void *data
)
443 struct lxc_netdev
*netdev
;
445 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
449 if (netdev
->type
!= LXC_NET_VETH
) {
450 ERROR("Invalid veth pair for a non-veth netdev");
454 return network_ifname(netdev
->priv
.veth_attr
.pair
, value
);
457 int set_config_network_legacy_macvlan_mode(const char *key
, const char *value
,
458 struct lxc_conf
*lxc_conf
,
461 struct lxc_netdev
*netdev
;
463 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
467 if (netdev
->type
!= LXC_NET_MACVLAN
) {
468 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
472 return lxc_macvlan_mode_to_flag(&netdev
->priv
.macvlan_attr
.mode
, value
);
475 int set_config_network_legacy_hwaddr(const char *key
, const char *value
,
476 struct lxc_conf
*lxc_conf
, void *data
)
478 struct lxc_netdev
*netdev
;
481 new_value
= strdup(value
);
483 SYSERROR("failed to strdup \"%s\"", value
);
486 rand_complete_hwaddr(new_value
);
488 netdev
= network_netdev(key
, new_value
, &lxc_conf
->network
);
494 if (lxc_config_value_empty(new_value
)) {
496 netdev
->hwaddr
= NULL
;
500 netdev
->hwaddr
= new_value
;
504 int set_config_network_legacy_vlan_id(const char *key
, const char *value
,
505 struct lxc_conf
*lxc_conf
, void *data
)
507 struct lxc_netdev
*netdev
;
509 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
513 if (netdev
->type
!= LXC_NET_VLAN
) {
514 ERROR("Invalid vlan.id for a non-macvlan netdev");
518 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
524 int set_config_network_legacy_mtu(const char *key
, const char *value
,
525 struct lxc_conf
*lxc_conf
, void *data
)
527 struct lxc_netdev
*netdev
;
529 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
533 return set_config_string_item(&netdev
->mtu
, value
);
536 int set_config_network_legacy_ipv4(const char *key
, const char *value
,
537 struct lxc_conf
*lxc_conf
, void *data
)
539 struct lxc_netdev
*netdev
;
540 struct lxc_inetdev
*inetdev
;
541 struct lxc_list
*list
;
542 char *cursor
, *slash
;
543 char *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
545 if (lxc_config_value_empty(value
))
546 return clr_config_network_legacy_item(key
, lxc_conf
, NULL
);
548 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
552 inetdev
= malloc(sizeof(*inetdev
));
554 SYSERROR("failed to allocate ipv4 address");
557 memset(inetdev
, 0, sizeof(*inetdev
));
559 list
= malloc(sizeof(*list
));
561 SYSERROR("failed to allocate memory");
567 list
->elem
= inetdev
;
569 addr
= strdup(value
);
571 ERROR("no address specified");
577 cursor
= strstr(addr
, " ");
583 slash
= strstr(addr
, "/");
589 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
590 SYSERROR("invalid ipv4 address: %s", value
);
597 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
598 SYSERROR("invalid ipv4 broadcast address: %s", value
);
605 /* No prefix specified, determine it from the network class. */
607 if (lxc_safe_uint(prefix
, &inetdev
->prefix
) < 0)
610 inetdev
->prefix
= config_ip_prefix(&inetdev
->addr
);
613 /* If no broadcast address, let compute one from the
614 * prefix and address.
617 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
618 inetdev
->bcast
.s_addr
|=
619 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
622 lxc_list_add_tail(&netdev
->ipv4
, list
);
628 int set_config_network_legacy_ipv4_gateway(const char *key
, const char *value
,
629 struct lxc_conf
*lxc_conf
,
632 struct lxc_netdev
*netdev
;
634 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
638 free(netdev
->ipv4_gateway
);
640 if (lxc_config_value_empty(value
)) {
641 netdev
->ipv4_gateway
= NULL
;
642 } else if (!strcmp(value
, "auto")) {
643 netdev
->ipv4_gateway
= NULL
;
644 netdev
->ipv4_gateway_auto
= true;
648 gw
= malloc(sizeof(*gw
));
650 SYSERROR("failed to allocate ipv4 gateway address");
654 if (!inet_pton(AF_INET
, value
, gw
)) {
655 SYSERROR("invalid ipv4 gateway address: %s", value
);
660 netdev
->ipv4_gateway
= gw
;
661 netdev
->ipv4_gateway_auto
= false;
667 int set_config_network_legacy_ipv6(const char *key
, const char *value
,
668 struct lxc_conf
*lxc_conf
, void *data
)
670 struct lxc_netdev
*netdev
;
671 struct lxc_inet6dev
*inet6dev
;
672 struct lxc_list
*list
;
673 char *slash
, *valdup
, *netmask
;
675 if (lxc_config_value_empty(value
))
676 return clr_config_network_legacy_item(key
, lxc_conf
, NULL
);
678 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
682 inet6dev
= malloc(sizeof(*inet6dev
));
684 SYSERROR("failed to allocate ipv6 address");
687 memset(inet6dev
, 0, sizeof(*inet6dev
));
689 list
= malloc(sizeof(*list
));
691 SYSERROR("failed to allocate memory");
697 list
->elem
= inet6dev
;
699 valdup
= strdup(value
);
701 ERROR("no address specified");
707 inet6dev
->prefix
= 64;
708 slash
= strstr(valdup
, "/");
712 if (lxc_safe_uint(netmask
, &inet6dev
->prefix
) < 0)
716 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
717 SYSERROR("invalid ipv6 address: %s", valdup
);
724 lxc_list_add_tail(&netdev
->ipv6
, list
);
730 int set_config_network_legacy_ipv6_gateway(const char *key
, const char *value
,
731 struct lxc_conf
*lxc_conf
,
734 struct lxc_netdev
*netdev
;
736 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
740 free(netdev
->ipv6_gateway
);
742 if (lxc_config_value_empty(value
)) {
743 netdev
->ipv6_gateway
= NULL
;
744 } else if (!strcmp(value
, "auto")) {
745 netdev
->ipv6_gateway
= NULL
;
746 netdev
->ipv6_gateway_auto
= true;
750 gw
= malloc(sizeof(*gw
));
752 SYSERROR("failed to allocate ipv6 gateway address");
756 if (!inet_pton(AF_INET6
, value
, gw
)) {
757 SYSERROR("invalid ipv6 gateway address: %s", value
);
762 netdev
->ipv6_gateway
= gw
;
763 netdev
->ipv6_gateway_auto
= false;
769 int set_config_network_legacy_script_up(const char *key
, const char *value
,
770 struct lxc_conf
*lxc_conf
, void *data
)
772 struct lxc_netdev
*netdev
;
774 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
778 return set_config_string_item(&netdev
->upscript
, value
);
781 int set_config_network_legacy_script_down(const char *key
, const char *value
,
782 struct lxc_conf
*lxc_conf
, void *data
)
784 struct lxc_netdev
*netdev
;
786 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
790 return set_config_string_item(&netdev
->downscript
, value
);
793 int get_config_network_legacy(const char *key
, char *retv
, int inlen
,
794 struct lxc_conf
*c
, void *data
)
796 int len
, fulllen
= 0;
802 memset(retv
, 0, inlen
);
804 lxc_list_for_each(it
, &c
->network
) {
805 struct lxc_netdev
*n
= it
->elem
;
806 const char *t
= lxc_net_type_to_str(n
->type
);
807 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
814 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
815 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
816 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
817 * of an address. ipv4 and ipv6 return lists (newline-separated).
818 * things like veth.pair return '' if invalid (i.e. if called for vlan
821 int get_config_network_legacy_item(const char *key
, char *retv
, int inlen
,
822 struct lxc_conf
*c
, void *data
)
825 int len
, fulllen
= 0;
826 struct lxc_netdev
*netdev
;
831 memset(retv
, 0, inlen
);
833 if (!strncmp(key
, "lxc.network.", 12))
838 p1
= strchr(key
, '.');
839 if (!p1
|| *(p1
+ 1) == '\0')
843 netdev
= get_netdev_from_key(key
, &c
->network
);
846 if (strcmp(p1
, "name") == 0) {
847 if (netdev
->name
[0] != '\0')
848 strprint(retv
, inlen
, "%s", netdev
->name
);
849 } else if (strcmp(p1
, "type") == 0) {
850 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
851 } else if (strcmp(p1
, "link") == 0) {
852 if (netdev
->link
[0] != '\0')
853 strprint(retv
, inlen
, "%s", netdev
->link
);
854 } else if (strcmp(p1
, "flags") == 0) {
855 if (netdev
->flags
& IFF_UP
)
856 strprint(retv
, inlen
, "up");
857 } else if (strcmp(p1
, "script.up") == 0) {
858 if (netdev
->upscript
)
859 strprint(retv
, inlen
, "%s", netdev
->upscript
);
860 } else if (strcmp(p1
, "script.down") == 0) {
861 if (netdev
->downscript
)
862 strprint(retv
, inlen
, "%s", netdev
->downscript
);
863 } else if (strcmp(p1
, "hwaddr") == 0) {
865 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
866 } else if (strcmp(p1
, "mtu") == 0) {
868 strprint(retv
, inlen
, "%s", netdev
->mtu
);
869 } else if (strcmp(p1
, "macvlan.mode") == 0) {
870 if (netdev
->type
== LXC_NET_MACVLAN
) {
872 switch (netdev
->priv
.macvlan_attr
.mode
) {
873 case MACVLAN_MODE_PRIVATE
:
876 case MACVLAN_MODE_VEPA
:
879 case MACVLAN_MODE_BRIDGE
:
882 case MACVLAN_MODE_PASSTHRU
:
889 strprint(retv
, inlen
, "%s", mode
);
891 } else if (strcmp(p1
, "veth.pair") == 0) {
892 if (netdev
->type
== LXC_NET_VETH
) {
893 strprint(retv
, inlen
, "%s",
894 netdev
->priv
.veth_attr
.pair
[0] != '\0'
895 ? netdev
->priv
.veth_attr
.pair
896 : netdev
->priv
.veth_attr
.veth1
);
898 } else if (strcmp(p1
, "vlan") == 0) {
899 if (netdev
->type
== LXC_NET_VLAN
) {
900 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
902 } else if (strcmp(p1
, "ipv4.gateway") == 0) {
903 if (netdev
->ipv4_gateway_auto
) {
904 strprint(retv
, inlen
, "auto");
905 } else if (netdev
->ipv4_gateway
) {
906 char buf
[INET_ADDRSTRLEN
];
907 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
,
909 strprint(retv
, inlen
, "%s", buf
);
911 } else if (strcmp(p1
, "ipv4") == 0) {
912 struct lxc_list
*it2
;
913 lxc_list_for_each(it2
, &netdev
->ipv4
) {
914 struct lxc_inetdev
*i
= it2
->elem
;
915 char buf
[INET_ADDRSTRLEN
];
916 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
917 strprint(retv
, inlen
, "%s/%u\n", buf
, i
->prefix
);
919 } else if (strcmp(p1
, "ipv6.gateway") == 0) {
920 if (netdev
->ipv6_gateway_auto
) {
921 strprint(retv
, inlen
, "auto");
922 } else if (netdev
->ipv6_gateway
) {
923 char buf
[INET6_ADDRSTRLEN
];
924 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
,
926 strprint(retv
, inlen
, "%s", buf
);
928 } else if (strcmp(p1
, "ipv6") == 0) {
929 struct lxc_list
*it2
;
930 lxc_list_for_each(it2
, &netdev
->ipv6
) {
931 struct lxc_inet6dev
*i
= it2
->elem
;
932 char buf
[INET6_ADDRSTRLEN
];
933 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
934 strprint(retv
, inlen
, "%s/%u\n", buf
, i
->prefix
);
940 /* we get passed in something like '0', '0.ipv4' or '1.ipv6' */
941 static int lxc_clear_nic(struct lxc_conf
*c
, const char *key
)
945 struct lxc_list
*it
= NULL
;
946 struct lxc_netdev
*netdev
= NULL
;
948 if (lxc_list_empty(&c
->network
)) {
949 ERROR("network is not created for %s", key
);
953 if ((idx
= get_network_netdev_idx(key
)) == EINVAL
)
954 netdev
= lxc_list_last_elem(&c
->network
);
956 lxc_list_for_each(it
, &c
->network
) {
958 if (idx
== netdev
->idx
)
966 p1
= strchr(key
, '.');
967 if (!p1
|| *(p1
+1) == '\0')
972 } else if (strcmp(p1
, ".ipv4") == 0) {
973 struct lxc_list
*it2
,*next
;
974 lxc_list_for_each_safe(it2
, &netdev
->ipv4
, next
) {
979 } else if (strcmp(p1
, ".ipv6") == 0) {
980 struct lxc_list
*it2
,*next
;
981 lxc_list_for_each_safe(it2
, &netdev
->ipv6
, next
) {
992 inline int clr_config_network_legacy_item(const char *key
, struct lxc_conf
*c
,
995 return lxc_clear_nic(c
, key
+ 12);
998 inline int clr_config_network_legacy(const char *key
, struct lxc_conf
*c
, void *data
)
1000 return lxc_clear_config_network(c
);
1003 inline int clr_config_lsm_aa_profile(const char *key
, struct lxc_conf
*c
,
1006 free(c
->lsm_aa_profile
);
1007 c
->lsm_aa_profile
= NULL
;
1011 inline int clr_config_lsm_aa_incomplete(const char *key
, struct lxc_conf
*c
,
1014 c
->lsm_aa_allow_incomplete
= 0;
1018 int get_config_lsm_aa_profile(const char *key
, char *retv
, int inlen
,
1019 struct lxc_conf
*c
, void *data
)
1021 return lxc_get_conf_str(retv
, inlen
, c
->lsm_aa_profile
);
1024 int get_config_lsm_aa_incomplete(const char *key
, char *retv
, int inlen
,
1025 struct lxc_conf
*c
, void *data
)
1027 return lxc_get_conf_int(c
, retv
, inlen
,
1028 c
->lsm_aa_allow_incomplete
);
1031 int set_config_lsm_aa_profile(const char *key
, const char *value
,
1032 struct lxc_conf
*lxc_conf
, void *data
)
1034 return set_config_string_item(&lxc_conf
->lsm_aa_profile
, value
);
1037 int set_config_lsm_aa_incomplete(const char *key
, const char *value
,
1038 struct lxc_conf
*lxc_conf
, void *data
)
1040 /* Set config value to default. */
1041 if (lxc_config_value_empty(value
)) {
1042 lxc_conf
->lsm_aa_allow_incomplete
= 0;
1046 /* Parse new config value. */
1047 if (lxc_safe_uint(value
, &lxc_conf
->lsm_aa_allow_incomplete
) < 0)
1050 if (lxc_conf
->lsm_aa_allow_incomplete
> 1) {
1051 ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only "
1052 "be set to 0 or 1");
1059 int set_config_lsm_se_context(const char *key
, const char *value
,
1060 struct lxc_conf
*lxc_conf
, void *data
)
1062 return set_config_string_item(&lxc_conf
->lsm_se_context
, value
);
1065 int get_config_lsm_se_context(const char *key
, char *retv
, int inlen
,
1066 struct lxc_conf
*c
, void *data
)
1068 return lxc_get_conf_str(retv
, inlen
, c
->lsm_se_context
);
1071 inline int clr_config_lsm_se_context(const char *key
, struct lxc_conf
*c
,
1074 free(c
->lsm_se_context
);
1075 c
->lsm_se_context
= NULL
;
1079 extern int set_config_limit(const char *key
, const char *value
,
1080 struct lxc_conf
*lxc_conf
, void *data
)
1082 struct lxc_list
*iter
;
1083 struct rlimit limit
;
1085 struct lxc_list
*limlist
= NULL
;
1086 struct lxc_limit
*limelem
= NULL
;
1088 if (lxc_config_value_empty(value
))
1089 return lxc_clear_limits(lxc_conf
, key
);
1091 if (strncmp(key
, "lxc.limit.", sizeof("lxc.limit.") - 1) != 0)
1094 key
+= sizeof("lxc.limit.") - 1;
1096 /* soft limit comes first in the value */
1097 if (!parse_limit_value(&value
, &limit_value
))
1099 limit
.rlim_cur
= limit_value
;
1101 /* skip spaces and a colon */
1102 while (isspace(*value
))
1107 else if (*value
) /* any other character is an error here */
1110 while (isspace(*value
))
1113 /* optional hard limit */
1115 if (!parse_limit_value(&value
, &limit_value
))
1117 limit
.rlim_max
= limit_value
;
1119 /* check for trailing garbage */
1120 while (isspace(*value
))
1126 /* a single value sets both hard and soft limit */
1127 limit
.rlim_max
= limit
.rlim_cur
;
1130 /* find existing list element */
1131 lxc_list_for_each(iter
, &lxc_conf
->limits
)
1133 limelem
= iter
->elem
;
1134 if (!strcmp(key
, limelem
->resource
)) {
1135 limelem
->limit
= limit
;
1140 /* allocate list element */
1141 limlist
= malloc(sizeof(*limlist
));
1145 limelem
= malloc(sizeof(*limelem
));
1148 memset(limelem
, 0, sizeof(*limelem
));
1150 limelem
->resource
= strdup(key
);
1151 if (!limelem
->resource
)
1153 limelem
->limit
= limit
;
1155 limlist
->elem
= limelem
;
1157 lxc_list_add_tail(&lxc_conf
->limits
, limlist
);
1164 free(limelem
->resource
);
1171 * If you ask for a specific value, i.e. lxc.limit.nofile, then just the value
1172 * will be printed. If you ask for 'lxc.limit', then all limit entries will be
1173 * printed, in 'lxc.limit.resource = value' format.
1175 extern int get_config_limit(const char *key
, char *retv
, int inlen
,
1176 struct lxc_conf
*c
, void *data
)
1178 int fulllen
= 0, len
;
1179 bool get_all
= false;
1180 struct lxc_list
*it
;
1185 memset(retv
, 0, inlen
);
1187 if (!strcmp(key
, "lxc.limit"))
1189 else if (strncmp(key
, "lxc.limit.", 10) == 0)
1194 lxc_list_for_each(it
, &c
->limits
) {
1195 char buf
[LXC_NUMSTRLEN64
* 2 + 2]; /* 2 colon separated 64 bit
1196 integers or the word
1199 struct lxc_limit
*lim
= it
->elem
;
1201 if (lim
->limit
.rlim_cur
== RLIM_INFINITY
) {
1202 memcpy(buf
, "unlimited", sizeof("unlimited"));
1203 partlen
= sizeof("unlimited") - 1;
1205 partlen
= sprintf(buf
, "%" PRIu64
,
1206 (uint64_t)lim
->limit
.rlim_cur
);
1208 if (lim
->limit
.rlim_cur
!= lim
->limit
.rlim_max
) {
1209 if (lim
->limit
.rlim_max
== RLIM_INFINITY
) {
1210 memcpy(buf
+ partlen
, ":unlimited",
1211 sizeof(":unlimited"));
1213 sprintf(buf
+ partlen
, ":%" PRIu64
,
1214 (uint64_t)lim
->limit
.rlim_max
);
1219 strprint(retv
, inlen
, "lxc.limit.%s = %s\n",
1220 lim
->resource
, buf
);
1221 } else if (strcmp(lim
->resource
, key
) == 0) {
1222 strprint(retv
, inlen
, "%s", buf
);
1229 extern int clr_config_limit(const char *key
, struct lxc_conf
*c
,
1232 return lxc_clear_limits(c
, key
);