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
66
#ifndef IFLA_INFO_DATA
67
# define IFLA_INFO_DATA 2
70
#ifndef VETH_INFO_PEER
71
# define VETH_INFO_PEER 1
76
struct ifinfomsg ifinfomsg;
84
int lxc_device_move(const char *name, pid_t pid)
86
struct nl_handler nlh;
87
struct nlmsg *nlmsg = NULL;
88
struct link_req *link_req;
89
int index, len, err = -1;
91
if (netlink_open(&nlh, NETLINK_ROUTE))
95
if (len == 1 || len > IFNAMSIZ)
98
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
102
index = if_nametoindex(name);
106
link_req = (struct link_req *)nlmsg;
107
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
108
link_req->ifinfomsg.ifi_index = index;
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 (nla_put_string(nlmsg, IFLA_IFNAME, name))
119
if (netlink_transaction(&nlh, nlmsg, nlmsg))
129
extern int lxc_device_delete(const char *name)
131
struct nl_handler nlh;
132
struct nlmsg *nlmsg = NULL, *answer = NULL;
133
struct link_req *link_req;
134
int index, len, err = -1;
136
if (netlink_open(&nlh, NETLINK_ROUTE))
140
if (len == 1 || len > IFNAMSIZ)
143
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
147
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
if (netlink_transaction(&nlh, nlmsg, answer))
176
static int device_set_flag(const char *name, int flag)
178
struct nl_handler nlh;
179
struct nlmsg *nlmsg = NULL, *answer = NULL;
180
struct link_req *link_req;
181
int index, len, err = -1;
183
if (netlink_open(&nlh, NETLINK_ROUTE))
187
if (len == 1 || len > IFNAMSIZ)
190
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
194
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
198
index = if_nametoindex(name);
202
link_req = (struct link_req *)nlmsg;
203
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
204
link_req->ifinfomsg.ifi_index = index;
205
link_req->ifinfomsg.ifi_change |= IFF_UP;
206
link_req->ifinfomsg.ifi_flags |= flag;
207
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
208
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
209
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
211
err = netlink_transaction(&nlh, nlmsg, answer);
223
extern int lxc_device_set_mtu(const char *name, int mtu)
225
struct nl_handler nlh;
226
struct nlmsg *nlmsg = NULL, *answer = NULL;
227
struct link_req *link_req;
228
int index, len, err = -1;
230
if (netlink_open(&nlh, NETLINK_ROUTE))
234
if (len == 1 || len > IFNAMSIZ)
237
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
241
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
245
index = if_nametoindex(name);
249
link_req = (struct link_req *)nlmsg;
250
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
251
link_req->ifinfomsg.ifi_index = index;
252
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
253
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
254
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
256
if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
259
err = netlink_transaction(&nlh, nlmsg, answer);
271
int lxc_device_up(const char *name)
273
return device_set_flag(name, IFF_UP);
276
int lxc_device_down(const char *name)
278
return device_set_flag(name, 0);
281
int lxc_device_rename(const char *oldname, const char *newname)
283
struct nl_handler nlh;
284
struct nlmsg *nlmsg = NULL, *answer = NULL;
285
struct link_req *link_req;
286
int index, len, err = -1;
288
if (netlink_open(&nlh, NETLINK_ROUTE))
291
len = strlen(oldname);
292
if (len == 1 || len > IFNAMSIZ)
295
len = strlen(newname);
296
if (len == 1 || len > IFNAMSIZ)
299
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
303
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
307
index = if_nametoindex(oldname);
311
link_req = (struct link_req *)nlmsg;
312
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
313
link_req->ifinfomsg.ifi_index = index;
314
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
315
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
316
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
318
if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
321
if (netlink_transaction(&nlh, nlmsg, answer))
332
int lxc_veth_create(const char *name1, const char *name2)
334
struct nl_handler nlh;
335
struct nlmsg *nlmsg = NULL, *answer = NULL;
336
struct link_req *link_req;
337
struct rtattr *nest1, *nest2, *nest3;
340
if (netlink_open(&nlh, NETLINK_ROUTE))
344
if (len == 1 || len > IFNAMSIZ)
348
if (len == 1 || len > IFNAMSIZ)
351
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
355
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
359
link_req = (struct link_req *)nlmsg;
360
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
361
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
362
nlmsg->nlmsghdr.nlmsg_flags =
363
NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
364
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
366
nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
370
if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
373
nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
377
nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
381
nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg);
383
if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
386
nla_end_nested(nlmsg, nest3);
388
nla_end_nested(nlmsg, nest2);
390
nla_end_nested(nlmsg, nest1);
392
if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
395
if (netlink_transaction(&nlh, nlmsg, answer))
406
int lxc_macvlan_create(const char *master, const char *name)
408
struct nl_handler nlh;
409
struct nlmsg *nlmsg = NULL, *answer = NULL;
410
struct link_req *link_req;
412
int index, len, err = -1;
414
if (netlink_open(&nlh, NETLINK_ROUTE))
417
len = strlen(master);
418
if (len == 1 || len > IFNAMSIZ)
422
if (len == 1 || len > IFNAMSIZ)
425
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
429
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
433
index = if_nametoindex(master);
437
link_req = (struct link_req *)nlmsg;
438
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
439
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
440
nlmsg->nlmsghdr.nlmsg_flags =
441
NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
442
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
444
nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
448
if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
451
nla_end_nested(nlmsg, nest);
453
if (nla_put_u32(nlmsg, IFLA_LINK, index))
456
if (nla_put_string(nlmsg, IFLA_IFNAME, name))
459
if (netlink_transaction(&nlh, nlmsg, answer))
470
static int proc_sys_net_write(const char *path, const char *value)
474
fd = open(path, O_WRONLY);
478
if (write(fd, value, strlen(value)) < 0)
485
static int ip_forward_set(const char *ifname, int family, int flag)
487
char path[MAXPATHLEN];
489
if (family != AF_INET && family != AF_INET6)
492
snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
493
family == AF_INET?"ipv4":"ipv6" , ifname);
495
return proc_sys_net_write(path, flag?"1":"0");
498
int lxc_ip_forward_on(const char *ifname, int family)
500
return ip_forward_set(ifname, family, 1);
503
int lxc_ip_forward_off(const char *ifname, int family)
505
return ip_forward_set(ifname, family, 0);
508
static int neigh_proxy_set(const char *ifname, int family, int flag)
510
char path[MAXPATHLEN];
512
if (family != AF_INET && family != AF_INET6)
515
sprintf(path, "/proc/sys/net/%s/conf/%s/%s",
516
family == AF_INET?"ipv4":"ipv6" , ifname,
517
family == AF_INET?"proxy_arp":"proxy_ndp");
519
return proc_sys_net_write(path, flag?"1":"0");
522
int lxc_neigh_proxy_on(const char *name, int family)
524
return neigh_proxy_set(name, family, 1);
527
int lxc_neigh_proxy_off(const char *name, int family)
529
return neigh_proxy_set(name, family, 0);
532
int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
539
sockaddr->sa_family = ARPHRD_ETHER;
540
data = (unsigned char *)sockaddr->sa_data;
542
while ((*macaddr != '\0') && (i < ETH_ALEN)) {
547
else if (c >= 'a' && c <= 'f')
549
else if (c >= 'A' && c <= 'F')
558
else if (c >= 'a' && c <= 'f')
560
else if (c >= 'A' && c <= 'F')
562
else if (c == ':' || c == 0)
569
*data++ = (unsigned char) (val & 0377);
579
int lxc_ip_addr_add(const char *ifname, const char *addr,
580
int prefix, const char *bcast)
582
struct nl_handler nlh;
583
struct in_addr in_addr;
584
/* struct in_addr in_bcast; */
585
struct nlmsg *nlmsg = NULL, *answer = NULL;
586
struct ip_req *ip_req;
587
int ifindex, err = -1;
589
if (netlink_open(&nlh, NETLINK_ROUTE))
592
if (inet_pton(AF_INET, addr, (void *)&in_addr) < 0)
595
/* if (inet_pton(AF_INET, bcast, (void *)&in_bcast) < 0) */
598
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
602
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
606
ifindex = if_nametoindex(ifname);
610
ip_req = (struct ip_req *)nlmsg;
611
ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
612
ip_req->nlmsg.nlmsghdr.nlmsg_flags =
613
NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
614
ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
615
ip_req->ifa.ifa_prefixlen = prefix;
616
ip_req->ifa.ifa_index = ifindex;
617
ip_req->ifa.ifa_family = AF_INET;
618
ip_req->ifa.ifa_scope = 0;
620
if (nla_put_buffer(nlmsg, IFA_LOCAL, &in_addr, sizeof(in_addr)))
623
if (nla_put_buffer(nlmsg, IFA_ADDRESS, &in_addr, sizeof(in_addr)))
626
/* if (in_bcast.s_addr != INADDR_ANY) */
627
/* if (nla_put_buffer(nlmsg, IFA_BROADCAST, &in_bcast, */
628
/* sizeof(in_bcast))) */
631
if (netlink_transaction(&nlh, nlmsg, answer))
642
int lxc_ip6_addr_add(const char *ifname, const char *addr,
643
int prefix, const char *bcast)
645
struct nl_handler nlh;
646
struct in6_addr in6_addr;
647
/* struct in6_addr in6_bcast; */
648
struct nlmsg *nlmsg = NULL, *answer = NULL;
649
struct ip_req *ip_req;
650
int ifindex, err = -1;
652
if (netlink_open(&nlh, NETLINK_ROUTE))
655
if (inet_pton(AF_INET6, addr, (void *)&in6_addr) < 0)
659
/* if (inet_pton(AF_INET6, bcast, (void *)&in6_bcast) < 0) */
662
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
666
answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
670
ifindex = if_nametoindex(ifname);
674
ip_req = (struct ip_req *)nlmsg;
675
ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
676
ip_req->nlmsg.nlmsghdr.nlmsg_flags =
677
NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
678
ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
679
ip_req->ifa.ifa_prefixlen = prefix;
680
ip_req->ifa.ifa_index = ifindex;
681
ip_req->ifa.ifa_family = AF_INET6;
682
ip_req->ifa.ifa_scope = 0;
684
if (nla_put_buffer(nlmsg, IFA_LOCAL, &in6_addr, sizeof(in6_addr)))
687
if (nla_put_buffer(nlmsg, IFA_ADDRESS, &in6_addr, sizeof(in6_addr)))
690
/* if (in6_bcast.s6_addr != in6addr_any.s6_addr) */
691
/* if (nla_put_buffer(nlmsg, IFA_BROADCAST, &in6_bcast, */
692
/* sizeof(in6_bcast))) */
695
if (netlink_transaction(&nlh, nlmsg, answer))
706
static int bridge_add_del_interface(const char *bridge,
707
const char *ifname, int detach)
712
if (strlen(ifname) > IFNAMSIZ)
715
index = if_nametoindex(ifname);
719
fd = socket(AF_INET, SOCK_STREAM, 0);
723
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
724
ifr.ifr_ifindex = index;
725
err = ioctl(fd, detach?SIOCBRDELIF:SIOCBRADDIF, &ifr);
731
int lxc_bridge_attach(const char *bridge, const char *ifname)
733
return bridge_add_del_interface(bridge, ifname, 0);
736
int lxc_bridge_detach(const char *bridge, const char *ifname)
738
return bridge_add_del_interface(bridge, ifname, 1);