]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/network.c
Merge pull request #3309 from brauner/2020-03-19/fixes
[mirror_lxc.git] / src / lxc / network.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
cb0dc11b 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
6#include <arpa/inet.h>
cb0dc11b
CB
7#include <ctype.h>
8#include <errno.h>
9#include <fcntl.h>
0ad19a3f 10#include <linux/netlink.h>
11#include <linux/rtnetlink.h>
12#include <linux/sockios.h>
cb0dc11b
CB
13#include <net/ethernet.h>
14#include <net/if.h>
15#include <net/if_arp.h>
16#include <netinet/in.h>
d38dd64a
CB
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
cb0dc11b
CB
20#include <sys/inotify.h>
21#include <sys/ioctl.h>
22#include <sys/param.h>
23#include <sys/socket.h>
24#include <sys/stat.h>
25#include <sys/types.h>
d38dd64a
CB
26#include <time.h>
27#include <unistd.h>
f549edcc 28
d38dd64a 29#include "../include/netns_ifaddrs.h"
7ab1ba02 30#include "af_unix.h"
72d0e1cb 31#include "conf.h"
811ef482 32#include "config.h"
e3233f26 33#include "file_utils.h"
cb0dc11b 34#include "log.h"
8335fd40 35#include "macro.h"
95ea3d1f 36#include "memory_utils.h"
cb0dc11b
CB
37#include "network.h"
38#include "nl.h"
d7b58715 39#include "raw_syscalls.h"
59524108 40#include "syscall_wrappers.h"
0d204771 41#include "utils.h"
0ad19a3f 42
9de31d5a
CB
43#ifndef HAVE_STRLCPY
44#include "include/strlcpy.h"
45#endif
46
ac2cecc4 47lxc_log_define(network, lxc);
f8fee0e2 48
811ef482 49typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
8bf64b77 50typedef int (*instantiate_ns_cb)(struct lxc_netdev *);
3ebffb98 51static const char loop_device[] = "lo";
811ef482 52
b670016a 53static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *dest, unsigned int netmask)
8f82874c 54{
55 int addrlen, err;
56 struct nl_handler nlh;
57 struct rtmsg *rt;
58 struct nlmsg *answer = NULL, *nlmsg = NULL;
59
60 addrlen = family == AF_INET ? sizeof(struct in_addr)
61 : sizeof(struct in6_addr);
62
63 err = netlink_open(&nlh, NETLINK_ROUTE);
64 if (err)
65 return err;
66
67 err = -ENOMEM;
68 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
69 if (!nlmsg)
70 goto out;
71
72 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
73 if (!answer)
74 goto out;
75
76 nlmsg->nlmsghdr->nlmsg_flags =
77 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
b670016a 78 nlmsg->nlmsghdr->nlmsg_type = nlmsg_type;
8f82874c 79
80 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
81 if (!rt)
82 goto out;
83 rt->rtm_family = family;
84 rt->rtm_table = RT_TABLE_MAIN;
85 rt->rtm_scope = RT_SCOPE_LINK;
86 rt->rtm_protocol = RTPROT_BOOT;
87 rt->rtm_type = RTN_UNICAST;
88 rt->rtm_dst_len = netmask;
89
90 err = -EINVAL;
91 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
92 goto out;
93 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
94 goto out;
95 err = netlink_transaction(&nlh, nlmsg, answer);
96out:
97 netlink_close(&nlh);
98 nlmsg_free(answer);
99 nlmsg_free(nlmsg);
100 return err;
101}
102
103static int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest, unsigned int netmask)
104{
b670016a 105 return lxc_ip_route_dest(RTM_NEWROUTE, AF_INET, ifindex, dest, netmask);
8f82874c 106}
107
108static int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest, unsigned int netmask)
109{
b670016a 110 return lxc_ip_route_dest(RTM_NEWROUTE, AF_INET6, ifindex, dest, netmask);
111}
112
113static int lxc_ipv4_dest_del(int ifindex, struct in_addr *dest, unsigned int netmask)
114{
115 return lxc_ip_route_dest(RTM_DELROUTE, AF_INET, ifindex, dest, netmask);
116}
117
118static int lxc_ipv6_dest_del(int ifindex, struct in6_addr *dest, unsigned int netmask)
119{
120 return lxc_ip_route_dest(RTM_DELROUTE, AF_INET6, ifindex, dest, netmask);
8f82874c 121}
122
d4a7da46 123static int lxc_setup_ipv4_routes(struct lxc_list *ip, int ifindex)
124{
125 struct lxc_list *iterator;
126 int err;
127
128 lxc_list_for_each(iterator, ip) {
129 struct lxc_inetdev *inetdev = iterator->elem;
130
131 err = lxc_ipv4_dest_add(ifindex, &inetdev->addr, inetdev->prefix);
132 if (err) {
133 SYSERROR("Failed to setup ipv4 route for network device "
134 "with ifindex %d", ifindex);
596a002c 135 return ret_set_errno(-1, -err);
d4a7da46 136 }
137 }
138
139 return 0;
140}
141
142static int lxc_setup_ipv6_routes(struct lxc_list *ip, int ifindex)
143{
144 struct lxc_list *iterator;
145 int err;
146
147 lxc_list_for_each(iterator, ip) {
148 struct lxc_inet6dev *inet6dev = iterator->elem;
149
150 err = lxc_ipv6_dest_add(ifindex, &inet6dev->addr, inet6dev->prefix);
151 if (err) {
152 SYSERROR("Failed to setup ipv6 route for network device "
153 "with ifindex %d", ifindex);
596a002c 154 return ret_set_errno(-1, -err);
d4a7da46 155 }
156 }
157
158 return 0;
159}
160
6dfa9581
TP
161static int setup_ipv4_addr_routes(struct lxc_list *ip, int ifindex)
162{
163 struct lxc_list *iterator;
164 int err;
165
166 lxc_list_for_each(iterator, ip) {
167 struct lxc_inetdev *inetdev = iterator->elem;
168
169 err = lxc_ipv4_dest_add(ifindex, &inetdev->addr, 32);
170
171 if (err)
596a002c 172 return log_error_errno(-1, err,
6dfa9581
TP
173 "Failed to setup ipv4 address route for network device with eifindex %d",
174 ifindex);
175 }
176
177 return 0;
178}
179
180static int setup_ipv6_addr_routes(struct lxc_list *ip, int ifindex)
181{
182 struct lxc_list *iterator;
183 int err;
184
185 lxc_list_for_each(iterator, ip) {
186 struct lxc_inet6dev *inet6dev = iterator->elem;
187
188 err = lxc_ipv6_dest_add(ifindex, &inet6dev->addr, 128);
189 if (err)
596a002c 190 return log_error_errno(-1, err,
6dfa9581
TP
191 "Failed to setup ipv6 address route for network device with eifindex %d",
192 ifindex);
193 }
194
195 return 0;
196}
197
198struct ip_proxy_args {
199 const char *ip;
200 const char *dev;
201};
202
5fe147e9 203static int lxc_ip_neigh_proxy(__u16 nlmsg_type, int family, int ifindex, void *dest)
6dfa9581 204{
5fe147e9
TP
205 int addrlen, err;
206 struct nl_handler nlh;
207 struct ndmsg *rt;
208 struct nlmsg *answer = NULL, *nlmsg = NULL;
6dfa9581 209
5fe147e9 210 addrlen = family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr);
6dfa9581 211
5fe147e9
TP
212 err = netlink_open(&nlh, NETLINK_ROUTE);
213 if (err)
214 return err;
6dfa9581 215
5fe147e9
TP
216 err = -ENOMEM;
217 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
218 if (!nlmsg)
219 goto out;
6dfa9581 220
5fe147e9
TP
221 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
222 if (!answer)
223 goto out;
6dfa9581 224
5fe147e9
TP
225 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
226 nlmsg->nlmsghdr->nlmsg_type = nlmsg_type;
6dfa9581 227
5fe147e9
TP
228 rt = nlmsg_reserve(nlmsg, sizeof(struct ndmsg));
229 if (!rt)
230 goto out;
231 rt->ndm_ifindex = ifindex;
232 rt->ndm_flags = NTF_PROXY;
233 rt->ndm_type = NDA_DST;
234 rt->ndm_family = family;
6dfa9581 235
5fe147e9
TP
236 err = -EINVAL;
237 if (nla_put_buffer(nlmsg, NDA_DST, dest, addrlen))
238 goto out;
6dfa9581 239
5fe147e9
TP
240 err = netlink_transaction(&nlh, nlmsg, answer);
241out:
242 netlink_close(&nlh);
243 nlmsg_free(answer);
244 nlmsg_free(nlmsg);
245 return err;
6dfa9581
TP
246}
247
248static int lxc_is_ip_forwarding_enabled(const char *ifname, int family)
249{
250 int ret;
251 char path[PATH_MAX];
252 char buf[1] = "";
253
254 if (family != AF_INET && family != AF_INET6)
596a002c 255 return ret_set_errno(-1, EINVAL);
6dfa9581
TP
256
257 ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
258 family == AF_INET ? "ipv4" : "ipv6", ifname,
259 "forwarding");
260 if (ret < 0 || (size_t)ret >= PATH_MAX)
596a002c 261 return ret_set_errno(-1, E2BIG);
6dfa9581
TP
262
263 return lxc_read_file_expect(path, buf, 1, "1");
264}
265
811ef482
CB
266static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
267{
54256301 268 int err;
a00fbab5 269 unsigned int mtu = 1500;
811ef482
CB
270 char *veth1, *veth2;
271 char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ];
811ef482 272
de4855a8 273 if (netdev->priv.veth_attr.pair[0] != '\0') {
811ef482
CB
274 veth1 = netdev->priv.veth_attr.pair;
275 if (handler->conf->reboot)
276 lxc_netdev_delete_by_name(veth1);
277 } else {
278 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
279 if (err < 0 || (size_t)err >= sizeof(veth1buf))
280 return -1;
281
282 veth1 = lxc_mkifname(veth1buf);
283 if (!veth1)
284 return -1;
285
286 /* store away for deconf */
287 memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
288 }
289
d34212ad
CB
290 err = snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
291 if (err < 0 || (size_t)err >= sizeof(veth2buf))
292 return -1;
293
811ef482
CB
294 veth2 = lxc_mkifname(veth2buf);
295 if (!veth2)
54256301
CB
296 return -1;
297
a00fbab5
TP
298 /* if mtu is specified in config then use that, otherwise inherit from link device if provided. */
299 if (netdev->mtu) {
300 if (lxc_safe_uint(netdev->mtu, &mtu))
301 return log_error_errno(-1, errno, "Failed to parse mtu");
54256301
CB
302 } else if (netdev->link[0] != '\0') {
303 int ifindex_mtu;
811ef482 304
54256301
CB
305 ifindex_mtu = if_nametoindex(netdev->link);
306 if (ifindex_mtu) {
307 mtu = netdev_get_mtu(ifindex_mtu);
308 INFO("Retrieved mtu %d from %s", mtu, netdev->link);
309 }
310 }
311
312 err = lxc_veth_create(veth1, veth2, handler->pid, mtu);
811ef482 313 if (err) {
6d1400b5 314 errno = -err;
315 SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1, veth2);
54256301 316 return -1;
811ef482
CB
317 }
318
24190194
CB
319 strlcpy(netdev->created_name, veth2, IFNAMSIZ);
320
811ef482
CB
321 /* changing the high byte of the mac address to 0xfe, the bridge interface
322 * will always keep the host's mac address and not take the mac address
323 * of a container */
324 err = setup_private_host_hw_addr(veth1);
325 if (err) {
6d1400b5 326 errno = -err;
327 SYSERROR("Failed to change mac address of host interface \"%s\"", veth1);
811ef482
CB
328 goto out_delete;
329 }
330
8da62485
CB
331 /* Retrieve ifindex of the host's veth device. */
332 netdev->priv.veth_attr.ifindex = if_nametoindex(veth1);
333 if (!netdev->priv.veth_attr.ifindex) {
334 ERROR("Failed to retrieve ifindex for \"%s\"", veth1);
335 goto out_delete;
336 }
337
811ef482
CB
338 if (mtu) {
339 err = lxc_netdev_set_mtu(veth1, mtu);
811ef482 340 if (err) {
6d1400b5 341 errno = -err;
54256301 342 SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" ", mtu, veth1);
811ef482
CB
343 goto out_delete;
344 }
345 }
346
6dfa9581 347 if (netdev->link[0] != '\0' && netdev->priv.veth_attr.mode == VETH_MODE_BRIDGE) {
811ef482
CB
348 err = lxc_bridge_attach(netdev->link, veth1);
349 if (err) {
6d1400b5 350 errno = -err;
351 SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
352 veth1, netdev->link);
811ef482
CB
353 goto out_delete;
354 }
355 INFO("Attached \"%s\" to bridge \"%s\"", veth1, netdev->link);
356 }
357
358 err = lxc_netdev_up(veth1);
359 if (err) {
6d1400b5 360 errno = -err;
361 SYSERROR("Failed to set \"%s\" up", veth1);
811ef482
CB
362 goto out_delete;
363 }
364
d4a7da46 365 /* setup ipv4 routes on the host interface */
366 if (lxc_setup_ipv4_routes(&netdev->priv.veth_attr.ipv4_routes, netdev->priv.veth_attr.ifindex)) {
367 ERROR("Failed to setup ipv4 routes for network device \"%s\"", veth1);
368 goto out_delete;
369 }
370
371 /* setup ipv6 routes on the host interface */
372 if (lxc_setup_ipv6_routes(&netdev->priv.veth_attr.ipv6_routes, netdev->priv.veth_attr.ifindex)) {
373 ERROR("Failed to setup ipv6 routes for network device \"%s\"", veth1);
374 goto out_delete;
375 }
376
6dfa9581 377 if (netdev->priv.veth_attr.mode == VETH_MODE_ROUTER) {
954e36b4
TP
378 /* sleep for a short period of time to work around a bug that intermittently prevents IP neighbour
379 proxy entries from being added using lxc_ip_neigh_proxy below. When the issue occurs the entries
380 appear to be added successfully but then do not appear in the proxy list. The length of time
381 slept doesn't appear to be important, only that the process sleeps for a short period of time.
382 */
383 nanosleep((const struct timespec[]){{0, 1000}}, NULL);
384
6dfa9581
TP
385 if (netdev->ipv4_gateway) {
386 char bufinet4[INET_ADDRSTRLEN];
387 if (!inet_ntop(AF_INET, netdev->ipv4_gateway, bufinet4, sizeof(bufinet4))) {
596a002c 388 log_error_errno(-1, -errno, "Failed to convert gateway ipv4 address on \"%s\"", veth1);
6dfa9581
TP
389 goto out_delete;
390 }
391
392 err = lxc_ip_forwarding_on(veth1, AF_INET);
393 if (err) {
596a002c 394 log_error_errno(-1, err, "Failed to activate ipv4 forwarding on \"%s\"", veth1);
6dfa9581
TP
395 goto out_delete;
396 }
397
5fe147e9 398 err = lxc_ip_neigh_proxy(RTM_NEWNEIGH, AF_INET, netdev->priv.veth_attr.ifindex, netdev->ipv4_gateway);
6dfa9581 399 if (err) {
596a002c 400 log_error_errno(-1, err, "Failed to add gateway ipv4 proxy on \"%s\"", veth1);
6dfa9581
TP
401 goto out_delete;
402 }
403 }
404
405 if (netdev->ipv6_gateway) {
406 char bufinet6[INET6_ADDRSTRLEN];
407
408 if (!inet_ntop(AF_INET6, netdev->ipv6_gateway, bufinet6, sizeof(bufinet6))) {
596a002c 409 log_error_errno(-1, -errno, "Failed to convert gateway ipv6 address on \"%s\"", veth1);
6dfa9581
TP
410 goto out_delete;
411 }
412
413 /* Check for sysctl net.ipv6.conf.all.forwarding=1
414 Kernel requires this to route any packets for IPv6.
415 */
416 err = lxc_is_ip_forwarding_enabled("all", AF_INET6);
417 if (err) {
596a002c 418 log_error_errno(-1, err, "Requires sysctl net.ipv6.conf.all.forwarding=1");
6dfa9581
TP
419 goto out_delete;
420 }
421
422 err = lxc_ip_forwarding_on(veth1, AF_INET6);
423 if (err) {
596a002c 424 log_error_errno(-1, err, "Failed to activate ipv6 forwarding on \"%s\"", veth1);
6dfa9581
TP
425 goto out_delete;
426 }
427
428 err = lxc_neigh_proxy_on(veth1, AF_INET6);
429 if (err) {
596a002c 430 log_error_errno(-1, err, "Failed to activate proxy ndp on \"%s\"", veth1);
6dfa9581
TP
431 goto out_delete;
432 }
433
5fe147e9 434 err = lxc_ip_neigh_proxy(RTM_NEWNEIGH, AF_INET6, netdev->priv.veth_attr.ifindex, netdev->ipv6_gateway);
6dfa9581 435 if (err) {
596a002c 436 log_error_errno(-1, err, "Failed to add gateway ipv6 proxy on \"%s\"", veth1);
6dfa9581
TP
437 goto out_delete;
438 }
439 }
440
441 /* setup ipv4 address routes on the host interface */
442 err = setup_ipv4_addr_routes(&netdev->ipv4, netdev->priv.veth_attr.ifindex);
443 if (err) {
596a002c 444 log_error_errno(-1, err, "Failed to setup ip address routes for network device \"%s\"", veth1);
6dfa9581
TP
445 goto out_delete;
446 }
447
448 /* setup ipv6 address routes on the host interface */
449 err = setup_ipv6_addr_routes(&netdev->ipv6, netdev->priv.veth_attr.ifindex);
450 if (err) {
596a002c 451 log_error_errno(-1, err, "Failed to setup ip address routes for network device \"%s\"", veth1);
6dfa9581
TP
452 goto out_delete;
453 }
454 }
455
811ef482 456 if (netdev->upscript) {
14a7b0f9
CB
457 char *argv[] = {
458 "veth",
459 netdev->link,
990b9ac3 460 veth1,
14a7b0f9
CB
461 NULL,
462 };
463
464 err = run_script_argv(handler->name,
465 handler->conf->hooks_version, "net",
466 netdev->upscript, "up", argv);
467 if (err < 0)
811ef482
CB
468 goto out_delete;
469 }
470
54256301 471 DEBUG("Instantiated veth tunnel \"%s <--> %s\"", veth1, veth2);
811ef482
CB
472
473 return 0;
474
475out_delete:
54256301 476 lxc_netdev_delete_by_name(veth1);
811ef482
CB
477 return -1;
478}
479
480static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
481{
8021de25 482 char peer[IFNAMSIZ];
811ef482
CB
483 int err;
484
de4855a8 485 if (netdev->link[0] == '\0') {
811ef482
CB
486 ERROR("No link for macvlan network device specified");
487 return -1;
488 }
489
8021de25
CB
490 err = snprintf(peer, sizeof(peer), "mcXXXXXX");
491 if (err < 0 || (size_t)err >= sizeof(peer))
811ef482
CB
492 return -1;
493
8021de25 494 if (!lxc_mkifname(peer))
811ef482
CB
495 return -1;
496
497 err = lxc_macvlan_create(netdev->link, peer,
498 netdev->priv.macvlan_attr.mode);
499 if (err) {
6d1400b5 500 errno = -err;
501 SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
502 peer, netdev->link);
966e9f1f 503 goto on_error;
811ef482
CB
504 }
505
a9704f05 506 strlcpy(netdev->created_name, peer, IFNAMSIZ);
3473ca76 507 if (is_empty_string(netdev->name))
8bf64b77 508 (void)strlcpy(netdev->name, peer, IFNAMSIZ);
a9704f05 509
811ef482
CB
510 netdev->ifindex = if_nametoindex(peer);
511 if (!netdev->ifindex) {
512 ERROR("Failed to retrieve ifindex for \"%s\"", peer);
966e9f1f 513 goto on_error;
811ef482
CB
514 }
515
3bef7b7b 516 if (netdev->mtu) {
54256301
CB
517 unsigned int mtu;
518
3bef7b7b
TP
519 err = lxc_safe_uint(netdev->mtu, &mtu);
520 if (err < 0) {
521 errno = -err;
522 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
523 goto on_error;
524 }
525
526 err = lxc_netdev_set_mtu(peer, mtu);
527 if (err < 0) {
528 errno = -err;
529 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
530 goto on_error;
531 }
532 }
533
811ef482 534 if (netdev->upscript) {
14a7b0f9
CB
535 char *argv[] = {
536 "macvlan",
537 netdev->link,
538 NULL,
539 };
540
541 err = run_script_argv(handler->name,
542 handler->conf->hooks_version, "net",
543 netdev->upscript, "up", argv);
544 if (err < 0)
966e9f1f 545 goto on_error;
811ef482
CB
546 }
547
548 DEBUG("Instantiated macvlan \"%s\" with ifindex is %d and mode %d",
549 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
550
551 return 0;
966e9f1f
CB
552
553on_error:
811ef482 554 lxc_netdev_delete_by_name(peer);
811ef482
CB
555 return -1;
556}
557
c9f52382 558static int lxc_ipvlan_create(const char *master, const char *name, int mode, int isolation)
559{
560 int err, index, len;
561 struct ifinfomsg *ifi;
562 struct nl_handler nlh;
563 struct rtattr *nest, *nest2;
564 struct nlmsg *answer = NULL, *nlmsg = NULL;
565
566 len = strlen(master);
567 if (len == 1 || len >= IFNAMSIZ)
596a002c 568 return ret_set_errno(-1, EINVAL);
c9f52382 569
570 len = strlen(name);
571 if (len == 1 || len >= IFNAMSIZ)
596a002c 572 return ret_set_errno(-1, EINVAL);
c9f52382 573
574 index = if_nametoindex(master);
575 if (!index)
596a002c 576 return ret_set_errno(-1, EINVAL);
c9f52382 577
578 err = netlink_open(&nlh, NETLINK_ROUTE);
579 if (err)
596a002c 580 return ret_set_errno(-1, -err);
c9f52382 581
582 err = -ENOMEM;
583 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
584 if (!nlmsg)
585 goto out;
586
587 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
588 if (!answer)
589 goto out;
590
591 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
592 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
593
594 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
595 if (!ifi) {
596 goto out;
597 }
598 ifi->ifi_family = AF_UNSPEC;
599
600 err = -EPROTO;
601 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
602 if (!nest)
603 goto out;
604
605 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "ipvlan"))
606 goto out;
607
608 if (mode) {
609 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
610 if (!nest2)
611 goto out;
612
613 if (nla_put_u32(nlmsg, IFLA_IPVLAN_MODE, mode))
614 goto out;
615
616 /* if_link.h does not define the isolation flag value for bridge mode so we define it as 0
617 * and only send mode if mode >0 as default mode is bridge anyway according to ipvlan docs.
618 */
619 if (isolation > 0) {
620 if (nla_put_u16(nlmsg, IFLA_IPVLAN_ISOLATION, isolation))
621 goto out;
622 }
623
624 nla_end_nested(nlmsg, nest2);
625 }
626
627 nla_end_nested(nlmsg, nest);
628
629 if (nla_put_u32(nlmsg, IFLA_LINK, index))
630 goto out;
631
632 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
633 goto out;
634
635 err = netlink_transaction(&nlh, nlmsg, answer);
636out:
637 netlink_close(&nlh);
638 nlmsg_free(answer);
639 nlmsg_free(nlmsg);
640 if (err < 0)
596a002c 641 return ret_set_errno(-1, -err);
c9f52382 642 return 0;
643}
644
645static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
646{
dd119206 647 char peer[IFNAMSIZ];
c9f52382 648 int err;
649
650 if (netdev->link[0] == '\0') {
651 ERROR("No link for ipvlan network device specified");
652 return -1;
653 }
654
dd119206
CB
655 err = snprintf(peer, sizeof(peer), "ipXXXXXX");
656 if (err < 0 || (size_t)err >= sizeof(peer))
c9f52382 657 return -1;
658
dd119206 659 if (!lxc_mkifname(peer))
c9f52382 660 return -1;
661
dd119206
CB
662 err = lxc_ipvlan_create(netdev->link, peer, netdev->priv.ipvlan_attr.mode,
663 netdev->priv.ipvlan_attr.isolation);
c9f52382 664 if (err) {
dd119206
CB
665 SYSERROR("Failed to create ipvlan interface \"%s\" on \"%s\"",
666 peer, netdev->link);
c9f52382 667 goto on_error;
668 }
669
e7fdd504 670 strlcpy(netdev->created_name, peer, IFNAMSIZ);
3473ca76 671 if (is_empty_string(netdev->name))
8bf64b77 672 (void)strlcpy(netdev->name, peer, IFNAMSIZ);
e7fdd504 673
c9f52382 674 netdev->ifindex = if_nametoindex(peer);
675 if (!netdev->ifindex) {
676 ERROR("Failed to retrieve ifindex for \"%s\"", peer);
677 goto on_error;
678 }
679
006e135e 680 if (netdev->mtu) {
54256301
CB
681 unsigned int mtu;
682
006e135e 683 err = lxc_safe_uint(netdev->mtu, &mtu);
684 if (err < 0) {
685 errno = -err;
54256301 686 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
006e135e 687 goto on_error;
688 }
689
690 err = lxc_netdev_set_mtu(peer, mtu);
691 if (err < 0) {
692 errno = -err;
54256301 693 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
006e135e 694 goto on_error;
695 }
696 }
697
c9f52382 698 if (netdev->upscript) {
699 char *argv[] = {
700 "ipvlan",
701 netdev->link,
702 NULL,
703 };
704
dd119206
CB
705 err = run_script_argv(handler->name, handler->conf->hooks_version,
706 "net", netdev->upscript, "up", argv);
c9f52382 707 if (err < 0)
708 goto on_error;
709 }
710
dd119206
CB
711 DEBUG("Instantiated ipvlan \"%s\" with ifindex is %d and mode %d", peer,
712 netdev->ifindex, netdev->priv.macvlan_attr.mode);
c9f52382 713
714 return 0;
715
716on_error:
717 lxc_netdev_delete_by_name(peer);
718 return -1;
719}
720
811ef482
CB
721static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
722{
723 char peer[IFNAMSIZ];
724 int err;
725 static uint16_t vlan_cntr = 0;
811ef482 726
de4855a8 727 if (netdev->link[0] == '\0') {
811ef482
CB
728 ERROR("No link for vlan network device specified");
729 return -1;
730 }
731
d4d68410
CB
732 err = snprintf(peer, sizeof(peer), "vlan%d-%d",
733 netdev->priv.vlan_attr.vid, vlan_cntr++);
811ef482
CB
734 if (err < 0 || (size_t)err >= sizeof(peer))
735 return -1;
736
737 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
738 if (err) {
6d1400b5 739 errno = -err;
740 SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
741 peer, netdev->link);
811ef482
CB
742 return -1;
743 }
744
83530dba 745 strlcpy(netdev->created_name, peer, IFNAMSIZ);
3473ca76 746 if (is_empty_string(netdev->name))
8bf64b77 747 (void)strlcpy(netdev->name, peer, IFNAMSIZ);
83530dba 748
811ef482
CB
749 netdev->ifindex = if_nametoindex(peer);
750 if (!netdev->ifindex) {
751 ERROR("Failed to retrieve ifindex for \"%s\"", peer);
3e2a7b08 752 goto on_error;
753 }
754
755 if (netdev->mtu) {
54256301
CB
756 unsigned int mtu;
757
3e2a7b08 758 err = lxc_safe_uint(netdev->mtu, &mtu);
759 if (err < 0) {
760 errno = -err;
54256301 761 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
3e2a7b08 762 goto on_error;
763 }
764
765 err = lxc_netdev_set_mtu(peer, mtu);
54256301 766 if (err < 0) {
3e2a7b08 767 errno = -err;
54256301 768 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
3e2a7b08 769 goto on_error;
770 }
811ef482
CB
771 }
772
3a73d9f1 773 if (netdev->upscript) {
774 char *argv[] = {
775 "vlan",
776 netdev->link,
777 NULL,
778 };
779
d4d68410
CB
780 err = run_script_argv(handler->name, handler->conf->hooks_version,
781 "net", netdev->upscript, "up", argv);
19abca58 782 if (err < 0) {
3e2a7b08 783 goto on_error;
19abca58 784 }
3a73d9f1 785 }
786
d4d68410
CB
787 DEBUG("Instantiated vlan \"%s\" with ifindex is \"%d\"", peer,
788 netdev->ifindex);
811ef482
CB
789
790 return 0;
3e2a7b08 791
792on_error:
793 lxc_netdev_delete_by_name(peer);
794 return -1;
811ef482
CB
795}
796
797static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
798{
0b154989 799 int err, mtu_orig = 0;
14a7b0f9 800
de4855a8 801 if (netdev->link[0] == '\0') {
811ef482
CB
802 ERROR("No link for physical interface specified");
803 return -1;
804 }
805
75b074ee
CB
806 /*
807 * Note that we're retrieving the container's ifindex in the host's
790255cf
CB
808 * network namespace because we need it to move the device from the
809 * host's network namespace to the container's network namespace later
810 * on.
811 * Note that netdev->link will contain the name of the physical network
812 * device in the host's namespace.
813 */
811ef482
CB
814 netdev->ifindex = if_nametoindex(netdev->link);
815 if (!netdev->ifindex) {
816 ERROR("Failed to retrieve ifindex for \"%s\"", netdev->link);
817 return -1;
818 }
819
61302ef7 820 strlcpy(netdev->created_name, netdev->link, IFNAMSIZ);
3473ca76 821 if (is_empty_string(netdev->name))
8bf64b77 822 (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
61302ef7 823
75b074ee
CB
824 /*
825 * Store the ifindex of the host's network device in the host's
790255cf
CB
826 * namespace.
827 */
828 netdev->priv.phys_attr.ifindex = netdev->ifindex;
829
75b074ee
CB
830 /*
831 * Get original device MTU setting and store for restoration after
832 * container shutdown.
833 */
0b154989
TP
834 mtu_orig = netdev_get_mtu(netdev->ifindex);
835 if (mtu_orig < 0) {
836 SYSERROR("Failed to get original mtu for interface \"%s\"", netdev->link);
596a002c 837 return ret_set_errno(-1, -mtu_orig);
0b154989
TP
838 }
839
840 netdev->priv.phys_attr.mtu = mtu_orig;
841
3bef7b7b 842 if (netdev->mtu) {
54256301
CB
843 unsigned int mtu;
844
3bef7b7b
TP
845 err = lxc_safe_uint(netdev->mtu, &mtu);
846 if (err < 0) {
847 errno = -err;
75b074ee
CB
848 SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"",
849 netdev->mtu, netdev->link);
3bef7b7b
TP
850 return -1;
851 }
14a7b0f9 852
3bef7b7b
TP
853 err = lxc_netdev_set_mtu(netdev->link, mtu);
854 if (err < 0) {
855 errno = -err;
54256301 856 SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, netdev->link);
3bef7b7b
TP
857 return -1;
858 }
859 }
860
861 if (netdev->upscript) {
862 char *argv[] = {
863 "phys",
864 netdev->link,
865 NULL,
866 };
867
75b074ee
CB
868 err = run_script_argv(handler->name, handler->conf->hooks_version,
869 "net", netdev->upscript, "up", argv);
3bef7b7b
TP
870 if (err < 0) {
871 return -1;
872 }
873 }
874
75b074ee
CB
875 DEBUG("Instantiated phys \"%s\" with ifindex is \"%d\"", netdev->link,
876 netdev->ifindex);
811ef482
CB
877
878 return 0;
879}
880
881static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
882{
14a7b0f9
CB
883 int ret;
884 char *argv[] = {
885 "empty",
886 NULL,
887 };
888
811ef482 889 netdev->ifindex = 0;
14a7b0f9
CB
890 if (!netdev->upscript)
891 return 0;
892
893 ret = run_script_argv(handler->name, handler->conf->hooks_version,
894 "net", netdev->upscript, "up", argv);
895 if (ret < 0)
896 return -1;
897
811ef482
CB
898 return 0;
899}
900
901static int instantiate_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
902{
903 netdev->ifindex = 0;
904 return 0;
905}
906
907static instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
908 [LXC_NET_VETH] = instantiate_veth,
909 [LXC_NET_MACVLAN] = instantiate_macvlan,
c9f52382 910 [LXC_NET_IPVLAN] = instantiate_ipvlan,
811ef482
CB
911 [LXC_NET_VLAN] = instantiate_vlan,
912 [LXC_NET_PHYS] = instantiate_phys,
913 [LXC_NET_EMPTY] = instantiate_empty,
914 [LXC_NET_NONE] = instantiate_none,
915};
916
8bf64b77
CB
917static int instantiate_ns_veth(struct lxc_netdev *netdev)
918{
919 char current_ifname[IFNAMSIZ];
920
921 netdev->ifindex = if_nametoindex(netdev->created_name);
922 if (!netdev->ifindex)
923 return log_error_errno(-1,
924 errno, "Failed to retrieve ifindex for network device with name %s",
925 netdev->created_name);
926
3473ca76 927 if (is_empty_string(netdev->name))
8bf64b77
CB
928 (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
929
930 if (strcmp(netdev->created_name, netdev->name) != 0) {
931 int ret;
932
933 ret = lxc_netdev_rename_by_name(netdev->created_name, netdev->name);
934 if (ret)
935 return log_error_errno(-1,
936 -ret, "Failed to rename network device \"%s\" to \"%s\"",
937 netdev->created_name,
938 netdev->name);
939
940 TRACE("Renamed network device from \"%s\" to \"%s\"", netdev->created_name, netdev->name);
941 }
942
943 /*
944 * Re-read the name of the interface because its name has changed and
945 * would be automatically allocated by the system
946 */
947 if (!if_indextoname(netdev->ifindex, current_ifname))
948 return log_error_errno(-1,
949 errno, "Failed get name for network device with ifindex %d",
950 netdev->ifindex);
951
952 /*
953 * Now update the recorded name of the network device to reflect the
954 * name of the network device in the child's network namespace. We will
955 * later on send this information back to the parent.
956 */
957 (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
958
959 return 0;
960}
961
962static int __instantiate_common(struct lxc_netdev *netdev)
963{
964 netdev->ifindex = if_nametoindex(netdev->name);
965 if (!netdev->ifindex)
966 return log_error_errno(-1,
967 errno, "Failed to retrieve ifindex for network device with name %s",
968 netdev->name);
969
970 return 0;
971}
972
973static int instantiate_ns_macvlan(struct lxc_netdev *netdev)
974{
975 return __instantiate_common(netdev);
976}
977
978static int instantiate_ns_ipvlan(struct lxc_netdev *netdev)
979{
980 return __instantiate_common(netdev);
981}
982
983static int instantiate_ns_vlan(struct lxc_netdev *netdev)
984{
985 return __instantiate_common(netdev);
986}
987
988static int instantiate_ns_phys(struct lxc_netdev *netdev)
989{
990 return __instantiate_common(netdev);
991}
992
993static int instantiate_ns_empty(struct lxc_netdev *netdev)
994{
995 return 0;
996}
997
998static int instantiate_ns_none(struct lxc_netdev *netdev)
999{
1000 return 0;
1001}
1002
1003static instantiate_ns_cb netdev_ns_conf[LXC_NET_MAXCONFTYPE + 1] = {
1004 [LXC_NET_VETH] = instantiate_ns_veth,
1005 [LXC_NET_MACVLAN] = instantiate_ns_macvlan,
1006 [LXC_NET_IPVLAN] = instantiate_ns_ipvlan,
1007 [LXC_NET_VLAN] = instantiate_ns_vlan,
1008 [LXC_NET_PHYS] = instantiate_ns_phys,
1009 [LXC_NET_EMPTY] = instantiate_ns_empty,
1010 [LXC_NET_NONE] = instantiate_ns_none,
1011};
1012
811ef482
CB
1013static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
1014{
14a7b0f9
CB
1015 int ret;
1016 char *argv[] = {
1017 "veth",
1018 netdev->link,
1019 NULL,
1020 NULL,
1021 };
1022
1023 if (!netdev->downscript)
1024 return 0;
811ef482 1025
de4855a8 1026 if (netdev->priv.veth_attr.pair[0] != '\0')
14a7b0f9 1027 argv[2] = netdev->priv.veth_attr.pair;
811ef482 1028 else
14a7b0f9
CB
1029 argv[2] = netdev->priv.veth_attr.veth1;
1030
1031 ret = run_script_argv(handler->name,
1032 handler->conf->hooks_version, "net",
1033 netdev->downscript, "down", argv);
1034 if (ret < 0)
1035 return -1;
811ef482 1036
811ef482
CB
1037 return 0;
1038}
1039
1040static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
1041{
14a7b0f9
CB
1042 int ret;
1043 char *argv[] = {
1044 "macvlan",
1045 netdev->link,
1046 NULL,
1047 };
1048
1049 if (!netdev->downscript)
1050 return 0;
1051
1052 ret = run_script_argv(handler->name, handler->conf->hooks_version,
1053 "net", netdev->downscript, "down", argv);
1054 if (ret < 0)
1055 return -1;
811ef482 1056
811ef482
CB
1057 return 0;
1058}
1059
c9f52382 1060static int shutdown_ipvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
1061{
1062 int ret;
1063 char *argv[] = {
1064 "ipvlan",
1065 netdev->link,
1066 NULL,
1067 };
1068
1069 if (!netdev->downscript)
1070 return 0;
1071
1072 ret = run_script_argv(handler->name, handler->conf->hooks_version,
1073 "net", netdev->downscript, "down", argv);
1074 if (ret < 0)
1075 return -1;
1076
1077 return 0;
1078}
1079
811ef482
CB
1080static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
1081{
3a73d9f1 1082 int ret;
1083 char *argv[] = {
1084 "vlan",
1085 netdev->link,
1086 NULL,
1087 };
1088
1089 if (!netdev->downscript)
1090 return 0;
1091
1092 ret = run_script_argv(handler->name, handler->conf->hooks_version,
1093 "net", netdev->downscript, "down", argv);
1094 if (ret < 0)
1095 return -1;
1096
811ef482
CB
1097 return 0;
1098}
1099
1100static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
1101{
14a7b0f9
CB
1102 int ret;
1103 char *argv[] = {
1104 "phys",
1105 netdev->link,
1106 NULL,
1107 };
1108
1109 if (!netdev->downscript)
1110 return 0;
1111
1112 ret = run_script_argv(handler->name, handler->conf->hooks_version,
1113 "net", netdev->downscript, "down", argv);
1114 if (ret < 0)
1115 return -1;
811ef482 1116
811ef482
CB
1117 return 0;
1118}
1119
1120static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
1121{
14a7b0f9
CB
1122 int ret;
1123 char *argv[] = {
1124 "empty",
1125 NULL,
1126 };
1127
1128 if (!netdev->downscript)
1129 return 0;
1130
1131 ret = run_script_argv(handler->name, handler->conf->hooks_version,
1132 "net", netdev->downscript, "down", argv);
1133 if (ret < 0)
1134 return -1;
811ef482 1135
811ef482
CB
1136 return 0;
1137}
1138
1139static int shutdown_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
1140{
1141 return 0;
1142}
1143
1144static instantiate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
1145 [LXC_NET_VETH] = shutdown_veth,
1146 [LXC_NET_MACVLAN] = shutdown_macvlan,
c9f52382 1147 [LXC_NET_IPVLAN] = shutdown_ipvlan,
811ef482
CB
1148 [LXC_NET_VLAN] = shutdown_vlan,
1149 [LXC_NET_PHYS] = shutdown_phys,
1150 [LXC_NET_EMPTY] = shutdown_empty,
1151 [LXC_NET_NONE] = shutdown_none,
1152};
1153
0037ab49
TP
1154static int lxc_netdev_move_by_index_fd(int ifindex, int fd, const char *ifname)
1155{
1156 int err;
1157 struct nl_handler nlh;
1158 struct ifinfomsg *ifi;
1159 struct nlmsg *nlmsg = NULL;
1160
1161 err = netlink_open(&nlh, NETLINK_ROUTE);
1162 if (err)
1163 return err;
1164
1165 err = -ENOMEM;
1166 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1167 if (!nlmsg)
1168 goto out;
1169
1170 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1171 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1172
1173 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
1174 if (!ifi)
1175 goto out;
1176 ifi->ifi_family = AF_UNSPEC;
1177 ifi->ifi_index = ifindex;
1178
1179 if (nla_put_u32(nlmsg, IFLA_NET_NS_FD, fd))
1180 goto out;
1181
3473ca76
CB
1182 if (!is_empty_string(ifname) && nla_put_string(nlmsg, IFLA_IFNAME, ifname))
1183 goto out;
0037ab49
TP
1184
1185 err = netlink_transaction(&nlh, nlmsg, nlmsg);
1186out:
1187 netlink_close(&nlh);
1188 nlmsg_free(nlmsg);
1189 return err;
1190}
1191
ebc73a67 1192int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char *ifname)
0ad19a3f 1193{
ebc73a67 1194 int err;
0ad19a3f 1195 struct nl_handler nlh;
06f976ca 1196 struct ifinfomsg *ifi;
ebc73a67 1197 struct nlmsg *nlmsg = NULL;
0ad19a3f 1198
3cfc0f3a
MN
1199 err = netlink_open(&nlh, NETLINK_ROUTE);
1200 if (err)
1201 return err;
0ad19a3f 1202
3cfc0f3a 1203 err = -ENOMEM;
0ad19a3f 1204 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1205 if (!nlmsg)
1206 goto out;
1207
ebc73a67 1208 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
1209 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1210
1211 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1212 if (!ifi)
1213 goto out;
06f976ca
SZ
1214 ifi->ifi_family = AF_UNSPEC;
1215 ifi->ifi_index = ifindex;
0ad19a3f 1216
1217 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
1218 goto out;
1219
3473ca76
CB
1220 if (!is_empty_string(ifname) && nla_put_string(nlmsg, IFLA_IFNAME, ifname))
1221 goto out;
8d357196 1222
3cfc0f3a 1223 err = netlink_transaction(&nlh, nlmsg, nlmsg);
0ad19a3f 1224out:
1225 netlink_close(&nlh);
1226 nlmsg_free(nlmsg);
1227 return err;
1228}
1229
ebc73a67
CB
1230/* If we are asked to move a wireless interface, then we must actually move its
1231 * phyN device. Detect that condition and return the physname here. The physname
1232 * will be passed to lxc_netdev_move_wlan() which will free it when done.
e5848d39
SH
1233 */
1234#define PHYSNAME "/sys/class/net/%s/phy80211/name"
e4103cf6 1235char *is_wlan(const char *ifname)
e5848d39 1236{
4110345b
CB
1237 __do_fclose FILE *f = NULL;
1238 __do_free char *path = NULL, *physname = NULL;
ebc73a67 1239 int i, ret;
e5848d39 1240 long physlen;
ebc73a67 1241 size_t len;
e5848d39 1242
ebc73a67 1243 len = strlen(ifname) + strlen(PHYSNAME) - 1;
95ea3d1f 1244 path = must_realloc(NULL, len + 1);
e5848d39 1245 ret = snprintf(path, len, PHYSNAME, ifname);
ebc73a67 1246 if (ret < 0 || (size_t)ret >= len)
4110345b 1247 return NULL;
ebc73a67 1248
4110345b 1249 f = fopen(path, "re");
ebc73a67 1250 if (!f)
4110345b 1251 return NULL;
ebc73a67 1252
1a0e70ac 1253 /* Feh - sb.st_size is always 4096. */
e5848d39
SH
1254 fseek(f, 0, SEEK_END);
1255 physlen = ftell(f);
1256 fseek(f, 0, SEEK_SET);
4110345b
CB
1257 if (physlen < 0)
1258 return NULL;
ebc73a67
CB
1259
1260 physname = malloc(physlen + 1);
4110345b
CB
1261 if (!physname)
1262 return NULL;
ebc73a67
CB
1263
1264 memset(physname, 0, physlen + 1);
e5848d39 1265 ret = fread(physname, 1, physlen, f);
e5848d39 1266 if (ret < 0)
4110345b 1267 return NULL;
e5848d39 1268
ebc73a67 1269 for (i = 0; i < physlen; i++) {
e5848d39
SH
1270 if (physname[i] == '\n')
1271 physname[i] = '\0';
ebc73a67 1272
e5848d39
SH
1273 if (physname[i] == '\0')
1274 break;
1275 }
1276
4110345b 1277 return move_ptr(physname);
e5848d39
SH
1278}
1279
ebc73a67
CB
1280static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
1281 const char *new)
e5848d39 1282{
ebc73a67 1283 pid_t fpid;
e5848d39 1284
ebc73a67 1285 fpid = fork();
e5848d39
SH
1286 if (fpid < 0)
1287 return -1;
ebc73a67 1288
e5848d39
SH
1289 if (fpid != 0)
1290 return wait_for_pid(fpid);
ebc73a67 1291
e5848d39
SH
1292 if (!switch_to_ns(pid, "net"))
1293 return -1;
ebc73a67 1294
05ec44f8 1295 _exit(lxc_netdev_rename_by_name(old, new));
e5848d39
SH
1296}
1297
e4103cf6 1298int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
ebc73a67 1299 const char *newname)
e5848d39 1300{
3dd78294 1301 __do_free char *cmd = NULL;
ebc73a67 1302 pid_t fpid;
e5848d39
SH
1303
1304 /* Move phyN into the container. TODO - do this using netlink.
ebc73a67
CB
1305 * However, IIUC this involves a bit more complicated work to talk to
1306 * the 80211 module, so for now just call out to iw.
e5848d39
SH
1307 */
1308 cmd = on_path("iw", NULL);
3dd78294
CB
1309 if (!cmd) {
1310 return -1;
1311 }
e5848d39
SH
1312
1313 fpid = fork();
1314 if (fpid < 0)
3dd78294 1315 return -1;
ebc73a67 1316
e5848d39
SH
1317 if (fpid == 0) {
1318 char pidstr[30];
1319 sprintf(pidstr, "%d", pid);
ebc73a67
CB
1320 execlp("iw", "iw", "phy", physname, "set", "netns", pidstr,
1321 (char *)NULL);
ebd582ae 1322 _exit(EXIT_FAILURE);
e5848d39 1323 }
ebc73a67 1324
e5848d39 1325 if (wait_for_pid(fpid))
3dd78294 1326 return -1;
e5848d39 1327
e5848d39 1328 if (newname)
3dd78294 1329 return lxc_netdev_rename_by_name_in_netns(pid, ifname, newname);
e5848d39 1330
3dd78294 1331 return 0;
e5848d39
SH
1332}
1333
8d357196 1334int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
8befa924 1335{
3dd78294 1336 __do_free char *physname = NULL;
8befa924
SH
1337 int index;
1338
8befa924
SH
1339 if (!ifname)
1340 return -EINVAL;
1341
32571606 1342 index = if_nametoindex(ifname);
49428bf3
DY
1343 if (!index)
1344 return -EINVAL;
32571606 1345
ebc73a67
CB
1346 physname = is_wlan(ifname);
1347 if (physname)
e5848d39
SH
1348 return lxc_netdev_move_wlan(physname, ifname, pid, newname);
1349
8d357196 1350 return lxc_netdev_move_by_index(index, pid, newname);
8befa924
SH
1351}
1352
b84f58b9 1353int lxc_netdev_delete_by_index(int ifindex)
0ad19a3f 1354{
b84f58b9 1355 int err;
ebc73a67
CB
1356 struct ifinfomsg *ifi;
1357 struct nl_handler nlh;
1358 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 1359
3cfc0f3a
MN
1360 err = netlink_open(&nlh, NETLINK_ROUTE);
1361 if (err)
1362 return err;
0ad19a3f 1363
3cfc0f3a 1364 err = -ENOMEM;
0ad19a3f 1365 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1366 if (!nlmsg)
1367 goto out;
1368
06f976ca 1369 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 1370 if (!answer)
1371 goto out;
1372
ebc73a67 1373 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
06f976ca
SZ
1374 nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
1375
1376 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1377 if (!ifi)
1378 goto out;
06f976ca
SZ
1379 ifi->ifi_family = AF_UNSPEC;
1380 ifi->ifi_index = ifindex;
0ad19a3f 1381
3cfc0f3a 1382 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 1383out:
1384 netlink_close(&nlh);
1385 nlmsg_free(answer);
1386 nlmsg_free(nlmsg);
1387 return err;
1388}
1389
b84f58b9
DL
1390int lxc_netdev_delete_by_name(const char *name)
1391{
1392 int index;
1393
1394 index = if_nametoindex(name);
1395 if (!index)
1396 return -EINVAL;
1397
1398 return lxc_netdev_delete_by_index(index);
1399}
1400
1401int lxc_netdev_rename_by_index(int ifindex, const char *newname)
b9a5bb58 1402{
ebc73a67 1403 int err, len;
06f976ca 1404 struct ifinfomsg *ifi;
ebc73a67
CB
1405 struct nl_handler nlh;
1406 struct nlmsg *answer = NULL, *nlmsg = NULL;
b9a5bb58 1407
3cfc0f3a
MN
1408 err = netlink_open(&nlh, NETLINK_ROUTE);
1409 if (err)
1410 return err;
b9a5bb58 1411
b84f58b9 1412 len = strlen(newname);
90d79629
CB
1413 if (len == 1 || len >= IFNAMSIZ) {
1414 err = -EINVAL;
b84f58b9 1415 goto out;
90d79629 1416 }
b84f58b9 1417
3cfc0f3a 1418 err = -ENOMEM;
b9a5bb58
DL
1419 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1420 if (!nlmsg)
1421 goto out;
1422
06f976ca 1423 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
b9a5bb58
DL
1424 if (!answer)
1425 goto out;
1426
ebc73a67 1427 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
06f976ca
SZ
1428 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1429
1430 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1431 if (!ifi)
1432 goto out;
06f976ca
SZ
1433 ifi->ifi_family = AF_UNSPEC;
1434 ifi->ifi_index = ifindex;
b84f58b9
DL
1435
1436 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
1437 goto out;
b9a5bb58 1438
3cfc0f3a 1439 err = netlink_transaction(&nlh, nlmsg, answer);
b9a5bb58
DL
1440out:
1441 netlink_close(&nlh);
1442 nlmsg_free(answer);
1443 nlmsg_free(nlmsg);
1444 return err;
1445}
1446
b84f58b9
DL
1447int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
1448{
1449 int len, index;
1450
1451 len = strlen(oldname);
dae3fdf6 1452 if (len == 1 || len >= IFNAMSIZ)
b84f58b9
DL
1453 return -EINVAL;
1454
1455 index = if_nametoindex(oldname);
1456 if (!index)
1457 return -EINVAL;
1458
1459 return lxc_netdev_rename_by_index(index, newname);
1460}
1461
8befa924 1462int netdev_set_flag(const char *name, int flag)
0ad19a3f 1463{
ebc73a67 1464 int err, index, len;
06f976ca 1465 struct ifinfomsg *ifi;
ebc73a67
CB
1466 struct nl_handler nlh;
1467 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 1468
3cfc0f3a
MN
1469 err = netlink_open(&nlh, NETLINK_ROUTE);
1470 if (err)
1471 return err;
0ad19a3f 1472
3cfc0f3a 1473 err = -EINVAL;
0ad19a3f 1474 len = strlen(name);
dae3fdf6 1475 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 1476 goto out;
1477
3cfc0f3a 1478 err = -ENOMEM;
0ad19a3f 1479 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1480 if (!nlmsg)
1481 goto out;
1482
06f976ca 1483 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 1484 if (!answer)
1485 goto out;
1486
3cfc0f3a 1487 err = -EINVAL;
0ad19a3f 1488 index = if_nametoindex(name);
1489 if (!index)
1490 goto out;
1491
ebc73a67 1492 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
1493 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1494
1495 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1496 if (!ifi) {
1497 err = -ENOMEM;
1498 goto out;
1499 }
06f976ca
SZ
1500 ifi->ifi_family = AF_UNSPEC;
1501 ifi->ifi_index = index;
1502 ifi->ifi_change |= IFF_UP;
1503 ifi->ifi_flags |= flag;
0ad19a3f 1504
1505 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 1506out:
1507 netlink_close(&nlh);
1508 nlmsg_free(nlmsg);
1509 nlmsg_free(answer);
1510 return err;
1511}
1512
ebc73a67 1513int netdev_get_flag(const char *name, int *flag)
efa1cf45 1514{
ebc73a67 1515 int err, index, len;
a4318300 1516 struct ifinfomsg *ifi;
ebc73a67
CB
1517 struct nl_handler nlh;
1518 struct nlmsg *answer = NULL, *nlmsg = NULL;
efa1cf45
DY
1519
1520 if (!name)
1521 return -EINVAL;
1522
1523 err = netlink_open(&nlh, NETLINK_ROUTE);
1524 if (err)
1525 return err;
1526
1527 err = -EINVAL;
1528 len = strlen(name);
1529 if (len == 1 || len >= IFNAMSIZ)
1530 goto out;
1531
1532 err = -ENOMEM;
1533 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1534 if (!nlmsg)
1535 goto out;
1536
06f976ca 1537 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
efa1cf45
DY
1538 if (!answer)
1539 goto out;
1540
1541 err = -EINVAL;
1542 index = if_nametoindex(name);
1543 if (!index)
1544 goto out;
1545
06f976ca
SZ
1546 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
1547 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
1548
1549 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1550 if (!ifi) {
1551 err = -ENOMEM;
1552 goto out;
1553 }
06f976ca
SZ
1554 ifi->ifi_family = AF_UNSPEC;
1555 ifi->ifi_index = index;
efa1cf45
DY
1556
1557 err = netlink_transaction(&nlh, nlmsg, answer);
1558 if (err)
1559 goto out;
1560
06f976ca 1561 ifi = NLMSG_DATA(answer->nlmsghdr);
efa1cf45
DY
1562
1563 *flag = ifi->ifi_flags;
1564out:
1565 netlink_close(&nlh);
1566 nlmsg_free(nlmsg);
1567 nlmsg_free(answer);
1568 return err;
1569}
1570
1571/*
1572 * \brief Check a interface is up or not.
1573 *
1574 * \param name: name for the interface.
1575 *
1576 * \return int.
1577 * 0 means interface is down.
1578 * 1 means interface is up.
1579 * Others means error happened, and ret-value is the error number.
1580 */
ebc73a67 1581int lxc_netdev_isup(const char *name)
efa1cf45 1582{
ebc73a67 1583 int err, flag;
efa1cf45
DY
1584
1585 err = netdev_get_flag(name, &flag);
1586 if (err)
ebc73a67
CB
1587 return err;
1588
efa1cf45
DY
1589 if (flag & IFF_UP)
1590 return 1;
ebc73a67 1591
efa1cf45 1592 return 0;
efa1cf45
DY
1593}
1594
0130df54
SH
1595int netdev_get_mtu(int ifindex)
1596{
ebc73a67 1597 int answer_len, err, res;
0130df54 1598 struct nl_handler nlh;
06f976ca 1599 struct ifinfomsg *ifi;
0130df54 1600 struct nlmsghdr *msg;
ebc73a67
CB
1601 int readmore = 0, recv_len = 0;
1602 struct nlmsg *answer = NULL, *nlmsg = NULL;
0130df54
SH
1603
1604 err = netlink_open(&nlh, NETLINK_ROUTE);
1605 if (err)
1606 return err;
1607
1608 err = -ENOMEM;
1609 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1610 if (!nlmsg)
1611 goto out;
1612
06f976ca 1613 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0130df54
SH
1614 if (!answer)
1615 goto out;
1616
1617 /* Save the answer buffer length, since it will be overwritten
1618 * on the first receive (and we might need to receive more than
ebc73a67
CB
1619 * once.
1620 */
06f976ca
SZ
1621 answer_len = answer->nlmsghdr->nlmsg_len;
1622
ebc73a67 1623 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
06f976ca 1624 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
0130df54 1625
06f976ca 1626 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1627 if (!ifi)
1628 goto out;
06f976ca 1629 ifi->ifi_family = AF_UNSPEC;
0130df54
SH
1630
1631 /* Send the request for addresses, which returns all addresses
1632 * on all interfaces. */
1633 err = netlink_send(&nlh, nlmsg);
1634 if (err < 0)
1635 goto out;
1636
6ce39620
CB
1637#pragma GCC diagnostic push
1638#pragma GCC diagnostic ignored "-Wcast-align"
1639
0130df54
SH
1640 do {
1641 /* Restore the answer buffer length, it might have been
ebc73a67
CB
1642 * overwritten by a previous receive.
1643 */
06f976ca 1644 answer->nlmsghdr->nlmsg_len = answer_len;
0130df54
SH
1645
1646 /* Get the (next) batch of reply messages */
1647 err = netlink_rcv(&nlh, answer);
1648 if (err < 0)
1649 goto out;
1650
1651 recv_len = err;
0130df54
SH
1652
1653 /* Satisfy the typing for the netlink macros */
06f976ca 1654 msg = answer->nlmsghdr;
0130df54
SH
1655
1656 while (NLMSG_OK(msg, recv_len)) {
1657
1658 /* Stop reading if we see an error message */
1659 if (msg->nlmsg_type == NLMSG_ERROR) {
ebc73a67
CB
1660 struct nlmsgerr *errmsg =
1661 (struct nlmsgerr *)NLMSG_DATA(msg);
0130df54
SH
1662 err = errmsg->error;
1663 goto out;
1664 }
1665
1666 /* Stop reading if we see a NLMSG_DONE message */
1667 if (msg->nlmsg_type == NLMSG_DONE) {
1668 readmore = 0;
1669 break;
1670 }
1671
06f976ca 1672 ifi = NLMSG_DATA(msg);
0130df54
SH
1673 if (ifi->ifi_index == ifindex) {
1674 struct rtattr *rta = IFLA_RTA(ifi);
ebc73a67
CB
1675 int attr_len =
1676 msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
0130df54 1677 res = 0;
ebc73a67
CB
1678 while (RTA_OK(rta, attr_len)) {
1679 /* Found a local address for the
1680 * requested interface, return it.
1681 */
0130df54 1682 if (rta->rta_type == IFLA_MTU) {
ebc73a67
CB
1683 memcpy(&res, RTA_DATA(rta),
1684 sizeof(int));
0130df54
SH
1685 err = res;
1686 goto out;
1687 }
1688 rta = RTA_NEXT(rta, attr_len);
1689 }
0130df54
SH
1690 }
1691
ebc73a67
CB
1692 /* Keep reading more data from the socket if the last
1693 * message had the NLF_F_MULTI flag set.
1694 */
0130df54
SH
1695 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1696
ebc73a67 1697 /* Look at the next message received in this buffer. */
0130df54
SH
1698 msg = NLMSG_NEXT(msg, recv_len);
1699 }
1700 } while (readmore);
1701
6ce39620
CB
1702#pragma GCC diagnostic pop
1703
ebc73a67 1704 /* If we end up here, we didn't find any result, so signal an error. */
0130df54
SH
1705 err = -1;
1706
1707out:
1708 netlink_close(&nlh);
1709 nlmsg_free(answer);
1710 nlmsg_free(nlmsg);
1711 return err;
1712}
1713
d472214b 1714int lxc_netdev_set_mtu(const char *name, int mtu)
75d09f83 1715{
54256301 1716 int err, len;
06f976ca 1717 struct ifinfomsg *ifi;
ebc73a67
CB
1718 struct nl_handler nlh;
1719 struct nlmsg *answer = NULL, *nlmsg = NULL;
75d09f83 1720
3cfc0f3a
MN
1721 err = netlink_open(&nlh, NETLINK_ROUTE);
1722 if (err)
1723 return err;
75d09f83 1724
3cfc0f3a 1725 err = -EINVAL;
75d09f83 1726 len = strlen(name);
dae3fdf6 1727 if (len == 1 || len >= IFNAMSIZ)
75d09f83
DL
1728 goto out;
1729
3cfc0f3a 1730 err = -ENOMEM;
75d09f83
DL
1731 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1732 if (!nlmsg)
1733 goto out;
1734
06f976ca 1735 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
75d09f83
DL
1736 if (!answer)
1737 goto out;
1738
ebc73a67 1739 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
1740 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1741
1742 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1743 if (!ifi) {
1744 err = -ENOMEM;
1745 goto out;
1746 }
06f976ca 1747 ifi->ifi_family = AF_UNSPEC;
54256301
CB
1748
1749 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
1750 goto out;
75d09f83
DL
1751
1752 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
1753 goto out;
1754
1755 err = netlink_transaction(&nlh, nlmsg, answer);
75d09f83
DL
1756out:
1757 netlink_close(&nlh);
1758 nlmsg_free(nlmsg);
1759 nlmsg_free(answer);
1760 return err;
1761}
1762
d472214b 1763int lxc_netdev_up(const char *name)
0ad19a3f 1764{
d472214b 1765 return netdev_set_flag(name, IFF_UP);
0ad19a3f 1766}
1767
d472214b 1768int lxc_netdev_down(const char *name)
0ad19a3f 1769{
d472214b 1770 return netdev_set_flag(name, 0);
0ad19a3f 1771}
1772
54256301 1773int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu)
0ad19a3f 1774{
ebc73a67 1775 int err, len;
06f976ca 1776 struct ifinfomsg *ifi;
ebc73a67 1777 struct nl_handler nlh;
0ad19a3f 1778 struct rtattr *nest1, *nest2, *nest3;
ebc73a67 1779 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 1780
3cfc0f3a
MN
1781 err = netlink_open(&nlh, NETLINK_ROUTE);
1782 if (err)
1783 return err;
0ad19a3f 1784
3cfc0f3a 1785 err = -EINVAL;
0ad19a3f 1786 len = strlen(name1);
dae3fdf6 1787 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 1788 goto out;
1789
1790 len = strlen(name2);
dae3fdf6 1791 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 1792 goto out;
1793
3cfc0f3a 1794 err = -ENOMEM;
0ad19a3f 1795 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1796 if (!nlmsg)
1797 goto out;
1798
06f976ca 1799 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 1800 if (!answer)
1801 goto out;
1802
06f976ca 1803 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1804 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
1805 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1806
1807 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1808 if (!ifi)
1809 goto out;
06f976ca 1810 ifi->ifi_family = AF_UNSPEC;
0ad19a3f 1811
3cfc0f3a 1812 err = -EINVAL;
79e68309 1813 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 1814 if (!nest1)
1815 goto out;
1816
1817 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
1818 goto out;
1819
1820 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1821 if (!nest2)
1822 goto out;
1823
1824 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
1825 if (!nest3)
1826 goto out;
1827
06f976ca 1828 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1829 if (!ifi) {
1830 err = -ENOMEM;
06f976ca 1831 goto out;
25a9939b 1832 }
0ad19a3f 1833
1834 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
1835 goto out;
1836
54256301
CB
1837 if (mtu > 0 && nla_put_u32(nlmsg, IFLA_MTU, mtu))
1838 goto out;
1839
1840 if (pid > 0 && nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
1841 goto out;
1842
0ad19a3f 1843 nla_end_nested(nlmsg, nest3);
0ad19a3f 1844 nla_end_nested(nlmsg, nest2);
0ad19a3f 1845 nla_end_nested(nlmsg, nest1);
1846
1847 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
1848 goto out;
1849
3cfc0f3a 1850 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 1851out:
1852 netlink_close(&nlh);
1853 nlmsg_free(answer);
1854 nlmsg_free(nlmsg);
1855 return err;
1856}
1857
ebc73a67 1858/* TODO: merge with lxc_macvlan_create */
7c11d57a 1859int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
26c39028 1860{
ebc73a67 1861 int err, len, lindex;
06f976ca 1862 struct ifinfomsg *ifi;
ebc73a67 1863 struct nl_handler nlh;
26c39028 1864 struct rtattr *nest, *nest2;
ebc73a67 1865 struct nlmsg *answer = NULL, *nlmsg = NULL;
26c39028 1866
3cfc0f3a
MN
1867 err = netlink_open(&nlh, NETLINK_ROUTE);
1868 if (err)
1869 return err;
26c39028 1870
3cfc0f3a 1871 err = -EINVAL;
26c39028 1872 len = strlen(master);
dae3fdf6 1873 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
1874 goto err3;
1875
1876 len = strlen(name);
dae3fdf6 1877 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
1878 goto err3;
1879
3cfc0f3a 1880 err = -ENOMEM;
26c39028
JHS
1881 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1882 if (!nlmsg)
1883 goto err3;
1884
06f976ca 1885 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
26c39028
JHS
1886 if (!answer)
1887 goto err2;
1888
3cfc0f3a 1889 err = -EINVAL;
26c39028
JHS
1890 lindex = if_nametoindex(master);
1891 if (!lindex)
1892 goto err1;
1893
06f976ca 1894 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1895 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
1896 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1897
1898 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1899 if (!ifi) {
1900 err = -ENOMEM;
1901 goto err1;
1902 }
06f976ca 1903 ifi->ifi_family = AF_UNSPEC;
26c39028 1904
79e68309 1905 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
26c39028
JHS
1906 if (!nest)
1907 goto err1;
1908
1909 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
1910 goto err1;
1911
1912 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1913 if (!nest2)
1914 goto err1;
e892973e 1915
26c39028
JHS
1916 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
1917 goto err1;
e892973e 1918
26c39028 1919 nla_end_nested(nlmsg, nest2);
26c39028
JHS
1920 nla_end_nested(nlmsg, nest);
1921
1922 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
1923 goto err1;
1924
1925 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
1926 goto err1;
1927
3cfc0f3a 1928 err = netlink_transaction(&nlh, nlmsg, answer);
26c39028
JHS
1929err1:
1930 nlmsg_free(answer);
1931err2:
1932 nlmsg_free(nlmsg);
1933err3:
1934 netlink_close(&nlh);
1935 return err;
1936}
1937
e892973e 1938int lxc_macvlan_create(const char *master, const char *name, int mode)
0ad19a3f 1939{
ebc73a67 1940 int err, index, len;
06f976ca 1941 struct ifinfomsg *ifi;
ebc73a67 1942 struct nl_handler nlh;
e892973e 1943 struct rtattr *nest, *nest2;
ebc73a67 1944 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 1945
3cfc0f3a
MN
1946 err = netlink_open(&nlh, NETLINK_ROUTE);
1947 if (err)
1948 return err;
0ad19a3f 1949
3cfc0f3a 1950 err = -EINVAL;
0ad19a3f 1951 len = strlen(master);
dae3fdf6 1952 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 1953 goto out;
1954
1955 len = strlen(name);
dae3fdf6 1956 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 1957 goto out;
1958
3cfc0f3a 1959 err = -ENOMEM;
0ad19a3f 1960 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1961 if (!nlmsg)
1962 goto out;
1963
06f976ca 1964 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 1965 if (!answer)
1966 goto out;
1967
3cfc0f3a 1968 err = -EINVAL;
0ad19a3f 1969 index = if_nametoindex(master);
1970 if (!index)
1971 goto out;
1972
06f976ca 1973 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1974 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
1975 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
1976
1977 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
1978 if (!ifi) {
1979 err = -ENOMEM;
1980 goto out;
1981 }
06f976ca 1982 ifi->ifi_family = AF_UNSPEC;
0ad19a3f 1983
79e68309 1984 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 1985 if (!nest)
1986 goto out;
1987
1988 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
1989 goto out;
1990
e892973e
DL
1991 if (mode) {
1992 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
1993 if (!nest2)
1994 goto out;
1995
1996 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
1997 goto out;
1998
1999 nla_end_nested(nlmsg, nest2);
2000 }
2001
0ad19a3f 2002 nla_end_nested(nlmsg, nest);
2003
2004 if (nla_put_u32(nlmsg, IFLA_LINK, index))
2005 goto out;
2006
2007 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
2008 goto out;
2009
3cfc0f3a 2010 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 2011out:
2012 netlink_close(&nlh);
2013 nlmsg_free(answer);
2014 nlmsg_free(nlmsg);
2015 return err;
2016}
2017
2018static int proc_sys_net_write(const char *path, const char *value)
2019{
ebc73a67
CB
2020 int fd;
2021 int err = 0;
0ad19a3f 2022
2023 fd = open(path, O_WRONLY);
2024 if (fd < 0)
2025 return -errno;
2026
f640cf46 2027 if (lxc_write_nointr(fd, value, strlen(value)) < 0)
0ad19a3f 2028 err = -errno;
2029
2030 close(fd);
2031 return err;
2032}
2033
6dfa9581 2034static int ip_forwarding_set(const char *ifname, int family, int flag)
6509154d 2035{
2036 int ret;
2037 char path[PATH_MAX];
6509154d 2038
2039 if (family != AF_INET && family != AF_INET6)
6dfa9581 2040 return -EINVAL;
6509154d 2041
2042 ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
6dfa9581 2043 family == AF_INET ? "ipv4" : "ipv6", ifname, "forwarding");
6509154d 2044 if (ret < 0 || (size_t)ret >= PATH_MAX)
6dfa9581 2045 return -E2BIG;
6509154d 2046
6dfa9581
TP
2047 return proc_sys_net_write(path, flag ? "1" : "0");
2048}
2049
2050int lxc_ip_forwarding_on(const char *name, int family)
2051{
2052 return ip_forwarding_set(name, family, 1);
2053}
2054
2055int lxc_ip_forwarding_off(const char *name, int family)
2056{
2057 return ip_forwarding_set(name, family, 0);
6509154d 2058}
2059
0ad19a3f 2060static int neigh_proxy_set(const char *ifname, int family, int flag)
2061{
9ba8130c 2062 int ret;
419590da 2063 char path[PATH_MAX];
0ad19a3f 2064
2065 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 2066 return -EINVAL;
0ad19a3f 2067
419590da 2068 ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
ebc73a67
CB
2069 family == AF_INET ? "ipv4" : "ipv6", ifname,
2070 family == AF_INET ? "proxy_arp" : "proxy_ndp");
419590da 2071 if (ret < 0 || (size_t)ret >= PATH_MAX)
9ba8130c 2072 return -E2BIG;
0ad19a3f 2073
ebc73a67 2074 return proc_sys_net_write(path, flag ? "1" : "0");
0ad19a3f 2075}
2076
6509154d 2077static int lxc_is_ip_neigh_proxy_enabled(const char *ifname, int family)
2078{
2079 int ret;
2080 char path[PATH_MAX];
2081 char buf[1] = "";
2082
2083 if (family != AF_INET && family != AF_INET6)
596a002c 2084 return ret_set_errno(-1, EINVAL);
6509154d 2085
2086 ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
2087 family == AF_INET ? "ipv4" : "ipv6", ifname,
2088 family == AF_INET ? "proxy_arp" : "proxy_ndp");
2089 if (ret < 0 || (size_t)ret >= PATH_MAX)
596a002c 2090 return ret_set_errno(-1, E2BIG);
6509154d 2091
2092 return lxc_read_file_expect(path, buf, 1, "1");
2093}
2094
497353b6 2095int lxc_neigh_proxy_on(const char *name, int family)
0ad19a3f 2096{
2097 return neigh_proxy_set(name, family, 1);
2098}
2099
497353b6 2100int lxc_neigh_proxy_off(const char *name, int family)
0ad19a3f 2101{
2102 return neigh_proxy_set(name, family, 0);
2103}
2104
2105int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
2106{
1f1b18e7
DL
2107 int i = 0;
2108 unsigned val;
ebc73a67
CB
2109 char c;
2110 unsigned char *data;
1f1b18e7
DL
2111
2112 sockaddr->sa_family = ARPHRD_ETHER;
2113 data = (unsigned char *)sockaddr->sa_data;
2114
2115 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
ebc73a67
CB
2116 c = *macaddr++;
2117 if (isdigit(c))
2118 val = c - '0';
2119 else if (c >= 'a' && c <= 'f')
2120 val = c - 'a' + 10;
2121 else if (c >= 'A' && c <= 'F')
2122 val = c - 'A' + 10;
2123 else
2124 return -EINVAL;
2125
2126 val <<= 4;
2127 c = *macaddr;
2128 if (isdigit(c))
2129 val |= c - '0';
2130 else if (c >= 'a' && c <= 'f')
2131 val |= c - 'a' + 10;
2132 else if (c >= 'A' && c <= 'F')
2133 val |= c - 'A' + 10;
2134 else if (c == ':' || c == 0)
2135 val >>= 4;
2136 else
2137 return -EINVAL;
2138 if (c != 0)
2139 macaddr++;
2140 *data++ = (unsigned char)(val & 0377);
2141 i++;
2142
2143 if (*macaddr == ':')
2144 macaddr++;
0ad19a3f 2145 }
0ad19a3f 2146
1f1b18e7 2147 return 0;
0ad19a3f 2148}
2149
ebc73a67
CB
2150static int ip_addr_add(int family, int ifindex, void *addr, void *bcast,
2151 void *acast, int prefix)
0ad19a3f 2152{
ebc73a67 2153 int addrlen, err;
06f976ca 2154 struct ifaddrmsg *ifa;
ebc73a67
CB
2155 struct nl_handler nlh;
2156 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 2157
ebc73a67
CB
2158 addrlen = family == AF_INET ? sizeof(struct in_addr)
2159 : sizeof(struct in6_addr);
4bf1968d 2160
3cfc0f3a
MN
2161 err = netlink_open(&nlh, NETLINK_ROUTE);
2162 if (err)
2163 return err;
0ad19a3f 2164
3cfc0f3a 2165 err = -ENOMEM;
0ad19a3f 2166 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
2167 if (!nlmsg)
2168 goto out;
2169
06f976ca 2170 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 2171 if (!answer)
2172 goto out;
2173
06f976ca 2174 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 2175 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
06f976ca
SZ
2176 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
2177
2178 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
acf47e1b 2179 if (!ifa)
25a9939b 2180 goto out;
06f976ca
SZ
2181 ifa->ifa_prefixlen = prefix;
2182 ifa->ifa_index = ifindex;
2183 ifa->ifa_family = family;
2184 ifa->ifa_scope = 0;
acf47e1b 2185
3cfc0f3a 2186 err = -EINVAL;
4bf1968d 2187 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
0ad19a3f 2188 goto out;
2189
4bf1968d 2190 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
0ad19a3f 2191 goto out;
2192
d8948a52 2193 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
1f1b18e7
DL
2194 goto out;
2195
ebc73a67 2196 /* TODO: multicast, anycast with ipv6 */
7ddc8f24 2197 err = -EPROTONOSUPPORT;
79881dc6
DL
2198 if (family == AF_INET6 &&
2199 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
2200 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
1f1b18e7 2201 goto out;
0ad19a3f 2202
3cfc0f3a 2203 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 2204out:
2205 netlink_close(&nlh);
2206 nlmsg_free(answer);
2207 nlmsg_free(nlmsg);
2208 return err;
2209}
2210
1f1b18e7 2211int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
ebc73a67
CB
2212 struct in6_addr *mcast, struct in6_addr *acast,
2213 int prefix)
1f1b18e7
DL
2214{
2215 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
2216}
2217
ebc73a67
CB
2218int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, struct in_addr *bcast,
2219 int prefix)
1f1b18e7
DL
2220{
2221 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
2222}
2223
ebc73a67
CB
2224/* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
2225 * the given RTM_NEWADDR message. Allocates memory for the address and stores
2226 * that pointer in *res (so res should be an in_addr** or in6_addr**).
19a26f82 2227 */
6ce39620
CB
2228#pragma GCC diagnostic push
2229#pragma GCC diagnostic ignored "-Wcast-align"
2230
ebc73a67
CB
2231static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res)
2232{
2233 int addrlen;
06f976ca
SZ
2234 struct ifaddrmsg *ifa = NLMSG_DATA(msg);
2235 struct rtattr *rta = IFA_RTA(ifa);
2236 int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
19a26f82 2237
06f976ca 2238 if (ifa->ifa_family != family)
19a26f82
MK
2239 return 0;
2240
ebc73a67
CB
2241 addrlen = family == AF_INET ? sizeof(struct in_addr)
2242 : sizeof(struct in6_addr);
19a26f82
MK
2243
2244 /* Loop over the rtattr's in this message */
ebc73a67 2245 while (RTA_OK(rta, attr_len)) {
19a26f82 2246 /* Found a local address for the requested interface,
ebc73a67
CB
2247 * return it.
2248 */
2249 if (rta->rta_type == IFA_LOCAL ||
2250 rta->rta_type == IFA_ADDRESS) {
2251 /* Sanity check. The family check above should make sure
2252 * the address length is correct, but check here just in
2253 * case.
2254 */
19a26f82
MK
2255 if (RTA_PAYLOAD(rta) != addrlen)
2256 return -1;
2257
ebc73a67
CB
2258 /* We might have found an IFA_ADDRESS before, which we
2259 * now overwrite with an IFA_LOCAL.
2260 */
dd66e5ad 2261 if (!*res) {
19a26f82 2262 *res = malloc(addrlen);
dd66e5ad
DE
2263 if (!*res)
2264 return -1;
2265 }
19a26f82
MK
2266
2267 memcpy(*res, RTA_DATA(rta), addrlen);
19a26f82
MK
2268 if (rta->rta_type == IFA_LOCAL)
2269 break;
2270 }
2271 rta = RTA_NEXT(rta, attr_len);
2272 }
2273 return 0;
2274}
2275
6ce39620
CB
2276#pragma GCC diagnostic pop
2277
19a26f82
MK
2278static int ip_addr_get(int family, int ifindex, void **res)
2279{
ebc73a67 2280 int answer_len, err;
06f976ca 2281 struct ifaddrmsg *ifa;
ebc73a67 2282 struct nl_handler nlh;
19a26f82 2283 struct nlmsghdr *msg;
ebc73a67
CB
2284 int readmore = 0, recv_len = 0;
2285 struct nlmsg *answer = NULL, *nlmsg = NULL;
19a26f82
MK
2286
2287 err = netlink_open(&nlh, NETLINK_ROUTE);
2288 if (err)
2289 return err;
2290
2291 err = -ENOMEM;
2292 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
2293 if (!nlmsg)
2294 goto out;
2295
06f976ca 2296 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
19a26f82
MK
2297 if (!answer)
2298 goto out;
2299
ebc73a67
CB
2300 /* Save the answer buffer length, since it will be overwritten on the
2301 * first receive (and we might need to receive more than once).
2302 */
06f976ca
SZ
2303 answer_len = answer->nlmsghdr->nlmsg_len;
2304
ebc73a67 2305 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
06f976ca 2306 nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
19a26f82 2307
06f976ca 2308 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
25a9939b
WC
2309 if (!ifa)
2310 goto out;
06f976ca 2311 ifa->ifa_family = family;
19a26f82 2312
ebc73a67
CB
2313 /* Send the request for addresses, which returns all addresses on all
2314 * interfaces.
2315 */
19a26f82
MK
2316 err = netlink_send(&nlh, nlmsg);
2317 if (err < 0)
2318 goto out;
19a26f82 2319
6ce39620
CB
2320#pragma GCC diagnostic push
2321#pragma GCC diagnostic ignored "-Wcast-align"
2322
19a26f82
MK
2323 do {
2324 /* Restore the answer buffer length, it might have been
ebc73a67
CB
2325 * overwritten by a previous receive.
2326 */
06f976ca 2327 answer->nlmsghdr->nlmsg_len = answer_len;
19a26f82 2328
ebc73a67 2329 /* Get the (next) batch of reply messages. */
19a26f82
MK
2330 err = netlink_rcv(&nlh, answer);
2331 if (err < 0)
2332 goto out;
2333
2334 recv_len = err;
2335 err = 0;
2336
ebc73a67 2337 /* Satisfy the typing for the netlink macros. */
06f976ca 2338 msg = answer->nlmsghdr;
19a26f82
MK
2339
2340 while (NLMSG_OK(msg, recv_len)) {
ebc73a67 2341 /* Stop reading if we see an error message. */
19a26f82 2342 if (msg->nlmsg_type == NLMSG_ERROR) {
ebc73a67
CB
2343 struct nlmsgerr *errmsg =
2344 (struct nlmsgerr *)NLMSG_DATA(msg);
19a26f82
MK
2345 err = errmsg->error;
2346 goto out;
2347 }
2348
ebc73a67 2349 /* Stop reading if we see a NLMSG_DONE message. */
19a26f82
MK
2350 if (msg->nlmsg_type == NLMSG_DONE) {
2351 readmore = 0;
2352 break;
2353 }
2354
2355 if (msg->nlmsg_type != RTM_NEWADDR) {
2356 err = -1;
2357 goto out;
2358 }
2359
06f976ca
SZ
2360 ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
2361 if (ifa->ifa_index == ifindex) {
2362 if (ifa_get_local_ip(family, msg, res) < 0) {
51e7a874
SG
2363 err = -1;
2364 goto out;
2365 }
2366
ebc73a67 2367 /* Found a result, stop searching. */
19a26f82
MK
2368 if (*res)
2369 goto out;
2370 }
2371
ebc73a67
CB
2372 /* Keep reading more data from the socket if the last
2373 * message had the NLF_F_MULTI flag set.
2374 */
19a26f82
MK
2375 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
2376
ebc73a67 2377 /* Look at the next message received in this buffer. */
19a26f82
MK
2378 msg = NLMSG_NEXT(msg, recv_len);
2379 }
2380 } while (readmore);
2381
6ce39620
CB
2382#pragma GCC diagnostic pop
2383
19a26f82 2384 /* If we end up here, we didn't find any result, so signal an
ebc73a67
CB
2385 * error.
2386 */
19a26f82
MK
2387 err = -1;
2388
2389out:
2390 netlink_close(&nlh);
2391 nlmsg_free(answer);
2392 nlmsg_free(nlmsg);
2393 return err;
2394}
2395
2396int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
2397{
ebc73a67 2398 return ip_addr_get(AF_INET6, ifindex, (void **)res);
19a26f82
MK
2399}
2400
ebc73a67 2401int lxc_ipv4_addr_get(int ifindex, struct in_addr **res)
19a26f82 2402{
ebc73a67 2403 return ip_addr_get(AF_INET, ifindex, (void **)res);
19a26f82
MK
2404}
2405
f8fee0e2
MK
2406static int ip_gateway_add(int family, int ifindex, void *gw)
2407{
ebc73a67 2408 int addrlen, err;
f8fee0e2 2409 struct nl_handler nlh;
06f976ca 2410 struct rtmsg *rt;
ebc73a67 2411 struct nlmsg *answer = NULL, *nlmsg = NULL;
f8fee0e2 2412
ebc73a67
CB
2413 addrlen = family == AF_INET ? sizeof(struct in_addr)
2414 : sizeof(struct in6_addr);
f8fee0e2
MK
2415
2416 err = netlink_open(&nlh, NETLINK_ROUTE);
2417 if (err)
2418 return err;
2419
2420 err = -ENOMEM;
2421 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
2422 if (!nlmsg)
2423 goto out;
2424
06f976ca 2425 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
f8fee0e2
MK
2426 if (!answer)
2427 goto out;
2428
06f976ca 2429 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 2430 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
06f976ca
SZ
2431 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
2432
2433 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
25a9939b
WC
2434 if (!rt)
2435 goto out;
06f976ca
SZ
2436 rt->rtm_family = family;
2437 rt->rtm_table = RT_TABLE_MAIN;
2438 rt->rtm_scope = RT_SCOPE_UNIVERSE;
2439 rt->rtm_protocol = RTPROT_BOOT;
2440 rt->rtm_type = RTN_UNICAST;
f8fee0e2 2441 /* "default" destination */
06f976ca 2442 rt->rtm_dst_len = 0;
f8fee0e2
MK
2443
2444 err = -EINVAL;
a2f9a670 2445
2446 /* If gateway address not supplied, then a device route will be created instead */
2447 if (gw != NULL) {
2448 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
2449 goto out;
2450 }
f8fee0e2
MK
2451
2452 /* Adding the interface index enables the use of link-local
ebc73a67
CB
2453 * addresses for the gateway.
2454 */
f8fee0e2
MK
2455 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
2456 goto out;
2457
2458 err = netlink_transaction(&nlh, nlmsg, answer);
2459out:
2460 netlink_close(&nlh);
2461 nlmsg_free(answer);
2462 nlmsg_free(nlmsg);
2463 return err;
2464}
2465
2466int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
2467{
2468 return ip_gateway_add(AF_INET, ifindex, gw);
2469}
2470
2471int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
2472{
2473 return ip_gateway_add(AF_INET6, ifindex, gw);
2474}
581c75e7 2475bool is_ovs_bridge(const char *bridge)
0d204771 2476{
ebc73a67 2477 int ret;
0d204771 2478 struct stat sb;
ebc73a67 2479 char brdirname[22 + IFNAMSIZ + 1] = {0};
0d204771 2480
ebc73a67
CB
2481 ret = snprintf(brdirname, 22 + IFNAMSIZ + 1, "/sys/class/net/%s/bridge",
2482 bridge);
2483 if (ret < 0 || (size_t)ret >= 22 + IFNAMSIZ + 1)
2484 return false;
2485
2486 ret = stat(brdirname, &sb);
2487 if (ret < 0 && errno == ENOENT)
0d204771 2488 return true;
ebc73a67 2489
0d204771
SH
2490 return false;
2491}
2492
581c75e7
CB
2493struct ovs_veth_args {
2494 const char *bridge;
2495 const char *nic;
2496};
2497
cb0dc11b
CB
2498/* Called from a background thread - when nic goes away, remove it from the
2499 * bridge.
c43cbc04 2500 */
581c75e7 2501static int lxc_ovs_delete_port_exec(void *data)
c43cbc04 2502{
581c75e7 2503 struct ovs_veth_args *args = data;
cb0dc11b 2504
581c75e7
CB
2505 execlp("ovs-vsctl", "ovs-vsctl", "del-port", args->bridge, args->nic,
2506 (char *)NULL);
2507 return -1;
c43cbc04
SH
2508}
2509
581c75e7 2510int lxc_ovs_delete_port(const char *bridge, const char *nic)
0d204771 2511{
c43cbc04 2512 int ret;
419590da 2513 char cmd_output[PATH_MAX];
581c75e7 2514 struct ovs_veth_args args;
6ad22d06 2515
581c75e7
CB
2516 args.bridge = bridge;
2517 args.nic = nic;
2518 ret = run_command(cmd_output, sizeof(cmd_output),
2519 lxc_ovs_delete_port_exec, (void *)&args);
2520 if (ret < 0) {
2521 ERROR("Failed to delete \"%s\" from openvswitch bridge \"%s\": "
53796b94 2522 "%s", nic, bridge, cmd_output);
6ad22d06 2523 return -1;
581c75e7 2524 }
0d204771 2525
581c75e7
CB
2526 return 0;
2527}
ebc73a67 2528
581c75e7
CB
2529static int lxc_ovs_attach_bridge_exec(void *data)
2530{
2531 struct ovs_veth_args *args = data;
ebc73a67 2532
581c75e7
CB
2533 execlp("ovs-vsctl", "ovs-vsctl", "add-port", args->bridge, args->nic,
2534 (char *)NULL);
2535 return -1;
2536}
ebc73a67 2537
581c75e7
CB
2538static int lxc_ovs_attach_bridge(const char *bridge, const char *nic)
2539{
2540 int ret;
419590da 2541 char cmd_output[PATH_MAX];
581c75e7 2542 struct ovs_veth_args args;
ebc73a67 2543
581c75e7
CB
2544 args.bridge = bridge;
2545 args.nic = nic;
2546 ret = run_command(cmd_output, sizeof(cmd_output),
2547 lxc_ovs_attach_bridge_exec, (void *)&args);
2548 if (ret < 0) {
2549 ERROR("Failed to attach \"%s\" to openvswitch bridge \"%s\": %s",
53796b94 2550 nic, bridge, cmd_output);
581c75e7 2551 return -1;
c43cbc04 2552 }
0d204771 2553
581c75e7 2554 return 0;
0d204771 2555}
0d204771 2556
581c75e7 2557int lxc_bridge_attach(const char *bridge, const char *ifname)
0ad19a3f 2558{
ebc73a67 2559 int err, fd, index;
9de31d5a 2560 size_t retlen;
0ad19a3f 2561 struct ifreq ifr;
2562
dae3fdf6 2563 if (strlen(ifname) >= IFNAMSIZ)
3cfc0f3a 2564 return -EINVAL;
0ad19a3f 2565
2566 index = if_nametoindex(ifname);
2567 if (!index)
3cfc0f3a 2568 return -EINVAL;
0ad19a3f 2569
0d204771 2570 if (is_ovs_bridge(bridge))
581c75e7 2571 return lxc_ovs_attach_bridge(bridge, ifname);
0d204771 2572
ad9429e5 2573 fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
0ad19a3f 2574 if (fd < 0)
3cfc0f3a 2575 return -errno;
0ad19a3f 2576
9de31d5a 2577 retlen = strlcpy(ifr.ifr_name, bridge, IFNAMSIZ);
42cc4083
CB
2578 if (retlen >= IFNAMSIZ) {
2579 close(fd);
9de31d5a 2580 return -E2BIG;
42cc4083 2581 }
9de31d5a 2582
ebc73a67 2583 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
0ad19a3f 2584 ifr.ifr_ifindex = index;
7d163508 2585 err = ioctl(fd, SIOCBRADDIF, &ifr);
0ad19a3f 2586 close(fd);
3cfc0f3a
MN
2587 if (err)
2588 err = -errno;
0ad19a3f 2589
2590 return err;
2591}
72d0e1cb 2592
ebc73a67 2593static const char *const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
b343592b 2594 [LXC_NET_EMPTY] = "empty",
72d0e1cb
SG
2595 [LXC_NET_VETH] = "veth",
2596 [LXC_NET_MACVLAN] = "macvlan",
c9f52382 2597 [LXC_NET_IPVLAN] = "ipvlan",
72d0e1cb 2598 [LXC_NET_PHYS] = "phys",
b343592b
BP
2599 [LXC_NET_VLAN] = "vlan",
2600 [LXC_NET_NONE] = "none",
72d0e1cb
SG
2601};
2602
2603const char *lxc_net_type_to_str(int type)
2604{
2605 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
2606 return NULL;
ebc73a67 2607
72d0e1cb
SG
2608 return lxc_network_types[type];
2609}
8befa924 2610
ebc73a67 2611static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
a0265685 2612
966e9f1f 2613char *lxc_mkifname(char *template)
a0265685 2614{
2d7bf744 2615 int ret;
b1e44ed1 2616 struct netns_ifaddrs *ifa, *ifaddr;
966e9f1f
CB
2617 char name[IFNAMSIZ];
2618 bool exists = false;
2619 size_t i = 0;
280cc35f 2620#ifdef HAVE_RAND_R
2621 unsigned int seed;
2622
2623 seed = randseed(false);
2624#else
2625
2626 (void)randseed(true);
2627#endif
a0265685 2628
535e8859
CB
2629 if (strlen(template) >= IFNAMSIZ)
2630 return NULL;
2631
ebc73a67 2632 /* Get all the network interfaces. */
b1e44ed1 2633 ret = netns_getifaddrs(&ifaddr, -1, &(bool){false});
2d7bf744 2634 if (ret < 0) {
6d1400b5 2635 SYSERROR("Failed to get network interfaces");
2d7bf744
CB
2636 return NULL;
2637 }
a0265685 2638
ebc73a67 2639 /* Generate random names until we find one that doesn't exist. */
51a8a74c 2640 for (;;) {
966e9f1f 2641 name[0] = '\0';
94b1cade 2642 (void)strlcpy(name, template, IFNAMSIZ);
a0265685 2643
966e9f1f 2644 exists = false;
280cc35f 2645
a0265685
SG
2646 for (i = 0; i < strlen(name); i++) {
2647 if (name[i] == 'X') {
2648#ifdef HAVE_RAND_R
8523344a 2649 name[i] = padchar[rand_r(&seed) % strlen(padchar)];
a0265685 2650#else
8523344a 2651 name[i] = padchar[rand() % strlen(padchar)];
a0265685
SG
2652#endif
2653 }
2654 }
2655
2656 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
966e9f1f
CB
2657 if (!strcmp(ifa->ifa_name, name)) {
2658 exists = true;
a0265685
SG
2659 break;
2660 }
2661 }
2662
966e9f1f 2663 if (!exists)
a0265685 2664 break;
a0265685
SG
2665 }
2666
b1e44ed1 2667 netns_freeifaddrs(ifaddr);
94b1cade
DJ
2668 (void)strlcpy(template, name, strlen(template) + 1);
2669
2670 return template;
a0265685
SG
2671}
2672
8befa924
SH
2673int setup_private_host_hw_addr(char *veth1)
2674{
ebc73a67 2675 int err, sockfd;
8befa924 2676 struct ifreq ifr;
8befa924 2677
ad9429e5 2678 sockfd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
8befa924
SH
2679 if (sockfd < 0)
2680 return -errno;
2681
ebc73a67 2682 err = snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
87c6e5db
DJ
2683 if (err < 0 || (size_t)err >= IFNAMSIZ) {
2684 close(sockfd);
ebc73a67 2685 return -E2BIG;
87c6e5db 2686 }
ebc73a67 2687
8befa924
SH
2688 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
2689 if (err < 0) {
8befa924 2690 close(sockfd);
8befa924
SH
2691 return -errno;
2692 }
2693
2694 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
2695 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
8befa924 2696 close(sockfd);
8befa924
SH
2697 if (err < 0)
2698 return -errno;
2699
2700 return 0;
2701}
811ef482
CB
2702
2703int lxc_find_gateway_addresses(struct lxc_handler *handler)
2704{
2705 struct lxc_list *network = &handler->conf->network;
2706 struct lxc_list *iterator;
2707 struct lxc_netdev *netdev;
2708 int link_index;
2709
2710 lxc_list_for_each(iterator, network) {
2711 netdev = iterator->elem;
2712
2713 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2714 continue;
2715
2716 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
03ca4af8 2717 ERROR("Automatic gateway detection is only supported for veth and macvlan");
811ef482
CB
2718 return -1;
2719 }
2720
de4855a8 2721 if (netdev->link[0] == '\0') {
811ef482
CB
2722 ERROR("Automatic gateway detection needs a link interface");
2723 return -1;
2724 }
2725
2726 link_index = if_nametoindex(netdev->link);
2727 if (!link_index)
2728 return -EINVAL;
2729
2730 if (netdev->ipv4_gateway_auto) {
2731 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
03ca4af8
TP
2732 ERROR("Failed to automatically find ipv4 gateway address from link interface \"%s\"",
2733 netdev->link);
811ef482
CB
2734 return -1;
2735 }
2736 }
2737
2738 if (netdev->ipv6_gateway_auto) {
2739 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
03ca4af8
TP
2740 ERROR("Failed to automatically find ipv6 gateway address from link interface \"%s\"",
2741 netdev->link);
811ef482
CB
2742 return -1;
2743 }
2744 }
2745 }
2746
2747 return 0;
2748}
2749
2750#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
f0ecc19d 2751static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname,
4d781681 2752 struct lxc_netdev *netdev, pid_t pid, unsigned int hooks_version)
811ef482
CB
2753{
2754 int ret;
2755 pid_t child;
2756 int bytes, pipefd[2];
2757 char *token, *saveptr = NULL;
095ead80 2758 char netdev_link[IFNAMSIZ];
419590da 2759 char buffer[PATH_MAX] = {0};
94b1cade 2760 size_t retlen;
811ef482
CB
2761
2762 if (netdev->type != LXC_NET_VETH) {
2763 ERROR("Network type %d not support for unprivileged use", netdev->type);
2764 return -1;
2765 }
2766
2767 ret = pipe(pipefd);
2768 if (ret < 0) {
2769 SYSERROR("Failed to create pipe");
2770 return -1;
2771 }
2772
2773 child = fork();
2774 if (child < 0) {
2775 SYSERROR("Failed to create new process");
2776 close(pipefd[0]);
2777 close(pipefd[1]);
2778 return -1;
2779 }
2780
2781 if (child == 0) {
8335fd40 2782 char pidstr[INTTYPE_TO_STRLEN(pid_t)];
811ef482
CB
2783
2784 close(pipefd[0]);
2785
2786 ret = dup2(pipefd[1], STDOUT_FILENO);
2787 if (ret >= 0)
2788 ret = dup2(pipefd[1], STDERR_FILENO);
2789 close(pipefd[1]);
2790 if (ret < 0) {
2791 SYSERROR("Failed to duplicate std{err,out} file descriptor");
78070056 2792 _exit(EXIT_FAILURE);
811ef482
CB
2793 }
2794
de4855a8 2795 if (netdev->link[0] != '\0')
9de31d5a 2796 retlen = strlcpy(netdev_link, netdev->link, IFNAMSIZ);
811ef482 2797 else
9de31d5a
CB
2798 retlen = strlcpy(netdev_link, "none", IFNAMSIZ);
2799 if (retlen >= IFNAMSIZ) {
2800 SYSERROR("Invalid network device name");
2801 _exit(EXIT_FAILURE);
2802 }
811ef482 2803
8335fd40
CB
2804 ret = snprintf(pidstr, sizeof(pidstr), "%d", pid);
2805 if (ret < 0 || ret >= sizeof(pidstr))
78070056 2806 _exit(EXIT_FAILURE);
8335fd40 2807 pidstr[sizeof(pidstr) - 1] = '\0';
811ef482
CB
2808
2809 INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath,
2810 lxcname, pidstr, netdev_link,
3473ca76
CB
2811 !is_empty_string(netdev->name) ? netdev->name : "(null)");
2812 if (!is_empty_string(netdev->name))
811ef482
CB
2813 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "create",
2814 lxcpath, lxcname, pidstr, "veth", netdev_link,
2815 netdev->name, (char *)NULL);
2816 else
2817 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "create",
2818 lxcpath, lxcname, pidstr, "veth", netdev_link,
2819 (char *)NULL);
2820 SYSERROR("Failed to execute lxc-user-nic");
78070056 2821 _exit(EXIT_FAILURE);
811ef482
CB
2822 }
2823
2824 /* close the write-end of the pipe */
2825 close(pipefd[1]);
2826
419590da 2827 bytes = lxc_read_nointr(pipefd[0], &buffer, PATH_MAX);
811ef482 2828 if (bytes < 0) {
74c6e2b0 2829 SYSERROR("Failed to read from pipe file descriptor");
811ef482 2830 close(pipefd[0]);
6b9f82a9
CB
2831 } else {
2832 buffer[bytes - 1] = '\0';
811ef482 2833 }
811ef482
CB
2834
2835 ret = wait_for_pid(child);
2836 close(pipefd[0]);
6b9f82a9 2837 if (ret != 0 || bytes < 0) {
811ef482
CB
2838 ERROR("lxc-user-nic failed to configure requested network: %s",
2839 buffer[0] != '\0' ? buffer : "(null)");
2840 return -1;
2841 }
2842 TRACE("Received output \"%s\" from lxc-user-nic", buffer);
2843
2844 /* netdev->name */
2845 token = strtok_r(buffer, ":", &saveptr);
74c6e2b0
CB
2846 if (!token) {
2847 ERROR("Failed to parse lxc-user-nic output");
811ef482 2848 return -1;
74c6e2b0 2849 }
811ef482 2850
e389f2af
CB
2851 /*
2852 * lxc-user-nic will take care of proper network device naming. So
2853 * netdev->name and netdev->created_name need to be identical to not
2854 * trigger another rename later on.
2855 */
2856 retlen = strlcpy(netdev->name, token, IFNAMSIZ);
2857 if (retlen < IFNAMSIZ)
2858 retlen = strlcpy(netdev->created_name, token, IFNAMSIZ);
2859 if (retlen >= IFNAMSIZ) {
2860 ERROR("Container side veth device name returned by lxc-user-nic is too long");
2861 return -E2BIG;
2862 }
811ef482 2863
74c6e2b0 2864 /* netdev->ifindex */
811ef482 2865 token = strtok_r(NULL, ":", &saveptr);
74c6e2b0
CB
2866 if (!token) {
2867 ERROR("Failed to parse lxc-user-nic output");
811ef482 2868 return -1;
74c6e2b0 2869 }
811ef482 2870
74c6e2b0
CB
2871 ret = lxc_safe_int(token, &netdev->ifindex);
2872 if (ret < 0) {
6d1400b5 2873 errno = -ret;
2874 SYSERROR("Failed to convert string \"%s\" to integer", token);
811ef482
CB
2875 return -1;
2876 }
2877
74c6e2b0 2878 /* netdev->priv.veth_attr.veth1 */
811ef482 2879 token = strtok_r(NULL, ":", &saveptr);
74c6e2b0
CB
2880 if (!token) {
2881 ERROR("Failed to parse lxc-user-nic output");
811ef482 2882 return -1;
74c6e2b0 2883 }
811ef482 2884
94b1cade
DJ
2885 retlen = strlcpy(netdev->priv.veth_attr.veth1, token, IFNAMSIZ);
2886 if (retlen >= IFNAMSIZ) {
74c6e2b0
CB
2887 ERROR("Host side veth device name returned by lxc-user-nic is "
2888 "too long");
2889 return -E2BIG;
2890 }
74c6e2b0
CB
2891
2892 /* netdev->priv.veth_attr.ifindex */
2893 token = strtok_r(NULL, ":", &saveptr);
2894 if (!token) {
2895 ERROR("Failed to parse lxc-user-nic output");
2896 return -1;
2897 }
2898
2899 ret = lxc_safe_int(token, &netdev->priv.veth_attr.ifindex);
811ef482 2900 if (ret < 0) {
6d1400b5 2901 errno = -ret;
2902 SYSERROR("Failed to convert string \"%s\" to integer", token);
811ef482
CB
2903 return -1;
2904 }
2905
4d781681 2906 if (netdev->upscript) {
2907 char *argv[] = {
2908 "veth",
2909 netdev->link,
2910 netdev->priv.veth_attr.veth1,
2911 NULL,
2912 };
2913
e389f2af
CB
2914 ret = run_script_argv(lxcname, hooks_version, "net",
2915 netdev->upscript, "up", argv);
4d781681 2916 if (ret < 0)
2917 return -1;
2918 }
2919
811ef482
CB
2920 return 0;
2921}
2922
f0ecc19d 2923static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcname,
1bd8d726
CB
2924 struct lxc_netdev *netdev,
2925 const char *netns_path)
811ef482
CB
2926{
2927 int bytes, ret;
2928 pid_t child;
2929 int pipefd[2];
419590da 2930 char buffer[PATH_MAX] = {0};
811ef482
CB
2931
2932 if (netdev->type != LXC_NET_VETH) {
2933 ERROR("Network type %d not support for unprivileged use", netdev->type);
2934 return -1;
2935 }
2936
2937 ret = pipe(pipefd);
2938 if (ret < 0) {
2939 SYSERROR("Failed to create pipe");
2940 return -1;
2941 }
2942
2943 child = fork();
2944 if (child < 0) {
2945 SYSERROR("Failed to create new process");
2946 close(pipefd[0]);
2947 close(pipefd[1]);
2948 return -1;
2949 }
2950
2951 if (child == 0) {
8843fde4 2952 char *hostveth;
811ef482
CB
2953
2954 close(pipefd[0]);
2955
2956 ret = dup2(pipefd[1], STDOUT_FILENO);
2957 if (ret >= 0)
2958 ret = dup2(pipefd[1], STDERR_FILENO);
2959 close(pipefd[1]);
2960 if (ret < 0) {
2961 SYSERROR("Failed to duplicate std{err,out} file descriptor");
a30b9023 2962 _exit(EXIT_FAILURE);
811ef482
CB
2963 }
2964
8843fde4
CB
2965 if (netdev->priv.veth_attr.pair[0] != '\0')
2966 hostveth = netdev->priv.veth_attr.pair;
2967 else
2968 hostveth = netdev->priv.veth_attr.veth1;
2969 if (hostveth[0] == '\0') {
74c6e2b0 2970 SYSERROR("Host side veth device name is missing");
a30b9023 2971 _exit(EXIT_FAILURE);
74c6e2b0
CB
2972 }
2973
de4855a8 2974 if (netdev->link[0] == '\0') {
811ef482 2975 SYSERROR("Network link for network device \"%s\" is "
74c6e2b0 2976 "missing", netdev->priv.veth_attr.veth1);
a30b9023 2977 _exit(EXIT_FAILURE);
74c6e2b0 2978 }
811ef482 2979
811ef482 2980 INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath,
8843fde4 2981 lxcname, netns_path, netdev->link, hostveth);
811ef482 2982 execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "delete", lxcpath,
8843fde4
CB
2983 lxcname, netns_path, "veth", netdev->link, hostveth,
2984 (char *)NULL);
811ef482 2985 SYSERROR("Failed to exec lxc-user-nic.");
a30b9023 2986 _exit(EXIT_FAILURE);
811ef482
CB
2987 }
2988
2989 close(pipefd[1]);
2990
419590da 2991 bytes = lxc_read_nointr(pipefd[0], &buffer, PATH_MAX);
811ef482
CB
2992 if (bytes < 0) {
2993 SYSERROR("Failed to read from pipe file descriptor.");
2994 close(pipefd[0]);
6b9f82a9
CB
2995 } else {
2996 buffer[bytes - 1] = '\0';
811ef482 2997 }
811ef482 2998
6b9f82a9
CB
2999 ret = wait_for_pid(child);
3000 close(pipefd[0]);
3001 if (ret != 0 || bytes < 0) {
811ef482
CB
3002 ERROR("lxc-user-nic failed to delete requested network: %s",
3003 buffer[0] != '\0' ? buffer : "(null)");
811ef482
CB
3004 return -1;
3005 }
3006
811ef482
CB
3007 return 0;
3008}
3009
1bd8d726
CB
3010bool lxc_delete_network_unpriv(struct lxc_handler *handler)
3011{
3012 int ret;
3013 struct lxc_list *iterator;
3014 struct lxc_list *network = &handler->conf->network;
3015 /* strlen("/proc/") = 6
3016 * +
8335fd40 3017 * INTTYPE_TO_STRLEN(pid_t)
1bd8d726
CB
3018 * +
3019 * strlen("/fd/") = 4
3020 * +
8335fd40 3021 * INTTYPE_TO_STRLEN(int)
1bd8d726
CB
3022 * +
3023 * \0
3024 */
8335fd40 3025 char netns_path[6 + INTTYPE_TO_STRLEN(pid_t) + 4 + INTTYPE_TO_STRLEN(int) + 1];
1bd8d726
CB
3026
3027 *netns_path = '\0';
3028
28d9e29e 3029 if (handler->nsfd[LXC_NS_NET] < 0) {
1bd8d726
CB
3030 DEBUG("Cannot not guarantee safe deletion of network devices. "
3031 "Manual cleanup maybe needed");
3032 return false;
3033 }
3034
3035 ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d",
0059379f 3036 lxc_raw_getpid(), handler->nsfd[LXC_NS_NET]);
1bd8d726
CB
3037 if (ret < 0 || ret >= sizeof(netns_path))
3038 return false;
3039
3040 lxc_list_for_each(iterator, network) {
3041 char *hostveth = NULL;
3042 struct lxc_netdev *netdev = iterator->elem;
3043
3044 /* We can only delete devices whose ifindex we have. If we don't
3045 * have the index it means that we didn't create it.
3046 */
3047 if (!netdev->ifindex)
3048 continue;
3049
3050 if (netdev->type == LXC_NET_PHYS) {
3051 ret = lxc_netdev_rename_by_index(netdev->ifindex,
3052 netdev->link);
3053 if (ret < 0)
3054 WARN("Failed to rename interface with index %d "
3055 "to its initial name \"%s\"",
3056 netdev->ifindex, netdev->link);
3057 else
3058 TRACE("Renamed interface with index %d to its "
3059 "initial name \"%s\"",
3060 netdev->ifindex, netdev->link);
b3259dc6
TP
3061
3062 ret = netdev_deconf[netdev->type](handler, netdev);
66a7c406 3063 goto clear_ifindices;
1bd8d726
CB
3064 }
3065
3066 ret = netdev_deconf[netdev->type](handler, netdev);
3067 if (ret < 0)
3068 WARN("Failed to deconfigure network device");
3069
3070 if (netdev->type != LXC_NET_VETH)
66a7c406 3071 goto clear_ifindices;
1bd8d726 3072
c869be20 3073 if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link))
66a7c406 3074 goto clear_ifindices;
1bd8d726 3075
8843fde4
CB
3076 if (netdev->priv.veth_attr.pair[0] != '\0')
3077 hostveth = netdev->priv.veth_attr.pair;
3078 else
3079 hostveth = netdev->priv.veth_attr.veth1;
3080 if (hostveth[0] == '\0')
66a7c406 3081 goto clear_ifindices;
8843fde4 3082
1bd8d726
CB
3083 ret = lxc_delete_network_unpriv_exec(handler->lxcpath,
3084 handler->name, netdev,
3085 netns_path);
3086 if (ret < 0) {
1bd8d726 3087 WARN("Failed to remove port \"%s\" from openvswitch "
8843fde4 3088 "bridge \"%s\"", hostveth, netdev->link);
66a7c406 3089 goto clear_ifindices;
1bd8d726
CB
3090 }
3091 INFO("Removed interface \"%s\" from \"%s\"", hostveth,
3092 netdev->link);
66a7c406
CB
3093
3094clear_ifindices:
0858c829
CB
3095 /*
3096 * We need to clear any ifindices we recorded so liblxc won't
3097 * have cached stale data which would cause it to fail on
3098 * reboot where we don't re-read the on-disk config file.
66a7c406
CB
3099 */
3100 netdev->ifindex = 0;
3101 if (netdev->type == LXC_NET_PHYS) {
3102 netdev->priv.phys_attr.ifindex = 0;
3103 } else if (netdev->type == LXC_NET_VETH) {
3104 netdev->priv.veth_attr.veth1[0] = '\0';
3105 netdev->priv.veth_attr.ifindex = 0;
3106 }
1bd8d726
CB
3107 }
3108
bb84beda 3109 return true;
1bd8d726
CB
3110}
3111
6509154d 3112static int lxc_setup_l2proxy(struct lxc_netdev *netdev) {
3113 struct lxc_list *cur, *next;
3114 struct lxc_inetdev *inet4dev;
3115 struct lxc_inet6dev *inet6dev;
3116 char bufinet4[INET_ADDRSTRLEN], bufinet6[INET6_ADDRSTRLEN];
b670016a 3117 int err = 0;
5fe147e9
TP
3118 unsigned int lo_ifindex = 0, link_ifindex = 0;
3119
3120 link_ifindex = if_nametoindex(netdev->link);
3121 if (link_ifindex == 0) {
3122 ERROR("Failed to retrieve ifindex for \"%s\" l2proxy setup", netdev->link);
3123 return ret_set_errno(-1, EINVAL);
3124 }
3125
6509154d 3126
3127 /* If IPv4 addresses are specified, then check that sysctl is configured correctly. */
3128 if (!lxc_list_empty(&netdev->ipv4)) {
3129 /* Check for net.ipv4.conf.[link].forwarding=1 */
3130 if (lxc_is_ip_forwarding_enabled(netdev->link, AF_INET) < 0) {
3131 ERROR("Requires sysctl net.ipv4.conf.%s.forwarding=1", netdev->link);
596a002c 3132 return ret_set_errno(-1, EINVAL);
6509154d 3133 }
3134 }
3135
3136 /* If IPv6 addresses are specified, then check that sysctl is configured correctly. */
3137 if (!lxc_list_empty(&netdev->ipv6)) {
3138 /* Check for net.ipv6.conf.[link].proxy_ndp=1 */
3139 if (lxc_is_ip_neigh_proxy_enabled(netdev->link, AF_INET6) < 0) {
3140 ERROR("Requires sysctl net.ipv6.conf.%s.proxy_ndp=1", netdev->link);
596a002c 3141 return ret_set_errno(-1, EINVAL);
6509154d 3142 }
3143
3144 /* Check for net.ipv6.conf.[link].forwarding=1 */
3145 if (lxc_is_ip_forwarding_enabled(netdev->link, AF_INET6) < 0) {
3146 ERROR("Requires sysctl net.ipv6.conf.%s.forwarding=1", netdev->link);
596a002c 3147 return ret_set_errno(-1, EINVAL);
6509154d 3148 }
3149 }
3150
b670016a 3151 /* Perform IPVLAN specific checks. */
3152 if (netdev->type == LXC_NET_IPVLAN) {
3153 /* Check mode is l3s as other modes do not work with l2proxy. */
3154 if (netdev->priv.ipvlan_attr.mode != IPVLAN_MODE_L3S) {
3155 ERROR("Requires ipvlan mode on dev \"%s\" be l3s when used with l2proxy", netdev->link);
596a002c 3156 return ret_set_errno(-1, EINVAL);
b670016a 3157 }
3158
3159 /* Retrieve local-loopback interface index for use with IPVLAN static routes. */
3ebffb98 3160 lo_ifindex = if_nametoindex(loop_device);
b670016a 3161 if (lo_ifindex == 0) {
3ebffb98 3162 ERROR("Failed to retrieve ifindex for \"%s\" routing cleanup", loop_device);
596a002c 3163 return ret_set_errno(-1, EINVAL);
b670016a 3164 }
3165 }
3166
6509154d 3167 lxc_list_for_each_safe(cur, &netdev->ipv4, next) {
3168 inet4dev = cur->elem;
3169 if (!inet_ntop(AF_INET, &inet4dev->addr, bufinet4, sizeof(bufinet4)))
596a002c 3170 return ret_set_errno(-1, -errno);
6509154d 3171
5fe147e9 3172 if (lxc_ip_neigh_proxy(RTM_NEWNEIGH, AF_INET, link_ifindex, &inet4dev->addr) < 0)
596a002c 3173 return ret_set_errno(-1, EINVAL);
b670016a 3174
3175 /* IPVLAN requires a route to local-loopback to trigger l2proxy. */
3176 if (netdev->type == LXC_NET_IPVLAN) {
3177 err = lxc_ipv4_dest_add(lo_ifindex, &inet4dev->addr, 32);
3178 if (err < 0) {
3ebffb98 3179 ERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"", bufinet4, loop_device);
596a002c 3180 return ret_set_errno(-1, -err);
b670016a 3181 }
3182 }
6509154d 3183 }
3184
3185 lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
3186 inet6dev = cur->elem;
3187 if (!inet_ntop(AF_INET6, &inet6dev->addr, bufinet6, sizeof(bufinet6)))
596a002c 3188 return ret_set_errno(-1, -errno);
6509154d 3189
5fe147e9 3190 if (lxc_ip_neigh_proxy(RTM_NEWNEIGH, AF_INET6, link_ifindex, &inet6dev->addr) < 0)
596a002c 3191 return ret_set_errno(-1, EINVAL);
b670016a 3192
3193 /* IPVLAN requires a route to local-loopback to trigger l2proxy. */
3194 if (netdev->type == LXC_NET_IPVLAN) {
3195 err = lxc_ipv6_dest_add(lo_ifindex, &inet6dev->addr, 128);
3196 if (err < 0) {
3ebffb98 3197 ERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"", bufinet6, loop_device);
596a002c 3198 return ret_set_errno(-1, -err);
b670016a 3199 }
3200 }
6509154d 3201 }
3202
3203 return 0;
3204}
3205
b670016a 3206static int lxc_delete_ipv4_l2proxy(struct in_addr *ip, char *link, unsigned int lo_ifindex) {
3207 char bufinet4[INET_ADDRSTRLEN];
5fe147e9 3208 unsigned int errCount = 0, link_ifindex = 0;
b670016a 3209
3210 if (!inet_ntop(AF_INET, ip, bufinet4, sizeof(bufinet4))) {
3211 SYSERROR("Failed to convert IP for l2proxy ipv4 removal on dev \"%s\"", link);
596a002c 3212 return ret_set_errno(-1, EINVAL);
b670016a 3213 }
3214
3215 /* If a local-loopback ifindex supplied remove the static route to the lo device. */
3216 if (lo_ifindex > 0) {
3217 if (lxc_ipv4_dest_del(lo_ifindex, ip, 32) < 0) {
3218 errCount++;
3219 ERROR("Failed to delete ipv4 dest \"%s\" for network ifindex \"%u\"", bufinet4, lo_ifindex);
3220 }
3221 }
3222
3223 /* If link is supplied remove the IP neigh proxy entry for this IP on the device. */
3224 if (link[0] != '\0') {
5fe147e9
TP
3225 link_ifindex = if_nametoindex(link);
3226 if (link_ifindex == 0) {
3227 ERROR("Failed to retrieve ifindex for \"%s\" l2proxy cleanup", link);
3228 return ret_set_errno(-1, EINVAL);
3229 }
3230
3231 if (lxc_ip_neigh_proxy(RTM_DELNEIGH, AF_INET, link_ifindex, ip) < 0)
b670016a 3232 errCount++;
3233 }
3234
3235 if (errCount > 0)
596a002c 3236 return ret_set_errno(-1, EINVAL);
b670016a 3237
3238 return 0;
3239}
3240
3241static int lxc_delete_ipv6_l2proxy(struct in6_addr *ip, char *link, unsigned int lo_ifindex) {
3242 char bufinet6[INET6_ADDRSTRLEN];
5fe147e9 3243 unsigned int errCount = 0, link_ifindex = 0;
b670016a 3244
3245 if (!inet_ntop(AF_INET6, ip, bufinet6, sizeof(bufinet6))) {
3246 SYSERROR("Failed to convert IP for l2proxy ipv6 removal on dev \"%s\"", link);
596a002c 3247 return ret_set_errno(-1, EINVAL);
b670016a 3248 }
3249
3250 /* If a local-loopback ifindex supplied remove the static route to the lo device. */
3251 if (lo_ifindex > 0) {
3252 if (lxc_ipv6_dest_del(lo_ifindex, ip, 128) < 0) {
3253 errCount++;
3254 ERROR("Failed to delete ipv6 dest \"%s\" for network ifindex \"%u\"", bufinet6, lo_ifindex);
3255 }
3256 }
3257
3258 /* If link is supplied remove the IP neigh proxy entry for this IP on the device. */
3259 if (link[0] != '\0') {
5fe147e9
TP
3260 link_ifindex = if_nametoindex(link);
3261 if (link_ifindex == 0) {
3262 ERROR("Failed to retrieve ifindex for \"%s\" l2proxy cleanup", link);
3263 return ret_set_errno(-1, EINVAL);
3264 }
3265
3266 if (lxc_ip_neigh_proxy(RTM_DELNEIGH, AF_INET6, link_ifindex, ip) < 0)
b670016a 3267 errCount++;
3268 }
3269
3270 if (errCount > 0)
596a002c 3271 return ret_set_errno(-1, EINVAL);
b670016a 3272
3273 return 0;
3274}
3275
6509154d 3276static int lxc_delete_l2proxy(struct lxc_netdev *netdev) {
b670016a 3277 unsigned int lo_ifindex = 0;
3278 unsigned int errCount = 0;
6509154d 3279 struct lxc_list *cur, *next;
3280 struct lxc_inetdev *inet4dev;
3281 struct lxc_inet6dev *inet6dev;
6509154d 3282
b670016a 3283 /* Perform IPVLAN specific checks. */
3284 if (netdev->type == LXC_NET_IPVLAN) {
3285 /* Retrieve local-loopback interface index for use with IPVLAN static routes. */
3ebffb98 3286 lo_ifindex = if_nametoindex(loop_device);
b670016a 3287 if (lo_ifindex == 0) {
3288 errCount++;
3ebffb98 3289 ERROR("Failed to retrieve ifindex for \"%s\" routing cleanup", loop_device);
6509154d 3290 }
b670016a 3291 }
6509154d 3292
b670016a 3293 lxc_list_for_each_safe(cur, &netdev->ipv4, next) {
3294 inet4dev = cur->elem;
3295 if (lxc_delete_ipv4_l2proxy(&inet4dev->addr, netdev->link, lo_ifindex) < 0)
3296 errCount++;
6509154d 3297 }
3298
3299 lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
3300 inet6dev = cur->elem;
b670016a 3301 if (lxc_delete_ipv6_l2proxy(&inet6dev->addr, netdev->link, lo_ifindex) < 0)
3302 errCount++;
6509154d 3303 }
3304
b670016a 3305 if (errCount > 0)
596a002c 3306 return ret_set_errno(-1, EINVAL);
6509154d 3307
3308 return 0;
3309}
3310
e389f2af 3311static int lxc_create_network_priv(struct lxc_handler *handler)
811ef482 3312{
811ef482
CB
3313 struct lxc_list *iterator;
3314 struct lxc_list *network = &handler->conf->network;
3315
811ef482
CB
3316 lxc_list_for_each(iterator, network) {
3317 struct lxc_netdev *netdev = iterator->elem;
3318
3319 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
3320 ERROR("Invalid network configuration type %d", netdev->type);
3321 return -1;
3322 }
3323
6509154d 3324 /* Setup l2proxy entries if enabled and used with a link property */
3325 if (netdev->l2proxy && netdev->link[0] != '\0') {
3326 if (lxc_setup_l2proxy(netdev)) {
3327 ERROR("Failed to setup l2proxy");
3328 return -1;
3329 }
3330 }
3331
811ef482
CB
3332 if (netdev_conf[netdev->type](handler, netdev)) {
3333 ERROR("Failed to create network device");
3334 return -1;
3335 }
811ef482
CB
3336 }
3337
3338 return 0;
3339}
3340
e389f2af 3341int lxc_network_move_created_netdev_priv(struct lxc_handler *handler)
811ef482 3342{
e389f2af
CB
3343 pid_t pid = handler->pid;
3344 struct lxc_list *network = &handler->conf->network;
811ef482
CB
3345 struct lxc_list *iterator;
3346
e0010464 3347 if (am_guest_unpriv())
74c6e2b0 3348 return 0;
811ef482
CB
3349
3350 lxc_list_for_each(iterator, network) {
3dd78294 3351 __do_free char *physname = NULL;
e389f2af 3352 int ret;
811ef482
CB
3353 struct lxc_netdev *netdev = iterator->elem;
3354
811ef482
CB
3355 if (!netdev->ifindex)
3356 continue;
3357
3dd78294
CB
3358 if (netdev->type == LXC_NET_PHYS)
3359 physname = is_wlan(netdev->link);
3360
3361 if (physname)
3c9fdb32 3362 ret = lxc_netdev_move_wlan(physname, netdev->link, pid, netdev->name);
3dd78294 3363 else
8bf64b77 3364 ret = lxc_netdev_move_by_index(netdev->ifindex, pid, netdev->name);
535e8859 3365 if (ret) {
6d1400b5 3366 errno = -ret;
24190194
CB
3367 SYSERROR("Failed to move network device \"%s\" with ifindex %d to network namespace %d",
3368 netdev->created_name, netdev->ifindex, pid);
811ef482
CB
3369 return -1;
3370 }
3371
24190194
CB
3372 DEBUG("Moved network device \"%s\" with ifindex %d to network namespace of %d",
3373 netdev->created_name, netdev->ifindex, pid);
811ef482
CB
3374 }
3375
3376 return 0;
3377}
3378
3c09b97c
CB
3379static int network_requires_advanced_setup(int type)
3380{
3381 if (type == LXC_NET_EMPTY)
3382 return false;
3383
3384 if (type == LXC_NET_NONE)
3385 return false;
3386
3387 return true;
3388}
3389
e389f2af 3390static int lxc_create_network_unpriv(struct lxc_handler *handler)
74c6e2b0 3391{
e389f2af
CB
3392 int hooks_version = handler->conf->hooks_version;
3393 const char *lxcname = handler->name;
3394 const char *lxcpath = handler->lxcpath;
3395 struct lxc_list *network = &handler->conf->network;
3396 pid_t pid = handler->pid;
74c6e2b0
CB
3397 struct lxc_list *iterator;
3398
74c6e2b0
CB
3399 lxc_list_for_each(iterator, network) {
3400 struct lxc_netdev *netdev = iterator->elem;
3401
3c09b97c 3402 if (!network_requires_advanced_setup(netdev->type))
74c6e2b0
CB
3403 continue;
3404
3405 if (netdev->type != LXC_NET_VETH) {
e389f2af 3406 ERROR("Networks of type %s are not supported by unprivileged containers",
74c6e2b0
CB
3407 lxc_net_type_to_str(netdev->type));
3408 return -1;
3409 }
3410
3411 if (netdev->mtu)
3412 INFO("mtu ignored due to insufficient privilege");
3413
e389f2af
CB
3414 if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev,
3415 pid, hooks_version))
74c6e2b0
CB
3416 return -1;
3417 }
3418
3419 return 0;
3420}
3421
1bd8d726 3422bool lxc_delete_network_priv(struct lxc_handler *handler)
811ef482
CB
3423{
3424 int ret;
3425 struct lxc_list *iterator;
3426 struct lxc_list *network = &handler->conf->network;
1bd8d726 3427
811ef482
CB
3428 lxc_list_for_each(iterator, network) {
3429 char *hostveth = NULL;
3430 struct lxc_netdev *netdev = iterator->elem;
3431
3432 /* We can only delete devices whose ifindex we have. If we don't
3433 * have the index it means that we didn't create it.
3434 */
3435 if (!netdev->ifindex)
3436 continue;
3437
0104c121
CB
3438 /*
3439 * If the network device has been moved back from the
3440 * containers network namespace, update the ifindex.
3441 */
3442 netdev->ifindex = if_nametoindex(netdev->name);
3443
6509154d 3444 /* Delete l2proxy entries if enabled and used with a link property */
3445 if (netdev->l2proxy && netdev->link[0] != '\0') {
3446 if (lxc_delete_l2proxy(netdev))
3447 WARN("Failed to delete all l2proxy config");
3448 /* Don't return, let the network be cleaned up as normal. */
3449 }
3450
811ef482
CB
3451 if (netdev->type == LXC_NET_PHYS) {
3452 ret = lxc_netdev_rename_by_index(netdev->ifindex, netdev->link);
3453 if (ret < 0)
3454 WARN("Failed to rename interface with index %d "
b809f232
CB
3455 "from \"%s\" to its initial name \"%s\"",
3456 netdev->ifindex, netdev->name, netdev->link);
0b154989 3457 else {
29589196
CB
3458 TRACE("Renamed interface with index %d from "
3459 "\"%s\" to its initial name \"%s\"",
3460 netdev->ifindex, netdev->name,
3461 netdev->link);
0b154989
TP
3462
3463 /* Restore original MTU */
3464 ret = lxc_netdev_set_mtu(netdev->link, netdev->priv.phys_attr.mtu);
3465 if (ret < 0) {
3466 WARN("Failed to set interface \"%s\" to its initial mtu \"%d\"",
3467 netdev->link, netdev->priv.phys_attr.mtu);
3468 } else {
3469 TRACE("Restored interface \"%s\" to its initial mtu \"%d\"",
3470 netdev->link, netdev->priv.phys_attr.mtu);
3471 }
3472 }
b3259dc6
TP
3473
3474 ret = netdev_deconf[netdev->type](handler, netdev);
66a7c406 3475 goto clear_ifindices;
811ef482
CB
3476 }
3477
3478 ret = netdev_deconf[netdev->type](handler, netdev);
3479 if (ret < 0)
3480 WARN("Failed to deconfigure network device");
3481
811ef482 3482 if (netdev->type != LXC_NET_VETH)
66a7c406 3483 goto clear_ifindices;
811ef482 3484
811ef482
CB
3485 /* Explicitly delete host veth device to prevent lingering
3486 * devices. We had issues in LXD around this.
3487 */
de4855a8 3488 if (netdev->priv.veth_attr.pair[0] != '\0')
811ef482
CB
3489 hostveth = netdev->priv.veth_attr.pair;
3490 else
3491 hostveth = netdev->priv.veth_attr.veth1;
de4855a8 3492 if (hostveth[0] == '\0')
66a7c406 3493 goto clear_ifindices;
811ef482
CB
3494
3495 ret = lxc_netdev_delete_by_name(hostveth);
3496 if (ret < 0) {
24548539
CB
3497 WARN("Failed to remove interface \"%s\" from \"%s\"",
3498 hostveth, netdev->link);
66a7c406 3499 goto clear_ifindices;
811ef482
CB
3500 }
3501 INFO("Removed interface \"%s\" from \"%s\"", hostveth, netdev->link);
3502
c869be20 3503 if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link)) {
811ef482 3504 netdev->priv.veth_attr.veth1[0] = '\0';
66a7c406
CB
3505 netdev->ifindex = 0;
3506 netdev->priv.veth_attr.ifindex = 0;
3507 goto clear_ifindices;
811ef482
CB
3508 }
3509
3510 /* Delete the openvswitch port. */
3511 ret = lxc_ovs_delete_port(netdev->link, hostveth);
3512 if (ret < 0)
3513 WARN("Failed to remove port \"%s\" from openvswitch "
3514 "bridge \"%s\"", hostveth, netdev->link);
3515 else
3516 INFO("Removed port \"%s\" from openvswitch bridge \"%s\"",
3517 hostveth, netdev->link);
3518
66a7c406 3519clear_ifindices:
ad2ddfcd 3520 /* We need to clear any ifindices we recorded so liblxc won't
66a7c406
CB
3521 * have cached stale data which would cause it to fail on reboot
3522 * we're we don't re-read the on-disk config file.
3523 */
3524 netdev->ifindex = 0;
3525 if (netdev->type == LXC_NET_PHYS) {
3526 netdev->priv.phys_attr.ifindex = 0;
3527 } else if (netdev->type == LXC_NET_VETH) {
3528 netdev->priv.veth_attr.veth1[0] = '\0';
3529 netdev->priv.veth_attr.ifindex = 0;
3530 }
811ef482
CB
3531 }
3532
bb84beda 3533 return true;
811ef482
CB
3534}
3535
3536int lxc_requests_empty_network(struct lxc_handler *handler)
3537{
3538 struct lxc_list *network = &handler->conf->network;
3539 struct lxc_list *iterator;
3540 bool found_none = false, found_nic = false;
3541
3542 if (lxc_list_empty(network))
3543 return 0;
3544
3545 lxc_list_for_each(iterator, network) {
3546 struct lxc_netdev *netdev = iterator->elem;
3547
3548 if (netdev->type == LXC_NET_NONE)
3549 found_none = true;
3550 else
3551 found_nic = true;
3552 }
3553 if (found_none && !found_nic)
3554 return 1;
3555 return 0;
3556}
3557
3558/* try to move physical nics to the init netns */
b809f232 3559int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
811ef482
CB
3560{
3561 int ret;
b809f232 3562 int oldfd;
811ef482 3563 char ifname[IFNAMSIZ];
b809f232 3564 struct lxc_list *iterator;
28d9e29e 3565 int netnsfd = handler->nsfd[LXC_NS_NET];
b809f232 3566 struct lxc_conf *conf = handler->conf;
811ef482 3567
b809f232
CB
3568 /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
3569 * the parent network namespace. We won't have this capability if we are
3570 * unprivileged.
3571 */
d0fbc7ba 3572 if (!handler->am_root)
b809f232 3573 return 0;
811ef482 3574
b809f232 3575 TRACE("Moving physical network devices back to parent network namespace");
811ef482 3576
0037ab49 3577 oldfd = lxc_preserve_ns(handler->monitor_pid, "net");
811ef482
CB
3578 if (oldfd < 0) {
3579 SYSERROR("Failed to preserve network namespace");
b809f232 3580 return -1;
811ef482
CB
3581 }
3582
b809f232 3583 ret = setns(netnsfd, CLONE_NEWNET);
811ef482
CB
3584 if (ret < 0) {
3585 SYSERROR("Failed to enter network namespace");
3586 close(oldfd);
b809f232 3587 return -1;
811ef482
CB
3588 }
3589
b809f232
CB
3590 lxc_list_for_each(iterator, &conf->network) {
3591 struct lxc_netdev *netdev = iterator->elem;
811ef482 3592
b809f232
CB
3593 if (netdev->type != LXC_NET_PHYS)
3594 continue;
3595
3596 /* Retrieve the name of the interface in the container's network
3597 * namespace.
3598 */
3599 if (!if_indextoname(netdev->ifindex, ifname)) {
811ef482 3600 WARN("No interface corresponding to ifindex %d",
b809f232 3601 netdev->ifindex);
811ef482
CB
3602 continue;
3603 }
b809f232 3604
0037ab49 3605 ret = lxc_netdev_move_by_index_fd(netdev->ifindex, oldfd, netdev->link);
b809f232 3606 if (ret < 0)
811ef482
CB
3607 WARN("Error moving network device \"%s\" back to "
3608 "network namespace", ifname);
b809f232
CB
3609 else
3610 TRACE("Moved network device \"%s\" back to network "
3611 "namespace", ifname);
811ef482 3612 }
811ef482 3613
b809f232 3614 ret = setns(oldfd, CLONE_NEWNET);
811ef482 3615 close(oldfd);
b809f232
CB
3616 if (ret < 0) {
3617 SYSERROR("Failed to enter network namespace");
3618 return -1;
3619 }
3620
3621 return 0;
811ef482
CB
3622}
3623
3624static int setup_hw_addr(char *hwaddr, const char *ifname)
3625{
3626 struct sockaddr sockaddr;
3627 struct ifreq ifr;
6d1400b5 3628 int ret, fd;
811ef482
CB
3629
3630 ret = lxc_convert_mac(hwaddr, &sockaddr);
3631 if (ret) {
6d1400b5 3632 errno = -ret;
3633 SYSERROR("Mac address \"%s\" conversion failed", hwaddr);
811ef482
CB
3634 return -1;
3635 }
3636
3637 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
3638 ifr.ifr_name[IFNAMSIZ-1] = '\0';
3639 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
3640
ad9429e5 3641 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
811ef482
CB
3642 if (fd < 0)
3643 return -1;
3644
3645 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
811ef482 3646 if (ret)
6d1400b5 3647 SYSERROR("Failed to perform ioctl");
3648
3649 close(fd);
811ef482
CB
3650
3651 DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr,
3652 ifr.ifr_name);
3653
3654 return ret;
3655}
3656
3657static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
3658{
3659 struct lxc_list *iterator;
3660 int err;
3661
3662 lxc_list_for_each(iterator, ip) {
3663 struct lxc_inetdev *inetdev = iterator->elem;
3664
3665 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
3666 &inetdev->bcast, inetdev->prefix);
3667 if (err) {
6d1400b5 3668 errno = -err;
3669 SYSERROR("Failed to setup ipv4 address for network device "
d4a7da46 3670 "with ifindex %d", ifindex);
811ef482
CB
3671 return -1;
3672 }
3673 }
3674
3675 return 0;
3676}
3677
3678static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
3679{
3680 struct lxc_list *iterator;
3681 int err;
3682
3683 lxc_list_for_each(iterator, ip) {
3684 struct lxc_inet6dev *inet6dev = iterator->elem;
3685
3686 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
3687 &inet6dev->mcast, &inet6dev->acast,
3688 inet6dev->prefix);
3689 if (err) {
6d1400b5 3690 errno = -err;
3691 SYSERROR("Failed to setup ipv6 address for network device "
d4a7da46 3692 "with ifindex %d", ifindex);
811ef482
CB
3693 return -1;
3694 }
3695 }
3696
3697 return 0;
3698}
3699
8bf64b77 3700static int lxc_network_setup_in_child_namespaces_common(struct lxc_netdev *netdev)
811ef482 3701{
811ef482 3702 int err;
009d6127 3703 char bufinet4[INET_ADDRSTRLEN], bufinet6[INET6_ADDRSTRLEN];
811ef482
CB
3704
3705 /* empty network namespace */
8bf64b77
CB
3706 if (!netdev->ifindex && netdev->flags & IFF_UP) {
3707 err = lxc_netdev_up("lo");
811ef482 3708 if (err) {
6d1400b5 3709 errno = -err;
8bf64b77 3710 SYSERROR( "Failed to set the loopback network device up");
811ef482
CB
3711 return -1;
3712 }
3713 }
3714
811ef482
CB
3715 /* set a mac address */
3716 if (netdev->hwaddr) {
8bf64b77 3717 if (setup_hw_addr(netdev->hwaddr, netdev->name)) {
811ef482 3718 ERROR("Failed to setup hw address for network device \"%s\"",
8bf64b77 3719 netdev->name);
811ef482
CB
3720 return -1;
3721 }
3722 }
3723
3724 /* setup ipv4 addresses on the interface */
3725 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
3726 ERROR("Failed to setup ip addresses for network device \"%s\"",
8bf64b77 3727 netdev->name);
811ef482
CB
3728 return -1;
3729 }
3730
3731 /* setup ipv6 addresses on the interface */
3732 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
3733 ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
8bf64b77 3734 netdev->name);
811ef482
CB
3735 return -1;
3736 }
3737
3738 /* set the network device up */
3739 if (netdev->flags & IFF_UP) {
8bf64b77 3740 err = lxc_netdev_up(netdev->name);
811ef482 3741 if (err) {
6d1400b5 3742 errno = -err;
3743 SYSERROR("Failed to set network device \"%s\" up",
8bf64b77 3744 netdev->name);
811ef482
CB
3745 return -1;
3746 }
3747
3748 /* the network is up, make the loopback up too */
3749 err = lxc_netdev_up("lo");
3750 if (err) {
6d1400b5 3751 errno = -err;
3752 SYSERROR("Failed to set the loopback network device up");
811ef482
CB
3753 return -1;
3754 }
3755 }
3756
811ef482 3757 /* setup ipv4 gateway on the interface */
a2f9a670 3758 if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) {
811ef482
CB
3759 if (!(netdev->flags & IFF_UP)) {
3760 ERROR("Cannot add ipv4 gateway for network device "
8bf64b77 3761 "\"%s\" when not bringing up the interface", netdev->name);
811ef482
CB
3762 return -1;
3763 }
3764
3765 if (lxc_list_empty(&netdev->ipv4)) {
3766 ERROR("Cannot add ipv4 gateway for network device "
8bf64b77 3767 "\"%s\" when not assigning an address", netdev->name);
811ef482
CB
3768 return -1;
3769 }
3770
a2f9a670 3771 /* Setup device route if ipv4_gateway_dev is enabled */
3772 if (netdev->ipv4_gateway_dev) {
3773 err = lxc_ipv4_gateway_add(netdev->ifindex, NULL);
3774 if (err < 0) {
3775 SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
8bf64b77 3776 netdev->name);
596a002c 3777 return ret_set_errno(-1, -err);
811ef482 3778 }
a2f9a670 3779 } else {
009d6127 3780 /* Check the gateway address is valid */
3781 if (!inet_ntop(AF_INET, netdev->ipv4_gateway, bufinet4, sizeof(bufinet4)))
596a002c 3782 return ret_set_errno(-1, errno);
009d6127 3783
3784 /* Try adding a default route to the gateway address */
811ef482 3785 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
009d6127 3786 if (err < 0) {
3787 /* If adding the default route fails, this could be because the
3788 * gateway address is in a different subnet to the container's address.
3789 * To work around this, we try adding a static device route to the
3790 * gateway address first, and then try again.
3791 */
a2f9a670 3792 err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway, 32);
009d6127 3793 if (err < 0) {
a2f9a670 3794 errno = -err;
009d6127 3795 SYSERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"",
8bf64b77 3796 bufinet4, netdev->name);
009d6127 3797 return -1;
a2f9a670 3798 }
6d1400b5 3799
a2f9a670 3800 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
009d6127 3801 if (err < 0) {
a2f9a670 3802 errno = -err;
009d6127 3803 SYSERROR("Failed to setup ipv4 gateway \"%s\" for network device \"%s\"",
8bf64b77 3804 bufinet4, netdev->name);
a2f9a670 3805 return -1;
811ef482 3806 }
811ef482
CB
3807 }
3808 }
3809 }
3810
3811 /* setup ipv6 gateway on the interface */
a2f9a670 3812 if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) {
811ef482 3813 if (!(netdev->flags & IFF_UP)) {
e389f2af 3814 ERROR("Cannot add ipv6 gateway for network device \"%s\" when not bringing up the interface",
8bf64b77 3815 netdev->name);
811ef482
CB
3816 return -1;
3817 }
3818
3819 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
e389f2af 3820 ERROR("Cannot add ipv6 gateway for network device \"%s\" when not assigning an address",
8bf64b77 3821 netdev->name);
811ef482
CB
3822 return -1;
3823 }
3824
a2f9a670 3825 /* Setup device route if ipv6_gateway_dev is enabled */
3826 if (netdev->ipv6_gateway_dev) {
3827 err = lxc_ipv6_gateway_add(netdev->ifindex, NULL);
3828 if (err < 0) {
3829 SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
8bf64b77 3830 netdev->name);
596a002c 3831 return ret_set_errno(-1, -err);
811ef482 3832 }
a2f9a670 3833 } else {
009d6127 3834 /* Check the gateway address is valid */
3835 if (!inet_ntop(AF_INET6, netdev->ipv6_gateway, bufinet6, sizeof(bufinet6)))
596a002c 3836 return ret_set_errno(-1, errno);
009d6127 3837
3838 /* Try adding a default route to the gateway address */
811ef482 3839 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
009d6127 3840 if (err < 0) {
3841 /* If adding the default route fails, this could be because the
3842 * gateway address is in a different subnet to the container's address.
3843 * To work around this, we try adding a static device route to the
3844 * gateway address first, and then try again.
3845 */
a2f9a670 3846 err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway, 128);
009d6127 3847 if (err < 0) {
a2f9a670 3848 errno = -err;
009d6127 3849 SYSERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"",
8bf64b77 3850 bufinet6, netdev->name);
009d6127 3851 return -1;
a2f9a670 3852 }
6d1400b5 3853
a2f9a670 3854 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
009d6127 3855 if (err < 0) {
a2f9a670 3856 errno = -err;
009d6127 3857 SYSERROR("Failed to setup ipv6 gateway \"%s\" for network device \"%s\"",
8bf64b77 3858 bufinet6, netdev->name);
a2f9a670 3859 return -1;
811ef482 3860 }
811ef482
CB
3861 }
3862 }
3863 }
3864
8bf64b77 3865 DEBUG("Network device \"%s\" has been setup", netdev->name);
811ef482
CB
3866
3867 return 0;
3868}
3869
3870int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
3871 struct lxc_list *network)
3872{
3873 struct lxc_list *iterator;
811ef482 3874
8bf64b77 3875 lxc_list_for_each (iterator, network) {
e389f2af 3876 struct lxc_netdev *netdev = iterator->elem;
8bf64b77 3877 int ret;
811ef482 3878
8bf64b77
CB
3879 ret = netdev_ns_conf[netdev->type](netdev);
3880 if (!ret)
3881 ret = lxc_network_setup_in_child_namespaces_common(netdev);
3882 if (ret) {
e389f2af 3883 ERROR("Failed to setup netdev");
811ef482
CB
3884 return -1;
3885 }
3886 }
3887
3888 if (!lxc_list_empty(network))
e389f2af 3889 INFO("Network has been setup");
811ef482
CB
3890
3891 return 0;
3892}
7ab1ba02 3893
3c09b97c 3894int lxc_network_send_to_child(struct lxc_handler *handler)
7ab1ba02
CB
3895{
3896 struct lxc_list *iterator;
3897 struct lxc_list *network = &handler->conf->network;
3898 int data_sock = handler->data_sock[0];
3899
7ab1ba02
CB
3900 lxc_list_for_each(iterator, network) {
3901 int ret;
3902 struct lxc_netdev *netdev = iterator->elem;
3903
3c09b97c 3904 if (!network_requires_advanced_setup(netdev->type))
7ab1ba02
CB
3905 continue;
3906
7fbb15ec 3907 ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
7729f8e5 3908 if (ret < 0)
7ab1ba02 3909 return -1;
e389f2af
CB
3910
3911 ret = lxc_send_nointr(data_sock, netdev->created_name, IFNAMSIZ, MSG_NOSIGNAL);
3912 if (ret < 0)
3913 return -1;
3914
3915 TRACE("Sent network device name \"%s\" to child", netdev->created_name);
7ab1ba02
CB
3916 }
3917
3918 return 0;
3919}
3920
3c09b97c 3921int lxc_network_recv_from_parent(struct lxc_handler *handler)
7ab1ba02
CB
3922{
3923 struct lxc_list *iterator;
3924 struct lxc_list *network = &handler->conf->network;
3925 int data_sock = handler->data_sock[1];
3926
7ab1ba02
CB
3927 lxc_list_for_each(iterator, network) {
3928 int ret;
3929 struct lxc_netdev *netdev = iterator->elem;
3930
3c09b97c 3931 if (!network_requires_advanced_setup(netdev->type))
7ab1ba02
CB
3932 continue;
3933
e3233f26 3934 ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
7729f8e5 3935 if (ret < 0)
7ab1ba02 3936 return -1;
e389f2af
CB
3937
3938 ret = lxc_recv_nointr(data_sock, netdev->created_name, IFNAMSIZ, 0);
3939 if (ret < 0)
3940 return -1;
54256301 3941
e389f2af 3942 TRACE("Received network device name \"%s\" from parent", netdev->created_name);
7ab1ba02
CB
3943 }
3944
3945 return 0;
3946}
a1ae535a
CB
3947
3948int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handler)
3949{
3950 struct lxc_list *iterator, *network;
3951 int data_sock = handler->data_sock[0];
3952
3953 if (!handler->am_root)
3954 return 0;
3955
3956 network = &handler->conf->network;
3957 lxc_list_for_each(iterator, network) {
3958 int ret;
3959 struct lxc_netdev *netdev = iterator->elem;
3960
3961 /* Send network device name in the child's namespace to parent. */
7fbb15ec 3962 ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
a1ae535a 3963 if (ret < 0)
7729f8e5 3964 return -1;
a1ae535a
CB
3965
3966 /* Send network device ifindex in the child's namespace to
3967 * parent.
3968 */
7fbb15ec 3969 ret = lxc_send_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), MSG_NOSIGNAL);
a1ae535a 3970 if (ret < 0)
7729f8e5 3971 return -1;
a1ae535a
CB
3972 }
3973
e389f2af
CB
3974 if (!lxc_list_empty(network))
3975 TRACE("Sent network device names and ifindices to parent");
3976
a1ae535a 3977 return 0;
a1ae535a
CB
3978}
3979
3980int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler)
3981{
3982 struct lxc_list *iterator, *network;
3983 int data_sock = handler->data_sock[1];
3984
3985 if (!handler->am_root)
3986 return 0;
3987
3988 network = &handler->conf->network;
3989 lxc_list_for_each(iterator, network) {
3990 int ret;
3991 struct lxc_netdev *netdev = iterator->elem;
3992
3993 /* Receive network device name in the child's namespace to
3994 * parent.
3995 */
e3233f26 3996 ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
a1ae535a 3997 if (ret < 0)
7729f8e5 3998 return -1;
a1ae535a
CB
3999
4000 /* Receive network device ifindex in the child's namespace to
4001 * parent.
4002 */
e3233f26 4003 ret = lxc_recv_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), 0);
a1ae535a 4004 if (ret < 0)
7729f8e5 4005 return -1;
a1ae535a
CB
4006 }
4007
4008 return 0;
a1ae535a 4009}
bb84beda
CB
4010
4011void lxc_delete_network(struct lxc_handler *handler)
4012{
4013 bool bret;
4014
4015 if (handler->am_root)
4016 bret = lxc_delete_network_priv(handler);
4017 else
4018 bret = lxc_delete_network_unpriv(handler);
4019 if (!bret)
4020 DEBUG("Failed to delete network devices");
4021 else
4022 DEBUG("Deleted network devices");
4023}
1cd95214 4024
1cd95214
CB
4025int lxc_netns_set_nsid(int fd)
4026{
41a3300d 4027 int ret;
0ce60f0d
CB
4028 char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
4029 NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
4030 NLMSG_ALIGN(1024)];
1cd95214 4031 struct nl_handler nlh;
0ce60f0d
CB
4032 struct nlmsghdr *hdr;
4033 struct rtgenmsg *msg;
bfcedc7e 4034 int saved_errno;
9d036caa
CB
4035 const __s32 ns_id = -1;
4036 const __u32 netns_fd = fd;
1cd95214
CB
4037
4038 ret = netlink_open(&nlh, NETLINK_ROUTE);
4039 if (ret < 0)
41a3300d 4040 return -1;
1cd95214 4041
0ce60f0d 4042 memset(buf, 0, sizeof(buf));
6ce39620
CB
4043
4044#pragma GCC diagnostic push
4045#pragma GCC diagnostic ignored "-Wcast-align"
0ce60f0d
CB
4046 hdr = (struct nlmsghdr *)buf;
4047 msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
6ce39620 4048#pragma GCC diagnostic pop
1cd95214 4049
0ce60f0d
CB
4050 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
4051 hdr->nlmsg_type = RTM_NEWNSID;
4052 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
4053 hdr->nlmsg_pid = 0;
4054 hdr->nlmsg_seq = RTM_NEWNSID;
4055 msg->rtgen_family = AF_UNSPEC;
1cd95214 4056
9d036caa
CB
4057 ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
4058 if (ret < 0)
4059 goto on_error;
4060
4061 ret = addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
4062 if (ret < 0)
4063 goto on_error;
1cd95214 4064
9fbbc427 4065 ret = __netlink_transaction(&nlh, hdr, hdr);
9d036caa
CB
4066
4067on_error:
bfcedc7e 4068 saved_errno = errno;
1cd95214 4069 netlink_close(&nlh);
bfcedc7e 4070 errno = saved_errno;
1cd95214 4071
9d036caa 4072 return ret;
1cd95214 4073}
938980ba
CB
4074
4075static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
4076{
4077
4078 memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
4079
4080 while (RTA_OK(rta, len)) {
4081 unsigned short type = rta->rta_type;
4082
4083 if ((type <= max) && (!tb[type]))
4084 tb[type] = rta;
4085
6ce39620
CB
4086#pragma GCC diagnostic push
4087#pragma GCC diagnostic ignored "-Wcast-align"
938980ba 4088 rta = RTA_NEXT(rta, len);
6ce39620 4089#pragma GCC diagnostic pop
938980ba
CB
4090 }
4091
4092 return 0;
4093}
4094
4095static inline __s32 rta_getattr_s32(const struct rtattr *rta)
4096{
4097 return *(__s32 *)RTA_DATA(rta);
4098}
4099
4100#ifndef NETNS_RTA
4101#define NETNS_RTA(r) \
4102 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
4103#endif
4104
4105int lxc_netns_get_nsid(int fd)
4106{
4107 int ret;
4108 ssize_t len;
4109 char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
9d036caa
CB
4110 NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
4111 NLMSG_ALIGN(1024)];
938980ba
CB
4112 struct rtattr *tb[__LXC_NETNSA_MAX + 1];
4113 struct nl_handler nlh;
4114 struct nlmsghdr *hdr;
4115 struct rtgenmsg *msg;
4116 int saved_errno;
4117 __u32 netns_fd = fd;
4118
4119 ret = netlink_open(&nlh, NETLINK_ROUTE);
4120 if (ret < 0)
4121 return -1;
4122
4123 memset(buf, 0, sizeof(buf));
6ce39620
CB
4124
4125#pragma GCC diagnostic push
4126#pragma GCC diagnostic ignored "-Wcast-align"
938980ba
CB
4127 hdr = (struct nlmsghdr *)buf;
4128 msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
6ce39620 4129#pragma GCC diagnostic pop
938980ba
CB
4130
4131 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
4132 hdr->nlmsg_type = RTM_GETNSID;
4133 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
4134 hdr->nlmsg_pid = 0;
4135 hdr->nlmsg_seq = RTM_GETNSID;
4136 msg->rtgen_family = AF_UNSPEC;
4137
9d036caa
CB
4138 ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
4139 if (ret == 0)
4140 ret = __netlink_transaction(&nlh, hdr, hdr);
938980ba 4141
938980ba
CB
4142 saved_errno = errno;
4143 netlink_close(&nlh);
4144 errno = saved_errno;
4145 if (ret < 0)
4146 return -1;
4147
9d036caa 4148 errno = EINVAL;
938980ba
CB
4149 msg = NLMSG_DATA(hdr);
4150 len = hdr->nlmsg_len - NLMSG_SPACE(sizeof(*msg));
4151 if (len < 0)
4152 return -1;
4153
6ce39620
CB
4154#pragma GCC diagnostic push
4155#pragma GCC diagnostic ignored "-Wcast-align"
938980ba
CB
4156 parse_rtattr(tb, __LXC_NETNSA_MAX, NETNS_RTA(msg), len);
4157 if (tb[__LXC_NETNSA_NSID])
4158 return rta_getattr_s32(tb[__LXC_NETNSA_NSID]);
6ce39620 4159#pragma GCC diagnostic pop
938980ba
CB
4160
4161 return -1;
4162}
e389f2af
CB
4163
4164int lxc_create_network(struct lxc_handler *handler)
4165{
4166 int ret;
4167
e389f2af
CB
4168 if (handler->am_root) {
4169 ret = lxc_create_network_priv(handler);
4170 if (ret)
4171 return -1;
4172
4173 return lxc_network_move_created_netdev_priv(handler);
4174 }
4175
4176 return lxc_create_network_unpriv(handler);
4177}