]>
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 <dlezcano at fr.ibm.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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>
51 # define IFLA_LINKMODE 17
55 # define IFLA_LINKINFO 18
58 #ifndef IFLA_NET_NS_PID
59 # define IFLA_NET_NS_PID 19
62 #ifndef IFLA_INFO_KIND
63 # define IFLA_INFO_KIND 1
67 # define IFLA_VLAN_ID 1
70 #ifndef IFLA_INFO_DATA
71 # define IFLA_INFO_DATA 2
74 #ifndef VETH_INFO_PEER
75 # define VETH_INFO_PEER 1
78 #ifndef IFLA_MACVLAN_MODE
79 # define IFLA_MACVLAN_MODE 1
84 struct ifinfomsg ifinfomsg
;
92 int lxc_device_move(int ifindex
, pid_t pid
)
94 struct nl_handler nlh
;
95 struct nlmsg
*nlmsg
= NULL
;
96 struct link_req
*link_req
;
99 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
104 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
108 link_req
= (struct link_req
*)nlmsg
;
109 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
110 link_req
->ifinfomsg
.ifi_index
= ifindex
;
111 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
112 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
113 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
115 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
118 err
= netlink_transaction(&nlh
, nlmsg
, nlmsg
);
125 int lxc_device_delete(const char *name
)
127 struct nl_handler nlh
;
128 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
129 struct link_req
*link_req
;
132 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
138 if (len
== 1 || len
> IFNAMSIZ
)
142 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
146 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
151 index
= if_nametoindex(name
);
155 link_req
= (struct link_req
*)nlmsg
;
156 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
157 link_req
->ifinfomsg
.ifi_index
= index
;
158 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
159 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
160 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_DELLINK
;
162 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
165 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
173 int lxc_device_delete_index(int ifindex
)
175 struct nl_handler nlh
;
176 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
177 struct link_req
*link_req
;
180 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
185 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
189 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
193 link_req
= (struct link_req
*)nlmsg
;
194 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
195 link_req
->ifinfomsg
.ifi_index
= ifindex
;
196 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
197 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
198 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_DELLINK
;
200 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
208 static int device_set_flag(const char *name
, int flag
)
210 struct nl_handler nlh
;
211 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
212 struct link_req
*link_req
;
215 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
221 if (len
== 1 || len
> IFNAMSIZ
)
225 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
229 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
234 index
= if_nametoindex(name
);
238 link_req
= (struct link_req
*)nlmsg
;
239 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
240 link_req
->ifinfomsg
.ifi_index
= index
;
241 link_req
->ifinfomsg
.ifi_change
|= IFF_UP
;
242 link_req
->ifinfomsg
.ifi_flags
|= flag
;
243 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
244 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
245 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
247 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
255 int lxc_device_set_mtu(const char *name
, int mtu
)
257 struct nl_handler nlh
;
258 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
259 struct link_req
*link_req
;
262 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
268 if (len
== 1 || len
> IFNAMSIZ
)
272 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
276 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
281 index
= if_nametoindex(name
);
285 link_req
= (struct link_req
*)nlmsg
;
286 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
287 link_req
->ifinfomsg
.ifi_index
= index
;
288 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
289 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
290 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
292 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
295 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
303 int lxc_device_up(const char *name
)
305 return device_set_flag(name
, IFF_UP
);
308 int lxc_device_down(const char *name
)
310 return device_set_flag(name
, 0);
313 int lxc_device_rename(const char *oldname
, const char *newname
)
315 struct nl_handler nlh
;
316 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
317 struct link_req
*link_req
;
320 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
325 len
= strlen(oldname
);
326 if (len
== 1 || len
> IFNAMSIZ
)
329 len
= strlen(newname
);
330 if (len
== 1 || len
> IFNAMSIZ
)
334 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
338 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
343 index
= if_nametoindex(oldname
);
347 link_req
= (struct link_req
*)nlmsg
;
348 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
349 link_req
->ifinfomsg
.ifi_index
= index
;
350 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
351 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
352 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
354 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
357 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
365 int lxc_veth_create(const char *name1
, const char *name2
)
367 struct nl_handler nlh
;
368 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
369 struct link_req
*link_req
;
370 struct rtattr
*nest1
, *nest2
, *nest3
;
373 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
379 if (len
== 1 || len
> IFNAMSIZ
)
383 if (len
== 1 || len
> IFNAMSIZ
)
387 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
391 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
395 link_req
= (struct link_req
*)nlmsg
;
396 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
397 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
398 nlmsg
->nlmsghdr
.nlmsg_flags
=
399 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
400 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
403 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
407 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
410 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
414 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
418 nlmsg
->nlmsghdr
.nlmsg_len
+= sizeof(struct ifinfomsg
);
420 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
423 nla_end_nested(nlmsg
, nest3
);
425 nla_end_nested(nlmsg
, nest2
);
427 nla_end_nested(nlmsg
, nest1
);
429 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
432 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
440 /* XXX: merge with lxc_macvlan_create */
441 int lxc_vlan_create(const char *master
, const char *name
, ushort vlanid
)
443 struct nl_handler nlh
;
444 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
445 struct link_req
*link_req
;
446 struct rtattr
*nest
, *nest2
;
447 int lindex
, len
, err
;
449 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
454 len
= strlen(master
);
455 if (len
== 1 || len
> IFNAMSIZ
)
459 if (len
== 1 || len
> IFNAMSIZ
)
463 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
467 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
472 lindex
= if_nametoindex(master
);
476 link_req
= (struct link_req
*)nlmsg
;
477 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
478 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
479 nlmsg
->nlmsghdr
.nlmsg_flags
=
480 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
481 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
483 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
487 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
490 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
494 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
497 nla_end_nested(nlmsg
, nest2
);
499 nla_end_nested(nlmsg
, nest
);
501 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
504 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
507 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
517 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
519 struct nl_handler nlh
;
520 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
521 struct link_req
*link_req
;
522 struct rtattr
*nest
, *nest2
;
525 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
530 len
= strlen(master
);
531 if (len
== 1 || len
> IFNAMSIZ
)
535 if (len
== 1 || len
> IFNAMSIZ
)
539 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
543 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
548 index
= if_nametoindex(master
);
552 link_req
= (struct link_req
*)nlmsg
;
553 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
554 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
555 nlmsg
->nlmsghdr
.nlmsg_flags
=
556 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
557 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
559 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
563 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
567 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
571 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
574 nla_end_nested(nlmsg
, nest2
);
577 nla_end_nested(nlmsg
, nest
);
579 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
582 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
585 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
593 static int proc_sys_net_write(const char *path
, const char *value
)
597 fd
= open(path
, O_WRONLY
);
601 if (write(fd
, value
, strlen(value
)) < 0)
608 static int ip_forward_set(const char *ifname
, int family
, int flag
)
610 char path
[MAXPATHLEN
];
612 if (family
!= AF_INET
&& family
!= AF_INET6
)
615 snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/forwarding",
616 family
== AF_INET
?"ipv4":"ipv6" , ifname
);
618 return proc_sys_net_write(path
, flag
?"1":"0");
621 int lxc_ip_forward_on(const char *ifname
, int family
)
623 return ip_forward_set(ifname
, family
, 1);
626 int lxc_ip_forward_off(const char *ifname
, int family
)
628 return ip_forward_set(ifname
, family
, 0);
631 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
633 char path
[MAXPATHLEN
];
635 if (family
!= AF_INET
&& family
!= AF_INET6
)
638 sprintf(path
, "/proc/sys/net/%s/conf/%s/%s",
639 family
== AF_INET
?"ipv4":"ipv6" , ifname
,
640 family
== AF_INET
?"proxy_arp":"proxy_ndp");
642 return proc_sys_net_write(path
, flag
?"1":"0");
645 int lxc_neigh_proxy_on(const char *name
, int family
)
647 return neigh_proxy_set(name
, family
, 1);
650 int lxc_neigh_proxy_off(const char *name
, int family
)
652 return neigh_proxy_set(name
, family
, 0);
655 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
662 sockaddr
->sa_family
= ARPHRD_ETHER
;
663 data
= (unsigned char *)sockaddr
->sa_data
;
665 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
670 else if (c
>= 'a' && c
<= 'f')
672 else if (c
>= 'A' && c
<= 'F')
681 else if (c
>= 'a' && c
<= 'f')
683 else if (c
>= 'A' && c
<= 'F')
685 else if (c
== ':' || c
== 0)
692 *data
++ = (unsigned char) (val
& 0377);
702 int lxc_ip_addr_add(int family
, int ifindex
, void *addr
, int prefix
)
704 struct nl_handler nlh
;
705 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
706 struct ip_req
*ip_req
;
710 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
711 sizeof(struct in6_addr
);
713 err
= netlink_open(&nlh
, NETLINK_ROUTE
);
718 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
722 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
726 ip_req
= (struct ip_req
*)nlmsg
;
727 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
728 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
729 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
730 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWADDR
;
731 ip_req
->ifa
.ifa_prefixlen
= prefix
;
732 ip_req
->ifa
.ifa_index
= ifindex
;
733 ip_req
->ifa
.ifa_family
= family
;
734 ip_req
->ifa
.ifa_scope
= 0;
737 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
740 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
743 /* if (in_bcast.s_addr != INADDR_ANY) */
744 /* if (nla_put_buffer(nlmsg, IFA_BROADCAST, &in_bcast, */
745 /* sizeof(in_bcast))) */
748 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
756 static int bridge_add_del_interface(const char *bridge
,
757 const char *ifname
, int detach
)
762 if (strlen(ifname
) > IFNAMSIZ
)
765 index
= if_nametoindex(ifname
);
769 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
773 strncpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
);
774 ifr
.ifr_ifindex
= index
;
775 err
= ioctl(fd
, detach
?SIOCBRDELIF
:SIOCBRADDIF
, &ifr
);
783 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
785 return bridge_add_del_interface(bridge
, ifname
, 0);
788 int lxc_bridge_detach(const char *bridge
, const char *ifname
)
790 return bridge_add_del_interface(bridge
, ifname
, 1);