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