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