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