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