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