]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
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
34 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
39 #include <sys/inotify.h>
40 #include <arpa/inet.h>
42 #include <net/if_arp.h>
43 #include <net/ethernet.h>
44 #include <netinet/in.h>
45 #include <linux/netlink.h>
46 #include <linux/rtnetlink.h>
47 #include <linux/sockios.h>
57 #include <../include/ifaddrs.h>
61 # define IFLA_LINKMODE 17
65 # define IFLA_LINKINFO 18
68 #ifndef IFLA_NET_NS_PID
69 # define IFLA_NET_NS_PID 19
72 #ifndef IFLA_INFO_KIND
73 # define IFLA_INFO_KIND 1
77 # define IFLA_VLAN_ID 1
80 #ifndef IFLA_INFO_DATA
81 # define IFLA_INFO_DATA 2
84 #ifndef VETH_INFO_PEER
85 # define VETH_INFO_PEER 1
88 #ifndef IFLA_MACVLAN_MODE
89 # define IFLA_MACVLAN_MODE 1
93 int lxc_netdev_move_by_index(int ifindex
, pid_t pid
, const char* ifname
)
95 struct nl_handler nlh
;
96 struct nlmsg
*nlmsg
= NULL
;
97 struct ifinfomsg
*ifi
;
100 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
105 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
109 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
110 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
112 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
115 ifi
->ifi_family
= AF_UNSPEC
;
116 ifi
->ifi_index
= ifindex
;
118 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
121 if (ifname
!= NULL
) {
122 if (nla_put_string(nlmsg
, IFLA_IFNAME
, ifname
))
126 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
134 * If we are asked to move a wireless interface, then
135 * we must actually move its phyN device. Detect
136 * that condition and return the physname here. The
137 * physname will be passed to lxc_netdev_move_wlan()
138 * which will free it when done
140 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
141 static char * is_wlan(const char *ifname
)
143 char *path
, *physname
= NULL
;
144 size_t len
= strlen(ifname
) + strlen(PHYSNAME
) - 1;
150 path
= alloca(len
+1);
151 ret
= snprintf(path
, len
, PHYSNAME
, ifname
);
152 if (ret
< 0 || ret
>= len
)
154 ret
= stat(path
, &sb
);
157 if (!(f
= fopen(path
, "r")))
159 // feh - sb.st_size is always 4096
160 fseek(f
, 0, SEEK_END
);
162 fseek(f
, 0, SEEK_SET
);
163 physname
= malloc(physlen
+1);
168 memset(physname
, 0, physlen
+1);
169 ret
= fread(physname
, 1, physlen
, f
);
174 for (i
= 0; i
< physlen
; i
++) {
175 if (physname
[i
] == '\n')
177 if (physname
[i
] == '\0')
189 lxc_netdev_rename_by_name_in_netns(pid_t pid
, const char *old
, const char *new)
196 return wait_for_pid(fpid
);
197 if (!switch_to_ns(pid
, "net"))
199 exit(lxc_netdev_rename_by_name(old
, new));
203 lxc_netdev_move_wlan(char *physname
, const char *ifname
, pid_t pid
, const char* newname
)
209 /* Move phyN into the container. TODO - do this using netlink.
210 * However, IIUC this involves a bit more complicated work to
211 * talk to the 80211 module, so for now just call out to iw
213 cmd
= on_path("iw", NULL
);
223 sprintf(pidstr
, "%d", pid
);
224 if (execlp("iw", "iw", "phy", physname
, "set", "netns", pidstr
, (char *)NULL
))
226 exit(0); // notreached
228 if (wait_for_pid(fpid
))
233 err
= lxc_netdev_rename_by_name_in_netns(pid
, ifname
, newname
);
240 int lxc_netdev_move_by_name(const char *ifname
, pid_t pid
, const char* newname
)
248 index
= if_nametoindex(ifname
);
252 if ((physname
= is_wlan(ifname
)))
253 return lxc_netdev_move_wlan(physname
, ifname
, pid
, newname
);
255 return lxc_netdev_move_by_index(index
, pid
, newname
);
258 int lxc_netdev_delete_by_index(int ifindex
)
260 struct nl_handler nlh
;
261 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
262 struct ifinfomsg
*ifi
;
265 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
270 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
274 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
278 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
279 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_DELLINK
;
281 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
284 ifi
->ifi_family
= AF_UNSPEC
;
285 ifi
->ifi_index
= ifindex
;
287 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
295 int lxc_netdev_delete_by_name(const char *name
)
299 index
= if_nametoindex(name
);
303 return lxc_netdev_delete_by_index(index
);
306 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
308 struct nl_handler nlh
;
309 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
310 struct ifinfomsg
*ifi
;
313 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
317 len
= strlen(newname
);
318 if (len
== 1 || len
>= IFNAMSIZ
)
322 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
326 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
330 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
331 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
333 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
336 ifi
->ifi_family
= AF_UNSPEC
;
337 ifi
->ifi_index
= ifindex
;
339 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
342 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
350 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
354 len
= strlen(oldname
);
355 if (len
== 1 || len
>= IFNAMSIZ
)
358 index
= if_nametoindex(oldname
);
362 return lxc_netdev_rename_by_index(index
, newname
);
365 int netdev_set_flag(const char *name
, int flag
)
367 struct nl_handler nlh
;
368 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
369 struct ifinfomsg
*ifi
;
372 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
378 if (len
== 1 || len
>= IFNAMSIZ
)
382 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
386 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
391 index
= if_nametoindex(name
);
395 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
396 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
398 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
403 ifi
->ifi_family
= AF_UNSPEC
;
404 ifi
->ifi_index
= index
;
405 ifi
->ifi_change
|= IFF_UP
;
406 ifi
->ifi_flags
|= flag
;
408 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
416 int netdev_get_flag(const char* name
, int *flag
)
418 struct nl_handler nlh
;
419 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
420 struct ifinfomsg
*ifi
;
426 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
432 if (len
== 1 || len
>= IFNAMSIZ
)
436 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
440 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
445 index
= if_nametoindex(name
);
449 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
;
450 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
452 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
457 ifi
->ifi_family
= AF_UNSPEC
;
458 ifi
->ifi_index
= index
;
460 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
464 ifi
= NLMSG_DATA(answer
->nlmsghdr
);
466 *flag
= ifi
->ifi_flags
;
475 * \brief Check a interface is up or not.
477 * \param name: name for the interface.
480 * 0 means interface is down.
481 * 1 means interface is up.
482 * Others means error happened, and ret-value is the error number.
484 int lxc_netdev_isup(const char* name
)
489 err
= netdev_get_flag(name
, &flag
);
499 int netdev_get_mtu(int ifindex
)
501 struct nl_handler nlh
;
502 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
503 struct ifinfomsg
*ifi
;
504 struct nlmsghdr
*msg
;
506 int recv_len
= 0, answer_len
;
509 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
514 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
518 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
522 /* Save the answer buffer length, since it will be overwritten
523 * on the first receive (and we might need to receive more than
525 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
527 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
|NLM_F_DUMP
;
528 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETLINK
;
530 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
533 ifi
->ifi_family
= AF_UNSPEC
;
535 /* Send the request for addresses, which returns all addresses
536 * on all interfaces. */
537 err
= netlink_send(&nlh
, nlmsg
);
542 /* Restore the answer buffer length, it might have been
543 * overwritten by a previous receive. */
544 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
546 /* Get the (next) batch of reply messages */
547 err
= netlink_rcv(&nlh
, answer
);
554 /* Satisfy the typing for the netlink macros */
555 msg
= answer
->nlmsghdr
;
557 while (NLMSG_OK(msg
, recv_len
)) {
559 /* Stop reading if we see an error message */
560 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
561 struct nlmsgerr
*errmsg
= (struct nlmsgerr
*)NLMSG_DATA(msg
);
566 /* Stop reading if we see a NLMSG_DONE message */
567 if (msg
->nlmsg_type
== NLMSG_DONE
) {
572 ifi
= NLMSG_DATA(msg
);
573 if (ifi
->ifi_index
== ifindex
) {
574 struct rtattr
*rta
= IFLA_RTA(ifi
);
575 int attr_len
= msg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
577 while(RTA_OK(rta
, attr_len
)) {
578 /* Found a local address for the requested interface,
580 if (rta
->rta_type
== IFLA_MTU
) {
581 memcpy(&res
, RTA_DATA(rta
), sizeof(int));
585 rta
= RTA_NEXT(rta
, attr_len
);
590 /* Keep reading more data from the socket if the
591 * last message had the NLF_F_MULTI flag set */
592 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
594 /* Look at the next message received in this buffer */
595 msg
= NLMSG_NEXT(msg
, recv_len
);
599 /* If we end up here, we didn't find any result, so signal an
610 int lxc_netdev_set_mtu(const char *name
, int mtu
)
612 struct nl_handler nlh
;
613 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
614 struct ifinfomsg
*ifi
;
617 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
623 if (len
== 1 || len
>= IFNAMSIZ
)
627 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
631 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
636 index
= if_nametoindex(name
);
640 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
641 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
643 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
648 ifi
->ifi_family
= AF_UNSPEC
;
649 ifi
->ifi_index
= index
;
651 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
654 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
662 int lxc_netdev_up(const char *name
)
664 return netdev_set_flag(name
, IFF_UP
);
667 int lxc_netdev_down(const char *name
)
669 return netdev_set_flag(name
, 0);
672 int lxc_veth_create(const char *name1
, const char *name2
)
674 struct nl_handler nlh
;
675 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
676 struct ifinfomsg
*ifi
;
677 struct rtattr
*nest1
, *nest2
, *nest3
;
680 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
686 if (len
== 1 || len
>= IFNAMSIZ
)
690 if (len
== 1 || len
>= IFNAMSIZ
)
694 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
698 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
702 nlmsg
->nlmsghdr
->nlmsg_flags
=
703 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
704 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
706 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
709 ifi
->ifi_family
= AF_UNSPEC
;
712 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
716 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
719 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
723 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
727 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
733 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
736 nla_end_nested(nlmsg
, nest3
);
738 nla_end_nested(nlmsg
, nest2
);
740 nla_end_nested(nlmsg
, nest1
);
742 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
745 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
753 /* XXX: merge with lxc_macvlan_create */
754 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
756 struct nl_handler nlh
;
757 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
758 struct ifinfomsg
*ifi
;
759 struct rtattr
*nest
, *nest2
;
760 int lindex
, len
, err
;
762 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
767 len
= strlen(master
);
768 if (len
== 1 || len
>= IFNAMSIZ
)
772 if (len
== 1 || len
>= IFNAMSIZ
)
776 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
780 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
785 lindex
= if_nametoindex(master
);
789 nlmsg
->nlmsghdr
->nlmsg_flags
=
790 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
791 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
793 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
798 ifi
->ifi_family
= AF_UNSPEC
;
800 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
804 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
807 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
811 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
814 nla_end_nested(nlmsg
, nest2
);
816 nla_end_nested(nlmsg
, nest
);
818 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
821 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
824 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
834 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
836 struct nl_handler nlh
;
837 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
838 struct ifinfomsg
*ifi
;
839 struct rtattr
*nest
, *nest2
;
842 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
847 len
= strlen(master
);
848 if (len
== 1 || len
>= IFNAMSIZ
)
852 if (len
== 1 || len
>= IFNAMSIZ
)
856 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
860 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
865 index
= if_nametoindex(master
);
869 nlmsg
->nlmsghdr
->nlmsg_flags
=
870 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
871 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWLINK
;
873 ifi
= nlmsg_reserve(nlmsg
, sizeof(struct ifinfomsg
));
878 ifi
->ifi_family
= AF_UNSPEC
;
880 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
884 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
888 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
892 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
895 nla_end_nested(nlmsg
, nest2
);
898 nla_end_nested(nlmsg
, nest
);
900 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
903 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
906 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
914 static int proc_sys_net_write(const char *path
, const char *value
)
918 fd
= open(path
, O_WRONLY
);
922 if (write(fd
, value
, strlen(value
)) < 0)
929 static int ip_forward_set(const char *ifname
, int family
, int flag
)
931 char path
[MAXPATHLEN
];
934 if (family
!= AF_INET
&& family
!= AF_INET6
)
937 rc
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/forwarding",
938 family
== AF_INET
?"ipv4":"ipv6" , ifname
);
939 if (rc
>= MAXPATHLEN
)
942 return proc_sys_net_write(path
, flag
?"1":"0");
945 int lxc_ip_forward_on(const char *ifname
, int family
)
947 return ip_forward_set(ifname
, family
, 1);
950 int lxc_ip_forward_off(const char *ifname
, int family
)
952 return ip_forward_set(ifname
, family
, 0);
955 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
957 char path
[MAXPATHLEN
];
960 if (family
!= AF_INET
&& family
!= AF_INET6
)
963 ret
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/%s",
964 family
== AF_INET
?"ipv4":"ipv6" , ifname
,
965 family
== AF_INET
?"proxy_arp":"proxy_ndp");
966 if (ret
< 0 || ret
>= MAXPATHLEN
)
969 return proc_sys_net_write(path
, flag
?"1":"0");
972 int lxc_neigh_proxy_on(const char *name
, int family
)
974 return neigh_proxy_set(name
, family
, 1);
977 int lxc_neigh_proxy_off(const char *name
, int family
)
979 return neigh_proxy_set(name
, family
, 0);
982 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
989 sockaddr
->sa_family
= ARPHRD_ETHER
;
990 data
= (unsigned char *)sockaddr
->sa_data
;
992 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
997 else if (c
>= 'a' && c
<= 'f')
999 else if (c
>= 'A' && c
<= 'F')
1008 else if (c
>= 'a' && c
<= 'f')
1009 val
|= c
- 'a' + 10;
1010 else if (c
>= 'A' && c
<= 'F')
1011 val
|= c
- 'A' + 10;
1012 else if (c
== ':' || c
== 0)
1019 *data
++ = (unsigned char) (val
& 0377);
1022 if (*macaddr
== ':')
1029 static int ip_addr_add(int family
, int ifindex
,
1030 void *addr
, void *bcast
, void *acast
, int prefix
)
1032 struct nl_handler nlh
;
1033 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1034 struct ifaddrmsg
*ifa
;
1038 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1039 sizeof(struct in6_addr
);
1041 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1046 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1050 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1054 nlmsg
->nlmsghdr
->nlmsg_flags
=
1055 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1056 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWADDR
;
1058 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1061 ifa
->ifa_prefixlen
= prefix
;
1062 ifa
->ifa_index
= ifindex
;
1063 ifa
->ifa_family
= family
;
1067 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
1070 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
1073 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
1076 /* TODO : multicast, anycast with ipv6 */
1077 err
= -EPROTONOSUPPORT
;
1078 if (family
== AF_INET6
&&
1079 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
1080 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
1083 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1085 netlink_close(&nlh
);
1091 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
1092 struct in6_addr
*mcast
,
1093 struct in6_addr
*acast
, int prefix
)
1095 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
1098 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
,
1099 struct in_addr
*bcast
, int prefix
)
1101 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
1104 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
1105 * address from the given RTM_NEWADDR message. Allocates memory for the
1106 * address and stores that pointer in *res (so res should be an
1107 * in_addr** or in6_addr**).
1109 static int ifa_get_local_ip(int family
, struct nlmsghdr
*msg
, void** res
) {
1110 struct ifaddrmsg
*ifa
= NLMSG_DATA(msg
);
1111 struct rtattr
*rta
= IFA_RTA(ifa
);
1112 int attr_len
= NLMSG_PAYLOAD(msg
, sizeof(struct ifaddrmsg
));
1115 if (ifa
->ifa_family
!= family
)
1118 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1119 sizeof(struct in6_addr
);
1121 /* Loop over the rtattr's in this message */
1122 while(RTA_OK(rta
, attr_len
)) {
1123 /* Found a local address for the requested interface,
1125 if (rta
->rta_type
== IFA_LOCAL
|| rta
->rta_type
== IFA_ADDRESS
) {
1126 /* Sanity check. The family check above should
1127 * make sure the address length is correct, but
1128 * check here just in case */
1129 if (RTA_PAYLOAD(rta
) != addrlen
)
1132 /* We might have found an IFA_ADDRESS before,
1133 * which we now overwrite with an IFA_LOCAL. */
1135 *res
= malloc(addrlen
);
1140 memcpy(*res
, RTA_DATA(rta
), addrlen
);
1142 if (rta
->rta_type
== IFA_LOCAL
)
1145 rta
= RTA_NEXT(rta
, attr_len
);
1150 static int ip_addr_get(int family
, int ifindex
, void **res
)
1152 struct nl_handler nlh
;
1153 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1154 struct ifaddrmsg
*ifa
;
1155 struct nlmsghdr
*msg
;
1157 int recv_len
= 0, answer_len
;
1160 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1165 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1169 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1173 /* Save the answer buffer length, since it will be overwritten
1174 * on the first receive (and we might need to receive more than
1176 answer_len
= answer
->nlmsghdr
->nlmsg_len
;
1178 nlmsg
->nlmsghdr
->nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ROOT
;
1179 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_GETADDR
;
1181 ifa
= nlmsg_reserve(nlmsg
, sizeof(struct ifaddrmsg
));
1184 ifa
->ifa_family
= family
;
1186 /* Send the request for addresses, which returns all addresses
1187 * on all interfaces. */
1188 err
= netlink_send(&nlh
, nlmsg
);
1193 /* Restore the answer buffer length, it might have been
1194 * overwritten by a previous receive. */
1195 answer
->nlmsghdr
->nlmsg_len
= answer_len
;
1197 /* Get the (next) batch of reply messages */
1198 err
= netlink_rcv(&nlh
, answer
);
1205 /* Satisfy the typing for the netlink macros */
1206 msg
= answer
->nlmsghdr
;
1208 while (NLMSG_OK(msg
, recv_len
)) {
1209 /* Stop reading if we see an error message */
1210 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
1211 struct nlmsgerr
*errmsg
= (struct nlmsgerr
*)NLMSG_DATA(msg
);
1212 err
= errmsg
->error
;
1216 /* Stop reading if we see a NLMSG_DONE message */
1217 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1222 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
1227 ifa
= (struct ifaddrmsg
*)NLMSG_DATA(msg
);
1228 if (ifa
->ifa_index
== ifindex
) {
1229 if (ifa_get_local_ip(family
, msg
, res
) < 0) {
1234 /* Found a result, stop searching */
1239 /* Keep reading more data from the socket if the
1240 * last message had the NLF_F_MULTI flag set */
1241 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1243 /* Look at the next message received in this buffer */
1244 msg
= NLMSG_NEXT(msg
, recv_len
);
1248 /* If we end up here, we didn't find any result, so signal an
1253 netlink_close(&nlh
);
1259 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
1261 return ip_addr_get(AF_INET6
, ifindex
, (void**)res
);
1264 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
** res
)
1266 return ip_addr_get(AF_INET
, ifindex
, (void**)res
);
1269 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
1271 struct nl_handler nlh
;
1272 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1277 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1278 sizeof(struct in6_addr
);
1280 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1285 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1289 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1293 nlmsg
->nlmsghdr
->nlmsg_flags
=
1294 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1295 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
1297 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
1300 rt
->rtm_family
= family
;
1301 rt
->rtm_table
= RT_TABLE_MAIN
;
1302 rt
->rtm_scope
= RT_SCOPE_UNIVERSE
;
1303 rt
->rtm_protocol
= RTPROT_BOOT
;
1304 rt
->rtm_type
= RTN_UNICAST
;
1305 /* "default" destination */
1306 rt
->rtm_dst_len
= 0;
1309 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
1312 /* Adding the interface index enables the use of link-local
1313 * addresses for the gateway */
1314 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1317 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1319 netlink_close(&nlh
);
1325 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
1327 return ip_gateway_add(AF_INET
, ifindex
, gw
);
1330 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
1332 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
1335 static int ip_route_dest_add(int family
, int ifindex
, void *dest
)
1337 struct nl_handler nlh
;
1338 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1343 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1344 sizeof(struct in6_addr
);
1346 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1351 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1355 answer
= nlmsg_alloc_reserve(NLMSG_GOOD_SIZE
);
1359 nlmsg
->nlmsghdr
->nlmsg_flags
=
1360 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1361 nlmsg
->nlmsghdr
->nlmsg_type
= RTM_NEWROUTE
;
1363 rt
= nlmsg_reserve(nlmsg
, sizeof(struct rtmsg
));
1366 rt
->rtm_family
= family
;
1367 rt
->rtm_table
= RT_TABLE_MAIN
;
1368 rt
->rtm_scope
= RT_SCOPE_LINK
;
1369 rt
->rtm_protocol
= RTPROT_BOOT
;
1370 rt
->rtm_type
= RTN_UNICAST
;
1371 rt
->rtm_dst_len
= addrlen
*8;
1374 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
1376 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1378 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1380 netlink_close(&nlh
);
1386 int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
)
1388 return ip_route_dest_add(AF_INET
, ifindex
, dest
);
1391 int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
)
1393 return ip_route_dest_add(AF_INET6
, ifindex
, dest
);
1396 static bool is_ovs_bridge(const char *bridge
)
1398 char brdirname
[22 + IFNAMSIZ
+ 1] = {0};
1401 snprintf(brdirname
, 22 +IFNAMSIZ
+ 1, "/sys/class/net/%s/bridge", bridge
);
1402 if (stat(brdirname
, &sb
) == -1 && errno
== ENOENT
)
1408 * Called from a background thread - when nic goes away, remove
1409 * it from the bridge
1411 static void ovs_cleanup_nic(const char *lxcpath
, const char *name
, const char *bridge
, const char *nic
)
1413 if (lxc_check_inherited(NULL
, true, &(int){-1}, 1) < 0)
1415 if (lxc_wait(name
, "STOPPED", -1, lxcpath
) < 0)
1417 execlp("ovs-vsctl", "ovs-vsctl", "del-port", bridge
, nic
, (char *)NULL
);
1418 exit(1); /* not reached */
1421 static int attach_to_ovs_bridge(const char *lxcpath
, const char *name
, const char *bridge
, const char *nic
)
1427 cmd
= on_path("ovs-vsctl", NULL
);
1436 ret
= wait_for_pid(pid
);
1441 return -1; // how to properly recover?
1444 ovs_cleanup_nic(lxcpath
, name
, bridge
, nic
);
1448 if (execlp("ovs-vsctl", "ovs-vsctl", "add-port", bridge
, nic
, (char *)NULL
))
1455 * There is a lxc_bridge_attach, but no need of a bridge detach
1456 * as automatically done by kernel when a netdev is deleted.
1458 int lxc_bridge_attach(const char *lxcpath
, const char *name
, const char *bridge
, const char *ifname
)
1463 if (strlen(ifname
) >= IFNAMSIZ
)
1466 index
= if_nametoindex(ifname
);
1470 if (is_ovs_bridge(bridge
))
1471 return attach_to_ovs_bridge(lxcpath
, name
, bridge
, ifname
);
1473 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
1477 strncpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
-1);
1478 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
1479 ifr
.ifr_ifindex
= index
;
1480 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
1488 static const char* const lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
1489 [LXC_NET_EMPTY
] = "empty",
1490 [LXC_NET_VETH
] = "veth",
1491 [LXC_NET_MACVLAN
] = "macvlan",
1492 [LXC_NET_PHYS
] = "phys",
1493 [LXC_NET_VLAN
] = "vlan",
1494 [LXC_NET_NONE
] = "none",
1497 const char *lxc_net_type_to_str(int type
)
1499 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
1501 return lxc_network_types
[type
];
1504 static const char padchar
[] =
1505 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1507 char *lxc_mkifname(char *template)
1513 struct ifaddrs
*ifaddr
, *ifa
;
1516 /* Get all the network interfaces */
1517 getifaddrs(&ifaddr
);
1519 /* Initialize the random number generator */
1520 urandom
= fopen ("/dev/urandom", "r");
1521 if (urandom
!= NULL
) {
1522 if (fread (&seed
, sizeof(seed
), 1, urandom
) <= 0)
1533 /* Generate random names until we find one that doesn't exist */
1536 name
= strdup(template);
1541 for (i
= 0; i
< strlen(name
); i
++) {
1542 if (name
[i
] == 'X') {
1544 name
[i
] = padchar
[rand_r(&seed
) % (strlen(padchar
) - 1)];
1546 name
[i
] = padchar
[rand() % (strlen(padchar
) - 1)];
1551 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1552 if (strcmp(ifa
->ifa_name
, name
) == 0) {
1564 freeifaddrs(ifaddr
);
1568 int setup_private_host_hw_addr(char *veth1
)
1574 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1578 snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
1579 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
1585 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
1586 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);