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