]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
Merge pull request #1659 from brauner/2017-06-28/do_not_use_cmd_socket_on_daemonized_...
[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 <sys/inotify.h>
40 #include <arpa/inet.h>
41 #include <net/if.h>
42 #include <net/if_arp.h>
43 #include <net/ethernet.h>
44 #include <netinet/in.h>
45 #include <linux/netlink.h>
46 #include <linux/rtnetlink.h>
47 #include <linux/sockios.h>
48
49 #include "nl.h"
50 #include "network.h"
51 #include "conf.h"
52 #include "utils.h"
53
54 #if HAVE_IFADDRS_H
55 #include <ifaddrs.h>
56 #else
57 #include <../include/ifaddrs.h>
58 #endif
59
60 #ifndef IFLA_LINKMODE
61 # define IFLA_LINKMODE 17
62 #endif
63
64 #ifndef IFLA_LINKINFO
65 # define IFLA_LINKINFO 18
66 #endif
67
68 #ifndef IFLA_NET_NS_PID
69 # define IFLA_NET_NS_PID 19
70 #endif
71
72 #ifndef IFLA_INFO_KIND
73 # define IFLA_INFO_KIND 1
74 #endif
75
76 #ifndef IFLA_VLAN_ID
77 # define IFLA_VLAN_ID 1
78 #endif
79
80 #ifndef IFLA_INFO_DATA
81 # define IFLA_INFO_DATA 2
82 #endif
83
84 #ifndef VETH_INFO_PEER
85 # define VETH_INFO_PEER 1
86 #endif
87
88 #ifndef IFLA_MACVLAN_MODE
89 # define IFLA_MACVLAN_MODE 1
90 #endif
91
92
93 int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname)
94 {
95 struct nl_handler nlh;
96 struct nlmsg *nlmsg = NULL;
97 struct ifinfomsg *ifi;
98 int err;
99
100 err = netlink_open(&nlh, NETLINK_ROUTE);
101 if (err)
102 return err;
103
104 err = -ENOMEM;
105 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
106 if (!nlmsg)
107 goto out;
108
109 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
110 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
111
112 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
113 if (!ifi)
114 goto out;
115 ifi->ifi_family = AF_UNSPEC;
116 ifi->ifi_index = ifindex;
117
118 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
119 goto out;
120
121 if (ifname != NULL) {
122 if (nla_put_string(nlmsg, IFLA_IFNAME, ifname))
123 goto out;
124 }
125
126 err = netlink_transaction(&nlh, nlmsg, nlmsg);
127 out:
128 netlink_close(&nlh);
129 nlmsg_free(nlmsg);
130 return err;
131 }
132
133 /*
134 * If we are asked to move a wireless interface, then
135 * we must actually move its phyN device. Detect
136 * that condition and return the physname here. The
137 * physname will be passed to lxc_netdev_move_wlan()
138 * which will free it when done
139 */
140 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
141 static char * is_wlan(const char *ifname)
142 {
143 char *path, *physname = NULL;
144 size_t len = strlen(ifname) + strlen(PHYSNAME) - 1;
145 struct stat sb;
146 long physlen;
147 FILE *f;
148 int ret, i;
149
150 path = alloca(len+1);
151 ret = snprintf(path, len, PHYSNAME, ifname);
152 if (ret < 0 || ret >= len)
153 goto bad;
154 ret = stat(path, &sb);
155 if (ret)
156 goto bad;
157 if (!(f = fopen(path, "r")))
158 goto bad;
159 // feh - sb.st_size is always 4096
160 fseek(f, 0, SEEK_END);
161 physlen = ftell(f);
162 fseek(f, 0, SEEK_SET);
163 physname = malloc(physlen+1);
164 if (!physname) {
165 fclose(f);
166 goto bad;
167 }
168 memset(physname, 0, physlen+1);
169 ret = fread(physname, 1, physlen, f);
170 fclose(f);
171 if (ret < 0)
172 goto bad;
173
174 for (i = 0; i < physlen; i++) {
175 if (physname[i] == '\n')
176 physname[i] = '\0';
177 if (physname[i] == '\0')
178 break;
179 }
180
181 return physname;
182
183 bad:
184 free(physname);
185 return NULL;
186 }
187
188 static int
189 lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old, const char *new)
190 {
191 pid_t fpid = fork();
192
193 if (fpid < 0)
194 return -1;
195 if (fpid != 0)
196 return wait_for_pid(fpid);
197 if (!switch_to_ns(pid, "net"))
198 return -1;
199 exit(lxc_netdev_rename_by_name(old, new));
200 }
201
202 static int
203 lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid, const char* newname)
204 {
205 int err = -1;
206 pid_t fpid;
207 char *cmd;
208
209 /* Move phyN into the container. TODO - do this using netlink.
210 * However, IIUC this involves a bit more complicated work to
211 * talk to the 80211 module, so for now just call out to iw
212 */
213 cmd = on_path("iw", NULL);
214 if (!cmd)
215 goto out1;
216 free(cmd);
217
218 fpid = fork();
219 if (fpid < 0)
220 goto out1;
221 if (fpid == 0) {
222 char pidstr[30];
223 sprintf(pidstr, "%d", pid);
224 if (execlp("iw", "iw", "phy", physname, "set", "netns", pidstr, (char *)NULL))
225 exit(1);
226 exit(0); // notreached
227 }
228 if (wait_for_pid(fpid))
229 goto out1;
230
231 err = 0;
232 if (newname)
233 err = lxc_netdev_rename_by_name_in_netns(pid, ifname, newname);
234
235 out1:
236 free(physname);
237 return err;
238 }
239
240 int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
241 {
242 int index;
243 char *physname;
244
245 if (!ifname)
246 return -EINVAL;
247
248 index = if_nametoindex(ifname);
249 if (!index)
250 return -EINVAL;
251
252 if ((physname = is_wlan(ifname)))
253 return lxc_netdev_move_wlan(physname, ifname, pid, newname);
254
255 return lxc_netdev_move_by_index(index, pid, newname);
256 }
257
258 int lxc_netdev_delete_by_index(int ifindex)
259 {
260 struct nl_handler nlh;
261 struct nlmsg *nlmsg = NULL, *answer = NULL;
262 struct ifinfomsg *ifi;
263 int err;
264
265 err = netlink_open(&nlh, NETLINK_ROUTE);
266 if (err)
267 return err;
268
269 err = -ENOMEM;
270 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
271 if (!nlmsg)
272 goto out;
273
274 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
275 if (!answer)
276 goto out;
277
278 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
279 nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
280
281 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
282 if (!ifi)
283 goto out;
284 ifi->ifi_family = AF_UNSPEC;
285 ifi->ifi_index = ifindex;
286
287 err = netlink_transaction(&nlh, nlmsg, answer);
288 out:
289 netlink_close(&nlh);
290 nlmsg_free(answer);
291 nlmsg_free(nlmsg);
292 return err;
293 }
294
295 int lxc_netdev_delete_by_name(const char *name)
296 {
297 int index;
298
299 index = if_nametoindex(name);
300 if (!index)
301 return -EINVAL;
302
303 return lxc_netdev_delete_by_index(index);
304 }
305
306 int lxc_netdev_rename_by_index(int ifindex, const char *newname)
307 {
308 struct nl_handler nlh;
309 struct nlmsg *nlmsg = NULL, *answer = NULL;
310 struct ifinfomsg *ifi;
311 int len, err;
312
313 err = netlink_open(&nlh, NETLINK_ROUTE);
314 if (err)
315 return err;
316
317 len = strlen(newname);
318 if (len == 1 || len >= IFNAMSIZ)
319 goto out;
320
321 err = -ENOMEM;
322 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
323 if (!nlmsg)
324 goto out;
325
326 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
327 if (!answer)
328 goto out;
329
330 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
331 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
332
333 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
334 if (!ifi)
335 goto out;
336 ifi->ifi_family = AF_UNSPEC;
337 ifi->ifi_index = ifindex;
338
339 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
340 goto out;
341
342 err = netlink_transaction(&nlh, nlmsg, answer);
343 out:
344 netlink_close(&nlh);
345 nlmsg_free(answer);
346 nlmsg_free(nlmsg);
347 return err;
348 }
349
350 int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
351 {
352 int len, index;
353
354 len = strlen(oldname);
355 if (len == 1 || len >= IFNAMSIZ)
356 return -EINVAL;
357
358 index = if_nametoindex(oldname);
359 if (!index)
360 return -EINVAL;
361
362 return lxc_netdev_rename_by_index(index, newname);
363 }
364
365 int netdev_set_flag(const char *name, int flag)
366 {
367 struct nl_handler nlh;
368 struct nlmsg *nlmsg = NULL, *answer = NULL;
369 struct ifinfomsg *ifi;
370 int index, len, err;
371
372 err = netlink_open(&nlh, NETLINK_ROUTE);
373 if (err)
374 return err;
375
376 err = -EINVAL;
377 len = strlen(name);
378 if (len == 1 || len >= IFNAMSIZ)
379 goto out;
380
381 err = -ENOMEM;
382 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
383 if (!nlmsg)
384 goto out;
385
386 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
387 if (!answer)
388 goto out;
389
390 err = -EINVAL;
391 index = if_nametoindex(name);
392 if (!index)
393 goto out;
394
395 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
396 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
397
398 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
399 if (!ifi) {
400 err = -ENOMEM;
401 goto out;
402 }
403 ifi->ifi_family = AF_UNSPEC;
404 ifi->ifi_index = index;
405 ifi->ifi_change |= IFF_UP;
406 ifi->ifi_flags |= flag;
407
408 err = netlink_transaction(&nlh, nlmsg, answer);
409 out:
410 netlink_close(&nlh);
411 nlmsg_free(nlmsg);
412 nlmsg_free(answer);
413 return err;
414 }
415
416 int netdev_get_flag(const char* name, int *flag)
417 {
418 struct nl_handler nlh;
419 struct nlmsg *nlmsg = NULL, *answer = NULL;
420 struct ifinfomsg *ifi;
421 int index, len, err;
422
423 if (!name)
424 return -EINVAL;
425
426 err = netlink_open(&nlh, NETLINK_ROUTE);
427 if (err)
428 return err;
429
430 err = -EINVAL;
431 len = strlen(name);
432 if (len == 1 || len >= IFNAMSIZ)
433 goto out;
434
435 err = -ENOMEM;
436 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
437 if (!nlmsg)
438 goto out;
439
440 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
441 if (!answer)
442 goto out;
443
444 err = -EINVAL;
445 index = if_nametoindex(name);
446 if (!index)
447 goto out;
448
449 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
450 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
451
452 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
453 if (!ifi) {
454 err = -ENOMEM;
455 goto out;
456 }
457 ifi->ifi_family = AF_UNSPEC;
458 ifi->ifi_index = index;
459
460 err = netlink_transaction(&nlh, nlmsg, answer);
461 if (err)
462 goto out;
463
464 ifi = NLMSG_DATA(answer->nlmsghdr);
465
466 *flag = ifi->ifi_flags;
467 out:
468 netlink_close(&nlh);
469 nlmsg_free(nlmsg);
470 nlmsg_free(answer);
471 return err;
472 }
473
474 /*
475 * \brief Check a interface is up or not.
476 *
477 * \param name: name for the interface.
478 *
479 * \return int.
480 * 0 means interface is down.
481 * 1 means interface is up.
482 * Others means error happened, and ret-value is the error number.
483 */
484 int lxc_netdev_isup(const char* name)
485 {
486 int flag;
487 int err;
488
489 err = netdev_get_flag(name, &flag);
490 if (err)
491 goto out;
492 if (flag & IFF_UP)
493 return 1;
494 return 0;
495 out:
496 return err;
497 }
498
499 int netdev_get_mtu(int ifindex)
500 {
501 struct nl_handler nlh;
502 struct nlmsg *nlmsg = NULL, *answer = NULL;
503 struct ifinfomsg *ifi;
504 struct nlmsghdr *msg;
505 int err, res;
506 int recv_len = 0, answer_len;
507 int readmore = 0;
508
509 err = netlink_open(&nlh, NETLINK_ROUTE);
510 if (err)
511 return err;
512
513 err = -ENOMEM;
514 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
515 if (!nlmsg)
516 goto out;
517
518 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
519 if (!answer)
520 goto out;
521
522 /* Save the answer buffer length, since it will be overwritten
523 * on the first receive (and we might need to receive more than
524 * once. */
525 answer_len = answer->nlmsghdr->nlmsg_len;
526
527 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
528 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
529
530 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
531 if (!ifi)
532 goto out;
533 ifi->ifi_family = AF_UNSPEC;
534
535 /* Send the request for addresses, which returns all addresses
536 * on all interfaces. */
537 err = netlink_send(&nlh, nlmsg);
538 if (err < 0)
539 goto out;
540
541 do {
542 /* Restore the answer buffer length, it might have been
543 * overwritten by a previous receive. */
544 answer->nlmsghdr->nlmsg_len = answer_len;
545
546 /* Get the (next) batch of reply messages */
547 err = netlink_rcv(&nlh, answer);
548 if (err < 0)
549 goto out;
550
551 recv_len = err;
552 err = 0;
553
554 /* Satisfy the typing for the netlink macros */
555 msg = answer->nlmsghdr;
556
557 while (NLMSG_OK(msg, recv_len)) {
558
559 /* Stop reading if we see an error message */
560 if (msg->nlmsg_type == NLMSG_ERROR) {
561 struct nlmsgerr *errmsg = (struct nlmsgerr*)NLMSG_DATA(msg);
562 err = errmsg->error;
563 goto out;
564 }
565
566 /* Stop reading if we see a NLMSG_DONE message */
567 if (msg->nlmsg_type == NLMSG_DONE) {
568 readmore = 0;
569 break;
570 }
571
572 ifi = NLMSG_DATA(msg);
573 if (ifi->ifi_index == ifindex) {
574 struct rtattr *rta = IFLA_RTA(ifi);
575 int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
576 res = 0;
577 while(RTA_OK(rta, attr_len)) {
578 /* Found a local address for the requested interface,
579 * return it. */
580 if (rta->rta_type == IFLA_MTU) {
581 memcpy(&res, RTA_DATA(rta), sizeof(int));
582 err = res;
583 goto out;
584 }
585 rta = RTA_NEXT(rta, attr_len);
586 }
587
588 }
589
590 /* Keep reading more data from the socket if the
591 * last message had the NLF_F_MULTI flag set */
592 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
593
594 /* Look at the next message received in this buffer */
595 msg = NLMSG_NEXT(msg, recv_len);
596 }
597 } while (readmore);
598
599 /* If we end up here, we didn't find any result, so signal an
600 * error */
601 err = -1;
602
603 out:
604 netlink_close(&nlh);
605 nlmsg_free(answer);
606 nlmsg_free(nlmsg);
607 return err;
608 }
609
610 int lxc_netdev_set_mtu(const char *name, int mtu)
611 {
612 struct nl_handler nlh;
613 struct nlmsg *nlmsg = NULL, *answer = NULL;
614 struct ifinfomsg *ifi;
615 int index, len, err;
616
617 err = netlink_open(&nlh, NETLINK_ROUTE);
618 if (err)
619 return err;
620
621 err = -EINVAL;
622 len = strlen(name);
623 if (len == 1 || len >= IFNAMSIZ)
624 goto out;
625
626 err = -ENOMEM;
627 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
628 if (!nlmsg)
629 goto out;
630
631 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
632 if (!answer)
633 goto out;
634
635 err = -EINVAL;
636 index = if_nametoindex(name);
637 if (!index)
638 goto out;
639
640 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
641 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
642
643 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
644 if (!ifi) {
645 err = -ENOMEM;
646 goto out;
647 }
648 ifi->ifi_family = AF_UNSPEC;
649 ifi->ifi_index = index;
650
651 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
652 goto out;
653
654 err = netlink_transaction(&nlh, nlmsg, answer);
655 out:
656 netlink_close(&nlh);
657 nlmsg_free(nlmsg);
658 nlmsg_free(answer);
659 return err;
660 }
661
662 int lxc_netdev_up(const char *name)
663 {
664 return netdev_set_flag(name, IFF_UP);
665 }
666
667 int lxc_netdev_down(const char *name)
668 {
669 return netdev_set_flag(name, 0);
670 }
671
672 int lxc_veth_create(const char *name1, const char *name2)
673 {
674 struct nl_handler nlh;
675 struct nlmsg *nlmsg = NULL, *answer = NULL;
676 struct ifinfomsg *ifi;
677 struct rtattr *nest1, *nest2, *nest3;
678 int len, err;
679
680 err = netlink_open(&nlh, NETLINK_ROUTE);
681 if (err)
682 return err;
683
684 err = -EINVAL;
685 len = strlen(name1);
686 if (len == 1 || len >= IFNAMSIZ)
687 goto out;
688
689 len = strlen(name2);
690 if (len == 1 || len >= IFNAMSIZ)
691 goto out;
692
693 err = -ENOMEM;
694 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
695 if (!nlmsg)
696 goto out;
697
698 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
699 if (!answer)
700 goto out;
701
702 nlmsg->nlmsghdr->nlmsg_flags =
703 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
704 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
705
706 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
707 if (!ifi)
708 goto out;
709 ifi->ifi_family = AF_UNSPEC;
710
711 err = -EINVAL;
712 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
713 if (!nest1)
714 goto out;
715
716 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
717 goto out;
718
719 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
720 if (!nest2)
721 goto out;
722
723 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
724 if (!nest3)
725 goto out;
726
727 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
728 if (!ifi) {
729 err = -ENOMEM;
730 goto out;
731 }
732
733 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
734 goto out;
735
736 nla_end_nested(nlmsg, nest3);
737
738 nla_end_nested(nlmsg, nest2);
739
740 nla_end_nested(nlmsg, nest1);
741
742 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
743 goto out;
744
745 err = netlink_transaction(&nlh, nlmsg, answer);
746 out:
747 netlink_close(&nlh);
748 nlmsg_free(answer);
749 nlmsg_free(nlmsg);
750 return err;
751 }
752
753 /* XXX: merge with lxc_macvlan_create */
754 int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
755 {
756 struct nl_handler nlh;
757 struct nlmsg *nlmsg = NULL, *answer = NULL;
758 struct ifinfomsg *ifi;
759 struct rtattr *nest, *nest2;
760 int lindex, len, err;
761
762 err = netlink_open(&nlh, NETLINK_ROUTE);
763 if (err)
764 return err;
765
766 err = -EINVAL;
767 len = strlen(master);
768 if (len == 1 || len >= IFNAMSIZ)
769 goto err3;
770
771 len = strlen(name);
772 if (len == 1 || len >= IFNAMSIZ)
773 goto err3;
774
775 err = -ENOMEM;
776 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
777 if (!nlmsg)
778 goto err3;
779
780 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
781 if (!answer)
782 goto err2;
783
784 err = -EINVAL;
785 lindex = if_nametoindex(master);
786 if (!lindex)
787 goto err1;
788
789 nlmsg->nlmsghdr->nlmsg_flags =
790 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
791 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
792
793 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
794 if (!ifi) {
795 err = -ENOMEM;
796 goto err1;
797 }
798 ifi->ifi_family = AF_UNSPEC;
799
800 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
801 if (!nest)
802 goto err1;
803
804 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
805 goto err1;
806
807 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
808 if (!nest2)
809 goto err1;
810
811 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
812 goto err1;
813
814 nla_end_nested(nlmsg, nest2);
815
816 nla_end_nested(nlmsg, nest);
817
818 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
819 goto err1;
820
821 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
822 goto err1;
823
824 err = netlink_transaction(&nlh, nlmsg, answer);
825 err1:
826 nlmsg_free(answer);
827 err2:
828 nlmsg_free(nlmsg);
829 err3:
830 netlink_close(&nlh);
831 return err;
832 }
833
834 int lxc_macvlan_create(const char *master, const char *name, int mode)
835 {
836 struct nl_handler nlh;
837 struct nlmsg *nlmsg = NULL, *answer = NULL;
838 struct ifinfomsg *ifi;
839 struct rtattr *nest, *nest2;
840 int index, len, err;
841
842 err = netlink_open(&nlh, NETLINK_ROUTE);
843 if (err)
844 return err;
845
846 err = -EINVAL;
847 len = strlen(master);
848 if (len == 1 || len >= IFNAMSIZ)
849 goto out;
850
851 len = strlen(name);
852 if (len == 1 || len >= IFNAMSIZ)
853 goto out;
854
855 err = -ENOMEM;
856 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
857 if (!nlmsg)
858 goto out;
859
860 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
861 if (!answer)
862 goto out;
863
864 err = -EINVAL;
865 index = if_nametoindex(master);
866 if (!index)
867 goto out;
868
869 nlmsg->nlmsghdr->nlmsg_flags =
870 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
871 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
872
873 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
874 if (!ifi) {
875 err = -ENOMEM;
876 goto out;
877 }
878 ifi->ifi_family = AF_UNSPEC;
879
880 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
881 if (!nest)
882 goto out;
883
884 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
885 goto out;
886
887 if (mode) {
888 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
889 if (!nest2)
890 goto out;
891
892 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
893 goto out;
894
895 nla_end_nested(nlmsg, nest2);
896 }
897
898 nla_end_nested(nlmsg, nest);
899
900 if (nla_put_u32(nlmsg, IFLA_LINK, index))
901 goto out;
902
903 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
904 goto out;
905
906 err = netlink_transaction(&nlh, nlmsg, answer);
907 out:
908 netlink_close(&nlh);
909 nlmsg_free(answer);
910 nlmsg_free(nlmsg);
911 return err;
912 }
913
914 static int proc_sys_net_write(const char *path, const char *value)
915 {
916 int fd, err = 0;
917
918 fd = open(path, O_WRONLY);
919 if (fd < 0)
920 return -errno;
921
922 if (write(fd, value, strlen(value)) < 0)
923 err = -errno;
924
925 close(fd);
926 return err;
927 }
928
929 static int ip_forward_set(const char *ifname, int family, int flag)
930 {
931 char path[MAXPATHLEN];
932 int rc;
933
934 if (family != AF_INET && family != AF_INET6)
935 return -EINVAL;
936
937 rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
938 family == AF_INET?"ipv4":"ipv6" , ifname);
939 if (rc >= MAXPATHLEN)
940 return -E2BIG;
941
942 return proc_sys_net_write(path, flag?"1":"0");
943 }
944
945 int lxc_ip_forward_on(const char *ifname, int family)
946 {
947 return ip_forward_set(ifname, family, 1);
948 }
949
950 int lxc_ip_forward_off(const char *ifname, int family)
951 {
952 return ip_forward_set(ifname, family, 0);
953 }
954
955 static int neigh_proxy_set(const char *ifname, int family, int flag)
956 {
957 char path[MAXPATHLEN];
958 int ret;
959
960 if (family != AF_INET && family != AF_INET6)
961 return -EINVAL;
962
963 ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
964 family == AF_INET?"ipv4":"ipv6" , ifname,
965 family == AF_INET?"proxy_arp":"proxy_ndp");
966 if (ret < 0 || ret >= MAXPATHLEN)
967 return -E2BIG;
968
969 return proc_sys_net_write(path, flag?"1":"0");
970 }
971
972 int lxc_neigh_proxy_on(const char *name, int family)
973 {
974 return neigh_proxy_set(name, family, 1);
975 }
976
977 int lxc_neigh_proxy_off(const char *name, int family)
978 {
979 return neigh_proxy_set(name, family, 0);
980 }
981
982 int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
983 {
984 unsigned char *data;
985 char c;
986 int i = 0;
987 unsigned val;
988
989 sockaddr->sa_family = ARPHRD_ETHER;
990 data = (unsigned char *)sockaddr->sa_data;
991
992 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
993 val = 0;
994 c = *macaddr++;
995 if (isdigit(c))
996 val = c - '0';
997 else if (c >= 'a' && c <= 'f')
998 val = c - 'a' + 10;
999 else if (c >= 'A' && c <= 'F')
1000 val = c - 'A' + 10;
1001 else {
1002 return -EINVAL;
1003 }
1004 val <<= 4;
1005 c = *macaddr;
1006 if (isdigit(c))
1007 val |= c - '0';
1008 else if (c >= 'a' && c <= 'f')
1009 val |= c - 'a' + 10;
1010 else if (c >= 'A' && c <= 'F')
1011 val |= c - 'A' + 10;
1012 else if (c == ':' || c == 0)
1013 val >>= 4;
1014 else {
1015 return -EINVAL;
1016 }
1017 if (c != 0)
1018 macaddr++;
1019 *data++ = (unsigned char) (val & 0377);
1020 i++;
1021
1022 if (*macaddr == ':')
1023 macaddr++;
1024 }
1025
1026 return 0;
1027 }
1028
1029 static int ip_addr_add(int family, int ifindex,
1030 void *addr, void *bcast, void *acast, int prefix)
1031 {
1032 struct nl_handler nlh;
1033 struct nlmsg *nlmsg = NULL, *answer = NULL;
1034 struct ifaddrmsg *ifa;
1035 int addrlen;
1036 int err;
1037
1038 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1039 sizeof(struct in6_addr);
1040
1041 err = netlink_open(&nlh, NETLINK_ROUTE);
1042 if (err)
1043 return err;
1044
1045 err = -ENOMEM;
1046 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1047 if (!nlmsg)
1048 goto out;
1049
1050 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1051 if (!answer)
1052 goto out;
1053
1054 nlmsg->nlmsghdr->nlmsg_flags =
1055 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1056 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
1057
1058 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
1059 if (!ifa)
1060 goto out;
1061 ifa->ifa_prefixlen = prefix;
1062 ifa->ifa_index = ifindex;
1063 ifa->ifa_family = family;
1064 ifa->ifa_scope = 0;
1065
1066 err = -EINVAL;
1067 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
1068 goto out;
1069
1070 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
1071 goto out;
1072
1073 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
1074 goto out;
1075
1076 /* TODO : multicast, anycast with ipv6 */
1077 err = -EPROTONOSUPPORT;
1078 if (family == AF_INET6 &&
1079 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
1080 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
1081 goto out;
1082
1083 err = netlink_transaction(&nlh, nlmsg, answer);
1084 out:
1085 netlink_close(&nlh);
1086 nlmsg_free(answer);
1087 nlmsg_free(nlmsg);
1088 return err;
1089 }
1090
1091 int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
1092 struct in6_addr *mcast,
1093 struct in6_addr *acast, int prefix)
1094 {
1095 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
1096 }
1097
1098 int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr,
1099 struct in_addr *bcast, int prefix)
1100 {
1101 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
1102 }
1103
1104 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
1105 * address from the given RTM_NEWADDR message. Allocates memory for the
1106 * address and stores that pointer in *res (so res should be an
1107 * in_addr** or in6_addr**).
1108 */
1109 static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void** res) {
1110 struct ifaddrmsg *ifa = NLMSG_DATA(msg);
1111 struct rtattr *rta = IFA_RTA(ifa);
1112 int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
1113 int addrlen;
1114
1115 if (ifa->ifa_family != family)
1116 return 0;
1117
1118 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1119 sizeof(struct in6_addr);
1120
1121 /* Loop over the rtattr's in this message */
1122 while(RTA_OK(rta, attr_len)) {
1123 /* Found a local address for the requested interface,
1124 * return it. */
1125 if (rta->rta_type == IFA_LOCAL || rta->rta_type == IFA_ADDRESS) {
1126 /* Sanity check. The family check above should
1127 * make sure the address length is correct, but
1128 * check here just in case */
1129 if (RTA_PAYLOAD(rta) != addrlen)
1130 return -1;
1131
1132 /* We might have found an IFA_ADDRESS before,
1133 * which we now overwrite with an IFA_LOCAL. */
1134 if (!*res) {
1135 *res = malloc(addrlen);
1136 if (!*res)
1137 return -1;
1138 }
1139
1140 memcpy(*res, RTA_DATA(rta), addrlen);
1141
1142 if (rta->rta_type == IFA_LOCAL)
1143 break;
1144 }
1145 rta = RTA_NEXT(rta, attr_len);
1146 }
1147 return 0;
1148 }
1149
1150 static int ip_addr_get(int family, int ifindex, void **res)
1151 {
1152 struct nl_handler nlh;
1153 struct nlmsg *nlmsg = NULL, *answer = NULL;
1154 struct ifaddrmsg *ifa;
1155 struct nlmsghdr *msg;
1156 int err;
1157 int recv_len = 0, answer_len;
1158 int readmore = 0;
1159
1160 err = netlink_open(&nlh, NETLINK_ROUTE);
1161 if (err)
1162 return err;
1163
1164 err = -ENOMEM;
1165 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1166 if (!nlmsg)
1167 goto out;
1168
1169 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1170 if (!answer)
1171 goto out;
1172
1173 /* Save the answer buffer length, since it will be overwritten
1174 * on the first receive (and we might need to receive more than
1175 * once. */
1176 answer_len = answer->nlmsghdr->nlmsg_len;
1177
1178 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
1179 nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
1180
1181 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
1182 if (!ifa)
1183 goto out;
1184 ifa->ifa_family = family;
1185
1186 /* Send the request for addresses, which returns all addresses
1187 * on all interfaces. */
1188 err = netlink_send(&nlh, nlmsg);
1189 if (err < 0)
1190 goto out;
1191
1192 do {
1193 /* Restore the answer buffer length, it might have been
1194 * overwritten by a previous receive. */
1195 answer->nlmsghdr->nlmsg_len = answer_len;
1196
1197 /* Get the (next) batch of reply messages */
1198 err = netlink_rcv(&nlh, answer);
1199 if (err < 0)
1200 goto out;
1201
1202 recv_len = err;
1203 err = 0;
1204
1205 /* Satisfy the typing for the netlink macros */
1206 msg = answer->nlmsghdr;
1207
1208 while (NLMSG_OK(msg, recv_len)) {
1209 /* Stop reading if we see an error message */
1210 if (msg->nlmsg_type == NLMSG_ERROR) {
1211 struct nlmsgerr *errmsg = (struct nlmsgerr*)NLMSG_DATA(msg);
1212 err = errmsg->error;
1213 goto out;
1214 }
1215
1216 /* Stop reading if we see a NLMSG_DONE message */
1217 if (msg->nlmsg_type == NLMSG_DONE) {
1218 readmore = 0;
1219 break;
1220 }
1221
1222 if (msg->nlmsg_type != RTM_NEWADDR) {
1223 err = -1;
1224 goto out;
1225 }
1226
1227 ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
1228 if (ifa->ifa_index == ifindex) {
1229 if (ifa_get_local_ip(family, msg, res) < 0) {
1230 err = -1;
1231 goto out;
1232 }
1233
1234 /* Found a result, stop searching */
1235 if (*res)
1236 goto out;
1237 }
1238
1239 /* Keep reading more data from the socket if the
1240 * last message had the NLF_F_MULTI flag set */
1241 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1242
1243 /* Look at the next message received in this buffer */
1244 msg = NLMSG_NEXT(msg, recv_len);
1245 }
1246 } while (readmore);
1247
1248 /* If we end up here, we didn't find any result, so signal an
1249 * error */
1250 err = -1;
1251
1252 out:
1253 netlink_close(&nlh);
1254 nlmsg_free(answer);
1255 nlmsg_free(nlmsg);
1256 return err;
1257 }
1258
1259 int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
1260 {
1261 return ip_addr_get(AF_INET6, ifindex, (void**)res);
1262 }
1263
1264 int lxc_ipv4_addr_get(int ifindex, struct in_addr** res)
1265 {
1266 return ip_addr_get(AF_INET, ifindex, (void**)res);
1267 }
1268
1269 static int ip_gateway_add(int family, int ifindex, void *gw)
1270 {
1271 struct nl_handler nlh;
1272 struct nlmsg *nlmsg = NULL, *answer = NULL;
1273 struct rtmsg *rt;
1274 int addrlen;
1275 int err;
1276
1277 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1278 sizeof(struct in6_addr);
1279
1280 err = netlink_open(&nlh, NETLINK_ROUTE);
1281 if (err)
1282 return err;
1283
1284 err = -ENOMEM;
1285 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1286 if (!nlmsg)
1287 goto out;
1288
1289 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1290 if (!answer)
1291 goto out;
1292
1293 nlmsg->nlmsghdr->nlmsg_flags =
1294 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1295 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1296
1297 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
1298 if (!rt)
1299 goto out;
1300 rt->rtm_family = family;
1301 rt->rtm_table = RT_TABLE_MAIN;
1302 rt->rtm_scope = RT_SCOPE_UNIVERSE;
1303 rt->rtm_protocol = RTPROT_BOOT;
1304 rt->rtm_type = RTN_UNICAST;
1305 /* "default" destination */
1306 rt->rtm_dst_len = 0;
1307
1308 err = -EINVAL;
1309 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
1310 goto out;
1311
1312 /* Adding the interface index enables the use of link-local
1313 * addresses for the gateway */
1314 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1315 goto out;
1316
1317 err = netlink_transaction(&nlh, nlmsg, answer);
1318 out:
1319 netlink_close(&nlh);
1320 nlmsg_free(answer);
1321 nlmsg_free(nlmsg);
1322 return err;
1323 }
1324
1325 int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
1326 {
1327 return ip_gateway_add(AF_INET, ifindex, gw);
1328 }
1329
1330 int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
1331 {
1332 return ip_gateway_add(AF_INET6, ifindex, gw);
1333 }
1334
1335 static int ip_route_dest_add(int family, int ifindex, void *dest)
1336 {
1337 struct nl_handler nlh;
1338 struct nlmsg *nlmsg = NULL, *answer = NULL;
1339 struct rtmsg *rt;
1340 int addrlen;
1341 int err;
1342
1343 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1344 sizeof(struct in6_addr);
1345
1346 err = netlink_open(&nlh, NETLINK_ROUTE);
1347 if (err)
1348 return err;
1349
1350 err = -ENOMEM;
1351 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1352 if (!nlmsg)
1353 goto out;
1354
1355 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1356 if (!answer)
1357 goto out;
1358
1359 nlmsg->nlmsghdr->nlmsg_flags =
1360 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1361 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1362
1363 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
1364 if (!rt)
1365 goto out;
1366 rt->rtm_family = family;
1367 rt->rtm_table = RT_TABLE_MAIN;
1368 rt->rtm_scope = RT_SCOPE_LINK;
1369 rt->rtm_protocol = RTPROT_BOOT;
1370 rt->rtm_type = RTN_UNICAST;
1371 rt->rtm_dst_len = addrlen*8;
1372
1373 err = -EINVAL;
1374 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
1375 goto out;
1376 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1377 goto out;
1378 err = netlink_transaction(&nlh, nlmsg, answer);
1379 out:
1380 netlink_close(&nlh);
1381 nlmsg_free(answer);
1382 nlmsg_free(nlmsg);
1383 return err;
1384 }
1385
1386 int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
1387 {
1388 return ip_route_dest_add(AF_INET, ifindex, dest);
1389 }
1390
1391 int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
1392 {
1393 return ip_route_dest_add(AF_INET6, ifindex, dest);
1394 }
1395
1396 static bool is_ovs_bridge(const char *bridge)
1397 {
1398 char brdirname[22 + IFNAMSIZ + 1] = {0};
1399 struct stat sb;
1400
1401 snprintf(brdirname, 22 +IFNAMSIZ + 1, "/sys/class/net/%s/bridge", bridge);
1402 if (stat(brdirname, &sb) == -1 && errno == ENOENT)
1403 return true;
1404 return false;
1405 }
1406
1407 /*
1408 * Called from a background thread - when nic goes away, remove
1409 * it from the bridge
1410 */
1411 static void ovs_cleanup_nic(const char *lxcpath, const char *name, const char *bridge, const char *nic)
1412 {
1413 if (lxc_check_inherited(NULL, true, &(int){-1}, 1) < 0)
1414 return;
1415 if (lxc_wait(name, "STOPPED", -1, lxcpath) < 0)
1416 return;
1417 execlp("ovs-vsctl", "ovs-vsctl", "del-port", bridge, nic, (char *)NULL);
1418 exit(1); /* not reached */
1419 }
1420
1421 static int attach_to_ovs_bridge(const char *lxcpath, const char *name, const char *bridge, const char *nic)
1422 {
1423 pid_t pid;
1424 char *cmd;
1425 int ret;
1426
1427 cmd = on_path("ovs-vsctl", NULL);
1428 if (!cmd)
1429 return -1;
1430 free(cmd);
1431
1432 pid = fork();
1433 if (pid < 0)
1434 return -1;
1435 if (pid > 0) {
1436 ret = wait_for_pid(pid);
1437 if (ret < 0)
1438 return ret;
1439 pid = fork();
1440 if (pid < 0)
1441 return -1; // how to properly recover?
1442 if (pid > 0)
1443 return 0;
1444 ovs_cleanup_nic(lxcpath, name, bridge, nic);
1445 exit(0);
1446 }
1447
1448 if (execlp("ovs-vsctl", "ovs-vsctl", "add-port", bridge, nic, (char *)NULL))
1449 exit(1);
1450 // not reached
1451 exit(1);
1452 }
1453
1454 /*
1455 * There is a lxc_bridge_attach, but no need of a bridge detach
1456 * as automatically done by kernel when a netdev is deleted.
1457 */
1458 int lxc_bridge_attach(const char *lxcpath, const char *name, const char *bridge, const char *ifname)
1459 {
1460 int fd, index, err;
1461 struct ifreq ifr;
1462
1463 if (strlen(ifname) >= IFNAMSIZ)
1464 return -EINVAL;
1465
1466 index = if_nametoindex(ifname);
1467 if (!index)
1468 return -EINVAL;
1469
1470 if (is_ovs_bridge(bridge))
1471 return attach_to_ovs_bridge(lxcpath, name, bridge, ifname);
1472
1473 fd = socket(AF_INET, SOCK_STREAM, 0);
1474 if (fd < 0)
1475 return -errno;
1476
1477 strncpy(ifr.ifr_name, bridge, IFNAMSIZ-1);
1478 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1479 ifr.ifr_ifindex = index;
1480 err = ioctl(fd, SIOCBRADDIF, &ifr);
1481 close(fd);
1482 if (err)
1483 err = -errno;
1484
1485 return err;
1486 }
1487
1488 static const char* const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
1489 [LXC_NET_EMPTY] = "empty",
1490 [LXC_NET_VETH] = "veth",
1491 [LXC_NET_MACVLAN] = "macvlan",
1492 [LXC_NET_PHYS] = "phys",
1493 [LXC_NET_VLAN] = "vlan",
1494 [LXC_NET_NONE] = "none",
1495 };
1496
1497 const char *lxc_net_type_to_str(int type)
1498 {
1499 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
1500 return NULL;
1501 return lxc_network_types[type];
1502 }
1503
1504 static const char padchar[] =
1505 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1506
1507 char *lxc_mkifname(char *template)
1508 {
1509 char *name = NULL;
1510 size_t i = 0;
1511 FILE *urandom;
1512 unsigned int seed;
1513 struct ifaddrs *ifaddr, *ifa;
1514 int ifexists = 0;
1515
1516 /* Get all the network interfaces */
1517 getifaddrs(&ifaddr);
1518
1519 /* Initialize the random number generator */
1520 urandom = fopen ("/dev/urandom", "r");
1521 if (urandom != NULL) {
1522 if (fread (&seed, sizeof(seed), 1, urandom) <= 0)
1523 seed = time(0);
1524 fclose(urandom);
1525 }
1526 else
1527 seed = time(0);
1528
1529 #ifndef HAVE_RAND_R
1530 srand(seed);
1531 #endif
1532
1533 /* Generate random names until we find one that doesn't exist */
1534 while(1) {
1535 ifexists = 0;
1536 name = strdup(template);
1537
1538 if (name == NULL)
1539 return NULL;
1540
1541 for (i = 0; i < strlen(name); i++) {
1542 if (name[i] == 'X') {
1543 #ifdef HAVE_RAND_R
1544 name[i] = padchar[rand_r(&seed) % (strlen(padchar) - 1)];
1545 #else
1546 name[i] = padchar[rand() % (strlen(padchar) - 1)];
1547 #endif
1548 }
1549 }
1550
1551 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1552 if (strcmp(ifa->ifa_name, name) == 0) {
1553 ifexists = 1;
1554 break;
1555 }
1556 }
1557
1558 if (ifexists == 0)
1559 break;
1560
1561 free(name);
1562 }
1563
1564 freeifaddrs(ifaddr);
1565 return name;
1566 }
1567
1568 int setup_private_host_hw_addr(char *veth1)
1569 {
1570 struct ifreq ifr;
1571 int err;
1572 int sockfd;
1573
1574 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1575 if (sockfd < 0)
1576 return -errno;
1577
1578 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1579 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1580 if (err < 0) {
1581 close(sockfd);
1582 return -errno;
1583 }
1584
1585 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1586 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
1587 close(sockfd);
1588 if (err < 0)
1589 return -errno;
1590
1591 return 0;
1592 }