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
27 #include <arpa/inet.h>
31 #include <linux/netlink.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/sockios.h>
34 #include <net/ethernet.h>
36 #include <net/if_arp.h>
37 #include <netinet/in.h>
41 #include <sys/inotify.h>
42 #include <sys/ioctl.h>
43 #include <sys/param.h>
44 #include <sys/socket.h>
46 #include <sys/types.h>
50 #include "../include/netns_ifaddrs.h"
54 #include "file_utils.h"
57 #include "memory_utils.h"
60 #include "raw_syscalls.h"
61 #include "syscall_wrappers.h"
65 #include "include/strlcpy.h"
68 lxc_log_define(network
, lxc
);
70 typedef int (*instantiate_cb
)(struct lxc_handler
*, struct lxc_netdev
*);
72 static int lxc_ip_route_dest_add(int family
, int ifindex
, void *dest
, unsigned int netmask
)
75 struct nl_handler nlh
;
77 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
79 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
80 : sizeof(struct in6_addr
);
82 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
87 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
91 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
95 nlmsg
->nlmsghdr
->nlmsg_flags
=
96 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
97 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
99 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
102 rt
->rtm_family
= family
;
103 rt
->rtm_table
= RT_TABLE_MAIN
;
104 rt
->rtm_scope
= RT_SCOPE_LINK
;
105 rt
->rtm_protocol
= RTPROT_BOOT
;
106 rt
->rtm_type
= RTN_UNICAST
;
107 rt
->rtm_dst_len
= netmask
;
110 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
112 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
114 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
122 static int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
, unsigned int netmask
)
124 return lxc_ip_route_dest_add(AF_INET
, ifindex
, dest
, netmask
);
127 static int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
, unsigned int netmask
)
129 return lxc_ip_route_dest_add(AF_INET6
, ifindex
, dest
, netmask
);
132 static int lxc_setup_ipv4_routes(struct lxc_list
*ip
, int ifindex
)
134 struct lxc_list
*iterator
;
137 lxc_list_for_each(iterator
, ip
) {
138 struct lxc_inetdev
*inetdev
= iterator
->elem
;
140 err
= lxc_ipv4_dest_add(ifindex
, &inetdev
->addr
, inetdev
->prefix
);
142 SYSERROR("Failed to setup ipv4 route for network device "
143 "with ifindex %d", ifindex
);
144 return minus_one_set_errno(-err
);
151 static int lxc_setup_ipv6_routes(struct lxc_list
*ip
, int ifindex
)
153 struct lxc_list
*iterator
;
156 lxc_list_for_each(iterator
, ip
) {
157 struct lxc_inet6dev
*inet6dev
= iterator
->elem
;
159 err
= lxc_ipv6_dest_add(ifindex
, &inet6dev
->addr
, inet6dev
->prefix
);
161 SYSERROR("Failed to setup ipv6 route for network device "
162 "with ifindex %d", ifindex
);
163 return minus_one_set_errno(-err
);
170 static int instantiate_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
172 int bridge_index
, err
;
174 char veth1buf
[IFNAMSIZ
], veth2buf
[IFNAMSIZ
];
175 unsigned int mtu
= 0;
177 if (netdev
->priv
.veth_attr
.pair
[0] != '\0') {
178 veth1
= netdev
->priv
.veth_attr
.pair
;
179 if (handler
->conf
->reboot
)
180 lxc_netdev_delete_by_name(veth1
);
182 err
= snprintf(veth1buf
, sizeof(veth1buf
), "vethXXXXXX");
183 if (err
< 0 || (size_t)err
>= sizeof(veth1buf
))
186 veth1
= lxc_mkifname(veth1buf
);
190 /* store away for deconf */
191 memcpy(netdev
->priv
.veth_attr
.veth1
, veth1
, IFNAMSIZ
);
194 err
= snprintf(veth2buf
, sizeof(veth2buf
), "vethXXXXXX");
195 if (err
< 0 || (size_t)err
>= sizeof(veth2buf
))
198 veth2
= lxc_mkifname(veth2buf
);
202 err
= lxc_veth_create(veth1
, veth2
);
205 SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1
, veth2
);
209 /* changing the high byte of the mac address to 0xfe, the bridge interface
210 * will always keep the host's mac address and not take the mac address
212 err
= setup_private_host_hw_addr(veth1
);
215 SYSERROR("Failed to change mac address of host interface \"%s\"", veth1
);
219 /* Retrieve ifindex of the host's veth device. */
220 netdev
->priv
.veth_attr
.ifindex
= if_nametoindex(veth1
);
221 if (!netdev
->priv
.veth_attr
.ifindex
) {
222 ERROR("Failed to retrieve ifindex for \"%s\"", veth1
);
226 /* Note that we're retrieving the container's ifindex in the host's
227 * network namespace because we need it to move the device from the
228 * host's network namespace to the container's network namespace later
231 netdev
->ifindex
= if_nametoindex(veth2
);
232 if (!netdev
->ifindex
) {
233 ERROR("Failed to retrieve ifindex for \"%s\"", veth2
);
238 if (lxc_safe_uint(netdev
->mtu
, &mtu
) < 0)
239 WARN("Failed to parse mtu");
241 INFO("Retrieved mtu %d", mtu
);
242 } else if (netdev
->link
[0] != '\0') {
243 bridge_index
= if_nametoindex(netdev
->link
);
245 mtu
= netdev_get_mtu(bridge_index
);
246 INFO("Retrieved mtu %d from %s", mtu
, netdev
->link
);
248 mtu
= netdev_get_mtu(netdev
->ifindex
);
249 INFO("Retrieved mtu %d from %s", mtu
, veth2
);
254 err
= lxc_netdev_set_mtu(veth1
, mtu
);
256 err
= lxc_netdev_set_mtu(veth2
, mtu
);
260 SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
261 "and \"%s\"", mtu
, veth1
, veth2
);
266 if (netdev
->link
[0] != '\0') {
267 err
= lxc_bridge_attach(netdev
->link
, veth1
);
270 SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
271 veth1
, netdev
->link
);
274 INFO("Attached \"%s\" to bridge \"%s\"", veth1
, netdev
->link
);
277 err
= lxc_netdev_up(veth1
);
280 SYSERROR("Failed to set \"%s\" up", veth1
);
284 /* setup ipv4 routes on the host interface */
285 if (lxc_setup_ipv4_routes(&netdev
->priv
.veth_attr
.ipv4_routes
, netdev
->priv
.veth_attr
.ifindex
)) {
286 ERROR("Failed to setup ipv4 routes for network device \"%s\"", veth1
);
290 /* setup ipv6 routes on the host interface */
291 if (lxc_setup_ipv6_routes(&netdev
->priv
.veth_attr
.ipv6_routes
, netdev
->priv
.veth_attr
.ifindex
)) {
292 ERROR("Failed to setup ipv6 routes for network device \"%s\"", veth1
);
296 if (netdev
->upscript
) {
304 err
= run_script_argv(handler
->name
,
305 handler
->conf
->hooks_version
, "net",
306 netdev
->upscript
, "up", argv
);
311 DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1
, veth2
,
317 if (netdev
->ifindex
!= 0)
318 lxc_netdev_delete_by_name(veth1
);
322 static int instantiate_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
324 char peerbuf
[IFNAMSIZ
], *peer
;
327 if (netdev
->link
[0] == '\0') {
328 ERROR("No link for macvlan network device specified");
332 err
= snprintf(peerbuf
, sizeof(peerbuf
), "mcXXXXXX");
333 if (err
< 0 || (size_t)err
>= sizeof(peerbuf
))
336 peer
= lxc_mkifname(peerbuf
);
340 err
= lxc_macvlan_create(netdev
->link
, peer
,
341 netdev
->priv
.macvlan_attr
.mode
);
344 SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
349 netdev
->ifindex
= if_nametoindex(peer
);
350 if (!netdev
->ifindex
) {
351 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
355 if (netdev
->upscript
) {
362 err
= run_script_argv(handler
->name
,
363 handler
->conf
->hooks_version
, "net",
364 netdev
->upscript
, "up", argv
);
369 DEBUG("Instantiated macvlan \"%s\" with ifindex is %d and mode %d",
370 peer
, netdev
->ifindex
, netdev
->priv
.macvlan_attr
.mode
);
375 lxc_netdev_delete_by_name(peer
);
379 static int lxc_ipvlan_create(const char *master
, const char *name
, int mode
, int isolation
)
382 struct ifinfomsg
*ifi
;
383 struct nl_handler nlh
;
384 struct rtattr
*nest
, *nest2
;
385 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
387 len
= strlen(master
);
388 if (len
== 1 || len
>= IFNAMSIZ
)
389 return minus_one_set_errno(EINVAL
);
392 if (len
== 1 || len
>= IFNAMSIZ
)
393 return minus_one_set_errno(EINVAL
);
395 index
= if_nametoindex(master
);
397 return minus_one_set_errno(EINVAL
);
399 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
401 return minus_one_set_errno(-err
);
404 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
408 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
412 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
413 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
415 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
419 ifi
->ifi_family
= AF_UNSPEC
;
422 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
426 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "ipvlan"))
430 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
434 if (nla_put_u32(nlmsg
, IFLA_IPVLAN_MODE
, mode
))
437 /* if_link.h does not define the isolation flag value for bridge mode so we define it as 0
438 * and only send mode if mode >0 as default mode is bridge anyway according to ipvlan docs.
441 if (nla_put_u16(nlmsg
, IFLA_IPVLAN_ISOLATION
, isolation
))
445 nla_end_nested(nlmsg
, nest2
);
448 nla_end_nested(nlmsg
, nest
);
450 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
453 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
456 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
462 return minus_one_set_errno(-err
);
466 static int instantiate_ipvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
468 char peerbuf
[IFNAMSIZ
], *peer
;
471 if (netdev
->link
[0] == '\0') {
472 ERROR("No link for ipvlan network device specified");
476 err
= snprintf(peerbuf
, sizeof(peerbuf
), "ipXXXXXX");
477 if (err
< 0 || (size_t)err
>= sizeof(peerbuf
))
480 peer
= lxc_mkifname(peerbuf
);
484 err
= lxc_ipvlan_create(netdev
->link
, peer
, netdev
->priv
.ipvlan_attr
.mode
, netdev
->priv
.ipvlan_attr
.isolation
);
486 SYSERROR("Failed to create ipvlan interface \"%s\" on \"%s\"", peer
, netdev
->link
);
490 netdev
->ifindex
= if_nametoindex(peer
);
491 if (!netdev
->ifindex
) {
492 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
496 if (netdev
->upscript
) {
503 err
= run_script_argv(handler
->name
,
504 handler
->conf
->hooks_version
, "net",
505 netdev
->upscript
, "up", argv
);
510 DEBUG("Instantiated ipvlan \"%s\" with ifindex is %d and mode %d",
511 peer
, netdev
->ifindex
, netdev
->priv
.macvlan_attr
.mode
);
516 lxc_netdev_delete_by_name(peer
);
520 static int instantiate_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
524 static uint16_t vlan_cntr
= 0;
525 unsigned int mtu
= 0;
527 if (netdev
->link
[0] == '\0') {
528 ERROR("No link for vlan network device specified");
532 err
= snprintf(peer
, sizeof(peer
), "vlan%d-%d", netdev
->priv
.vlan_attr
.vid
, vlan_cntr
++);
533 if (err
< 0 || (size_t)err
>= sizeof(peer
))
536 err
= lxc_vlan_create(netdev
->link
, peer
, netdev
->priv
.vlan_attr
.vid
);
539 SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
544 netdev
->ifindex
= if_nametoindex(peer
);
545 if (!netdev
->ifindex
) {
546 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
547 lxc_netdev_delete_by_name(peer
);
551 if (netdev
->upscript
) {
558 err
= run_script_argv(handler
->name
,
559 handler
->conf
->hooks_version
, "net",
560 netdev
->upscript
, "up", argv
);
562 lxc_netdev_delete_by_name(peer
);
567 DEBUG("Instantiated vlan \"%s\" with ifindex is \"%d\" (vlan1000)",
568 peer
, netdev
->ifindex
);
570 if (lxc_safe_uint(netdev
->mtu
, &mtu
) < 0) {
571 ERROR("Failed to retrieve mtu from \"%d\"/\"%s\".",
573 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)");
577 err
= lxc_netdev_set_mtu(peer
, mtu
);
580 SYSERROR("Failed to set mtu \"%s\" for \"%s\"",
582 lxc_netdev_delete_by_name(peer
);
590 static int instantiate_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
599 if (netdev
->link
[0] == '\0') {
600 ERROR("No link for physical interface specified");
604 /* Note that we're retrieving the container's ifindex in the host's
605 * network namespace because we need it to move the device from the
606 * host's network namespace to the container's network namespace later
608 * Note that netdev->link will contain the name of the physical network
609 * device in the host's namespace.
611 netdev
->ifindex
= if_nametoindex(netdev
->link
);
612 if (!netdev
->ifindex
) {
613 ERROR("Failed to retrieve ifindex for \"%s\"", netdev
->link
);
617 /* Store the ifindex of the host's network device in the host's
620 netdev
->priv
.phys_attr
.ifindex
= netdev
->ifindex
;
622 if (!netdev
->upscript
)
625 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
626 "net", netdev
->upscript
, "up", argv
);
633 static int instantiate_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
642 if (!netdev
->upscript
)
645 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
646 "net", netdev
->upscript
, "up", argv
);
653 static int instantiate_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
659 static instantiate_cb netdev_conf
[LXC_NET_MAXCONFTYPE
+ 1] = {
660 [LXC_NET_VETH
] = instantiate_veth
,
661 [LXC_NET_MACVLAN
] = instantiate_macvlan
,
662 [LXC_NET_IPVLAN
] = instantiate_ipvlan
,
663 [LXC_NET_VLAN
] = instantiate_vlan
,
664 [LXC_NET_PHYS
] = instantiate_phys
,
665 [LXC_NET_EMPTY
] = instantiate_empty
,
666 [LXC_NET_NONE
] = instantiate_none
,
669 static int shutdown_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
679 if (!netdev
->downscript
)
682 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
683 argv
[2] = netdev
->priv
.veth_attr
.pair
;
685 argv
[2] = netdev
->priv
.veth_attr
.veth1
;
687 ret
= run_script_argv(handler
->name
,
688 handler
->conf
->hooks_version
, "net",
689 netdev
->downscript
, "down", argv
);
696 static int shutdown_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
705 if (!netdev
->downscript
)
708 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
709 "net", netdev
->downscript
, "down", argv
);
716 static int shutdown_ipvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
725 if (!netdev
->downscript
)
728 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
729 "net", netdev
->downscript
, "down", argv
);
736 static int shutdown_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
745 if (!netdev
->downscript
)
748 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
749 "net", netdev
->downscript
, "down", argv
);
756 static int shutdown_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
765 if (!netdev
->downscript
)
768 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
769 "net", netdev
->downscript
, "down", argv
);
776 static int shutdown_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
784 if (!netdev
->downscript
)
787 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
788 "net", netdev
->downscript
, "down", argv
);
795 static int shutdown_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
800 static instantiate_cb netdev_deconf
[LXC_NET_MAXCONFTYPE
+ 1] = {
801 [LXC_NET_VETH
] = shutdown_veth
,
802 [LXC_NET_MACVLAN
] = shutdown_macvlan
,
803 [LXC_NET_IPVLAN
] = shutdown_ipvlan
,
804 [LXC_NET_VLAN
] = shutdown_vlan
,
805 [LXC_NET_PHYS
] = shutdown_phys
,
806 [LXC_NET_EMPTY
] = shutdown_empty
,
807 [LXC_NET_NONE
] = shutdown_none
,
810 int lxc_netdev_move_by_index(int ifindex
, pid_t pid
, const char *ifname
)
813 struct nl_handler nlh
;
814 struct ifinfomsg
*ifi
;
815 struct nlmsg
*nlmsg
= NULL
;
817 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
822 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
826 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
827 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
829 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
832 ifi
->ifi_family
= AF_UNSPEC
;
833 ifi
->ifi_index
= ifindex
;
835 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
838 if (ifname
!= NULL
) {
839 if (nla_put_string(nlmsg
, IFLA_IFNAME
, ifname
))
843 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
850 /* If we are asked to move a wireless interface, then we must actually move its
851 * phyN device. Detect that condition and return the physname here. The physname
852 * will be passed to lxc_netdev_move_wlan() which will free it when done.
854 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
855 static char *is_wlan(const char *ifname
)
857 __do_free
char *path
= NULL
;
862 char *physname
= NULL
;
864 len
= strlen(ifname
) + strlen(PHYSNAME
) - 1;
865 path
= must_realloc(NULL
, len
+ 1);
866 ret
= snprintf(path
, len
, PHYSNAME
, ifname
);
867 if (ret
< 0 || (size_t)ret
>= len
)
870 f
= fopen(path
, "r");
874 /* Feh - sb.st_size is always 4096. */
875 fseek(f
, 0, SEEK_END
);
877 fseek(f
, 0, SEEK_SET
);
883 physname
= malloc(physlen
+ 1);
889 memset(physname
, 0, physlen
+ 1);
890 ret
= fread(physname
, 1, physlen
, f
);
895 for (i
= 0; i
< physlen
; i
++) {
896 if (physname
[i
] == '\n')
899 if (physname
[i
] == '\0')
910 static int lxc_netdev_rename_by_name_in_netns(pid_t pid
, const char *old
,
920 return wait_for_pid(fpid
);
922 if (!switch_to_ns(pid
, "net"))
925 _exit(lxc_netdev_rename_by_name(old
, new));
928 static int lxc_netdev_move_wlan(char *physname
, const char *ifname
, pid_t pid
,
935 /* Move phyN into the container. TODO - do this using netlink.
936 * However, IIUC this involves a bit more complicated work to talk to
937 * the 80211 module, so for now just call out to iw.
939 cmd
= on_path("iw", NULL
);
950 sprintf(pidstr
, "%d", pid
);
951 execlp("iw", "iw", "phy", physname
, "set", "netns", pidstr
,
956 if (wait_for_pid(fpid
))
961 err
= lxc_netdev_rename_by_name_in_netns(pid
, ifname
, newname
);
968 int lxc_netdev_move_by_name(const char *ifname
, pid_t pid
, const char* newname
)
976 index
= if_nametoindex(ifname
);
980 physname
= is_wlan(ifname
);
982 return lxc_netdev_move_wlan(physname
, ifname
, pid
, newname
);
984 return lxc_netdev_move_by_index(index
, pid
, newname
);
987 int lxc_netdev_delete_by_index(int ifindex
)
990 struct ifinfomsg
*ifi
;
991 struct nl_handler nlh
;
992 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
994 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
999 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1003 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1007 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
1008 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_DELLINK
;
1010 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1013 ifi
->ifi_family
= AF_UNSPEC
;
1014 ifi
->ifi_index
= ifindex
;
1016 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1018 netlink_close(&nlh
);
1024 int lxc_netdev_delete_by_name(const char *name
)
1028 index
= if_nametoindex(name
);
1032 return lxc_netdev_delete_by_index(index
);
1035 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
1038 struct ifinfomsg
*ifi
;
1039 struct nl_handler nlh
;
1040 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1042 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1046 len
= strlen(newname
);
1047 if (len
== 1 || len
>= IFNAMSIZ
)
1051 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1055 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1059 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
1060 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1062 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1065 ifi
->ifi_family
= AF_UNSPEC
;
1066 ifi
->ifi_index
= ifindex
;
1068 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
1071 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1073 netlink_close(&nlh
);
1079 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
1083 len
= strlen(oldname
);
1084 if (len
== 1 || len
>= IFNAMSIZ
)
1087 index
= if_nametoindex(oldname
);
1091 return lxc_netdev_rename_by_index(index
, newname
);
1094 int netdev_set_flag(const char *name
, int flag
)
1096 int err
, index
, len
;
1097 struct ifinfomsg
*ifi
;
1098 struct nl_handler nlh
;
1099 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1101 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1107 if (len
== 1 || len
>= IFNAMSIZ
)
1111 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1115 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1120 index
= if_nametoindex(name
);
1124 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1125 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1127 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1132 ifi
->ifi_family
= AF_UNSPEC
;
1133 ifi
->ifi_index
= index
;
1134 ifi
->ifi_change
|= IFF_UP
;
1135 ifi
->ifi_flags
|= flag
;
1137 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1139 netlink_close(&nlh
);
1145 int netdev_get_flag(const char *name
, int *flag
)
1147 int err
, index
, len
;
1148 struct ifinfomsg
*ifi
;
1149 struct nl_handler nlh
;
1150 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1155 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1161 if (len
== 1 || len
>= IFNAMSIZ
)
1165 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1169 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1174 index
= if_nametoindex(name
);
1178 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
;
1179 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
1181 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1186 ifi
->ifi_family
= AF_UNSPEC
;
1187 ifi
->ifi_index
= index
;
1189 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1193 ifi
= NLMSG_DATA(answer
->nlmsghdr
);
1195 *flag
= ifi
->ifi_flags
;
1197 netlink_close(&nlh
);
1204 * \brief Check a interface is up or not.
1206 * \param name: name for the interface.
1209 * 0 means interface is down.
1210 * 1 means interface is up.
1211 * Others means error happened, and ret-value is the error number.
1213 int lxc_netdev_isup(const char *name
)
1217 err
= netdev_get_flag(name
, &flag
);
1227 int netdev_get_mtu(int ifindex
)
1229 int answer_len
, err
, res
;
1230 struct nl_handler nlh
;
1231 struct ifinfomsg
*ifi
;
1232 struct nlmsghdr
*msg
;
1233 int readmore
= 0, recv_len
= 0;
1234 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1236 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1241 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1245 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1249 /* Save the answer buffer length, since it will be overwritten
1250 * on the first receive (and we might need to receive more than
1253 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1255 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
1256 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
1258 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1261 ifi
->ifi_family
= AF_UNSPEC
;
1263 /* Send the request for addresses, which returns all addresses
1264 * on all interfaces. */
1265 err
= netlink_send(&nlh
, nlmsg
);
1269 #pragma GCC diagnostic push
1270 #pragma GCC diagnostic ignored "-Wcast-align"
1273 /* Restore the answer buffer length, it might have been
1274 * overwritten by a previous receive.
1276 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1278 /* Get the (next) batch of reply messages */
1279 err
= netlink_rcv(&nlh
, answer
);
1285 /* Satisfy the typing for the netlink macros */
1286 msg
= answer
->nlmsghdr
;
1288 while (NLMSG_OK(msg
, recv_len
)) {
1290 /* Stop reading if we see an error message */
1291 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1292 struct nlmsgerr
*errmsg
=
1293 (struct nlmsgerr
*)NLMSG_DATA(msg
);
1294 err
= errmsg
->error
;
1298 /* Stop reading if we see a NLMSG_DONE message */
1299 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1304 ifi
= NLMSG_DATA(msg
);
1305 if (ifi
->ifi_index
== ifindex
) {
1306 struct rtattr
*rta
= IFLA_RTA(ifi
);
1308 msg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
1310 while (RTA_OK(rta
, attr_len
)) {
1311 /* Found a local address for the
1312 * requested interface, return it.
1314 if (rta
->rta_type
== IFLA_MTU
) {
1315 memcpy(&res
, RTA_DATA(rta
),
1320 rta
= RTA_NEXT(rta
, attr_len
);
1324 /* Keep reading more data from the socket if the last
1325 * message had the NLF_F_MULTI flag set.
1327 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1329 /* Look at the next message received in this buffer. */
1330 msg
= NLMSG_NEXT(msg
, recv_len
);
1334 #pragma GCC diagnostic pop
1336 /* If we end up here, we didn't find any result, so signal an error. */
1340 netlink_close(&nlh
);
1346 int lxc_netdev_set_mtu(const char *name
, int mtu
)
1348 int err
, index
, len
;
1349 struct ifinfomsg
*ifi
;
1350 struct nl_handler nlh
;
1351 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1353 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1359 if (len
== 1 || len
>= IFNAMSIZ
)
1363 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1367 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1372 index
= if_nametoindex(name
);
1376 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1377 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1379 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1384 ifi
->ifi_family
= AF_UNSPEC
;
1385 ifi
->ifi_index
= index
;
1387 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
1390 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1392 netlink_close(&nlh
);
1398 int lxc_netdev_up(const char *name
)
1400 return netdev_set_flag(name
, IFF_UP
);
1403 int lxc_netdev_down(const char *name
)
1405 return netdev_set_flag(name
, 0);
1408 int lxc_veth_create(const char *name1
, const char *name2
)
1411 struct ifinfomsg
*ifi
;
1412 struct nl_handler nlh
;
1413 struct rtattr
*nest1
, *nest2
, *nest3
;
1414 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1416 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1421 len
= strlen(name1
);
1422 if (len
== 1 || len
>= IFNAMSIZ
)
1425 len
= strlen(name2
);
1426 if (len
== 1 || len
>= IFNAMSIZ
)
1430 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1434 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1438 nlmsg
->nlmsghdr
->nlmsg_flags
=
1439 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1440 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1442 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1445 ifi
->ifi_family
= AF_UNSPEC
;
1448 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1452 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
1455 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1459 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
1463 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1469 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
1472 nla_end_nested(nlmsg
, nest3
);
1473 nla_end_nested(nlmsg
, nest2
);
1474 nla_end_nested(nlmsg
, nest1
);
1476 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
1479 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1481 netlink_close(&nlh
);
1487 /* TODO: merge with lxc_macvlan_create */
1488 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
1490 int err
, len
, lindex
;
1491 struct ifinfomsg
*ifi
;
1492 struct nl_handler nlh
;
1493 struct rtattr
*nest
, *nest2
;
1494 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1496 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1501 len
= strlen(master
);
1502 if (len
== 1 || len
>= IFNAMSIZ
)
1506 if (len
== 1 || len
>= IFNAMSIZ
)
1510 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1514 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1519 lindex
= if_nametoindex(master
);
1523 nlmsg
->nlmsghdr
->nlmsg_flags
=
1524 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1525 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1527 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1532 ifi
->ifi_family
= AF_UNSPEC
;
1534 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1538 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
1541 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1545 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
1548 nla_end_nested(nlmsg
, nest2
);
1549 nla_end_nested(nlmsg
, nest
);
1551 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
1554 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1557 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1563 netlink_close(&nlh
);
1567 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
1569 int err
, index
, len
;
1570 struct ifinfomsg
*ifi
;
1571 struct nl_handler nlh
;
1572 struct rtattr
*nest
, *nest2
;
1573 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1575 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1580 len
= strlen(master
);
1581 if (len
== 1 || len
>= IFNAMSIZ
)
1585 if (len
== 1 || len
>= IFNAMSIZ
)
1589 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1593 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1598 index
= if_nametoindex(master
);
1602 nlmsg
->nlmsghdr
->nlmsg_flags
=
1603 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1604 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1606 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1611 ifi
->ifi_family
= AF_UNSPEC
;
1613 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1617 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
1621 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1625 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
1628 nla_end_nested(nlmsg
, nest2
);
1631 nla_end_nested(nlmsg
, nest
);
1633 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
1636 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1639 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1641 netlink_close(&nlh
);
1647 static int proc_sys_net_write(const char *path
, const char *value
)
1652 fd
= open(path
, O_WRONLY
);
1656 if (lxc_write_nointr(fd
, value
, strlen(value
)) < 0)
1663 static int lxc_is_ip_forwarding_enabled(const char *ifname
, int family
)
1666 char path
[PATH_MAX
];
1669 if (family
!= AF_INET
&& family
!= AF_INET6
)
1670 return minus_one_set_errno(EINVAL
);
1672 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1673 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1675 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1676 return minus_one_set_errno(E2BIG
);
1678 return lxc_read_file_expect(path
, buf
, 1, "1");
1681 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
1684 char path
[PATH_MAX
];
1686 if (family
!= AF_INET
&& family
!= AF_INET6
)
1689 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1690 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1691 family
== AF_INET
? "proxy_arp" : "proxy_ndp");
1692 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1695 return proc_sys_net_write(path
, flag
? "1" : "0");
1698 static int lxc_is_ip_neigh_proxy_enabled(const char *ifname
, int family
)
1701 char path
[PATH_MAX
];
1704 if (family
!= AF_INET
&& family
!= AF_INET6
)
1705 return minus_one_set_errno(EINVAL
);
1707 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1708 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1709 family
== AF_INET
? "proxy_arp" : "proxy_ndp");
1710 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1711 return minus_one_set_errno(E2BIG
);
1713 return lxc_read_file_expect(path
, buf
, 1, "1");
1716 int lxc_neigh_proxy_on(const char *name
, int family
)
1718 return neigh_proxy_set(name
, family
, 1);
1721 int lxc_neigh_proxy_off(const char *name
, int family
)
1723 return neigh_proxy_set(name
, family
, 0);
1726 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
1731 unsigned char *data
;
1733 sockaddr
->sa_family
= ARPHRD_ETHER
;
1734 data
= (unsigned char *)sockaddr
->sa_data
;
1736 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
1740 else if (c
>= 'a' && c
<= 'f')
1742 else if (c
>= 'A' && c
<= 'F')
1751 else if (c
>= 'a' && c
<= 'f')
1752 val
|= c
- 'a' + 10;
1753 else if (c
>= 'A' && c
<= 'F')
1754 val
|= c
- 'A' + 10;
1755 else if (c
== ':' || c
== 0)
1761 *data
++ = (unsigned char)(val
& 0377);
1764 if (*macaddr
== ':')
1771 static int ip_addr_add(int family
, int ifindex
, void *addr
, void *bcast
,
1772 void *acast
, int prefix
)
1775 struct ifaddrmsg
*ifa
;
1776 struct nl_handler nlh
;
1777 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1779 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1780 : sizeof(struct in6_addr
);
1782 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1787 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1791 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1795 nlmsg
->nlmsghdr
->nlmsg_flags
=
1796 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
1797 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWADDR
;
1799 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1802 ifa
->ifa_prefixlen
= prefix
;
1803 ifa
->ifa_index
= ifindex
;
1804 ifa
->ifa_family
= family
;
1808 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
1811 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
1814 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
1817 /* TODO: multicast, anycast with ipv6 */
1818 err
= -EPROTONOSUPPORT
;
1819 if (family
== AF_INET6
&&
1820 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
1821 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
1824 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1826 netlink_close(&nlh
);
1832 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
1833 struct in6_addr
*mcast
, struct in6_addr
*acast
,
1836 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
1839 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
, struct in_addr
*bcast
,
1842 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
1845 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
1846 * the given RTM_NEWADDR message. Allocates memory for the address and stores
1847 * that pointer in *res (so res should be an in_addr** or in6_addr**).
1849 #pragma GCC diagnostic push
1850 #pragma GCC diagnostic ignored "-Wcast-align"
1852 static int ifa_get_local_ip(int family
, struct nlmsghdr
*msg
, void **res
)
1855 struct ifaddrmsg
*ifa
= NLMSG_DATA(msg
);
1856 struct rtattr
*rta
= IFA_RTA(ifa
);
1857 int attr_len
= NLMSG_PAYLOAD(msg
, sizeof(struct ifaddrmsg
));
1859 if (ifa
->ifa_family
!= family
)
1862 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1863 : sizeof(struct in6_addr
);
1865 /* Loop over the rtattr's in this message */
1866 while (RTA_OK(rta
, attr_len
)) {
1867 /* Found a local address for the requested interface,
1870 if (rta
->rta_type
== IFA_LOCAL
||
1871 rta
->rta_type
== IFA_ADDRESS
) {
1872 /* Sanity check. The family check above should make sure
1873 * the address length is correct, but check here just in
1876 if (RTA_PAYLOAD(rta
) != addrlen
)
1879 /* We might have found an IFA_ADDRESS before, which we
1880 * now overwrite with an IFA_LOCAL.
1883 *res
= malloc(addrlen
);
1888 memcpy(*res
, RTA_DATA(rta
), addrlen
);
1889 if (rta
->rta_type
== IFA_LOCAL
)
1892 rta
= RTA_NEXT(rta
, attr_len
);
1897 #pragma GCC diagnostic pop
1899 static int ip_addr_get(int family
, int ifindex
, void **res
)
1901 int answer_len
, err
;
1902 struct ifaddrmsg
*ifa
;
1903 struct nl_handler nlh
;
1904 struct nlmsghdr
*msg
;
1905 int readmore
= 0, recv_len
= 0;
1906 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1908 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1913 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1917 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1921 /* Save the answer buffer length, since it will be overwritten on the
1922 * first receive (and we might need to receive more than once).
1924 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1926 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ROOT
;
1927 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETADDR
;
1929 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1932 ifa
->ifa_family
= family
;
1934 /* Send the request for addresses, which returns all addresses on all
1937 err
= netlink_send(&nlh
, nlmsg
);
1941 #pragma GCC diagnostic push
1942 #pragma GCC diagnostic ignored "-Wcast-align"
1945 /* Restore the answer buffer length, it might have been
1946 * overwritten by a previous receive.
1948 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1950 /* Get the (next) batch of reply messages. */
1951 err
= netlink_rcv(&nlh
, answer
);
1958 /* Satisfy the typing for the netlink macros. */
1959 msg
= answer
->nlmsghdr
;
1961 while (NLMSG_OK(msg
, recv_len
)) {
1962 /* Stop reading if we see an error message. */
1963 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1964 struct nlmsgerr
*errmsg
=
1965 (struct nlmsgerr
*)NLMSG_DATA(msg
);
1966 err
= errmsg
->error
;
1970 /* Stop reading if we see a NLMSG_DONE message. */
1971 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1976 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
1981 ifa
= (struct ifaddrmsg
*)NLMSG_DATA(msg
);
1982 if (ifa
->ifa_index
== ifindex
) {
1983 if (ifa_get_local_ip(family
, msg
, res
) < 0) {
1988 /* Found a result, stop searching. */
1993 /* Keep reading more data from the socket if the last
1994 * message had the NLF_F_MULTI flag set.
1996 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1998 /* Look at the next message received in this buffer. */
1999 msg
= NLMSG_NEXT(msg
, recv_len
);
2003 #pragma GCC diagnostic pop
2005 /* If we end up here, we didn't find any result, so signal an
2011 netlink_close(&nlh
);
2017 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
2019 return ip_addr_get(AF_INET6
, ifindex
, (void **)res
);
2022 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
**res
)
2024 return ip_addr_get(AF_INET
, ifindex
, (void **)res
);
2027 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
2030 struct nl_handler nlh
;
2032 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
2034 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
2035 : sizeof(struct in6_addr
);
2037 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
2042 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
2046 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
2050 nlmsg
->nlmsghdr
->nlmsg_flags
=
2051 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
2052 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
2054 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
2057 rt
->rtm_family
= family
;
2058 rt
->rtm_table
= RT_TABLE_MAIN
;
2059 rt
->rtm_scope
= RT_SCOPE_UNIVERSE
;
2060 rt
->rtm_protocol
= RTPROT_BOOT
;
2061 rt
->rtm_type
= RTN_UNICAST
;
2062 /* "default" destination */
2063 rt
->rtm_dst_len
= 0;
2066 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
2069 /* Adding the interface index enables the use of link-local
2070 * addresses for the gateway.
2072 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
2075 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
2077 netlink_close(&nlh
);
2083 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
2085 return ip_gateway_add(AF_INET
, ifindex
, gw
);
2088 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
2090 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
2092 bool is_ovs_bridge(const char *bridge
)
2096 char brdirname
[22 + IFNAMSIZ
+ 1] = {0};
2098 ret
= snprintf(brdirname
, 22 + IFNAMSIZ
+ 1, "/sys/class/net/%s/bridge",
2100 if (ret
< 0 || (size_t)ret
>= 22 + IFNAMSIZ
+ 1)
2103 ret
= stat(brdirname
, &sb
);
2104 if (ret
< 0 && errno
== ENOENT
)
2110 struct ovs_veth_args
{
2115 /* Called from a background thread - when nic goes away, remove it from the
2118 static int lxc_ovs_delete_port_exec(void *data
)
2120 struct ovs_veth_args
*args
= data
;
2122 execlp("ovs-vsctl", "ovs-vsctl", "del-port", args
->bridge
, args
->nic
,
2127 int lxc_ovs_delete_port(const char *bridge
, const char *nic
)
2130 char cmd_output
[PATH_MAX
];
2131 struct ovs_veth_args args
;
2133 args
.bridge
= bridge
;
2135 ret
= run_command(cmd_output
, sizeof(cmd_output
),
2136 lxc_ovs_delete_port_exec
, (void *)&args
);
2138 ERROR("Failed to delete \"%s\" from openvswitch bridge \"%s\": "
2139 "%s", bridge
, nic
, cmd_output
);
2146 static int lxc_ovs_attach_bridge_exec(void *data
)
2148 struct ovs_veth_args
*args
= data
;
2150 execlp("ovs-vsctl", "ovs-vsctl", "add-port", args
->bridge
, args
->nic
,
2155 static int lxc_ovs_attach_bridge(const char *bridge
, const char *nic
)
2158 char cmd_output
[PATH_MAX
];
2159 struct ovs_veth_args args
;
2161 args
.bridge
= bridge
;
2163 ret
= run_command(cmd_output
, sizeof(cmd_output
),
2164 lxc_ovs_attach_bridge_exec
, (void *)&args
);
2166 ERROR("Failed to attach \"%s\" to openvswitch bridge \"%s\": %s",
2167 bridge
, nic
, cmd_output
);
2174 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
2180 if (strlen(ifname
) >= IFNAMSIZ
)
2183 index
= if_nametoindex(ifname
);
2187 if (is_ovs_bridge(bridge
))
2188 return lxc_ovs_attach_bridge(bridge
, ifname
);
2190 fd
= socket(AF_INET
, SOCK_STREAM
| SOCK_CLOEXEC
, 0);
2194 retlen
= strlcpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
);
2195 if (retlen
>= IFNAMSIZ
) {
2200 ifr
.ifr_name
[IFNAMSIZ
- 1] = '\0';
2201 ifr
.ifr_ifindex
= index
;
2202 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
2210 static const char *const lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
2211 [LXC_NET_EMPTY
] = "empty",
2212 [LXC_NET_VETH
] = "veth",
2213 [LXC_NET_MACVLAN
] = "macvlan",
2214 [LXC_NET_IPVLAN
] = "ipvlan",
2215 [LXC_NET_PHYS
] = "phys",
2216 [LXC_NET_VLAN
] = "vlan",
2217 [LXC_NET_NONE
] = "none",
2220 const char *lxc_net_type_to_str(int type
)
2222 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
2225 return lxc_network_types
[type
];
2228 static const char padchar
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2230 char *lxc_mkifname(char *template)
2233 struct netns_ifaddrs
*ifa
, *ifaddr
;
2234 char name
[IFNAMSIZ
];
2235 bool exists
= false;
2240 seed
= randseed(false);
2243 (void)randseed(true);
2246 if (strlen(template) >= IFNAMSIZ
)
2249 /* Get all the network interfaces. */
2250 ret
= netns_getifaddrs(&ifaddr
, -1, &(bool){false});
2252 SYSERROR("Failed to get network interfaces");
2256 /* Generate random names until we find one that doesn't exist. */
2259 (void)strlcpy(name
, template, IFNAMSIZ
);
2263 for (i
= 0; i
< strlen(name
); i
++) {
2264 if (name
[i
] == 'X') {
2266 name
[i
] = padchar
[rand_r(&seed
) % strlen(padchar
)];
2268 name
[i
] = padchar
[rand() % strlen(padchar
)];
2273 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
2274 if (!strcmp(ifa
->ifa_name
, name
)) {
2284 netns_freeifaddrs(ifaddr
);
2285 (void)strlcpy(template, name
, strlen(template) + 1);
2290 int setup_private_host_hw_addr(char *veth1
)
2295 sockfd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0);
2299 err
= snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
2300 if (err
< 0 || (size_t)err
>= IFNAMSIZ
) {
2305 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
2311 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
2312 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);
2320 int lxc_find_gateway_addresses(struct lxc_handler
*handler
)
2322 struct lxc_list
*network
= &handler
->conf
->network
;
2323 struct lxc_list
*iterator
;
2324 struct lxc_netdev
*netdev
;
2327 lxc_list_for_each(iterator
, network
) {
2328 netdev
= iterator
->elem
;
2330 if (!netdev
->ipv4_gateway_auto
&& !netdev
->ipv6_gateway_auto
)
2333 if (netdev
->type
!= LXC_NET_VETH
&& netdev
->type
!= LXC_NET_MACVLAN
) {
2334 ERROR("Automatic gateway detection is only supported "
2335 "for veth and macvlan");
2339 if (netdev
->link
[0] == '\0') {
2340 ERROR("Automatic gateway detection needs a link interface");
2344 link_index
= if_nametoindex(netdev
->link
);
2348 if (netdev
->ipv4_gateway_auto
) {
2349 if (lxc_ipv4_addr_get(link_index
, &netdev
->ipv4_gateway
)) {
2350 ERROR("Failed to automatically find ipv4 gateway "
2351 "address from link interface \"%s\"", netdev
->link
);
2356 if (netdev
->ipv6_gateway_auto
) {
2357 if (lxc_ipv6_addr_get(link_index
, &netdev
->ipv6_gateway
)) {
2358 ERROR("Failed to automatically find ipv6 gateway "
2359 "address from link interface \"%s\"", netdev
->link
);
2368 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
2369 static int lxc_create_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2370 struct lxc_netdev
*netdev
, pid_t pid
, unsigned int hooks_version
)
2374 int bytes
, pipefd
[2];
2375 char *token
, *saveptr
= NULL
;
2376 char netdev_link
[IFNAMSIZ
];
2377 char buffer
[PATH_MAX
] = {0};
2380 if (netdev
->type
!= LXC_NET_VETH
) {
2381 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2387 SYSERROR("Failed to create pipe");
2393 SYSERROR("Failed to create new process");
2400 char pidstr
[INTTYPE_TO_STRLEN(pid_t
)];
2404 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2406 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2409 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2410 _exit(EXIT_FAILURE
);
2413 if (netdev
->link
[0] != '\0')
2414 retlen
= strlcpy(netdev_link
, netdev
->link
, IFNAMSIZ
);
2416 retlen
= strlcpy(netdev_link
, "none", IFNAMSIZ
);
2417 if (retlen
>= IFNAMSIZ
) {
2418 SYSERROR("Invalid network device name");
2419 _exit(EXIT_FAILURE
);
2422 ret
= snprintf(pidstr
, sizeof(pidstr
), "%d", pid
);
2423 if (ret
< 0 || ret
>= sizeof(pidstr
))
2424 _exit(EXIT_FAILURE
);
2425 pidstr
[sizeof(pidstr
) - 1] = '\0';
2427 INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath
,
2428 lxcname
, pidstr
, netdev_link
,
2429 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)");
2430 if (netdev
->name
[0] != '\0')
2431 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2432 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2433 netdev
->name
, (char *)NULL
);
2435 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2436 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2438 SYSERROR("Failed to execute lxc-user-nic");
2439 _exit(EXIT_FAILURE
);
2442 /* close the write-end of the pipe */
2445 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, PATH_MAX
);
2447 SYSERROR("Failed to read from pipe file descriptor");
2450 buffer
[bytes
- 1] = '\0';
2453 ret
= wait_for_pid(child
);
2455 if (ret
!= 0 || bytes
< 0) {
2456 ERROR("lxc-user-nic failed to configure requested network: %s",
2457 buffer
[0] != '\0' ? buffer
: "(null)");
2460 TRACE("Received output \"%s\" from lxc-user-nic", buffer
);
2463 token
= strtok_r(buffer
, ":", &saveptr
);
2465 ERROR("Failed to parse lxc-user-nic output");
2469 memset(netdev
->name
, 0, IFNAMSIZ
);
2470 memcpy(netdev
->name
, token
, IFNAMSIZ
- 1);
2472 /* netdev->ifindex */
2473 token
= strtok_r(NULL
, ":", &saveptr
);
2475 ERROR("Failed to parse lxc-user-nic output");
2479 ret
= lxc_safe_int(token
, &netdev
->ifindex
);
2482 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2486 /* netdev->priv.veth_attr.veth1 */
2487 token
= strtok_r(NULL
, ":", &saveptr
);
2489 ERROR("Failed to parse lxc-user-nic output");
2493 retlen
= strlcpy(netdev
->priv
.veth_attr
.veth1
, token
, IFNAMSIZ
);
2494 if (retlen
>= IFNAMSIZ
) {
2495 ERROR("Host side veth device name returned by lxc-user-nic is "
2500 /* netdev->priv.veth_attr.ifindex */
2501 token
= strtok_r(NULL
, ":", &saveptr
);
2503 ERROR("Failed to parse lxc-user-nic output");
2507 ret
= lxc_safe_int(token
, &netdev
->priv
.veth_attr
.ifindex
);
2510 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2514 if (netdev
->upscript
) {
2518 netdev
->priv
.veth_attr
.veth1
,
2522 ret
= run_script_argv(lxcname
,
2523 hooks_version
, "net",
2524 netdev
->upscript
, "up", argv
);
2532 static int lxc_delete_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2533 struct lxc_netdev
*netdev
,
2534 const char *netns_path
)
2539 char buffer
[PATH_MAX
] = {0};
2541 if (netdev
->type
!= LXC_NET_VETH
) {
2542 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2548 SYSERROR("Failed to create pipe");
2554 SYSERROR("Failed to create new process");
2565 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2567 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2570 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2571 _exit(EXIT_FAILURE
);
2574 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2575 hostveth
= netdev
->priv
.veth_attr
.pair
;
2577 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2578 if (hostveth
[0] == '\0') {
2579 SYSERROR("Host side veth device name is missing");
2580 _exit(EXIT_FAILURE
);
2583 if (netdev
->link
[0] == '\0') {
2584 SYSERROR("Network link for network device \"%s\" is "
2585 "missing", netdev
->priv
.veth_attr
.veth1
);
2586 _exit(EXIT_FAILURE
);
2589 INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath
,
2590 lxcname
, netns_path
, netdev
->link
, hostveth
);
2591 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "delete", lxcpath
,
2592 lxcname
, netns_path
, "veth", netdev
->link
, hostveth
,
2594 SYSERROR("Failed to exec lxc-user-nic.");
2595 _exit(EXIT_FAILURE
);
2600 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, PATH_MAX
);
2602 SYSERROR("Failed to read from pipe file descriptor.");
2605 buffer
[bytes
- 1] = '\0';
2608 ret
= wait_for_pid(child
);
2610 if (ret
!= 0 || bytes
< 0) {
2611 ERROR("lxc-user-nic failed to delete requested network: %s",
2612 buffer
[0] != '\0' ? buffer
: "(null)");
2619 bool lxc_delete_network_unpriv(struct lxc_handler
*handler
)
2622 struct lxc_list
*iterator
;
2623 struct lxc_list
*network
= &handler
->conf
->network
;
2624 /* strlen("/proc/") = 6
2626 * INTTYPE_TO_STRLEN(pid_t)
2628 * strlen("/fd/") = 4
2630 * INTTYPE_TO_STRLEN(int)
2634 char netns_path
[6 + INTTYPE_TO_STRLEN(pid_t
) + 4 + INTTYPE_TO_STRLEN(int) + 1];
2638 if (handler
->nsfd
[LXC_NS_NET
] < 0) {
2639 DEBUG("Cannot not guarantee safe deletion of network devices. "
2640 "Manual cleanup maybe needed");
2644 ret
= snprintf(netns_path
, sizeof(netns_path
), "/proc/%d/fd/%d",
2645 lxc_raw_getpid(), handler
->nsfd
[LXC_NS_NET
]);
2646 if (ret
< 0 || ret
>= sizeof(netns_path
))
2649 lxc_list_for_each(iterator
, network
) {
2650 char *hostveth
= NULL
;
2651 struct lxc_netdev
*netdev
= iterator
->elem
;
2653 /* We can only delete devices whose ifindex we have. If we don't
2654 * have the index it means that we didn't create it.
2656 if (!netdev
->ifindex
)
2659 if (netdev
->type
== LXC_NET_PHYS
) {
2660 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
,
2663 WARN("Failed to rename interface with index %d "
2664 "to its initial name \"%s\"",
2665 netdev
->ifindex
, netdev
->link
);
2667 TRACE("Renamed interface with index %d to its "
2668 "initial name \"%s\"",
2669 netdev
->ifindex
, netdev
->link
);
2670 goto clear_ifindices
;
2673 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
2675 WARN("Failed to deconfigure network device");
2677 if (netdev
->type
!= LXC_NET_VETH
)
2678 goto clear_ifindices
;
2680 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
))
2681 goto clear_ifindices
;
2683 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2684 hostveth
= netdev
->priv
.veth_attr
.pair
;
2686 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2687 if (hostveth
[0] == '\0')
2688 goto clear_ifindices
;
2690 ret
= lxc_delete_network_unpriv_exec(handler
->lxcpath
,
2691 handler
->name
, netdev
,
2694 WARN("Failed to remove port \"%s\" from openvswitch "
2695 "bridge \"%s\"", hostveth
, netdev
->link
);
2696 goto clear_ifindices
;
2698 INFO("Removed interface \"%s\" from \"%s\"", hostveth
,
2702 /* We need to clear any ifindices we recorded so liblxc won't
2703 * have cached stale data which would cause it to fail on reboot
2704 * we're we don't re-read the on-disk config file.
2706 netdev
->ifindex
= 0;
2707 if (netdev
->type
== LXC_NET_PHYS
) {
2708 netdev
->priv
.phys_attr
.ifindex
= 0;
2709 } else if (netdev
->type
== LXC_NET_VETH
) {
2710 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
2711 netdev
->priv
.veth_attr
.ifindex
= 0;
2718 struct ip_proxy_args
{
2723 static int lxc_add_ip_neigh_proxy_exec_wrapper(void *data
)
2725 struct ip_proxy_args
*args
= data
;
2727 execlp("ip", "ip", "neigh", "add", "proxy", args
->ip
, "dev", args
->dev
, (char *)NULL
);
2731 static int lxc_del_ip_neigh_proxy_exec_wrapper(void *data
)
2733 struct ip_proxy_args
*args
= data
;
2735 execlp("ip", "ip", "neigh", "flush", "proxy", args
->ip
, "dev", args
->dev
, (char *)NULL
);
2739 static int lxc_add_ip_neigh_proxy(const char *ip
, const char *dev
)
2742 char cmd_output
[PATH_MAX
];
2743 struct ip_proxy_args args
= {
2748 ret
= run_command(cmd_output
, sizeof(cmd_output
), lxc_add_ip_neigh_proxy_exec_wrapper
, &args
);
2750 ERROR("Failed to add ip proxy \"%s\" to dev \"%s\": %s", ip
, dev
, cmd_output
);
2757 static int lxc_del_ip_neigh_proxy(const char *ip
, const char *dev
)
2760 char cmd_output
[PATH_MAX
];
2761 struct ip_proxy_args args
= {
2766 ret
= run_command(cmd_output
, sizeof(cmd_output
), lxc_del_ip_neigh_proxy_exec_wrapper
, &args
);
2768 ERROR("Failed to delete ip proxy \"%s\" to dev \"%s\": %s", ip
, dev
, cmd_output
);
2775 static int lxc_setup_l2proxy(struct lxc_netdev
*netdev
) {
2776 struct lxc_list
*cur
, *next
;
2777 struct lxc_inetdev
*inet4dev
;
2778 struct lxc_inet6dev
*inet6dev
;
2779 char bufinet4
[INET_ADDRSTRLEN
], bufinet6
[INET6_ADDRSTRLEN
];
2781 /* If IPv4 addresses are specified, then check that sysctl is configured correctly. */
2782 if (!lxc_list_empty(&netdev
->ipv4
)) {
2783 /* Check for net.ipv4.conf.[link].forwarding=1 */
2784 if (lxc_is_ip_forwarding_enabled(netdev
->link
, AF_INET
) < 0) {
2785 ERROR("Requires sysctl net.ipv4.conf.%s.forwarding=1", netdev
->link
);
2786 return minus_one_set_errno(EINVAL
);
2790 /* If IPv6 addresses are specified, then check that sysctl is configured correctly. */
2791 if (!lxc_list_empty(&netdev
->ipv6
)) {
2792 /* Check for net.ipv6.conf.[link].proxy_ndp=1 */
2793 if (lxc_is_ip_neigh_proxy_enabled(netdev
->link
, AF_INET6
) < 0) {
2794 ERROR("Requires sysctl net.ipv6.conf.%s.proxy_ndp=1", netdev
->link
);
2795 return minus_one_set_errno(EINVAL
);
2798 /* Check for net.ipv6.conf.[link].forwarding=1 */
2799 if (lxc_is_ip_forwarding_enabled(netdev
->link
, AF_INET6
) < 0) {
2800 ERROR("Requires sysctl net.ipv6.conf.%s.forwarding=1", netdev
->link
);
2801 return minus_one_set_errno(EINVAL
);
2805 lxc_list_for_each_safe(cur
, &netdev
->ipv4
, next
) {
2806 inet4dev
= cur
->elem
;
2807 if (!inet_ntop(AF_INET
, &inet4dev
->addr
, bufinet4
, sizeof(bufinet4
)))
2808 return minus_one_set_errno(-errno
);
2810 if (lxc_add_ip_neigh_proxy(bufinet4
, netdev
->link
) < 0)
2811 return minus_one_set_errno(EINVAL
);
2814 lxc_list_for_each_safe(cur
, &netdev
->ipv6
, next
) {
2815 inet6dev
= cur
->elem
;
2816 if (!inet_ntop(AF_INET6
, &inet6dev
->addr
, bufinet6
, sizeof(bufinet6
)))
2817 return minus_one_set_errno(-errno
);
2819 if (lxc_add_ip_neigh_proxy(bufinet6
, netdev
->link
) < 0)
2820 return minus_one_set_errno(EINVAL
);
2826 static int lxc_delete_l2proxy(struct lxc_netdev
*netdev
) {
2827 struct lxc_list
*cur
, *next
;
2828 struct lxc_inetdev
*inet4dev
;
2829 struct lxc_inet6dev
*inet6dev
;
2830 char bufinet4
[INET_ADDRSTRLEN
], bufinet6
[INET6_ADDRSTRLEN
];
2833 lxc_list_for_each_safe(cur
, &netdev
->ipv4
, next
) {
2834 inet4dev
= cur
->elem
;
2835 if (!inet_ntop(AF_INET
, &inet4dev
->addr
, bufinet4
, sizeof(bufinet4
))) {
2837 SYSERROR("Failed to convert IP for l2proxy removal on dev \"%s\"", netdev
->link
);
2838 continue; /* Try to remove any other l2proxy entries */
2841 if (lxc_del_ip_neigh_proxy(bufinet4
, netdev
->link
) < 0) {
2843 continue; /* Try to remove any other l2proxy entries */
2847 lxc_list_for_each_safe(cur
, &netdev
->ipv6
, next
) {
2848 inet6dev
= cur
->elem
;
2849 if (!inet_ntop(AF_INET6
, &inet6dev
->addr
, bufinet6
, sizeof(bufinet6
))) {
2851 SYSERROR("Failed to convert IP for l2proxy removal on dev \"%s\"", netdev
->link
);
2852 continue; /* Try to remove any other l2proxy entries */
2855 if (lxc_del_ip_neigh_proxy(bufinet6
, netdev
->link
) < 0) {
2857 continue; /* Try to remove any other l2proxy entries */
2862 return minus_one_set_errno(EINVAL
);
2867 int lxc_create_network_priv(struct lxc_handler
*handler
)
2869 struct lxc_list
*iterator
;
2870 struct lxc_list
*network
= &handler
->conf
->network
;
2872 if (!handler
->am_root
)
2875 lxc_list_for_each(iterator
, network
) {
2876 struct lxc_netdev
*netdev
= iterator
->elem
;
2878 if (netdev
->type
< 0 || netdev
->type
> LXC_NET_MAXCONFTYPE
) {
2879 ERROR("Invalid network configuration type %d", netdev
->type
);
2883 /* Setup l2proxy entries if enabled and used with a link property */
2884 if (netdev
->l2proxy
&& netdev
->link
[0] != '\0') {
2885 if (lxc_setup_l2proxy(netdev
)) {
2886 ERROR("Failed to setup l2proxy");
2891 if (netdev_conf
[netdev
->type
](handler
, netdev
)) {
2892 ERROR("Failed to create network device");
2900 int lxc_network_move_created_netdev_priv(const char *lxcpath
, const char *lxcname
,
2901 struct lxc_list
*network
, pid_t pid
)
2904 char ifname
[IFNAMSIZ
];
2905 struct lxc_list
*iterator
;
2907 if (am_guest_unpriv())
2910 lxc_list_for_each(iterator
, network
) {
2911 struct lxc_netdev
*netdev
= iterator
->elem
;
2913 if (!netdev
->ifindex
)
2916 /* retrieve the name of the interface */
2917 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
2918 ERROR("No interface corresponding to ifindex \"%d\"",
2923 ret
= lxc_netdev_move_by_name(ifname
, pid
, NULL
);
2926 SYSERROR("Failed to move network device \"%s\" to "
2927 "network namespace %d", ifname
, pid
);
2931 DEBUG("Moved network device \"%s\"/\"%s\" to network namespace "
2933 ifname
, netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
2940 int lxc_create_network_unpriv(const char *lxcpath
, const char *lxcname
,
2941 struct lxc_list
*network
, pid_t pid
, unsigned int hooks_version
)
2943 struct lxc_list
*iterator
;
2945 if (!am_guest_unpriv())
2948 lxc_list_for_each(iterator
, network
) {
2949 struct lxc_netdev
*netdev
= iterator
->elem
;
2951 if (netdev
->type
== LXC_NET_EMPTY
)
2954 if (netdev
->type
== LXC_NET_NONE
)
2957 if (netdev
->type
!= LXC_NET_VETH
) {
2958 ERROR("Networks of type %s are not supported by "
2959 "unprivileged containers",
2960 lxc_net_type_to_str(netdev
->type
));
2965 INFO("mtu ignored due to insufficient privilege");
2967 if (lxc_create_network_unpriv_exec(lxcpath
, lxcname
, netdev
, pid
, hooks_version
))
2974 bool lxc_delete_network_priv(struct lxc_handler
*handler
)
2977 struct lxc_list
*iterator
;
2978 struct lxc_list
*network
= &handler
->conf
->network
;
2980 lxc_list_for_each(iterator
, network
) {
2981 char *hostveth
= NULL
;
2982 struct lxc_netdev
*netdev
= iterator
->elem
;
2984 /* We can only delete devices whose ifindex we have. If we don't
2985 * have the index it means that we didn't create it.
2987 if (!netdev
->ifindex
)
2990 /* Delete l2proxy entries if enabled and used with a link property */
2991 if (netdev
->l2proxy
&& netdev
->link
[0] != '\0') {
2992 if (lxc_delete_l2proxy(netdev
))
2993 WARN("Failed to delete all l2proxy config");
2994 /* Don't return, let the network be cleaned up as normal. */
2997 if (netdev
->type
== LXC_NET_PHYS
) {
2998 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
, netdev
->link
);
3000 WARN("Failed to rename interface with index %d "
3001 "from \"%s\" to its initial name \"%s\"",
3002 netdev
->ifindex
, netdev
->name
, netdev
->link
);
3004 TRACE("Renamed interface with index %d from "
3005 "\"%s\" to its initial name \"%s\"",
3006 netdev
->ifindex
, netdev
->name
,
3008 goto clear_ifindices
;
3011 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
3013 WARN("Failed to deconfigure network device");
3015 /* Recent kernels remove the virtual interfaces when the network
3016 * namespace is destroyed but in case we did not move the
3017 * interface to the network namespace, we have to destroy it.
3019 ret
= lxc_netdev_delete_by_index(netdev
->ifindex
);
3021 if (errno
!= ENODEV
) {
3022 WARN("Failed to remove interface \"%s\" with index %d",
3023 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3025 goto clear_ifindices
;
3027 INFO("Interface \"%s\" with index %d already deleted or existing in different network namespace",
3028 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3031 INFO("Removed interface \"%s\" with index %d",
3032 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3035 if (netdev
->type
!= LXC_NET_VETH
)
3036 goto clear_ifindices
;
3038 /* Explicitly delete host veth device to prevent lingering
3039 * devices. We had issues in LXD around this.
3041 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
3042 hostveth
= netdev
->priv
.veth_attr
.pair
;
3044 hostveth
= netdev
->priv
.veth_attr
.veth1
;
3045 if (hostveth
[0] == '\0')
3046 goto clear_ifindices
;
3048 ret
= lxc_netdev_delete_by_name(hostveth
);
3050 WARN("Failed to remove interface \"%s\" from \"%s\"",
3051 hostveth
, netdev
->link
);
3052 goto clear_ifindices
;
3054 INFO("Removed interface \"%s\" from \"%s\"", hostveth
, netdev
->link
);
3056 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
)) {
3057 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
3058 netdev
->ifindex
= 0;
3059 netdev
->priv
.veth_attr
.ifindex
= 0;
3060 goto clear_ifindices
;
3063 /* Delete the openvswitch port. */
3064 ret
= lxc_ovs_delete_port(netdev
->link
, hostveth
);
3066 WARN("Failed to remove port \"%s\" from openvswitch "
3067 "bridge \"%s\"", hostveth
, netdev
->link
);
3069 INFO("Removed port \"%s\" from openvswitch bridge \"%s\"",
3070 hostveth
, netdev
->link
);
3073 /* We need to clear any ifindices we recorded so liblxc won't
3074 * have cached stale data which would cause it to fail on reboot
3075 * we're we don't re-read the on-disk config file.
3077 netdev
->ifindex
= 0;
3078 if (netdev
->type
== LXC_NET_PHYS
) {
3079 netdev
->priv
.phys_attr
.ifindex
= 0;
3080 } else if (netdev
->type
== LXC_NET_VETH
) {
3081 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
3082 netdev
->priv
.veth_attr
.ifindex
= 0;
3089 int lxc_requests_empty_network(struct lxc_handler
*handler
)
3091 struct lxc_list
*network
= &handler
->conf
->network
;
3092 struct lxc_list
*iterator
;
3093 bool found_none
= false, found_nic
= false;
3095 if (lxc_list_empty(network
))
3098 lxc_list_for_each(iterator
, network
) {
3099 struct lxc_netdev
*netdev
= iterator
->elem
;
3101 if (netdev
->type
== LXC_NET_NONE
)
3106 if (found_none
&& !found_nic
)
3111 /* try to move physical nics to the init netns */
3112 int lxc_restore_phys_nics_to_netns(struct lxc_handler
*handler
)
3116 char ifname
[IFNAMSIZ
];
3117 struct lxc_list
*iterator
;
3118 int netnsfd
= handler
->nsfd
[LXC_NS_NET
];
3119 struct lxc_conf
*conf
= handler
->conf
;
3121 /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
3122 * the parent network namespace. We won't have this capability if we are
3125 if (!handler
->am_root
)
3128 TRACE("Moving physical network devices back to parent network namespace");
3130 oldfd
= lxc_preserve_ns(lxc_raw_getpid(), "net");
3132 SYSERROR("Failed to preserve network namespace");
3136 ret
= setns(netnsfd
, CLONE_NEWNET
);
3138 SYSERROR("Failed to enter network namespace");
3143 lxc_list_for_each(iterator
, &conf
->network
) {
3144 struct lxc_netdev
*netdev
= iterator
->elem
;
3146 if (netdev
->type
!= LXC_NET_PHYS
)
3149 /* Retrieve the name of the interface in the container's network
3152 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
3153 WARN("No interface corresponding to ifindex %d",
3158 ret
= lxc_netdev_move_by_name(ifname
, 1, netdev
->link
);
3160 WARN("Error moving network device \"%s\" back to "
3161 "network namespace", ifname
);
3163 TRACE("Moved network device \"%s\" back to network "
3164 "namespace", ifname
);
3167 ret
= setns(oldfd
, CLONE_NEWNET
);
3170 SYSERROR("Failed to enter network namespace");
3177 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
3179 struct sockaddr sockaddr
;
3183 ret
= lxc_convert_mac(hwaddr
, &sockaddr
);
3186 SYSERROR("Mac address \"%s\" conversion failed", hwaddr
);
3190 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
3191 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
3192 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
3194 fd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0);
3198 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
3200 SYSERROR("Failed to perform ioctl");
3204 DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr
,
3210 static int setup_ipv4_addr(struct lxc_list
*ip
, int ifindex
)
3212 struct lxc_list
*iterator
;
3215 lxc_list_for_each(iterator
, ip
) {
3216 struct lxc_inetdev
*inetdev
= iterator
->elem
;
3218 err
= lxc_ipv4_addr_add(ifindex
, &inetdev
->addr
,
3219 &inetdev
->bcast
, inetdev
->prefix
);
3222 SYSERROR("Failed to setup ipv4 address for network device "
3223 "with ifindex %d", ifindex
);
3231 static int setup_ipv6_addr(struct lxc_list
*ip
, int ifindex
)
3233 struct lxc_list
*iterator
;
3236 lxc_list_for_each(iterator
, ip
) {
3237 struct lxc_inet6dev
*inet6dev
= iterator
->elem
;
3239 err
= lxc_ipv6_addr_add(ifindex
, &inet6dev
->addr
,
3240 &inet6dev
->mcast
, &inet6dev
->acast
,
3244 SYSERROR("Failed to setup ipv6 address for network device "
3245 "with ifindex %d", ifindex
);
3253 static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev
*netdev
)
3255 char ifname
[IFNAMSIZ
];
3257 const char *net_type_name
;
3258 char *current_ifname
= ifname
;
3260 /* empty network namespace */
3261 if (!netdev
->ifindex
) {
3262 if (netdev
->flags
& IFF_UP
) {
3263 err
= lxc_netdev_up("lo");
3266 SYSERROR("Failed to set the loopback network device up");
3271 if (netdev
->type
== LXC_NET_EMPTY
)
3274 if (netdev
->type
== LXC_NET_NONE
)
3277 if (netdev
->type
!= LXC_NET_VETH
) {
3278 net_type_name
= lxc_net_type_to_str(netdev
->type
);
3279 ERROR("%s networks are not supported for containers "
3280 "not setup up by privileged users", net_type_name
);
3284 netdev
->ifindex
= if_nametoindex(netdev
->name
);
3287 /* get the new ifindex in case of physical netdev */
3288 if (netdev
->type
== LXC_NET_PHYS
) {
3289 netdev
->ifindex
= if_nametoindex(netdev
->link
);
3290 if (!netdev
->ifindex
) {
3291 ERROR("Failed to get ifindex for network device \"%s\"",
3297 /* retrieve the name of the interface */
3298 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
3299 ERROR("Failed get name for network device with ifindex %d",
3304 /* Default: let the system to choose one interface name.
3305 * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
3306 * netlink will replace the format specifier with an appropriate index.
3308 if (netdev
->name
[0] == '\0') {
3309 if (netdev
->type
== LXC_NET_PHYS
)
3310 (void)strlcpy(netdev
->name
, netdev
->link
, IFNAMSIZ
);
3312 (void)strlcpy(netdev
->name
, "eth%d", IFNAMSIZ
);
3315 /* rename the interface name */
3316 if (strcmp(ifname
, netdev
->name
) != 0) {
3317 err
= lxc_netdev_rename_by_name(ifname
, netdev
->name
);
3320 SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
3321 ifname
, netdev
->name
);
3326 /* Re-read the name of the interface because its name has changed
3327 * and would be automatically allocated by the system
3329 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
3330 ERROR("Failed get name for network device with ifindex %d",
3335 /* Now update the recorded name of the network device to reflect the
3336 * name of the network device in the child's network namespace. We will
3337 * later on send this information back to the parent.
3339 (void)strlcpy(netdev
->name
, current_ifname
, IFNAMSIZ
);
3341 /* set a mac address */
3342 if (netdev
->hwaddr
) {
3343 if (setup_hw_addr(netdev
->hwaddr
, current_ifname
)) {
3344 ERROR("Failed to setup hw address for network device \"%s\"",
3350 /* setup ipv4 addresses on the interface */
3351 if (setup_ipv4_addr(&netdev
->ipv4
, netdev
->ifindex
)) {
3352 ERROR("Failed to setup ip addresses for network device \"%s\"",
3357 /* setup ipv6 addresses on the interface */
3358 if (setup_ipv6_addr(&netdev
->ipv6
, netdev
->ifindex
)) {
3359 ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
3364 /* set the network device up */
3365 if (netdev
->flags
& IFF_UP
) {
3366 err
= lxc_netdev_up(current_ifname
);
3369 SYSERROR("Failed to set network device \"%s\" up",
3374 /* the network is up, make the loopback up too */
3375 err
= lxc_netdev_up("lo");
3378 SYSERROR("Failed to set the loopback network device up");
3383 /* We can only set up the default routes after bringing
3384 * up the interface, sine bringing up the interface adds
3385 * the link-local routes and we can't add a default
3386 * route if the gateway is not reachable. */
3388 /* setup ipv4 gateway on the interface */
3389 if (netdev
->ipv4_gateway
) {
3390 if (!(netdev
->flags
& IFF_UP
)) {
3391 ERROR("Cannot add ipv4 gateway for network device "
3392 "\"%s\" when not bringing up the interface", ifname
);
3396 if (lxc_list_empty(&netdev
->ipv4
)) {
3397 ERROR("Cannot add ipv4 gateway for network device "
3398 "\"%s\" when not assigning an address", ifname
);
3402 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
3404 err
= lxc_ipv4_dest_add(netdev
->ifindex
, netdev
->ipv4_gateway
, 32);
3407 SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
3411 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
3414 SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
3417 if (netdev
->ipv4_gateway_auto
) {
3418 char buf
[INET_ADDRSTRLEN
];
3419 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
3420 ERROR("Tried to set autodetected ipv4 gateway \"%s\"", buf
);
3427 /* setup ipv6 gateway on the interface */
3428 if (netdev
->ipv6_gateway
) {
3429 if (!(netdev
->flags
& IFF_UP
)) {
3430 ERROR("Cannot add ipv6 gateway for network device "
3431 "\"%s\" when not bringing up the interface", ifname
);
3435 if (lxc_list_empty(&netdev
->ipv6
) && !IN6_IS_ADDR_LINKLOCAL(netdev
->ipv6_gateway
)) {
3436 ERROR("Cannot add ipv6 gateway for network device "
3437 "\"%s\" when not assigning an address", ifname
);
3441 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3443 err
= lxc_ipv6_dest_add(netdev
->ifindex
, netdev
->ipv6_gateway
, 128);
3446 SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
3450 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3453 SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
3456 if (netdev
->ipv6_gateway_auto
) {
3457 char buf
[INET6_ADDRSTRLEN
];
3458 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
3459 ERROR("Tried to set autodetected ipv6 "
3460 "gateway for network device "
3468 DEBUG("Network device \"%s\" has been setup", current_ifname
);
3473 int lxc_setup_network_in_child_namespaces(const struct lxc_conf
*conf
,
3474 struct lxc_list
*network
)
3476 struct lxc_list
*iterator
;
3477 struct lxc_netdev
*netdev
;
3479 lxc_list_for_each(iterator
, network
) {
3480 netdev
= iterator
->elem
;
3482 if (lxc_setup_netdev_in_child_namespaces(netdev
)) {
3483 ERROR("failed to setup netdev");
3488 if (!lxc_list_empty(network
))
3489 INFO("network has been setup");
3494 int lxc_network_send_veth_names_to_child(struct lxc_handler
*handler
)
3496 struct lxc_list
*iterator
;
3497 struct lxc_list
*network
= &handler
->conf
->network
;
3498 int data_sock
= handler
->data_sock
[0];
3500 if (handler
->am_root
)
3503 lxc_list_for_each(iterator
, network
) {
3505 struct lxc_netdev
*netdev
= iterator
->elem
;
3507 if (netdev
->type
!= LXC_NET_VETH
)
3510 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3513 TRACE("Sent network device name \"%s\" to child", netdev
->name
);
3519 int lxc_network_recv_veth_names_from_parent(struct lxc_handler
*handler
)
3521 struct lxc_list
*iterator
;
3522 struct lxc_list
*network
= &handler
->conf
->network
;
3523 int data_sock
= handler
->data_sock
[1];
3525 if (handler
->am_root
)
3528 lxc_list_for_each(iterator
, network
) {
3530 struct lxc_netdev
*netdev
= iterator
->elem
;
3532 if (netdev
->type
!= LXC_NET_VETH
)
3535 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3538 TRACE("Received network device name \"%s\" from parent", netdev
->name
);
3544 int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler
*handler
)
3546 struct lxc_list
*iterator
, *network
;
3547 int data_sock
= handler
->data_sock
[0];
3549 if (!handler
->am_root
)
3552 network
= &handler
->conf
->network
;
3553 lxc_list_for_each(iterator
, network
) {
3555 struct lxc_netdev
*netdev
= iterator
->elem
;
3557 /* Send network device name in the child's namespace to parent. */
3558 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3562 /* Send network device ifindex in the child's namespace to
3565 ret
= lxc_send_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), MSG_NOSIGNAL
);
3570 TRACE("Sent network device names and ifindices to parent");
3574 int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler
*handler
)
3576 struct lxc_list
*iterator
, *network
;
3577 int data_sock
= handler
->data_sock
[1];
3579 if (!handler
->am_root
)
3582 network
= &handler
->conf
->network
;
3583 lxc_list_for_each(iterator
, network
) {
3585 struct lxc_netdev
*netdev
= iterator
->elem
;
3587 /* Receive network device name in the child's namespace to
3590 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3594 /* Receive network device ifindex in the child's namespace to
3597 ret
= lxc_recv_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), 0);
3605 void lxc_delete_network(struct lxc_handler
*handler
)
3609 if (handler
->am_root
)
3610 bret
= lxc_delete_network_priv(handler
);
3612 bret
= lxc_delete_network_unpriv(handler
);
3614 DEBUG("Failed to delete network devices");
3616 DEBUG("Deleted network devices");
3619 int lxc_netns_set_nsid(int fd
)
3622 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3623 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3625 struct nl_handler nlh
;
3626 struct nlmsghdr
*hdr
;
3627 struct rtgenmsg
*msg
;
3629 const __s32 ns_id
= -1;
3630 const __u32 netns_fd
= fd
;
3632 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3636 memset(buf
, 0, sizeof(buf
));
3638 #pragma GCC diagnostic push
3639 #pragma GCC diagnostic ignored "-Wcast-align"
3640 hdr
= (struct nlmsghdr
*)buf
;
3641 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3642 #pragma GCC diagnostic pop
3644 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3645 hdr
->nlmsg_type
= RTM_NEWNSID
;
3646 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3648 hdr
->nlmsg_seq
= RTM_NEWNSID
;
3649 msg
->rtgen_family
= AF_UNSPEC
;
3651 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3655 ret
= addattr(hdr
, 1024, __LXC_NETNSA_NSID
, &ns_id
, sizeof(ns_id
));
3659 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3662 saved_errno
= errno
;
3663 netlink_close(&nlh
);
3664 errno
= saved_errno
;
3669 static int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
3672 memset(tb
, 0, sizeof(struct rtattr
*) * (max
+ 1));
3674 while (RTA_OK(rta
, len
)) {
3675 unsigned short type
= rta
->rta_type
;
3677 if ((type
<= max
) && (!tb
[type
]))
3680 #pragma GCC diagnostic push
3681 #pragma GCC diagnostic ignored "-Wcast-align"
3682 rta
= RTA_NEXT(rta
, len
);
3683 #pragma GCC diagnostic pop
3689 static inline __s32
rta_getattr_s32(const struct rtattr
*rta
)
3691 return *(__s32
*)RTA_DATA(rta
);
3695 #define NETNS_RTA(r) \
3696 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
3699 int lxc_netns_get_nsid(int fd
)
3703 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3704 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3706 struct rtattr
*tb
[__LXC_NETNSA_MAX
+ 1];
3707 struct nl_handler nlh
;
3708 struct nlmsghdr
*hdr
;
3709 struct rtgenmsg
*msg
;
3711 __u32 netns_fd
= fd
;
3713 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3717 memset(buf
, 0, sizeof(buf
));
3719 #pragma GCC diagnostic push
3720 #pragma GCC diagnostic ignored "-Wcast-align"
3721 hdr
= (struct nlmsghdr
*)buf
;
3722 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3723 #pragma GCC diagnostic pop
3725 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3726 hdr
->nlmsg_type
= RTM_GETNSID
;
3727 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3729 hdr
->nlmsg_seq
= RTM_GETNSID
;
3730 msg
->rtgen_family
= AF_UNSPEC
;
3732 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3734 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3736 saved_errno
= errno
;
3737 netlink_close(&nlh
);
3738 errno
= saved_errno
;
3743 msg
= NLMSG_DATA(hdr
);
3744 len
= hdr
->nlmsg_len
- NLMSG_SPACE(sizeof(*msg
));
3748 #pragma GCC diagnostic push
3749 #pragma GCC diagnostic ignored "-Wcast-align"
3750 parse_rtattr(tb
, __LXC_NETNSA_MAX
, NETNS_RTA(msg
), len
);
3751 if (tb
[__LXC_NETNSA_NSID
])
3752 return rta_getattr_s32(tb
[__LXC_NETNSA_NSID
]);
3753 #pragma GCC diagnostic pop