]>
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 if (netlink_open(&nlh
, NETLINK_ROUTE
))
102 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
106 link_req
= (struct link_req
*)nlmsg
;
107 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
108 link_req
->ifinfomsg
.ifi_index
= ifindex
;
109 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
110 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
111 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
113 if (nla_put_u32(nlmsg
, IFLA_NET_NS_PID
, pid
))
116 if (netlink_transaction(&nlh
, nlmsg
, nlmsg
))
126 extern int lxc_device_delete(const char *name
)
128 struct nl_handler nlh
;
129 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
130 struct link_req
*link_req
;
131 int index
, len
, err
= -1;
133 if (netlink_open(&nlh
, NETLINK_ROUTE
))
137 if (len
== 1 || len
> IFNAMSIZ
)
140 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
144 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
148 index
= if_nametoindex(name
);
152 link_req
= (struct link_req
*)nlmsg
;
153 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
154 link_req
->ifinfomsg
.ifi_index
= index
;
155 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
156 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
157 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_DELLINK
;
159 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
162 if (netlink_transaction(&nlh
, nlmsg
, answer
))
173 static int device_set_flag(const char *name
, int flag
)
175 struct nl_handler nlh
;
176 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
177 struct link_req
*link_req
;
178 int index
, len
, err
= -1;
180 if (netlink_open(&nlh
, NETLINK_ROUTE
))
184 if (len
== 1 || len
> IFNAMSIZ
)
187 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
191 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
195 index
= if_nametoindex(name
);
199 link_req
= (struct link_req
*)nlmsg
;
200 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
201 link_req
->ifinfomsg
.ifi_index
= index
;
202 link_req
->ifinfomsg
.ifi_change
|= IFF_UP
;
203 link_req
->ifinfomsg
.ifi_flags
|= flag
;
204 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
205 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
206 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
208 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
220 extern int lxc_device_set_mtu(const char *name
, int mtu
)
222 struct nl_handler nlh
;
223 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
224 struct link_req
*link_req
;
225 int index
, len
, err
= -1;
227 if (netlink_open(&nlh
, NETLINK_ROUTE
))
231 if (len
== 1 || len
> IFNAMSIZ
)
234 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
238 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
242 index
= if_nametoindex(name
);
246 link_req
= (struct link_req
*)nlmsg
;
247 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
248 link_req
->ifinfomsg
.ifi_index
= index
;
249 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
250 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
251 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
253 if (nla_put_u32(nlmsg
, IFLA_MTU
, mtu
))
256 err
= netlink_transaction(&nlh
, nlmsg
, answer
);
268 int lxc_device_up(const char *name
)
270 return device_set_flag(name
, IFF_UP
);
273 int lxc_device_down(const char *name
)
275 return device_set_flag(name
, 0);
278 int lxc_device_rename(const char *oldname
, const char *newname
)
280 struct nl_handler nlh
;
281 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
282 struct link_req
*link_req
;
283 int index
, len
, err
= -1;
285 if (netlink_open(&nlh
, NETLINK_ROUTE
))
288 len
= strlen(oldname
);
289 if (len
== 1 || len
> IFNAMSIZ
)
292 len
= strlen(newname
);
293 if (len
== 1 || len
> IFNAMSIZ
)
296 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
300 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
304 index
= if_nametoindex(oldname
);
308 link_req
= (struct link_req
*)nlmsg
;
309 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
310 link_req
->ifinfomsg
.ifi_index
= index
;
311 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
312 nlmsg
->nlmsghdr
.nlmsg_flags
= NLM_F_ACK
|NLM_F_REQUEST
;
313 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
315 if (nla_put_string(nlmsg
, IFLA_IFNAME
, newname
))
318 if (netlink_transaction(&nlh
, nlmsg
, answer
))
329 int lxc_veth_create(const char *name1
, const char *name2
)
331 struct nl_handler nlh
;
332 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
333 struct link_req
*link_req
;
334 struct rtattr
*nest1
, *nest2
, *nest3
;
337 if (netlink_open(&nlh
, NETLINK_ROUTE
))
341 if (len
== 1 || len
> IFNAMSIZ
)
345 if (len
== 1 || len
> IFNAMSIZ
)
348 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
352 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
356 link_req
= (struct link_req
*)nlmsg
;
357 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
358 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
359 nlmsg
->nlmsghdr
.nlmsg_flags
=
360 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
361 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
363 nest1
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
367 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "veth"))
370 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
374 nest3
= nla_begin_nested(nlmsg
, VETH_INFO_PEER
);
378 nlmsg
->nlmsghdr
.nlmsg_len
+= sizeof(struct ifinfomsg
);
380 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name2
))
383 nla_end_nested(nlmsg
, nest3
);
385 nla_end_nested(nlmsg
, nest2
);
387 nla_end_nested(nlmsg
, nest1
);
389 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name1
))
392 if (netlink_transaction(&nlh
, nlmsg
, answer
))
403 /* XXX: merge with lxc_macvlan_create */
404 int lxc_vlan_create(const char *master
, const char *name
, ushort vlanid
)
406 struct nl_handler nlh
;
407 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
408 struct link_req
*link_req
;
409 struct rtattr
*nest
, *nest2
;
410 int lindex
, len
, err
= -1;
412 if (netlink_open(&nlh
, NETLINK_ROUTE
))
415 len
= strlen(master
);
416 if (len
== 1 || len
> IFNAMSIZ
)
420 if (len
== 1 || len
> IFNAMSIZ
)
423 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
427 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
431 lindex
= if_nametoindex(master
);
435 link_req
= (struct link_req
*)nlmsg
;
436 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
437 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
438 nlmsg
->nlmsghdr
.nlmsg_flags
=
439 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
440 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
442 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
446 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "vlan"))
449 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
453 if (nla_put_u16(nlmsg
, IFLA_VLAN_ID
, vlanid
))
456 nla_end_nested(nlmsg
, nest2
);
458 nla_end_nested(nlmsg
, nest
);
460 if (nla_put_u32(nlmsg
, IFLA_LINK
, lindex
))
463 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
466 if (netlink_transaction(&nlh
, nlmsg
, answer
))
479 int lxc_macvlan_create(const char *master
, const char *name
, int mode
)
481 struct nl_handler nlh
;
482 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
483 struct link_req
*link_req
;
484 struct rtattr
*nest
, *nest2
;
485 int index
, len
, err
= -1;
487 if (netlink_open(&nlh
, NETLINK_ROUTE
))
490 len
= strlen(master
);
491 if (len
== 1 || len
> IFNAMSIZ
)
495 if (len
== 1 || len
> IFNAMSIZ
)
498 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
502 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
506 index
= if_nametoindex(master
);
510 link_req
= (struct link_req
*)nlmsg
;
511 link_req
->ifinfomsg
.ifi_family
= AF_UNSPEC
;
512 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
513 nlmsg
->nlmsghdr
.nlmsg_flags
=
514 NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
|NLM_F_ACK
;
515 nlmsg
->nlmsghdr
.nlmsg_type
= RTM_NEWLINK
;
517 nest
= nla_begin_nested(nlmsg
, IFLA_LINKINFO
);
521 if (nla_put_string(nlmsg
, IFLA_INFO_KIND
, "macvlan"))
525 nest2
= nla_begin_nested(nlmsg
, IFLA_INFO_DATA
);
529 if (nla_put_u32(nlmsg
, IFLA_MACVLAN_MODE
, mode
))
532 nla_end_nested(nlmsg
, nest2
);
535 nla_end_nested(nlmsg
, nest
);
537 if (nla_put_u32(nlmsg
, IFLA_LINK
, index
))
540 if (nla_put_string(nlmsg
, IFLA_IFNAME
, name
))
543 if (netlink_transaction(&nlh
, nlmsg
, answer
))
554 static int proc_sys_net_write(const char *path
, const char *value
)
558 fd
= open(path
, O_WRONLY
);
562 if (write(fd
, value
, strlen(value
)) < 0)
569 static int ip_forward_set(const char *ifname
, int family
, int flag
)
571 char path
[MAXPATHLEN
];
573 if (family
!= AF_INET
&& family
!= AF_INET6
)
576 snprintf(path
, MAXPATHLEN
, "/proc/sys/net/%s/conf/%s/forwarding",
577 family
== AF_INET
?"ipv4":"ipv6" , ifname
);
579 return proc_sys_net_write(path
, flag
?"1":"0");
582 int lxc_ip_forward_on(const char *ifname
, int family
)
584 return ip_forward_set(ifname
, family
, 1);
587 int lxc_ip_forward_off(const char *ifname
, int family
)
589 return ip_forward_set(ifname
, family
, 0);
592 static int neigh_proxy_set(const char *ifname
, int family
, int flag
)
594 char path
[MAXPATHLEN
];
596 if (family
!= AF_INET
&& family
!= AF_INET6
)
599 sprintf(path
, "/proc/sys/net/%s/conf/%s/%s",
600 family
== AF_INET
?"ipv4":"ipv6" , ifname
,
601 family
== AF_INET
?"proxy_arp":"proxy_ndp");
603 return proc_sys_net_write(path
, flag
?"1":"0");
606 int lxc_neigh_proxy_on(const char *name
, int family
)
608 return neigh_proxy_set(name
, family
, 1);
611 int lxc_neigh_proxy_off(const char *name
, int family
)
613 return neigh_proxy_set(name
, family
, 0);
616 int lxc_convert_mac(char *macaddr
, struct sockaddr
*sockaddr
)
623 sockaddr
->sa_family
= ARPHRD_ETHER
;
624 data
= (unsigned char *)sockaddr
->sa_data
;
626 while ((*macaddr
!= '\0') && (i
< ETH_ALEN
)) {
631 else if (c
>= 'a' && c
<= 'f')
633 else if (c
>= 'A' && c
<= 'F')
642 else if (c
>= 'a' && c
<= 'f')
644 else if (c
>= 'A' && c
<= 'F')
646 else if (c
== ':' || c
== 0)
653 *data
++ = (unsigned char) (val
& 0377);
663 int lxc_ip_addr_add(int family
, int ifindex
, void *addr
, int prefix
)
665 struct nl_handler nlh
;
666 struct nlmsg
*nlmsg
= NULL
, *answer
= NULL
;
667 struct ip_req
*ip_req
;
671 addrlen
= family
== AF_INET
? sizeof(struct in_addr
) :
672 sizeof(struct in6_addr
);
674 if (netlink_open(&nlh
, NETLINK_ROUTE
))
677 nlmsg
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
681 answer
= nlmsg_alloc(NLMSG_GOOD_SIZE
);
685 ip_req
= (struct ip_req
*)nlmsg
;
686 ip_req
->nlmsg
.nlmsghdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
687 ip_req
->nlmsg
.nlmsghdr
.nlmsg_flags
=
688 NLM_F_ACK
|NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_EXCL
;
689 ip_req
->nlmsg
.nlmsghdr
.nlmsg_type
= RTM_NEWADDR
;
690 ip_req
->ifa
.ifa_prefixlen
= prefix
;
691 ip_req
->ifa
.ifa_index
= ifindex
;
692 ip_req
->ifa
.ifa_family
= family
;
693 ip_req
->ifa
.ifa_scope
= 0;
695 if (nla_put_buffer(nlmsg
, IFA_LOCAL
, addr
, addrlen
))
698 if (nla_put_buffer(nlmsg
, IFA_ADDRESS
, addr
, addrlen
))
701 /* if (in_bcast.s_addr != INADDR_ANY) */
702 /* if (nla_put_buffer(nlmsg, IFA_BROADCAST, &in_bcast, */
703 /* sizeof(in_bcast))) */
706 if (netlink_transaction(&nlh
, nlmsg
, answer
))
717 static int bridge_add_del_interface(const char *bridge
,
718 const char *ifname
, int detach
)
723 if (strlen(ifname
) > IFNAMSIZ
)
726 index
= if_nametoindex(ifname
);
730 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
734 strncpy(ifr
.ifr_name
, bridge
, IFNAMSIZ
);
735 ifr
.ifr_ifindex
= index
;
736 err
= ioctl(fd
, detach
?SIOCBRDELIF
:SIOCBRADDIF
, &ifr
);
742 int lxc_bridge_attach(const char *bridge
, const char *ifname
)
744 return bridge_add_del_interface(bridge
, ifname
, 0);
747 int lxc_bridge_detach(const char *bridge
, const char *ifname
)
749 return bridge_add_del_interface(bridge
, ifname
, 1);