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