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