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