]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/network.c
conf: log lxc-user-nic output
[mirror_lxc.git] / src / lxc / network.c
CommitLineData
0ad19a3f 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
0ad19a3f 8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0ad19a3f 22 */
cb0dc11b
CB
23
24#include "config.h"
25
26#include <ctype.h>
27#include <errno.h>
28#include <fcntl.h>
0ad19a3f 29#include <stdio.h>
0ad19a3f 30#include <stdlib.h>
0ad19a3f 31#include <string.h>
dd1d77f9 32#include <time.h>
cb0dc11b 33#include <unistd.h>
0ad19a3f 34#include <arpa/inet.h>
0ad19a3f 35#include <linux/netlink.h>
36#include <linux/rtnetlink.h>
37#include <linux/sockios.h>
cb0dc11b
CB
38#include <net/ethernet.h>
39#include <net/if.h>
40#include <net/if_arp.h>
41#include <netinet/in.h>
42#include <sys/inotify.h>
43#include <sys/ioctl.h>
44#include <sys/param.h>
45#include <sys/socket.h>
46#include <sys/stat.h>
47#include <sys/types.h>
f549edcc 48
72d0e1cb 49#include "conf.h"
cb0dc11b
CB
50#include "log.h"
51#include "network.h"
52#include "nl.h"
0d204771 53#include "utils.h"
0ad19a3f 54
a0265685
SG
55#if HAVE_IFADDRS_H
56#include <ifaddrs.h>
57#else
58#include <../include/ifaddrs.h>
59#endif
60
0ad19a3f 61#ifndef IFLA_LINKMODE
cb0dc11b 62#define IFLA_LINKMODE 17
0ad19a3f 63#endif
64
65#ifndef IFLA_LINKINFO
cb0dc11b 66#define IFLA_LINKINFO 18
0ad19a3f 67#endif
68
69#ifndef IFLA_NET_NS_PID
cb0dc11b 70#define IFLA_NET_NS_PID 19
0ad19a3f 71#endif
72
73#ifndef IFLA_INFO_KIND
cb0dc11b 74#define IFLA_INFO_KIND 1
0ad19a3f 75#endif
76
26c39028 77#ifndef IFLA_VLAN_ID
cb0dc11b 78#define IFLA_VLAN_ID 1
26c39028
JHS
79#endif
80
0ad19a3f 81#ifndef IFLA_INFO_DATA
cb0dc11b 82#define IFLA_INFO_DATA 2
0ad19a3f 83#endif
84
85#ifndef VETH_INFO_PEER
cb0dc11b 86#define VETH_INFO_PEER 1
0ad19a3f 87#endif
88
e892973e 89#ifndef IFLA_MACVLAN_MODE
cb0dc11b 90#define IFLA_MACVLAN_MODE 1
e892973e
DL
91#endif
92
cb0dc11b 93lxc_log_define(lxc_network, lxc);
f8fee0e2 94
ebc73a67 95int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char *ifname)
0ad19a3f 96{
ebc73a67 97 int err;
0ad19a3f 98 struct nl_handler nlh;
06f976ca 99 struct ifinfomsg *ifi;
ebc73a67 100 struct nlmsg *nlmsg = NULL;
0ad19a3f 101
3cfc0f3a
MN
102 err = netlink_open(&nlh, NETLINK_ROUTE);
103 if (err)
104 return err;
0ad19a3f 105
3cfc0f3a 106 err = -ENOMEM;
0ad19a3f 107 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
108 if (!nlmsg)
109 goto out;
110
ebc73a67 111 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
112 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
113
114 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
115 if (!ifi)
116 goto out;
06f976ca
SZ
117 ifi->ifi_family = AF_UNSPEC;
118 ifi->ifi_index = ifindex;
0ad19a3f 119
120 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
121 goto out;
122
8d357196
DY
123 if (ifname != NULL) {
124 if (nla_put_string(nlmsg, IFLA_IFNAME, ifname))
125 goto out;
126 }
127
3cfc0f3a 128 err = netlink_transaction(&nlh, nlmsg, nlmsg);
0ad19a3f 129out:
130 netlink_close(&nlh);
131 nlmsg_free(nlmsg);
132 return err;
133}
134
ebc73a67
CB
135/* If we are asked to move a wireless interface, then we must actually move its
136 * phyN device. Detect that condition and return the physname here. The physname
137 * will be passed to lxc_netdev_move_wlan() which will free it when done.
e5848d39
SH
138 */
139#define PHYSNAME "/sys/class/net/%s/phy80211/name"
ebc73a67 140static char *is_wlan(const char *ifname)
e5848d39 141{
ebc73a67 142 int i, ret;
e5848d39 143 long physlen;
ebc73a67
CB
144 size_t len;
145 char *path;
e5848d39 146 FILE *f;
ebc73a67
CB
147 struct stat sb;
148 char *physname = NULL;
e5848d39 149
ebc73a67
CB
150 len = strlen(ifname) + strlen(PHYSNAME) - 1;
151 path = alloca(len + 1);
e5848d39 152 ret = snprintf(path, len, PHYSNAME, ifname);
ebc73a67 153 if (ret < 0 || (size_t)ret >= len)
e5848d39 154 goto bad;
ebc73a67 155
e5848d39
SH
156 ret = stat(path, &sb);
157 if (ret)
158 goto bad;
ebc73a67
CB
159
160 f = fopen(path, "r");
161 if (!f)
e5848d39 162 goto bad;
ebc73a67 163
1a0e70ac 164 /* Feh - sb.st_size is always 4096. */
e5848d39
SH
165 fseek(f, 0, SEEK_END);
166 physlen = ftell(f);
167 fseek(f, 0, SEEK_SET);
ebc73a67
CB
168
169 physname = malloc(physlen + 1);
ee54ea9a 170 if (!physname) {
acf47e1b 171 fclose(f);
e5848d39 172 goto bad;
ee54ea9a 173 }
ebc73a67
CB
174
175 memset(physname, 0, physlen + 1);
e5848d39
SH
176 ret = fread(physname, 1, physlen, f);
177 fclose(f);
178 if (ret < 0)
179 goto bad;
180
ebc73a67 181 for (i = 0; i < physlen; i++) {
e5848d39
SH
182 if (physname[i] == '\n')
183 physname[i] = '\0';
ebc73a67 184
e5848d39
SH
185 if (physname[i] == '\0')
186 break;
187 }
188
189 return physname;
190
191bad:
f10fad2f 192 free(physname);
e5848d39
SH
193 return NULL;
194}
195
ebc73a67
CB
196static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
197 const char *new)
e5848d39 198{
ebc73a67 199 pid_t fpid;
e5848d39 200
ebc73a67 201 fpid = fork();
e5848d39
SH
202 if (fpid < 0)
203 return -1;
ebc73a67 204
e5848d39
SH
205 if (fpid != 0)
206 return wait_for_pid(fpid);
ebc73a67 207
e5848d39
SH
208 if (!switch_to_ns(pid, "net"))
209 return -1;
ebc73a67 210
e5848d39
SH
211 exit(lxc_netdev_rename_by_name(old, new));
212}
213
ebc73a67
CB
214static int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
215 const char *newname)
e5848d39 216{
e5848d39 217 char *cmd;
ebc73a67
CB
218 pid_t fpid;
219 int err = -1;
e5848d39
SH
220
221 /* Move phyN into the container. TODO - do this using netlink.
ebc73a67
CB
222 * However, IIUC this involves a bit more complicated work to talk to
223 * the 80211 module, so for now just call out to iw.
e5848d39
SH
224 */
225 cmd = on_path("iw", NULL);
226 if (!cmd)
227 goto out1;
228 free(cmd);
229
230 fpid = fork();
231 if (fpid < 0)
232 goto out1;
ebc73a67 233
e5848d39
SH
234 if (fpid == 0) {
235 char pidstr[30];
236 sprintf(pidstr, "%d", pid);
ebc73a67
CB
237 execlp("iw", "iw", "phy", physname, "set", "netns", pidstr,
238 (char *)NULL);
239 exit(EXIT_FAILURE);
e5848d39 240 }
ebc73a67 241
e5848d39
SH
242 if (wait_for_pid(fpid))
243 goto out1;
244
245 err = 0;
246 if (newname)
247 err = lxc_netdev_rename_by_name_in_netns(pid, ifname, newname);
248
249out1:
250 free(physname);
251 return err;
252}
253
8d357196 254int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
8befa924
SH
255{
256 int index;
e5848d39 257 char *physname;
8befa924 258
8befa924
SH
259 if (!ifname)
260 return -EINVAL;
261
32571606 262 index = if_nametoindex(ifname);
49428bf3
DY
263 if (!index)
264 return -EINVAL;
32571606 265
ebc73a67
CB
266 physname = is_wlan(ifname);
267 if (physname)
e5848d39
SH
268 return lxc_netdev_move_wlan(physname, ifname, pid, newname);
269
8d357196 270 return lxc_netdev_move_by_index(index, pid, newname);
8befa924
SH
271}
272
b84f58b9 273int lxc_netdev_delete_by_index(int ifindex)
0ad19a3f 274{
b84f58b9 275 int err;
ebc73a67
CB
276 struct ifinfomsg *ifi;
277 struct nl_handler nlh;
278 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 279
3cfc0f3a
MN
280 err = netlink_open(&nlh, NETLINK_ROUTE);
281 if (err)
282 return err;
0ad19a3f 283
3cfc0f3a 284 err = -ENOMEM;
0ad19a3f 285 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
286 if (!nlmsg)
287 goto out;
288
06f976ca 289 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 290 if (!answer)
291 goto out;
292
ebc73a67 293 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
06f976ca
SZ
294 nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
295
296 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
297 if (!ifi)
298 goto out;
06f976ca
SZ
299 ifi->ifi_family = AF_UNSPEC;
300 ifi->ifi_index = ifindex;
0ad19a3f 301
3cfc0f3a 302 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 303out:
304 netlink_close(&nlh);
305 nlmsg_free(answer);
306 nlmsg_free(nlmsg);
307 return err;
308}
309
b84f58b9
DL
310int lxc_netdev_delete_by_name(const char *name)
311{
312 int index;
313
314 index = if_nametoindex(name);
315 if (!index)
316 return -EINVAL;
317
318 return lxc_netdev_delete_by_index(index);
319}
320
321int lxc_netdev_rename_by_index(int ifindex, const char *newname)
b9a5bb58 322{
ebc73a67 323 int err, len;
06f976ca 324 struct ifinfomsg *ifi;
ebc73a67
CB
325 struct nl_handler nlh;
326 struct nlmsg *answer = NULL, *nlmsg = NULL;
b9a5bb58 327
3cfc0f3a
MN
328 err = netlink_open(&nlh, NETLINK_ROUTE);
329 if (err)
330 return err;
b9a5bb58 331
b84f58b9 332 len = strlen(newname);
dae3fdf6 333 if (len == 1 || len >= IFNAMSIZ)
b84f58b9
DL
334 goto out;
335
3cfc0f3a 336 err = -ENOMEM;
b9a5bb58
DL
337 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
338 if (!nlmsg)
339 goto out;
340
06f976ca 341 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
b9a5bb58
DL
342 if (!answer)
343 goto out;
344
ebc73a67 345 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
06f976ca
SZ
346 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
347
348 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
349 if (!ifi)
350 goto out;
06f976ca
SZ
351 ifi->ifi_family = AF_UNSPEC;
352 ifi->ifi_index = ifindex;
b84f58b9
DL
353
354 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
355 goto out;
b9a5bb58 356
3cfc0f3a 357 err = netlink_transaction(&nlh, nlmsg, answer);
b9a5bb58
DL
358out:
359 netlink_close(&nlh);
360 nlmsg_free(answer);
361 nlmsg_free(nlmsg);
362 return err;
363}
364
b84f58b9
DL
365int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
366{
367 int len, index;
368
369 len = strlen(oldname);
dae3fdf6 370 if (len == 1 || len >= IFNAMSIZ)
b84f58b9
DL
371 return -EINVAL;
372
373 index = if_nametoindex(oldname);
374 if (!index)
375 return -EINVAL;
376
377 return lxc_netdev_rename_by_index(index, newname);
378}
379
8befa924 380int netdev_set_flag(const char *name, int flag)
0ad19a3f 381{
ebc73a67 382 int err, index, len;
06f976ca 383 struct ifinfomsg *ifi;
ebc73a67
CB
384 struct nl_handler nlh;
385 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 386
3cfc0f3a
MN
387 err = netlink_open(&nlh, NETLINK_ROUTE);
388 if (err)
389 return err;
0ad19a3f 390
3cfc0f3a 391 err = -EINVAL;
0ad19a3f 392 len = strlen(name);
dae3fdf6 393 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 394 goto out;
395
3cfc0f3a 396 err = -ENOMEM;
0ad19a3f 397 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
398 if (!nlmsg)
399 goto out;
400
06f976ca 401 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 402 if (!answer)
403 goto out;
404
3cfc0f3a 405 err = -EINVAL;
0ad19a3f 406 index = if_nametoindex(name);
407 if (!index)
408 goto out;
409
ebc73a67 410 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
411 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
412
413 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
414 if (!ifi) {
415 err = -ENOMEM;
416 goto out;
417 }
06f976ca
SZ
418 ifi->ifi_family = AF_UNSPEC;
419 ifi->ifi_index = index;
420 ifi->ifi_change |= IFF_UP;
421 ifi->ifi_flags |= flag;
0ad19a3f 422
423 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 424out:
425 netlink_close(&nlh);
426 nlmsg_free(nlmsg);
427 nlmsg_free(answer);
428 return err;
429}
430
ebc73a67 431int netdev_get_flag(const char *name, int *flag)
efa1cf45 432{
ebc73a67 433 int err, index, len;
a4318300 434 struct ifinfomsg *ifi;
ebc73a67
CB
435 struct nl_handler nlh;
436 struct nlmsg *answer = NULL, *nlmsg = NULL;
efa1cf45
DY
437
438 if (!name)
439 return -EINVAL;
440
441 err = netlink_open(&nlh, NETLINK_ROUTE);
442 if (err)
443 return err;
444
445 err = -EINVAL;
446 len = strlen(name);
447 if (len == 1 || len >= IFNAMSIZ)
448 goto out;
449
450 err = -ENOMEM;
451 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
452 if (!nlmsg)
453 goto out;
454
06f976ca 455 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
efa1cf45
DY
456 if (!answer)
457 goto out;
458
459 err = -EINVAL;
460 index = if_nametoindex(name);
461 if (!index)
462 goto out;
463
06f976ca
SZ
464 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
465 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
466
467 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
468 if (!ifi) {
469 err = -ENOMEM;
470 goto out;
471 }
06f976ca
SZ
472 ifi->ifi_family = AF_UNSPEC;
473 ifi->ifi_index = index;
efa1cf45
DY
474
475 err = netlink_transaction(&nlh, nlmsg, answer);
476 if (err)
477 goto out;
478
06f976ca 479 ifi = NLMSG_DATA(answer->nlmsghdr);
efa1cf45
DY
480
481 *flag = ifi->ifi_flags;
482out:
483 netlink_close(&nlh);
484 nlmsg_free(nlmsg);
485 nlmsg_free(answer);
486 return err;
487}
488
489/*
490 * \brief Check a interface is up or not.
491 *
492 * \param name: name for the interface.
493 *
494 * \return int.
495 * 0 means interface is down.
496 * 1 means interface is up.
497 * Others means error happened, and ret-value is the error number.
498 */
ebc73a67 499int lxc_netdev_isup(const char *name)
efa1cf45 500{
ebc73a67 501 int err, flag;
efa1cf45
DY
502
503 err = netdev_get_flag(name, &flag);
504 if (err)
ebc73a67
CB
505 return err;
506
efa1cf45
DY
507 if (flag & IFF_UP)
508 return 1;
ebc73a67 509
efa1cf45 510 return 0;
efa1cf45
DY
511}
512
0130df54
SH
513int netdev_get_mtu(int ifindex)
514{
ebc73a67 515 int answer_len, err, res;
0130df54 516 struct nl_handler nlh;
06f976ca 517 struct ifinfomsg *ifi;
0130df54 518 struct nlmsghdr *msg;
ebc73a67
CB
519 int readmore = 0, recv_len = 0;
520 struct nlmsg *answer = NULL, *nlmsg = NULL;
0130df54
SH
521
522 err = netlink_open(&nlh, NETLINK_ROUTE);
523 if (err)
524 return err;
525
526 err = -ENOMEM;
527 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
528 if (!nlmsg)
529 goto out;
530
06f976ca 531 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0130df54
SH
532 if (!answer)
533 goto out;
534
535 /* Save the answer buffer length, since it will be overwritten
536 * on the first receive (and we might need to receive more than
ebc73a67
CB
537 * once.
538 */
06f976ca
SZ
539 answer_len = answer->nlmsghdr->nlmsg_len;
540
ebc73a67 541 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
06f976ca 542 nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
0130df54 543
06f976ca 544 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
545 if (!ifi)
546 goto out;
06f976ca 547 ifi->ifi_family = AF_UNSPEC;
0130df54
SH
548
549 /* Send the request for addresses, which returns all addresses
550 * on all interfaces. */
551 err = netlink_send(&nlh, nlmsg);
552 if (err < 0)
553 goto out;
554
555 do {
556 /* Restore the answer buffer length, it might have been
ebc73a67
CB
557 * overwritten by a previous receive.
558 */
06f976ca 559 answer->nlmsghdr->nlmsg_len = answer_len;
0130df54
SH
560
561 /* Get the (next) batch of reply messages */
562 err = netlink_rcv(&nlh, answer);
563 if (err < 0)
564 goto out;
565
566 recv_len = err;
567 err = 0;
568
569 /* Satisfy the typing for the netlink macros */
06f976ca 570 msg = answer->nlmsghdr;
0130df54
SH
571
572 while (NLMSG_OK(msg, recv_len)) {
573
574 /* Stop reading if we see an error message */
575 if (msg->nlmsg_type == NLMSG_ERROR) {
ebc73a67
CB
576 struct nlmsgerr *errmsg =
577 (struct nlmsgerr *)NLMSG_DATA(msg);
0130df54
SH
578 err = errmsg->error;
579 goto out;
580 }
581
582 /* Stop reading if we see a NLMSG_DONE message */
583 if (msg->nlmsg_type == NLMSG_DONE) {
584 readmore = 0;
585 break;
586 }
587
06f976ca 588 ifi = NLMSG_DATA(msg);
0130df54
SH
589 if (ifi->ifi_index == ifindex) {
590 struct rtattr *rta = IFLA_RTA(ifi);
ebc73a67
CB
591 int attr_len =
592 msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
0130df54 593 res = 0;
ebc73a67
CB
594 while (RTA_OK(rta, attr_len)) {
595 /* Found a local address for the
596 * requested interface, return it.
597 */
0130df54 598 if (rta->rta_type == IFLA_MTU) {
ebc73a67
CB
599 memcpy(&res, RTA_DATA(rta),
600 sizeof(int));
0130df54
SH
601 err = res;
602 goto out;
603 }
604 rta = RTA_NEXT(rta, attr_len);
605 }
0130df54
SH
606 }
607
ebc73a67
CB
608 /* Keep reading more data from the socket if the last
609 * message had the NLF_F_MULTI flag set.
610 */
0130df54
SH
611 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
612
ebc73a67 613 /* Look at the next message received in this buffer. */
0130df54
SH
614 msg = NLMSG_NEXT(msg, recv_len);
615 }
616 } while (readmore);
617
ebc73a67 618 /* If we end up here, we didn't find any result, so signal an error. */
0130df54
SH
619 err = -1;
620
621out:
622 netlink_close(&nlh);
623 nlmsg_free(answer);
624 nlmsg_free(nlmsg);
625 return err;
626}
627
d472214b 628int lxc_netdev_set_mtu(const char *name, int mtu)
75d09f83 629{
ebc73a67 630 int err, index, len;
06f976ca 631 struct ifinfomsg *ifi;
ebc73a67
CB
632 struct nl_handler nlh;
633 struct nlmsg *answer = NULL, *nlmsg = NULL;
75d09f83 634
3cfc0f3a
MN
635 err = netlink_open(&nlh, NETLINK_ROUTE);
636 if (err)
637 return err;
75d09f83 638
3cfc0f3a 639 err = -EINVAL;
75d09f83 640 len = strlen(name);
dae3fdf6 641 if (len == 1 || len >= IFNAMSIZ)
75d09f83
DL
642 goto out;
643
3cfc0f3a 644 err = -ENOMEM;
75d09f83
DL
645 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
646 if (!nlmsg)
647 goto out;
648
06f976ca 649 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
75d09f83
DL
650 if (!answer)
651 goto out;
652
3cfc0f3a 653 err = -EINVAL;
75d09f83
DL
654 index = if_nametoindex(name);
655 if (!index)
656 goto out;
657
ebc73a67 658 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
06f976ca
SZ
659 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
660
661 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
662 if (!ifi) {
663 err = -ENOMEM;
664 goto out;
665 }
06f976ca
SZ
666 ifi->ifi_family = AF_UNSPEC;
667 ifi->ifi_index = index;
75d09f83
DL
668
669 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
670 goto out;
671
672 err = netlink_transaction(&nlh, nlmsg, answer);
75d09f83
DL
673out:
674 netlink_close(&nlh);
675 nlmsg_free(nlmsg);
676 nlmsg_free(answer);
677 return err;
678}
679
d472214b 680int lxc_netdev_up(const char *name)
0ad19a3f 681{
d472214b 682 return netdev_set_flag(name, IFF_UP);
0ad19a3f 683}
684
d472214b 685int lxc_netdev_down(const char *name)
0ad19a3f 686{
d472214b 687 return netdev_set_flag(name, 0);
0ad19a3f 688}
689
497353b6 690int lxc_veth_create(const char *name1, const char *name2)
0ad19a3f 691{
ebc73a67 692 int err, len;
06f976ca 693 struct ifinfomsg *ifi;
ebc73a67 694 struct nl_handler nlh;
0ad19a3f 695 struct rtattr *nest1, *nest2, *nest3;
ebc73a67 696 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 697
3cfc0f3a
MN
698 err = netlink_open(&nlh, NETLINK_ROUTE);
699 if (err)
700 return err;
0ad19a3f 701
3cfc0f3a 702 err = -EINVAL;
0ad19a3f 703 len = strlen(name1);
dae3fdf6 704 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 705 goto out;
706
707 len = strlen(name2);
dae3fdf6 708 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 709 goto out;
710
3cfc0f3a 711 err = -ENOMEM;
0ad19a3f 712 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
713 if (!nlmsg)
714 goto out;
715
06f976ca 716 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 717 if (!answer)
718 goto out;
719
06f976ca 720 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 721 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
722 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
723
724 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
725 if (!ifi)
726 goto out;
06f976ca 727 ifi->ifi_family = AF_UNSPEC;
0ad19a3f 728
3cfc0f3a 729 err = -EINVAL;
79e68309 730 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 731 if (!nest1)
732 goto out;
733
734 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
735 goto out;
736
737 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
738 if (!nest2)
739 goto out;
740
741 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
742 if (!nest3)
743 goto out;
744
06f976ca 745 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
746 if (!ifi) {
747 err = -ENOMEM;
06f976ca 748 goto out;
25a9939b 749 }
0ad19a3f 750
751 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
752 goto out;
753
754 nla_end_nested(nlmsg, nest3);
0ad19a3f 755 nla_end_nested(nlmsg, nest2);
0ad19a3f 756 nla_end_nested(nlmsg, nest1);
757
758 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
759 goto out;
760
3cfc0f3a 761 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 762out:
763 netlink_close(&nlh);
764 nlmsg_free(answer);
765 nlmsg_free(nlmsg);
766 return err;
767}
768
ebc73a67 769/* TODO: merge with lxc_macvlan_create */
7c11d57a 770int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
26c39028 771{
ebc73a67 772 int err, len, lindex;
06f976ca 773 struct ifinfomsg *ifi;
ebc73a67 774 struct nl_handler nlh;
26c39028 775 struct rtattr *nest, *nest2;
ebc73a67 776 struct nlmsg *answer = NULL, *nlmsg = NULL;
26c39028 777
3cfc0f3a
MN
778 err = netlink_open(&nlh, NETLINK_ROUTE);
779 if (err)
780 return err;
26c39028 781
3cfc0f3a 782 err = -EINVAL;
26c39028 783 len = strlen(master);
dae3fdf6 784 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
785 goto err3;
786
787 len = strlen(name);
dae3fdf6 788 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
789 goto err3;
790
3cfc0f3a 791 err = -ENOMEM;
26c39028
JHS
792 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
793 if (!nlmsg)
794 goto err3;
795
06f976ca 796 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
26c39028
JHS
797 if (!answer)
798 goto err2;
799
3cfc0f3a 800 err = -EINVAL;
26c39028
JHS
801 lindex = if_nametoindex(master);
802 if (!lindex)
803 goto err1;
804
06f976ca 805 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 806 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
807 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
808
809 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
810 if (!ifi) {
811 err = -ENOMEM;
812 goto err1;
813 }
06f976ca 814 ifi->ifi_family = AF_UNSPEC;
26c39028 815
79e68309 816 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
26c39028
JHS
817 if (!nest)
818 goto err1;
819
820 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
821 goto err1;
822
823 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
824 if (!nest2)
825 goto err1;
e892973e 826
26c39028
JHS
827 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
828 goto err1;
e892973e 829
26c39028 830 nla_end_nested(nlmsg, nest2);
26c39028
JHS
831 nla_end_nested(nlmsg, nest);
832
833 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
834 goto err1;
835
836 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
837 goto err1;
838
3cfc0f3a 839 err = netlink_transaction(&nlh, nlmsg, answer);
26c39028
JHS
840err1:
841 nlmsg_free(answer);
842err2:
843 nlmsg_free(nlmsg);
844err3:
845 netlink_close(&nlh);
846 return err;
847}
848
e892973e 849int lxc_macvlan_create(const char *master, const char *name, int mode)
0ad19a3f 850{
ebc73a67 851 int err, index, len;
06f976ca 852 struct ifinfomsg *ifi;
ebc73a67 853 struct nl_handler nlh;
e892973e 854 struct rtattr *nest, *nest2;
ebc73a67 855 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 856
3cfc0f3a
MN
857 err = netlink_open(&nlh, NETLINK_ROUTE);
858 if (err)
859 return err;
0ad19a3f 860
3cfc0f3a 861 err = -EINVAL;
0ad19a3f 862 len = strlen(master);
dae3fdf6 863 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 864 goto out;
865
866 len = strlen(name);
dae3fdf6 867 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 868 goto out;
869
3cfc0f3a 870 err = -ENOMEM;
0ad19a3f 871 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
872 if (!nlmsg)
873 goto out;
874
06f976ca 875 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 876 if (!answer)
877 goto out;
878
3cfc0f3a 879 err = -EINVAL;
0ad19a3f 880 index = if_nametoindex(master);
881 if (!index)
882 goto out;
883
06f976ca 884 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 885 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
06f976ca
SZ
886 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
887
888 ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
25a9939b
WC
889 if (!ifi) {
890 err = -ENOMEM;
891 goto out;
892 }
06f976ca 893 ifi->ifi_family = AF_UNSPEC;
0ad19a3f 894
79e68309 895 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 896 if (!nest)
897 goto out;
898
899 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
900 goto out;
901
e892973e
DL
902 if (mode) {
903 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
904 if (!nest2)
905 goto out;
906
907 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
908 goto out;
909
910 nla_end_nested(nlmsg, nest2);
911 }
912
0ad19a3f 913 nla_end_nested(nlmsg, nest);
914
915 if (nla_put_u32(nlmsg, IFLA_LINK, index))
916 goto out;
917
918 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
919 goto out;
920
3cfc0f3a 921 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 922out:
923 netlink_close(&nlh);
924 nlmsg_free(answer);
925 nlmsg_free(nlmsg);
926 return err;
927}
928
929static int proc_sys_net_write(const char *path, const char *value)
930{
ebc73a67
CB
931 int fd;
932 int err = 0;
0ad19a3f 933
934 fd = open(path, O_WRONLY);
935 if (fd < 0)
936 return -errno;
937
938 if (write(fd, value, strlen(value)) < 0)
939 err = -errno;
940
941 close(fd);
942 return err;
943}
944
945static int ip_forward_set(const char *ifname, int family, int flag)
946{
9ba8130c 947 int rc;
ebc73a67 948 char path[MAXPATHLEN];
0ad19a3f 949
950 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 951 return -EINVAL;
0ad19a3f 952
9ba8130c 953 rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
ebc73a67
CB
954 family == AF_INET ? "ipv4" : "ipv6", ifname);
955 if (rc < 0 || (size_t)rc >= MAXPATHLEN)
9ba8130c 956 return -E2BIG;
0ad19a3f 957
ebc73a67 958 return proc_sys_net_write(path, flag ? "1" : "0");
0ad19a3f 959}
960
497353b6 961int lxc_ip_forward_on(const char *ifname, int family)
0ad19a3f 962{
963 return ip_forward_set(ifname, family, 1);
964}
965
497353b6 966int lxc_ip_forward_off(const char *ifname, int family)
0ad19a3f 967{
968 return ip_forward_set(ifname, family, 0);
969}
970
971static int neigh_proxy_set(const char *ifname, int family, int flag)
972{
9ba8130c 973 int ret;
ebc73a67 974 char path[MAXPATHLEN];
0ad19a3f 975
976 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 977 return -EINVAL;
0ad19a3f 978
9ba8130c 979 ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
ebc73a67
CB
980 family == AF_INET ? "ipv4" : "ipv6", ifname,
981 family == AF_INET ? "proxy_arp" : "proxy_ndp");
982 if (ret < 0 || (size_t)ret >= MAXPATHLEN)
9ba8130c 983 return -E2BIG;
0ad19a3f 984
ebc73a67 985 return proc_sys_net_write(path, flag ? "1" : "0");
0ad19a3f 986}
987
497353b6 988int lxc_neigh_proxy_on(const char *name, int family)
0ad19a3f 989{
990 return neigh_proxy_set(name, family, 1);
991}
992
497353b6 993int lxc_neigh_proxy_off(const char *name, int family)
0ad19a3f 994{
995 return neigh_proxy_set(name, family, 0);
996}
997
998int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
999{
1f1b18e7
DL
1000 int i = 0;
1001 unsigned val;
ebc73a67
CB
1002 char c;
1003 unsigned char *data;
1f1b18e7
DL
1004
1005 sockaddr->sa_family = ARPHRD_ETHER;
1006 data = (unsigned char *)sockaddr->sa_data;
1007
1008 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
ebc73a67
CB
1009 val = 0;
1010 c = *macaddr++;
1011 if (isdigit(c))
1012 val = c - '0';
1013 else if (c >= 'a' && c <= 'f')
1014 val = c - 'a' + 10;
1015 else if (c >= 'A' && c <= 'F')
1016 val = c - 'A' + 10;
1017 else
1018 return -EINVAL;
1019
1020 val <<= 4;
1021 c = *macaddr;
1022 if (isdigit(c))
1023 val |= c - '0';
1024 else if (c >= 'a' && c <= 'f')
1025 val |= c - 'a' + 10;
1026 else if (c >= 'A' && c <= 'F')
1027 val |= c - 'A' + 10;
1028 else if (c == ':' || c == 0)
1029 val >>= 4;
1030 else
1031 return -EINVAL;
1032 if (c != 0)
1033 macaddr++;
1034 *data++ = (unsigned char)(val & 0377);
1035 i++;
1036
1037 if (*macaddr == ':')
1038 macaddr++;
0ad19a3f 1039 }
0ad19a3f 1040
1f1b18e7 1041 return 0;
0ad19a3f 1042}
1043
ebc73a67
CB
1044static int ip_addr_add(int family, int ifindex, void *addr, void *bcast,
1045 void *acast, int prefix)
0ad19a3f 1046{
ebc73a67 1047 int addrlen, err;
06f976ca 1048 struct ifaddrmsg *ifa;
ebc73a67
CB
1049 struct nl_handler nlh;
1050 struct nlmsg *answer = NULL, *nlmsg = NULL;
0ad19a3f 1051
ebc73a67
CB
1052 addrlen = family == AF_INET ? sizeof(struct in_addr)
1053 : sizeof(struct in6_addr);
4bf1968d 1054
3cfc0f3a
MN
1055 err = netlink_open(&nlh, NETLINK_ROUTE);
1056 if (err)
1057 return err;
0ad19a3f 1058
3cfc0f3a 1059 err = -ENOMEM;
0ad19a3f 1060 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1061 if (!nlmsg)
1062 goto out;
1063
06f976ca 1064 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
0ad19a3f 1065 if (!answer)
1066 goto out;
1067
06f976ca 1068 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1069 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
06f976ca
SZ
1070 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
1071
1072 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
acf47e1b 1073 if (!ifa)
25a9939b 1074 goto out;
06f976ca
SZ
1075 ifa->ifa_prefixlen = prefix;
1076 ifa->ifa_index = ifindex;
1077 ifa->ifa_family = family;
1078 ifa->ifa_scope = 0;
acf47e1b 1079
3cfc0f3a 1080 err = -EINVAL;
4bf1968d 1081 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
0ad19a3f 1082 goto out;
1083
4bf1968d 1084 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
0ad19a3f 1085 goto out;
1086
d8948a52 1087 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
1f1b18e7
DL
1088 goto out;
1089
ebc73a67 1090 /* TODO: multicast, anycast with ipv6 */
7ddc8f24 1091 err = -EPROTONOSUPPORT;
79881dc6
DL
1092 if (family == AF_INET6 &&
1093 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
1094 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
1f1b18e7 1095 goto out;
0ad19a3f 1096
3cfc0f3a 1097 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 1098out:
1099 netlink_close(&nlh);
1100 nlmsg_free(answer);
1101 nlmsg_free(nlmsg);
1102 return err;
1103}
1104
1f1b18e7 1105int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
ebc73a67
CB
1106 struct in6_addr *mcast, struct in6_addr *acast,
1107 int prefix)
1f1b18e7
DL
1108{
1109 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
1110}
1111
ebc73a67
CB
1112int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, struct in_addr *bcast,
1113 int prefix)
1f1b18e7
DL
1114{
1115 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
1116}
1117
ebc73a67
CB
1118/* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present) address from
1119 * the given RTM_NEWADDR message. Allocates memory for the address and stores
1120 * that pointer in *res (so res should be an in_addr** or in6_addr**).
19a26f82 1121 */
ebc73a67
CB
1122static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res)
1123{
1124 int addrlen;
06f976ca
SZ
1125 struct ifaddrmsg *ifa = NLMSG_DATA(msg);
1126 struct rtattr *rta = IFA_RTA(ifa);
1127 int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
19a26f82 1128
06f976ca 1129 if (ifa->ifa_family != family)
19a26f82
MK
1130 return 0;
1131
ebc73a67
CB
1132 addrlen = family == AF_INET ? sizeof(struct in_addr)
1133 : sizeof(struct in6_addr);
19a26f82
MK
1134
1135 /* Loop over the rtattr's in this message */
ebc73a67 1136 while (RTA_OK(rta, attr_len)) {
19a26f82 1137 /* Found a local address for the requested interface,
ebc73a67
CB
1138 * return it.
1139 */
1140 if (rta->rta_type == IFA_LOCAL ||
1141 rta->rta_type == IFA_ADDRESS) {
1142 /* Sanity check. The family check above should make sure
1143 * the address length is correct, but check here just in
1144 * case.
1145 */
19a26f82
MK
1146 if (RTA_PAYLOAD(rta) != addrlen)
1147 return -1;
1148
ebc73a67
CB
1149 /* We might have found an IFA_ADDRESS before, which we
1150 * now overwrite with an IFA_LOCAL.
1151 */
dd66e5ad 1152 if (!*res) {
19a26f82 1153 *res = malloc(addrlen);
dd66e5ad
DE
1154 if (!*res)
1155 return -1;
1156 }
19a26f82
MK
1157
1158 memcpy(*res, RTA_DATA(rta), addrlen);
19a26f82
MK
1159 if (rta->rta_type == IFA_LOCAL)
1160 break;
1161 }
1162 rta = RTA_NEXT(rta, attr_len);
1163 }
1164 return 0;
1165}
1166
1167static int ip_addr_get(int family, int ifindex, void **res)
1168{
ebc73a67 1169 int answer_len, err;
06f976ca 1170 struct ifaddrmsg *ifa;
ebc73a67 1171 struct nl_handler nlh;
19a26f82 1172 struct nlmsghdr *msg;
ebc73a67
CB
1173 int readmore = 0, recv_len = 0;
1174 struct nlmsg *answer = NULL, *nlmsg = NULL;
19a26f82
MK
1175
1176 err = netlink_open(&nlh, NETLINK_ROUTE);
1177 if (err)
1178 return err;
1179
1180 err = -ENOMEM;
1181 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1182 if (!nlmsg)
1183 goto out;
1184
06f976ca 1185 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
19a26f82
MK
1186 if (!answer)
1187 goto out;
1188
ebc73a67
CB
1189 /* Save the answer buffer length, since it will be overwritten on the
1190 * first receive (and we might need to receive more than once).
1191 */
06f976ca
SZ
1192 answer_len = answer->nlmsghdr->nlmsg_len;
1193
ebc73a67 1194 nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
06f976ca 1195 nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
19a26f82 1196
06f976ca 1197 ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
25a9939b
WC
1198 if (!ifa)
1199 goto out;
06f976ca 1200 ifa->ifa_family = family;
19a26f82 1201
ebc73a67
CB
1202 /* Send the request for addresses, which returns all addresses on all
1203 * interfaces.
1204 */
19a26f82
MK
1205 err = netlink_send(&nlh, nlmsg);
1206 if (err < 0)
1207 goto out;
19a26f82
MK
1208
1209 do {
1210 /* Restore the answer buffer length, it might have been
ebc73a67
CB
1211 * overwritten by a previous receive.
1212 */
06f976ca 1213 answer->nlmsghdr->nlmsg_len = answer_len;
19a26f82 1214
ebc73a67 1215 /* Get the (next) batch of reply messages. */
19a26f82
MK
1216 err = netlink_rcv(&nlh, answer);
1217 if (err < 0)
1218 goto out;
1219
1220 recv_len = err;
1221 err = 0;
1222
ebc73a67 1223 /* Satisfy the typing for the netlink macros. */
06f976ca 1224 msg = answer->nlmsghdr;
19a26f82
MK
1225
1226 while (NLMSG_OK(msg, recv_len)) {
ebc73a67 1227 /* Stop reading if we see an error message. */
19a26f82 1228 if (msg->nlmsg_type == NLMSG_ERROR) {
ebc73a67
CB
1229 struct nlmsgerr *errmsg =
1230 (struct nlmsgerr *)NLMSG_DATA(msg);
19a26f82
MK
1231 err = errmsg->error;
1232 goto out;
1233 }
1234
ebc73a67 1235 /* Stop reading if we see a NLMSG_DONE message. */
19a26f82
MK
1236 if (msg->nlmsg_type == NLMSG_DONE) {
1237 readmore = 0;
1238 break;
1239 }
1240
1241 if (msg->nlmsg_type != RTM_NEWADDR) {
1242 err = -1;
1243 goto out;
1244 }
1245
06f976ca
SZ
1246 ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
1247 if (ifa->ifa_index == ifindex) {
1248 if (ifa_get_local_ip(family, msg, res) < 0) {
51e7a874
SG
1249 err = -1;
1250 goto out;
1251 }
1252
ebc73a67 1253 /* Found a result, stop searching. */
19a26f82
MK
1254 if (*res)
1255 goto out;
1256 }
1257
ebc73a67
CB
1258 /* Keep reading more data from the socket if the last
1259 * message had the NLF_F_MULTI flag set.
1260 */
19a26f82
MK
1261 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1262
ebc73a67 1263 /* Look at the next message received in this buffer. */
19a26f82
MK
1264 msg = NLMSG_NEXT(msg, recv_len);
1265 }
1266 } while (readmore);
1267
1268 /* If we end up here, we didn't find any result, so signal an
ebc73a67
CB
1269 * error.
1270 */
19a26f82
MK
1271 err = -1;
1272
1273out:
1274 netlink_close(&nlh);
1275 nlmsg_free(answer);
1276 nlmsg_free(nlmsg);
1277 return err;
1278}
1279
1280int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
1281{
ebc73a67 1282 return ip_addr_get(AF_INET6, ifindex, (void **)res);
19a26f82
MK
1283}
1284
ebc73a67 1285int lxc_ipv4_addr_get(int ifindex, struct in_addr **res)
19a26f82 1286{
ebc73a67 1287 return ip_addr_get(AF_INET, ifindex, (void **)res);
19a26f82
MK
1288}
1289
f8fee0e2
MK
1290static int ip_gateway_add(int family, int ifindex, void *gw)
1291{
ebc73a67 1292 int addrlen, err;
f8fee0e2 1293 struct nl_handler nlh;
06f976ca 1294 struct rtmsg *rt;
ebc73a67 1295 struct nlmsg *answer = NULL, *nlmsg = NULL;
f8fee0e2 1296
ebc73a67
CB
1297 addrlen = family == AF_INET ? sizeof(struct in_addr)
1298 : sizeof(struct in6_addr);
f8fee0e2
MK
1299
1300 err = netlink_open(&nlh, NETLINK_ROUTE);
1301 if (err)
1302 return err;
1303
1304 err = -ENOMEM;
1305 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1306 if (!nlmsg)
1307 goto out;
1308
06f976ca 1309 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
f8fee0e2
MK
1310 if (!answer)
1311 goto out;
1312
06f976ca 1313 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1314 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
06f976ca
SZ
1315 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1316
1317 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
25a9939b
WC
1318 if (!rt)
1319 goto out;
06f976ca
SZ
1320 rt->rtm_family = family;
1321 rt->rtm_table = RT_TABLE_MAIN;
1322 rt->rtm_scope = RT_SCOPE_UNIVERSE;
1323 rt->rtm_protocol = RTPROT_BOOT;
1324 rt->rtm_type = RTN_UNICAST;
f8fee0e2 1325 /* "default" destination */
06f976ca 1326 rt->rtm_dst_len = 0;
f8fee0e2
MK
1327
1328 err = -EINVAL;
1329 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
1330 goto out;
1331
1332 /* Adding the interface index enables the use of link-local
ebc73a67
CB
1333 * addresses for the gateway.
1334 */
f8fee0e2
MK
1335 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1336 goto out;
1337
1338 err = netlink_transaction(&nlh, nlmsg, answer);
1339out:
1340 netlink_close(&nlh);
1341 nlmsg_free(answer);
1342 nlmsg_free(nlmsg);
1343 return err;
1344}
1345
1346int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
1347{
1348 return ip_gateway_add(AF_INET, ifindex, gw);
1349}
1350
1351int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
1352{
1353 return ip_gateway_add(AF_INET6, ifindex, gw);
1354}
1355
77dcf03a
GL
1356static int ip_route_dest_add(int family, int ifindex, void *dest)
1357{
ebc73a67 1358 int addrlen, err;
77dcf03a 1359 struct nl_handler nlh;
06f976ca 1360 struct rtmsg *rt;
ebc73a67 1361 struct nlmsg *answer = NULL, *nlmsg = NULL;
acf47e1b 1362
ebc73a67
CB
1363 addrlen = family == AF_INET ? sizeof(struct in_addr)
1364 : sizeof(struct in6_addr);
acf47e1b 1365
77dcf03a
GL
1366 err = netlink_open(&nlh, NETLINK_ROUTE);
1367 if (err)
1368 return err;
acf47e1b 1369
77dcf03a
GL
1370 err = -ENOMEM;
1371 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1372 if (!nlmsg)
1373 goto out;
acf47e1b 1374
06f976ca 1375 answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
77dcf03a
GL
1376 if (!answer)
1377 goto out;
acf47e1b 1378
06f976ca 1379 nlmsg->nlmsghdr->nlmsg_flags =
ebc73a67 1380 NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
06f976ca
SZ
1381 nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
1382
1383 rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
25a9939b
WC
1384 if (!rt)
1385 goto out;
06f976ca
SZ
1386 rt->rtm_family = family;
1387 rt->rtm_table = RT_TABLE_MAIN;
1388 rt->rtm_scope = RT_SCOPE_LINK;
1389 rt->rtm_protocol = RTPROT_BOOT;
1390 rt->rtm_type = RTN_UNICAST;
ebc73a67 1391 rt->rtm_dst_len = addrlen * 8;
acf47e1b 1392
77dcf03a
GL
1393 err = -EINVAL;
1394 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
1395 goto out;
1396 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1397 goto out;
1398 err = netlink_transaction(&nlh, nlmsg, answer);
1399out:
1400 netlink_close(&nlh);
1401 nlmsg_free(answer);
1402 nlmsg_free(nlmsg);
1403 return err;
1404}
1405
1406int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
1407{
1408 return ip_route_dest_add(AF_INET, ifindex, dest);
1409}
1410
1411int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
1412{
1413 return ip_route_dest_add(AF_INET6, ifindex, dest);
1414}
1415
0d204771
SH
1416static bool is_ovs_bridge(const char *bridge)
1417{
ebc73a67 1418 int ret;
0d204771 1419 struct stat sb;
ebc73a67 1420 char brdirname[22 + IFNAMSIZ + 1] = {0};
0d204771 1421
ebc73a67
CB
1422 ret = snprintf(brdirname, 22 + IFNAMSIZ + 1, "/sys/class/net/%s/bridge",
1423 bridge);
1424 if (ret < 0 || (size_t)ret >= 22 + IFNAMSIZ + 1)
1425 return false;
1426
1427 ret = stat(brdirname, &sb);
1428 if (ret < 0 && errno == ENOENT)
0d204771 1429 return true;
ebc73a67 1430
0d204771
SH
1431 return false;
1432}
1433
cb0dc11b
CB
1434/* Called from a background thread - when nic goes away, remove it from the
1435 * bridge.
c43cbc04 1436 */
cb0dc11b
CB
1437static void ovs_cleanup_nic(const char *lxcpath, const char *name,
1438 const char *bridge, const char *nic)
c43cbc04 1439{
cb0dc11b
CB
1440 int ret;
1441
1442 ret = lxc_check_inherited(NULL, true, &(int){-1}, 1);
1443 if (ret < 0)
c43cbc04 1444 return;
cb0dc11b
CB
1445
1446 TRACE("Registering cleanup thread to remove nic \"%s\" from "
1447 "openvswitch bridge \"%s\"", nic, bridge);
1448
1449 ret = lxc_wait(name, "STOPPED", -1, lxcpath);
1450 if (ret < 0) {
1451 ERROR("Failed to register cleanup thread to remove nic \"%s\" "
1452 "from openvswitch bridge \"%s\"", nic, bridge);
c43cbc04 1453 return;
cb0dc11b
CB
1454 }
1455
acf47e1b 1456 execlp("ovs-vsctl", "ovs-vsctl", "del-port", bridge, nic, (char *)NULL);
cb0dc11b 1457 exit(EXIT_FAILURE);
c43cbc04
SH
1458}
1459
ebc73a67
CB
1460static int attach_to_ovs_bridge(const char *lxcpath, const char *name,
1461 const char *bridge, const char *nic)
0d204771
SH
1462{
1463 pid_t pid;
6ad22d06 1464 char *cmd;
c43cbc04 1465 int ret;
6ad22d06
SH
1466
1467 cmd = on_path("ovs-vsctl", NULL);
1468 if (!cmd)
1469 return -1;
1470 free(cmd);
0d204771
SH
1471
1472 pid = fork();
1473 if (pid < 0)
1474 return -1;
ebc73a67 1475
c43cbc04
SH
1476 if (pid > 0) {
1477 ret = wait_for_pid(pid);
1478 if (ret < 0)
1479 return ret;
ebc73a67 1480
c43cbc04
SH
1481 pid = fork();
1482 if (pid < 0)
ebc73a67
CB
1483 return -1;
1484
c43cbc04
SH
1485 if (pid > 0)
1486 return 0;
ebc73a67 1487
c43cbc04 1488 ovs_cleanup_nic(lxcpath, name, bridge, nic);
ebc73a67 1489 exit(EXIT_SUCCESS);
c43cbc04 1490 }
0d204771 1491
ebc73a67
CB
1492 execlp("ovs-vsctl", "ovs-vsctl", "add-port", bridge, nic, (char *)NULL);
1493 exit(EXIT_FAILURE);
0d204771 1494}
0d204771 1495
1a0e70ac
CB
1496/* There is a lxc_bridge_attach, but no need of a bridge detach as automatically
1497 * done by kernel when a netdev is deleted.
7d163508 1498 */
ebc73a67
CB
1499int lxc_bridge_attach(const char *lxcpath, const char *name, const char *bridge,
1500 const char *ifname)
0ad19a3f 1501{
ebc73a67 1502 int err, fd, index;
0ad19a3f 1503 struct ifreq ifr;
1504
dae3fdf6 1505 if (strlen(ifname) >= IFNAMSIZ)
3cfc0f3a 1506 return -EINVAL;
0ad19a3f 1507
1508 index = if_nametoindex(ifname);
1509 if (!index)
3cfc0f3a 1510 return -EINVAL;
0ad19a3f 1511
0d204771 1512 if (is_ovs_bridge(bridge))
c43cbc04 1513 return attach_to_ovs_bridge(lxcpath, name, bridge, ifname);
0d204771 1514
0ad19a3f 1515 fd = socket(AF_INET, SOCK_STREAM, 0);
1516 if (fd < 0)
3cfc0f3a 1517 return -errno;
0ad19a3f 1518
ebc73a67
CB
1519 strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1520 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
0ad19a3f 1521 ifr.ifr_ifindex = index;
7d163508 1522 err = ioctl(fd, SIOCBRADDIF, &ifr);
0ad19a3f 1523 close(fd);
3cfc0f3a
MN
1524 if (err)
1525 err = -errno;
0ad19a3f 1526
1527 return err;
1528}
72d0e1cb 1529
ebc73a67 1530static const char *const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
b343592b 1531 [LXC_NET_EMPTY] = "empty",
72d0e1cb
SG
1532 [LXC_NET_VETH] = "veth",
1533 [LXC_NET_MACVLAN] = "macvlan",
72d0e1cb 1534 [LXC_NET_PHYS] = "phys",
b343592b
BP
1535 [LXC_NET_VLAN] = "vlan",
1536 [LXC_NET_NONE] = "none",
72d0e1cb
SG
1537};
1538
1539const char *lxc_net_type_to_str(int type)
1540{
1541 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
1542 return NULL;
ebc73a67 1543
72d0e1cb
SG
1544 return lxc_network_types[type];
1545}
8befa924 1546
ebc73a67 1547static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
a0265685
SG
1548
1549char *lxc_mkifname(char *template)
1550{
ebc73a67 1551 int ifexists = 0;
84760c11 1552 size_t i = 0;
ebc73a67 1553 char *name = NULL;
a0265685 1554 unsigned int seed;
ebc73a67
CB
1555 FILE *urandom;
1556 struct ifaddrs *ifa, *ifaddr;
a0265685 1557
ebc73a67 1558 /* Get all the network interfaces. */
a0265685
SG
1559 getifaddrs(&ifaddr);
1560
ebc73a67
CB
1561 /* Initialize the random number generator. */
1562 urandom = fopen("/dev/urandom", "r");
a0265685 1563 if (urandom != NULL) {
ebc73a67 1564 if (fread(&seed, sizeof(seed), 1, urandom) <= 0)
a0265685 1565 seed = time(0);
a0265685 1566 fclose(urandom);
ebc73a67 1567 } else {
a0265685 1568 seed = time(0);
ebc73a67 1569 }
a0265685
SG
1570
1571#ifndef HAVE_RAND_R
1572 srand(seed);
1573#endif
1574
ebc73a67
CB
1575 /* Generate random names until we find one that doesn't exist. */
1576 while (true) {
a0265685
SG
1577 ifexists = 0;
1578 name = strdup(template);
1579
1580 if (name == NULL)
1581 return NULL;
1582
1583 for (i = 0; i < strlen(name); i++) {
1584 if (name[i] == 'X') {
1585#ifdef HAVE_RAND_R
ebc73a67
CB
1586 name[i] = padchar[rand_r(&seed) %
1587 (strlen(padchar) - 1)];
a0265685
SG
1588#else
1589 name[i] = padchar[rand() % (strlen(padchar) - 1)];
1590#endif
1591 }
1592 }
1593
1594 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1595 if (strcmp(ifa->ifa_name, name) == 0) {
1596 ifexists = 1;
1597 break;
1598 }
1599 }
1600
1601 if (ifexists == 0)
1602 break;
1603
1604 free(name);
1605 }
1606
1607 freeifaddrs(ifaddr);
1608 return name;
1609}
1610
8befa924
SH
1611int setup_private_host_hw_addr(char *veth1)
1612{
ebc73a67 1613 int err, sockfd;
8befa924 1614 struct ifreq ifr;
8befa924 1615
8befa924 1616 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
8befa924
SH
1617 if (sockfd < 0)
1618 return -errno;
1619
ebc73a67
CB
1620 err = snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1621 if (err < 0 || (size_t)err >= IFNAMSIZ)
1622 return -E2BIG;
1623
8befa924
SH
1624 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1625 if (err < 0) {
8befa924 1626 close(sockfd);
8befa924
SH
1627 return -errno;
1628 }
1629
1630 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1631 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
8befa924 1632 close(sockfd);
8befa924
SH
1633 if (err < 0)
1634 return -errno;
1635
1636 return 0;
1637}