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