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