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