]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
Make lxc-user-nic use mkifname
[mirror_lxc.git] / src / lxc / network.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
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.
13 *
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.
18 *
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
22 */
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #undef _GNU_SOURCe
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/socket.h>
36 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <arpa/inet.h>
39 #include <net/if.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>
47
48 #include "nl.h"
49 #include "network.h"
50 #include "conf.h"
51 #include "lxclock.h"
52
53 #if HAVE_IFADDRS_H
54 #include <ifaddrs.h>
55 #else
56 #include <../include/ifaddrs.h>
57 #endif
58
59 #ifndef IFLA_LINKMODE
60 # define IFLA_LINKMODE 17
61 #endif
62
63 #ifndef IFLA_LINKINFO
64 # define IFLA_LINKINFO 18
65 #endif
66
67 #ifndef IFLA_NET_NS_PID
68 # define IFLA_NET_NS_PID 19
69 #endif
70
71 #ifndef IFLA_INFO_KIND
72 # define IFLA_INFO_KIND 1
73 #endif
74
75 #ifndef IFLA_VLAN_ID
76 # define IFLA_VLAN_ID 1
77 #endif
78
79 #ifndef IFLA_INFO_DATA
80 # define IFLA_INFO_DATA 2
81 #endif
82
83 #ifndef VETH_INFO_PEER
84 # define VETH_INFO_PEER 1
85 #endif
86
87 #ifndef IFLA_MACVLAN_MODE
88 # define IFLA_MACVLAN_MODE 1
89 #endif
90
91 struct link_req {
92 struct nlmsg nlmsg;
93 struct ifinfomsg ifinfomsg;
94 };
95
96 struct ip_req {
97 struct nlmsg nlmsg;
98 struct ifaddrmsg ifa;
99 };
100
101 struct rt_req {
102 struct nlmsg nlmsg;
103 struct rtmsg rt;
104 };
105
106 int lxc_netdev_move_by_index(int ifindex, pid_t pid)
107 {
108 struct nl_handler nlh;
109 struct nlmsg *nlmsg = NULL;
110 struct link_req *link_req;
111 int err;
112
113 err = netlink_open(&nlh, NETLINK_ROUTE);
114 if (err)
115 return err;
116
117 err = -ENOMEM;
118 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
119 if (!nlmsg)
120 goto out;
121
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;
128
129 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
130 goto out;
131
132 err = netlink_transaction(&nlh, nlmsg, nlmsg);
133 out:
134 netlink_close(&nlh);
135 nlmsg_free(nlmsg);
136 return err;
137 }
138
139 int lxc_netdev_move_by_name(char *ifname, pid_t pid)
140 {
141 int index;
142
143 index = if_nametoindex(ifname);
144 if (!ifname)
145 return -EINVAL;
146
147 return lxc_netdev_move_by_index(index, pid);
148 }
149
150 int lxc_netdev_delete_by_index(int ifindex)
151 {
152 struct nl_handler nlh;
153 struct nlmsg *nlmsg = NULL, *answer = NULL;
154 struct link_req *link_req;
155 int err;
156
157 err = netlink_open(&nlh, NETLINK_ROUTE);
158 if (err)
159 return err;
160
161 err = -ENOMEM;
162 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
163 if (!nlmsg)
164 goto out;
165
166 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
167 if (!answer)
168 goto out;
169
170 link_req = (struct link_req *)nlmsg;
171 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
172 link_req->ifinfomsg.ifi_index = ifindex;
173 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
174 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
175 nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK;
176
177 err = netlink_transaction(&nlh, nlmsg, answer);
178 out:
179 netlink_close(&nlh);
180 nlmsg_free(answer);
181 nlmsg_free(nlmsg);
182 return err;
183 }
184
185 int lxc_netdev_delete_by_name(const char *name)
186 {
187 int index;
188
189 index = if_nametoindex(name);
190 if (!index)
191 return -EINVAL;
192
193 return lxc_netdev_delete_by_index(index);
194 }
195
196 int lxc_netdev_rename_by_index(int ifindex, const char *newname)
197 {
198 struct nl_handler nlh;
199 struct nlmsg *nlmsg = NULL, *answer = NULL;
200 struct link_req *link_req;
201 int len, err;
202
203 err = netlink_open(&nlh, NETLINK_ROUTE);
204 if (err)
205 return err;
206
207 len = strlen(newname);
208 if (len == 1 || len >= IFNAMSIZ)
209 goto out;
210
211 err = -ENOMEM;
212 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
213 if (!nlmsg)
214 goto out;
215
216 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
217 if (!answer)
218 goto out;
219
220 link_req = (struct link_req *)nlmsg;
221 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
222 link_req->ifinfomsg.ifi_index = ifindex;
223 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
224 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
225 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
226
227 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
228 goto out;
229
230 err = netlink_transaction(&nlh, nlmsg, answer);
231 out:
232 netlink_close(&nlh);
233 nlmsg_free(answer);
234 nlmsg_free(nlmsg);
235 return err;
236 }
237
238 int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
239 {
240 int len, index;
241
242 len = strlen(oldname);
243 if (len == 1 || len >= IFNAMSIZ)
244 return -EINVAL;
245
246 index = if_nametoindex(oldname);
247 if (!index)
248 return -EINVAL;
249
250 return lxc_netdev_rename_by_index(index, newname);
251 }
252
253 int netdev_set_flag(const char *name, int flag)
254 {
255 struct nl_handler nlh;
256 struct nlmsg *nlmsg = NULL, *answer = NULL;
257 struct link_req *link_req;
258 int index, len, err;
259
260 err = netlink_open(&nlh, NETLINK_ROUTE);
261 if (err)
262 return err;
263
264 err = -EINVAL;
265 len = strlen(name);
266 if (len == 1 || len >= IFNAMSIZ)
267 goto out;
268
269 err = -ENOMEM;
270 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
271 if (!nlmsg)
272 goto out;
273
274 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
275 if (!answer)
276 goto out;
277
278 err = -EINVAL;
279 index = if_nametoindex(name);
280 if (!index)
281 goto out;
282
283 link_req = (struct link_req *)nlmsg;
284 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
285 link_req->ifinfomsg.ifi_index = index;
286 link_req->ifinfomsg.ifi_change |= IFF_UP;
287 link_req->ifinfomsg.ifi_flags |= flag;
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;
291
292 err = netlink_transaction(&nlh, nlmsg, answer);
293 out:
294 netlink_close(&nlh);
295 nlmsg_free(nlmsg);
296 nlmsg_free(answer);
297 return err;
298 }
299
300 int lxc_netdev_set_mtu(const char *name, int mtu)
301 {
302 struct nl_handler nlh;
303 struct nlmsg *nlmsg = NULL, *answer = NULL;
304 struct link_req *link_req;
305 int index, len, err;
306
307 err = netlink_open(&nlh, NETLINK_ROUTE);
308 if (err)
309 return err;
310
311 err = -EINVAL;
312 len = strlen(name);
313 if (len == 1 || len >= IFNAMSIZ)
314 goto out;
315
316 err = -ENOMEM;
317 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
318 if (!nlmsg)
319 goto out;
320
321 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
322 if (!answer)
323 goto out;
324
325 err = -EINVAL;
326 index = if_nametoindex(name);
327 if (!index)
328 goto out;
329
330 link_req = (struct link_req *)nlmsg;
331 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
332 link_req->ifinfomsg.ifi_index = index;
333 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
334 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
335 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
336
337 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
338 goto out;
339
340 err = netlink_transaction(&nlh, nlmsg, answer);
341 out:
342 netlink_close(&nlh);
343 nlmsg_free(nlmsg);
344 nlmsg_free(answer);
345 return err;
346 }
347
348 int lxc_netdev_up(const char *name)
349 {
350 return netdev_set_flag(name, IFF_UP);
351 }
352
353 int lxc_netdev_down(const char *name)
354 {
355 return netdev_set_flag(name, 0);
356 }
357
358 int lxc_veth_create(const char *name1, const char *name2)
359 {
360 struct nl_handler nlh;
361 struct nlmsg *nlmsg = NULL, *answer = NULL;
362 struct link_req *link_req;
363 struct rtattr *nest1, *nest2, *nest3;
364 int len, err;
365
366 err = netlink_open(&nlh, NETLINK_ROUTE);
367 if (err)
368 return err;
369
370 err = -EINVAL;
371 len = strlen(name1);
372 if (len == 1 || len >= IFNAMSIZ)
373 goto out;
374
375 len = strlen(name2);
376 if (len == 1 || len >= IFNAMSIZ)
377 goto out;
378
379 err = -ENOMEM;
380 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
381 if (!nlmsg)
382 goto out;
383
384 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
385 if (!answer)
386 goto out;
387
388 link_req = (struct link_req *)nlmsg;
389 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
390 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
391 nlmsg->nlmsghdr.nlmsg_flags =
392 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
393 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
394
395 err = -EINVAL;
396 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
397 if (!nest1)
398 goto out;
399
400 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
401 goto out;
402
403 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
404 if (!nest2)
405 goto out;
406
407 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
408 if (!nest3)
409 goto out;
410
411 nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg);
412
413 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
414 goto out;
415
416 nla_end_nested(nlmsg, nest3);
417
418 nla_end_nested(nlmsg, nest2);
419
420 nla_end_nested(nlmsg, nest1);
421
422 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
423 goto out;
424
425 err = netlink_transaction(&nlh, nlmsg, answer);
426 out:
427 netlink_close(&nlh);
428 nlmsg_free(answer);
429 nlmsg_free(nlmsg);
430 return err;
431 }
432
433 /* XXX: merge with lxc_macvlan_create */
434 int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
435 {
436 struct nl_handler nlh;
437 struct nlmsg *nlmsg = NULL, *answer = NULL;
438 struct link_req *link_req;
439 struct rtattr *nest, *nest2;
440 int lindex, len, err;
441
442 err = netlink_open(&nlh, NETLINK_ROUTE);
443 if (err)
444 return err;
445
446 err = -EINVAL;
447 len = strlen(master);
448 if (len == 1 || len >= IFNAMSIZ)
449 goto err3;
450
451 len = strlen(name);
452 if (len == 1 || len >= IFNAMSIZ)
453 goto err3;
454
455 err = -ENOMEM;
456 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
457 if (!nlmsg)
458 goto err3;
459
460 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
461 if (!answer)
462 goto err2;
463
464 err = -EINVAL;
465 lindex = if_nametoindex(master);
466 if (!lindex)
467 goto err1;
468
469 link_req = (struct link_req *)nlmsg;
470 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
471 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
472 nlmsg->nlmsghdr.nlmsg_flags =
473 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
474 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
475
476 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
477 if (!nest)
478 goto err1;
479
480 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
481 goto err1;
482
483 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
484 if (!nest2)
485 goto err1;
486
487 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
488 goto err1;
489
490 nla_end_nested(nlmsg, nest2);
491
492 nla_end_nested(nlmsg, nest);
493
494 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
495 goto err1;
496
497 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
498 goto err1;
499
500 err = netlink_transaction(&nlh, nlmsg, answer);
501 err1:
502 nlmsg_free(answer);
503 err2:
504 nlmsg_free(nlmsg);
505 err3:
506 netlink_close(&nlh);
507 return err;
508 }
509
510 int lxc_macvlan_create(const char *master, const char *name, int mode)
511 {
512 struct nl_handler nlh;
513 struct nlmsg *nlmsg = NULL, *answer = NULL;
514 struct link_req *link_req;
515 struct rtattr *nest, *nest2;
516 int index, len, err;
517
518 err = netlink_open(&nlh, NETLINK_ROUTE);
519 if (err)
520 return err;
521
522 err = -EINVAL;
523 len = strlen(master);
524 if (len == 1 || len >= IFNAMSIZ)
525 goto out;
526
527 len = strlen(name);
528 if (len == 1 || len >= IFNAMSIZ)
529 goto out;
530
531 err = -ENOMEM;
532 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
533 if (!nlmsg)
534 goto out;
535
536 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
537 if (!answer)
538 goto out;
539
540 err = -EINVAL;
541 index = if_nametoindex(master);
542 if (!index)
543 goto out;
544
545 link_req = (struct link_req *)nlmsg;
546 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
547 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
548 nlmsg->nlmsghdr.nlmsg_flags =
549 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
550 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
551
552 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
553 if (!nest)
554 goto out;
555
556 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
557 goto out;
558
559 if (mode) {
560 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
561 if (!nest2)
562 goto out;
563
564 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
565 goto out;
566
567 nla_end_nested(nlmsg, nest2);
568 }
569
570 nla_end_nested(nlmsg, nest);
571
572 if (nla_put_u32(nlmsg, IFLA_LINK, index))
573 goto out;
574
575 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
576 goto out;
577
578 err = netlink_transaction(&nlh, nlmsg, answer);
579 out:
580 netlink_close(&nlh);
581 nlmsg_free(answer);
582 nlmsg_free(nlmsg);
583 return err;
584 }
585
586 static int proc_sys_net_write(const char *path, const char *value)
587 {
588 int fd, err = 0;
589
590 process_lock();
591 fd = open(path, O_WRONLY);
592 process_unlock();
593 if (fd < 0)
594 return -errno;
595
596 if (write(fd, value, strlen(value)) < 0)
597 err = -errno;
598
599 process_lock();
600 close(fd);
601 process_unlock();
602 return err;
603 }
604
605 static int ip_forward_set(const char *ifname, int family, int flag)
606 {
607 char path[MAXPATHLEN];
608 int rc;
609
610 if (family != AF_INET && family != AF_INET6)
611 return -EINVAL;
612
613 rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
614 family == AF_INET?"ipv4":"ipv6" , ifname);
615 if (rc >= MAXPATHLEN)
616 return -E2BIG;
617
618 return proc_sys_net_write(path, flag?"1":"0");
619 }
620
621 int lxc_ip_forward_on(const char *ifname, int family)
622 {
623 return ip_forward_set(ifname, family, 1);
624 }
625
626 int lxc_ip_forward_off(const char *ifname, int family)
627 {
628 return ip_forward_set(ifname, family, 0);
629 }
630
631 static int neigh_proxy_set(const char *ifname, int family, int flag)
632 {
633 char path[MAXPATHLEN];
634 int ret;
635
636 if (family != AF_INET && family != AF_INET6)
637 return -EINVAL;
638
639 ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
640 family == AF_INET?"ipv4":"ipv6" , ifname,
641 family == AF_INET?"proxy_arp":"proxy_ndp");
642 if (ret < 0 || ret >= MAXPATHLEN)
643 return -E2BIG;
644
645 return proc_sys_net_write(path, flag?"1":"0");
646 }
647
648 int lxc_neigh_proxy_on(const char *name, int family)
649 {
650 return neigh_proxy_set(name, family, 1);
651 }
652
653 int lxc_neigh_proxy_off(const char *name, int family)
654 {
655 return neigh_proxy_set(name, family, 0);
656 }
657
658 int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
659 {
660 unsigned char *data;
661 char c;
662 int i = 0;
663 unsigned val;
664
665 sockaddr->sa_family = ARPHRD_ETHER;
666 data = (unsigned char *)sockaddr->sa_data;
667
668 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
669 val = 0;
670 c = *macaddr++;
671 if (isdigit(c))
672 val = c - '0';
673 else if (c >= 'a' && c <= 'f')
674 val = c - 'a' + 10;
675 else if (c >= 'A' && c <= 'F')
676 val = c - 'A' + 10;
677 else {
678 return -EINVAL;
679 }
680 val <<= 4;
681 c = *macaddr;
682 if (isdigit(c))
683 val |= c - '0';
684 else if (c >= 'a' && c <= 'f')
685 val |= c - 'a' + 10;
686 else if (c >= 'A' && c <= 'F')
687 val |= c - 'A' + 10;
688 else if (c == ':' || c == 0)
689 val >>= 4;
690 else {
691 return -EINVAL;
692 }
693 if (c != 0)
694 macaddr++;
695 *data++ = (unsigned char) (val & 0377);
696 i++;
697
698 if (*macaddr == ':')
699 macaddr++;
700 }
701
702 return 0;
703 }
704
705 static int ip_addr_add(int family, int ifindex,
706 void *addr, void *bcast, void *acast, int prefix)
707 {
708 struct nl_handler nlh;
709 struct nlmsg *nlmsg = NULL, *answer = NULL;
710 struct ip_req *ip_req;
711 int addrlen;
712 int err;
713
714 addrlen = family == AF_INET ? sizeof(struct in_addr) :
715 sizeof(struct in6_addr);
716
717 err = netlink_open(&nlh, NETLINK_ROUTE);
718 if (err)
719 return err;
720
721 err = -ENOMEM;
722 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
723 if (!nlmsg)
724 goto out;
725
726 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
727 if (!answer)
728 goto out;
729
730 ip_req = (struct ip_req *)nlmsg;
731 ip_req->nlmsg.nlmsghdr.nlmsg_len =
732 NLMSG_LENGTH(sizeof(struct ifaddrmsg));
733 ip_req->nlmsg.nlmsghdr.nlmsg_flags =
734 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
735 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
736 ip_req->ifa.ifa_prefixlen = prefix;
737 ip_req->ifa.ifa_index = ifindex;
738 ip_req->ifa.ifa_family = family;
739 ip_req->ifa.ifa_scope = 0;
740
741 err = -EINVAL;
742 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
743 goto out;
744
745 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
746 goto out;
747
748 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
749 goto out;
750
751 /* TODO : multicast, anycast with ipv6 */
752 err = -EPROTONOSUPPORT;
753 if (family == AF_INET6 &&
754 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
755 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
756 goto out;
757
758 err = netlink_transaction(&nlh, nlmsg, answer);
759 out:
760 netlink_close(&nlh);
761 nlmsg_free(answer);
762 nlmsg_free(nlmsg);
763 return err;
764 }
765
766 int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
767 struct in6_addr *mcast,
768 struct in6_addr *acast, int prefix)
769 {
770 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
771 }
772
773 int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr,
774 struct in_addr *bcast, int prefix)
775 {
776 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
777 }
778
779 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
780 * address from the given RTM_NEWADDR message. Allocates memory for the
781 * address and stores that pointer in *res (so res should be an
782 * in_addr** or in6_addr**).
783 */
784 static int ifa_get_local_ip(int family, struct ip_req *ip_info, void** res) {
785 struct rtattr *rta = IFA_RTA(&ip_info->ifa);
786 int attr_len = IFA_PAYLOAD(&ip_info->nlmsg.nlmsghdr);
787 int addrlen;
788
789 if (ip_info->ifa.ifa_family != family)
790 return 0;
791
792 addrlen = family == AF_INET ? sizeof(struct in_addr) :
793 sizeof(struct in6_addr);
794
795 /* Loop over the rtattr's in this message */
796 while(RTA_OK(rta, attr_len)) {
797 /* Found a local address for the requested interface,
798 * return it. */
799 if (rta->rta_type == IFA_LOCAL || rta->rta_type == IFA_ADDRESS) {
800 /* Sanity check. The family check above should
801 * make sure the address length is correct, but
802 * check here just in case */
803 if (RTA_PAYLOAD(rta) != addrlen)
804 return -1;
805
806 /* We might have found an IFA_ADDRESS before,
807 * which we now overwrite with an IFA_LOCAL. */
808 if (!*res) {
809 *res = malloc(addrlen);
810 if (!*res)
811 return -1;
812 }
813
814 memcpy(*res, RTA_DATA(rta), addrlen);
815
816 if (rta->rta_type == IFA_LOCAL)
817 break;
818 }
819 rta = RTA_NEXT(rta, attr_len);
820 }
821 return 0;
822 }
823
824 static int ip_addr_get(int family, int ifindex, void **res)
825 {
826 struct nl_handler nlh;
827 struct nlmsg *nlmsg = NULL, *answer = NULL;
828 struct ip_req *ip_req, *ip_info;
829 struct nlmsghdr *msg;
830 int err;
831 int recv_len = 0, answer_len;
832 int readmore = 0;
833
834 err = netlink_open(&nlh, NETLINK_ROUTE);
835 if (err)
836 return err;
837
838 err = -ENOMEM;
839 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
840 if (!nlmsg)
841 goto out;
842
843 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
844 if (!answer)
845 goto out;
846
847 /* Save the answer buffer length, since it will be overwritten
848 * on the first receive (and we might need to receive more than
849 * once. */
850 answer_len = answer->nlmsghdr.nlmsg_len;
851
852 ip_req = (struct ip_req *)nlmsg;
853 ip_req->nlmsg.nlmsghdr.nlmsg_len =
854 NLMSG_LENGTH(sizeof(struct ifaddrmsg));
855 ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
856 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETADDR;
857 ip_req->ifa.ifa_family = family;
858
859 /* Send the request for addresses, which returns all addresses
860 * on all interfaces. */
861 err = netlink_send(&nlh, nlmsg);
862 if (err < 0)
863 goto out;
864
865 do {
866 /* Restore the answer buffer length, it might have been
867 * overwritten by a previous receive. */
868 answer->nlmsghdr.nlmsg_len = answer_len;
869
870 /* Get the (next) batch of reply messages */
871 err = netlink_rcv(&nlh, answer);
872 if (err < 0)
873 goto out;
874
875 recv_len = err;
876 err = 0;
877
878 /* Satisfy the typing for the netlink macros */
879 msg = &answer->nlmsghdr;
880
881 while (NLMSG_OK(msg, recv_len)) {
882 /* Stop reading if we see an error message */
883 if (msg->nlmsg_type == NLMSG_ERROR) {
884 struct nlmsgerr *errmsg = (struct nlmsgerr*)NLMSG_DATA(msg);
885 err = errmsg->error;
886 goto out;
887 }
888
889 /* Stop reading if we see a NLMSG_DONE message */
890 if (msg->nlmsg_type == NLMSG_DONE) {
891 readmore = 0;
892 break;
893 }
894
895 if (msg->nlmsg_type != RTM_NEWADDR) {
896 err = -1;
897 goto out;
898 }
899
900 ip_info = (struct ip_req *)msg;
901 if (ip_info->ifa.ifa_index == ifindex) {
902 if (ifa_get_local_ip(family, ip_info, res) < 0) {
903 err = -1;
904 goto out;
905 }
906
907 /* Found a result, stop searching */
908 if (*res)
909 goto out;
910 }
911
912 /* Keep reading more data from the socket if the
913 * last message had the NLF_F_MULTI flag set */
914 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
915
916 /* Look at the next message received in this buffer */
917 msg = NLMSG_NEXT(msg, recv_len);
918 }
919 } while (readmore);
920
921 /* If we end up here, we didn't find any result, so signal an
922 * error */
923 err = -1;
924
925 out:
926 netlink_close(&nlh);
927 nlmsg_free(answer);
928 nlmsg_free(nlmsg);
929 return err;
930 }
931
932 int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
933 {
934 return ip_addr_get(AF_INET6, ifindex, (void**)res);
935 }
936
937 int lxc_ipv4_addr_get(int ifindex, struct in_addr** res)
938 {
939 return ip_addr_get(AF_INET, ifindex, (void**)res);
940 }
941
942 static int ip_gateway_add(int family, int ifindex, void *gw)
943 {
944 struct nl_handler nlh;
945 struct nlmsg *nlmsg = NULL, *answer = NULL;
946 struct rt_req *rt_req;
947 int addrlen;
948 int err;
949
950 addrlen = family == AF_INET ? sizeof(struct in_addr) :
951 sizeof(struct in6_addr);
952
953 err = netlink_open(&nlh, NETLINK_ROUTE);
954 if (err)
955 return err;
956
957 err = -ENOMEM;
958 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
959 if (!nlmsg)
960 goto out;
961
962 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
963 if (!answer)
964 goto out;
965
966 rt_req = (struct rt_req *)nlmsg;
967 rt_req->nlmsg.nlmsghdr.nlmsg_len =
968 NLMSG_LENGTH(sizeof(struct rtmsg));
969 rt_req->nlmsg.nlmsghdr.nlmsg_flags =
970 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
971 rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
972 rt_req->rt.rtm_family = family;
973 rt_req->rt.rtm_table = RT_TABLE_MAIN;
974 rt_req->rt.rtm_scope = RT_SCOPE_UNIVERSE;
975 rt_req->rt.rtm_protocol = RTPROT_BOOT;
976 rt_req->rt.rtm_type = RTN_UNICAST;
977 /* "default" destination */
978 rt_req->rt.rtm_dst_len = 0;
979
980 err = -EINVAL;
981 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
982 goto out;
983
984 /* Adding the interface index enables the use of link-local
985 * addresses for the gateway */
986 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
987 goto out;
988
989 err = netlink_transaction(&nlh, nlmsg, answer);
990 out:
991 netlink_close(&nlh);
992 nlmsg_free(answer);
993 nlmsg_free(nlmsg);
994 return err;
995 }
996
997 int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
998 {
999 return ip_gateway_add(AF_INET, ifindex, gw);
1000 }
1001
1002 int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
1003 {
1004 return ip_gateway_add(AF_INET6, ifindex, gw);
1005 }
1006
1007 static int ip_route_dest_add(int family, int ifindex, void *dest)
1008 {
1009 struct nl_handler nlh;
1010 struct nlmsg *nlmsg = NULL, *answer = NULL;
1011 struct rt_req *rt_req;
1012 int addrlen;
1013 int err;
1014
1015 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1016 sizeof(struct in6_addr);
1017
1018 err = netlink_open(&nlh, NETLINK_ROUTE);
1019 if (err)
1020 return err;
1021
1022 err = -ENOMEM;
1023 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1024 if (!nlmsg)
1025 goto out;
1026
1027 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
1028 if (!answer)
1029 goto out;
1030
1031 rt_req = (struct rt_req *)nlmsg;
1032 rt_req->nlmsg.nlmsghdr.nlmsg_len =
1033 NLMSG_LENGTH(sizeof(struct rtmsg));
1034 rt_req->nlmsg.nlmsghdr.nlmsg_flags =
1035 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1036 rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
1037 rt_req->rt.rtm_family = family;
1038 rt_req->rt.rtm_table = RT_TABLE_MAIN;
1039 rt_req->rt.rtm_scope = RT_SCOPE_LINK;
1040 rt_req->rt.rtm_protocol = RTPROT_BOOT;
1041 rt_req->rt.rtm_type = RTN_UNICAST;
1042 rt_req->rt.rtm_dst_len = addrlen*8;
1043
1044 err = -EINVAL;
1045 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
1046 goto out;
1047 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1048 goto out;
1049 err = netlink_transaction(&nlh, nlmsg, answer);
1050 out:
1051 netlink_close(&nlh);
1052 nlmsg_free(answer);
1053 nlmsg_free(nlmsg);
1054 return err;
1055 }
1056
1057 int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
1058 {
1059 return ip_route_dest_add(AF_INET, ifindex, dest);
1060 }
1061
1062 int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
1063 {
1064 return ip_route_dest_add(AF_INET6, ifindex, dest);
1065 }
1066
1067 /*
1068 * There is a lxc_bridge_attach, but no need of a bridge detach
1069 * as automatically done by kernel when a netdev is deleted.
1070 */
1071 int lxc_bridge_attach(const char *bridge, const char *ifname)
1072 {
1073 int fd, index, err;
1074 struct ifreq ifr;
1075
1076 if (strlen(ifname) >= IFNAMSIZ)
1077 return -EINVAL;
1078
1079 index = if_nametoindex(ifname);
1080 if (!index)
1081 return -EINVAL;
1082
1083 process_lock();
1084 fd = socket(AF_INET, SOCK_STREAM, 0);
1085 process_unlock();
1086 if (fd < 0)
1087 return -errno;
1088
1089 strncpy(ifr.ifr_name, bridge, IFNAMSIZ-1);
1090 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1091 ifr.ifr_ifindex = index;
1092 err = ioctl(fd, SIOCBRADDIF, &ifr);
1093 process_lock();
1094 close(fd);
1095 process_unlock();
1096 if (err)
1097 err = -errno;
1098
1099 return err;
1100 }
1101
1102 static char* lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
1103 [LXC_NET_VETH] = "veth",
1104 [LXC_NET_MACVLAN] = "macvlan",
1105 [LXC_NET_VLAN] = "vlan",
1106 [LXC_NET_PHYS] = "phys",
1107 [LXC_NET_EMPTY] = "empty",
1108 };
1109
1110 const char *lxc_net_type_to_str(int type)
1111 {
1112 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
1113 return NULL;
1114 return lxc_network_types[type];
1115 }
1116
1117 static char padchar[] =
1118 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1119
1120 char *lxc_mkifname(char *template)
1121 {
1122 char *name = NULL;
1123 int i = 0;
1124 FILE *urandom;
1125 unsigned int seed;
1126 struct ifaddrs *ifaddr, *ifa;
1127 int ifexists = 0;
1128
1129 /* Get all the network interfaces */
1130 getifaddrs(&ifaddr);
1131
1132 /* Initialize the random number generator */
1133 process_lock();
1134 urandom = fopen ("/dev/urandom", "r");
1135 process_unlock();
1136 if (urandom != NULL) {
1137 if (fread (&seed, sizeof(seed), 1, urandom) <= 0)
1138 seed = time(0);
1139 process_lock();
1140 fclose(urandom);
1141 process_unlock();
1142 }
1143 else
1144 seed = time(0);
1145
1146 #ifndef HAVE_RAND_R
1147 srand(seed);
1148 #endif
1149
1150 /* Generate random names until we find one that doesn't exist */
1151 while(1) {
1152 ifexists = 0;
1153 name = strdup(template);
1154
1155 if (name == NULL)
1156 return NULL;
1157
1158 for (i = 0; i < strlen(name); i++) {
1159 if (name[i] == 'X') {
1160 #ifdef HAVE_RAND_R
1161 name[i] = padchar[rand_r(&seed) % (strlen(padchar) - 1)];
1162 #else
1163 name[i] = padchar[rand() % (strlen(padchar) - 1)];
1164 #endif
1165 }
1166 }
1167
1168 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1169 if (strcmp(ifa->ifa_name, name) == 0) {
1170 ifexists = 1;
1171 break;
1172 }
1173 }
1174
1175 if (ifexists == 0)
1176 break;
1177
1178 free(name);
1179 }
1180
1181 freeifaddrs(ifaddr);
1182 return name;
1183 }
1184
1185 int setup_private_host_hw_addr(char *veth1)
1186 {
1187 struct ifreq ifr;
1188 int err;
1189 int sockfd;
1190
1191 process_lock();
1192 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1193 process_unlock();
1194 if (sockfd < 0)
1195 return -errno;
1196
1197 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1198 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1199 if (err < 0) {
1200 process_lock();
1201 close(sockfd);
1202 process_unlock();
1203 return -errno;
1204 }
1205
1206 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1207 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
1208 process_lock();
1209 close(sockfd);
1210 process_unlock();
1211 if (err < 0)
1212 return -errno;
1213
1214 return 0;
1215 }