]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
4c577b17dfe285654b6f20363021f9df26ceda21
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 <arpa/inet.h>
41 #include <net/if_arp.h>
42 #include <net/ethernet.h>
43 #include <netinet/in.h>
44 #include <linux/netlink.h>
45 #include <linux/rtnetlink.h>
46 #include <linux/sockios.h>
56 #include <../include/ifaddrs.h>
60 # define IFLA_LINKMODE 17
64 # define IFLA_LINKINFO 18
67 #ifndef IFLA_NET_NS_PID
68 # define IFLA_NET_NS_PID 19
71 #ifndef IFLA_INFO_KIND
72 # define IFLA_INFO_KIND 1
76 # define IFLA_VLAN_ID 1
79 #ifndef IFLA_INFO_DATA
80 # define IFLA_INFO_DATA 2
83 #ifndef VETH_INFO_PEER
84 # define VETH_INFO_PEER 1
87 #ifndef IFLA_MACVLAN_MODE
88 # define IFLA_MACVLAN_MODE 1
93 struct ifinfomsg ifinfomsg
;
106 int lxc_netdev_move_by_index(int ifindex
, pid_t pid
, const char* ifname
)
108 struct nl_handler nlh
;
109 struct nlmsg
*nlmsg
= NULL
;
110 struct link_req
*link_req
;
113 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
118 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
122 link_req
= (struct link_req
*)nlmsg
;
123 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
124 link_req
->ifinfomsg
.ifi_index
= ifindex
;
125 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
126 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
127 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
129 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
132 if (ifname
!= NULL
) {
133 if (nla_put_string(nlmsg
, IFLA_IFNAME
, ifname
))
137 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
144 int lxc_netdev_move_by_name(const char *ifname
, pid_t pid
, const char* newname
)
151 index
= if_nametoindex(ifname
);
155 return lxc_netdev_move_by_index(index
, pid
, newname
);
158 int lxc_netdev_delete_by_index(int ifindex
)
160 struct nl_handler nlh
;
161 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
162 struct link_req
*link_req
;
165 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
170 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
174 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
178 link_req
= (struct link_req
*)nlmsg
;
179 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
180 link_req
->ifinfomsg
.ifi_index
= ifindex
;
181 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
182 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
183 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_DELLINK
;
185 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
193 int lxc_netdev_delete_by_name(const char *name
)
197 index
= if_nametoindex(name
);
201 return lxc_netdev_delete_by_index(index
);
204 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
206 struct nl_handler nlh
;
207 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
208 struct link_req
*link_req
;
211 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
215 len
= strlen(newname
);
216 if (len
== 1 || len
>= IFNAMSIZ
)
220 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
224 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
228 link_req
= (struct link_req
*)nlmsg
;
229 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
230 link_req
->ifinfomsg
.ifi_index
= ifindex
;
231 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
232 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
233 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
235 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
238 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
246 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
250 len
= strlen(oldname
);
251 if (len
== 1 || len
>= IFNAMSIZ
)
254 index
= if_nametoindex(oldname
);
258 return lxc_netdev_rename_by_index(index
, newname
);
261 int netdev_set_flag(const char *name
, int flag
)
263 struct nl_handler nlh
;
264 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
265 struct link_req
*link_req
;
268 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
274 if (len
== 1 || len
>= IFNAMSIZ
)
278 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
282 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
287 index
= if_nametoindex(name
);
291 link_req
= (struct link_req
*)nlmsg
;
292 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
293 link_req
->ifinfomsg
.ifi_index
= index
;
294 link_req
->ifinfomsg
.ifi_change
|= IFF_UP
;
295 link_req
->ifinfomsg
.ifi_flags
|= flag
;
296 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
297 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
298 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
300 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
308 int netdev_get_mtu(int ifindex
)
310 struct nl_handler nlh
;
311 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
312 struct ip_req
*ip_req
;
313 struct nlmsghdr
*msg
;
315 int recv_len
= 0, answer_len
;
318 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
323 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
327 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
331 /* Save the answer buffer length, since it will be overwritten
332 * on the first receive (and we might need to receive more than
334 answer_len
= answer
->nlmsghdr
.nlmsg_len
;
336 ip_req
= (struct ip_req
*)nlmsg
;
337 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
338 NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
339 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_DUMP
;
340 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_GETLINK
;
341 ip_req
->ifa
.ifa_family
= AF_UNSPEC
;
343 /* Send the request for addresses, which returns all addresses
344 * on all interfaces. */
345 err
= netlink_send(&nlh
, nlmsg
);
350 /* Restore the answer buffer length, it might have been
351 * overwritten by a previous receive. */
352 answer
->nlmsghdr
.nlmsg_len
= answer_len
;
354 /* Get the (next) batch of reply messages */
355 err
= netlink_rcv(&nlh
, answer
);
362 /* Satisfy the typing for the netlink macros */
363 msg
= &answer
->nlmsghdr
;
365 while (NLMSG_OK(msg
, recv_len
)) {
367 /* Stop reading if we see an error message */
368 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
369 struct nlmsgerr
*errmsg
= (struct nlmsgerr
*)NLMSG_DATA(msg
);
374 /* Stop reading if we see a NLMSG_DONE message */
375 if (msg
->nlmsg_type
== NLMSG_DONE
) {
380 struct ifinfomsg
*ifi
= NLMSG_DATA(msg
);
381 if (ifi
->ifi_index
== ifindex
) {
382 struct rtattr
*rta
= IFLA_RTA(ifi
);
383 int attr_len
= msg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
385 while(RTA_OK(rta
, attr_len
)) {
386 /* Found a local address for the requested interface,
388 if (rta
->rta_type
== IFLA_MTU
) {
389 memcpy(&res
, RTA_DATA(rta
), sizeof(int));
393 rta
= RTA_NEXT(rta
, attr_len
);
398 /* Keep reading more data from the socket if the
399 * last message had the NLF_F_MULTI flag set */
400 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
402 /* Look at the next message received in this buffer */
403 msg
= NLMSG_NEXT(msg
, recv_len
);
407 /* If we end up here, we didn't find any result, so signal an
418 int lxc_netdev_set_mtu(const char *name
, int mtu
)
420 struct nl_handler nlh
;
421 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
422 struct link_req
*link_req
;
425 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
431 if (len
== 1 || len
>= IFNAMSIZ
)
435 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
439 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
444 index
= if_nametoindex(name
);
448 link_req
= (struct link_req
*)nlmsg
;
449 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
450 link_req
->ifinfomsg
.ifi_index
= index
;
451 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
452 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
453 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
455 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
458 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
466 int lxc_netdev_up(const char *name
)
468 return netdev_set_flag(name
, IFF_UP
);
471 int lxc_netdev_down(const char *name
)
473 return netdev_set_flag(name
, 0);
476 int lxc_veth_create(const char *name1
, const char *name2
)
478 struct nl_handler nlh
;
479 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
480 struct link_req
*link_req
;
481 struct rtattr
*nest1
, *nest2
, *nest3
;
484 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
490 if (len
== 1 || len
>= IFNAMSIZ
)
494 if (len
== 1 || len
>= IFNAMSIZ
)
498 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
502 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
506 link_req
= (struct link_req
*)nlmsg
;
507 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
508 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
509 nlmsg
->nlmsghdr
.nlmsg_flags
=
510 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
511 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
514 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
518 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
521 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
525 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
529 nlmsg
->nlmsghdr
.nlmsg_len
+= sizeof(struct ifinfomsg
);
531 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
534 nla_end_nested(nlmsg
, nest3
);
536 nla_end_nested(nlmsg
, nest2
);
538 nla_end_nested(nlmsg
, nest1
);
540 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
543 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
551 /* XXX: merge with lxc_macvlan_create */
552 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
554 struct nl_handler nlh
;
555 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
556 struct link_req
*link_req
;
557 struct rtattr
*nest
, *nest2
;
558 int lindex
, len
, err
;
560 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
565 len
= strlen(master
);
566 if (len
== 1 || len
>= IFNAMSIZ
)
570 if (len
== 1 || len
>= IFNAMSIZ
)
574 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
578 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
583 lindex
= if_nametoindex(master
);
587 link_req
= (struct link_req
*)nlmsg
;
588 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
589 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
590 nlmsg
->nlmsghdr
.nlmsg_flags
=
591 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
592 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
594 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
598 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
601 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
605 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
608 nla_end_nested(nlmsg
, nest2
);
610 nla_end_nested(nlmsg
, nest
);
612 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
615 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
618 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
628 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
630 struct nl_handler nlh
;
631 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
632 struct link_req
*link_req
;
633 struct rtattr
*nest
, *nest2
;
636 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
641 len
= strlen(master
);
642 if (len
== 1 || len
>= IFNAMSIZ
)
646 if (len
== 1 || len
>= IFNAMSIZ
)
650 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
654 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
659 index
= if_nametoindex(master
);
663 link_req
= (struct link_req
*)nlmsg
;
664 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
665 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
666 nlmsg
->nlmsghdr
.nlmsg_flags
=
667 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
668 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
670 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
674 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
678 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
682 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
685 nla_end_nested(nlmsg
, nest2
);
688 nla_end_nested(nlmsg
, nest
);
690 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
693 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
696 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
704 static int proc_sys_net_write(const char *path
, const char *value
)
708 fd
= open(path
, O_WRONLY
);
712 if (write(fd
, value
, strlen(value
)) < 0)
719 static int ip_forward_set(const char *ifname
, int family
, int flag
)
721 char path
[MAXPATHLEN
];
724 if (family
!= AF_INET
&& family
!= AF_INET6
)
727 rc
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/forwarding",
728 family
== AF_INET
?"ipv4":"ipv6" , ifname
);
729 if (rc
>= MAXPATHLEN
)
732 return proc_sys_net_write(path
, flag
?"1":"0");
735 int lxc_ip_forward_on(const char *ifname
, int family
)
737 return ip_forward_set(ifname
, family
, 1);
740 int lxc_ip_forward_off(const char *ifname
, int family
)
742 return ip_forward_set(ifname
, family
, 0);
745 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
747 char path
[MAXPATHLEN
];
750 if (family
!= AF_INET
&& family
!= AF_INET6
)
753 ret
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/%s",
754 family
== AF_INET
?"ipv4":"ipv6" , ifname
,
755 family
== AF_INET
?"proxy_arp":"proxy_ndp");
756 if (ret
< 0 || ret
>= MAXPATHLEN
)
759 return proc_sys_net_write(path
, flag
?"1":"0");
762 int lxc_neigh_proxy_on(const char *name
, int family
)
764 return neigh_proxy_set(name
, family
, 1);
767 int lxc_neigh_proxy_off(const char *name
, int family
)
769 return neigh_proxy_set(name
, family
, 0);
772 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
779 sockaddr
->sa_family
= ARPHRD_ETHER
;
780 data
= (unsigned char *)sockaddr
->sa_data
;
782 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
787 else if (c
>= 'a' && c
<= 'f')
789 else if (c
>= 'A' && c
<= 'F')
798 else if (c
>= 'a' && c
<= 'f')
800 else if (c
>= 'A' && c
<= 'F')
802 else if (c
== ':' || c
== 0)
809 *data
++ = (unsigned char) (val
& 0377);
819 static int ip_addr_add(int family
, int ifindex
,
820 void *addr
, void *bcast
, void *acast
, int prefix
)
822 struct nl_handler nlh
;
823 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
824 struct ip_req
*ip_req
;
828 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
829 sizeof(struct in6_addr
);
831 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
836 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
840 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
844 ip_req
= (struct ip_req
*)nlmsg
;
845 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
846 NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
847 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
848 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
849 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWADDR
;
850 ip_req
->ifa
.ifa_prefixlen
= prefix
;
851 ip_req
->ifa
.ifa_index
= ifindex
;
852 ip_req
->ifa
.ifa_family
= family
;
853 ip_req
->ifa
.ifa_scope
= 0;
856 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
859 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
862 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
865 /* TODO : multicast, anycast with ipv6 */
866 err
= -EPROTONOSUPPORT
;
867 if (family
== AF_INET6
&&
868 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
869 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
872 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
880 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
881 struct in6_addr
*mcast
,
882 struct in6_addr
*acast
, int prefix
)
884 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
887 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
,
888 struct in_addr
*bcast
, int prefix
)
890 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
893 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
894 * address from the given RTM_NEWADDR message. Allocates memory for the
895 * address and stores that pointer in *res (so res should be an
896 * in_addr** or in6_addr**).
898 static int ifa_get_local_ip(int family
, struct ip_req
*ip_info
, void** res
) {
899 struct rtattr
*rta
= IFA_RTA(&ip_info
->ifa
);
900 int attr_len
= IFA_PAYLOAD(&ip_info
->nlmsg
.nlmsghdr
);
903 if (ip_info
->ifa
.ifa_family
!= family
)
906 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
907 sizeof(struct in6_addr
);
909 /* Loop over the rtattr's in this message */
910 while(RTA_OK(rta
, attr_len
)) {
911 /* Found a local address for the requested interface,
913 if (rta
->rta_type
== IFA_LOCAL
|| rta
->rta_type
== IFA_ADDRESS
) {
914 /* Sanity check. The family check above should
915 * make sure the address length is correct, but
916 * check here just in case */
917 if (RTA_PAYLOAD(rta
) != addrlen
)
920 /* We might have found an IFA_ADDRESS before,
921 * which we now overwrite with an IFA_LOCAL. */
923 *res
= malloc(addrlen
);
928 memcpy(*res
, RTA_DATA(rta
), addrlen
);
930 if (rta
->rta_type
== IFA_LOCAL
)
933 rta
= RTA_NEXT(rta
, attr_len
);
938 static int ip_addr_get(int family
, int ifindex
, void **res
)
940 struct nl_handler nlh
;
941 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
942 struct ip_req
*ip_req
, *ip_info
;
943 struct nlmsghdr
*msg
;
945 int recv_len
= 0, answer_len
;
948 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
953 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
957 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
961 /* Save the answer buffer length, since it will be overwritten
962 * on the first receive (and we might need to receive more than
964 answer_len
= answer
->nlmsghdr
.nlmsg_len
;
966 ip_req
= (struct ip_req
*)nlmsg
;
967 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
968 NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
969 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ROOT
;
970 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_GETADDR
;
971 ip_req
->ifa
.ifa_family
= family
;
973 /* Send the request for addresses, which returns all addresses
974 * on all interfaces. */
975 err
= netlink_send(&nlh
, nlmsg
);
980 /* Restore the answer buffer length, it might have been
981 * overwritten by a previous receive. */
982 answer
->nlmsghdr
.nlmsg_len
= answer_len
;
984 /* Get the (next) batch of reply messages */
985 err
= netlink_rcv(&nlh
, answer
);
992 /* Satisfy the typing for the netlink macros */
993 msg
= &answer
->nlmsghdr
;
995 while (NLMSG_OK(msg
, recv_len
)) {
996 /* Stop reading if we see an error message */
997 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
998 struct nlmsgerr
*errmsg
= (struct nlmsgerr
*)NLMSG_DATA(msg
);
1003 /* Stop reading if we see a NLMSG_DONE message */
1004 if (msg
->nlmsg_type
== NLMSG_DONE
) {
1009 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
1014 ip_info
= (struct ip_req
*)msg
;
1015 if (ip_info
->ifa
.ifa_index
== ifindex
) {
1016 if (ifa_get_local_ip(family
, ip_info
, res
) < 0) {
1021 /* Found a result, stop searching */
1026 /* Keep reading more data from the socket if the
1027 * last message had the NLF_F_MULTI flag set */
1028 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
1030 /* Look at the next message received in this buffer */
1031 msg
= NLMSG_NEXT(msg
, recv_len
);
1035 /* If we end up here, we didn't find any result, so signal an
1040 netlink_close(&nlh
);
1046 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
1048 return ip_addr_get(AF_INET6
, ifindex
, (void**)res
);
1051 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
** res
)
1053 return ip_addr_get(AF_INET
, ifindex
, (void**)res
);
1056 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
1058 struct nl_handler nlh
;
1059 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1060 struct rt_req
*rt_req
;
1064 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1065 sizeof(struct in6_addr
);
1067 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1072 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1076 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1080 rt_req
= (struct rt_req
*)nlmsg
;
1081 rt_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
1082 NLMSG_LENGTH(sizeof(struct rtmsg
));
1083 rt_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
1084 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1085 rt_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWROUTE
;
1086 rt_req
->rt
.rtm_family
= family
;
1087 rt_req
->rt
.rtm_table
= RT_TABLE_MAIN
;
1088 rt_req
->rt
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1089 rt_req
->rt
.rtm_protocol
= RTPROT_BOOT
;
1090 rt_req
->rt
.rtm_type
= RTN_UNICAST
;
1091 /* "default" destination */
1092 rt_req
->rt
.rtm_dst_len
= 0;
1095 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
1098 /* Adding the interface index enables the use of link-local
1099 * addresses for the gateway */
1100 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1103 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1105 netlink_close(&nlh
);
1111 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
1113 return ip_gateway_add(AF_INET
, ifindex
, gw
);
1116 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
1118 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
1121 static int ip_route_dest_add(int family
, int ifindex
, void *dest
)
1123 struct nl_handler nlh
;
1124 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1125 struct rt_req
*rt_req
;
1129 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1130 sizeof(struct in6_addr
);
1132 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1137 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1141 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1145 rt_req
= (struct rt_req
*)nlmsg
;
1146 rt_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
1147 NLMSG_LENGTH(sizeof(struct rtmsg
));
1148 rt_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
1149 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1150 rt_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWROUTE
;
1151 rt_req
->rt
.rtm_family
= family
;
1152 rt_req
->rt
.rtm_table
= RT_TABLE_MAIN
;
1153 rt_req
->rt
.rtm_scope
= RT_SCOPE_LINK
;
1154 rt_req
->rt
.rtm_protocol
= RTPROT_BOOT
;
1155 rt_req
->rt
.rtm_type
= RTN_UNICAST
;
1156 rt_req
->rt
.rtm_dst_len
= addrlen
*8;
1159 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
1161 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1163 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1165 netlink_close(&nlh
);
1171 int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
)
1173 return ip_route_dest_add(AF_INET
, ifindex
, dest
);
1176 int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
)
1178 return ip_route_dest_add(AF_INET6
, ifindex
, dest
);
1181 static bool is_ovs_bridge(const char *bridge
)
1183 char brdirname
[22 + IFNAMSIZ
+ 1] = {0};
1186 snprintf(brdirname
, 22 +IFNAMSIZ
+ 1, "/sys/class/net/%s/bridge", bridge
);
1187 if (stat(brdirname
, &sb
) == -1 && errno
== ENOENT
)
1192 static int attach_to_ovs_bridge(const char *bridge
, const char *nic
)
1197 cmd
= on_path("ovs-vsctl", NULL
);
1206 return wait_for_pid(pid
);
1208 if (execlp("ovs-vsctl", "ovs-vsctl", "add-port", bridge
, nic
, NULL
))
1215 * There is a lxc_bridge_attach, but no need of a bridge detach
1216 * as automatically done by kernel when a netdev is deleted.
1218 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
1223 if (strlen(ifname
) >= IFNAMSIZ
)
1226 index
= if_nametoindex(ifname
);
1230 if (is_ovs_bridge(bridge
))
1231 return attach_to_ovs_bridge(bridge
, ifname
);
1233 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
1237 strncpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
-1);
1238 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
1239 ifr
.ifr_ifindex
= index
;
1240 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
1248 static const char* const lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
1249 [LXC_NET_EMPTY
] = "empty",
1250 [LXC_NET_VETH
] = "veth",
1251 [LXC_NET_MACVLAN
] = "macvlan",
1252 [LXC_NET_PHYS
] = "phys",
1253 [LXC_NET_VLAN
] = "vlan",
1254 [LXC_NET_NONE
] = "none",
1257 const char *lxc_net_type_to_str(int type
)
1259 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
1261 return lxc_network_types
[type
];
1264 static const char padchar
[] =
1265 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1267 char *lxc_mkifname(char *template)
1273 struct ifaddrs
*ifaddr
, *ifa
;
1276 /* Get all the network interfaces */
1277 getifaddrs(&ifaddr
);
1279 /* Initialize the random number generator */
1280 urandom
= fopen ("/dev/urandom", "r");
1281 if (urandom
!= NULL
) {
1282 if (fread (&seed
, sizeof(seed
), 1, urandom
) <= 0)
1293 /* Generate random names until we find one that doesn't exist */
1296 name
= strdup(template);
1301 for (i
= 0; i
< strlen(name
); i
++) {
1302 if (name
[i
] == 'X') {
1304 name
[i
] = padchar
[rand_r(&seed
) % (strlen(padchar
) - 1)];
1306 name
[i
] = padchar
[rand() % (strlen(padchar
) - 1)];
1311 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1312 if (strcmp(ifa
->ifa_name
, name
) == 0) {
1324 freeifaddrs(ifaddr
);
1328 int setup_private_host_hw_addr(char *veth1
)
1334 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1338 snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
1339 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
1345 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
1346 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);