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
33 #include <arpa/inet.h>
34 #include <linux/netlink.h>
35 #include <linux/rtnetlink.h>
36 #include <linux/sockios.h>
37 #include <net/ethernet.h>
39 #include <net/if_arp.h>
40 #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>
51 #include "file_utils.h"
61 #include <../include/ifaddrs.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 instantiate_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
74 int bridge_index
, err
;
76 char veth1buf
[IFNAMSIZ
], veth2buf
[IFNAMSIZ
];
79 if (netdev
->priv
.veth_attr
.pair
[0] != '\0') {
80 veth1
= netdev
->priv
.veth_attr
.pair
;
81 if (handler
->conf
->reboot
)
82 lxc_netdev_delete_by_name(veth1
);
84 err
= snprintf(veth1buf
, sizeof(veth1buf
), "vethXXXXXX");
85 if (err
< 0 || (size_t)err
>= sizeof(veth1buf
))
88 veth1
= lxc_mkifname(veth1buf
);
92 /* store away for deconf */
93 memcpy(netdev
->priv
.veth_attr
.veth1
, veth1
, IFNAMSIZ
);
96 err
= snprintf(veth2buf
, sizeof(veth2buf
), "vethXXXXXX");
97 if (err
< 0 || (size_t)err
>= sizeof(veth2buf
))
100 veth2
= lxc_mkifname(veth2buf
);
104 err
= lxc_veth_create(veth1
, veth2
);
107 SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1
, veth2
);
111 /* changing the high byte of the mac address to 0xfe, the bridge interface
112 * will always keep the host's mac address and not take the mac address
114 err
= setup_private_host_hw_addr(veth1
);
117 SYSERROR("Failed to change mac address of host interface \"%s\"", veth1
);
121 /* Retrieve ifindex of the host's veth device. */
122 netdev
->priv
.veth_attr
.ifindex
= if_nametoindex(veth1
);
123 if (!netdev
->priv
.veth_attr
.ifindex
) {
124 ERROR("Failed to retrieve ifindex for \"%s\"", veth1
);
128 /* Note that we're retrieving the container's ifindex in the host's
129 * network namespace because we need it to move the device from the
130 * host's network namespace to the container's network namespace later
133 netdev
->ifindex
= if_nametoindex(veth2
);
134 if (!netdev
->ifindex
) {
135 ERROR("Failed to retrieve ifindex for \"%s\"", veth2
);
140 if (lxc_safe_uint(netdev
->mtu
, &mtu
) < 0)
141 WARN("Failed to parse mtu");
143 INFO("Retrieved mtu %d", mtu
);
144 } else if (netdev
->link
[0] != '\0') {
145 bridge_index
= if_nametoindex(netdev
->link
);
147 mtu
= netdev_get_mtu(bridge_index
);
148 INFO("Retrieved mtu %d from %s", mtu
, netdev
->link
);
150 mtu
= netdev_get_mtu(netdev
->ifindex
);
151 INFO("Retrieved mtu %d from %s", mtu
, veth2
);
156 err
= lxc_netdev_set_mtu(veth1
, mtu
);
158 err
= lxc_netdev_set_mtu(veth2
, mtu
);
162 SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
163 "and \"%s\"", mtu
, veth1
, veth2
);
168 if (netdev
->link
[0] != '\0') {
169 err
= lxc_bridge_attach(netdev
->link
, veth1
);
172 SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
173 veth1
, netdev
->link
);
176 INFO("Attached \"%s\" to bridge \"%s\"", veth1
, netdev
->link
);
179 err
= lxc_netdev_up(veth1
);
182 SYSERROR("Failed to set \"%s\" up", veth1
);
186 if (netdev
->upscript
) {
194 err
= run_script_argv(handler
->name
,
195 handler
->conf
->hooks_version
, "net",
196 netdev
->upscript
, "up", argv
);
201 DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1
, veth2
,
207 if (netdev
->ifindex
!= 0)
208 lxc_netdev_delete_by_name(veth1
);
212 static int instantiate_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
214 char peerbuf
[IFNAMSIZ
], *peer
;
217 if (netdev
->link
[0] == '\0') {
218 ERROR("No link for macvlan network device specified");
222 err
= snprintf(peerbuf
, sizeof(peerbuf
), "mcXXXXXX");
223 if (err
< 0 || (size_t)err
>= sizeof(peerbuf
))
226 peer
= lxc_mkifname(peerbuf
);
230 err
= lxc_macvlan_create(netdev
->link
, peer
,
231 netdev
->priv
.macvlan_attr
.mode
);
234 SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
239 netdev
->ifindex
= if_nametoindex(peer
);
240 if (!netdev
->ifindex
) {
241 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
245 if (netdev
->upscript
) {
252 err
= run_script_argv(handler
->name
,
253 handler
->conf
->hooks_version
, "net",
254 netdev
->upscript
, "up", argv
);
259 DEBUG("Instantiated macvlan \"%s\" with ifindex is %d and mode %d",
260 peer
, netdev
->ifindex
, netdev
->priv
.macvlan_attr
.mode
);
265 lxc_netdev_delete_by_name(peer
);
269 static int instantiate_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
273 static uint16_t vlan_cntr
= 0;
274 unsigned int mtu
= 0;
276 if (netdev
->link
[0] == '\0') {
277 ERROR("No link for vlan network device specified");
281 err
= snprintf(peer
, sizeof(peer
), "vlan%d-%d", netdev
->priv
.vlan_attr
.vid
, vlan_cntr
++);
282 if (err
< 0 || (size_t)err
>= sizeof(peer
))
285 err
= lxc_vlan_create(netdev
->link
, peer
, netdev
->priv
.vlan_attr
.vid
);
288 SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
293 netdev
->ifindex
= if_nametoindex(peer
);
294 if (!netdev
->ifindex
) {
295 ERROR("Failed to retrieve ifindex for \"%s\"", peer
);
296 lxc_netdev_delete_by_name(peer
);
300 DEBUG("Instantiated vlan \"%s\" with ifindex is \"%d\" (vlan1000)",
301 peer
, netdev
->ifindex
);
303 if (lxc_safe_uint(netdev
->mtu
, &mtu
) < 0) {
304 ERROR("Failed to retrieve mtu from \"%d\"/\"%s\".",
306 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)");
310 err
= lxc_netdev_set_mtu(peer
, mtu
);
313 SYSERROR("Failed to set mtu \"%s\" for \"%s\"",
315 lxc_netdev_delete_by_name(peer
);
323 static int instantiate_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
332 if (netdev
->link
[0] == '\0') {
333 ERROR("No link for physical interface specified");
337 /* Note that we're retrieving the container's ifindex in the host's
338 * network namespace because we need it to move the device from the
339 * host's network namespace to the container's network namespace later
341 * Note that netdev->link will contain the name of the physical network
342 * device in the host's namespace.
344 netdev
->ifindex
= if_nametoindex(netdev
->link
);
345 if (!netdev
->ifindex
) {
346 ERROR("Failed to retrieve ifindex for \"%s\"", netdev
->link
);
350 /* Store the ifindex of the host's network device in the host's
353 netdev
->priv
.phys_attr
.ifindex
= netdev
->ifindex
;
355 if (!netdev
->upscript
)
358 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
359 "net", netdev
->upscript
, "up", argv
);
366 static int instantiate_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
375 if (!netdev
->upscript
)
378 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
379 "net", netdev
->upscript
, "up", argv
);
386 static int instantiate_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
392 static instantiate_cb netdev_conf
[LXC_NET_MAXCONFTYPE
+ 1] = {
393 [LXC_NET_VETH
] = instantiate_veth
,
394 [LXC_NET_MACVLAN
] = instantiate_macvlan
,
395 [LXC_NET_VLAN
] = instantiate_vlan
,
396 [LXC_NET_PHYS
] = instantiate_phys
,
397 [LXC_NET_EMPTY
] = instantiate_empty
,
398 [LXC_NET_NONE
] = instantiate_none
,
401 static int shutdown_veth(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
411 if (!netdev
->downscript
)
414 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
415 argv
[2] = netdev
->priv
.veth_attr
.pair
;
417 argv
[2] = netdev
->priv
.veth_attr
.veth1
;
419 ret
= run_script_argv(handler
->name
,
420 handler
->conf
->hooks_version
, "net",
421 netdev
->downscript
, "down", argv
);
428 static int shutdown_macvlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
437 if (!netdev
->downscript
)
440 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
441 "net", netdev
->downscript
, "down", argv
);
448 static int shutdown_vlan(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
453 static int shutdown_phys(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
462 if (!netdev
->downscript
)
465 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
466 "net", netdev
->downscript
, "down", argv
);
473 static int shutdown_empty(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
481 if (!netdev
->downscript
)
484 ret
= run_script_argv(handler
->name
, handler
->conf
->hooks_version
,
485 "net", netdev
->downscript
, "down", argv
);
492 static int shutdown_none(struct lxc_handler
*handler
, struct lxc_netdev
*netdev
)
497 static instantiate_cb netdev_deconf
[LXC_NET_MAXCONFTYPE
+ 1] = {
498 [LXC_NET_VETH
] = shutdown_veth
,
499 [LXC_NET_MACVLAN
] = shutdown_macvlan
,
500 [LXC_NET_VLAN
] = shutdown_vlan
,
501 [LXC_NET_PHYS
] = shutdown_phys
,
502 [LXC_NET_EMPTY
] = shutdown_empty
,
503 [LXC_NET_NONE
] = shutdown_none
,
506 int lxc_netdev_move_by_index(int ifindex
, pid_t pid
, const char *ifname
)
509 struct nl_handler nlh
;
510 struct ifinfomsg
*ifi
;
511 struct nlmsg
*nlmsg
= NULL
;
513 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
518 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
522 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
523 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
525 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
528 ifi
->ifi_family
= AF_UNSPEC
;
529 ifi
->ifi_index
= ifindex
;
531 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
534 if (ifname
!= NULL
) {
535 if (nla_put_string(nlmsg
, IFLA_IFNAME
, ifname
))
539 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
546 /* If we are asked to move a wireless interface, then we must actually move its
547 * phyN device. Detect that condition and return the physname here. The physname
548 * will be passed to lxc_netdev_move_wlan() which will free it when done.
550 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
551 static char *is_wlan(const char *ifname
)
558 char *physname
= NULL
;
560 len
= strlen(ifname
) + strlen(PHYSNAME
) - 1;
561 path
= alloca(len
+ 1);
562 ret
= snprintf(path
, len
, PHYSNAME
, ifname
);
563 if (ret
< 0 || (size_t)ret
>= len
)
566 f
= fopen(path
, "r");
570 /* Feh - sb.st_size is always 4096. */
571 fseek(f
, 0, SEEK_END
);
573 fseek(f
, 0, SEEK_SET
);
579 physname
= malloc(physlen
+ 1);
585 memset(physname
, 0, physlen
+ 1);
586 ret
= fread(physname
, 1, physlen
, f
);
591 for (i
= 0; i
< physlen
; i
++) {
592 if (physname
[i
] == '\n')
595 if (physname
[i
] == '\0')
606 static int lxc_netdev_rename_by_name_in_netns(pid_t pid
, const char *old
,
616 return wait_for_pid(fpid
);
618 if (!switch_to_ns(pid
, "net"))
621 _exit(lxc_netdev_rename_by_name(old
, new));
624 static int lxc_netdev_move_wlan(char *physname
, const char *ifname
, pid_t pid
,
631 /* Move phyN into the container. TODO - do this using netlink.
632 * However, IIUC this involves a bit more complicated work to talk to
633 * the 80211 module, so for now just call out to iw.
635 cmd
= on_path("iw", NULL
);
646 sprintf(pidstr
, "%d", pid
);
647 execlp("iw", "iw", "phy", physname
, "set", "netns", pidstr
,
652 if (wait_for_pid(fpid
))
657 err
= lxc_netdev_rename_by_name_in_netns(pid
, ifname
, newname
);
664 int lxc_netdev_move_by_name(const char *ifname
, pid_t pid
, const char* newname
)
672 index
= if_nametoindex(ifname
);
676 physname
= is_wlan(ifname
);
678 return lxc_netdev_move_wlan(physname
, ifname
, pid
, newname
);
680 return lxc_netdev_move_by_index(index
, pid
, newname
);
683 int lxc_netdev_delete_by_index(int ifindex
)
686 struct ifinfomsg
*ifi
;
687 struct nl_handler nlh
;
688 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
690 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
695 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
699 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
703 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
704 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_DELLINK
;
706 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
709 ifi
->ifi_family
= AF_UNSPEC
;
710 ifi
->ifi_index
= ifindex
;
712 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
720 int lxc_netdev_delete_by_name(const char *name
)
724 index
= if_nametoindex(name
);
728 return lxc_netdev_delete_by_index(index
);
731 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
734 struct ifinfomsg
*ifi
;
735 struct nl_handler nlh
;
736 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
738 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
742 len
= strlen(newname
);
743 if (len
== 1 || len
>= IFNAMSIZ
)
747 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
751 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
755 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
| NLM_F_REQUEST
;
756 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
758 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
761 ifi
->ifi_family
= AF_UNSPEC
;
762 ifi
->ifi_index
= ifindex
;
764 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
767 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
775 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
779 len
= strlen(oldname
);
780 if (len
== 1 || len
>= IFNAMSIZ
)
783 index
= if_nametoindex(oldname
);
787 return lxc_netdev_rename_by_index(index
, newname
);
790 int netdev_set_flag(const char *name
, int flag
)
793 struct ifinfomsg
*ifi
;
794 struct nl_handler nlh
;
795 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
797 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
803 if (len
== 1 || len
>= IFNAMSIZ
)
807 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
811 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
816 index
= if_nametoindex(name
);
820 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
821 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
823 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
828 ifi
->ifi_family
= AF_UNSPEC
;
829 ifi
->ifi_index
= index
;
830 ifi
->ifi_change
|= IFF_UP
;
831 ifi
->ifi_flags
|= flag
;
833 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
841 int netdev_get_flag(const char *name
, int *flag
)
844 struct ifinfomsg
*ifi
;
845 struct nl_handler nlh
;
846 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
851 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
857 if (len
== 1 || len
>= IFNAMSIZ
)
861 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
865 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
870 index
= if_nametoindex(name
);
874 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
;
875 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
877 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
882 ifi
->ifi_family
= AF_UNSPEC
;
883 ifi
->ifi_index
= index
;
885 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
889 ifi
= NLMSG_DATA(answer
->nlmsghdr
);
891 *flag
= ifi
->ifi_flags
;
900 * \brief Check a interface is up or not.
902 * \param name: name for the interface.
905 * 0 means interface is down.
906 * 1 means interface is up.
907 * Others means error happened, and ret-value is the error number.
909 int lxc_netdev_isup(const char *name
)
913 err
= netdev_get_flag(name
, &flag
);
923 int netdev_get_mtu(int ifindex
)
925 int answer_len
, err
, res
;
926 struct nl_handler nlh
;
927 struct ifinfomsg
*ifi
;
928 struct nlmsghdr
*msg
;
929 int readmore
= 0, recv_len
= 0;
930 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
932 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
937 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
941 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
945 /* Save the answer buffer length, since it will be overwritten
946 * on the first receive (and we might need to receive more than
949 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
951 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
952 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
954 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
957 ifi
->ifi_family
= AF_UNSPEC
;
959 /* Send the request for addresses, which returns all addresses
960 * on all interfaces. */
961 err
= netlink_send(&nlh
, nlmsg
);
965 #pragma GCC diagnostic push
966 #pragma GCC diagnostic ignored "-Wcast-align"
969 /* Restore the answer buffer length, it might have been
970 * overwritten by a previous receive.
972 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
974 /* Get the (next) batch of reply messages */
975 err
= netlink_rcv(&nlh
, answer
);
981 /* Satisfy the typing for the netlink macros */
982 msg
= answer
->nlmsghdr
;
984 while (NLMSG_OK(msg
, recv_len
)) {
986 /* Stop reading if we see an error message */
987 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
988 struct nlmsgerr
*errmsg
=
989 (struct nlmsgerr
*)NLMSG_DATA(msg
);
994 /* Stop reading if we see a NLMSG_DONE message */
995 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1000 ifi
= NLMSG_DATA(msg
);
1001 if (ifi
->ifi_index
== ifindex
) {
1002 struct rtattr
*rta
= IFLA_RTA(ifi
);
1004 msg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
1006 while (RTA_OK(rta
, attr_len
)) {
1007 /* Found a local address for the
1008 * requested interface, return it.
1010 if (rta
->rta_type
== IFLA_MTU
) {
1011 memcpy(&res
, RTA_DATA(rta
),
1016 rta
= RTA_NEXT(rta
, attr_len
);
1020 /* Keep reading more data from the socket if the last
1021 * message had the NLF_F_MULTI flag set.
1023 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1025 /* Look at the next message received in this buffer. */
1026 msg
= NLMSG_NEXT(msg
, recv_len
);
1030 #pragma GCC diagnostic pop
1032 /* If we end up here, we didn't find any result, so signal an error. */
1036 netlink_close(&nlh
);
1042 int lxc_netdev_set_mtu(const char *name
, int mtu
)
1044 int err
, index
, len
;
1045 struct ifinfomsg
*ifi
;
1046 struct nl_handler nlh
;
1047 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1049 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1055 if (len
== 1 || len
>= IFNAMSIZ
)
1059 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1063 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1068 index
= if_nametoindex(name
);
1072 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1073 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1075 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1080 ifi
->ifi_family
= AF_UNSPEC
;
1081 ifi
->ifi_index
= index
;
1083 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
1086 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1088 netlink_close(&nlh
);
1094 int lxc_netdev_up(const char *name
)
1096 return netdev_set_flag(name
, IFF_UP
);
1099 int lxc_netdev_down(const char *name
)
1101 return netdev_set_flag(name
, 0);
1104 int lxc_veth_create(const char *name1
, const char *name2
)
1107 struct ifinfomsg
*ifi
;
1108 struct nl_handler nlh
;
1109 struct rtattr
*nest1
, *nest2
, *nest3
;
1110 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1112 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1117 len
= strlen(name1
);
1118 if (len
== 1 || len
>= IFNAMSIZ
)
1121 len
= strlen(name2
);
1122 if (len
== 1 || len
>= IFNAMSIZ
)
1126 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1130 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1134 nlmsg
->nlmsghdr
->nlmsg_flags
=
1135 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1136 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1138 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1141 ifi
->ifi_family
= AF_UNSPEC
;
1144 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1148 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
1151 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1155 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
1159 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1165 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
1168 nla_end_nested(nlmsg
, nest3
);
1169 nla_end_nested(nlmsg
, nest2
);
1170 nla_end_nested(nlmsg
, nest1
);
1172 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
1175 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1177 netlink_close(&nlh
);
1183 /* TODO: merge with lxc_macvlan_create */
1184 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
1186 int err
, len
, lindex
;
1187 struct ifinfomsg
*ifi
;
1188 struct nl_handler nlh
;
1189 struct rtattr
*nest
, *nest2
;
1190 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1192 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1197 len
= strlen(master
);
1198 if (len
== 1 || len
>= IFNAMSIZ
)
1202 if (len
== 1 || len
>= IFNAMSIZ
)
1206 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1210 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1215 lindex
= if_nametoindex(master
);
1219 nlmsg
->nlmsghdr
->nlmsg_flags
=
1220 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1221 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1223 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1228 ifi
->ifi_family
= AF_UNSPEC
;
1230 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1234 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
1237 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1241 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
1244 nla_end_nested(nlmsg
, nest2
);
1245 nla_end_nested(nlmsg
, nest
);
1247 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
1250 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1253 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1259 netlink_close(&nlh
);
1263 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
1265 int err
, index
, len
;
1266 struct ifinfomsg
*ifi
;
1267 struct nl_handler nlh
;
1268 struct rtattr
*nest
, *nest2
;
1269 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1271 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1276 len
= strlen(master
);
1277 if (len
== 1 || len
>= IFNAMSIZ
)
1281 if (len
== 1 || len
>= IFNAMSIZ
)
1285 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1289 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1294 index
= if_nametoindex(master
);
1298 nlmsg
->nlmsghdr
->nlmsg_flags
=
1299 NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
| NLM_F_ACK
;
1300 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
1302 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
1307 ifi
->ifi_family
= AF_UNSPEC
;
1309 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
1313 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
1317 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
1321 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
1324 nla_end_nested(nlmsg
, nest2
);
1327 nla_end_nested(nlmsg
, nest
);
1329 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
1332 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
1335 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1337 netlink_close(&nlh
);
1343 static int proc_sys_net_write(const char *path
, const char *value
)
1348 fd
= open(path
, O_WRONLY
);
1352 if (lxc_write_nointr(fd
, value
, strlen(value
)) < 0)
1359 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
1362 char path
[MAXPATHLEN
];
1364 if (family
!= AF_INET
&& family
!= AF_INET6
)
1367 ret
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/%s",
1368 family
== AF_INET
? "ipv4" : "ipv6", ifname
,
1369 family
== AF_INET
? "proxy_arp" : "proxy_ndp");
1370 if (ret
< 0 || (size_t)ret
>= MAXPATHLEN
)
1373 return proc_sys_net_write(path
, flag
? "1" : "0");
1376 int lxc_neigh_proxy_on(const char *name
, int family
)
1378 return neigh_proxy_set(name
, family
, 1);
1381 int lxc_neigh_proxy_off(const char *name
, int family
)
1383 return neigh_proxy_set(name
, family
, 0);
1386 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
1391 unsigned char *data
;
1393 sockaddr
->sa_family
= ARPHRD_ETHER
;
1394 data
= (unsigned char *)sockaddr
->sa_data
;
1396 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
1400 else if (c
>= 'a' && c
<= 'f')
1402 else if (c
>= 'A' && c
<= 'F')
1411 else if (c
>= 'a' && c
<= 'f')
1412 val
|= c
- 'a' + 10;
1413 else if (c
>= 'A' && c
<= 'F')
1414 val
|= c
- 'A' + 10;
1415 else if (c
== ':' || c
== 0)
1421 *data
++ = (unsigned char)(val
& 0377);
1424 if (*macaddr
== ':')
1431 static int ip_addr_add(int family
, int ifindex
, void *addr
, void *bcast
,
1432 void *acast
, int prefix
)
1435 struct ifaddrmsg
*ifa
;
1436 struct nl_handler nlh
;
1437 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1439 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1440 : sizeof(struct in6_addr
);
1442 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1447 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1451 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1455 nlmsg
->nlmsghdr
->nlmsg_flags
=
1456 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
1457 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWADDR
;
1459 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1462 ifa
->ifa_prefixlen
= prefix
;
1463 ifa
->ifa_index
= ifindex
;
1464 ifa
->ifa_family
= family
;
1468 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
1471 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
1474 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
1477 /* TODO: multicast, anycast with ipv6 */
1478 err
= -EPROTONOSUPPORT
;
1479 if (family
== AF_INET6
&&
1480 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
1481 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
1484 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1486 netlink_close(&nlh
);
1492 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
1493 struct in6_addr
*mcast
, struct in6_addr
*acast
,
1496 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
1499 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
, struct in_addr
*bcast
,
1502 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
1505 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
1506 * the given RTM_NEWADDR message. Allocates memory for the address and stores
1507 * that pointer in *res (so res should be an in_addr** or in6_addr**).
1509 #pragma GCC diagnostic push
1510 #pragma GCC diagnostic ignored "-Wcast-align"
1512 static int ifa_get_local_ip(int family
, struct nlmsghdr
*msg
, void **res
)
1515 struct ifaddrmsg
*ifa
= NLMSG_DATA(msg
);
1516 struct rtattr
*rta
= IFA_RTA(ifa
);
1517 int attr_len
= NLMSG_PAYLOAD(msg
, sizeof(struct ifaddrmsg
));
1519 if (ifa
->ifa_family
!= family
)
1522 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1523 : sizeof(struct in6_addr
);
1525 /* Loop over the rtattr's in this message */
1526 while (RTA_OK(rta
, attr_len
)) {
1527 /* Found a local address for the requested interface,
1530 if (rta
->rta_type
== IFA_LOCAL
||
1531 rta
->rta_type
== IFA_ADDRESS
) {
1532 /* Sanity check. The family check above should make sure
1533 * the address length is correct, but check here just in
1536 if (RTA_PAYLOAD(rta
) != addrlen
)
1539 /* We might have found an IFA_ADDRESS before, which we
1540 * now overwrite with an IFA_LOCAL.
1543 *res
= malloc(addrlen
);
1548 memcpy(*res
, RTA_DATA(rta
), addrlen
);
1549 if (rta
->rta_type
== IFA_LOCAL
)
1552 rta
= RTA_NEXT(rta
, attr_len
);
1557 #pragma GCC diagnostic pop
1559 static int ip_addr_get(int family
, int ifindex
, void **res
)
1561 int answer_len
, err
;
1562 struct ifaddrmsg
*ifa
;
1563 struct nl_handler nlh
;
1564 struct nlmsghdr
*msg
;
1565 int readmore
= 0, recv_len
= 0;
1566 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1568 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1573 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1577 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1581 /* Save the answer buffer length, since it will be overwritten on the
1582 * first receive (and we might need to receive more than once).
1584 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1586 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ROOT
;
1587 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETADDR
;
1589 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1592 ifa
->ifa_family
= family
;
1594 /* Send the request for addresses, which returns all addresses on all
1597 err
= netlink_send(&nlh
, nlmsg
);
1601 #pragma GCC diagnostic push
1602 #pragma GCC diagnostic ignored "-Wcast-align"
1605 /* Restore the answer buffer length, it might have been
1606 * overwritten by a previous receive.
1608 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1610 /* Get the (next) batch of reply messages. */
1611 err
= netlink_rcv(&nlh
, answer
);
1618 /* Satisfy the typing for the netlink macros. */
1619 msg
= answer
->nlmsghdr
;
1621 while (NLMSG_OK(msg
, recv_len
)) {
1622 /* Stop reading if we see an error message. */
1623 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1624 struct nlmsgerr
*errmsg
=
1625 (struct nlmsgerr
*)NLMSG_DATA(msg
);
1626 err
= errmsg
->error
;
1630 /* Stop reading if we see a NLMSG_DONE message. */
1631 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1636 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
1641 ifa
= (struct ifaddrmsg
*)NLMSG_DATA(msg
);
1642 if (ifa
->ifa_index
== ifindex
) {
1643 if (ifa_get_local_ip(family
, msg
, res
) < 0) {
1648 /* Found a result, stop searching. */
1653 /* Keep reading more data from the socket if the last
1654 * message had the NLF_F_MULTI flag set.
1656 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1658 /* Look at the next message received in this buffer. */
1659 msg
= NLMSG_NEXT(msg
, recv_len
);
1663 #pragma GCC diagnostic pop
1665 /* If we end up here, we didn't find any result, so signal an
1671 netlink_close(&nlh
);
1677 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
1679 return ip_addr_get(AF_INET6
, ifindex
, (void **)res
);
1682 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
**res
)
1684 return ip_addr_get(AF_INET
, ifindex
, (void **)res
);
1687 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
1690 struct nl_handler nlh
;
1692 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1694 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1695 : sizeof(struct in6_addr
);
1697 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1702 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1706 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1710 nlmsg
->nlmsghdr
->nlmsg_flags
=
1711 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
1712 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
1714 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
1717 rt
->rtm_family
= family
;
1718 rt
->rtm_table
= RT_TABLE_MAIN
;
1719 rt
->rtm_scope
= RT_SCOPE_UNIVERSE
;
1720 rt
->rtm_protocol
= RTPROT_BOOT
;
1721 rt
->rtm_type
= RTN_UNICAST
;
1722 /* "default" destination */
1723 rt
->rtm_dst_len
= 0;
1726 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
1729 /* Adding the interface index enables the use of link-local
1730 * addresses for the gateway.
1732 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1735 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1737 netlink_close(&nlh
);
1743 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
1745 return ip_gateway_add(AF_INET
, ifindex
, gw
);
1748 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
1750 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
1753 static int ip_route_dest_add(int family
, int ifindex
, void *dest
)
1756 struct nl_handler nlh
;
1758 struct nlmsg
*answer
= NULL
, *nlmsg
= NULL
;
1760 addrlen
= family
== AF_INET
? sizeof(struct in_addr
)
1761 : sizeof(struct in6_addr
);
1763 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1768 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1772 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1776 nlmsg
->nlmsghdr
->nlmsg_flags
=
1777 NLM_F_ACK
| NLM_F_REQUEST
| NLM_F_CREATE
| NLM_F_EXCL
;
1778 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
1780 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
1783 rt
->rtm_family
= family
;
1784 rt
->rtm_table
= RT_TABLE_MAIN
;
1785 rt
->rtm_scope
= RT_SCOPE_LINK
;
1786 rt
->rtm_protocol
= RTPROT_BOOT
;
1787 rt
->rtm_type
= RTN_UNICAST
;
1788 rt
->rtm_dst_len
= addrlen
* 8;
1791 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
1793 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1795 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1797 netlink_close(&nlh
);
1803 int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
)
1805 return ip_route_dest_add(AF_INET
, ifindex
, dest
);
1808 int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
)
1810 return ip_route_dest_add(AF_INET6
, ifindex
, dest
);
1813 bool is_ovs_bridge(const char *bridge
)
1817 char brdirname
[22 + IFNAMSIZ
+ 1] = {0};
1819 ret
= snprintf(brdirname
, 22 + IFNAMSIZ
+ 1, "/sys/class/net/%s/bridge",
1821 if (ret
< 0 || (size_t)ret
>= 22 + IFNAMSIZ
+ 1)
1824 ret
= stat(brdirname
, &sb
);
1825 if (ret
< 0 && errno
== ENOENT
)
1831 struct ovs_veth_args
{
1836 /* Called from a background thread - when nic goes away, remove it from the
1839 static int lxc_ovs_delete_port_exec(void *data
)
1841 struct ovs_veth_args
*args
= data
;
1843 execlp("ovs-vsctl", "ovs-vsctl", "del-port", args
->bridge
, args
->nic
,
1848 int lxc_ovs_delete_port(const char *bridge
, const char *nic
)
1851 char cmd_output
[MAXPATHLEN
];
1852 struct ovs_veth_args args
;
1854 args
.bridge
= bridge
;
1856 ret
= run_command(cmd_output
, sizeof(cmd_output
),
1857 lxc_ovs_delete_port_exec
, (void *)&args
);
1859 ERROR("Failed to delete \"%s\" from openvswitch bridge \"%s\": "
1860 "%s", bridge
, nic
, cmd_output
);
1867 static int lxc_ovs_attach_bridge_exec(void *data
)
1869 struct ovs_veth_args
*args
= data
;
1871 execlp("ovs-vsctl", "ovs-vsctl", "add-port", args
->bridge
, args
->nic
,
1876 static int lxc_ovs_attach_bridge(const char *bridge
, const char *nic
)
1879 char cmd_output
[MAXPATHLEN
];
1880 struct ovs_veth_args args
;
1882 args
.bridge
= bridge
;
1884 ret
= run_command(cmd_output
, sizeof(cmd_output
),
1885 lxc_ovs_attach_bridge_exec
, (void *)&args
);
1887 ERROR("Failed to attach \"%s\" to openvswitch bridge \"%s\": %s",
1888 bridge
, nic
, cmd_output
);
1895 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
1901 if (strlen(ifname
) >= IFNAMSIZ
)
1904 index
= if_nametoindex(ifname
);
1908 if (is_ovs_bridge(bridge
))
1909 return lxc_ovs_attach_bridge(bridge
, ifname
);
1911 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
1915 retlen
= strlcpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
);
1916 if (retlen
>= IFNAMSIZ
) {
1921 ifr
.ifr_name
[IFNAMSIZ
- 1] = '\0';
1922 ifr
.ifr_ifindex
= index
;
1923 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
1931 static const char *const lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
1932 [LXC_NET_EMPTY
] = "empty",
1933 [LXC_NET_VETH
] = "veth",
1934 [LXC_NET_MACVLAN
] = "macvlan",
1935 [LXC_NET_PHYS
] = "phys",
1936 [LXC_NET_VLAN
] = "vlan",
1937 [LXC_NET_NONE
] = "none",
1940 const char *lxc_net_type_to_str(int type
)
1942 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
1945 return lxc_network_types
[type
];
1948 static const char padchar
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1950 char *lxc_mkifname(char *template)
1953 struct ifaddrs
*ifa
, *ifaddr
;
1954 char name
[IFNAMSIZ
];
1955 bool exists
= false;
1960 seed
= randseed(false);
1963 (void)randseed(true);
1966 if (strlen(template) >= IFNAMSIZ
)
1969 /* Get all the network interfaces. */
1970 ret
= getifaddrs(&ifaddr
);
1972 SYSERROR("Failed to get network interfaces");
1976 /* Generate random names until we find one that doesn't exist. */
1979 (void)strlcpy(name
, template, IFNAMSIZ
);
1983 for (i
= 0; i
< strlen(name
); i
++) {
1984 if (name
[i
] == 'X') {
1986 name
[i
] = padchar
[rand_r(&seed
) % (strlen(padchar
) - 1)];
1988 name
[i
] = padchar
[rand() % (strlen(padchar
) - 1)];
1993 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1994 if (!strcmp(ifa
->ifa_name
, name
)) {
2004 freeifaddrs(ifaddr
);
2005 (void)strlcpy(template, name
, strlen(template) + 1);
2010 int setup_private_host_hw_addr(char *veth1
)
2015 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
2019 err
= snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
2020 if (err
< 0 || (size_t)err
>= IFNAMSIZ
) {
2025 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
2031 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
2032 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);
2040 int lxc_find_gateway_addresses(struct lxc_handler
*handler
)
2042 struct lxc_list
*network
= &handler
->conf
->network
;
2043 struct lxc_list
*iterator
;
2044 struct lxc_netdev
*netdev
;
2047 lxc_list_for_each(iterator
, network
) {
2048 netdev
= iterator
->elem
;
2050 if (!netdev
->ipv4_gateway_auto
&& !netdev
->ipv6_gateway_auto
)
2053 if (netdev
->type
!= LXC_NET_VETH
&& netdev
->type
!= LXC_NET_MACVLAN
) {
2054 ERROR("Automatic gateway detection is only supported "
2055 "for veth and macvlan");
2059 if (netdev
->link
[0] == '\0') {
2060 ERROR("Automatic gateway detection needs a link interface");
2064 link_index
= if_nametoindex(netdev
->link
);
2068 if (netdev
->ipv4_gateway_auto
) {
2069 if (lxc_ipv4_addr_get(link_index
, &netdev
->ipv4_gateway
)) {
2070 ERROR("Failed to automatically find ipv4 gateway "
2071 "address from link interface \"%s\"", netdev
->link
);
2076 if (netdev
->ipv6_gateway_auto
) {
2077 if (lxc_ipv6_addr_get(link_index
, &netdev
->ipv6_gateway
)) {
2078 ERROR("Failed to automatically find ipv6 gateway "
2079 "address from link interface \"%s\"", netdev
->link
);
2088 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
2089 static int lxc_create_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2090 struct lxc_netdev
*netdev
, pid_t pid
, unsigned int hooks_version
)
2094 int bytes
, pipefd
[2];
2095 char *token
, *saveptr
= NULL
;
2096 char netdev_link
[IFNAMSIZ
];
2097 char buffer
[MAXPATHLEN
] = {0};
2100 if (netdev
->type
!= LXC_NET_VETH
) {
2101 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2107 SYSERROR("Failed to create pipe");
2113 SYSERROR("Failed to create new process");
2122 char pidstr
[INTTYPE_TO_STRLEN(pid_t
)];
2126 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2128 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2131 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2132 _exit(EXIT_FAILURE
);
2135 if (netdev
->link
[0] != '\0')
2136 retlen
= strlcpy(netdev_link
, netdev
->link
, IFNAMSIZ
);
2138 retlen
= strlcpy(netdev_link
, "none", IFNAMSIZ
);
2139 if (retlen
>= IFNAMSIZ
) {
2140 SYSERROR("Invalid network device name");
2141 _exit(EXIT_FAILURE
);
2144 ret
= snprintf(pidstr
, sizeof(pidstr
), "%d", pid
);
2145 if (ret
< 0 || ret
>= sizeof(pidstr
))
2146 _exit(EXIT_FAILURE
);
2147 pidstr
[sizeof(pidstr
) - 1] = '\0';
2149 INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath
,
2150 lxcname
, pidstr
, netdev_link
,
2151 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)");
2152 if (netdev
->name
[0] != '\0')
2153 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2154 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2155 netdev
->name
, (char *)NULL
);
2157 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "create",
2158 lxcpath
, lxcname
, pidstr
, "veth", netdev_link
,
2160 SYSERROR("Failed to execute lxc-user-nic");
2161 _exit(EXIT_FAILURE
);
2164 /* close the write-end of the pipe */
2167 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, MAXPATHLEN
);
2169 SYSERROR("Failed to read from pipe file descriptor");
2172 buffer
[bytes
- 1] = '\0';
2175 ret
= wait_for_pid(child
);
2177 if (ret
!= 0 || bytes
< 0) {
2178 ERROR("lxc-user-nic failed to configure requested network: %s",
2179 buffer
[0] != '\0' ? buffer
: "(null)");
2182 TRACE("Received output \"%s\" from lxc-user-nic", buffer
);
2185 token
= strtok_r(buffer
, ":", &saveptr
);
2187 ERROR("Failed to parse lxc-user-nic output");
2191 memset(netdev
->name
, 0, IFNAMSIZ
);
2192 memcpy(netdev
->name
, token
, IFNAMSIZ
- 1);
2194 /* netdev->ifindex */
2195 token
= strtok_r(NULL
, ":", &saveptr
);
2197 ERROR("Failed to parse lxc-user-nic output");
2201 ret
= lxc_safe_int(token
, &netdev
->ifindex
);
2204 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2208 /* netdev->priv.veth_attr.veth1 */
2209 token
= strtok_r(NULL
, ":", &saveptr
);
2211 ERROR("Failed to parse lxc-user-nic output");
2215 retlen
= strlcpy(netdev
->priv
.veth_attr
.veth1
, token
, IFNAMSIZ
);
2216 if (retlen
>= IFNAMSIZ
) {
2217 ERROR("Host side veth device name returned by lxc-user-nic is "
2222 /* netdev->priv.veth_attr.ifindex */
2223 token
= strtok_r(NULL
, ":", &saveptr
);
2225 ERROR("Failed to parse lxc-user-nic output");
2229 ret
= lxc_safe_int(token
, &netdev
->priv
.veth_attr
.ifindex
);
2232 SYSERROR("Failed to convert string \"%s\" to integer", token
);
2236 if (netdev
->upscript
) {
2240 netdev
->priv
.veth_attr
.veth1
,
2244 ret
= run_script_argv(lxcname
,
2245 hooks_version
, "net",
2246 netdev
->upscript
, "up", argv
);
2254 static int lxc_delete_network_unpriv_exec(const char *lxcpath
, const char *lxcname
,
2255 struct lxc_netdev
*netdev
,
2256 const char *netns_path
)
2261 char buffer
[MAXPATHLEN
] = {0};
2263 if (netdev
->type
!= LXC_NET_VETH
) {
2264 ERROR("Network type %d not support for unprivileged use", netdev
->type
);
2270 SYSERROR("Failed to create pipe");
2276 SYSERROR("Failed to create new process");
2288 ret
= dup2(pipefd
[1], STDOUT_FILENO
);
2290 ret
= dup2(pipefd
[1], STDERR_FILENO
);
2293 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2294 _exit(EXIT_FAILURE
);
2297 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2298 hostveth
= netdev
->priv
.veth_attr
.pair
;
2300 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2301 if (hostveth
[0] == '\0') {
2302 SYSERROR("Host side veth device name is missing");
2303 _exit(EXIT_FAILURE
);
2306 if (netdev
->link
[0] == '\0') {
2307 SYSERROR("Network link for network device \"%s\" is "
2308 "missing", netdev
->priv
.veth_attr
.veth1
);
2309 _exit(EXIT_FAILURE
);
2312 INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath
,
2313 lxcname
, netns_path
, netdev
->link
, hostveth
);
2314 execlp(LXC_USERNIC_PATH
, LXC_USERNIC_PATH
, "delete", lxcpath
,
2315 lxcname
, netns_path
, "veth", netdev
->link
, hostveth
,
2317 SYSERROR("Failed to exec lxc-user-nic.");
2318 _exit(EXIT_FAILURE
);
2323 bytes
= lxc_read_nointr(pipefd
[0], &buffer
, MAXPATHLEN
);
2325 SYSERROR("Failed to read from pipe file descriptor.");
2328 buffer
[bytes
- 1] = '\0';
2331 ret
= wait_for_pid(child
);
2333 if (ret
!= 0 || bytes
< 0) {
2334 ERROR("lxc-user-nic failed to delete requested network: %s",
2335 buffer
[0] != '\0' ? buffer
: "(null)");
2342 bool lxc_delete_network_unpriv(struct lxc_handler
*handler
)
2345 struct lxc_list
*iterator
;
2346 struct lxc_list
*network
= &handler
->conf
->network
;
2347 /* strlen("/proc/") = 6
2349 * INTTYPE_TO_STRLEN(pid_t)
2351 * strlen("/fd/") = 4
2353 * INTTYPE_TO_STRLEN(int)
2357 char netns_path
[6 + INTTYPE_TO_STRLEN(pid_t
) + 4 + INTTYPE_TO_STRLEN(int) + 1];
2361 if (handler
->nsfd
[LXC_NS_NET
] < 0) {
2362 DEBUG("Cannot not guarantee safe deletion of network devices. "
2363 "Manual cleanup maybe needed");
2367 ret
= snprintf(netns_path
, sizeof(netns_path
), "/proc/%d/fd/%d",
2368 lxc_raw_getpid(), handler
->nsfd
[LXC_NS_NET
]);
2369 if (ret
< 0 || ret
>= sizeof(netns_path
))
2372 lxc_list_for_each(iterator
, network
) {
2373 char *hostveth
= NULL
;
2374 struct lxc_netdev
*netdev
= iterator
->elem
;
2376 /* We can only delete devices whose ifindex we have. If we don't
2377 * have the index it means that we didn't create it.
2379 if (!netdev
->ifindex
)
2382 if (netdev
->type
== LXC_NET_PHYS
) {
2383 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
,
2386 WARN("Failed to rename interface with index %d "
2387 "to its initial name \"%s\"",
2388 netdev
->ifindex
, netdev
->link
);
2390 TRACE("Renamed interface with index %d to its "
2391 "initial name \"%s\"",
2392 netdev
->ifindex
, netdev
->link
);
2393 goto clear_ifindices
;
2396 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
2398 WARN("Failed to deconfigure network device");
2400 if (netdev
->type
!= LXC_NET_VETH
)
2401 goto clear_ifindices
;
2403 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
))
2404 goto clear_ifindices
;
2406 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2407 hostveth
= netdev
->priv
.veth_attr
.pair
;
2409 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2410 if (hostveth
[0] == '\0')
2411 goto clear_ifindices
;
2413 ret
= lxc_delete_network_unpriv_exec(handler
->lxcpath
,
2414 handler
->name
, netdev
,
2417 WARN("Failed to remove port \"%s\" from openvswitch "
2418 "bridge \"%s\"", hostveth
, netdev
->link
);
2419 goto clear_ifindices
;
2421 INFO("Removed interface \"%s\" from \"%s\"", hostveth
,
2425 /* We need to clear any ifindeces we recorded so liblxc won't
2426 * have cached stale data which would cause it to fail on reboot
2427 * we're we don't re-read the on-disk config file.
2429 netdev
->ifindex
= 0;
2430 if (netdev
->type
== LXC_NET_PHYS
) {
2431 netdev
->priv
.phys_attr
.ifindex
= 0;
2432 } else if (netdev
->type
== LXC_NET_VETH
) {
2433 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
2434 netdev
->priv
.veth_attr
.ifindex
= 0;
2441 int lxc_create_network_priv(struct lxc_handler
*handler
)
2443 struct lxc_list
*iterator
;
2444 struct lxc_list
*network
= &handler
->conf
->network
;
2446 if (!handler
->am_root
)
2449 lxc_list_for_each(iterator
, network
) {
2450 struct lxc_netdev
*netdev
= iterator
->elem
;
2452 if (netdev
->type
< 0 || netdev
->type
> LXC_NET_MAXCONFTYPE
) {
2453 ERROR("Invalid network configuration type %d", netdev
->type
);
2457 if (netdev_conf
[netdev
->type
](handler
, netdev
)) {
2458 ERROR("Failed to create network device");
2467 int lxc_network_move_created_netdev_priv(const char *lxcpath
, const char *lxcname
,
2468 struct lxc_list
*network
, pid_t pid
)
2471 char ifname
[IFNAMSIZ
];
2472 struct lxc_list
*iterator
;
2474 if (am_guest_unpriv())
2477 lxc_list_for_each(iterator
, network
) {
2478 struct lxc_netdev
*netdev
= iterator
->elem
;
2480 if (!netdev
->ifindex
)
2483 /* retrieve the name of the interface */
2484 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
2485 ERROR("No interface corresponding to ifindex \"%d\"",
2490 ret
= lxc_netdev_move_by_name(ifname
, pid
, NULL
);
2493 SYSERROR("Failed to move network device \"%s\" to "
2494 "network namespace %d", ifname
, pid
);
2498 DEBUG("Moved network device \"%s\"/\"%s\" to network namespace "
2500 ifname
, netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
2507 int lxc_create_network_unpriv(const char *lxcpath
, const char *lxcname
,
2508 struct lxc_list
*network
, pid_t pid
, unsigned int hooks_version
)
2510 struct lxc_list
*iterator
;
2512 if (!am_guest_unpriv())
2515 lxc_list_for_each(iterator
, network
) {
2516 struct lxc_netdev
*netdev
= iterator
->elem
;
2518 if (netdev
->type
== LXC_NET_EMPTY
)
2521 if (netdev
->type
== LXC_NET_NONE
)
2524 if (netdev
->type
!= LXC_NET_VETH
) {
2525 ERROR("Networks of type %s are not supported by "
2526 "unprivileged containers",
2527 lxc_net_type_to_str(netdev
->type
));
2532 INFO("mtu ignored due to insufficient privilege");
2534 if (lxc_create_network_unpriv_exec(lxcpath
, lxcname
, netdev
, pid
, hooks_version
))
2541 bool lxc_delete_network_priv(struct lxc_handler
*handler
)
2544 struct lxc_list
*iterator
;
2545 struct lxc_list
*network
= &handler
->conf
->network
;
2547 lxc_list_for_each(iterator
, network
) {
2548 char *hostveth
= NULL
;
2549 struct lxc_netdev
*netdev
= iterator
->elem
;
2551 /* We can only delete devices whose ifindex we have. If we don't
2552 * have the index it means that we didn't create it.
2554 if (!netdev
->ifindex
)
2557 if (netdev
->type
== LXC_NET_PHYS
) {
2558 ret
= lxc_netdev_rename_by_index(netdev
->ifindex
, netdev
->link
);
2560 WARN("Failed to rename interface with index %d "
2561 "from \"%s\" to its initial name \"%s\"",
2562 netdev
->ifindex
, netdev
->name
, netdev
->link
);
2564 TRACE("Renamed interface with index %d from "
2565 "\"%s\" to its initial name \"%s\"",
2566 netdev
->ifindex
, netdev
->name
,
2568 goto clear_ifindices
;
2571 ret
= netdev_deconf
[netdev
->type
](handler
, netdev
);
2573 WARN("Failed to deconfigure network device");
2575 /* Recent kernels remove the virtual interfaces when the network
2576 * namespace is destroyed but in case we did not move the
2577 * interface to the network namespace, we have to destroy it.
2579 ret
= lxc_netdev_delete_by_index(netdev
->ifindex
);
2580 if (-ret
== ENODEV
) {
2581 INFO("Interface \"%s\" with index %d already "
2582 "deleted or existing in different network "
2584 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
2586 } else if (ret
< 0) {
2588 SYSWARN("Failed to remove interface \"%s\" with index %d",
2589 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
2591 goto clear_ifindices
;
2593 INFO("Removed interface \"%s\" with index %d",
2594 netdev
->name
[0] != '\0' ? netdev
->name
: "(null)",
2597 if (netdev
->type
!= LXC_NET_VETH
)
2598 goto clear_ifindices
;
2600 /* Explicitly delete host veth device to prevent lingering
2601 * devices. We had issues in LXD around this.
2603 if (netdev
->priv
.veth_attr
.pair
[0] != '\0')
2604 hostveth
= netdev
->priv
.veth_attr
.pair
;
2606 hostveth
= netdev
->priv
.veth_attr
.veth1
;
2607 if (hostveth
[0] == '\0')
2608 goto clear_ifindices
;
2610 ret
= lxc_netdev_delete_by_name(hostveth
);
2613 SYSWARN("Failed to remove interface \"%s\" from \"%s\"",
2614 hostveth
, netdev
->link
);
2615 goto clear_ifindices
;
2617 INFO("Removed interface \"%s\" from \"%s\"", hostveth
, netdev
->link
);
2619 if (netdev
->link
[0] == '\0' || !is_ovs_bridge(netdev
->link
)) {
2620 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
2621 netdev
->ifindex
= 0;
2622 netdev
->priv
.veth_attr
.ifindex
= 0;
2623 goto clear_ifindices
;
2626 /* Delete the openvswitch port. */
2627 ret
= lxc_ovs_delete_port(netdev
->link
, hostveth
);
2629 WARN("Failed to remove port \"%s\" from openvswitch "
2630 "bridge \"%s\"", hostveth
, netdev
->link
);
2632 INFO("Removed port \"%s\" from openvswitch bridge \"%s\"",
2633 hostveth
, netdev
->link
);
2636 /* We need to clear any ifindeces we recorded so liblxc won't
2637 * have cached stale data which would cause it to fail on reboot
2638 * we're we don't re-read the on-disk config file.
2640 netdev
->ifindex
= 0;
2641 if (netdev
->type
== LXC_NET_PHYS
) {
2642 netdev
->priv
.phys_attr
.ifindex
= 0;
2643 } else if (netdev
->type
== LXC_NET_VETH
) {
2644 netdev
->priv
.veth_attr
.veth1
[0] = '\0';
2645 netdev
->priv
.veth_attr
.ifindex
= 0;
2652 int lxc_requests_empty_network(struct lxc_handler
*handler
)
2654 struct lxc_list
*network
= &handler
->conf
->network
;
2655 struct lxc_list
*iterator
;
2656 bool found_none
= false, found_nic
= false;
2658 if (lxc_list_empty(network
))
2661 lxc_list_for_each(iterator
, network
) {
2662 struct lxc_netdev
*netdev
= iterator
->elem
;
2664 if (netdev
->type
== LXC_NET_NONE
)
2669 if (found_none
&& !found_nic
)
2674 /* try to move physical nics to the init netns */
2675 int lxc_restore_phys_nics_to_netns(struct lxc_handler
*handler
)
2679 char ifname
[IFNAMSIZ
];
2680 struct lxc_list
*iterator
;
2681 int netnsfd
= handler
->nsfd
[LXC_NS_NET
];
2682 struct lxc_conf
*conf
= handler
->conf
;
2684 /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
2685 * the parent network namespace. We won't have this capability if we are
2688 if (!handler
->am_root
)
2691 TRACE("Moving physical network devices back to parent network namespace");
2693 oldfd
= lxc_preserve_ns(lxc_raw_getpid(), "net");
2695 SYSERROR("Failed to preserve network namespace");
2699 ret
= setns(netnsfd
, CLONE_NEWNET
);
2701 SYSERROR("Failed to enter network namespace");
2706 lxc_list_for_each(iterator
, &conf
->network
) {
2707 struct lxc_netdev
*netdev
= iterator
->elem
;
2709 if (netdev
->type
!= LXC_NET_PHYS
)
2712 /* Retrieve the name of the interface in the container's network
2715 if (!if_indextoname(netdev
->ifindex
, ifname
)) {
2716 WARN("No interface corresponding to ifindex %d",
2721 ret
= lxc_netdev_move_by_name(ifname
, 1, netdev
->link
);
2723 WARN("Error moving network device \"%s\" back to "
2724 "network namespace", ifname
);
2726 TRACE("Moved network device \"%s\" back to network "
2727 "namespace", ifname
);
2730 ret
= setns(oldfd
, CLONE_NEWNET
);
2733 SYSERROR("Failed to enter network namespace");
2740 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
2742 struct sockaddr sockaddr
;
2746 ret
= lxc_convert_mac(hwaddr
, &sockaddr
);
2749 SYSERROR("Mac address \"%s\" conversion failed", hwaddr
);
2753 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
2754 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
2755 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
2757 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
2761 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
2763 SYSERROR("Failed to perform ioctl");
2767 DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr
,
2773 static int setup_ipv4_addr(struct lxc_list
*ip
, int ifindex
)
2775 struct lxc_list
*iterator
;
2778 lxc_list_for_each(iterator
, ip
) {
2779 struct lxc_inetdev
*inetdev
= iterator
->elem
;
2781 err
= lxc_ipv4_addr_add(ifindex
, &inetdev
->addr
,
2782 &inetdev
->bcast
, inetdev
->prefix
);
2785 SYSERROR("Failed to setup ipv4 address for network device "
2786 "with eifindex %d", ifindex
);
2794 static int setup_ipv6_addr(struct lxc_list
*ip
, int ifindex
)
2796 struct lxc_list
*iterator
;
2799 lxc_list_for_each(iterator
, ip
) {
2800 struct lxc_inet6dev
*inet6dev
= iterator
->elem
;
2802 err
= lxc_ipv6_addr_add(ifindex
, &inet6dev
->addr
,
2803 &inet6dev
->mcast
, &inet6dev
->acast
,
2807 SYSERROR("Failed to setup ipv6 address for network device "
2808 "with eifindex %d", ifindex
);
2816 static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev
*netdev
)
2818 char ifname
[IFNAMSIZ
];
2820 const char *net_type_name
;
2821 char *current_ifname
= ifname
;
2823 /* empty network namespace */
2824 if (!netdev
->ifindex
) {
2825 if (netdev
->flags
& IFF_UP
) {
2826 err
= lxc_netdev_up("lo");
2829 SYSERROR("Failed to set the loopback network device up");
2834 if (netdev
->type
== LXC_NET_EMPTY
)
2837 if (netdev
->type
== LXC_NET_NONE
)
2840 if (netdev
->type
!= LXC_NET_VETH
) {
2841 net_type_name
= lxc_net_type_to_str(netdev
->type
);
2842 ERROR("%s networks are not supported for containers "
2843 "not setup up by privileged users", net_type_name
);
2847 netdev
->ifindex
= if_nametoindex(netdev
->name
);
2850 /* get the new ifindex in case of physical netdev */
2851 if (netdev
->type
== LXC_NET_PHYS
) {
2852 netdev
->ifindex
= if_nametoindex(netdev
->link
);
2853 if (!netdev
->ifindex
) {
2854 ERROR("Failed to get ifindex for network device \"%s\"",
2860 /* retrieve the name of the interface */
2861 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
2862 ERROR("Failed get name for network device with ifindex %d",
2867 /* Default: let the system to choose one interface name.
2868 * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
2869 * netlink will replace the format specifier with an appropriate index.
2871 if (netdev
->name
[0] == '\0') {
2872 if (netdev
->type
== LXC_NET_PHYS
)
2873 (void)strlcpy(netdev
->name
, netdev
->link
, IFNAMSIZ
);
2875 (void)strlcpy(netdev
->name
, "eth%d", IFNAMSIZ
);
2878 /* rename the interface name */
2879 if (strcmp(ifname
, netdev
->name
) != 0) {
2880 err
= lxc_netdev_rename_by_name(ifname
, netdev
->name
);
2883 SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
2884 ifname
, netdev
->name
);
2889 /* Re-read the name of the interface because its name has changed
2890 * and would be automatically allocated by the system
2892 if (!if_indextoname(netdev
->ifindex
, current_ifname
)) {
2893 ERROR("Failed get name for network device with ifindex %d",
2898 /* Now update the recorded name of the network device to reflect the
2899 * name of the network device in the child's network namespace. We will
2900 * later on send this information back to the parent.
2902 (void)strlcpy(netdev
->name
, current_ifname
, IFNAMSIZ
);
2904 /* set a mac address */
2905 if (netdev
->hwaddr
) {
2906 if (setup_hw_addr(netdev
->hwaddr
, current_ifname
)) {
2907 ERROR("Failed to setup hw address for network device \"%s\"",
2913 /* setup ipv4 addresses on the interface */
2914 if (setup_ipv4_addr(&netdev
->ipv4
, netdev
->ifindex
)) {
2915 ERROR("Failed to setup ip addresses for network device \"%s\"",
2920 /* setup ipv6 addresses on the interface */
2921 if (setup_ipv6_addr(&netdev
->ipv6
, netdev
->ifindex
)) {
2922 ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
2927 /* set the network device up */
2928 if (netdev
->flags
& IFF_UP
) {
2931 err
= lxc_netdev_up(current_ifname
);
2934 SYSERROR("Failed to set network device \"%s\" up",
2939 /* the network is up, make the loopback up too */
2940 err
= lxc_netdev_up("lo");
2943 SYSERROR("Failed to set the loopback network device up");
2948 /* We can only set up the default routes after bringing
2949 * up the interface, sine bringing up the interface adds
2950 * the link-local routes and we can't add a default
2951 * route if the gateway is not reachable. */
2953 /* setup ipv4 gateway on the interface */
2954 if (netdev
->ipv4_gateway
) {
2955 if (!(netdev
->flags
& IFF_UP
)) {
2956 ERROR("Cannot add ipv4 gateway for network device "
2957 "\"%s\" when not bringing up the interface", ifname
);
2961 if (lxc_list_empty(&netdev
->ipv4
)) {
2962 ERROR("Cannot add ipv4 gateway for network device "
2963 "\"%s\" when not assigning an address", ifname
);
2967 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
2969 err
= lxc_ipv4_dest_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
2972 SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
2976 err
= lxc_ipv4_gateway_add(netdev
->ifindex
, netdev
->ipv4_gateway
);
2979 SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
2982 if (netdev
->ipv4_gateway_auto
) {
2983 char buf
[INET_ADDRSTRLEN
];
2984 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
2985 ERROR("Fried to set autodetected ipv4 gateway \"%s\"", buf
);
2992 /* setup ipv6 gateway on the interface */
2993 if (netdev
->ipv6_gateway
) {
2994 if (!(netdev
->flags
& IFF_UP
)) {
2995 ERROR("Cannot add ipv6 gateway for network device "
2996 "\"%s\" when not bringing up the interface", ifname
);
3000 if (lxc_list_empty(&netdev
->ipv6
) && !IN6_IS_ADDR_LINKLOCAL(netdev
->ipv6_gateway
)) {
3001 ERROR("Cannot add ipv6 gateway for network device "
3002 "\"%s\" when not assigning an address", ifname
);
3006 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3008 err
= lxc_ipv6_dest_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3011 SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
3015 err
= lxc_ipv6_gateway_add(netdev
->ifindex
, netdev
->ipv6_gateway
);
3018 SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
3021 if (netdev
->ipv6_gateway_auto
) {
3022 char buf
[INET6_ADDRSTRLEN
];
3023 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
3024 ERROR("Tried to set autodetected ipv6 "
3025 "gateway for network device "
3033 DEBUG("Network device \"%s\" has been setup", current_ifname
);
3038 int lxc_setup_network_in_child_namespaces(const struct lxc_conf
*conf
,
3039 struct lxc_list
*network
)
3041 struct lxc_list
*iterator
;
3042 struct lxc_netdev
*netdev
;
3044 lxc_list_for_each(iterator
, network
) {
3045 netdev
= iterator
->elem
;
3047 if (lxc_setup_netdev_in_child_namespaces(netdev
)) {
3048 ERROR("failed to setup netdev");
3053 if (!lxc_list_empty(network
))
3054 INFO("network has been setup");
3059 int lxc_network_send_veth_names_to_child(struct lxc_handler
*handler
)
3061 struct lxc_list
*iterator
;
3062 struct lxc_list
*network
= &handler
->conf
->network
;
3063 int data_sock
= handler
->data_sock
[0];
3065 if (handler
->am_root
)
3068 lxc_list_for_each(iterator
, network
) {
3070 struct lxc_netdev
*netdev
= iterator
->elem
;
3072 if (netdev
->type
!= LXC_NET_VETH
)
3075 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3078 TRACE("Sent network device name \"%s\" to child", netdev
->name
);
3084 int lxc_network_recv_veth_names_from_parent(struct lxc_handler
*handler
)
3086 struct lxc_list
*iterator
;
3087 struct lxc_list
*network
= &handler
->conf
->network
;
3088 int data_sock
= handler
->data_sock
[1];
3090 if (handler
->am_root
)
3093 lxc_list_for_each(iterator
, network
) {
3095 struct lxc_netdev
*netdev
= iterator
->elem
;
3097 if (netdev
->type
!= LXC_NET_VETH
)
3100 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3103 TRACE("Received network device name \"%s\" from parent", netdev
->name
);
3109 int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler
*handler
)
3111 struct lxc_list
*iterator
, *network
;
3112 int data_sock
= handler
->data_sock
[0];
3114 if (!handler
->am_root
)
3117 network
= &handler
->conf
->network
;
3118 lxc_list_for_each(iterator
, network
) {
3120 struct lxc_netdev
*netdev
= iterator
->elem
;
3122 /* Send network device name in the child's namespace to parent. */
3123 ret
= lxc_send_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, MSG_NOSIGNAL
);
3127 /* Send network device ifindex in the child's namespace to
3130 ret
= lxc_send_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), MSG_NOSIGNAL
);
3135 TRACE("Sent network device names and ifindeces to parent");
3139 int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler
*handler
)
3141 struct lxc_list
*iterator
, *network
;
3142 int data_sock
= handler
->data_sock
[1];
3144 if (!handler
->am_root
)
3147 network
= &handler
->conf
->network
;
3148 lxc_list_for_each(iterator
, network
) {
3150 struct lxc_netdev
*netdev
= iterator
->elem
;
3152 /* Receive network device name in the child's namespace to
3155 ret
= lxc_recv_nointr(data_sock
, netdev
->name
, IFNAMSIZ
, 0);
3159 /* Receive network device ifindex in the child's namespace to
3162 ret
= lxc_recv_nointr(data_sock
, &netdev
->ifindex
, sizeof(netdev
->ifindex
), 0);
3170 void lxc_delete_network(struct lxc_handler
*handler
)
3174 if (handler
->am_root
)
3175 bret
= lxc_delete_network_priv(handler
);
3177 bret
= lxc_delete_network_unpriv(handler
);
3179 DEBUG("Failed to delete network devices");
3181 DEBUG("Deleted network devices");
3184 int lxc_netns_set_nsid(int fd
)
3187 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3188 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3190 struct nl_handler nlh
;
3191 struct nlmsghdr
*hdr
;
3192 struct rtgenmsg
*msg
;
3194 const __s32 ns_id
= -1;
3195 const __u32 netns_fd
= fd
;
3197 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3201 memset(buf
, 0, sizeof(buf
));
3203 #pragma GCC diagnostic push
3204 #pragma GCC diagnostic ignored "-Wcast-align"
3205 hdr
= (struct nlmsghdr
*)buf
;
3206 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3207 #pragma GCC diagnostic pop
3209 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3210 hdr
->nlmsg_type
= RTM_NEWNSID
;
3211 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3213 hdr
->nlmsg_seq
= RTM_NEWNSID
;
3214 msg
->rtgen_family
= AF_UNSPEC
;
3216 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3220 ret
= addattr(hdr
, 1024, __LXC_NETNSA_NSID
, &ns_id
, sizeof(ns_id
));
3224 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3227 saved_errno
= errno
;
3228 netlink_close(&nlh
);
3229 errno
= saved_errno
;
3234 static int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
3237 memset(tb
, 0, sizeof(struct rtattr
*) * (max
+ 1));
3239 while (RTA_OK(rta
, len
)) {
3240 unsigned short type
= rta
->rta_type
;
3242 if ((type
<= max
) && (!tb
[type
]))
3245 #pragma GCC diagnostic push
3246 #pragma GCC diagnostic ignored "-Wcast-align"
3247 rta
= RTA_NEXT(rta
, len
);
3248 #pragma GCC diagnostic pop
3254 static inline __s32
rta_getattr_s32(const struct rtattr
*rta
)
3256 return *(__s32
*)RTA_DATA(rta
);
3260 #define NETNS_RTA(r) \
3261 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
3264 int lxc_netns_get_nsid(int fd
)
3268 char buf
[NLMSG_ALIGN(sizeof(struct nlmsghdr
)) +
3269 NLMSG_ALIGN(sizeof(struct rtgenmsg
)) +
3271 struct rtattr
*tb
[__LXC_NETNSA_MAX
+ 1];
3272 struct nl_handler nlh
;
3273 struct nlmsghdr
*hdr
;
3274 struct rtgenmsg
*msg
;
3276 __u32 netns_fd
= fd
;
3278 ret
= netlink_open(&nlh
, NETLINK_ROUTE
);
3282 memset(buf
, 0, sizeof(buf
));
3284 #pragma GCC diagnostic push
3285 #pragma GCC diagnostic ignored "-Wcast-align"
3286 hdr
= (struct nlmsghdr
*)buf
;
3287 msg
= (struct rtgenmsg
*)NLMSG_DATA(hdr
);
3288 #pragma GCC diagnostic pop
3290 hdr
->nlmsg_len
= NLMSG_LENGTH(sizeof(*msg
));
3291 hdr
->nlmsg_type
= RTM_GETNSID
;
3292 hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
3294 hdr
->nlmsg_seq
= RTM_GETNSID
;
3295 msg
->rtgen_family
= AF_UNSPEC
;
3297 ret
= addattr(hdr
, 1024, __LXC_NETNSA_FD
, &netns_fd
, sizeof(netns_fd
));
3299 ret
= __netlink_transaction(&nlh
, hdr
, hdr
);
3301 saved_errno
= errno
;
3302 netlink_close(&nlh
);
3303 errno
= saved_errno
;
3308 msg
= NLMSG_DATA(hdr
);
3309 len
= hdr
->nlmsg_len
- NLMSG_SPACE(sizeof(*msg
));
3313 #pragma GCC diagnostic push
3314 #pragma GCC diagnostic ignored "-Wcast-align"
3315 parse_rtattr(tb
, __LXC_NETNSA_MAX
, NETNS_RTA(msg
), len
);
3316 if (tb
[__LXC_NETNSA_NSID
])
3317 return rta_getattr_s32(tb
[__LXC_NETNSA_NSID
]);
3318 #pragma GCC diagnostic pop