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
*);
71 static const char loDev
[] = "lo";
73 static int lxc_ip_route_dest(__u16 nlmsg_type
, int family
, int ifindex
, void *dest
, unsigned int netmask
)
76 struct nl_handler nlh
;
78 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
80 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
81 : sizeof(struct in6_addr
);
83 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
88 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
92 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
96 nlmsg
->nlmsghdr
->nlmsg_flags
=
97 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
98 nlmsg
->nlmsghdr
->nlmsg_type
= nlmsg_type
;
100 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
103 rt
->rtm_family
= family
;
104 rt
->rtm_table
= RT_TABLE_MAIN
;
105 rt
->rtm_scope
= RT_SCOPE_LINK
;
106 rt
->rtm_protocol
= RTPROT_BOOT
;
107 rt
->rtm_type
= RTN_UNICAST
;
108 rt
->rtm_dst_len
= netmask
;
111 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
113 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
115 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
123 static int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
, unsigned int netmask
)
125 return lxc_ip_route_dest(RTM_NEWROUTE
, AF_INET
, ifindex
, dest
, netmask
);
128 static int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
, unsigned int netmask
)
130 return lxc_ip_route_dest(RTM_NEWROUTE
, AF_INET6
, ifindex
, dest
, netmask
);
133 static int lxc_ipv4_dest_del(int ifindex
, struct in_addr
*dest
, unsigned int netmask
)
135 return lxc_ip_route_dest(RTM_DELROUTE
, AF_INET
, ifindex
, dest
, netmask
);
138 static int lxc_ipv6_dest_del(int ifindex
, struct in6_addr
*dest
, unsigned int netmask
)
140 return lxc_ip_route_dest(RTM_DELROUTE
, AF_INET6
, ifindex
, dest
, netmask
);
143 static int lxc_setup_ipv4_routes(struct lxc_list
*ip
, int ifindex
)
145 struct lxc_list
*iterator
;
148 lxc_list_for_each(iterator
, ip
) {
149 struct lxc_inetdev
*inetdev
= iterator
->elem
;
151 err
= lxc_ipv4_dest_add(ifindex
, &inetdev
->addr
, inetdev
->prefix
);
153 SYSERROR("Failed to setup ipv4 route for network device "
154 "with ifindex %d", ifindex
);
155 return minus_one_set_errno(-err
);
162 static int lxc_setup_ipv6_routes(struct lxc_list
*ip
, int ifindex
)
164 struct lxc_list
*iterator
;
167 lxc_list_for_each(iterator
, ip
) {
168 struct lxc_inet6dev
*inet6dev
= iterator
->elem
;
170 err
= lxc_ipv6_dest_add(ifindex
, &inet6dev
->addr
, inet6dev
->prefix
);
172 SYSERROR("Failed to setup ipv6 route for network device "
173 "with ifindex %d", ifindex
);
174 return minus_one_set_errno(-err
);
181 static int instantiate_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
183 int bridge_index
, err
;
185 char veth1buf
[IFNAMSIZ
], veth2buf
[IFNAMSIZ
];
186 unsigned int mtu
= 0;
188 if (netdev
->priv
.veth_attr
.pair
[0] != '\0') {
189 veth1
= netdev
->priv
.veth_attr
.pair
;
190 if (handler
->conf
->reboot
)
191 lxc_netdev_delete_by_name(veth1
);
193 err
= snprintf(veth1buf
, sizeof(veth1buf
), "vethXXXXXX");
194 if (err
< 0 || (size_t)err
>= sizeof(veth1buf
))
197 veth1
= lxc_mkifname(veth1buf
);
201 /* store away for deconf */
202 memcpy(netdev
->priv
.veth_attr
.veth1
, veth1
, IFNAMSIZ
);
205 err
= snprintf(veth2buf
, sizeof(veth2buf
), "vethXXXXXX");
206 if (err
< 0 || (size_t)err
>= sizeof(veth2buf
))
209 veth2
= lxc_mkifname(veth2buf
);
213 err
= lxc_veth_create(veth1
, veth2
);
216 SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1
, veth2
);
220 /* changing the high byte of the mac address to 0xfe, the bridge interface
221 * will always keep the host's mac address and not take the mac address
223 err
= setup_private_host_hw_addr(veth1
);
226 SYSERROR("Failed to change mac address of host interface \"%s\"", veth1
);
230 /* Retrieve ifindex of the host's veth device. */
231 netdev
->priv
.veth_attr
.ifindex
= if_nametoindex(veth1
);
232 if (!netdev
->priv
.veth_attr
.ifindex
) {
233 ERROR("Failed to retrieve ifindex for \"%s\"", veth1
);
237 /* Note that we're retrieving the container's ifindex in the host's
238 * network namespace because we need it to move the device from the
239 * host's network namespace to the container's network namespace later
242 netdev
->ifindex
= if_nametoindex(veth2
);
243 if (!netdev
->ifindex
) {
244 ERROR("Failed to retrieve ifindex for \"%s\"", veth2
);
249 if (lxc_safe_uint(netdev
->mtu
, &mtu
) < 0)
250 WARN("Failed to parse mtu");
252 INFO("Retrieved mtu %d", mtu
);
253 } else if (netdev
->link
[0] != '\0') {
254 bridge_index
= if_nametoindex(netdev
->link
);
256 mtu
= netdev_get_mtu(bridge_index
);
257 INFO("Retrieved mtu %d from %s", mtu
, netdev
->link
);
259 mtu
= netdev_get_mtu(netdev
->ifindex
);
260 INFO("Retrieved mtu %d from %s", mtu
, veth2
);
265 err
= lxc_netdev_set_mtu(veth1
, mtu
);
267 err
= lxc_netdev_set_mtu(veth2
, mtu
);
271 SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
272 "and \"%s\"", mtu
, veth1
, veth2
);
277 if (netdev
->link
[0] != '\0') {
278 err
= lxc_bridge_attach(netdev
->link
, veth1
);
281 SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
282 veth1
, netdev
->link
);
285 INFO("Attached \"%s\" to bridge \"%s\"", veth1
, netdev
->link
);
288 err
= lxc_netdev_up(veth1
);
291 SYSERROR("Failed to set \"%s\" up", veth1
);
295 /* setup ipv4 routes on the host interface */
296 if (lxc_setup_ipv4_routes(&netdev
->priv
.veth_attr
.ipv4_routes
, netdev
->priv
.veth_attr
.ifindex
)) {
297 ERROR("Failed to setup ipv4 routes for network device \"%s\"", veth1
);
301 /* setup ipv6 routes on the host interface */
302 if (lxc_setup_ipv6_routes(&netdev
->priv
.veth_attr
.ipv6_routes
, netdev
->priv
.veth_attr
.ifindex
)) {
303 ERROR("Failed to setup ipv6 routes for network device \"%s\"", veth1
);
307 if (netdev
->upscript
) {
315 err
= run_script_argv(handler
->name
,
316 handler
->conf
->hooks_version
, "net",
317 netdev
->upscript
, "up", argv
);
322 DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1
, veth2
,
328 if (netdev
->ifindex
!= 0)
329 lxc_netdev_delete_by_name(veth1
);
333 static int instantiate_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
335 char peerbuf
[IFNAMSIZ
], *peer
;
338 if (netdev
->link
[0] == '\0') {
339 ERROR("No link for macvlan network device specified");
343 err
= snprintf(peerbuf
, sizeof(peerbuf
), "mcXXXXXX");
344 if (err
< 0 || (size_t)err
>= sizeof(peerbuf
))
347 peer
= lxc_mkifname(peerbuf
);
351 err
= lxc_macvlan_create(netdev
->link
, peer
,
352 netdev
->priv
.macvlan_attr
.mode
);
355 SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
360 netdev
->ifindex
= if_nametoindex(peer
);
361 if (!netdev
->ifindex
) {
362 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
366 if (netdev
->upscript
) {
373 err
= run_script_argv(handler
->name
,
374 handler
->conf
->hooks_version
, "net",
375 netdev
->upscript
, "up", argv
);
380 DEBUG("Instantiated macvlan \"%s\" with ifindex is %d and mode %d",
381 peer
, netdev
->ifindex
, netdev
->priv
.macvlan_attr
.mode
);
386 lxc_netdev_delete_by_name(peer
);
390 static int lxc_ipvlan_create(const char *master
, const char *name
, int mode
, int isolation
)
393 struct ifinfomsg
*ifi
;
394 struct nl_handler nlh
;
395 struct rtattr
*nest
, *nest2
;
396 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
398 len
= strlen(master
);
399 if (len
== 1 || len
>= IFNAMSIZ
)
400 return minus_one_set_errno(EINVAL
);
403 if (len
== 1 || len
>= IFNAMSIZ
)
404 return minus_one_set_errno(EINVAL
);
406 index
= if_nametoindex(master
);
408 return minus_one_set_errno(EINVAL
);
410 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
412 return minus_one_set_errno(-err
);
415 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
419 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
423 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
424 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
426 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
430 ifi
->ifi_family
= AF_UNSPEC
;
433 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
437 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "ipvlan"))
441 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
445 if (nla_put_u32(nlmsg
, IFLA_IPVLAN_MODE
, mode
))
448 /* if_link.h does not define the isolation flag value for bridge mode so we define it as 0
449 * and only send mode if mode >0 as default mode is bridge anyway according to ipvlan docs.
452 if (nla_put_u16(nlmsg
, IFLA_IPVLAN_ISOLATION
, isolation
))
456 nla_end_nested(nlmsg
, nest2
);
459 nla_end_nested(nlmsg
, nest
);
461 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
464 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
467 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
473 return minus_one_set_errno(-err
);
477 static int instantiate_ipvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
479 char peerbuf
[IFNAMSIZ
], *peer
;
481 unsigned int mtu
= 0;
483 if (netdev
->link
[0] == '\0') {
484 ERROR("No link for ipvlan network device specified");
488 err
= snprintf(peerbuf
, sizeof(peerbuf
), "ipXXXXXX");
489 if (err
< 0 || (size_t)err
>= sizeof(peerbuf
))
492 peer
= lxc_mkifname(peerbuf
);
496 err
= lxc_ipvlan_create(netdev
->link
, peer
, netdev
->priv
.ipvlan_attr
.mode
, netdev
->priv
.ipvlan_attr
.isolation
);
498 SYSERROR("Failed to create ipvlan interface \"%s\" on \"%s\"", peer
, netdev
->link
);
502 netdev
->ifindex
= if_nametoindex(peer
);
503 if (!netdev
->ifindex
) {
504 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
509 err
= lxc_safe_uint(netdev
->mtu
, &mtu
);
512 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev
->mtu
, peer
);
516 err
= lxc_netdev_set_mtu(peer
, mtu
);
519 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev
->mtu
, peer
);
524 if (netdev
->upscript
) {
531 err
= run_script_argv(handler
->name
,
532 handler
->conf
->hooks_version
, "net",
533 netdev
->upscript
, "up", argv
);
538 DEBUG("Instantiated ipvlan \"%s\" with ifindex is %d and mode %d",
539 peer
, netdev
->ifindex
, netdev
->priv
.macvlan_attr
.mode
);
544 lxc_netdev_delete_by_name(peer
);
548 static int instantiate_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
552 static uint16_t vlan_cntr
= 0;
553 unsigned int mtu
= 0;
555 if (netdev
->link
[0] == '\0') {
556 ERROR("No link for vlan network device specified");
560 err
= snprintf(peer
, sizeof(peer
), "vlan%d-%d", netdev
->priv
.vlan_attr
.vid
, vlan_cntr
++);
561 if (err
< 0 || (size_t)err
>= sizeof(peer
))
564 err
= lxc_vlan_create(netdev
->link
, peer
, netdev
->priv
.vlan_attr
.vid
);
567 SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
572 netdev
->ifindex
= if_nametoindex(peer
);
573 if (!netdev
->ifindex
) {
574 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
579 err
= lxc_safe_uint(netdev
->mtu
, &mtu
);
582 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev
->mtu
, peer
);
586 err
= lxc_netdev_set_mtu(peer
, mtu
);
589 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev
->mtu
, peer
);
594 if (netdev
->upscript
) {
601 err
= run_script_argv(handler
->name
,
602 handler
->conf
->hooks_version
, "net",
603 netdev
->upscript
, "up", argv
);
609 DEBUG("Instantiated vlan \"%s\" with ifindex is \"%d\" (vlan1000)",
610 peer
, netdev
->ifindex
);
615 lxc_netdev_delete_by_name(peer
);
619 static int instantiate_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
628 if (netdev
->link
[0] == '\0') {
629 ERROR("No link for physical interface specified");
633 /* Note that we're retrieving the container's ifindex in the host's
634 * network namespace because we need it to move the device from the
635 * host's network namespace to the container's network namespace later
637 * Note that netdev->link will contain the name of the physical network
638 * device in the host's namespace.
640 netdev
->ifindex
= if_nametoindex(netdev
->link
);
641 if (!netdev
->ifindex
) {
642 ERROR("Failed to retrieve ifindex for \"%s\"", netdev
->link
);
646 /* Store the ifindex of the host's network device in the host's
649 netdev
->priv
.phys_attr
.ifindex
= netdev
->ifindex
;
651 if (!netdev
->upscript
)
654 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
655 "net", netdev
->upscript
, "up", argv
);
662 static int instantiate_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
671 if (!netdev
->upscript
)
674 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
675 "net", netdev
->upscript
, "up", argv
);
682 static int instantiate_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
688 static instantiate_cb netdev_conf
[LXC_NET_MAXCONFTYPE
+ 1] = {
689 [LXC_NET_VETH
] = instantiate_veth
,
690 [LXC_NET_MACVLAN
] = instantiate_macvlan
,
691 [LXC_NET_IPVLAN
] = instantiate_ipvlan
,
692 [LXC_NET_VLAN
] = instantiate_vlan
,
693 [LXC_NET_PHYS
] = instantiate_phys
,
694 [LXC_NET_EMPTY
] = instantiate_empty
,
695 [LXC_NET_NONE
] = instantiate_none
,
698 static int shutdown_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
708 if (!netdev
->downscript
)
711 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
712 argv
[2] = netdev
->priv
.veth_attr
.pair
;
714 argv
[2] = netdev
->priv
.veth_attr
.veth1
;
716 ret
= run_script_argv(handler
->name
,
717 handler
->conf
->hooks_version
, "net",
718 netdev
->downscript
, "down", argv
);
725 static int shutdown_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
734 if (!netdev
->downscript
)
737 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
738 "net", netdev
->downscript
, "down", argv
);
745 static int shutdown_ipvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
754 if (!netdev
->downscript
)
757 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
758 "net", netdev
->downscript
, "down", argv
);
765 static int shutdown_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
774 if (!netdev
->downscript
)
777 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
778 "net", netdev
->downscript
, "down", argv
);
785 static int shutdown_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
794 if (!netdev
->downscript
)
797 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
798 "net", netdev
->downscript
, "down", argv
);
805 static int shutdown_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
813 if (!netdev
->downscript
)
816 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
817 "net", netdev
->downscript
, "down", argv
);
824 static int shutdown_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
829 static instantiate_cb netdev_deconf
[LXC_NET_MAXCONFTYPE
+ 1] = {
830 [LXC_NET_VETH
] = shutdown_veth
,
831 [LXC_NET_MACVLAN
] = shutdown_macvlan
,
832 [LXC_NET_IPVLAN
] = shutdown_ipvlan
,
833 [LXC_NET_VLAN
] = shutdown_vlan
,
834 [LXC_NET_PHYS
] = shutdown_phys
,
835 [LXC_NET_EMPTY
] = shutdown_empty
,
836 [LXC_NET_NONE
] = shutdown_none
,
839 int lxc_netdev_move_by_index(int ifindex
, pid_t pid
, const char *ifname
)
842 struct nl_handler nlh
;
843 struct ifinfomsg
*ifi
;
844 struct nlmsg
*nlmsg
= NULL
;
846 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
851 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
855 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
856 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
858 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
861 ifi
->ifi_family
= AF_UNSPEC
;
862 ifi
->ifi_index
= ifindex
;
864 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
867 if (ifname
!= NULL
) {
868 if (nla_put_string(nlmsg
, IFLA_IFNAME
, ifname
))
872 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
879 /* If we are asked to move a wireless interface, then we must actually move its
880 * phyN device. Detect that condition and return the physname here. The physname
881 * will be passed to lxc_netdev_move_wlan() which will free it when done.
883 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
884 static char *is_wlan(const char *ifname
)
886 __do_free
char *path
= NULL
;
891 char *physname
= NULL
;
893 len
= strlen(ifname
) + strlen(PHYSNAME
) - 1;
894 path
= must_realloc(NULL
, len
+ 1);
895 ret
= snprintf(path
, len
, PHYSNAME
, ifname
);
896 if (ret
< 0 || (size_t)ret
>= len
)
899 f
= fopen(path
, "r");
903 /* Feh - sb.st_size is always 4096. */
904 fseek(f
, 0, SEEK_END
);
906 fseek(f
, 0, SEEK_SET
);
912 physname
= malloc(physlen
+ 1);
918 memset(physname
, 0, physlen
+ 1);
919 ret
= fread(physname
, 1, physlen
, f
);
924 for (i
= 0; i
< physlen
; i
++) {
925 if (physname
[i
] == '\n')
928 if (physname
[i
] == '\0')
939 static int lxc_netdev_rename_by_name_in_netns(pid_t pid
, const char *old
,
949 return wait_for_pid(fpid
);
951 if (!switch_to_ns(pid
, "net"))
954 _exit(lxc_netdev_rename_by_name(old
, new));
957 static int lxc_netdev_move_wlan(char *physname
, const char *ifname
, pid_t pid
,
964 /* Move phyN into the container. TODO - do this using netlink.
965 * However, IIUC this involves a bit more complicated work to talk to
966 * the 80211 module, so for now just call out to iw.
968 cmd
= on_path("iw", NULL
);
979 sprintf(pidstr
, "%d", pid
);
980 execlp("iw", "iw", "phy", physname
, "set", "netns", pidstr
,
985 if (wait_for_pid(fpid
))
990 err
= lxc_netdev_rename_by_name_in_netns(pid
, ifname
, newname
);
997 int lxc_netdev_move_by_name(const char *ifname
, pid_t pid
, const char* newname
)
1005 index
= if_nametoindex(ifname
);
1009 physname
= is_wlan(ifname
);
1011 return lxc_netdev_move_wlan(physname
, ifname
, pid
, newname
);
1013 return lxc_netdev_move_by_index(index
, pid
, newname
);
1016 int lxc_netdev_delete_by_index(int ifindex
)
1019 struct ifinfomsg
*ifi
;
1020 struct nl_handler nlh
;
1021 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1023 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1028 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1032 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1036 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
1037 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_DELLINK
;
1039 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1042 ifi
->ifi_family
= AF_UNSPEC
;
1043 ifi
->ifi_index
= ifindex
;
1045 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1047 netlink_close(&nlh
);
1053 int lxc_netdev_delete_by_name(const char *name
)
1057 index
= if_nametoindex(name
);
1061 return lxc_netdev_delete_by_index(index
);
1064 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
1067 struct ifinfomsg
*ifi
;
1068 struct nl_handler nlh
;
1069 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1071 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1075 len
= strlen(newname
);
1076 if (len
== 1 || len
>= IFNAMSIZ
)
1080 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1084 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1088 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
1089 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1091 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1094 ifi
->ifi_family
= AF_UNSPEC
;
1095 ifi
->ifi_index
= ifindex
;
1097 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
1100 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1102 netlink_close(&nlh
);
1108 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
1112 len
= strlen(oldname
);
1113 if (len
== 1 || len
>= IFNAMSIZ
)
1116 index
= if_nametoindex(oldname
);
1120 return lxc_netdev_rename_by_index(index
, newname
);
1123 int netdev_set_flag(const char *name
, int flag
)
1125 int err
, index
, len
;
1126 struct ifinfomsg
*ifi
;
1127 struct nl_handler nlh
;
1128 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1130 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1136 if (len
== 1 || len
>= IFNAMSIZ
)
1140 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1144 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1149 index
= if_nametoindex(name
);
1153 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1154 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1156 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1161 ifi
->ifi_family
= AF_UNSPEC
;
1162 ifi
->ifi_index
= index
;
1163 ifi
->ifi_change
|= IFF_UP
;
1164 ifi
->ifi_flags
|= flag
;
1166 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1168 netlink_close(&nlh
);
1174 int netdev_get_flag(const char *name
, int *flag
)
1176 int err
, index
, len
;
1177 struct ifinfomsg
*ifi
;
1178 struct nl_handler nlh
;
1179 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1184 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1190 if (len
== 1 || len
>= IFNAMSIZ
)
1194 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1198 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1203 index
= if_nametoindex(name
);
1207 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
;
1208 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
1210 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1215 ifi
->ifi_family
= AF_UNSPEC
;
1216 ifi
->ifi_index
= index
;
1218 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1222 ifi
= NLMSG_DATA(answer
->nlmsghdr
);
1224 *flag
= ifi
->ifi_flags
;
1226 netlink_close(&nlh
);
1233 * \brief Check a interface is up or not.
1235 * \param name: name for the interface.
1238 * 0 means interface is down.
1239 * 1 means interface is up.
1240 * Others means error happened, and ret-value is the error number.
1242 int lxc_netdev_isup(const char *name
)
1246 err
= netdev_get_flag(name
, &flag
);
1256 int netdev_get_mtu(int ifindex
)
1258 int answer_len
, err
, res
;
1259 struct nl_handler nlh
;
1260 struct ifinfomsg
*ifi
;
1261 struct nlmsghdr
*msg
;
1262 int readmore
= 0, recv_len
= 0;
1263 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1265 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1270 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1274 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1278 /* Save the answer buffer length, since it will be overwritten
1279 * on the first receive (and we might need to receive more than
1282 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1284 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
1285 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
1287 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1290 ifi
->ifi_family
= AF_UNSPEC
;
1292 /* Send the request for addresses, which returns all addresses
1293 * on all interfaces. */
1294 err
= netlink_send(&nlh
, nlmsg
);
1298 #pragma GCC diagnostic push
1299 #pragma GCC diagnostic ignored "-Wcast-align"
1302 /* Restore the answer buffer length, it might have been
1303 * overwritten by a previous receive.
1305 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1307 /* Get the (next) batch of reply messages */
1308 err
= netlink_rcv(&nlh
, answer
);
1314 /* Satisfy the typing for the netlink macros */
1315 msg
= answer
->nlmsghdr
;
1317 while (NLMSG_OK(msg
, recv_len
)) {
1319 /* Stop reading if we see an error message */
1320 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1321 struct nlmsgerr
*errmsg
=
1322 (struct nlmsgerr
*)NLMSG_DATA(msg
);
1323 err
= errmsg
->error
;
1327 /* Stop reading if we see a NLMSG_DONE message */
1328 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1333 ifi
= NLMSG_DATA(msg
);
1334 if (ifi
->ifi_index
== ifindex
) {
1335 struct rtattr
*rta
= IFLA_RTA(ifi
);
1337 msg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
1339 while (RTA_OK(rta
, attr_len
)) {
1340 /* Found a local address for the
1341 * requested interface, return it.
1343 if (rta
->rta_type
== IFLA_MTU
) {
1344 memcpy(&res
, RTA_DATA(rta
),
1349 rta
= RTA_NEXT(rta
, attr_len
);
1353 /* Keep reading more data from the socket if the last
1354 * message had the NLF_F_MULTI flag set.
1356 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1358 /* Look at the next message received in this buffer. */
1359 msg
= NLMSG_NEXT(msg
, recv_len
);
1363 #pragma GCC diagnostic pop
1365 /* If we end up here, we didn't find any result, so signal an error. */
1369 netlink_close(&nlh
);
1375 int lxc_netdev_set_mtu(const char *name
, int mtu
)
1377 int err
, index
, len
;
1378 struct ifinfomsg
*ifi
;
1379 struct nl_handler nlh
;
1380 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1382 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1388 if (len
== 1 || len
>= IFNAMSIZ
)
1392 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1396 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1401 index
= if_nametoindex(name
);
1405 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1406 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1408 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1413 ifi
->ifi_family
= AF_UNSPEC
;
1414 ifi
->ifi_index
= index
;
1416 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
1419 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1421 netlink_close(&nlh
);
1427 int lxc_netdev_up(const char *name
)
1429 return netdev_set_flag(name
, IFF_UP
);
1432 int lxc_netdev_down(const char *name
)
1434 return netdev_set_flag(name
, 0);
1437 int lxc_veth_create(const char *name1
, const char *name2
)
1440 struct ifinfomsg
*ifi
;
1441 struct nl_handler nlh
;
1442 struct rtattr
*nest1
, *nest2
, *nest3
;
1443 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1445 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1450 len
= strlen(name1
);
1451 if (len
== 1 || len
>= IFNAMSIZ
)
1454 len
= strlen(name2
);
1455 if (len
== 1 || len
>= IFNAMSIZ
)
1459 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1463 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1467 nlmsg
->nlmsghdr
->nlmsg_flags
=
1468 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1469 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1471 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1474 ifi
->ifi_family
= AF_UNSPEC
;
1477 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1481 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
1484 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1488 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
1492 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1498 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
1501 nla_end_nested(nlmsg
, nest3
);
1502 nla_end_nested(nlmsg
, nest2
);
1503 nla_end_nested(nlmsg
, nest1
);
1505 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
1508 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1510 netlink_close(&nlh
);
1516 /* TODO: merge with lxc_macvlan_create */
1517 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
1519 int err
, len
, lindex
;
1520 struct ifinfomsg
*ifi
;
1521 struct nl_handler nlh
;
1522 struct rtattr
*nest
, *nest2
;
1523 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1525 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1530 len
= strlen(master
);
1531 if (len
== 1 || len
>= IFNAMSIZ
)
1535 if (len
== 1 || len
>= IFNAMSIZ
)
1539 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1543 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1548 lindex
= if_nametoindex(master
);
1552 nlmsg
->nlmsghdr
->nlmsg_flags
=
1553 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1554 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1556 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1561 ifi
->ifi_family
= AF_UNSPEC
;
1563 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1567 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
1570 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1574 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
1577 nla_end_nested(nlmsg
, nest2
);
1578 nla_end_nested(nlmsg
, nest
);
1580 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
1583 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1586 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1592 netlink_close(&nlh
);
1596 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
1598 int err
, index
, len
;
1599 struct ifinfomsg
*ifi
;
1600 struct nl_handler nlh
;
1601 struct rtattr
*nest
, *nest2
;
1602 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1604 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1609 len
= strlen(master
);
1610 if (len
== 1 || len
>= IFNAMSIZ
)
1614 if (len
== 1 || len
>= IFNAMSIZ
)
1618 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1622 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1627 index
= if_nametoindex(master
);
1631 nlmsg
->nlmsghdr
->nlmsg_flags
=
1632 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1633 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1635 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1640 ifi
->ifi_family
= AF_UNSPEC
;
1642 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1646 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
1650 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1654 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
1657 nla_end_nested(nlmsg
, nest2
);
1660 nla_end_nested(nlmsg
, nest
);
1662 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
1665 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1668 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1670 netlink_close(&nlh
);
1676 static int proc_sys_net_write(const char *path
, const char *value
)
1681 fd
= open(path
, O_WRONLY
);
1685 if (lxc_write_nointr(fd
, value
, strlen(value
)) < 0)
1692 static int lxc_is_ip_forwarding_enabled(const char *ifname
, int family
)
1695 char path
[PATH_MAX
];
1698 if (family
!= AF_INET
&& family
!= AF_INET6
)
1699 return minus_one_set_errno(EINVAL
);
1701 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1702 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1704 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1705 return minus_one_set_errno(E2BIG
);
1707 return lxc_read_file_expect(path
, buf
, 1, "1");
1710 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
1713 char path
[PATH_MAX
];
1715 if (family
!= AF_INET
&& family
!= AF_INET6
)
1718 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1719 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1720 family
== AF_INET
? "proxy_arp" : "proxy_ndp");
1721 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1724 return proc_sys_net_write(path
, flag
? "1" : "0");
1727 static int lxc_is_ip_neigh_proxy_enabled(const char *ifname
, int family
)
1730 char path
[PATH_MAX
];
1733 if (family
!= AF_INET
&& family
!= AF_INET6
)
1734 return minus_one_set_errno(EINVAL
);
1736 ret
= snprintf(path
, PATH_MAX
, "/proc/sys/net/%s/conf/%s/%s",
1737 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1738 family
== AF_INET
? "proxy_arp" : "proxy_ndp");
1739 if (ret
< 0 || (size_t)ret
>= PATH_MAX
)
1740 return minus_one_set_errno(E2BIG
);
1742 return lxc_read_file_expect(path
, buf
, 1, "1");
1745 int lxc_neigh_proxy_on(const char *name
, int family
)
1747 return neigh_proxy_set(name
, family
, 1);
1750 int lxc_neigh_proxy_off(const char *name
, int family
)
1752 return neigh_proxy_set(name
, family
, 0);
1755 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
1760 unsigned char *data
;
1762 sockaddr
->sa_family
= ARPHRD_ETHER
;
1763 data
= (unsigned char *)sockaddr
->sa_data
;
1765 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
1769 else if (c
>= 'a' && c
<= 'f')
1771 else if (c
>= 'A' && c
<= 'F')
1780 else if (c
>= 'a' && c
<= 'f')
1781 val
|= c
- 'a' + 10;
1782 else if (c
>= 'A' && c
<= 'F')
1783 val
|= c
- 'A' + 10;
1784 else if (c
== ':' || c
== 0)
1790 *data
++ = (unsigned char)(val
& 0377);
1793 if (*macaddr
== ':')
1800 static int ip_addr_add(int family
, int ifindex
, void *addr
, void *bcast
,
1801 void *acast
, int prefix
)
1804 struct ifaddrmsg
*ifa
;
1805 struct nl_handler nlh
;
1806 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1808 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1809 : sizeof(struct in6_addr
);
1811 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1816 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1820 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1824 nlmsg
->nlmsghdr
->nlmsg_flags
=
1825 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
1826 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWADDR
;
1828 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1831 ifa
->ifa_prefixlen
= prefix
;
1832 ifa
->ifa_index
= ifindex
;
1833 ifa
->ifa_family
= family
;
1837 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
1840 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
1843 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
1846 /* TODO: multicast, anycast with ipv6 */
1847 err
= -EPROTONOSUPPORT
;
1848 if (family
== AF_INET6
&&
1849 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
1850 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
1853 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1855 netlink_close(&nlh
);
1861 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
1862 struct in6_addr
*mcast
, struct in6_addr
*acast
,
1865 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
1868 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
, struct in_addr
*bcast
,
1871 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
1874 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
1875 * the given RTM_NEWADDR message. Allocates memory for the address and stores
1876 * that pointer in *res (so res should be an in_addr** or in6_addr**).
1878 #pragma GCC diagnostic push
1879 #pragma GCC diagnostic ignored "-Wcast-align"
1881 static int ifa_get_local_ip(int family
, struct nlmsghdr
*msg
, void **res
)
1884 struct ifaddrmsg
*ifa
= NLMSG_DATA(msg
);
1885 struct rtattr
*rta
= IFA_RTA(ifa
);
1886 int attr_len
= NLMSG_PAYLOAD(msg
, sizeof(struct ifaddrmsg
));
1888 if (ifa
->ifa_family
!= family
)
1891 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1892 : sizeof(struct in6_addr
);
1894 /* Loop over the rtattr's in this message */
1895 while (RTA_OK(rta
, attr_len
)) {
1896 /* Found a local address for the requested interface,
1899 if (rta
->rta_type
== IFA_LOCAL
||
1900 rta
->rta_type
== IFA_ADDRESS
) {
1901 /* Sanity check. The family check above should make sure
1902 * the address length is correct, but check here just in
1905 if (RTA_PAYLOAD(rta
) != addrlen
)
1908 /* We might have found an IFA_ADDRESS before, which we
1909 * now overwrite with an IFA_LOCAL.
1912 *res
= malloc(addrlen
);
1917 memcpy(*res
, RTA_DATA(rta
), addrlen
);
1918 if (rta
->rta_type
== IFA_LOCAL
)
1921 rta
= RTA_NEXT(rta
, attr_len
);
1926 #pragma GCC diagnostic pop
1928 static int ip_addr_get(int family
, int ifindex
, void **res
)
1930 int answer_len
, err
;
1931 struct ifaddrmsg
*ifa
;
1932 struct nl_handler nlh
;
1933 struct nlmsghdr
*msg
;
1934 int readmore
= 0, recv_len
= 0;
1935 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1937 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1942 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1946 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1950 /* Save the answer buffer length, since it will be overwritten on the
1951 * first receive (and we might need to receive more than once).
1953 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1955 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ROOT
;
1956 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETADDR
;
1958 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1961 ifa
->ifa_family
= family
;
1963 /* Send the request for addresses, which returns all addresses on all
1966 err
= netlink_send(&nlh
, nlmsg
);
1970 #pragma GCC diagnostic push
1971 #pragma GCC diagnostic ignored "-Wcast-align"
1974 /* Restore the answer buffer length, it might have been
1975 * overwritten by a previous receive.
1977 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1979 /* Get the (next) batch of reply messages. */
1980 err
= netlink_rcv(&nlh
, answer
);
1987 /* Satisfy the typing for the netlink macros. */
1988 msg
= answer
->nlmsghdr
;
1990 while (NLMSG_OK(msg
, recv_len
)) {
1991 /* Stop reading if we see an error message. */
1992 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1993 struct nlmsgerr
*errmsg
=
1994 (struct nlmsgerr
*)NLMSG_DATA(msg
);
1995 err
= errmsg
->error
;
1999 /* Stop reading if we see a NLMSG_DONE message. */
2000 if (msg
->nlmsg_type
== NLMSG_DONE
) {
2005 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
2010 ifa
= (struct ifaddrmsg
*)NLMSG_DATA(msg
);
2011 if (ifa
->ifa_index
== ifindex
) {
2012 if (ifa_get_local_ip(family
, msg
, res
) < 0) {
2017 /* Found a result, stop searching. */
2022 /* Keep reading more data from the socket if the last
2023 * message had the NLF_F_MULTI flag set.
2025 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
2027 /* Look at the next message received in this buffer. */
2028 msg
= NLMSG_NEXT(msg
, recv_len
);
2032 #pragma GCC diagnostic pop
2034 /* If we end up here, we didn't find any result, so signal an
2040 netlink_close(&nlh
);
2046 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
2048 return ip_addr_get(AF_INET6
, ifindex
, (void **)res
);
2051 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
**res
)
2053 return ip_addr_get(AF_INET
, ifindex
, (void **)res
);
2056 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
2059 struct nl_handler nlh
;
2061 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
2063 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
2064 : sizeof(struct in6_addr
);
2066 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
2071 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
2075 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
2079 nlmsg
->nlmsghdr
->nlmsg_flags
=
2080 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
2081 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
2083 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
2086 rt
->rtm_family
= family
;
2087 rt
->rtm_table
= RT_TABLE_MAIN
;
2088 rt
->rtm_scope
= RT_SCOPE_UNIVERSE
;
2089 rt
->rtm_protocol
= RTPROT_BOOT
;
2090 rt
->rtm_type
= RTN_UNICAST
;
2091 /* "default" destination */
2092 rt
->rtm_dst_len
= 0;
2096 /* If gateway address not supplied, then a device route will be created instead */
2098 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
2102 /* Adding the interface index enables the use of link-local
2103 * addresses for the gateway.
2105 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
2108 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
2110 netlink_close(&nlh
);
2116 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
2118 return ip_gateway_add(AF_INET
, ifindex
, gw
);
2121 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
2123 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
2125 bool is_ovs_bridge(const char *bridge
)
2129 char brdirname
[22 + IFNAMSIZ
+ 1] = {0};
2131 ret
= snprintf(brdirname
, 22 + IFNAMSIZ
+ 1, "/sys/class/net/%s/bridge",
2133 if (ret
< 0 || (size_t)ret
>= 22 + IFNAMSIZ
+ 1)
2136 ret
= stat(brdirname
, &sb
);
2137 if (ret
< 0 && errno
== ENOENT
)
2143 struct ovs_veth_args
{
2148 /* Called from a background thread - when nic goes away, remove it from the
2151 static int lxc_ovs_delete_port_exec(void *data
)
2153 struct ovs_veth_args
*args
= data
;
2155 execlp("ovs-vsctl", "ovs-vsctl", "del-port", args
->bridge
, args
->nic
,
2160 int lxc_ovs_delete_port(const char *bridge
, const char *nic
)
2163 char cmd_output
[PATH_MAX
];
2164 struct ovs_veth_args args
;
2166 args
.bridge
= bridge
;
2168 ret
= run_command(cmd_output
, sizeof(cmd_output
),
2169 lxc_ovs_delete_port_exec
, (void *)&args
);
2171 ERROR("Failed to delete \"%s\" from openvswitch bridge \"%s\": "
2172 "%s", bridge
, nic
, cmd_output
);
2179 static int lxc_ovs_attach_bridge_exec(void *data
)
2181 struct ovs_veth_args
*args
= data
;
2183 execlp("ovs-vsctl", "ovs-vsctl", "add-port", args
->bridge
, args
->nic
,
2188 static int lxc_ovs_attach_bridge(const char *bridge
, const char *nic
)
2191 char cmd_output
[PATH_MAX
];
2192 struct ovs_veth_args args
;
2194 args
.bridge
= bridge
;
2196 ret
= run_command(cmd_output
, sizeof(cmd_output
),
2197 lxc_ovs_attach_bridge_exec
, (void *)&args
);
2199 ERROR("Failed to attach \"%s\" to openvswitch bridge \"%s\": %s",
2200 bridge
, nic
, cmd_output
);
2207 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
2213 if (strlen(ifname
) >= IFNAMSIZ
)
2216 index
= if_nametoindex(ifname
);
2220 if (is_ovs_bridge(bridge
))
2221 return lxc_ovs_attach_bridge(bridge
, ifname
);
2223 fd
= socket(AF_INET
, SOCK_STREAM
| SOCK_CLOEXEC
, 0);
2227 retlen
= strlcpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
);
2228 if (retlen
>= IFNAMSIZ
) {
2233 ifr
.ifr_name
[IFNAMSIZ
- 1] = '\0';
2234 ifr
.ifr_ifindex
= index
;
2235 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
2243 static const char *const lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
2244 [LXC_NET_EMPTY
] = "empty",
2245 [LXC_NET_VETH
] = "veth",
2246 [LXC_NET_MACVLAN
] = "macvlan",
2247 [LXC_NET_IPVLAN
] = "ipvlan",
2248 [LXC_NET_PHYS
] = "phys",
2249 [LXC_NET_VLAN
] = "vlan",
2250 [LXC_NET_NONE
] = "none",
2253 const char *lxc_net_type_to_str(int type
)
2255 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
2258 return lxc_network_types
[type
];
2261 static const char padchar
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2263 char *lxc_mkifname(char *template)
2266 struct netns_ifaddrs
*ifa
, *ifaddr
;
2267 char name
[IFNAMSIZ
];
2268 bool exists
= false;
2273 seed
= randseed(false);
2276 (void)randseed(true);
2279 if (strlen(template) >= IFNAMSIZ
)
2282 /* Get all the network interfaces. */
2283 ret
= netns_getifaddrs(&ifaddr
, -1, &(bool){false});
2285 SYSERROR("Failed to get network interfaces");
2289 /* Generate random names until we find one that doesn't exist. */
2292 (void)strlcpy(name
, template, IFNAMSIZ
);
2296 for (i
= 0; i
< strlen(name
); i
++) {
2297 if (name
[i
] == 'X') {
2299 name
[i
] = padchar
[rand_r(&seed
) % strlen(padchar
)];
2301 name
[i
] = padchar
[rand() % strlen(padchar
)];
2306 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
2307 if (!strcmp(ifa
->ifa_name
, name
)) {
2317 netns_freeifaddrs(ifaddr
);
2318 (void)strlcpy(template, name
, strlen(template) + 1);
2323 int setup_private_host_hw_addr(char *veth1
)
2328 sockfd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0);
2332 err
= snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
2333 if (err
< 0 || (size_t)err
>= IFNAMSIZ
) {
2338 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
2344 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
2345 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);
2353 int lxc_find_gateway_addresses(struct lxc_handler
*handler
)
2355 struct lxc_list
*network
= &handler
->conf
->network
;
2356 struct lxc_list
*iterator
;
2357 struct lxc_netdev
*netdev
;
2360 lxc_list_for_each(iterator
, network
) {
2361 netdev
= iterator
->elem
;
2363 if (!netdev
->ipv4_gateway_auto
&& !netdev
->ipv6_gateway_auto
)
2366 if (netdev
->type
!= LXC_NET_VETH
&& netdev
->type
!= LXC_NET_MACVLAN
) {
2367 ERROR("Automatic gateway detection is only supported "
2368 "for veth and macvlan");
2372 if (netdev
->link
[0] == '\0') {
2373 ERROR("Automatic gateway detection needs a link interface");
2377 link_index
= if_nametoindex(netdev
->link
);
2381 if (netdev
->ipv4_gateway_auto
) {
2382 if (lxc_ipv4_addr_get(link_index
, &netdev
->ipv4_gateway
)) {
2383 ERROR("Failed to automatically find ipv4 gateway "
2384 "address from link interface \"%s\"", netdev
->link
);
2389 if (netdev
->ipv6_gateway_auto
) {
2390 if (lxc_ipv6_addr_get(link_index
, &netdev
->ipv6_gateway
)) {
2391 ERROR("Failed to automatically find ipv6 gateway "
2392 "address from link interface \"%s\"", netdev
->link
);
2401 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
2402 static int lxc_create_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2403 struct lxc_netdev
*netdev
, pid_t pid
, unsigned int hooks_version
)
2407 int bytes
, pipefd
[2];
2408 char *token
, *saveptr
= NULL
;
2409 char netdev_link
[IFNAMSIZ
];
2410 char buffer
[PATH_MAX
] = {0};
2413 if (netdev
->type
!= LXC_NET_VETH
) {
2414 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2420 SYSERROR("Failed to create pipe");
2426 SYSERROR("Failed to create new process");
2433 char pidstr
[INTTYPE_TO_STRLEN(pid_t
)];
2437 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2439 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2442 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2443 _exit(EXIT_FAILURE
);
2446 if (netdev
->link
[0] != '\0')
2447 retlen
= strlcpy(netdev_link
, netdev
->link
, IFNAMSIZ
);
2449 retlen
= strlcpy(netdev_link
, "none", IFNAMSIZ
);
2450 if (retlen
>= IFNAMSIZ
) {
2451 SYSERROR("Invalid network device name");
2452 _exit(EXIT_FAILURE
);
2455 ret
= snprintf(pidstr
, sizeof(pidstr
), "%d", pid
);
2456 if (ret
< 0 || ret
>= sizeof(pidstr
))
2457 _exit(EXIT_FAILURE
);
2458 pidstr
[sizeof(pidstr
) - 1] = '\0';
2460 INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath
,
2461 lxcname
, pidstr
, netdev_link
,
2462 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)");
2463 if (netdev
->name
[0] != '\0')
2464 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2465 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2466 netdev
->name
, (char *)NULL
);
2468 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2469 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2471 SYSERROR("Failed to execute lxc-user-nic");
2472 _exit(EXIT_FAILURE
);
2475 /* close the write-end of the pipe */
2478 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, PATH_MAX
);
2480 SYSERROR("Failed to read from pipe file descriptor");
2483 buffer
[bytes
- 1] = '\0';
2486 ret
= wait_for_pid(child
);
2488 if (ret
!= 0 || bytes
< 0) {
2489 ERROR("lxc-user-nic failed to configure requested network: %s",
2490 buffer
[0] != '\0' ? buffer
: "(null)");
2493 TRACE("Received output \"%s\" from lxc-user-nic", buffer
);
2496 token
= strtok_r(buffer
, ":", &saveptr
);
2498 ERROR("Failed to parse lxc-user-nic output");
2502 memset(netdev
->name
, 0, IFNAMSIZ
);
2503 memcpy(netdev
->name
, token
, IFNAMSIZ
- 1);
2505 /* netdev->ifindex */
2506 token
= strtok_r(NULL
, ":", &saveptr
);
2508 ERROR("Failed to parse lxc-user-nic output");
2512 ret
= lxc_safe_int(token
, &netdev
->ifindex
);
2515 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2519 /* netdev->priv.veth_attr.veth1 */
2520 token
= strtok_r(NULL
, ":", &saveptr
);
2522 ERROR("Failed to parse lxc-user-nic output");
2526 retlen
= strlcpy(netdev
->priv
.veth_attr
.veth1
, token
, IFNAMSIZ
);
2527 if (retlen
>= IFNAMSIZ
) {
2528 ERROR("Host side veth device name returned by lxc-user-nic is "
2533 /* netdev->priv.veth_attr.ifindex */
2534 token
= strtok_r(NULL
, ":", &saveptr
);
2536 ERROR("Failed to parse lxc-user-nic output");
2540 ret
= lxc_safe_int(token
, &netdev
->priv
.veth_attr
.ifindex
);
2543 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2547 if (netdev
->upscript
) {
2551 netdev
->priv
.veth_attr
.veth1
,
2555 ret
= run_script_argv(lxcname
,
2556 hooks_version
, "net",
2557 netdev
->upscript
, "up", argv
);
2565 static int lxc_delete_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2566 struct lxc_netdev
*netdev
,
2567 const char *netns_path
)
2572 char buffer
[PATH_MAX
] = {0};
2574 if (netdev
->type
!= LXC_NET_VETH
) {
2575 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2581 SYSERROR("Failed to create pipe");
2587 SYSERROR("Failed to create new process");
2598 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2600 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2603 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2604 _exit(EXIT_FAILURE
);
2607 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2608 hostveth
= netdev
->priv
.veth_attr
.pair
;
2610 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2611 if (hostveth
[0] == '\0') {
2612 SYSERROR("Host side veth device name is missing");
2613 _exit(EXIT_FAILURE
);
2616 if (netdev
->link
[0] == '\0') {
2617 SYSERROR("Network link for network device \"%s\" is "
2618 "missing", netdev
->priv
.veth_attr
.veth1
);
2619 _exit(EXIT_FAILURE
);
2622 INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath
,
2623 lxcname
, netns_path
, netdev
->link
, hostveth
);
2624 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "delete", lxcpath
,
2625 lxcname
, netns_path
, "veth", netdev
->link
, hostveth
,
2627 SYSERROR("Failed to exec lxc-user-nic.");
2628 _exit(EXIT_FAILURE
);
2633 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, PATH_MAX
);
2635 SYSERROR("Failed to read from pipe file descriptor.");
2638 buffer
[bytes
- 1] = '\0';
2641 ret
= wait_for_pid(child
);
2643 if (ret
!= 0 || bytes
< 0) {
2644 ERROR("lxc-user-nic failed to delete requested network: %s",
2645 buffer
[0] != '\0' ? buffer
: "(null)");
2652 bool lxc_delete_network_unpriv(struct lxc_handler
*handler
)
2655 struct lxc_list
*iterator
;
2656 struct lxc_list
*network
= &handler
->conf
->network
;
2657 /* strlen("/proc/") = 6
2659 * INTTYPE_TO_STRLEN(pid_t)
2661 * strlen("/fd/") = 4
2663 * INTTYPE_TO_STRLEN(int)
2667 char netns_path
[6 + INTTYPE_TO_STRLEN(pid_t
) + 4 + INTTYPE_TO_STRLEN(int) + 1];
2671 if (handler
->nsfd
[LXC_NS_NET
] < 0) {
2672 DEBUG("Cannot not guarantee safe deletion of network devices. "
2673 "Manual cleanup maybe needed");
2677 ret
= snprintf(netns_path
, sizeof(netns_path
), "/proc/%d/fd/%d",
2678 lxc_raw_getpid(), handler
->nsfd
[LXC_NS_NET
]);
2679 if (ret
< 0 || ret
>= sizeof(netns_path
))
2682 lxc_list_for_each(iterator
, network
) {
2683 char *hostveth
= NULL
;
2684 struct lxc_netdev
*netdev
= iterator
->elem
;
2686 /* We can only delete devices whose ifindex we have. If we don't
2687 * have the index it means that we didn't create it.
2689 if (!netdev
->ifindex
)
2692 if (netdev
->type
== LXC_NET_PHYS
) {
2693 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
,
2696 WARN("Failed to rename interface with index %d "
2697 "to its initial name \"%s\"",
2698 netdev
->ifindex
, netdev
->link
);
2700 TRACE("Renamed interface with index %d to its "
2701 "initial name \"%s\"",
2702 netdev
->ifindex
, netdev
->link
);
2703 goto clear_ifindices
;
2706 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
2708 WARN("Failed to deconfigure network device");
2710 if (netdev
->type
!= LXC_NET_VETH
)
2711 goto clear_ifindices
;
2713 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
))
2714 goto clear_ifindices
;
2716 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2717 hostveth
= netdev
->priv
.veth_attr
.pair
;
2719 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2720 if (hostveth
[0] == '\0')
2721 goto clear_ifindices
;
2723 ret
= lxc_delete_network_unpriv_exec(handler
->lxcpath
,
2724 handler
->name
, netdev
,
2727 WARN("Failed to remove port \"%s\" from openvswitch "
2728 "bridge \"%s\"", hostveth
, netdev
->link
);
2729 goto clear_ifindices
;
2731 INFO("Removed interface \"%s\" from \"%s\"", hostveth
,
2735 /* We need to clear any ifindices we recorded so liblxc won't
2736 * have cached stale data which would cause it to fail on reboot
2737 * we're we don't re-read the on-disk config file.
2739 netdev
->ifindex
= 0;
2740 if (netdev
->type
== LXC_NET_PHYS
) {
2741 netdev
->priv
.phys_attr
.ifindex
= 0;
2742 } else if (netdev
->type
== LXC_NET_VETH
) {
2743 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
2744 netdev
->priv
.veth_attr
.ifindex
= 0;
2751 struct ip_proxy_args
{
2756 static int lxc_add_ip_neigh_proxy_exec_wrapper(void *data
)
2758 struct ip_proxy_args
*args
= data
;
2760 execlp("ip", "ip", "neigh", "add", "proxy", args
->ip
, "dev", args
->dev
, (char *)NULL
);
2764 static int lxc_del_ip_neigh_proxy_exec_wrapper(void *data
)
2766 struct ip_proxy_args
*args
= data
;
2768 execlp("ip", "ip", "neigh", "flush", "proxy", args
->ip
, "dev", args
->dev
, (char *)NULL
);
2772 static int lxc_add_ip_neigh_proxy(const char *ip
, const char *dev
)
2775 char cmd_output
[PATH_MAX
];
2776 struct ip_proxy_args args
= {
2781 ret
= run_command(cmd_output
, sizeof(cmd_output
), lxc_add_ip_neigh_proxy_exec_wrapper
, &args
);
2783 ERROR("Failed to add ip proxy \"%s\" to dev \"%s\": %s", ip
, dev
, cmd_output
);
2790 static int lxc_del_ip_neigh_proxy(const char *ip
, const char *dev
)
2793 char cmd_output
[PATH_MAX
];
2794 struct ip_proxy_args args
= {
2799 ret
= run_command(cmd_output
, sizeof(cmd_output
), lxc_del_ip_neigh_proxy_exec_wrapper
, &args
);
2801 ERROR("Failed to delete ip proxy \"%s\" to dev \"%s\": %s", ip
, dev
, cmd_output
);
2808 static int lxc_setup_l2proxy(struct lxc_netdev
*netdev
) {
2809 struct lxc_list
*cur
, *next
;
2810 struct lxc_inetdev
*inet4dev
;
2811 struct lxc_inet6dev
*inet6dev
;
2812 char bufinet4
[INET_ADDRSTRLEN
], bufinet6
[INET6_ADDRSTRLEN
];
2814 unsigned int lo_ifindex
= 0;
2816 /* If IPv4 addresses are specified, then check that sysctl is configured correctly. */
2817 if (!lxc_list_empty(&netdev
->ipv4
)) {
2818 /* Check for net.ipv4.conf.[link].forwarding=1 */
2819 if (lxc_is_ip_forwarding_enabled(netdev
->link
, AF_INET
) < 0) {
2820 ERROR("Requires sysctl net.ipv4.conf.%s.forwarding=1", netdev
->link
);
2821 return minus_one_set_errno(EINVAL
);
2825 /* If IPv6 addresses are specified, then check that sysctl is configured correctly. */
2826 if (!lxc_list_empty(&netdev
->ipv6
)) {
2827 /* Check for net.ipv6.conf.[link].proxy_ndp=1 */
2828 if (lxc_is_ip_neigh_proxy_enabled(netdev
->link
, AF_INET6
) < 0) {
2829 ERROR("Requires sysctl net.ipv6.conf.%s.proxy_ndp=1", netdev
->link
);
2830 return minus_one_set_errno(EINVAL
);
2833 /* Check for net.ipv6.conf.[link].forwarding=1 */
2834 if (lxc_is_ip_forwarding_enabled(netdev
->link
, AF_INET6
) < 0) {
2835 ERROR("Requires sysctl net.ipv6.conf.%s.forwarding=1", netdev
->link
);
2836 return minus_one_set_errno(EINVAL
);
2840 /* Perform IPVLAN specific checks. */
2841 if (netdev
->type
== LXC_NET_IPVLAN
) {
2842 /* Check mode is l3s as other modes do not work with l2proxy. */
2843 if (netdev
->priv
.ipvlan_attr
.mode
!= IPVLAN_MODE_L3S
) {
2844 ERROR("Requires ipvlan mode on dev \"%s\" be l3s when used with l2proxy", netdev
->link
);
2845 return minus_one_set_errno(EINVAL
);
2848 /* Retrieve local-loopback interface index for use with IPVLAN static routes. */
2849 lo_ifindex
= if_nametoindex(loDev
);
2850 if (lo_ifindex
== 0) {
2851 ERROR("Failed to retrieve ifindex for \"%s\" routing cleanup", loDev
);
2852 return minus_one_set_errno(EINVAL
);
2856 lxc_list_for_each_safe(cur
, &netdev
->ipv4
, next
) {
2857 inet4dev
= cur
->elem
;
2858 if (!inet_ntop(AF_INET
, &inet4dev
->addr
, bufinet4
, sizeof(bufinet4
)))
2859 return minus_one_set_errno(-errno
);
2861 if (lxc_add_ip_neigh_proxy(bufinet4
, netdev
->link
) < 0)
2862 return minus_one_set_errno(EINVAL
);
2864 /* IPVLAN requires a route to local-loopback to trigger l2proxy. */
2865 if (netdev
->type
== LXC_NET_IPVLAN
) {
2866 err
= lxc_ipv4_dest_add(lo_ifindex
, &inet4dev
->addr
, 32);
2868 ERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"", bufinet4
, loDev
);
2869 return minus_one_set_errno(-err
);
2874 lxc_list_for_each_safe(cur
, &netdev
->ipv6
, next
) {
2875 inet6dev
= cur
->elem
;
2876 if (!inet_ntop(AF_INET6
, &inet6dev
->addr
, bufinet6
, sizeof(bufinet6
)))
2877 return minus_one_set_errno(-errno
);
2879 if (lxc_add_ip_neigh_proxy(bufinet6
, netdev
->link
) < 0)
2880 return minus_one_set_errno(EINVAL
);
2882 /* IPVLAN requires a route to local-loopback to trigger l2proxy. */
2883 if (netdev
->type
== LXC_NET_IPVLAN
) {
2884 err
= lxc_ipv6_dest_add(lo_ifindex
, &inet6dev
->addr
, 128);
2886 ERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"", bufinet6
, loDev
);
2887 return minus_one_set_errno(-err
);
2895 static int lxc_delete_ipv4_l2proxy(struct in_addr
*ip
, char *link
, unsigned int lo_ifindex
) {
2896 char bufinet4
[INET_ADDRSTRLEN
];
2897 unsigned int errCount
= 0;
2899 if (!inet_ntop(AF_INET
, ip
, bufinet4
, sizeof(bufinet4
))) {
2900 SYSERROR("Failed to convert IP for l2proxy ipv4 removal on dev \"%s\"", link
);
2901 return minus_one_set_errno(EINVAL
);
2904 /* If a local-loopback ifindex supplied remove the static route to the lo device. */
2905 if (lo_ifindex
> 0) {
2906 if (lxc_ipv4_dest_del(lo_ifindex
, ip
, 32) < 0) {
2908 ERROR("Failed to delete ipv4 dest \"%s\" for network ifindex \"%u\"", bufinet4
, lo_ifindex
);
2912 /* If link is supplied remove the IP neigh proxy entry for this IP on the device. */
2913 if (link
[0] != '\0') {
2914 if (lxc_del_ip_neigh_proxy(bufinet4
, link
) < 0)
2919 return minus_one_set_errno(EINVAL
);
2924 static int lxc_delete_ipv6_l2proxy(struct in6_addr
*ip
, char *link
, unsigned int lo_ifindex
) {
2925 char bufinet6
[INET6_ADDRSTRLEN
];
2926 unsigned int errCount
= 0;
2928 if (!inet_ntop(AF_INET6
, ip
, bufinet6
, sizeof(bufinet6
))) {
2929 SYSERROR("Failed to convert IP for l2proxy ipv6 removal on dev \"%s\"", link
);
2930 return minus_one_set_errno(EINVAL
);
2933 /* If a local-loopback ifindex supplied remove the static route to the lo device. */
2934 if (lo_ifindex
> 0) {
2935 if (lxc_ipv6_dest_del(lo_ifindex
, ip
, 128) < 0) {
2937 ERROR("Failed to delete ipv6 dest \"%s\" for network ifindex \"%u\"", bufinet6
, lo_ifindex
);
2941 /* If link is supplied remove the IP neigh proxy entry for this IP on the device. */
2942 if (link
[0] != '\0') {
2943 if (lxc_del_ip_neigh_proxy(bufinet6
, link
) < 0)
2948 return minus_one_set_errno(EINVAL
);
2953 static int lxc_delete_l2proxy(struct lxc_netdev
*netdev
) {
2954 unsigned int lo_ifindex
= 0;
2955 unsigned int errCount
= 0;
2956 struct lxc_list
*cur
, *next
;
2957 struct lxc_inetdev
*inet4dev
;
2958 struct lxc_inet6dev
*inet6dev
;
2960 /* Perform IPVLAN specific checks. */
2961 if (netdev
->type
== LXC_NET_IPVLAN
) {
2962 /* Retrieve local-loopback interface index for use with IPVLAN static routes. */
2963 lo_ifindex
= if_nametoindex(loDev
);
2964 if (lo_ifindex
== 0) {
2966 ERROR("Failed to retrieve ifindex for \"%s\" routing cleanup", loDev
);
2970 lxc_list_for_each_safe(cur
, &netdev
->ipv4
, next
) {
2971 inet4dev
= cur
->elem
;
2972 if (lxc_delete_ipv4_l2proxy(&inet4dev
->addr
, netdev
->link
, lo_ifindex
) < 0)
2976 lxc_list_for_each_safe(cur
, &netdev
->ipv6
, next
) {
2977 inet6dev
= cur
->elem
;
2978 if (lxc_delete_ipv6_l2proxy(&inet6dev
->addr
, netdev
->link
, lo_ifindex
) < 0)
2983 return minus_one_set_errno(EINVAL
);
2988 int lxc_create_network_priv(struct lxc_handler
*handler
)
2990 struct lxc_list
*iterator
;
2991 struct lxc_list
*network
= &handler
->conf
->network
;
2993 if (!handler
->am_root
)
2996 lxc_list_for_each(iterator
, network
) {
2997 struct lxc_netdev
*netdev
= iterator
->elem
;
2999 if (netdev
->type
< 0 || netdev
->type
> LXC_NET_MAXCONFTYPE
) {
3000 ERROR("Invalid network configuration type %d", netdev
->type
);
3004 /* Setup l2proxy entries if enabled and used with a link property */
3005 if (netdev
->l2proxy
&& netdev
->link
[0] != '\0') {
3006 if (lxc_setup_l2proxy(netdev
)) {
3007 ERROR("Failed to setup l2proxy");
3012 if (netdev_conf
[netdev
->type
](handler
, netdev
)) {
3013 ERROR("Failed to create network device");
3021 int lxc_network_move_created_netdev_priv(const char *lxcpath
, const char *lxcname
,
3022 struct lxc_list
*network
, pid_t pid
)
3025 char ifname
[IFNAMSIZ
];
3026 struct lxc_list
*iterator
;
3028 if (am_guest_unpriv())
3031 lxc_list_for_each(iterator
, network
) {
3032 struct lxc_netdev
*netdev
= iterator
->elem
;
3034 if (!netdev
->ifindex
)
3037 /* retrieve the name of the interface */
3038 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
3039 ERROR("No interface corresponding to ifindex \"%d\"",
3044 ret
= lxc_netdev_move_by_name(ifname
, pid
, NULL
);
3047 SYSERROR("Failed to move network device \"%s\" to "
3048 "network namespace %d", ifname
, pid
);
3052 DEBUG("Moved network device \"%s\"/\"%s\" to network namespace "
3054 ifname
, netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3061 int lxc_create_network_unpriv(const char *lxcpath
, const char *lxcname
,
3062 struct lxc_list
*network
, pid_t pid
, unsigned int hooks_version
)
3064 struct lxc_list
*iterator
;
3066 if (!am_guest_unpriv())
3069 lxc_list_for_each(iterator
, network
) {
3070 struct lxc_netdev
*netdev
= iterator
->elem
;
3072 if (netdev
->type
== LXC_NET_EMPTY
)
3075 if (netdev
->type
== LXC_NET_NONE
)
3078 if (netdev
->type
!= LXC_NET_VETH
) {
3079 ERROR("Networks of type %s are not supported by "
3080 "unprivileged containers",
3081 lxc_net_type_to_str(netdev
->type
));
3086 INFO("mtu ignored due to insufficient privilege");
3088 if (lxc_create_network_unpriv_exec(lxcpath
, lxcname
, netdev
, pid
, hooks_version
))
3095 bool lxc_delete_network_priv(struct lxc_handler
*handler
)
3098 struct lxc_list
*iterator
;
3099 struct lxc_list
*network
= &handler
->conf
->network
;
3101 lxc_list_for_each(iterator
, network
) {
3102 char *hostveth
= NULL
;
3103 struct lxc_netdev
*netdev
= iterator
->elem
;
3105 /* We can only delete devices whose ifindex we have. If we don't
3106 * have the index it means that we didn't create it.
3108 if (!netdev
->ifindex
)
3111 /* Delete l2proxy entries if enabled and used with a link property */
3112 if (netdev
->l2proxy
&& netdev
->link
[0] != '\0') {
3113 if (lxc_delete_l2proxy(netdev
))
3114 WARN("Failed to delete all l2proxy config");
3115 /* Don't return, let the network be cleaned up as normal. */
3118 if (netdev
->type
== LXC_NET_PHYS
) {
3119 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
, netdev
->link
);
3121 WARN("Failed to rename interface with index %d "
3122 "from \"%s\" to its initial name \"%s\"",
3123 netdev
->ifindex
, netdev
->name
, netdev
->link
);
3125 TRACE("Renamed interface with index %d from "
3126 "\"%s\" to its initial name \"%s\"",
3127 netdev
->ifindex
, netdev
->name
,
3129 goto clear_ifindices
;
3132 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
3134 WARN("Failed to deconfigure network device");
3136 /* Recent kernels remove the virtual interfaces when the network
3137 * namespace is destroyed but in case we did not move the
3138 * interface to the network namespace, we have to destroy it.
3140 ret
= lxc_netdev_delete_by_index(netdev
->ifindex
);
3142 if (errno
!= ENODEV
) {
3143 WARN("Failed to remove interface \"%s\" with index %d",
3144 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3146 goto clear_ifindices
;
3148 INFO("Interface \"%s\" with index %d already deleted or existing in different network namespace",
3149 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3152 INFO("Removed interface \"%s\" with index %d",
3153 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
3156 if (netdev
->type
!= LXC_NET_VETH
)
3157 goto clear_ifindices
;
3159 /* Explicitly delete host veth device to prevent lingering
3160 * devices. We had issues in LXD around this.
3162 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
3163 hostveth
= netdev
->priv
.veth_attr
.pair
;
3165 hostveth
= netdev
->priv
.veth_attr
.veth1
;
3166 if (hostveth
[0] == '\0')
3167 goto clear_ifindices
;
3169 ret
= lxc_netdev_delete_by_name(hostveth
);
3171 WARN("Failed to remove interface \"%s\" from \"%s\"",
3172 hostveth
, netdev
->link
);
3173 goto clear_ifindices
;
3175 INFO("Removed interface \"%s\" from \"%s\"", hostveth
, netdev
->link
);
3177 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
)) {
3178 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
3179 netdev
->ifindex
= 0;
3180 netdev
->priv
.veth_attr
.ifindex
= 0;
3181 goto clear_ifindices
;
3184 /* Delete the openvswitch port. */
3185 ret
= lxc_ovs_delete_port(netdev
->link
, hostveth
);
3187 WARN("Failed to remove port \"%s\" from openvswitch "
3188 "bridge \"%s\"", hostveth
, netdev
->link
);
3190 INFO("Removed port \"%s\" from openvswitch bridge \"%s\"",
3191 hostveth
, netdev
->link
);
3194 /* We need to clear any ifindices we recorded so liblxc won't
3195 * have cached stale data which would cause it to fail on reboot
3196 * we're we don't re-read the on-disk config file.
3198 netdev
->ifindex
= 0;
3199 if (netdev
->type
== LXC_NET_PHYS
) {
3200 netdev
->priv
.phys_attr
.ifindex
= 0;
3201 } else if (netdev
->type
== LXC_NET_VETH
) {
3202 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
3203 netdev
->priv
.veth_attr
.ifindex
= 0;
3210 int lxc_requests_empty_network(struct lxc_handler
*handler
)
3212 struct lxc_list
*network
= &handler
->conf
->network
;
3213 struct lxc_list
*iterator
;
3214 bool found_none
= false, found_nic
= false;
3216 if (lxc_list_empty(network
))
3219 lxc_list_for_each(iterator
, network
) {
3220 struct lxc_netdev
*netdev
= iterator
->elem
;
3222 if (netdev
->type
== LXC_NET_NONE
)
3227 if (found_none
&& !found_nic
)
3232 /* try to move physical nics to the init netns */
3233 int lxc_restore_phys_nics_to_netns(struct lxc_handler
*handler
)
3237 char ifname
[IFNAMSIZ
];
3238 struct lxc_list
*iterator
;
3239 int netnsfd
= handler
->nsfd
[LXC_NS_NET
];
3240 struct lxc_conf
*conf
= handler
->conf
;
3242 /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
3243 * the parent network namespace. We won't have this capability if we are
3246 if (!handler
->am_root
)
3249 TRACE("Moving physical network devices back to parent network namespace");
3251 oldfd
= lxc_preserve_ns(lxc_raw_getpid(), "net");
3253 SYSERROR("Failed to preserve network namespace");
3257 ret
= setns(netnsfd
, CLONE_NEWNET
);
3259 SYSERROR("Failed to enter network namespace");
3264 lxc_list_for_each(iterator
, &conf
->network
) {
3265 struct lxc_netdev
*netdev
= iterator
->elem
;
3267 if (netdev
->type
!= LXC_NET_PHYS
)
3270 /* Retrieve the name of the interface in the container's network
3273 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
3274 WARN("No interface corresponding to ifindex %d",
3279 ret
= lxc_netdev_move_by_name(ifname
, 1, netdev
->link
);
3281 WARN("Error moving network device \"%s\" back to "
3282 "network namespace", ifname
);
3284 TRACE("Moved network device \"%s\" back to network "
3285 "namespace", ifname
);
3288 ret
= setns(oldfd
, CLONE_NEWNET
);
3291 SYSERROR("Failed to enter network namespace");
3298 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
3300 struct sockaddr sockaddr
;
3304 ret
= lxc_convert_mac(hwaddr
, &sockaddr
);
3307 SYSERROR("Mac address \"%s\" conversion failed", hwaddr
);
3311 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
3312 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
3313 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
3315 fd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0);
3319 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
3321 SYSERROR("Failed to perform ioctl");
3325 DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr
,
3331 static int setup_ipv4_addr(struct lxc_list
*ip
, int ifindex
)
3333 struct lxc_list
*iterator
;
3336 lxc_list_for_each(iterator
, ip
) {
3337 struct lxc_inetdev
*inetdev
= iterator
->elem
;
3339 err
= lxc_ipv4_addr_add(ifindex
, &inetdev
->addr
,
3340 &inetdev
->bcast
, inetdev
->prefix
);
3343 SYSERROR("Failed to setup ipv4 address for network device "
3344 "with ifindex %d", ifindex
);
3352 static int setup_ipv6_addr(struct lxc_list
*ip
, int ifindex
)
3354 struct lxc_list
*iterator
;
3357 lxc_list_for_each(iterator
, ip
) {
3358 struct lxc_inet6dev
*inet6dev
= iterator
->elem
;
3360 err
= lxc_ipv6_addr_add(ifindex
, &inet6dev
->addr
,
3361 &inet6dev
->mcast
, &inet6dev
->acast
,
3365 SYSERROR("Failed to setup ipv6 address for network device "
3366 "with ifindex %d", ifindex
);
3374 static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev
*netdev
)
3376 char ifname
[IFNAMSIZ
];
3378 const char *net_type_name
;
3379 char *current_ifname
= ifname
;
3381 /* empty network namespace */
3382 if (!netdev
->ifindex
) {
3383 if (netdev
->flags
& IFF_UP
) {
3384 err
= lxc_netdev_up("lo");
3387 SYSERROR("Failed to set the loopback network device up");
3392 if (netdev
->type
== LXC_NET_EMPTY
)
3395 if (netdev
->type
== LXC_NET_NONE
)
3398 if (netdev
->type
!= LXC_NET_VETH
) {
3399 net_type_name
= lxc_net_type_to_str(netdev
->type
);
3400 ERROR("%s networks are not supported for containers "
3401 "not setup up by privileged users", net_type_name
);
3405 netdev
->ifindex
= if_nametoindex(netdev
->name
);
3408 /* get the new ifindex in case of physical netdev */
3409 if (netdev
->type
== LXC_NET_PHYS
) {
3410 netdev
->ifindex
= if_nametoindex(netdev
->link
);
3411 if (!netdev
->ifindex
) {
3412 ERROR("Failed to get ifindex for network device \"%s\"",
3418 /* retrieve the name of the interface */
3419 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
3420 ERROR("Failed get name for network device with ifindex %d",
3425 /* Default: let the system to choose one interface name.
3426 * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
3427 * netlink will replace the format specifier with an appropriate index.
3429 if (netdev
->name
[0] == '\0') {
3430 if (netdev
->type
== LXC_NET_PHYS
)
3431 (void)strlcpy(netdev
->name
, netdev
->link
, IFNAMSIZ
);
3433 (void)strlcpy(netdev
->name
, "eth%d", IFNAMSIZ
);
3436 /* rename the interface name */
3437 if (strcmp(ifname
, netdev
->name
) != 0) {
3438 err
= lxc_netdev_rename_by_name(ifname
, netdev
->name
);
3441 SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
3442 ifname
, netdev
->name
);
3447 /* Re-read the name of the interface because its name has changed
3448 * and would be automatically allocated by the system
3450 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
3451 ERROR("Failed get name for network device with ifindex %d",
3456 /* Now update the recorded name of the network device to reflect the
3457 * name of the network device in the child's network namespace. We will
3458 * later on send this information back to the parent.
3460 (void)strlcpy(netdev
->name
, current_ifname
, IFNAMSIZ
);
3462 /* set a mac address */
3463 if (netdev
->hwaddr
) {
3464 if (setup_hw_addr(netdev
->hwaddr
, current_ifname
)) {
3465 ERROR("Failed to setup hw address for network device \"%s\"",
3471 /* setup ipv4 addresses on the interface */
3472 if (setup_ipv4_addr(&netdev
->ipv4
, netdev
->ifindex
)) {
3473 ERROR("Failed to setup ip addresses for network device \"%s\"",
3478 /* setup ipv6 addresses on the interface */
3479 if (setup_ipv6_addr(&netdev
->ipv6
, netdev
->ifindex
)) {
3480 ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
3485 /* set the network device up */
3486 if (netdev
->flags
& IFF_UP
) {
3487 err
= lxc_netdev_up(current_ifname
);
3490 SYSERROR("Failed to set network device \"%s\" up",
3495 /* the network is up, make the loopback up too */
3496 err
= lxc_netdev_up("lo");
3499 SYSERROR("Failed to set the loopback network device up");
3504 /* We can only set up the default routes after bringing
3505 * up the interface, since bringing up the interface adds
3506 * the link-local routes and we can't add a default
3507 * route if the gateway is not reachable. */
3509 /* setup ipv4 gateway on the interface */
3510 if (netdev
->ipv4_gateway
|| netdev
->ipv4_gateway_dev
) {
3511 if (!(netdev
->flags
& IFF_UP
)) {
3512 ERROR("Cannot add ipv4 gateway for network device "
3513 "\"%s\" when not bringing up the interface", ifname
);
3517 if (lxc_list_empty(&netdev
->ipv4
)) {
3518 ERROR("Cannot add ipv4 gateway for network device "
3519 "\"%s\" when not assigning an address", ifname
);
3523 /* Setup device route if ipv4_gateway_dev is enabled */
3524 if (netdev
->ipv4_gateway_dev
) {
3525 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, NULL
);
3527 SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
3529 return minus_one_set_errno(-err
);
3532 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
3534 err
= lxc_ipv4_dest_add(netdev
->ifindex
, netdev
->ipv4_gateway
, 32);
3537 SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
3541 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
3544 SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
3547 if (netdev
->ipv4_gateway_auto
) {
3548 char buf
[INET_ADDRSTRLEN
];
3549 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
3550 ERROR("Tried to set autodetected ipv4 gateway \"%s\"", buf
);
3558 /* setup ipv6 gateway on the interface */
3559 if (netdev
->ipv6_gateway
|| netdev
->ipv6_gateway_dev
) {
3560 if (!(netdev
->flags
& IFF_UP
)) {
3561 ERROR("Cannot add ipv6 gateway for network device "
3562 "\"%s\" when not bringing up the interface", ifname
);
3566 if (lxc_list_empty(&netdev
->ipv6
) && !IN6_IS_ADDR_LINKLOCAL(netdev
->ipv6_gateway
)) {
3567 ERROR("Cannot add ipv6 gateway for network device "
3568 "\"%s\" when not assigning an address", ifname
);
3572 /* Setup device route if ipv6_gateway_dev is enabled */
3573 if (netdev
->ipv6_gateway_dev
) {
3574 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, NULL
);
3576 SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
3578 return minus_one_set_errno(-err
);
3581 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3583 err
= lxc_ipv6_dest_add(netdev
->ifindex
, netdev
->ipv6_gateway
, 128);
3586 SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
3590 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3593 SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
3596 if (netdev
->ipv6_gateway_auto
) {
3597 char buf
[INET6_ADDRSTRLEN
];
3598 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
3599 ERROR("Tried to set autodetected ipv6 "
3600 "gateway for network device "
3609 DEBUG("Network device \"%s\" has been setup", current_ifname
);
3614 int lxc_setup_network_in_child_namespaces(const struct lxc_conf
*conf
,
3615 struct lxc_list
*network
)
3617 struct lxc_list
*iterator
;
3618 struct lxc_netdev
*netdev
;
3620 lxc_list_for_each(iterator
, network
) {
3621 netdev
= iterator
->elem
;
3623 if (lxc_setup_netdev_in_child_namespaces(netdev
)) {
3624 ERROR("failed to setup netdev");
3629 if (!lxc_list_empty(network
))
3630 INFO("network has been setup");
3635 int lxc_network_send_veth_names_to_child(struct lxc_handler
*handler
)
3637 struct lxc_list
*iterator
;
3638 struct lxc_list
*network
= &handler
->conf
->network
;
3639 int data_sock
= handler
->data_sock
[0];
3641 if (handler
->am_root
)
3644 lxc_list_for_each(iterator
, network
) {
3646 struct lxc_netdev
*netdev
= iterator
->elem
;
3648 if (netdev
->type
!= LXC_NET_VETH
)
3651 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3654 TRACE("Sent network device name \"%s\" to child", netdev
->name
);
3660 int lxc_network_recv_veth_names_from_parent(struct lxc_handler
*handler
)
3662 struct lxc_list
*iterator
;
3663 struct lxc_list
*network
= &handler
->conf
->network
;
3664 int data_sock
= handler
->data_sock
[1];
3666 if (handler
->am_root
)
3669 lxc_list_for_each(iterator
, network
) {
3671 struct lxc_netdev
*netdev
= iterator
->elem
;
3673 if (netdev
->type
!= LXC_NET_VETH
)
3676 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3679 TRACE("Received network device name \"%s\" from parent", netdev
->name
);
3685 int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler
*handler
)
3687 struct lxc_list
*iterator
, *network
;
3688 int data_sock
= handler
->data_sock
[0];
3690 if (!handler
->am_root
)
3693 network
= &handler
->conf
->network
;
3694 lxc_list_for_each(iterator
, network
) {
3696 struct lxc_netdev
*netdev
= iterator
->elem
;
3698 /* Send network device name in the child's namespace to parent. */
3699 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3703 /* Send network device ifindex in the child's namespace to
3706 ret
= lxc_send_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), MSG_NOSIGNAL
);
3711 TRACE("Sent network device names and ifindices to parent");
3715 int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler
*handler
)
3717 struct lxc_list
*iterator
, *network
;
3718 int data_sock
= handler
->data_sock
[1];
3720 if (!handler
->am_root
)
3723 network
= &handler
->conf
->network
;
3724 lxc_list_for_each(iterator
, network
) {
3726 struct lxc_netdev
*netdev
= iterator
->elem
;
3728 /* Receive network device name in the child's namespace to
3731 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3735 /* Receive network device ifindex in the child's namespace to
3738 ret
= lxc_recv_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), 0);
3746 void lxc_delete_network(struct lxc_handler
*handler
)
3750 if (handler
->am_root
)
3751 bret
= lxc_delete_network_priv(handler
);
3753 bret
= lxc_delete_network_unpriv(handler
);
3755 DEBUG("Failed to delete network devices");
3757 DEBUG("Deleted network devices");
3760 int lxc_netns_set_nsid(int fd
)
3763 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3764 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3766 struct nl_handler nlh
;
3767 struct nlmsghdr
*hdr
;
3768 struct rtgenmsg
*msg
;
3770 const __s32 ns_id
= -1;
3771 const __u32 netns_fd
= fd
;
3773 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3777 memset(buf
, 0, sizeof(buf
));
3779 #pragma GCC diagnostic push
3780 #pragma GCC diagnostic ignored "-Wcast-align"
3781 hdr
= (struct nlmsghdr
*)buf
;
3782 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3783 #pragma GCC diagnostic pop
3785 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3786 hdr
->nlmsg_type
= RTM_NEWNSID
;
3787 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3789 hdr
->nlmsg_seq
= RTM_NEWNSID
;
3790 msg
->rtgen_family
= AF_UNSPEC
;
3792 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3796 ret
= addattr(hdr
, 1024, __LXC_NETNSA_NSID
, &ns_id
, sizeof(ns_id
));
3800 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3803 saved_errno
= errno
;
3804 netlink_close(&nlh
);
3805 errno
= saved_errno
;
3810 static int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
3813 memset(tb
, 0, sizeof(struct rtattr
*) * (max
+ 1));
3815 while (RTA_OK(rta
, len
)) {
3816 unsigned short type
= rta
->rta_type
;
3818 if ((type
<= max
) && (!tb
[type
]))
3821 #pragma GCC diagnostic push
3822 #pragma GCC diagnostic ignored "-Wcast-align"
3823 rta
= RTA_NEXT(rta
, len
);
3824 #pragma GCC diagnostic pop
3830 static inline __s32
rta_getattr_s32(const struct rtattr
*rta
)
3832 return *(__s32
*)RTA_DATA(rta
);
3836 #define NETNS_RTA(r) \
3837 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
3840 int lxc_netns_get_nsid(int fd
)
3844 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3845 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3847 struct rtattr
*tb
[__LXC_NETNSA_MAX
+ 1];
3848 struct nl_handler nlh
;
3849 struct nlmsghdr
*hdr
;
3850 struct rtgenmsg
*msg
;
3852 __u32 netns_fd
= fd
;
3854 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3858 memset(buf
, 0, sizeof(buf
));
3860 #pragma GCC diagnostic push
3861 #pragma GCC diagnostic ignored "-Wcast-align"
3862 hdr
= (struct nlmsghdr
*)buf
;
3863 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3864 #pragma GCC diagnostic pop
3866 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3867 hdr
->nlmsg_type
= RTM_GETNSID
;
3868 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3870 hdr
->nlmsg_seq
= RTM_GETNSID
;
3871 msg
->rtgen_family
= AF_UNSPEC
;
3873 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3875 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3877 saved_errno
= errno
;
3878 netlink_close(&nlh
);
3879 errno
= saved_errno
;
3884 msg
= NLMSG_DATA(hdr
);
3885 len
= hdr
->nlmsg_len
- NLMSG_SPACE(sizeof(*msg
));
3889 #pragma GCC diagnostic push
3890 #pragma GCC diagnostic ignored "-Wcast-align"
3891 parse_rtattr(tb
, __LXC_NETNSA_MAX
, NETNS_RTA(msg
), len
);
3892 if (tb
[__LXC_NETNSA_NSID
])
3893 return rta_getattr_s32(tb
[__LXC_NETNSA_NSID
]);
3894 #pragma GCC diagnostic pop