]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
8bfe6a1a2f4c223acd572fe2a1b008f02bf8fc7f
[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
24 #define _GNU_SOURCE
25 #include <ctype.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <arpa/inet.h>
34 #include <linux/netlink.h>
35 #include <linux/rtnetlink.h>
36 #include <linux/sockios.h>
37 #include <net/ethernet.h>
38 #include <net/if.h>
39 #include <net/if_arp.h>
40 #include <netinet/in.h>
41 #include <sys/inotify.h>
42 #include <sys/ioctl.h>
43 #include <sys/param.h>
44 #include <sys/socket.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47
48 #include "af_unix.h"
49 #include "conf.h"
50 #include "config.h"
51 #include "file_utils.h"
52 #include "log.h"
53 #include "macro.h"
54 #include "network.h"
55 #include "nl.h"
56 #include "utils.h"
57
58 #if HAVE_IFADDRS_H
59 #include <ifaddrs.h>
60 #else
61 #include <../include/ifaddrs.h>
62 #endif
63
64 #ifndef HAVE_STRLCPY
65 #include "include/strlcpy.h"
66 #endif
67
68 lxc_log_define(network, lxc);
69
70 typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
71
72 static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
73 {
74 int bridge_index, err;
75 char *veth1, *veth2;
76 char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ];
77 unsigned int mtu = 0;
78
79 if (netdev->priv.veth_attr.pair[0] != '\0') {
80 veth1 = netdev->priv.veth_attr.pair;
81 if (handler->conf->reboot)
82 lxc_netdev_delete_by_name(veth1);
83 } else {
84 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
85 if (err < 0 || (size_t)err >= sizeof(veth1buf))
86 return -1;
87
88 veth1 = lxc_mkifname(veth1buf);
89 if (!veth1)
90 return -1;
91
92 /* store away for deconf */
93 memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
94 }
95
96 err = snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
97 if (err < 0 || (size_t)err >= sizeof(veth2buf))
98 return -1;
99
100 veth2 = lxc_mkifname(veth2buf);
101 if (!veth2)
102 goto out_delete;
103
104 err = lxc_veth_create(veth1, veth2);
105 if (err) {
106 errno = -err;
107 SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1, veth2);
108 goto out_delete;
109 }
110
111 /* changing the high byte of the mac address to 0xfe, the bridge interface
112 * will always keep the host's mac address and not take the mac address
113 * of a container */
114 err = setup_private_host_hw_addr(veth1);
115 if (err) {
116 errno = -err;
117 SYSERROR("Failed to change mac address of host interface \"%s\"", veth1);
118 goto out_delete;
119 }
120
121 /* Retrieve ifindex of the host's veth device. */
122 netdev->priv.veth_attr.ifindex = if_nametoindex(veth1);
123 if (!netdev->priv.veth_attr.ifindex) {
124 ERROR("Failed to retrieve ifindex for \"%s\"", veth1);
125 goto out_delete;
126 }
127
128 /* Note that we're retrieving the container's ifindex in the host's
129 * network namespace because we need it to move the device from the
130 * host's network namespace to the container's network namespace later
131 * on.
132 */
133 netdev->ifindex = if_nametoindex(veth2);
134 if (!netdev->ifindex) {
135 ERROR("Failed to retrieve ifindex for \"%s\"", veth2);
136 goto out_delete;
137 }
138
139 if (netdev->mtu) {
140 if (lxc_safe_uint(netdev->mtu, &mtu) < 0)
141 WARN("Failed to parse mtu");
142 else
143 INFO("Retrieved mtu %d", mtu);
144 } else if (netdev->link[0] != '\0') {
145 bridge_index = if_nametoindex(netdev->link);
146 if (bridge_index) {
147 mtu = netdev_get_mtu(bridge_index);
148 INFO("Retrieved mtu %d from %s", mtu, netdev->link);
149 } else {
150 mtu = netdev_get_mtu(netdev->ifindex);
151 INFO("Retrieved mtu %d from %s", mtu, veth2);
152 }
153 }
154
155 if (mtu) {
156 err = lxc_netdev_set_mtu(veth1, mtu);
157 if (!err)
158 err = lxc_netdev_set_mtu(veth2, mtu);
159
160 if (err) {
161 errno = -err;
162 SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
163 "and \"%s\"", mtu, veth1, veth2);
164 goto out_delete;
165 }
166 }
167
168 if (netdev->link[0] != '\0') {
169 err = lxc_bridge_attach(netdev->link, veth1);
170 if (err) {
171 errno = -err;
172 SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
173 veth1, netdev->link);
174 goto out_delete;
175 }
176 INFO("Attached \"%s\" to bridge \"%s\"", veth1, netdev->link);
177 }
178
179 err = lxc_netdev_up(veth1);
180 if (err) {
181 errno = -err;
182 SYSERROR("Failed to set \"%s\" up", veth1);
183 goto out_delete;
184 }
185
186 if (netdev->upscript) {
187 char *argv[] = {
188 "veth",
189 netdev->link,
190 veth1,
191 NULL,
192 };
193
194 err = run_script_argv(handler->name,
195 handler->conf->hooks_version, "net",
196 netdev->upscript, "up", argv);
197 if (err < 0)
198 goto out_delete;
199 }
200
201 DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1, veth2,
202 netdev->ifindex);
203
204 return 0;
205
206 out_delete:
207 if (netdev->ifindex != 0)
208 lxc_netdev_delete_by_name(veth1);
209 return -1;
210 }
211
212 static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
213 {
214 char peerbuf[IFNAMSIZ], *peer;
215 int err;
216
217 if (netdev->link[0] == '\0') {
218 ERROR("No link for macvlan network device specified");
219 return -1;
220 }
221
222 err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
223 if (err < 0 || (size_t)err >= sizeof(peerbuf))
224 return -1;
225
226 peer = lxc_mkifname(peerbuf);
227 if (!peer)
228 return -1;
229
230 err = lxc_macvlan_create(netdev->link, peer,
231 netdev->priv.macvlan_attr.mode);
232 if (err) {
233 errno = -err;
234 SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
235 peer, netdev->link);
236 goto on_error;
237 }
238
239 netdev->ifindex = if_nametoindex(peer);
240 if (!netdev->ifindex) {
241 ERROR("Failed to retrieve ifindex for \"%s\"", peer);
242 goto on_error;
243 }
244
245 if (netdev->upscript) {
246 char *argv[] = {
247 "macvlan",
248 netdev->link,
249 NULL,
250 };
251
252 err = run_script_argv(handler->name,
253 handler->conf->hooks_version, "net",
254 netdev->upscript, "up", argv);
255 if (err < 0)
256 goto on_error;
257 }
258
259 DEBUG("Instantiated macvlan \"%s\" with ifindex is %d and mode %d",
260 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
261
262 return 0;
263
264 on_error:
265 lxc_netdev_delete_by_name(peer);
266 return -1;
267 }
268
269 static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
270 {
271 char peer[IFNAMSIZ];
272 int err;
273 static uint16_t vlan_cntr = 0;
274 unsigned int mtu = 0;
275
276 if (netdev->link[0] == '\0') {
277 ERROR("No link for vlan network device specified");
278 return -1;
279 }
280
281 err = snprintf(peer, sizeof(peer), "vlan%d-%d", netdev->priv.vlan_attr.vid, vlan_cntr++);
282 if (err < 0 || (size_t)err >= sizeof(peer))
283 return -1;
284
285 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
286 if (err) {
287 errno = -err;
288 SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
289 peer, netdev->link);
290 return -1;
291 }
292
293 netdev->ifindex = if_nametoindex(peer);
294 if (!netdev->ifindex) {
295 ERROR("Failed to retrieve ifindex for \"%s\"", peer);
296 lxc_netdev_delete_by_name(peer);
297 return -1;
298 }
299
300 DEBUG("Instantiated vlan \"%s\" with ifindex is \"%d\" (vlan1000)",
301 peer, netdev->ifindex);
302 if (netdev->mtu) {
303 if (lxc_safe_uint(netdev->mtu, &mtu) < 0) {
304 ERROR("Failed to retrieve mtu from \"%d\"/\"%s\".",
305 netdev->ifindex,
306 netdev->name[0] != '\0' ? netdev->name : "(null)");
307 return -1;
308 }
309
310 err = lxc_netdev_set_mtu(peer, mtu);
311 if (err) {
312 errno = -err;
313 SYSERROR("Failed to set mtu \"%s\" for \"%s\"",
314 netdev->mtu, peer);
315 lxc_netdev_delete_by_name(peer);
316 return -1;
317 }
318 }
319
320 return 0;
321 }
322
323 static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
324 {
325 int ret;
326 char *argv[] = {
327 "phys",
328 netdev->link,
329 NULL,
330 };
331
332 if (netdev->link[0] == '\0') {
333 ERROR("No link for physical interface specified");
334 return -1;
335 }
336
337 /* Note that we're retrieving the container's ifindex in the host's
338 * network namespace because we need it to move the device from the
339 * host's network namespace to the container's network namespace later
340 * on.
341 * Note that netdev->link will contain the name of the physical network
342 * device in the host's namespace.
343 */
344 netdev->ifindex = if_nametoindex(netdev->link);
345 if (!netdev->ifindex) {
346 ERROR("Failed to retrieve ifindex for \"%s\"", netdev->link);
347 return -1;
348 }
349
350 /* Store the ifindex of the host's network device in the host's
351 * namespace.
352 */
353 netdev->priv.phys_attr.ifindex = netdev->ifindex;
354
355 if (!netdev->upscript)
356 return 0;
357
358 ret = run_script_argv(handler->name, handler->conf->hooks_version,
359 "net", netdev->upscript, "up", argv);
360 if (ret < 0)
361 return -1;
362
363 return 0;
364 }
365
366 static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
367 {
368 int ret;
369 char *argv[] = {
370 "empty",
371 NULL,
372 };
373
374 netdev->ifindex = 0;
375 if (!netdev->upscript)
376 return 0;
377
378 ret = run_script_argv(handler->name, handler->conf->hooks_version,
379 "net", netdev->upscript, "up", argv);
380 if (ret < 0)
381 return -1;
382
383 return 0;
384 }
385
386 static int instantiate_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
387 {
388 netdev->ifindex = 0;
389 return 0;
390 }
391
392 static instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
393 [LXC_NET_VETH] = instantiate_veth,
394 [LXC_NET_MACVLAN] = instantiate_macvlan,
395 [LXC_NET_VLAN] = instantiate_vlan,
396 [LXC_NET_PHYS] = instantiate_phys,
397 [LXC_NET_EMPTY] = instantiate_empty,
398 [LXC_NET_NONE] = instantiate_none,
399 };
400
401 static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
402 {
403 int ret;
404 char *argv[] = {
405 "veth",
406 netdev->link,
407 NULL,
408 NULL,
409 };
410
411 if (!netdev->downscript)
412 return 0;
413
414 if (netdev->priv.veth_attr.pair[0] != '\0')
415 argv[2] = netdev->priv.veth_attr.pair;
416 else
417 argv[2] = netdev->priv.veth_attr.veth1;
418
419 ret = run_script_argv(handler->name,
420 handler->conf->hooks_version, "net",
421 netdev->downscript, "down", argv);
422 if (ret < 0)
423 return -1;
424
425 return 0;
426 }
427
428 static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
429 {
430 int ret;
431 char *argv[] = {
432 "macvlan",
433 netdev->link,
434 NULL,
435 };
436
437 if (!netdev->downscript)
438 return 0;
439
440 ret = run_script_argv(handler->name, handler->conf->hooks_version,
441 "net", netdev->downscript, "down", argv);
442 if (ret < 0)
443 return -1;
444
445 return 0;
446 }
447
448 static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
449 {
450 return 0;
451 }
452
453 static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
454 {
455 int ret;
456 char *argv[] = {
457 "phys",
458 netdev->link,
459 NULL,
460 };
461
462 if (!netdev->downscript)
463 return 0;
464
465 ret = run_script_argv(handler->name, handler->conf->hooks_version,
466 "net", netdev->downscript, "down", argv);
467 if (ret < 0)
468 return -1;
469
470 return 0;
471 }
472
473 static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
474 {
475 int ret;
476 char *argv[] = {
477 "empty",
478 NULL,
479 };
480
481 if (!netdev->downscript)
482 return 0;
483
484 ret = run_script_argv(handler->name, handler->conf->hooks_version,
485 "net", netdev->downscript, "down", argv);
486 if (ret < 0)
487 return -1;
488
489 return 0;
490 }
491
492 static int shutdown_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
493 {
494 return 0;
495 }
496
497 static instantiate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
498 [LXC_NET_VETH] = shutdown_veth,
499 [LXC_NET_MACVLAN] = shutdown_macvlan,
500 [LXC_NET_VLAN] = shutdown_vlan,
501 [LXC_NET_PHYS] = shutdown_phys,
502 [LXC_NET_EMPTY] = shutdown_empty,
503 [LXC_NET_NONE] = shutdown_none,
504 };
505
506 int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char *ifname)
507 {
508 int err;
509 struct nl_handler nlh;
510 struct ifinfomsg *ifi;
511 struct nlmsg *nlmsg = NULL;
512
513 err = netlink_open(&nlh, NETLINK_ROUTE);
514 if (err)
515 return err;
516
517 err = -ENOMEM;
518 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
519 if (!nlmsg)
520 goto out;
521
522 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
523 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
524
525 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
526 if (!ifi)
527 goto out;
528 ifi->ifi_family = AF_UNSPEC;
529 ifi->ifi_index = ifindex;
530
531 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
532 goto out;
533
534 if (ifname != NULL) {
535 if (nla_put_string(nlmsg, IFLA_IFNAME, ifname))
536 goto out;
537 }
538
539 err = netlink_transaction(&nlh, nlmsg, nlmsg);
540 out:
541 netlink_close(&nlh);
542 nlmsg_free(nlmsg);
543 return err;
544 }
545
546 /* If we are asked to move a wireless interface, then we must actually move its
547 * phyN device. Detect that condition and return the physname here. The physname
548 * will be passed to lxc_netdev_move_wlan() which will free it when done.
549 */
550 #define PHYSNAME "/sys/class/net/%s/phy80211/name"
551 static char *is_wlan(const char *ifname)
552 {
553 int i, ret;
554 long physlen;
555 size_t len;
556 char *path;
557 FILE *f;
558 char *physname = NULL;
559
560 len = strlen(ifname) + strlen(PHYSNAME) - 1;
561 path = alloca(len + 1);
562 ret = snprintf(path, len, PHYSNAME, ifname);
563 if (ret < 0 || (size_t)ret >= len)
564 goto bad;
565
566 f = fopen(path, "r");
567 if (!f)
568 goto bad;
569
570 /* Feh - sb.st_size is always 4096. */
571 fseek(f, 0, SEEK_END);
572 physlen = ftell(f);
573 fseek(f, 0, SEEK_SET);
574 if (physlen < 0) {
575 fclose(f);
576 goto bad;
577 }
578
579 physname = malloc(physlen + 1);
580 if (!physname) {
581 fclose(f);
582 goto bad;
583 }
584
585 memset(physname, 0, physlen + 1);
586 ret = fread(physname, 1, physlen, f);
587 fclose(f);
588 if (ret < 0)
589 goto bad;
590
591 for (i = 0; i < physlen; i++) {
592 if (physname[i] == '\n')
593 physname[i] = '\0';
594
595 if (physname[i] == '\0')
596 break;
597 }
598
599 return physname;
600
601 bad:
602 free(physname);
603 return NULL;
604 }
605
606 static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
607 const char *new)
608 {
609 pid_t fpid;
610
611 fpid = fork();
612 if (fpid < 0)
613 return -1;
614
615 if (fpid != 0)
616 return wait_for_pid(fpid);
617
618 if (!switch_to_ns(pid, "net"))
619 return -1;
620
621 _exit(lxc_netdev_rename_by_name(old, new));
622 }
623
624 static int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
625 const char *newname)
626 {
627 char *cmd;
628 pid_t fpid;
629 int err = -1;
630
631 /* Move phyN into the container. TODO - do this using netlink.
632 * However, IIUC this involves a bit more complicated work to talk to
633 * the 80211 module, so for now just call out to iw.
634 */
635 cmd = on_path("iw", NULL);
636 if (!cmd)
637 goto out1;
638 free(cmd);
639
640 fpid = fork();
641 if (fpid < 0)
642 goto out1;
643
644 if (fpid == 0) {
645 char pidstr[30];
646 sprintf(pidstr, "%d", pid);
647 execlp("iw", "iw", "phy", physname, "set", "netns", pidstr,
648 (char *)NULL);
649 _exit(EXIT_FAILURE);
650 }
651
652 if (wait_for_pid(fpid))
653 goto out1;
654
655 err = 0;
656 if (newname)
657 err = lxc_netdev_rename_by_name_in_netns(pid, ifname, newname);
658
659 out1:
660 free(physname);
661 return err;
662 }
663
664 int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
665 {
666 int index;
667 char *physname;
668
669 if (!ifname)
670 return -EINVAL;
671
672 index = if_nametoindex(ifname);
673 if (!index)
674 return -EINVAL;
675
676 physname = is_wlan(ifname);
677 if (physname)
678 return lxc_netdev_move_wlan(physname, ifname, pid, newname);
679
680 return lxc_netdev_move_by_index(index, pid, newname);
681 }
682
683 int lxc_netdev_delete_by_index(int ifindex)
684 {
685 int err;
686 struct ifinfomsg *ifi;
687 struct nl_handler nlh;
688 struct nlmsg *answer = NULL, *nlmsg = NULL;
689
690 err = netlink_open(&nlh, NETLINK_ROUTE);
691 if (err)
692 return err;
693
694 err = -ENOMEM;
695 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
696 if (!nlmsg)
697 goto out;
698
699 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
700 if (!answer)
701 goto out;
702
703 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
704 nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
705
706 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
707 if (!ifi)
708 goto out;
709 ifi->ifi_family = AF_UNSPEC;
710 ifi->ifi_index = ifindex;
711
712 err = netlink_transaction(&nlh, nlmsg, answer);
713 out:
714 netlink_close(&nlh);
715 nlmsg_free(answer);
716 nlmsg_free(nlmsg);
717 return err;
718 }
719
720 int lxc_netdev_delete_by_name(const char *name)
721 {
722 int index;
723
724 index = if_nametoindex(name);
725 if (!index)
726 return -EINVAL;
727
728 return lxc_netdev_delete_by_index(index);
729 }
730
731 int lxc_netdev_rename_by_index(int ifindex, const char *newname)
732 {
733 int err, len;
734 struct ifinfomsg *ifi;
735 struct nl_handler nlh;
736 struct nlmsg *answer = NULL, *nlmsg = NULL;
737
738 err = netlink_open(&nlh, NETLINK_ROUTE);
739 if (err)
740 return err;
741
742 len = strlen(newname);
743 if (len == 1 || len >= IFNAMSIZ)
744 goto out;
745
746 err = -ENOMEM;
747 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
748 if (!nlmsg)
749 goto out;
750
751 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
752 if (!answer)
753 goto out;
754
755 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
756 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
757
758 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
759 if (!ifi)
760 goto out;
761 ifi->ifi_family = AF_UNSPEC;
762 ifi->ifi_index = ifindex;
763
764 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
765 goto out;
766
767 err = netlink_transaction(&nlh, nlmsg, answer);
768 out:
769 netlink_close(&nlh);
770 nlmsg_free(answer);
771 nlmsg_free(nlmsg);
772 return err;
773 }
774
775 int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
776 {
777 int len, index;
778
779 len = strlen(oldname);
780 if (len == 1 || len >= IFNAMSIZ)
781 return -EINVAL;
782
783 index = if_nametoindex(oldname);
784 if (!index)
785 return -EINVAL;
786
787 return lxc_netdev_rename_by_index(index, newname);
788 }
789
790 int netdev_set_flag(const char *name, int flag)
791 {
792 int err, index, len;
793 struct ifinfomsg *ifi;
794 struct nl_handler nlh;
795 struct nlmsg *answer = NULL, *nlmsg = NULL;
796
797 err = netlink_open(&nlh, NETLINK_ROUTE);
798 if (err)
799 return err;
800
801 err = -EINVAL;
802 len = strlen(name);
803 if (len == 1 || len >= IFNAMSIZ)
804 goto out;
805
806 err = -ENOMEM;
807 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
808 if (!nlmsg)
809 goto out;
810
811 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
812 if (!answer)
813 goto out;
814
815 err = -EINVAL;
816 index = if_nametoindex(name);
817 if (!index)
818 goto out;
819
820 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
821 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
822
823 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
824 if (!ifi) {
825 err = -ENOMEM;
826 goto out;
827 }
828 ifi->ifi_family = AF_UNSPEC;
829 ifi->ifi_index = index;
830 ifi->ifi_change |= IFF_UP;
831 ifi->ifi_flags |= flag;
832
833 err = netlink_transaction(&nlh, nlmsg, answer);
834 out:
835 netlink_close(&nlh);
836 nlmsg_free(nlmsg);
837 nlmsg_free(answer);
838 return err;
839 }
840
841 int netdev_get_flag(const char *name, int *flag)
842 {
843 int err, index, len;
844 struct ifinfomsg *ifi;
845 struct nl_handler nlh;
846 struct nlmsg *answer = NULL, *nlmsg = NULL;
847
848 if (!name)
849 return -EINVAL;
850
851 err = netlink_open(&nlh, NETLINK_ROUTE);
852 if (err)
853 return err;
854
855 err = -EINVAL;
856 len = strlen(name);
857 if (len == 1 || len >= IFNAMSIZ)
858 goto out;
859
860 err = -ENOMEM;
861 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
862 if (!nlmsg)
863 goto out;
864
865 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
866 if (!answer)
867 goto out;
868
869 err = -EINVAL;
870 index = if_nametoindex(name);
871 if (!index)
872 goto out;
873
874 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
875 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
876
877 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
878 if (!ifi) {
879 err = -ENOMEM;
880 goto out;
881 }
882 ifi->ifi_family = AF_UNSPEC;
883 ifi->ifi_index = index;
884
885 err = netlink_transaction(&nlh, nlmsg, answer);
886 if (err)
887 goto out;
888
889 ifi = NLMSG_DATA(answer->nlmsghdr);
890
891 *flag = ifi->ifi_flags;
892 out:
893 netlink_close(&nlh);
894 nlmsg_free(nlmsg);
895 nlmsg_free(answer);
896 return err;
897 }
898
899 /*
900 * \brief Check a interface is up or not.
901 *
902 * \param name: name for the interface.
903 *
904 * \return int.
905 * 0 means interface is down.
906 * 1 means interface is up.
907 * Others means error happened, and ret-value is the error number.
908 */
909 int lxc_netdev_isup(const char *name)
910 {
911 int err, flag;
912
913 err = netdev_get_flag(name, &flag);
914 if (err)
915 return err;
916
917 if (flag & IFF_UP)
918 return 1;
919
920 return 0;
921 }
922
923 int netdev_get_mtu(int ifindex)
924 {
925 int answer_len, err, res;
926 struct nl_handler nlh;
927 struct ifinfomsg *ifi;
928 struct nlmsghdr *msg;
929 int readmore = 0, recv_len = 0;
930 struct nlmsg *answer = NULL, *nlmsg = NULL;
931
932 err = netlink_open(&nlh, NETLINK_ROUTE);
933 if (err)
934 return err;
935
936 err = -ENOMEM;
937 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
938 if (!nlmsg)
939 goto out;
940
941 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
942 if (!answer)
943 goto out;
944
945 /* Save the answer buffer length, since it will be overwritten
946 * on the first receive (and we might need to receive more than
947 * once.
948 */
949 answer_len = answer->nlmsghdr->nlmsg_len;
950
951 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
952 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
953
954 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
955 if (!ifi)
956 goto out;
957 ifi->ifi_family = AF_UNSPEC;
958
959 /* Send the request for addresses, which returns all addresses
960 * on all interfaces. */
961 err = netlink_send(&nlh, nlmsg);
962 if (err < 0)
963 goto out;
964
965 #pragma GCC diagnostic push
966 #pragma GCC diagnostic ignored "-Wcast-align"
967
968 do {
969 /* Restore the answer buffer length, it might have been
970 * overwritten by a previous receive.
971 */
972 answer->nlmsghdr->nlmsg_len = answer_len;
973
974 /* Get the (next) batch of reply messages */
975 err = netlink_rcv(&nlh, answer);
976 if (err < 0)
977 goto out;
978
979 recv_len = err;
980
981 /* Satisfy the typing for the netlink macros */
982 msg = answer->nlmsghdr;
983
984 while (NLMSG_OK(msg, recv_len)) {
985
986 /* Stop reading if we see an error message */
987 if (msg->nlmsg_type == NLMSG_ERROR) {
988 struct nlmsgerr *errmsg =
989 (struct nlmsgerr *)NLMSG_DATA(msg);
990 err = errmsg->error;
991 goto out;
992 }
993
994 /* Stop reading if we see a NLMSG_DONE message */
995 if (msg->nlmsg_type == NLMSG_DONE) {
996 readmore = 0;
997 break;
998 }
999
1000 ifi = NLMSG_DATA(msg);
1001 if (ifi->ifi_index == ifindex) {
1002 struct rtattr *rta = IFLA_RTA(ifi);
1003 int attr_len =
1004 msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
1005 res = 0;
1006 while (RTA_OK(rta, attr_len)) {
1007 /* Found a local address for the
1008 * requested interface, return it.
1009 */
1010 if (rta->rta_type == IFLA_MTU) {
1011 memcpy(&res, RTA_DATA(rta),
1012 sizeof(int));
1013 err = res;
1014 goto out;
1015 }
1016 rta = RTA_NEXT(rta, attr_len);
1017 }
1018 }
1019
1020 /* Keep reading more data from the socket if the last
1021 * message had the NLF_F_MULTI flag set.
1022 */
1023 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1024
1025 /* Look at the next message received in this buffer. */
1026 msg = NLMSG_NEXT(msg, recv_len);
1027 }
1028 } while (readmore);
1029
1030 #pragma GCC diagnostic pop
1031
1032 /* If we end up here, we didn't find any result, so signal an error. */
1033 err = -1;
1034
1035 out:
1036 netlink_close(&nlh);
1037 nlmsg_free(answer);
1038 nlmsg_free(nlmsg);
1039 return err;
1040 }
1041
1042 int lxc_netdev_set_mtu(const char *name, int mtu)
1043 {
1044 int err, index, len;
1045 struct ifinfomsg *ifi;
1046 struct nl_handler nlh;
1047 struct nlmsg *answer = NULL, *nlmsg = NULL;
1048
1049 err = netlink_open(&nlh, NETLINK_ROUTE);
1050 if (err)
1051 return err;
1052
1053 err = -EINVAL;
1054 len = strlen(name);
1055 if (len == 1 || len >= IFNAMSIZ)
1056 goto out;
1057
1058 err = -ENOMEM;
1059 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1060 if (!nlmsg)
1061 goto out;
1062
1063 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1064 if (!answer)
1065 goto out;
1066
1067 err = -EINVAL;
1068 index = if_nametoindex(name);
1069 if (!index)
1070 goto out;
1071
1072 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1073 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1074
1075 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1076 if (!ifi) {
1077 err = -ENOMEM;
1078 goto out;
1079 }
1080 ifi->ifi_family = AF_UNSPEC;
1081 ifi->ifi_index = index;
1082
1083 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
1084 goto out;
1085
1086 err = netlink_transaction(&nlh, nlmsg, answer);
1087 out:
1088 netlink_close(&nlh);
1089 nlmsg_free(nlmsg);
1090 nlmsg_free(answer);
1091 return err;
1092 }
1093
1094 int lxc_netdev_up(const char *name)
1095 {
1096 return netdev_set_flag(name, IFF_UP);
1097 }
1098
1099 int lxc_netdev_down(const char *name)
1100 {
1101 return netdev_set_flag(name, 0);
1102 }
1103
1104 int lxc_veth_create(const char *name1, const char *name2)
1105 {
1106 int err, len;
1107 struct ifinfomsg *ifi;
1108 struct nl_handler nlh;
1109 struct rtattr *nest1, *nest2, *nest3;
1110 struct nlmsg *answer = NULL, *nlmsg = NULL;
1111
1112 err = netlink_open(&nlh, NETLINK_ROUTE);
1113 if (err)
1114 return err;
1115
1116 err = -EINVAL;
1117 len = strlen(name1);
1118 if (len == 1 || len >= IFNAMSIZ)
1119 goto out;
1120
1121 len = strlen(name2);
1122 if (len == 1 || len >= IFNAMSIZ)
1123 goto out;
1124
1125 err = -ENOMEM;
1126 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1127 if (!nlmsg)
1128 goto out;
1129
1130 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1131 if (!answer)
1132 goto out;
1133
1134 nlmsg->nlmsghdr->nlmsg_flags =
1135 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
1136 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1137
1138 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1139 if (!ifi)
1140 goto out;
1141 ifi->ifi_family = AF_UNSPEC;
1142
1143 err = -EINVAL;
1144 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
1145 if (!nest1)
1146 goto out;
1147
1148 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
1149 goto out;
1150
1151 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1152 if (!nest2)
1153 goto out;
1154
1155 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
1156 if (!nest3)
1157 goto out;
1158
1159 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1160 if (!ifi) {
1161 err = -ENOMEM;
1162 goto out;
1163 }
1164
1165 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
1166 goto out;
1167
1168 nla_end_nested(nlmsg, nest3);
1169 nla_end_nested(nlmsg, nest2);
1170 nla_end_nested(nlmsg, nest1);
1171
1172 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
1173 goto out;
1174
1175 err = netlink_transaction(&nlh, nlmsg, answer);
1176 out:
1177 netlink_close(&nlh);
1178 nlmsg_free(answer);
1179 nlmsg_free(nlmsg);
1180 return err;
1181 }
1182
1183 /* TODO: merge with lxc_macvlan_create */
1184 int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
1185 {
1186 int err, len, lindex;
1187 struct ifinfomsg *ifi;
1188 struct nl_handler nlh;
1189 struct rtattr *nest, *nest2;
1190 struct nlmsg *answer = NULL, *nlmsg = NULL;
1191
1192 err = netlink_open(&nlh, NETLINK_ROUTE);
1193 if (err)
1194 return err;
1195
1196 err = -EINVAL;
1197 len = strlen(master);
1198 if (len == 1 || len >= IFNAMSIZ)
1199 goto err3;
1200
1201 len = strlen(name);
1202 if (len == 1 || len >= IFNAMSIZ)
1203 goto err3;
1204
1205 err = -ENOMEM;
1206 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1207 if (!nlmsg)
1208 goto err3;
1209
1210 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1211 if (!answer)
1212 goto err2;
1213
1214 err = -EINVAL;
1215 lindex = if_nametoindex(master);
1216 if (!lindex)
1217 goto err1;
1218
1219 nlmsg->nlmsghdr->nlmsg_flags =
1220 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
1221 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1222
1223 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1224 if (!ifi) {
1225 err = -ENOMEM;
1226 goto err1;
1227 }
1228 ifi->ifi_family = AF_UNSPEC;
1229
1230 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
1231 if (!nest)
1232 goto err1;
1233
1234 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
1235 goto err1;
1236
1237 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1238 if (!nest2)
1239 goto err1;
1240
1241 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
1242 goto err1;
1243
1244 nla_end_nested(nlmsg, nest2);
1245 nla_end_nested(nlmsg, nest);
1246
1247 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
1248 goto err1;
1249
1250 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
1251 goto err1;
1252
1253 err = netlink_transaction(&nlh, nlmsg, answer);
1254 err1:
1255 nlmsg_free(answer);
1256 err2:
1257 nlmsg_free(nlmsg);
1258 err3:
1259 netlink_close(&nlh);
1260 return err;
1261 }
1262
1263 int lxc_macvlan_create(const char *master, const char *name, int mode)
1264 {
1265 int err, index, len;
1266 struct ifinfomsg *ifi;
1267 struct nl_handler nlh;
1268 struct rtattr *nest, *nest2;
1269 struct nlmsg *answer = NULL, *nlmsg = NULL;
1270
1271 err = netlink_open(&nlh, NETLINK_ROUTE);
1272 if (err)
1273 return err;
1274
1275 err = -EINVAL;
1276 len = strlen(master);
1277 if (len == 1 || len >= IFNAMSIZ)
1278 goto out;
1279
1280 len = strlen(name);
1281 if (len == 1 || len >= IFNAMSIZ)
1282 goto out;
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 err = -EINVAL;
1294 index = if_nametoindex(master);
1295 if (!index)
1296 goto out;
1297
1298 nlmsg->nlmsghdr->nlmsg_flags =
1299 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
1300 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1301
1302 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1303 if (!ifi) {
1304 err = -ENOMEM;
1305 goto out;
1306 }
1307 ifi->ifi_family = AF_UNSPEC;
1308
1309 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
1310 if (!nest)
1311 goto out;
1312
1313 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
1314 goto out;
1315
1316 if (mode) {
1317 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1318 if (!nest2)
1319 goto out;
1320
1321 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
1322 goto out;
1323
1324 nla_end_nested(nlmsg, nest2);
1325 }
1326
1327 nla_end_nested(nlmsg, nest);
1328
1329 if (nla_put_u32(nlmsg, IFLA_LINK, index))
1330 goto out;
1331
1332 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
1333 goto out;
1334
1335 err = netlink_transaction(&nlh, nlmsg, answer);
1336 out:
1337 netlink_close(&nlh);
1338 nlmsg_free(answer);
1339 nlmsg_free(nlmsg);
1340 return err;
1341 }
1342
1343 static int proc_sys_net_write(const char *path, const char *value)
1344 {
1345 int fd;
1346 int err = 0;
1347
1348 fd = open(path, O_WRONLY);
1349 if (fd < 0)
1350 return -errno;
1351
1352 if (lxc_write_nointr(fd, value, strlen(value)) < 0)
1353 err = -errno;
1354
1355 close(fd);
1356 return err;
1357 }
1358
1359 static int neigh_proxy_set(const char *ifname, int family, int flag)
1360 {
1361 int ret;
1362 char path[MAXPATHLEN];
1363
1364 if (family != AF_INET && family != AF_INET6)
1365 return -EINVAL;
1366
1367 ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
1368 family == AF_INET ? "ipv4" : "ipv6", ifname,
1369 family == AF_INET ? "proxy_arp" : "proxy_ndp");
1370 if (ret < 0 || (size_t)ret >= MAXPATHLEN)
1371 return -E2BIG;
1372
1373 return proc_sys_net_write(path, flag ? "1" : "0");
1374 }
1375
1376 int lxc_neigh_proxy_on(const char *name, int family)
1377 {
1378 return neigh_proxy_set(name, family, 1);
1379 }
1380
1381 int lxc_neigh_proxy_off(const char *name, int family)
1382 {
1383 return neigh_proxy_set(name, family, 0);
1384 }
1385
1386 int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
1387 {
1388 int i = 0;
1389 unsigned val;
1390 char c;
1391 unsigned char *data;
1392
1393 sockaddr->sa_family = ARPHRD_ETHER;
1394 data = (unsigned char *)sockaddr->sa_data;
1395
1396 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
1397 c = *macaddr++;
1398 if (isdigit(c))
1399 val = c - '0';
1400 else if (c >= 'a' && c <= 'f')
1401 val = c - 'a' + 10;
1402 else if (c >= 'A' && c <= 'F')
1403 val = c - 'A' + 10;
1404 else
1405 return -EINVAL;
1406
1407 val <<= 4;
1408 c = *macaddr;
1409 if (isdigit(c))
1410 val |= c - '0';
1411 else if (c >= 'a' && c <= 'f')
1412 val |= c - 'a' + 10;
1413 else if (c >= 'A' && c <= 'F')
1414 val |= c - 'A' + 10;
1415 else if (c == ':' || c == 0)
1416 val >>= 4;
1417 else
1418 return -EINVAL;
1419 if (c != 0)
1420 macaddr++;
1421 *data++ = (unsigned char)(val & 0377);
1422 i++;
1423
1424 if (*macaddr == ':')
1425 macaddr++;
1426 }
1427
1428 return 0;
1429 }
1430
1431 static int ip_addr_add(int family, int ifindex, void *addr, void *bcast,
1432 void *acast, int prefix)
1433 {
1434 int addrlen, err;
1435 struct ifaddrmsg *ifa;
1436 struct nl_handler nlh;
1437 struct nlmsg *answer = NULL, *nlmsg = NULL;
1438
1439 addrlen = family == AF_INET ? sizeof(struct in_addr)
1440 : sizeof(struct in6_addr);
1441
1442 err = netlink_open(&nlh, NETLINK_ROUTE);
1443 if (err)
1444 return err;
1445
1446 err = -ENOMEM;
1447 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1448 if (!nlmsg)
1449 goto out;
1450
1451 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1452 if (!answer)
1453 goto out;
1454
1455 nlmsg->nlmsghdr->nlmsg_flags =
1456 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
1457 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
1458
1459 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
1460 if (!ifa)
1461 goto out;
1462 ifa->ifa_prefixlen = prefix;
1463 ifa->ifa_index = ifindex;
1464 ifa->ifa_family = family;
1465 ifa->ifa_scope = 0;
1466
1467 err = -EINVAL;
1468 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
1469 goto out;
1470
1471 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
1472 goto out;
1473
1474 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
1475 goto out;
1476
1477 /* TODO: multicast, anycast with ipv6 */
1478 err = -EPROTONOSUPPORT;
1479 if (family == AF_INET6 &&
1480 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
1481 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
1482 goto out;
1483
1484 err = netlink_transaction(&nlh, nlmsg, answer);
1485 out:
1486 netlink_close(&nlh);
1487 nlmsg_free(answer);
1488 nlmsg_free(nlmsg);
1489 return err;
1490 }
1491
1492 int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
1493 struct in6_addr *mcast, struct in6_addr *acast,
1494 int prefix)
1495 {
1496 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
1497 }
1498
1499 int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, struct in_addr *bcast,
1500 int prefix)
1501 {
1502 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
1503 }
1504
1505 /* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
1506 * the given RTM_NEWADDR message. Allocates memory for the address and stores
1507 * that pointer in *res (so res should be an in_addr** or in6_addr**).
1508 */
1509 #pragma GCC diagnostic push
1510 #pragma GCC diagnostic ignored "-Wcast-align"
1511
1512 static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res)
1513 {
1514 int addrlen;
1515 struct ifaddrmsg *ifa = NLMSG_DATA(msg);
1516 struct rtattr *rta = IFA_RTA(ifa);
1517 int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
1518
1519 if (ifa->ifa_family != family)
1520 return 0;
1521
1522 addrlen = family == AF_INET ? sizeof(struct in_addr)
1523 : sizeof(struct in6_addr);
1524
1525 /* Loop over the rtattr's in this message */
1526 while (RTA_OK(rta, attr_len)) {
1527 /* Found a local address for the requested interface,
1528 * return it.
1529 */
1530 if (rta->rta_type == IFA_LOCAL ||
1531 rta->rta_type == IFA_ADDRESS) {
1532 /* Sanity check. The family check above should make sure
1533 * the address length is correct, but check here just in
1534 * case.
1535 */
1536 if (RTA_PAYLOAD(rta) != addrlen)
1537 return -1;
1538
1539 /* We might have found an IFA_ADDRESS before, which we
1540 * now overwrite with an IFA_LOCAL.
1541 */
1542 if (!*res) {
1543 *res = malloc(addrlen);
1544 if (!*res)
1545 return -1;
1546 }
1547
1548 memcpy(*res, RTA_DATA(rta), addrlen);
1549 if (rta->rta_type == IFA_LOCAL)
1550 break;
1551 }
1552 rta = RTA_NEXT(rta, attr_len);
1553 }
1554 return 0;
1555 }
1556
1557 #pragma GCC diagnostic pop
1558
1559 static int ip_addr_get(int family, int ifindex, void **res)
1560 {
1561 int answer_len, err;
1562 struct ifaddrmsg *ifa;
1563 struct nl_handler nlh;
1564 struct nlmsghdr *msg;
1565 int readmore = 0, recv_len = 0;
1566 struct nlmsg *answer = NULL, *nlmsg = NULL;
1567
1568 err = netlink_open(&nlh, NETLINK_ROUTE);
1569 if (err)
1570 return err;
1571
1572 err = -ENOMEM;
1573 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1574 if (!nlmsg)
1575 goto out;
1576
1577 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1578 if (!answer)
1579 goto out;
1580
1581 /* Save the answer buffer length, since it will be overwritten on the
1582 * first receive (and we might need to receive more than once).
1583 */
1584 answer_len = answer->nlmsghdr->nlmsg_len;
1585
1586 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
1587 nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
1588
1589 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
1590 if (!ifa)
1591 goto out;
1592 ifa->ifa_family = family;
1593
1594 /* Send the request for addresses, which returns all addresses on all
1595 * interfaces.
1596 */
1597 err = netlink_send(&nlh, nlmsg);
1598 if (err < 0)
1599 goto out;
1600
1601 #pragma GCC diagnostic push
1602 #pragma GCC diagnostic ignored "-Wcast-align"
1603
1604 do {
1605 /* Restore the answer buffer length, it might have been
1606 * overwritten by a previous receive.
1607 */
1608 answer->nlmsghdr->nlmsg_len = answer_len;
1609
1610 /* Get the (next) batch of reply messages. */
1611 err = netlink_rcv(&nlh, answer);
1612 if (err < 0)
1613 goto out;
1614
1615 recv_len = err;
1616 err = 0;
1617
1618 /* Satisfy the typing for the netlink macros. */
1619 msg = answer->nlmsghdr;
1620
1621 while (NLMSG_OK(msg, recv_len)) {
1622 /* Stop reading if we see an error message. */
1623 if (msg->nlmsg_type == NLMSG_ERROR) {
1624 struct nlmsgerr *errmsg =
1625 (struct nlmsgerr *)NLMSG_DATA(msg);
1626 err = errmsg->error;
1627 goto out;
1628 }
1629
1630 /* Stop reading if we see a NLMSG_DONE message. */
1631 if (msg->nlmsg_type == NLMSG_DONE) {
1632 readmore = 0;
1633 break;
1634 }
1635
1636 if (msg->nlmsg_type != RTM_NEWADDR) {
1637 err = -1;
1638 goto out;
1639 }
1640
1641 ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
1642 if (ifa->ifa_index == ifindex) {
1643 if (ifa_get_local_ip(family, msg, res) < 0) {
1644 err = -1;
1645 goto out;
1646 }
1647
1648 /* Found a result, stop searching. */
1649 if (*res)
1650 goto out;
1651 }
1652
1653 /* Keep reading more data from the socket if the last
1654 * message had the NLF_F_MULTI flag set.
1655 */
1656 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1657
1658 /* Look at the next message received in this buffer. */
1659 msg = NLMSG_NEXT(msg, recv_len);
1660 }
1661 } while (readmore);
1662
1663 #pragma GCC diagnostic pop
1664
1665 /* If we end up here, we didn't find any result, so signal an
1666 * error.
1667 */
1668 err = -1;
1669
1670 out:
1671 netlink_close(&nlh);
1672 nlmsg_free(answer);
1673 nlmsg_free(nlmsg);
1674 return err;
1675 }
1676
1677 int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
1678 {
1679 return ip_addr_get(AF_INET6, ifindex, (void **)res);
1680 }
1681
1682 int lxc_ipv4_addr_get(int ifindex, struct in_addr **res)
1683 {
1684 return ip_addr_get(AF_INET, ifindex, (void **)res);
1685 }
1686
1687 static int ip_gateway_add(int family, int ifindex, void *gw)
1688 {
1689 int addrlen, err;
1690 struct nl_handler nlh;
1691 struct rtmsg *rt;
1692 struct nlmsg *answer = NULL, *nlmsg = NULL;
1693
1694 addrlen = family == AF_INET ? sizeof(struct in_addr)
1695 : sizeof(struct in6_addr);
1696
1697 err = netlink_open(&nlh, NETLINK_ROUTE);
1698 if (err)
1699 return err;
1700
1701 err = -ENOMEM;
1702 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1703 if (!nlmsg)
1704 goto out;
1705
1706 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1707 if (!answer)
1708 goto out;
1709
1710 nlmsg->nlmsghdr->nlmsg_flags =
1711 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
1712 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1713
1714 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
1715 if (!rt)
1716 goto out;
1717 rt->rtm_family = family;
1718 rt->rtm_table = RT_TABLE_MAIN;
1719 rt->rtm_scope = RT_SCOPE_UNIVERSE;
1720 rt->rtm_protocol = RTPROT_BOOT;
1721 rt->rtm_type = RTN_UNICAST;
1722 /* "default" destination */
1723 rt->rtm_dst_len = 0;
1724
1725 err = -EINVAL;
1726 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
1727 goto out;
1728
1729 /* Adding the interface index enables the use of link-local
1730 * addresses for the gateway.
1731 */
1732 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1733 goto out;
1734
1735 err = netlink_transaction(&nlh, nlmsg, answer);
1736 out:
1737 netlink_close(&nlh);
1738 nlmsg_free(answer);
1739 nlmsg_free(nlmsg);
1740 return err;
1741 }
1742
1743 int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
1744 {
1745 return ip_gateway_add(AF_INET, ifindex, gw);
1746 }
1747
1748 int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
1749 {
1750 return ip_gateway_add(AF_INET6, ifindex, gw);
1751 }
1752
1753 static int ip_route_dest_add(int family, int ifindex, void *dest)
1754 {
1755 int addrlen, err;
1756 struct nl_handler nlh;
1757 struct rtmsg *rt;
1758 struct nlmsg *answer = NULL, *nlmsg = NULL;
1759
1760 addrlen = family == AF_INET ? sizeof(struct in_addr)
1761 : sizeof(struct in6_addr);
1762
1763 err = netlink_open(&nlh, NETLINK_ROUTE);
1764 if (err)
1765 return err;
1766
1767 err = -ENOMEM;
1768 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1769 if (!nlmsg)
1770 goto out;
1771
1772 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
1773 if (!answer)
1774 goto out;
1775
1776 nlmsg->nlmsghdr->nlmsg_flags =
1777 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
1778 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1779
1780 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
1781 if (!rt)
1782 goto out;
1783 rt->rtm_family = family;
1784 rt->rtm_table = RT_TABLE_MAIN;
1785 rt->rtm_scope = RT_SCOPE_LINK;
1786 rt->rtm_protocol = RTPROT_BOOT;
1787 rt->rtm_type = RTN_UNICAST;
1788 rt->rtm_dst_len = addrlen * 8;
1789
1790 err = -EINVAL;
1791 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
1792 goto out;
1793 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1794 goto out;
1795 err = netlink_transaction(&nlh, nlmsg, answer);
1796 out:
1797 netlink_close(&nlh);
1798 nlmsg_free(answer);
1799 nlmsg_free(nlmsg);
1800 return err;
1801 }
1802
1803 int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
1804 {
1805 return ip_route_dest_add(AF_INET, ifindex, dest);
1806 }
1807
1808 int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
1809 {
1810 return ip_route_dest_add(AF_INET6, ifindex, dest);
1811 }
1812
1813 bool is_ovs_bridge(const char *bridge)
1814 {
1815 int ret;
1816 struct stat sb;
1817 char brdirname[22 + IFNAMSIZ + 1] = {0};
1818
1819 ret = snprintf(brdirname, 22 + IFNAMSIZ + 1, "/sys/class/net/%s/bridge",
1820 bridge);
1821 if (ret < 0 || (size_t)ret >= 22 + IFNAMSIZ + 1)
1822 return false;
1823
1824 ret = stat(brdirname, &sb);
1825 if (ret < 0 && errno == ENOENT)
1826 return true;
1827
1828 return false;
1829 }
1830
1831 struct ovs_veth_args {
1832 const char *bridge;
1833 const char *nic;
1834 };
1835
1836 /* Called from a background thread - when nic goes away, remove it from the
1837 * bridge.
1838 */
1839 static int lxc_ovs_delete_port_exec(void *data)
1840 {
1841 struct ovs_veth_args *args = data;
1842
1843 execlp("ovs-vsctl", "ovs-vsctl", "del-port", args->bridge, args->nic,
1844 (char *)NULL);
1845 return -1;
1846 }
1847
1848 int lxc_ovs_delete_port(const char *bridge, const char *nic)
1849 {
1850 int ret;
1851 char cmd_output[MAXPATHLEN];
1852 struct ovs_veth_args args;
1853
1854 args.bridge = bridge;
1855 args.nic = nic;
1856 ret = run_command(cmd_output, sizeof(cmd_output),
1857 lxc_ovs_delete_port_exec, (void *)&args);
1858 if (ret < 0) {
1859 ERROR("Failed to delete \"%s\" from openvswitch bridge \"%s\": "
1860 "%s", bridge, nic, cmd_output);
1861 return -1;
1862 }
1863
1864 return 0;
1865 }
1866
1867 static int lxc_ovs_attach_bridge_exec(void *data)
1868 {
1869 struct ovs_veth_args *args = data;
1870
1871 execlp("ovs-vsctl", "ovs-vsctl", "add-port", args->bridge, args->nic,
1872 (char *)NULL);
1873 return -1;
1874 }
1875
1876 static int lxc_ovs_attach_bridge(const char *bridge, const char *nic)
1877 {
1878 int ret;
1879 char cmd_output[MAXPATHLEN];
1880 struct ovs_veth_args args;
1881
1882 args.bridge = bridge;
1883 args.nic = nic;
1884 ret = run_command(cmd_output, sizeof(cmd_output),
1885 lxc_ovs_attach_bridge_exec, (void *)&args);
1886 if (ret < 0) {
1887 ERROR("Failed to attach \"%s\" to openvswitch bridge \"%s\": %s",
1888 bridge, nic, cmd_output);
1889 return -1;
1890 }
1891
1892 return 0;
1893 }
1894
1895 int lxc_bridge_attach(const char *bridge, const char *ifname)
1896 {
1897 int err, fd, index;
1898 size_t retlen;
1899 struct ifreq ifr;
1900
1901 if (strlen(ifname) >= IFNAMSIZ)
1902 return -EINVAL;
1903
1904 index = if_nametoindex(ifname);
1905 if (!index)
1906 return -EINVAL;
1907
1908 if (is_ovs_bridge(bridge))
1909 return lxc_ovs_attach_bridge(bridge, ifname);
1910
1911 fd = socket(AF_INET, SOCK_STREAM, 0);
1912 if (fd < 0)
1913 return -errno;
1914
1915 retlen = strlcpy(ifr.ifr_name, bridge, IFNAMSIZ);
1916 if (retlen >= IFNAMSIZ) {
1917 close(fd);
1918 return -E2BIG;
1919 }
1920
1921 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
1922 ifr.ifr_ifindex = index;
1923 err = ioctl(fd, SIOCBRADDIF, &ifr);
1924 close(fd);
1925 if (err)
1926 err = -errno;
1927
1928 return err;
1929 }
1930
1931 static const char *const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
1932 [LXC_NET_EMPTY] = "empty",
1933 [LXC_NET_VETH] = "veth",
1934 [LXC_NET_MACVLAN] = "macvlan",
1935 [LXC_NET_PHYS] = "phys",
1936 [LXC_NET_VLAN] = "vlan",
1937 [LXC_NET_NONE] = "none",
1938 };
1939
1940 const char *lxc_net_type_to_str(int type)
1941 {
1942 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
1943 return NULL;
1944
1945 return lxc_network_types[type];
1946 }
1947
1948 static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1949
1950 char *lxc_mkifname(char *template)
1951 {
1952 int ret;
1953 struct ifaddrs *ifa, *ifaddr;
1954 char name[IFNAMSIZ];
1955 bool exists = false;
1956 size_t i = 0;
1957 #ifdef HAVE_RAND_R
1958 unsigned int seed;
1959
1960 seed = randseed(false);
1961 #else
1962
1963 (void)randseed(true);
1964 #endif
1965
1966 if (strlen(template) >= IFNAMSIZ)
1967 return NULL;
1968
1969 /* Get all the network interfaces. */
1970 ret = getifaddrs(&ifaddr);
1971 if (ret < 0) {
1972 SYSERROR("Failed to get network interfaces");
1973 return NULL;
1974 }
1975
1976 /* Generate random names until we find one that doesn't exist. */
1977 while (true) {
1978 name[0] = '\0';
1979 (void)strlcpy(name, template, IFNAMSIZ);
1980
1981 exists = false;
1982
1983 for (i = 0; i < strlen(name); i++) {
1984 if (name[i] == 'X') {
1985 #ifdef HAVE_RAND_R
1986 name[i] = padchar[rand_r(&seed) % (strlen(padchar) - 1)];
1987 #else
1988 name[i] = padchar[rand() % (strlen(padchar) - 1)];
1989 #endif
1990 }
1991 }
1992
1993 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1994 if (!strcmp(ifa->ifa_name, name)) {
1995 exists = true;
1996 break;
1997 }
1998 }
1999
2000 if (!exists)
2001 break;
2002 }
2003
2004 freeifaddrs(ifaddr);
2005 (void)strlcpy(template, name, strlen(template) + 1);
2006
2007 return template;
2008 }
2009
2010 int setup_private_host_hw_addr(char *veth1)
2011 {
2012 int err, sockfd;
2013 struct ifreq ifr;
2014
2015 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2016 if (sockfd < 0)
2017 return -errno;
2018
2019 err = snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
2020 if (err < 0 || (size_t)err >= IFNAMSIZ) {
2021 close(sockfd);
2022 return -E2BIG;
2023 }
2024
2025 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
2026 if (err < 0) {
2027 close(sockfd);
2028 return -errno;
2029 }
2030
2031 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
2032 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
2033 close(sockfd);
2034 if (err < 0)
2035 return -errno;
2036
2037 return 0;
2038 }
2039
2040 int lxc_find_gateway_addresses(struct lxc_handler *handler)
2041 {
2042 struct lxc_list *network = &handler->conf->network;
2043 struct lxc_list *iterator;
2044 struct lxc_netdev *netdev;
2045 int link_index;
2046
2047 lxc_list_for_each(iterator, network) {
2048 netdev = iterator->elem;
2049
2050 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2051 continue;
2052
2053 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
2054 ERROR("Automatic gateway detection is only supported "
2055 "for veth and macvlan");
2056 return -1;
2057 }
2058
2059 if (netdev->link[0] == '\0') {
2060 ERROR("Automatic gateway detection needs a link interface");
2061 return -1;
2062 }
2063
2064 link_index = if_nametoindex(netdev->link);
2065 if (!link_index)
2066 return -EINVAL;
2067
2068 if (netdev->ipv4_gateway_auto) {
2069 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
2070 ERROR("Failed to automatically find ipv4 gateway "
2071 "address from link interface \"%s\"", netdev->link);
2072 return -1;
2073 }
2074 }
2075
2076 if (netdev->ipv6_gateway_auto) {
2077 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
2078 ERROR("Failed to automatically find ipv6 gateway "
2079 "address from link interface \"%s\"", netdev->link);
2080 return -1;
2081 }
2082 }
2083 }
2084
2085 return 0;
2086 }
2087
2088 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
2089 static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname,
2090 struct lxc_netdev *netdev, pid_t pid, unsigned int hooks_version)
2091 {
2092 int ret;
2093 pid_t child;
2094 int bytes, pipefd[2];
2095 char *token, *saveptr = NULL;
2096 char netdev_link[IFNAMSIZ];
2097 char buffer[MAXPATHLEN] = {0};
2098 size_t retlen;
2099
2100 if (netdev->type != LXC_NET_VETH) {
2101 ERROR("Network type %d not support for unprivileged use", netdev->type);
2102 return -1;
2103 }
2104
2105 ret = pipe(pipefd);
2106 if (ret < 0) {
2107 SYSERROR("Failed to create pipe");
2108 return -1;
2109 }
2110
2111 child = fork();
2112 if (child < 0) {
2113 SYSERROR("Failed to create new process");
2114 close(pipefd[0]);
2115 close(pipefd[1]);
2116 return -1;
2117 }
2118
2119 if (child == 0) {
2120 int ret;
2121 size_t retlen;
2122 char pidstr[INTTYPE_TO_STRLEN(pid_t)];
2123
2124 close(pipefd[0]);
2125
2126 ret = dup2(pipefd[1], STDOUT_FILENO);
2127 if (ret >= 0)
2128 ret = dup2(pipefd[1], STDERR_FILENO);
2129 close(pipefd[1]);
2130 if (ret < 0) {
2131 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2132 _exit(EXIT_FAILURE);
2133 }
2134
2135 if (netdev->link[0] != '\0')
2136 retlen = strlcpy(netdev_link, netdev->link, IFNAMSIZ);
2137 else
2138 retlen = strlcpy(netdev_link, "none", IFNAMSIZ);
2139 if (retlen >= IFNAMSIZ) {
2140 SYSERROR("Invalid network device name");
2141 _exit(EXIT_FAILURE);
2142 }
2143
2144 ret = snprintf(pidstr, sizeof(pidstr), "%d", pid);
2145 if (ret < 0 || ret >= sizeof(pidstr))
2146 _exit(EXIT_FAILURE);
2147 pidstr[sizeof(pidstr) - 1] = '\0';
2148
2149 INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath,
2150 lxcname, pidstr, netdev_link,
2151 netdev->name[0] != '\0' ? netdev->name : "(null)");
2152 if (netdev->name[0] != '\0')
2153 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "create",
2154 lxcpath, lxcname, pidstr, "veth", netdev_link,
2155 netdev->name, (char *)NULL);
2156 else
2157 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "create",
2158 lxcpath, lxcname, pidstr, "veth", netdev_link,
2159 (char *)NULL);
2160 SYSERROR("Failed to execute lxc-user-nic");
2161 _exit(EXIT_FAILURE);
2162 }
2163
2164 /* close the write-end of the pipe */
2165 close(pipefd[1]);
2166
2167 bytes = lxc_read_nointr(pipefd[0], &buffer, MAXPATHLEN);
2168 if (bytes < 0) {
2169 SYSERROR("Failed to read from pipe file descriptor");
2170 close(pipefd[0]);
2171 } else {
2172 buffer[bytes - 1] = '\0';
2173 }
2174
2175 ret = wait_for_pid(child);
2176 close(pipefd[0]);
2177 if (ret != 0 || bytes < 0) {
2178 ERROR("lxc-user-nic failed to configure requested network: %s",
2179 buffer[0] != '\0' ? buffer : "(null)");
2180 return -1;
2181 }
2182 TRACE("Received output \"%s\" from lxc-user-nic", buffer);
2183
2184 /* netdev->name */
2185 token = strtok_r(buffer, ":", &saveptr);
2186 if (!token) {
2187 ERROR("Failed to parse lxc-user-nic output");
2188 return -1;
2189 }
2190
2191 memset(netdev->name, 0, IFNAMSIZ);
2192 memcpy(netdev->name, token, IFNAMSIZ - 1);
2193
2194 /* netdev->ifindex */
2195 token = strtok_r(NULL, ":", &saveptr);
2196 if (!token) {
2197 ERROR("Failed to parse lxc-user-nic output");
2198 return -1;
2199 }
2200
2201 ret = lxc_safe_int(token, &netdev->ifindex);
2202 if (ret < 0) {
2203 errno = -ret;
2204 SYSERROR("Failed to convert string \"%s\" to integer", token);
2205 return -1;
2206 }
2207
2208 /* netdev->priv.veth_attr.veth1 */
2209 token = strtok_r(NULL, ":", &saveptr);
2210 if (!token) {
2211 ERROR("Failed to parse lxc-user-nic output");
2212 return -1;
2213 }
2214
2215 retlen = strlcpy(netdev->priv.veth_attr.veth1, token, IFNAMSIZ);
2216 if (retlen >= IFNAMSIZ) {
2217 ERROR("Host side veth device name returned by lxc-user-nic is "
2218 "too long");
2219 return -E2BIG;
2220 }
2221
2222 /* netdev->priv.veth_attr.ifindex */
2223 token = strtok_r(NULL, ":", &saveptr);
2224 if (!token) {
2225 ERROR("Failed to parse lxc-user-nic output");
2226 return -1;
2227 }
2228
2229 ret = lxc_safe_int(token, &netdev->priv.veth_attr.ifindex);
2230 if (ret < 0) {
2231 errno = -ret;
2232 SYSERROR("Failed to convert string \"%s\" to integer", token);
2233 return -1;
2234 }
2235
2236 if (netdev->upscript) {
2237 char *argv[] = {
2238 "veth",
2239 netdev->link,
2240 netdev->priv.veth_attr.veth1,
2241 NULL,
2242 };
2243
2244 ret = run_script_argv(lxcname,
2245 hooks_version, "net",
2246 netdev->upscript, "up", argv);
2247 if (ret < 0)
2248 return -1;
2249 }
2250
2251 return 0;
2252 }
2253
2254 static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcname,
2255 struct lxc_netdev *netdev,
2256 const char *netns_path)
2257 {
2258 int bytes, ret;
2259 pid_t child;
2260 int pipefd[2];
2261 char buffer[MAXPATHLEN] = {0};
2262
2263 if (netdev->type != LXC_NET_VETH) {
2264 ERROR("Network type %d not support for unprivileged use", netdev->type);
2265 return -1;
2266 }
2267
2268 ret = pipe(pipefd);
2269 if (ret < 0) {
2270 SYSERROR("Failed to create pipe");
2271 return -1;
2272 }
2273
2274 child = fork();
2275 if (child < 0) {
2276 SYSERROR("Failed to create new process");
2277 close(pipefd[0]);
2278 close(pipefd[1]);
2279 return -1;
2280 }
2281
2282 if (child == 0) {
2283 char *hostveth;
2284 int ret;
2285
2286 close(pipefd[0]);
2287
2288 ret = dup2(pipefd[1], STDOUT_FILENO);
2289 if (ret >= 0)
2290 ret = dup2(pipefd[1], STDERR_FILENO);
2291 close(pipefd[1]);
2292 if (ret < 0) {
2293 SYSERROR("Failed to duplicate std{err,out} file descriptor");
2294 _exit(EXIT_FAILURE);
2295 }
2296
2297 if (netdev->priv.veth_attr.pair[0] != '\0')
2298 hostveth = netdev->priv.veth_attr.pair;
2299 else
2300 hostveth = netdev->priv.veth_attr.veth1;
2301 if (hostveth[0] == '\0') {
2302 SYSERROR("Host side veth device name is missing");
2303 _exit(EXIT_FAILURE);
2304 }
2305
2306 if (netdev->link[0] == '\0') {
2307 SYSERROR("Network link for network device \"%s\" is "
2308 "missing", netdev->priv.veth_attr.veth1);
2309 _exit(EXIT_FAILURE);
2310 }
2311
2312 INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath,
2313 lxcname, netns_path, netdev->link, hostveth);
2314 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "delete", lxcpath,
2315 lxcname, netns_path, "veth", netdev->link, hostveth,
2316 (char *)NULL);
2317 SYSERROR("Failed to exec lxc-user-nic.");
2318 _exit(EXIT_FAILURE);
2319 }
2320
2321 close(pipefd[1]);
2322
2323 bytes = lxc_read_nointr(pipefd[0], &buffer, MAXPATHLEN);
2324 if (bytes < 0) {
2325 SYSERROR("Failed to read from pipe file descriptor.");
2326 close(pipefd[0]);
2327 } else {
2328 buffer[bytes - 1] = '\0';
2329 }
2330
2331 ret = wait_for_pid(child);
2332 close(pipefd[0]);
2333 if (ret != 0 || bytes < 0) {
2334 ERROR("lxc-user-nic failed to delete requested network: %s",
2335 buffer[0] != '\0' ? buffer : "(null)");
2336 return -1;
2337 }
2338
2339 return 0;
2340 }
2341
2342 bool lxc_delete_network_unpriv(struct lxc_handler *handler)
2343 {
2344 int ret;
2345 struct lxc_list *iterator;
2346 struct lxc_list *network = &handler->conf->network;
2347 /* strlen("/proc/") = 6
2348 * +
2349 * INTTYPE_TO_STRLEN(pid_t)
2350 * +
2351 * strlen("/fd/") = 4
2352 * +
2353 * INTTYPE_TO_STRLEN(int)
2354 * +
2355 * \0
2356 */
2357 char netns_path[6 + INTTYPE_TO_STRLEN(pid_t) + 4 + INTTYPE_TO_STRLEN(int) + 1];
2358
2359 *netns_path = '\0';
2360
2361 if (handler->nsfd[LXC_NS_NET] < 0) {
2362 DEBUG("Cannot not guarantee safe deletion of network devices. "
2363 "Manual cleanup maybe needed");
2364 return false;
2365 }
2366
2367 ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d",
2368 lxc_raw_getpid(), handler->nsfd[LXC_NS_NET]);
2369 if (ret < 0 || ret >= sizeof(netns_path))
2370 return false;
2371
2372 lxc_list_for_each(iterator, network) {
2373 char *hostveth = NULL;
2374 struct lxc_netdev *netdev = iterator->elem;
2375
2376 /* We can only delete devices whose ifindex we have. If we don't
2377 * have the index it means that we didn't create it.
2378 */
2379 if (!netdev->ifindex)
2380 continue;
2381
2382 if (netdev->type == LXC_NET_PHYS) {
2383 ret = lxc_netdev_rename_by_index(netdev->ifindex,
2384 netdev->link);
2385 if (ret < 0)
2386 WARN("Failed to rename interface with index %d "
2387 "to its initial name \"%s\"",
2388 netdev->ifindex, netdev->link);
2389 else
2390 TRACE("Renamed interface with index %d to its "
2391 "initial name \"%s\"",
2392 netdev->ifindex, netdev->link);
2393 goto clear_ifindices;
2394 }
2395
2396 ret = netdev_deconf[netdev->type](handler, netdev);
2397 if (ret < 0)
2398 WARN("Failed to deconfigure network device");
2399
2400 if (netdev->type != LXC_NET_VETH)
2401 goto clear_ifindices;
2402
2403 if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link))
2404 goto clear_ifindices;
2405
2406 if (netdev->priv.veth_attr.pair[0] != '\0')
2407 hostveth = netdev->priv.veth_attr.pair;
2408 else
2409 hostveth = netdev->priv.veth_attr.veth1;
2410 if (hostveth[0] == '\0')
2411 goto clear_ifindices;
2412
2413 ret = lxc_delete_network_unpriv_exec(handler->lxcpath,
2414 handler->name, netdev,
2415 netns_path);
2416 if (ret < 0) {
2417 WARN("Failed to remove port \"%s\" from openvswitch "
2418 "bridge \"%s\"", hostveth, netdev->link);
2419 goto clear_ifindices;
2420 }
2421 INFO("Removed interface \"%s\" from \"%s\"", hostveth,
2422 netdev->link);
2423
2424 clear_ifindices:
2425 /* We need to clear any ifindeces we recorded so liblxc won't
2426 * have cached stale data which would cause it to fail on reboot
2427 * we're we don't re-read the on-disk config file.
2428 */
2429 netdev->ifindex = 0;
2430 if (netdev->type == LXC_NET_PHYS) {
2431 netdev->priv.phys_attr.ifindex = 0;
2432 } else if (netdev->type == LXC_NET_VETH) {
2433 netdev->priv.veth_attr.veth1[0] = '\0';
2434 netdev->priv.veth_attr.ifindex = 0;
2435 }
2436 }
2437
2438 return true;
2439 }
2440
2441 int lxc_create_network_priv(struct lxc_handler *handler)
2442 {
2443 struct lxc_list *iterator;
2444 struct lxc_list *network = &handler->conf->network;
2445
2446 if (!handler->am_root)
2447 return 0;
2448
2449 lxc_list_for_each(iterator, network) {
2450 struct lxc_netdev *netdev = iterator->elem;
2451
2452 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
2453 ERROR("Invalid network configuration type %d", netdev->type);
2454 return -1;
2455 }
2456
2457 if (netdev_conf[netdev->type](handler, netdev)) {
2458 ERROR("Failed to create network device");
2459 return -1;
2460 }
2461
2462 }
2463
2464 return 0;
2465 }
2466
2467 int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcname,
2468 struct lxc_list *network, pid_t pid)
2469 {
2470 int ret;
2471 char ifname[IFNAMSIZ];
2472 struct lxc_list *iterator;
2473
2474 if (am_guest_unpriv())
2475 return 0;
2476
2477 lxc_list_for_each(iterator, network) {
2478 struct lxc_netdev *netdev = iterator->elem;
2479
2480 if (!netdev->ifindex)
2481 continue;
2482
2483 /* retrieve the name of the interface */
2484 if (!if_indextoname(netdev->ifindex, ifname)) {
2485 ERROR("No interface corresponding to ifindex \"%d\"",
2486 netdev->ifindex);
2487 return -1;
2488 }
2489
2490 ret = lxc_netdev_move_by_name(ifname, pid, NULL);
2491 if (ret) {
2492 errno = -ret;
2493 SYSERROR("Failed to move network device \"%s\" to "
2494 "network namespace %d", ifname, pid);
2495 return -1;
2496 }
2497
2498 DEBUG("Moved network device \"%s\"/\"%s\" to network namespace "
2499 "of %d",
2500 ifname, netdev->name[0] != '\0' ? netdev->name : "(null)",
2501 pid);
2502 }
2503
2504 return 0;
2505 }
2506
2507 int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
2508 struct lxc_list *network, pid_t pid, unsigned int hooks_version)
2509 {
2510 struct lxc_list *iterator;
2511
2512 if (!am_guest_unpriv())
2513 return 0;
2514
2515 lxc_list_for_each(iterator, network) {
2516 struct lxc_netdev *netdev = iterator->elem;
2517
2518 if (netdev->type == LXC_NET_EMPTY)
2519 continue;
2520
2521 if (netdev->type == LXC_NET_NONE)
2522 continue;
2523
2524 if (netdev->type != LXC_NET_VETH) {
2525 ERROR("Networks of type %s are not supported by "
2526 "unprivileged containers",
2527 lxc_net_type_to_str(netdev->type));
2528 return -1;
2529 }
2530
2531 if (netdev->mtu)
2532 INFO("mtu ignored due to insufficient privilege");
2533
2534 if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev, pid, hooks_version))
2535 return -1;
2536 }
2537
2538 return 0;
2539 }
2540
2541 bool lxc_delete_network_priv(struct lxc_handler *handler)
2542 {
2543 int ret;
2544 struct lxc_list *iterator;
2545 struct lxc_list *network = &handler->conf->network;
2546
2547 lxc_list_for_each(iterator, network) {
2548 char *hostveth = NULL;
2549 struct lxc_netdev *netdev = iterator->elem;
2550
2551 /* We can only delete devices whose ifindex we have. If we don't
2552 * have the index it means that we didn't create it.
2553 */
2554 if (!netdev->ifindex)
2555 continue;
2556
2557 if (netdev->type == LXC_NET_PHYS) {
2558 ret = lxc_netdev_rename_by_index(netdev->ifindex, netdev->link);
2559 if (ret < 0)
2560 WARN("Failed to rename interface with index %d "
2561 "from \"%s\" to its initial name \"%s\"",
2562 netdev->ifindex, netdev->name, netdev->link);
2563 else
2564 TRACE("Renamed interface with index %d from "
2565 "\"%s\" to its initial name \"%s\"",
2566 netdev->ifindex, netdev->name,
2567 netdev->link);
2568 goto clear_ifindices;
2569 }
2570
2571 ret = netdev_deconf[netdev->type](handler, netdev);
2572 if (ret < 0)
2573 WARN("Failed to deconfigure network device");
2574
2575 /* Recent kernels remove the virtual interfaces when the network
2576 * namespace is destroyed but in case we did not move the
2577 * interface to the network namespace, we have to destroy it.
2578 */
2579 ret = lxc_netdev_delete_by_index(netdev->ifindex);
2580 if (-ret == ENODEV) {
2581 INFO("Interface \"%s\" with index %d already "
2582 "deleted or existing in different network "
2583 "namespace",
2584 netdev->name[0] != '\0' ? netdev->name : "(null)",
2585 netdev->ifindex);
2586 } else if (ret < 0) {
2587 errno = -ret;
2588 SYSWARN("Failed to remove interface \"%s\" with index %d",
2589 netdev->name[0] != '\0' ? netdev->name : "(null)",
2590 netdev->ifindex);
2591 goto clear_ifindices;
2592 }
2593 INFO("Removed interface \"%s\" with index %d",
2594 netdev->name[0] != '\0' ? netdev->name : "(null)",
2595 netdev->ifindex);
2596
2597 if (netdev->type != LXC_NET_VETH)
2598 goto clear_ifindices;
2599
2600 /* Explicitly delete host veth device to prevent lingering
2601 * devices. We had issues in LXD around this.
2602 */
2603 if (netdev->priv.veth_attr.pair[0] != '\0')
2604 hostveth = netdev->priv.veth_attr.pair;
2605 else
2606 hostveth = netdev->priv.veth_attr.veth1;
2607 if (hostveth[0] == '\0')
2608 goto clear_ifindices;
2609
2610 ret = lxc_netdev_delete_by_name(hostveth);
2611 if (ret < 0) {
2612 errno = -ret;
2613 SYSWARN("Failed to remove interface \"%s\" from \"%s\"",
2614 hostveth, netdev->link);
2615 goto clear_ifindices;
2616 }
2617 INFO("Removed interface \"%s\" from \"%s\"", hostveth, netdev->link);
2618
2619 if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link)) {
2620 netdev->priv.veth_attr.veth1[0] = '\0';
2621 netdev->ifindex = 0;
2622 netdev->priv.veth_attr.ifindex = 0;
2623 goto clear_ifindices;
2624 }
2625
2626 /* Delete the openvswitch port. */
2627 ret = lxc_ovs_delete_port(netdev->link, hostveth);
2628 if (ret < 0)
2629 WARN("Failed to remove port \"%s\" from openvswitch "
2630 "bridge \"%s\"", hostveth, netdev->link);
2631 else
2632 INFO("Removed port \"%s\" from openvswitch bridge \"%s\"",
2633 hostveth, netdev->link);
2634
2635 clear_ifindices:
2636 /* We need to clear any ifindeces we recorded so liblxc won't
2637 * have cached stale data which would cause it to fail on reboot
2638 * we're we don't re-read the on-disk config file.
2639 */
2640 netdev->ifindex = 0;
2641 if (netdev->type == LXC_NET_PHYS) {
2642 netdev->priv.phys_attr.ifindex = 0;
2643 } else if (netdev->type == LXC_NET_VETH) {
2644 netdev->priv.veth_attr.veth1[0] = '\0';
2645 netdev->priv.veth_attr.ifindex = 0;
2646 }
2647 }
2648
2649 return true;
2650 }
2651
2652 int lxc_requests_empty_network(struct lxc_handler *handler)
2653 {
2654 struct lxc_list *network = &handler->conf->network;
2655 struct lxc_list *iterator;
2656 bool found_none = false, found_nic = false;
2657
2658 if (lxc_list_empty(network))
2659 return 0;
2660
2661 lxc_list_for_each(iterator, network) {
2662 struct lxc_netdev *netdev = iterator->elem;
2663
2664 if (netdev->type == LXC_NET_NONE)
2665 found_none = true;
2666 else
2667 found_nic = true;
2668 }
2669 if (found_none && !found_nic)
2670 return 1;
2671 return 0;
2672 }
2673
2674 /* try to move physical nics to the init netns */
2675 int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
2676 {
2677 int ret;
2678 int oldfd;
2679 char ifname[IFNAMSIZ];
2680 struct lxc_list *iterator;
2681 int netnsfd = handler->nsfd[LXC_NS_NET];
2682 struct lxc_conf *conf = handler->conf;
2683
2684 /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
2685 * the parent network namespace. We won't have this capability if we are
2686 * unprivileged.
2687 */
2688 if (!handler->am_root)
2689 return 0;
2690
2691 TRACE("Moving physical network devices back to parent network namespace");
2692
2693 oldfd = lxc_preserve_ns(lxc_raw_getpid(), "net");
2694 if (oldfd < 0) {
2695 SYSERROR("Failed to preserve network namespace");
2696 return -1;
2697 }
2698
2699 ret = setns(netnsfd, CLONE_NEWNET);
2700 if (ret < 0) {
2701 SYSERROR("Failed to enter network namespace");
2702 close(oldfd);
2703 return -1;
2704 }
2705
2706 lxc_list_for_each(iterator, &conf->network) {
2707 struct lxc_netdev *netdev = iterator->elem;
2708
2709 if (netdev->type != LXC_NET_PHYS)
2710 continue;
2711
2712 /* Retrieve the name of the interface in the container's network
2713 * namespace.
2714 */
2715 if (!if_indextoname(netdev->ifindex, ifname)) {
2716 WARN("No interface corresponding to ifindex %d",
2717 netdev->ifindex);
2718 continue;
2719 }
2720
2721 ret = lxc_netdev_move_by_name(ifname, 1, netdev->link);
2722 if (ret < 0)
2723 WARN("Error moving network device \"%s\" back to "
2724 "network namespace", ifname);
2725 else
2726 TRACE("Moved network device \"%s\" back to network "
2727 "namespace", ifname);
2728 }
2729
2730 ret = setns(oldfd, CLONE_NEWNET);
2731 close(oldfd);
2732 if (ret < 0) {
2733 SYSERROR("Failed to enter network namespace");
2734 return -1;
2735 }
2736
2737 return 0;
2738 }
2739
2740 static int setup_hw_addr(char *hwaddr, const char *ifname)
2741 {
2742 struct sockaddr sockaddr;
2743 struct ifreq ifr;
2744 int ret, fd;
2745
2746 ret = lxc_convert_mac(hwaddr, &sockaddr);
2747 if (ret) {
2748 errno = -ret;
2749 SYSERROR("Mac address \"%s\" conversion failed", hwaddr);
2750 return -1;
2751 }
2752
2753 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
2754 ifr.ifr_name[IFNAMSIZ-1] = '\0';
2755 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
2756
2757 fd = socket(AF_INET, SOCK_DGRAM, 0);
2758 if (fd < 0)
2759 return -1;
2760
2761 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
2762 if (ret)
2763 SYSERROR("Failed to perform ioctl");
2764
2765 close(fd);
2766
2767 DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr,
2768 ifr.ifr_name);
2769
2770 return ret;
2771 }
2772
2773 static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
2774 {
2775 struct lxc_list *iterator;
2776 int err;
2777
2778 lxc_list_for_each(iterator, ip) {
2779 struct lxc_inetdev *inetdev = iterator->elem;
2780
2781 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
2782 &inetdev->bcast, inetdev->prefix);
2783 if (err) {
2784 errno = -err;
2785 SYSERROR("Failed to setup ipv4 address for network device "
2786 "with eifindex %d", ifindex);
2787 return -1;
2788 }
2789 }
2790
2791 return 0;
2792 }
2793
2794 static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
2795 {
2796 struct lxc_list *iterator;
2797 int err;
2798
2799 lxc_list_for_each(iterator, ip) {
2800 struct lxc_inet6dev *inet6dev = iterator->elem;
2801
2802 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
2803 &inet6dev->mcast, &inet6dev->acast,
2804 inet6dev->prefix);
2805 if (err) {
2806 errno = -err;
2807 SYSERROR("Failed to setup ipv6 address for network device "
2808 "with eifindex %d", ifindex);
2809 return -1;
2810 }
2811 }
2812
2813 return 0;
2814 }
2815
2816 static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
2817 {
2818 char ifname[IFNAMSIZ];
2819 int err;
2820 const char *net_type_name;
2821 char *current_ifname = ifname;
2822
2823 /* empty network namespace */
2824 if (!netdev->ifindex) {
2825 if (netdev->flags & IFF_UP) {
2826 err = lxc_netdev_up("lo");
2827 if (err) {
2828 errno = -err;
2829 SYSERROR("Failed to set the loopback network device up");
2830 return -1;
2831 }
2832 }
2833
2834 if (netdev->type == LXC_NET_EMPTY)
2835 return 0;
2836
2837 if (netdev->type == LXC_NET_NONE)
2838 return 0;
2839
2840 if (netdev->type != LXC_NET_VETH) {
2841 net_type_name = lxc_net_type_to_str(netdev->type);
2842 ERROR("%s networks are not supported for containers "
2843 "not setup up by privileged users", net_type_name);
2844 return -1;
2845 }
2846
2847 netdev->ifindex = if_nametoindex(netdev->name);
2848 }
2849
2850 /* get the new ifindex in case of physical netdev */
2851 if (netdev->type == LXC_NET_PHYS) {
2852 netdev->ifindex = if_nametoindex(netdev->link);
2853 if (!netdev->ifindex) {
2854 ERROR("Failed to get ifindex for network device \"%s\"",
2855 netdev->link);
2856 return -1;
2857 }
2858 }
2859
2860 /* retrieve the name of the interface */
2861 if (!if_indextoname(netdev->ifindex, current_ifname)) {
2862 ERROR("Failed get name for network device with ifindex %d",
2863 netdev->ifindex);
2864 return -1;
2865 }
2866
2867 /* Default: let the system to choose one interface name.
2868 * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
2869 * netlink will replace the format specifier with an appropriate index.
2870 */
2871 if (netdev->name[0] == '\0') {
2872 if (netdev->type == LXC_NET_PHYS)
2873 (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
2874 else
2875 (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
2876 }
2877
2878 /* rename the interface name */
2879 if (strcmp(ifname, netdev->name) != 0) {
2880 err = lxc_netdev_rename_by_name(ifname, netdev->name);
2881 if (err) {
2882 errno = -err;
2883 SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
2884 ifname, netdev->name);
2885 return -1;
2886 }
2887 }
2888
2889 /* Re-read the name of the interface because its name has changed
2890 * and would be automatically allocated by the system
2891 */
2892 if (!if_indextoname(netdev->ifindex, current_ifname)) {
2893 ERROR("Failed get name for network device with ifindex %d",
2894 netdev->ifindex);
2895 return -1;
2896 }
2897
2898 /* Now update the recorded name of the network device to reflect the
2899 * name of the network device in the child's network namespace. We will
2900 * later on send this information back to the parent.
2901 */
2902 (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
2903
2904 /* set a mac address */
2905 if (netdev->hwaddr) {
2906 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
2907 ERROR("Failed to setup hw address for network device \"%s\"",
2908 current_ifname);
2909 return -1;
2910 }
2911 }
2912
2913 /* setup ipv4 addresses on the interface */
2914 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
2915 ERROR("Failed to setup ip addresses for network device \"%s\"",
2916 ifname);
2917 return -1;
2918 }
2919
2920 /* setup ipv6 addresses on the interface */
2921 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
2922 ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
2923 ifname);
2924 return -1;
2925 }
2926
2927 /* set the network device up */
2928 if (netdev->flags & IFF_UP) {
2929 int err;
2930
2931 err = lxc_netdev_up(current_ifname);
2932 if (err) {
2933 errno = -err;
2934 SYSERROR("Failed to set network device \"%s\" up",
2935 current_ifname);
2936 return -1;
2937 }
2938
2939 /* the network is up, make the loopback up too */
2940 err = lxc_netdev_up("lo");
2941 if (err) {
2942 errno = -err;
2943 SYSERROR("Failed to set the loopback network device up");
2944 return -1;
2945 }
2946 }
2947
2948 /* We can only set up the default routes after bringing
2949 * up the interface, sine bringing up the interface adds
2950 * the link-local routes and we can't add a default
2951 * route if the gateway is not reachable. */
2952
2953 /* setup ipv4 gateway on the interface */
2954 if (netdev->ipv4_gateway) {
2955 if (!(netdev->flags & IFF_UP)) {
2956 ERROR("Cannot add ipv4 gateway for network device "
2957 "\"%s\" when not bringing up the interface", ifname);
2958 return -1;
2959 }
2960
2961 if (lxc_list_empty(&netdev->ipv4)) {
2962 ERROR("Cannot add ipv4 gateway for network device "
2963 "\"%s\" when not assigning an address", ifname);
2964 return -1;
2965 }
2966
2967 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
2968 if (err) {
2969 err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway);
2970 if (err) {
2971 errno = -err;
2972 SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
2973 ifname);
2974 }
2975
2976 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
2977 if (err) {
2978 errno = -err;
2979 SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
2980 ifname);
2981
2982 if (netdev->ipv4_gateway_auto) {
2983 char buf[INET_ADDRSTRLEN];
2984 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
2985 ERROR("Fried to set autodetected ipv4 gateway \"%s\"", buf);
2986 }
2987 return -1;
2988 }
2989 }
2990 }
2991
2992 /* setup ipv6 gateway on the interface */
2993 if (netdev->ipv6_gateway) {
2994 if (!(netdev->flags & IFF_UP)) {
2995 ERROR("Cannot add ipv6 gateway for network device "
2996 "\"%s\" when not bringing up the interface", ifname);
2997 return -1;
2998 }
2999
3000 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
3001 ERROR("Cannot add ipv6 gateway for network device "
3002 "\"%s\" when not assigning an address", ifname);
3003 return -1;
3004 }
3005
3006 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
3007 if (err) {
3008 err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway);
3009 if (err) {
3010 errno = -err;
3011 SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
3012 ifname);
3013 }
3014
3015 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
3016 if (err) {
3017 errno = -err;
3018 SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
3019 ifname);
3020
3021 if (netdev->ipv6_gateway_auto) {
3022 char buf[INET6_ADDRSTRLEN];
3023 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
3024 ERROR("Tried to set autodetected ipv6 "
3025 "gateway for network device "
3026 "\"%s\"", buf);
3027 }
3028 return -1;
3029 }
3030 }
3031 }
3032
3033 DEBUG("Network device \"%s\" has been setup", current_ifname);
3034
3035 return 0;
3036 }
3037
3038 int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
3039 struct lxc_list *network)
3040 {
3041 struct lxc_list *iterator;
3042 struct lxc_netdev *netdev;
3043
3044 lxc_list_for_each(iterator, network) {
3045 netdev = iterator->elem;
3046
3047 if (lxc_setup_netdev_in_child_namespaces(netdev)) {
3048 ERROR("failed to setup netdev");
3049 return -1;
3050 }
3051 }
3052
3053 if (!lxc_list_empty(network))
3054 INFO("network has been setup");
3055
3056 return 0;
3057 }
3058
3059 int lxc_network_send_veth_names_to_child(struct lxc_handler *handler)
3060 {
3061 struct lxc_list *iterator;
3062 struct lxc_list *network = &handler->conf->network;
3063 int data_sock = handler->data_sock[0];
3064
3065 if (handler->am_root)
3066 return 0;
3067
3068 lxc_list_for_each(iterator, network) {
3069 int ret;
3070 struct lxc_netdev *netdev = iterator->elem;
3071
3072 if (netdev->type != LXC_NET_VETH)
3073 continue;
3074
3075 ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
3076 if (ret < 0)
3077 return -1;
3078 TRACE("Sent network device name \"%s\" to child", netdev->name);
3079 }
3080
3081 return 0;
3082 }
3083
3084 int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler)
3085 {
3086 struct lxc_list *iterator;
3087 struct lxc_list *network = &handler->conf->network;
3088 int data_sock = handler->data_sock[1];
3089
3090 if (handler->am_root)
3091 return 0;
3092
3093 lxc_list_for_each(iterator, network) {
3094 int ret;
3095 struct lxc_netdev *netdev = iterator->elem;
3096
3097 if (netdev->type != LXC_NET_VETH)
3098 continue;
3099
3100 ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
3101 if (ret < 0)
3102 return -1;
3103 TRACE("Received network device name \"%s\" from parent", netdev->name);
3104 }
3105
3106 return 0;
3107 }
3108
3109 int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handler)
3110 {
3111 struct lxc_list *iterator, *network;
3112 int data_sock = handler->data_sock[0];
3113
3114 if (!handler->am_root)
3115 return 0;
3116
3117 network = &handler->conf->network;
3118 lxc_list_for_each(iterator, network) {
3119 int ret;
3120 struct lxc_netdev *netdev = iterator->elem;
3121
3122 /* Send network device name in the child's namespace to parent. */
3123 ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
3124 if (ret < 0)
3125 return -1;
3126
3127 /* Send network device ifindex in the child's namespace to
3128 * parent.
3129 */
3130 ret = lxc_send_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), MSG_NOSIGNAL);
3131 if (ret < 0)
3132 return -1;
3133 }
3134
3135 TRACE("Sent network device names and ifindeces to parent");
3136 return 0;
3137 }
3138
3139 int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler)
3140 {
3141 struct lxc_list *iterator, *network;
3142 int data_sock = handler->data_sock[1];
3143
3144 if (!handler->am_root)
3145 return 0;
3146
3147 network = &handler->conf->network;
3148 lxc_list_for_each(iterator, network) {
3149 int ret;
3150 struct lxc_netdev *netdev = iterator->elem;
3151
3152 /* Receive network device name in the child's namespace to
3153 * parent.
3154 */
3155 ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
3156 if (ret < 0)
3157 return -1;
3158
3159 /* Receive network device ifindex in the child's namespace to
3160 * parent.
3161 */
3162 ret = lxc_recv_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), 0);
3163 if (ret < 0)
3164 return -1;
3165 }
3166
3167 return 0;
3168 }
3169
3170 void lxc_delete_network(struct lxc_handler *handler)
3171 {
3172 bool bret;
3173
3174 if (handler->am_root)
3175 bret = lxc_delete_network_priv(handler);
3176 else
3177 bret = lxc_delete_network_unpriv(handler);
3178 if (!bret)
3179 DEBUG("Failed to delete network devices");
3180 else
3181 DEBUG("Deleted network devices");
3182 }
3183
3184 int lxc_netns_set_nsid(int fd)
3185 {
3186 int ret;
3187 char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
3188 NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
3189 NLMSG_ALIGN(1024)];
3190 struct nl_handler nlh;
3191 struct nlmsghdr *hdr;
3192 struct rtgenmsg *msg;
3193 int saved_errno;
3194 const __s32 ns_id = -1;
3195 const __u32 netns_fd = fd;
3196
3197 ret = netlink_open(&nlh, NETLINK_ROUTE);
3198 if (ret < 0)
3199 return -1;
3200
3201 memset(buf, 0, sizeof(buf));
3202
3203 #pragma GCC diagnostic push
3204 #pragma GCC diagnostic ignored "-Wcast-align"
3205 hdr = (struct nlmsghdr *)buf;
3206 msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
3207 #pragma GCC diagnostic pop
3208
3209 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
3210 hdr->nlmsg_type = RTM_NEWNSID;
3211 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
3212 hdr->nlmsg_pid = 0;
3213 hdr->nlmsg_seq = RTM_NEWNSID;
3214 msg->rtgen_family = AF_UNSPEC;
3215
3216 ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
3217 if (ret < 0)
3218 goto on_error;
3219
3220 ret = addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
3221 if (ret < 0)
3222 goto on_error;
3223
3224 ret = __netlink_transaction(&nlh, hdr, hdr);
3225
3226 on_error:
3227 saved_errno = errno;
3228 netlink_close(&nlh);
3229 errno = saved_errno;
3230
3231 return ret;
3232 }
3233
3234 static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
3235 {
3236
3237 memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
3238
3239 while (RTA_OK(rta, len)) {
3240 unsigned short type = rta->rta_type;
3241
3242 if ((type <= max) && (!tb[type]))
3243 tb[type] = rta;
3244
3245 #pragma GCC diagnostic push
3246 #pragma GCC diagnostic ignored "-Wcast-align"
3247 rta = RTA_NEXT(rta, len);
3248 #pragma GCC diagnostic pop
3249 }
3250
3251 return 0;
3252 }
3253
3254 static inline __s32 rta_getattr_s32(const struct rtattr *rta)
3255 {
3256 return *(__s32 *)RTA_DATA(rta);
3257 }
3258
3259 #ifndef NETNS_RTA
3260 #define NETNS_RTA(r) \
3261 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
3262 #endif
3263
3264 int lxc_netns_get_nsid(int fd)
3265 {
3266 int ret;
3267 ssize_t len;
3268 char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
3269 NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
3270 NLMSG_ALIGN(1024)];
3271 struct rtattr *tb[__LXC_NETNSA_MAX + 1];
3272 struct nl_handler nlh;
3273 struct nlmsghdr *hdr;
3274 struct rtgenmsg *msg;
3275 int saved_errno;
3276 __u32 netns_fd = fd;
3277
3278 ret = netlink_open(&nlh, NETLINK_ROUTE);
3279 if (ret < 0)
3280 return -1;
3281
3282 memset(buf, 0, sizeof(buf));
3283
3284 #pragma GCC diagnostic push
3285 #pragma GCC diagnostic ignored "-Wcast-align"
3286 hdr = (struct nlmsghdr *)buf;
3287 msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
3288 #pragma GCC diagnostic pop
3289
3290 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
3291 hdr->nlmsg_type = RTM_GETNSID;
3292 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
3293 hdr->nlmsg_pid = 0;
3294 hdr->nlmsg_seq = RTM_GETNSID;
3295 msg->rtgen_family = AF_UNSPEC;
3296
3297 ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
3298 if (ret == 0)
3299 ret = __netlink_transaction(&nlh, hdr, hdr);
3300
3301 saved_errno = errno;
3302 netlink_close(&nlh);
3303 errno = saved_errno;
3304 if (ret < 0)
3305 return -1;
3306
3307 errno = EINVAL;
3308 msg = NLMSG_DATA(hdr);
3309 len = hdr->nlmsg_len - NLMSG_SPACE(sizeof(*msg));
3310 if (len < 0)
3311 return -1;
3312
3313 #pragma GCC diagnostic push
3314 #pragma GCC diagnostic ignored "-Wcast-align"
3315 parse_rtattr(tb, __LXC_NETNSA_MAX, NETNS_RTA(msg), len);
3316 if (tb[__LXC_NETNSA_NSID])
3317 return rta_getattr_s32(tb[__LXC_NETNSA_NSID]);
3318 #pragma GCC diagnostic pop
3319
3320 return -1;
3321 }