]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/network.c
unprivileged containers: use next available nic name if unspecified
[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 */
23#define _GNU_SOURCE
24#include <stdio.h>
25#undef _GNU_SOURCe
26#include <stdlib.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <errno.h>
30#include <string.h>
31#include <stdio.h>
32#include <ctype.h>
dd1d77f9 33#include <time.h>
0ad19a3f 34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/socket.h>
37#include <sys/param.h>
38#include <sys/ioctl.h>
39#include <arpa/inet.h>
40#include <net/if.h>
41#include <net/if_arp.h>
42#include <net/ethernet.h>
43#include <netinet/in.h>
44#include <linux/netlink.h>
45#include <linux/rtnetlink.h>
46#include <linux/sockios.h>
f549edcc
GK
47
48#include "nl.h"
49#include "network.h"
72d0e1cb 50#include "conf.h"
0ad19a3f 51
a0265685
SG
52#if HAVE_IFADDRS_H
53#include <ifaddrs.h>
54#else
55#include <../include/ifaddrs.h>
56#endif
57
0ad19a3f 58#ifndef IFLA_LINKMODE
59# define IFLA_LINKMODE 17
60#endif
61
62#ifndef IFLA_LINKINFO
63# define IFLA_LINKINFO 18
64#endif
65
66#ifndef IFLA_NET_NS_PID
67# define IFLA_NET_NS_PID 19
68#endif
69
70#ifndef IFLA_INFO_KIND
71# define IFLA_INFO_KIND 1
72#endif
73
26c39028
JHS
74#ifndef IFLA_VLAN_ID
75# define IFLA_VLAN_ID 1
76#endif
77
0ad19a3f 78#ifndef IFLA_INFO_DATA
79# define IFLA_INFO_DATA 2
80#endif
81
82#ifndef VETH_INFO_PEER
83# define VETH_INFO_PEER 1
84#endif
85
e892973e
DL
86#ifndef IFLA_MACVLAN_MODE
87# define IFLA_MACVLAN_MODE 1
88#endif
89
0ad19a3f 90struct link_req {
91 struct nlmsg nlmsg;
92 struct ifinfomsg ifinfomsg;
93};
94
95struct ip_req {
96 struct nlmsg nlmsg;
97 struct ifaddrmsg ifa;
98};
99
f8fee0e2
MK
100struct rt_req {
101 struct nlmsg nlmsg;
102 struct rtmsg rt;
103};
104
d472214b 105int lxc_netdev_move_by_index(int ifindex, pid_t pid)
0ad19a3f 106{
107 struct nl_handler nlh;
108 struct nlmsg *nlmsg = NULL;
109 struct link_req *link_req;
3cfc0f3a 110 int err;
0ad19a3f 111
3cfc0f3a
MN
112 err = netlink_open(&nlh, NETLINK_ROUTE);
113 if (err)
114 return err;
0ad19a3f 115
3cfc0f3a 116 err = -ENOMEM;
0ad19a3f 117 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
118 if (!nlmsg)
119 goto out;
120
0ad19a3f 121 link_req = (struct link_req *)nlmsg;
122 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
82d5ae15 123 link_req->ifinfomsg.ifi_index = ifindex;
0ad19a3f 124 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
125 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
126 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
127
128 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
129 goto out;
130
3cfc0f3a 131 err = netlink_transaction(&nlh, nlmsg, nlmsg);
0ad19a3f 132out:
133 netlink_close(&nlh);
134 nlmsg_free(nlmsg);
135 return err;
136}
137
8befa924
SH
138int lxc_netdev_move_by_name(char *ifname, pid_t pid)
139{
140 int index;
141
8befa924
SH
142 if (!ifname)
143 return -EINVAL;
144
32571606
SH
145 index = if_nametoindex(ifname);
146
8befa924
SH
147 return lxc_netdev_move_by_index(index, pid);
148}
149
b84f58b9 150int lxc_netdev_delete_by_index(int ifindex)
0ad19a3f 151{
152 struct nl_handler nlh;
153 struct nlmsg *nlmsg = NULL, *answer = NULL;
154 struct link_req *link_req;
b84f58b9 155 int err;
0ad19a3f 156
3cfc0f3a
MN
157 err = netlink_open(&nlh, NETLINK_ROUTE);
158 if (err)
159 return err;
0ad19a3f 160
3cfc0f3a 161 err = -ENOMEM;
0ad19a3f 162 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
163 if (!nlmsg)
164 goto out;
165
166 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
167 if (!answer)
168 goto out;
169
0ad19a3f 170 link_req = (struct link_req *)nlmsg;
171 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
b84f58b9 172 link_req->ifinfomsg.ifi_index = ifindex;
0ad19a3f 173 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
174 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
175 nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK;
176
3cfc0f3a 177 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 178out:
179 netlink_close(&nlh);
180 nlmsg_free(answer);
181 nlmsg_free(nlmsg);
182 return err;
183}
184
b84f58b9
DL
185int lxc_netdev_delete_by_name(const char *name)
186{
187 int index;
188
189 index = if_nametoindex(name);
190 if (!index)
191 return -EINVAL;
192
193 return lxc_netdev_delete_by_index(index);
194}
195
196int lxc_netdev_rename_by_index(int ifindex, const char *newname)
b9a5bb58
DL
197{
198 struct nl_handler nlh;
199 struct nlmsg *nlmsg = NULL, *answer = NULL;
200 struct link_req *link_req;
b84f58b9 201 int len, err;
b9a5bb58 202
3cfc0f3a
MN
203 err = netlink_open(&nlh, NETLINK_ROUTE);
204 if (err)
205 return err;
b9a5bb58 206
b84f58b9 207 len = strlen(newname);
dae3fdf6 208 if (len == 1 || len >= IFNAMSIZ)
b84f58b9
DL
209 goto out;
210
3cfc0f3a 211 err = -ENOMEM;
b9a5bb58
DL
212 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
213 if (!nlmsg)
214 goto out;
215
216 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
217 if (!answer)
218 goto out;
219
220 link_req = (struct link_req *)nlmsg;
221 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
222 link_req->ifinfomsg.ifi_index = ifindex;
223 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
224 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
b84f58b9
DL
225 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
226
227 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
228 goto out;
b9a5bb58 229
3cfc0f3a 230 err = netlink_transaction(&nlh, nlmsg, answer);
b9a5bb58
DL
231out:
232 netlink_close(&nlh);
233 nlmsg_free(answer);
234 nlmsg_free(nlmsg);
235 return err;
236}
237
b84f58b9
DL
238int lxc_netdev_rename_by_name(const char *oldname, const char *newname)
239{
240 int len, index;
241
242 len = strlen(oldname);
dae3fdf6 243 if (len == 1 || len >= IFNAMSIZ)
b84f58b9
DL
244 return -EINVAL;
245
246 index = if_nametoindex(oldname);
247 if (!index)
248 return -EINVAL;
249
250 return lxc_netdev_rename_by_index(index, newname);
251}
252
8befa924 253int netdev_set_flag(const char *name, int flag)
0ad19a3f 254{
255 struct nl_handler nlh;
256 struct nlmsg *nlmsg = NULL, *answer = NULL;
257 struct link_req *link_req;
3cfc0f3a 258 int index, len, err;
0ad19a3f 259
3cfc0f3a
MN
260 err = netlink_open(&nlh, NETLINK_ROUTE);
261 if (err)
262 return err;
0ad19a3f 263
3cfc0f3a 264 err = -EINVAL;
0ad19a3f 265 len = strlen(name);
dae3fdf6 266 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 267 goto out;
268
3cfc0f3a 269 err = -ENOMEM;
0ad19a3f 270 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
271 if (!nlmsg)
272 goto out;
273
274 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
275 if (!answer)
276 goto out;
277
3cfc0f3a 278 err = -EINVAL;
0ad19a3f 279 index = if_nametoindex(name);
280 if (!index)
281 goto out;
282
283 link_req = (struct link_req *)nlmsg;
284 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
285 link_req->ifinfomsg.ifi_index = index;
286 link_req->ifinfomsg.ifi_change |= IFF_UP;
287 link_req->ifinfomsg.ifi_flags |= flag;
288 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
289 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
290 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
291
292 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 293out:
294 netlink_close(&nlh);
295 nlmsg_free(nlmsg);
296 nlmsg_free(answer);
297 return err;
298}
299
0130df54
SH
300int netdev_get_mtu(int ifindex)
301{
302 struct nl_handler nlh;
303 struct nlmsg *nlmsg = NULL, *answer = NULL;
304 struct ip_req *ip_req;
305 struct nlmsghdr *msg;
306 int err, res;
307 int recv_len = 0, answer_len;
308 int readmore = 0;
309
310 err = netlink_open(&nlh, NETLINK_ROUTE);
311 if (err)
312 return err;
313
314 err = -ENOMEM;
315 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
316 if (!nlmsg)
317 goto out;
318
319 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
320 if (!answer)
321 goto out;
322
323 /* Save the answer buffer length, since it will be overwritten
324 * on the first receive (and we might need to receive more than
325 * once. */
326 answer_len = answer->nlmsghdr.nlmsg_len;
327
328 ip_req = (struct ip_req *)nlmsg;
329 ip_req->nlmsg.nlmsghdr.nlmsg_len =
330 NLMSG_LENGTH(sizeof(struct ifaddrmsg));
331 ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
332 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETLINK;
333 ip_req->ifa.ifa_family = AF_UNSPEC;
334
335 /* Send the request for addresses, which returns all addresses
336 * on all interfaces. */
337 err = netlink_send(&nlh, nlmsg);
338 if (err < 0)
339 goto out;
340
341 do {
342 /* Restore the answer buffer length, it might have been
343 * overwritten by a previous receive. */
344 answer->nlmsghdr.nlmsg_len = answer_len;
345
346 /* Get the (next) batch of reply messages */
347 err = netlink_rcv(&nlh, answer);
348 if (err < 0)
349 goto out;
350
351 recv_len = err;
352 err = 0;
353
354 /* Satisfy the typing for the netlink macros */
355 msg = &answer->nlmsghdr;
356
357 while (NLMSG_OK(msg, recv_len)) {
358
359 /* Stop reading if we see an error message */
360 if (msg->nlmsg_type == NLMSG_ERROR) {
361 struct nlmsgerr *errmsg = (struct nlmsgerr*)NLMSG_DATA(msg);
362 err = errmsg->error;
363 goto out;
364 }
365
366 /* Stop reading if we see a NLMSG_DONE message */
367 if (msg->nlmsg_type == NLMSG_DONE) {
368 readmore = 0;
369 break;
370 }
371
372 struct ifinfomsg *ifi = NLMSG_DATA(msg);
373 if (ifi->ifi_index == ifindex) {
374 struct rtattr *rta = IFLA_RTA(ifi);
375 int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
376 res = 0;
377 while(RTA_OK(rta, attr_len)) {
378 /* Found a local address for the requested interface,
379 * return it. */
380 if (rta->rta_type == IFLA_MTU) {
381 memcpy(&res, RTA_DATA(rta), sizeof(int));
382 err = res;
383 goto out;
384 }
385 rta = RTA_NEXT(rta, attr_len);
386 }
387
388 }
389
390 /* Keep reading more data from the socket if the
391 * last message had the NLF_F_MULTI flag set */
392 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
393
394 /* Look at the next message received in this buffer */
395 msg = NLMSG_NEXT(msg, recv_len);
396 }
397 } while (readmore);
398
399 /* If we end up here, we didn't find any result, so signal an
400 * error */
401 err = -1;
402
403out:
404 netlink_close(&nlh);
405 nlmsg_free(answer);
406 nlmsg_free(nlmsg);
407 return err;
408}
409
d472214b 410int lxc_netdev_set_mtu(const char *name, int mtu)
75d09f83
DL
411{
412 struct nl_handler nlh;
413 struct nlmsg *nlmsg = NULL, *answer = NULL;
414 struct link_req *link_req;
3cfc0f3a 415 int index, len, err;
75d09f83 416
3cfc0f3a
MN
417 err = netlink_open(&nlh, NETLINK_ROUTE);
418 if (err)
419 return err;
75d09f83 420
3cfc0f3a 421 err = -EINVAL;
75d09f83 422 len = strlen(name);
dae3fdf6 423 if (len == 1 || len >= IFNAMSIZ)
75d09f83
DL
424 goto out;
425
3cfc0f3a 426 err = -ENOMEM;
75d09f83
DL
427 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
428 if (!nlmsg)
429 goto out;
430
431 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
432 if (!answer)
433 goto out;
434
3cfc0f3a 435 err = -EINVAL;
75d09f83
DL
436 index = if_nametoindex(name);
437 if (!index)
438 goto out;
439
440 link_req = (struct link_req *)nlmsg;
441 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
442 link_req->ifinfomsg.ifi_index = index;
443 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
444 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
445 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
446
447 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
448 goto out;
449
450 err = netlink_transaction(&nlh, nlmsg, answer);
75d09f83
DL
451out:
452 netlink_close(&nlh);
453 nlmsg_free(nlmsg);
454 nlmsg_free(answer);
455 return err;
456}
457
d472214b 458int lxc_netdev_up(const char *name)
0ad19a3f 459{
d472214b 460 return netdev_set_flag(name, IFF_UP);
0ad19a3f 461}
462
d472214b 463int lxc_netdev_down(const char *name)
0ad19a3f 464{
d472214b 465 return netdev_set_flag(name, 0);
0ad19a3f 466}
467
497353b6 468int lxc_veth_create(const char *name1, const char *name2)
0ad19a3f 469{
470 struct nl_handler nlh;
471 struct nlmsg *nlmsg = NULL, *answer = NULL;
472 struct link_req *link_req;
473 struct rtattr *nest1, *nest2, *nest3;
3cfc0f3a 474 int len, err;
0ad19a3f 475
3cfc0f3a
MN
476 err = netlink_open(&nlh, NETLINK_ROUTE);
477 if (err)
478 return err;
0ad19a3f 479
3cfc0f3a 480 err = -EINVAL;
0ad19a3f 481 len = strlen(name1);
dae3fdf6 482 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 483 goto out;
484
485 len = strlen(name2);
dae3fdf6 486 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 487 goto out;
488
3cfc0f3a 489 err = -ENOMEM;
0ad19a3f 490 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
491 if (!nlmsg)
492 goto out;
493
494 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
495 if (!answer)
496 goto out;
497
498 link_req = (struct link_req *)nlmsg;
499 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
500 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
79e68309 501 nlmsg->nlmsghdr.nlmsg_flags =
0ad19a3f 502 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
503 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
504
3cfc0f3a 505 err = -EINVAL;
79e68309 506 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 507 if (!nest1)
508 goto out;
509
510 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
511 goto out;
512
513 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
514 if (!nest2)
515 goto out;
516
517 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
518 if (!nest3)
519 goto out;
520
521 nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg);
522
523 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
524 goto out;
525
526 nla_end_nested(nlmsg, nest3);
527
528 nla_end_nested(nlmsg, nest2);
529
530 nla_end_nested(nlmsg, nest1);
531
532 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
533 goto out;
534
3cfc0f3a 535 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 536out:
537 netlink_close(&nlh);
538 nlmsg_free(answer);
539 nlmsg_free(nlmsg);
540 return err;
541}
542
26c39028 543/* XXX: merge with lxc_macvlan_create */
7c11d57a 544int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
26c39028
JHS
545{
546 struct nl_handler nlh;
547 struct nlmsg *nlmsg = NULL, *answer = NULL;
548 struct link_req *link_req;
549 struct rtattr *nest, *nest2;
3cfc0f3a 550 int lindex, len, err;
26c39028 551
3cfc0f3a
MN
552 err = netlink_open(&nlh, NETLINK_ROUTE);
553 if (err)
554 return err;
26c39028 555
3cfc0f3a 556 err = -EINVAL;
26c39028 557 len = strlen(master);
dae3fdf6 558 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
559 goto err3;
560
561 len = strlen(name);
dae3fdf6 562 if (len == 1 || len >= IFNAMSIZ)
26c39028
JHS
563 goto err3;
564
3cfc0f3a 565 err = -ENOMEM;
26c39028
JHS
566 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
567 if (!nlmsg)
568 goto err3;
569
570 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
571 if (!answer)
572 goto err2;
573
3cfc0f3a 574 err = -EINVAL;
26c39028
JHS
575 lindex = if_nametoindex(master);
576 if (!lindex)
577 goto err1;
578
579 link_req = (struct link_req *)nlmsg;
580 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
581 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
582 nlmsg->nlmsghdr.nlmsg_flags =
583 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
584 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
585
79e68309 586 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
26c39028
JHS
587 if (!nest)
588 goto err1;
589
590 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
591 goto err1;
592
593 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
594 if (!nest2)
595 goto err1;
e892973e 596
26c39028
JHS
597 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
598 goto err1;
e892973e 599
26c39028
JHS
600 nla_end_nested(nlmsg, nest2);
601
602 nla_end_nested(nlmsg, nest);
603
604 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
605 goto err1;
606
607 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
608 goto err1;
609
3cfc0f3a 610 err = netlink_transaction(&nlh, nlmsg, answer);
26c39028
JHS
611err1:
612 nlmsg_free(answer);
613err2:
614 nlmsg_free(nlmsg);
615err3:
616 netlink_close(&nlh);
617 return err;
618}
619
e892973e 620int lxc_macvlan_create(const char *master, const char *name, int mode)
0ad19a3f 621{
622 struct nl_handler nlh;
623 struct nlmsg *nlmsg = NULL, *answer = NULL;
624 struct link_req *link_req;
e892973e 625 struct rtattr *nest, *nest2;
3cfc0f3a 626 int index, len, err;
0ad19a3f 627
3cfc0f3a
MN
628 err = netlink_open(&nlh, NETLINK_ROUTE);
629 if (err)
630 return err;
0ad19a3f 631
3cfc0f3a 632 err = -EINVAL;
0ad19a3f 633 len = strlen(master);
dae3fdf6 634 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 635 goto out;
636
637 len = strlen(name);
dae3fdf6 638 if (len == 1 || len >= IFNAMSIZ)
0ad19a3f 639 goto out;
640
3cfc0f3a 641 err = -ENOMEM;
0ad19a3f 642 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
643 if (!nlmsg)
644 goto out;
645
646 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
647 if (!answer)
648 goto out;
649
3cfc0f3a 650 err = -EINVAL;
0ad19a3f 651 index = if_nametoindex(master);
652 if (!index)
653 goto out;
654
655 link_req = (struct link_req *)nlmsg;
656 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
657 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
658 nlmsg->nlmsghdr.nlmsg_flags =
659 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
660 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
661
79e68309 662 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 663 if (!nest)
664 goto out;
665
666 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
667 goto out;
668
e892973e
DL
669 if (mode) {
670 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
671 if (!nest2)
672 goto out;
673
674 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
675 goto out;
676
677 nla_end_nested(nlmsg, nest2);
678 }
679
0ad19a3f 680 nla_end_nested(nlmsg, nest);
681
682 if (nla_put_u32(nlmsg, IFLA_LINK, index))
683 goto out;
684
685 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
686 goto out;
687
3cfc0f3a 688 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 689out:
690 netlink_close(&nlh);
691 nlmsg_free(answer);
692 nlmsg_free(nlmsg);
693 return err;
694}
695
696static int proc_sys_net_write(const char *path, const char *value)
697{
698 int fd, err = 0;
699
700 fd = open(path, O_WRONLY);
701 if (fd < 0)
702 return -errno;
703
704 if (write(fd, value, strlen(value)) < 0)
705 err = -errno;
706
707 close(fd);
708 return err;
709}
710
711static int ip_forward_set(const char *ifname, int family, int flag)
712{
22ebac19 713 char path[MAXPATHLEN];
9ba8130c 714 int rc;
0ad19a3f 715
716 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 717 return -EINVAL;
0ad19a3f 718
9ba8130c 719 rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
0ad19a3f 720 family == AF_INET?"ipv4":"ipv6" , ifname);
9ba8130c
SH
721 if (rc >= MAXPATHLEN)
722 return -E2BIG;
0ad19a3f 723
22ebac19 724 return proc_sys_net_write(path, flag?"1":"0");
0ad19a3f 725}
726
497353b6 727int lxc_ip_forward_on(const char *ifname, int family)
0ad19a3f 728{
729 return ip_forward_set(ifname, family, 1);
730}
731
497353b6 732int lxc_ip_forward_off(const char *ifname, int family)
0ad19a3f 733{
734 return ip_forward_set(ifname, family, 0);
735}
736
737static int neigh_proxy_set(const char *ifname, int family, int flag)
738{
739 char path[MAXPATHLEN];
9ba8130c 740 int ret;
0ad19a3f 741
742 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 743 return -EINVAL;
0ad19a3f 744
9ba8130c 745 ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
79e68309 746 family == AF_INET?"ipv4":"ipv6" , ifname,
0ad19a3f 747 family == AF_INET?"proxy_arp":"proxy_ndp");
9ba8130c
SH
748 if (ret < 0 || ret >= MAXPATHLEN)
749 return -E2BIG;
0ad19a3f 750
751 return proc_sys_net_write(path, flag?"1":"0");
752}
753
497353b6 754int lxc_neigh_proxy_on(const char *name, int family)
0ad19a3f 755{
756 return neigh_proxy_set(name, family, 1);
757}
758
497353b6 759int lxc_neigh_proxy_off(const char *name, int family)
0ad19a3f 760{
761 return neigh_proxy_set(name, family, 0);
762}
763
764int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
765{
1f1b18e7
DL
766 unsigned char *data;
767 char c;
768 int i = 0;
769 unsigned val;
770
771 sockaddr->sa_family = ARPHRD_ETHER;
772 data = (unsigned char *)sockaddr->sa_data;
773
774 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
775 val = 0;
776 c = *macaddr++;
777 if (isdigit(c))
778 val = c - '0';
779 else if (c >= 'a' && c <= 'f')
780 val = c - 'a' + 10;
781 else if (c >= 'A' && c <= 'F')
782 val = c - 'A' + 10;
783 else {
784 return -EINVAL;
785 }
786 val <<= 4;
787 c = *macaddr;
788 if (isdigit(c))
789 val |= c - '0';
790 else if (c >= 'a' && c <= 'f')
791 val |= c - 'a' + 10;
792 else if (c >= 'A' && c <= 'F')
793 val |= c - 'A' + 10;
794 else if (c == ':' || c == 0)
795 val >>= 4;
796 else {
797 return -EINVAL;
798 }
799 if (c != 0)
800 macaddr++;
801 *data++ = (unsigned char) (val & 0377);
802 i++;
803
804 if (*macaddr == ':')
805 macaddr++;
0ad19a3f 806 }
0ad19a3f 807
1f1b18e7 808 return 0;
0ad19a3f 809}
810
1f1b18e7
DL
811static int ip_addr_add(int family, int ifindex,
812 void *addr, void *bcast, void *acast, int prefix)
0ad19a3f 813{
814 struct nl_handler nlh;
0ad19a3f 815 struct nlmsg *nlmsg = NULL, *answer = NULL;
816 struct ip_req *ip_req;
4bf1968d 817 int addrlen;
3cfc0f3a 818 int err;
0ad19a3f 819
4bf1968d
DL
820 addrlen = family == AF_INET ? sizeof(struct in_addr) :
821 sizeof(struct in6_addr);
822
3cfc0f3a
MN
823 err = netlink_open(&nlh, NETLINK_ROUTE);
824 if (err)
825 return err;
0ad19a3f 826
3cfc0f3a 827 err = -ENOMEM;
0ad19a3f 828 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
829 if (!nlmsg)
830 goto out;
831
832 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
833 if (!answer)
834 goto out;
835
0ad19a3f 836 ip_req = (struct ip_req *)nlmsg;
1f1b18e7
DL
837 ip_req->nlmsg.nlmsghdr.nlmsg_len =
838 NLMSG_LENGTH(sizeof(struct ifaddrmsg));
0ad19a3f 839 ip_req->nlmsg.nlmsghdr.nlmsg_flags =
840 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
841 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
842 ip_req->ifa.ifa_prefixlen = prefix;
843 ip_req->ifa.ifa_index = ifindex;
4bf1968d 844 ip_req->ifa.ifa_family = family;
0ad19a3f 845 ip_req->ifa.ifa_scope = 0;
846
3cfc0f3a 847 err = -EINVAL;
4bf1968d 848 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
0ad19a3f 849 goto out;
850
4bf1968d 851 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
0ad19a3f 852 goto out;
853
d8948a52 854 if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
1f1b18e7
DL
855 goto out;
856
857 /* TODO : multicast, anycast with ipv6 */
7ddc8f24 858 err = -EPROTONOSUPPORT;
79881dc6
DL
859 if (family == AF_INET6 &&
860 (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
861 memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
1f1b18e7 862 goto out;
0ad19a3f 863
3cfc0f3a 864 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 865out:
866 netlink_close(&nlh);
867 nlmsg_free(answer);
868 nlmsg_free(nlmsg);
869 return err;
870}
871
1f1b18e7
DL
872int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
873 struct in6_addr *mcast,
874 struct in6_addr *acast, int prefix)
875{
876 return ip_addr_add(AF_INET6, ifindex, addr, mcast, acast, prefix);
877}
878
879int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr,
880 struct in_addr *bcast, int prefix)
881{
882 return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix);
883}
884
19a26f82
MK
885/* Find an IFA_LOCAL (or IFA_ADDRESS if not IFA_LOCAL is present)
886 * address from the given RTM_NEWADDR message. Allocates memory for the
887 * address and stores that pointer in *res (so res should be an
888 * in_addr** or in6_addr**).
889 */
890static int ifa_get_local_ip(int family, struct ip_req *ip_info, void** res) {
891 struct rtattr *rta = IFA_RTA(&ip_info->ifa);
892 int attr_len = IFA_PAYLOAD(&ip_info->nlmsg.nlmsghdr);
893 int addrlen;
894
895 if (ip_info->ifa.ifa_family != family)
896 return 0;
897
898 addrlen = family == AF_INET ? sizeof(struct in_addr) :
899 sizeof(struct in6_addr);
900
901 /* Loop over the rtattr's in this message */
902 while(RTA_OK(rta, attr_len)) {
903 /* Found a local address for the requested interface,
904 * return it. */
905 if (rta->rta_type == IFA_LOCAL || rta->rta_type == IFA_ADDRESS) {
906 /* Sanity check. The family check above should
907 * make sure the address length is correct, but
908 * check here just in case */
909 if (RTA_PAYLOAD(rta) != addrlen)
910 return -1;
911
912 /* We might have found an IFA_ADDRESS before,
913 * which we now overwrite with an IFA_LOCAL. */
dd66e5ad 914 if (!*res) {
19a26f82 915 *res = malloc(addrlen);
dd66e5ad
DE
916 if (!*res)
917 return -1;
918 }
19a26f82
MK
919
920 memcpy(*res, RTA_DATA(rta), addrlen);
921
922 if (rta->rta_type == IFA_LOCAL)
923 break;
924 }
925 rta = RTA_NEXT(rta, attr_len);
926 }
927 return 0;
928}
929
930static int ip_addr_get(int family, int ifindex, void **res)
931{
932 struct nl_handler nlh;
933 struct nlmsg *nlmsg = NULL, *answer = NULL;
934 struct ip_req *ip_req, *ip_info;
935 struct nlmsghdr *msg;
936 int err;
937 int recv_len = 0, answer_len;
938 int readmore = 0;
939
940 err = netlink_open(&nlh, NETLINK_ROUTE);
941 if (err)
942 return err;
943
944 err = -ENOMEM;
945 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
946 if (!nlmsg)
947 goto out;
948
949 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
950 if (!answer)
951 goto out;
952
953 /* Save the answer buffer length, since it will be overwritten
954 * on the first receive (and we might need to receive more than
955 * once. */
956 answer_len = answer->nlmsghdr.nlmsg_len;
957
958 ip_req = (struct ip_req *)nlmsg;
959 ip_req->nlmsg.nlmsghdr.nlmsg_len =
960 NLMSG_LENGTH(sizeof(struct ifaddrmsg));
961 ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
962 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETADDR;
963 ip_req->ifa.ifa_family = family;
964
965 /* Send the request for addresses, which returns all addresses
966 * on all interfaces. */
967 err = netlink_send(&nlh, nlmsg);
968 if (err < 0)
969 goto out;
19a26f82
MK
970
971 do {
972 /* Restore the answer buffer length, it might have been
973 * overwritten by a previous receive. */
974 answer->nlmsghdr.nlmsg_len = answer_len;
975
976 /* Get the (next) batch of reply messages */
977 err = netlink_rcv(&nlh, answer);
978 if (err < 0)
979 goto out;
980
981 recv_len = err;
982 err = 0;
983
984 /* Satisfy the typing for the netlink macros */
985 msg = &answer->nlmsghdr;
986
987 while (NLMSG_OK(msg, recv_len)) {
988 /* Stop reading if we see an error message */
989 if (msg->nlmsg_type == NLMSG_ERROR) {
990 struct nlmsgerr *errmsg = (struct nlmsgerr*)NLMSG_DATA(msg);
991 err = errmsg->error;
992 goto out;
993 }
994
995 /* Stop reading if we see a NLMSG_DONE message */
996 if (msg->nlmsg_type == NLMSG_DONE) {
997 readmore = 0;
998 break;
999 }
1000
1001 if (msg->nlmsg_type != RTM_NEWADDR) {
1002 err = -1;
1003 goto out;
1004 }
1005
1006 ip_info = (struct ip_req *)msg;
1007 if (ip_info->ifa.ifa_index == ifindex) {
51e7a874
SG
1008 if (ifa_get_local_ip(family, ip_info, res) < 0) {
1009 err = -1;
1010 goto out;
1011 }
1012
19a26f82
MK
1013 /* Found a result, stop searching */
1014 if (*res)
1015 goto out;
1016 }
1017
1018 /* Keep reading more data from the socket if the
1019 * last message had the NLF_F_MULTI flag set */
1020 readmore = (msg->nlmsg_flags & NLM_F_MULTI);
1021
1022 /* Look at the next message received in this buffer */
1023 msg = NLMSG_NEXT(msg, recv_len);
1024 }
1025 } while (readmore);
1026
1027 /* If we end up here, we didn't find any result, so signal an
1028 * error */
1029 err = -1;
1030
1031out:
1032 netlink_close(&nlh);
1033 nlmsg_free(answer);
1034 nlmsg_free(nlmsg);
1035 return err;
1036}
1037
1038int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
1039{
1040 return ip_addr_get(AF_INET6, ifindex, (void**)res);
1041}
1042
1043int lxc_ipv4_addr_get(int ifindex, struct in_addr** res)
1044{
1045 return ip_addr_get(AF_INET, ifindex, (void**)res);
1046}
1047
f8fee0e2
MK
1048static int ip_gateway_add(int family, int ifindex, void *gw)
1049{
1050 struct nl_handler nlh;
1051 struct nlmsg *nlmsg = NULL, *answer = NULL;
1052 struct rt_req *rt_req;
1053 int addrlen;
1054 int err;
1055
1056 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1057 sizeof(struct in6_addr);
1058
1059 err = netlink_open(&nlh, NETLINK_ROUTE);
1060 if (err)
1061 return err;
1062
1063 err = -ENOMEM;
1064 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1065 if (!nlmsg)
1066 goto out;
1067
1068 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
1069 if (!answer)
1070 goto out;
1071
1072 rt_req = (struct rt_req *)nlmsg;
1073 rt_req->nlmsg.nlmsghdr.nlmsg_len =
1074 NLMSG_LENGTH(sizeof(struct rtmsg));
1075 rt_req->nlmsg.nlmsghdr.nlmsg_flags =
1076 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1077 rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
1078 rt_req->rt.rtm_family = family;
1079 rt_req->rt.rtm_table = RT_TABLE_MAIN;
1080 rt_req->rt.rtm_scope = RT_SCOPE_UNIVERSE;
1081 rt_req->rt.rtm_protocol = RTPROT_BOOT;
1082 rt_req->rt.rtm_type = RTN_UNICAST;
1083 /* "default" destination */
1084 rt_req->rt.rtm_dst_len = 0;
1085
1086 err = -EINVAL;
1087 if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
1088 goto out;
1089
1090 /* Adding the interface index enables the use of link-local
1091 * addresses for the gateway */
1092 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1093 goto out;
1094
1095 err = netlink_transaction(&nlh, nlmsg, answer);
1096out:
1097 netlink_close(&nlh);
1098 nlmsg_free(answer);
1099 nlmsg_free(nlmsg);
1100 return err;
1101}
1102
1103int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
1104{
1105 return ip_gateway_add(AF_INET, ifindex, gw);
1106}
1107
1108int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
1109{
1110 return ip_gateway_add(AF_INET6, ifindex, gw);
1111}
1112
77dcf03a
GL
1113static int ip_route_dest_add(int family, int ifindex, void *dest)
1114{
1115 struct nl_handler nlh;
1116 struct nlmsg *nlmsg = NULL, *answer = NULL;
1117 struct rt_req *rt_req;
1118 int addrlen;
1119 int err;
1120
1121 addrlen = family == AF_INET ? sizeof(struct in_addr) :
1122 sizeof(struct in6_addr);
1123
1124 err = netlink_open(&nlh, NETLINK_ROUTE);
1125 if (err)
1126 return err;
1127
1128 err = -ENOMEM;
1129 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
1130 if (!nlmsg)
1131 goto out;
1132
1133 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
1134 if (!answer)
1135 goto out;
1136
1137 rt_req = (struct rt_req *)nlmsg;
1138 rt_req->nlmsg.nlmsghdr.nlmsg_len =
1139 NLMSG_LENGTH(sizeof(struct rtmsg));
1140 rt_req->nlmsg.nlmsghdr.nlmsg_flags =
1141 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
1142 rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
1143 rt_req->rt.rtm_family = family;
1144 rt_req->rt.rtm_table = RT_TABLE_MAIN;
1145 rt_req->rt.rtm_scope = RT_SCOPE_LINK;
1146 rt_req->rt.rtm_protocol = RTPROT_BOOT;
1147 rt_req->rt.rtm_type = RTN_UNICAST;
1148 rt_req->rt.rtm_dst_len = addrlen*8;
1149
1150 err = -EINVAL;
1151 if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
1152 goto out;
1153 if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
1154 goto out;
1155 err = netlink_transaction(&nlh, nlmsg, answer);
1156out:
1157 netlink_close(&nlh);
1158 nlmsg_free(answer);
1159 nlmsg_free(nlmsg);
1160 return err;
1161}
1162
1163int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
1164{
1165 return ip_route_dest_add(AF_INET, ifindex, dest);
1166}
1167
1168int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
1169{
1170 return ip_route_dest_add(AF_INET6, ifindex, dest);
1171}
1172
7d163508
MN
1173/*
1174 * There is a lxc_bridge_attach, but no need of a bridge detach
d472214b 1175 * as automatically done by kernel when a netdev is deleted.
7d163508
MN
1176 */
1177int lxc_bridge_attach(const char *bridge, const char *ifname)
0ad19a3f 1178{
1179 int fd, index, err;
1180 struct ifreq ifr;
1181
dae3fdf6 1182 if (strlen(ifname) >= IFNAMSIZ)
3cfc0f3a 1183 return -EINVAL;
0ad19a3f 1184
1185 index = if_nametoindex(ifname);
1186 if (!index)
3cfc0f3a 1187 return -EINVAL;
0ad19a3f 1188
1189 fd = socket(AF_INET, SOCK_STREAM, 0);
1190 if (fd < 0)
3cfc0f3a 1191 return -errno;
0ad19a3f 1192
5da6aa8c
DE
1193 strncpy(ifr.ifr_name, bridge, IFNAMSIZ-1);
1194 ifr.ifr_name[IFNAMSIZ-1] = '\0';
0ad19a3f 1195 ifr.ifr_ifindex = index;
7d163508 1196 err = ioctl(fd, SIOCBRADDIF, &ifr);
0ad19a3f 1197 close(fd);
3cfc0f3a
MN
1198 if (err)
1199 err = -errno;
0ad19a3f 1200
1201 return err;
1202}
72d0e1cb 1203
74a3920a 1204static const char* const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
b343592b 1205 [LXC_NET_EMPTY] = "empty",
72d0e1cb
SG
1206 [LXC_NET_VETH] = "veth",
1207 [LXC_NET_MACVLAN] = "macvlan",
72d0e1cb 1208 [LXC_NET_PHYS] = "phys",
b343592b
BP
1209 [LXC_NET_VLAN] = "vlan",
1210 [LXC_NET_NONE] = "none",
72d0e1cb
SG
1211};
1212
1213const char *lxc_net_type_to_str(int type)
1214{
1215 if (type < 0 || type > LXC_NET_MAXCONFTYPE)
1216 return NULL;
1217 return lxc_network_types[type];
1218}
8befa924 1219
74a3920a 1220static const char padchar[] =
a0265685
SG
1221"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1222
1223char *lxc_mkifname(char *template)
1224{
1225 char *name = NULL;
1226 int i = 0;
1227 FILE *urandom;
1228 unsigned int seed;
1229 struct ifaddrs *ifaddr, *ifa;
1230 int ifexists = 0;
1231
1232 /* Get all the network interfaces */
1233 getifaddrs(&ifaddr);
1234
1235 /* Initialize the random number generator */
a0265685 1236 urandom = fopen ("/dev/urandom", "r");
a0265685
SG
1237 if (urandom != NULL) {
1238 if (fread (&seed, sizeof(seed), 1, urandom) <= 0)
1239 seed = time(0);
a0265685 1240 fclose(urandom);
a0265685
SG
1241 }
1242 else
1243 seed = time(0);
1244
1245#ifndef HAVE_RAND_R
1246 srand(seed);
1247#endif
1248
1249 /* Generate random names until we find one that doesn't exist */
1250 while(1) {
1251 ifexists = 0;
1252 name = strdup(template);
1253
1254 if (name == NULL)
1255 return NULL;
1256
1257 for (i = 0; i < strlen(name); i++) {
1258 if (name[i] == 'X') {
1259#ifdef HAVE_RAND_R
1260 name[i] = padchar[rand_r(&seed) % (strlen(padchar) - 1)];
1261#else
1262 name[i] = padchar[rand() % (strlen(padchar) - 1)];
1263#endif
1264 }
1265 }
1266
1267 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1268 if (strcmp(ifa->ifa_name, name) == 0) {
1269 ifexists = 1;
1270 break;
1271 }
1272 }
1273
1274 if (ifexists == 0)
1275 break;
1276
1277 free(name);
1278 }
1279
1280 freeifaddrs(ifaddr);
1281 return name;
1282}
1283
8befa924
SH
1284int setup_private_host_hw_addr(char *veth1)
1285{
1286 struct ifreq ifr;
1287 int err;
1288 int sockfd;
1289
8befa924 1290 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
8befa924
SH
1291 if (sockfd < 0)
1292 return -errno;
1293
1294 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1295 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1296 if (err < 0) {
8befa924 1297 close(sockfd);
8befa924
SH
1298 return -errno;
1299 }
1300
1301 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1302 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
8befa924 1303 close(sockfd);
8befa924
SH
1304 if (err < 0)
1305 return -errno;
1306
1307 return 0;
1308}