]>
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
33 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <arpa/inet.h>
40 #include <net/if_arp.h>
41 #include <net/ethernet.h>
42 #include <netinet/in.h>
43 #include <linux/netlink.h>
44 #include <linux/rtnetlink.h>
45 #include <linux/sockios.h>
46 #include <linux/if_bridge.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
)
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 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
139 int lxc_netdev_move_by_name(char *ifname
, pid_t pid
)
146 index
= if_nametoindex(ifname
);
148 return lxc_netdev_move_by_index(index
, pid
);
151 int lxc_netdev_delete_by_index(int ifindex
)
153 struct nl_handler nlh
;
154 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
155 struct link_req
*link_req
;
158 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
163 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
167 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
171 link_req
= (struct link_req
*)nlmsg
;
172 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
173 link_req
->ifinfomsg
.ifi_index
= ifindex
;
174 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
175 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
176 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_DELLINK
;
178 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
186 int lxc_netdev_delete_by_name(const char *name
)
190 index
= if_nametoindex(name
);
194 return lxc_netdev_delete_by_index(index
);
197 int lxc_netdev_rename_by_index(int ifindex
, const char *newname
)
199 struct nl_handler nlh
;
200 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
201 struct link_req
*link_req
;
204 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
208 len
= strlen(newname
);
209 if (len
== 1 || len
>= IFNAMSIZ
)
213 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
217 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
221 link_req
= (struct link_req
*)nlmsg
;
222 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
223 link_req
->ifinfomsg
.ifi_index
= ifindex
;
224 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
225 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
226 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
228 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
231 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
239 int lxc_netdev_rename_by_name(const char *oldname
, const char *newname
)
243 len
= strlen(oldname
);
244 if (len
== 1 || len
>= IFNAMSIZ
)
247 index
= if_nametoindex(oldname
);
251 return lxc_netdev_rename_by_index(index
, newname
);
254 int netdev_set_flag(const char *name
, int flag
)
256 struct nl_handler nlh
;
257 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
258 struct link_req
*link_req
;
261 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
267 if (len
== 1 || len
>= IFNAMSIZ
)
271 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
275 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
280 index
= if_nametoindex(name
);
284 link_req
= (struct link_req
*)nlmsg
;
285 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
286 link_req
->ifinfomsg
.ifi_index
= index
;
287 link_req
->ifinfomsg
.ifi_change
|= IFF_UP
;
288 link_req
->ifinfomsg
.ifi_flags
|= flag
;
289 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
290 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
291 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
293 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
301 int lxc_netdev_set_mtu(const char *name
, int mtu
)
303 struct nl_handler nlh
;
304 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
305 struct link_req
*link_req
;
308 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
314 if (len
== 1 || len
>= IFNAMSIZ
)
318 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
322 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
327 index
= if_nametoindex(name
);
331 link_req
= (struct link_req
*)nlmsg
;
332 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
333 link_req
->ifinfomsg
.ifi_index
= index
;
334 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
335 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
336 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
338 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
341 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
349 int lxc_netdev_up(const char *name
)
351 return netdev_set_flag(name
, IFF_UP
);
354 int lxc_netdev_down(const char *name
)
356 return netdev_set_flag(name
, 0);
359 int lxc_veth_create(const char *name1
, const char *name2
)
361 struct nl_handler nlh
;
362 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
363 struct link_req
*link_req
;
364 struct rtattr
*nest1
, *nest2
, *nest3
;
367 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
373 if (len
== 1 || len
>= IFNAMSIZ
)
377 if (len
== 1 || len
>= IFNAMSIZ
)
381 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
385 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
389 link_req
= (struct link_req
*)nlmsg
;
390 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
391 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
392 nlmsg
->nlmsghdr
.nlmsg_flags
=
393 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
394 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
397 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
401 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
404 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
408 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
412 nlmsg
->nlmsghdr
.nlmsg_len
+= sizeof(struct ifinfomsg
);
414 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
417 nla_end_nested(nlmsg
, nest3
);
419 nla_end_nested(nlmsg
, nest2
);
421 nla_end_nested(nlmsg
, nest1
);
423 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
426 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
434 /* XXX: merge with lxc_macvlan_create */
435 int lxc_vlan_create(const char *master
, const char *name
, unsigned short vlanid
)
437 struct nl_handler nlh
;
438 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
439 struct link_req
*link_req
;
440 struct rtattr
*nest
, *nest2
;
441 int lindex
, len
, err
;
443 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
448 len
= strlen(master
);
449 if (len
== 1 || len
>= IFNAMSIZ
)
453 if (len
== 1 || len
>= IFNAMSIZ
)
457 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
461 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
466 lindex
= if_nametoindex(master
);
470 link_req
= (struct link_req
*)nlmsg
;
471 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
472 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
473 nlmsg
->nlmsghdr
.nlmsg_flags
=
474 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
475 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
477 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
481 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
484 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
488 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
491 nla_end_nested(nlmsg
, nest2
);
493 nla_end_nested(nlmsg
, nest
);
495 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
498 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
501 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
511 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
513 struct nl_handler nlh
;
514 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
515 struct link_req
*link_req
;
516 struct rtattr
*nest
, *nest2
;
519 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
524 len
= strlen(master
);
525 if (len
== 1 || len
>= IFNAMSIZ
)
529 if (len
== 1 || len
>= IFNAMSIZ
)
533 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
537 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
542 index
= if_nametoindex(master
);
546 link_req
= (struct link_req
*)nlmsg
;
547 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
548 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
549 nlmsg
->nlmsghdr
.nlmsg_flags
=
550 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
551 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
553 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
557 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
561 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
565 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
568 nla_end_nested(nlmsg
, nest2
);
571 nla_end_nested(nlmsg
, nest
);
573 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
576 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
579 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
587 static int proc_sys_net_write(const char *path
, const char *value
)
592 fd
= open(path
, O_WRONLY
);
597 if (write(fd
, value
, strlen(value
)) < 0)
606 static int ip_forward_set(const char *ifname
, int family
, int flag
)
608 char path
[MAXPATHLEN
];
611 if (family
!= AF_INET
&& family
!= AF_INET6
)
614 rc
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/forwarding",
615 family
== AF_INET
?"ipv4":"ipv6" , ifname
);
616 if (rc
>= MAXPATHLEN
)
619 return proc_sys_net_write(path
, flag
?"1":"0");
622 int lxc_ip_forward_on(const char *ifname
, int family
)
624 return ip_forward_set(ifname
, family
, 1);
627 int lxc_ip_forward_off(const char *ifname
, int family
)
629 return ip_forward_set(ifname
, family
, 0);
632 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
634 char path
[MAXPATHLEN
];
637 if (family
!= AF_INET
&& family
!= AF_INET6
)
640 ret
= snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/%s",
641 family
== AF_INET
?"ipv4":"ipv6" , ifname
,
642 family
== AF_INET
?"proxy_arp":"proxy_ndp");
643 if (ret
< 0 || ret
>= MAXPATHLEN
)
646 return proc_sys_net_write(path
, flag
?"1":"0");
649 int lxc_neigh_proxy_on(const char *name
, int family
)
651 return neigh_proxy_set(name
, family
, 1);
654 int lxc_neigh_proxy_off(const char *name
, int family
)
656 return neigh_proxy_set(name
, family
, 0);
659 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
666 sockaddr
->sa_family
= ARPHRD_ETHER
;
667 data
= (unsigned char *)sockaddr
->sa_data
;
669 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
674 else if (c
>= 'a' && c
<= 'f')
676 else if (c
>= 'A' && c
<= 'F')
685 else if (c
>= 'a' && c
<= 'f')
687 else if (c
>= 'A' && c
<= 'F')
689 else if (c
== ':' || c
== 0)
696 *data
++ = (unsigned char) (val
& 0377);
706 static int ip_addr_add(int family
, int ifindex
,
707 void *addr
, void *bcast
, void *acast
, int prefix
)
709 struct nl_handler nlh
;
710 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
711 struct ip_req
*ip_req
;
715 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
716 sizeof(struct in6_addr
);
718 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
723 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
727 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
731 ip_req
= (struct ip_req
*)nlmsg
;
732 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
733 NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
734 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
735 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
736 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWADDR
;
737 ip_req
->ifa
.ifa_prefixlen
= prefix
;
738 ip_req
->ifa
.ifa_index
= ifindex
;
739 ip_req
->ifa
.ifa_family
= family
;
740 ip_req
->ifa
.ifa_scope
= 0;
743 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
746 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
749 if (nla_put_buffer(nlmsg
, IFA_BROADCAST
, bcast
, addrlen
))
752 /* TODO : multicast, anycast with ipv6 */
753 err
= -EPROTONOSUPPORT
;
754 if (family
== AF_INET6
&&
755 (memcmp(bcast
, &in6addr_any
, sizeof(in6addr_any
)) ||
756 memcmp(acast
, &in6addr_any
, sizeof(in6addr_any
))))
759 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
767 int lxc_ipv6_addr_add(int ifindex
, struct in6_addr
*addr
,
768 struct in6_addr
*mcast
,
769 struct in6_addr
*acast
, int prefix
)
771 return ip_addr_add(AF_INET6
, ifindex
, addr
, mcast
, acast
, prefix
);
774 int lxc_ipv4_addr_add(int ifindex
, struct in_addr
*addr
,
775 struct in_addr
*bcast
, int prefix
)
777 return ip_addr_add(AF_INET
, ifindex
, addr
, bcast
, NULL
, prefix
);
780 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
781 * address from the given RTM_NEWADDR message. Allocates memory for the
782 * address and stores that pointer in *res (so res should be an
783 * in_addr** or in6_addr**).
785 static int ifa_get_local_ip(int family
, struct ip_req
*ip_info
, void** res
) {
786 struct rtattr
*rta
= IFA_RTA(&ip_info
->ifa
);
787 int attr_len
= IFA_PAYLOAD(&ip_info
->nlmsg
.nlmsghdr
);
790 if (ip_info
->ifa
.ifa_family
!= family
)
793 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
794 sizeof(struct in6_addr
);
796 /* Loop over the rtattr's in this message */
797 while(RTA_OK(rta
, attr_len
)) {
798 /* Found a local address for the requested interface,
800 if (rta
->rta_type
== IFA_LOCAL
|| rta
->rta_type
== IFA_ADDRESS
) {
801 /* Sanity check. The family check above should
802 * make sure the address length is correct, but
803 * check here just in case */
804 if (RTA_PAYLOAD(rta
) != addrlen
)
807 /* We might have found an IFA_ADDRESS before,
808 * which we now overwrite with an IFA_LOCAL. */
810 *res
= malloc(addrlen
);
815 memcpy(*res
, RTA_DATA(rta
), addrlen
);
817 if (rta
->rta_type
== IFA_LOCAL
)
820 rta
= RTA_NEXT(rta
, attr_len
);
825 static int ip_addr_get(int family
, int ifindex
, void **res
)
827 struct nl_handler nlh
;
828 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
829 struct ip_req
*ip_req
, *ip_info
;
830 struct nlmsghdr
*msg
;
832 int recv_len
= 0, answer_len
;
835 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
840 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
844 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
848 /* Save the answer buffer length, since it will be overwritten
849 * on the first receive (and we might need to receive more than
851 answer_len
= answer
->nlmsghdr
.nlmsg_len
;
853 ip_req
= (struct ip_req
*)nlmsg
;
854 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
855 NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
856 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ROOT
;
857 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_GETADDR
;
858 ip_req
->ifa
.ifa_family
= family
;
860 /* Send the request for addresses, which returns all addresses
861 * on all interfaces. */
862 err
= netlink_send(&nlh
, nlmsg
);
867 /* Restore the answer buffer length, it might have been
868 * overwritten by a previous receive. */
869 answer
->nlmsghdr
.nlmsg_len
= answer_len
;
871 /* Get the (next) batch of reply messages */
872 err
= netlink_rcv(&nlh
, answer
);
879 /* Satisfy the typing for the netlink macros */
880 msg
= &answer
->nlmsghdr
;
882 while (NLMSG_OK(msg
, recv_len
)) {
883 /* Stop reading if we see an error message */
884 if (msg
->nlmsg_type
== NLMSG_ERROR
) {
885 struct nlmsgerr
*errmsg
= (struct nlmsgerr
*)NLMSG_DATA(msg
);
890 /* Stop reading if we see a NLMSG_DONE message */
891 if (msg
->nlmsg_type
== NLMSG_DONE
) {
896 if (msg
->nlmsg_type
!= RTM_NEWADDR
) {
901 ip_info
= (struct ip_req
*)msg
;
902 if (ip_info
->ifa
.ifa_index
== ifindex
) {
903 if (ifa_get_local_ip(family
, ip_info
, res
) < 0) {
908 /* Found a result, stop searching */
913 /* Keep reading more data from the socket if the
914 * last message had the NLF_F_MULTI flag set */
915 readmore
= (msg
->nlmsg_flags
& NLM_F_MULTI
);
917 /* Look at the next message received in this buffer */
918 msg
= NLMSG_NEXT(msg
, recv_len
);
922 /* If we end up here, we didn't find any result, so signal an
933 int lxc_ipv6_addr_get(int ifindex
, struct in6_addr
**res
)
935 return ip_addr_get(AF_INET6
, ifindex
, (void**)res
);
938 int lxc_ipv4_addr_get(int ifindex
, struct in_addr
** res
)
940 return ip_addr_get(AF_INET
, ifindex
, (void**)res
);
943 static int ip_gateway_add(int family
, int ifindex
, void *gw
)
945 struct nl_handler nlh
;
946 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
947 struct rt_req
*rt_req
;
951 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
952 sizeof(struct in6_addr
);
954 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
959 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
963 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
967 rt_req
= (struct rt_req
*)nlmsg
;
968 rt_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
969 NLMSG_LENGTH(sizeof(struct rtmsg
));
970 rt_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
971 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
972 rt_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWROUTE
;
973 rt_req
->rt
.rtm_family
= family
;
974 rt_req
->rt
.rtm_table
= RT_TABLE_MAIN
;
975 rt_req
->rt
.rtm_scope
= RT_SCOPE_UNIVERSE
;
976 rt_req
->rt
.rtm_protocol
= RTPROT_BOOT
;
977 rt_req
->rt
.rtm_type
= RTN_UNICAST
;
978 /* "default" destination */
979 rt_req
->rt
.rtm_dst_len
= 0;
982 if (nla_put_buffer(nlmsg
, RTA_GATEWAY
, gw
, addrlen
))
985 /* Adding the interface index enables the use of link-local
986 * addresses for the gateway */
987 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
990 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
998 int lxc_ipv4_gateway_add(int ifindex
, struct in_addr
*gw
)
1000 return ip_gateway_add(AF_INET
, ifindex
, gw
);
1003 int lxc_ipv6_gateway_add(int ifindex
, struct in6_addr
*gw
)
1005 return ip_gateway_add(AF_INET6
, ifindex
, gw
);
1008 static int ip_route_dest_add(int family
, int ifindex
, void *dest
)
1010 struct nl_handler nlh
;
1011 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
1012 struct rt_req
*rt_req
;
1016 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
1017 sizeof(struct in6_addr
);
1019 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
1024 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1028 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
1032 rt_req
= (struct rt_req
*)nlmsg
;
1033 rt_req
->nlmsg
.nlmsghdr
.nlmsg_len
=
1034 NLMSG_LENGTH(sizeof(struct rtmsg
));
1035 rt_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
1036 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
1037 rt_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWROUTE
;
1038 rt_req
->rt
.rtm_family
= family
;
1039 rt_req
->rt
.rtm_table
= RT_TABLE_MAIN
;
1040 rt_req
->rt
.rtm_scope
= RT_SCOPE_LINK
;
1041 rt_req
->rt
.rtm_protocol
= RTPROT_BOOT
;
1042 rt_req
->rt
.rtm_type
= RTN_UNICAST
;
1043 rt_req
->rt
.rtm_dst_len
= addrlen
*8;
1046 if (nla_put_buffer(nlmsg
, RTA_DST
, dest
, addrlen
))
1048 if (nla_put_u32(nlmsg
, RTA_OIF
, ifindex
))
1050 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
1052 netlink_close(&nlh
);
1058 int lxc_ipv4_dest_add(int ifindex
, struct in_addr
*dest
)
1060 return ip_route_dest_add(AF_INET
, ifindex
, dest
);
1063 int lxc_ipv6_dest_add(int ifindex
, struct in6_addr
*dest
)
1065 return ip_route_dest_add(AF_INET6
, ifindex
, dest
);
1069 * There is a lxc_bridge_attach, but no need of a bridge detach
1070 * as automatically done by kernel when a netdev is deleted.
1072 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
1077 if (strlen(ifname
) >= IFNAMSIZ
)
1080 index
= if_nametoindex(ifname
);
1085 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
1090 strncpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
-1);
1091 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
1092 ifr
.ifr_ifindex
= index
;
1093 err
= ioctl(fd
, SIOCBRADDIF
, &ifr
);
1103 static char* lxc_network_types
[LXC_NET_MAXCONFTYPE
+ 1] = {
1104 [LXC_NET_VETH
] = "veth",
1105 [LXC_NET_MACVLAN
] = "macvlan",
1106 [LXC_NET_VLAN
] = "vlan",
1107 [LXC_NET_PHYS
] = "phys",
1108 [LXC_NET_EMPTY
] = "empty",
1111 const char *lxc_net_type_to_str(int type
)
1113 if (type
< 0 || type
> LXC_NET_MAXCONFTYPE
)
1115 return lxc_network_types
[type
];
1118 static char padchar
[] =
1119 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1121 char *lxc_mkifname(char *template)
1127 struct ifaddrs
*ifaddr
, *ifa
;
1130 /* Get all the network interfaces */
1131 getifaddrs(&ifaddr
);
1133 /* Initialize the random number generator */
1135 urandom
= fopen ("/dev/urandom", "r");
1137 if (urandom
!= NULL
) {
1138 if (fread (&seed
, sizeof(seed
), 1, urandom
) <= 0)
1151 /* Generate random names until we find one that doesn't exist */
1154 name
= strdup(template);
1159 for (i
= 0; i
< strlen(name
); i
++) {
1160 if (name
[i
] == 'X') {
1162 name
[i
] = padchar
[rand_r(&seed
) % (strlen(padchar
) - 1)];
1164 name
[i
] = padchar
[rand() % (strlen(padchar
) - 1)];
1169 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1170 if (strcmp(ifa
->ifa_name
, name
) == 0) {
1182 freeifaddrs(ifaddr
);
1186 int setup_private_host_hw_addr(char *veth1
)
1193 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1198 snprintf((char *)ifr
.ifr_name
, IFNAMSIZ
, "%s", veth1
);
1199 err
= ioctl(sockfd
, SIOCGIFHWADDR
, &ifr
);
1207 ifr
.ifr_hwaddr
.sa_data
[0] = 0xfe;
1208 err
= ioctl(sockfd
, SIOCSIFHWADDR
, &ifr
);