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