]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/network.c
lxc: remove perror call in nl.c (V2)
[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:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/socket.h>
36#include <sys/param.h>
37#include <sys/ioctl.h>
38#include <arpa/inet.h>
39#include <net/if.h>
40#include <net/if_arp.h>
41#include <net/ethernet.h>
42#include <netinet/in.h>
43#include <linux/netlink.h>
44#include <linux/rtnetlink.h>
45#include <linux/sockios.h>
46#include <linux/if_bridge.h>
47#include <nl.h>
48#include <network.h>
49
50#ifndef IFLA_LINKMODE
51# define IFLA_LINKMODE 17
52#endif
53
54#ifndef IFLA_LINKINFO
55# define IFLA_LINKINFO 18
56#endif
57
58#ifndef IFLA_NET_NS_PID
59# define IFLA_NET_NS_PID 19
60#endif
61
62#ifndef IFLA_INFO_KIND
63# define IFLA_INFO_KIND 1
64#endif
65
26c39028
JHS
66#ifndef IFLA_VLAN_ID
67# define IFLA_VLAN_ID 1
68#endif
69
0ad19a3f 70#ifndef IFLA_INFO_DATA
71# define IFLA_INFO_DATA 2
72#endif
73
74#ifndef VETH_INFO_PEER
75# define VETH_INFO_PEER 1
76#endif
77
e892973e
DL
78#ifndef IFLA_MACVLAN_MODE
79# define IFLA_MACVLAN_MODE 1
80#endif
81
0ad19a3f 82struct link_req {
83 struct nlmsg nlmsg;
84 struct ifinfomsg ifinfomsg;
85};
86
87struct ip_req {
88 struct nlmsg nlmsg;
89 struct ifaddrmsg ifa;
90};
91
82d5ae15 92int lxc_device_move(int ifindex, pid_t pid)
0ad19a3f 93{
94 struct nl_handler nlh;
95 struct nlmsg *nlmsg = NULL;
96 struct link_req *link_req;
3cfc0f3a 97 int err;
0ad19a3f 98
3cfc0f3a
MN
99 err = netlink_open(&nlh, NETLINK_ROUTE);
100 if (err)
101 return err;
0ad19a3f 102
3cfc0f3a 103 err = -ENOMEM;
0ad19a3f 104 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
105 if (!nlmsg)
106 goto out;
107
0ad19a3f 108 link_req = (struct link_req *)nlmsg;
109 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
82d5ae15 110 link_req->ifinfomsg.ifi_index = ifindex;
0ad19a3f 111 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
112 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
113 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
114
115 if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
116 goto out;
117
3cfc0f3a 118 err = netlink_transaction(&nlh, nlmsg, nlmsg);
0ad19a3f 119out:
120 netlink_close(&nlh);
121 nlmsg_free(nlmsg);
122 return err;
123}
124
c547a835 125int lxc_device_delete(const char *name)
0ad19a3f 126{
127 struct nl_handler nlh;
128 struct nlmsg *nlmsg = NULL, *answer = NULL;
129 struct link_req *link_req;
3cfc0f3a 130 int index, len, err;
0ad19a3f 131
3cfc0f3a
MN
132 err = netlink_open(&nlh, NETLINK_ROUTE);
133 if (err)
134 return err;
0ad19a3f 135
3cfc0f3a 136 err = -EINVAL;
0ad19a3f 137 len = strlen(name);
138 if (len == 1 || len > IFNAMSIZ)
139 goto out;
140
3cfc0f3a 141 err = -ENOMEM;
0ad19a3f 142 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
143 if (!nlmsg)
144 goto out;
145
146 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
147 if (!answer)
148 goto out;
149
3cfc0f3a 150 err = -EINVAL;
0ad19a3f 151 index = if_nametoindex(name);
152 if (!index)
153 goto out;
154
155 link_req = (struct link_req *)nlmsg;
156 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
157 link_req->ifinfomsg.ifi_index = index;
158 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
159 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
160 nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK;
161
162 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
163 goto out;
164
3cfc0f3a 165 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 166out:
167 netlink_close(&nlh);
168 nlmsg_free(answer);
169 nlmsg_free(nlmsg);
170 return err;
171}
172
b9a5bb58
DL
173int lxc_device_delete_index(int ifindex)
174{
175 struct nl_handler nlh;
176 struct nlmsg *nlmsg = NULL, *answer = NULL;
177 struct link_req *link_req;
3cfc0f3a 178 int err;
b9a5bb58 179
3cfc0f3a
MN
180 err = netlink_open(&nlh, NETLINK_ROUTE);
181 if (err)
182 return err;
b9a5bb58 183
3cfc0f3a 184 err = -ENOMEM;
b9a5bb58
DL
185 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
186 if (!nlmsg)
187 goto out;
188
189 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
190 if (!answer)
191 goto out;
192
193 link_req = (struct link_req *)nlmsg;
194 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
195 link_req->ifinfomsg.ifi_index = ifindex;
196 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
197 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
198 nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK;
199
3cfc0f3a 200 err = netlink_transaction(&nlh, nlmsg, answer);
b9a5bb58
DL
201out:
202 netlink_close(&nlh);
203 nlmsg_free(answer);
204 nlmsg_free(nlmsg);
205 return err;
206}
207
0ad19a3f 208static int device_set_flag(const char *name, int flag)
209{
210 struct nl_handler nlh;
211 struct nlmsg *nlmsg = NULL, *answer = NULL;
212 struct link_req *link_req;
3cfc0f3a 213 int index, len, err;
0ad19a3f 214
3cfc0f3a
MN
215 err = netlink_open(&nlh, NETLINK_ROUTE);
216 if (err)
217 return err;
0ad19a3f 218
3cfc0f3a 219 err = -EINVAL;
0ad19a3f 220 len = strlen(name);
221 if (len == 1 || len > IFNAMSIZ)
222 goto out;
223
3cfc0f3a 224 err = -ENOMEM;
0ad19a3f 225 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
226 if (!nlmsg)
227 goto out;
228
229 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
230 if (!answer)
231 goto out;
232
3cfc0f3a 233 err = -EINVAL;
0ad19a3f 234 index = if_nametoindex(name);
235 if (!index)
236 goto out;
237
238 link_req = (struct link_req *)nlmsg;
239 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
240 link_req->ifinfomsg.ifi_index = index;
241 link_req->ifinfomsg.ifi_change |= IFF_UP;
242 link_req->ifinfomsg.ifi_flags |= flag;
243 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
244 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
245 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
246
247 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 248out:
249 netlink_close(&nlh);
250 nlmsg_free(nlmsg);
251 nlmsg_free(answer);
252 return err;
253}
254
c547a835 255int lxc_device_set_mtu(const char *name, int mtu)
75d09f83
DL
256{
257 struct nl_handler nlh;
258 struct nlmsg *nlmsg = NULL, *answer = NULL;
259 struct link_req *link_req;
3cfc0f3a 260 int index, len, err;
75d09f83 261
3cfc0f3a
MN
262 err = netlink_open(&nlh, NETLINK_ROUTE);
263 if (err)
264 return err;
75d09f83 265
3cfc0f3a 266 err = -EINVAL;
75d09f83
DL
267 len = strlen(name);
268 if (len == 1 || len > IFNAMSIZ)
269 goto out;
270
3cfc0f3a 271 err = -ENOMEM;
75d09f83
DL
272 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
273 if (!nlmsg)
274 goto out;
275
276 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
277 if (!answer)
278 goto out;
279
3cfc0f3a 280 err = -EINVAL;
75d09f83
DL
281 index = if_nametoindex(name);
282 if (!index)
283 goto out;
284
285 link_req = (struct link_req *)nlmsg;
286 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
287 link_req->ifinfomsg.ifi_index = index;
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 if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
293 goto out;
294
295 err = netlink_transaction(&nlh, nlmsg, answer);
75d09f83
DL
296out:
297 netlink_close(&nlh);
298 nlmsg_free(nlmsg);
299 nlmsg_free(answer);
300 return err;
301}
302
497353b6 303int lxc_device_up(const char *name)
0ad19a3f 304{
305 return device_set_flag(name, IFF_UP);
306}
307
497353b6 308int lxc_device_down(const char *name)
0ad19a3f 309{
310 return device_set_flag(name, 0);
311}
312
497353b6 313int lxc_device_rename(const char *oldname, const char *newname)
0ad19a3f 314{
315 struct nl_handler nlh;
316 struct nlmsg *nlmsg = NULL, *answer = NULL;
317 struct link_req *link_req;
3cfc0f3a 318 int index, len, err;
0ad19a3f 319
3cfc0f3a
MN
320 err = netlink_open(&nlh, NETLINK_ROUTE);
321 if (err)
322 return err;
0ad19a3f 323
3cfc0f3a 324 err = -EINVAL;
0ad19a3f 325 len = strlen(oldname);
326 if (len == 1 || len > IFNAMSIZ)
327 goto out;
328
329 len = strlen(newname);
330 if (len == 1 || len > IFNAMSIZ)
331 goto out;
332
3cfc0f3a 333 err = -ENOMEM;
0ad19a3f 334 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
335 if (!nlmsg)
336 goto out;
337
338 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
339 if (!answer)
340 goto out;
341
3cfc0f3a 342 err = -EINVAL;
0ad19a3f 343 index = if_nametoindex(oldname);
344 if (!index)
345 goto out;
346
347 link_req = (struct link_req *)nlmsg;
348 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
349 link_req->ifinfomsg.ifi_index = index;
350 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
351 nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
352 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
353
354 if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
355 goto out;
356
3cfc0f3a 357 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 358out:
359 netlink_close(&nlh);
360 nlmsg_free(answer);
361 nlmsg_free(nlmsg);
362 return err;
363}
364
497353b6 365int lxc_veth_create(const char *name1, const char *name2)
0ad19a3f 366{
367 struct nl_handler nlh;
368 struct nlmsg *nlmsg = NULL, *answer = NULL;
369 struct link_req *link_req;
370 struct rtattr *nest1, *nest2, *nest3;
3cfc0f3a 371 int len, err;
0ad19a3f 372
3cfc0f3a
MN
373 err = netlink_open(&nlh, NETLINK_ROUTE);
374 if (err)
375 return err;
0ad19a3f 376
3cfc0f3a 377 err = -EINVAL;
0ad19a3f 378 len = strlen(name1);
379 if (len == 1 || len > IFNAMSIZ)
380 goto out;
381
382 len = strlen(name2);
383 if (len == 1 || len > IFNAMSIZ)
384 goto out;
385
3cfc0f3a 386 err = -ENOMEM;
0ad19a3f 387 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
388 if (!nlmsg)
389 goto out;
390
391 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
392 if (!answer)
393 goto out;
394
395 link_req = (struct link_req *)nlmsg;
396 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
397 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
79e68309 398 nlmsg->nlmsghdr.nlmsg_flags =
0ad19a3f 399 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
400 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
401
3cfc0f3a 402 err = -EINVAL;
79e68309 403 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 404 if (!nest1)
405 goto out;
406
407 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
408 goto out;
409
410 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
411 if (!nest2)
412 goto out;
413
414 nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
415 if (!nest3)
416 goto out;
417
418 nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg);
419
420 if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
421 goto out;
422
423 nla_end_nested(nlmsg, nest3);
424
425 nla_end_nested(nlmsg, nest2);
426
427 nla_end_nested(nlmsg, nest1);
428
429 if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
430 goto out;
431
3cfc0f3a 432 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 433out:
434 netlink_close(&nlh);
435 nlmsg_free(answer);
436 nlmsg_free(nlmsg);
437 return err;
438}
439
26c39028
JHS
440/* XXX: merge with lxc_macvlan_create */
441int lxc_vlan_create(const char *master, const char *name, ushort vlanid)
442{
443 struct nl_handler nlh;
444 struct nlmsg *nlmsg = NULL, *answer = NULL;
445 struct link_req *link_req;
446 struct rtattr *nest, *nest2;
3cfc0f3a 447 int lindex, len, err;
26c39028 448
3cfc0f3a
MN
449 err = netlink_open(&nlh, NETLINK_ROUTE);
450 if (err)
451 return err;
26c39028 452
3cfc0f3a 453 err = -EINVAL;
26c39028
JHS
454 len = strlen(master);
455 if (len == 1 || len > IFNAMSIZ)
456 goto err3;
457
458 len = strlen(name);
459 if (len == 1 || len > IFNAMSIZ)
460 goto err3;
461
3cfc0f3a 462 err = -ENOMEM;
26c39028
JHS
463 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
464 if (!nlmsg)
465 goto err3;
466
467 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
468 if (!answer)
469 goto err2;
470
3cfc0f3a 471 err = -EINVAL;
26c39028
JHS
472 lindex = if_nametoindex(master);
473 if (!lindex)
474 goto err1;
475
476 link_req = (struct link_req *)nlmsg;
477 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
478 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
479 nlmsg->nlmsghdr.nlmsg_flags =
480 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
481 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
482
79e68309 483 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
26c39028
JHS
484 if (!nest)
485 goto err1;
486
487 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
488 goto err1;
489
490 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
491 if (!nest2)
492 goto err1;
e892973e 493
26c39028
JHS
494 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
495 goto err1;
e892973e 496
26c39028
JHS
497 nla_end_nested(nlmsg, nest2);
498
499 nla_end_nested(nlmsg, nest);
500
501 if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
502 goto err1;
503
504 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
505 goto err1;
506
3cfc0f3a 507 err = netlink_transaction(&nlh, nlmsg, answer);
26c39028
JHS
508err1:
509 nlmsg_free(answer);
510err2:
511 nlmsg_free(nlmsg);
512err3:
513 netlink_close(&nlh);
514 return err;
515}
516
e892973e 517int lxc_macvlan_create(const char *master, const char *name, int mode)
0ad19a3f 518{
519 struct nl_handler nlh;
520 struct nlmsg *nlmsg = NULL, *answer = NULL;
521 struct link_req *link_req;
e892973e 522 struct rtattr *nest, *nest2;
3cfc0f3a 523 int index, len, err;
0ad19a3f 524
3cfc0f3a
MN
525 err = netlink_open(&nlh, NETLINK_ROUTE);
526 if (err)
527 return err;
0ad19a3f 528
3cfc0f3a 529 err = -EINVAL;
0ad19a3f 530 len = strlen(master);
531 if (len == 1 || len > IFNAMSIZ)
532 goto out;
533
534 len = strlen(name);
535 if (len == 1 || len > IFNAMSIZ)
536 goto out;
537
3cfc0f3a 538 err = -ENOMEM;
0ad19a3f 539 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
540 if (!nlmsg)
541 goto out;
542
543 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
544 if (!answer)
545 goto out;
546
3cfc0f3a 547 err = -EINVAL;
0ad19a3f 548 index = if_nametoindex(master);
549 if (!index)
550 goto out;
551
552 link_req = (struct link_req *)nlmsg;
553 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
554 nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
555 nlmsg->nlmsghdr.nlmsg_flags =
556 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
557 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
558
79e68309 559 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
0ad19a3f 560 if (!nest)
561 goto out;
562
563 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
564 goto out;
565
e892973e
DL
566 if (mode) {
567 nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
568 if (!nest2)
569 goto out;
570
571 if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
572 goto out;
573
574 nla_end_nested(nlmsg, nest2);
575 }
576
0ad19a3f 577 nla_end_nested(nlmsg, nest);
578
579 if (nla_put_u32(nlmsg, IFLA_LINK, index))
580 goto out;
581
582 if (nla_put_string(nlmsg, IFLA_IFNAME, name))
583 goto out;
584
3cfc0f3a 585 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 586out:
587 netlink_close(&nlh);
588 nlmsg_free(answer);
589 nlmsg_free(nlmsg);
590 return err;
591}
592
593static int proc_sys_net_write(const char *path, const char *value)
594{
595 int fd, err = 0;
596
597 fd = open(path, O_WRONLY);
598 if (fd < 0)
599 return -errno;
600
601 if (write(fd, value, strlen(value)) < 0)
602 err = -errno;
603
604 close(fd);
605 return err;
606}
607
608static int ip_forward_set(const char *ifname, int family, int flag)
609{
22ebac19 610 char path[MAXPATHLEN];
0ad19a3f 611
612 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 613 return -EINVAL;
0ad19a3f 614
79e68309 615 snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
0ad19a3f 616 family == AF_INET?"ipv4":"ipv6" , ifname);
617
22ebac19 618 return proc_sys_net_write(path, flag?"1":"0");
0ad19a3f 619}
620
497353b6 621int lxc_ip_forward_on(const char *ifname, int family)
0ad19a3f 622{
623 return ip_forward_set(ifname, family, 1);
624}
625
497353b6 626int lxc_ip_forward_off(const char *ifname, int family)
0ad19a3f 627{
628 return ip_forward_set(ifname, family, 0);
629}
630
631static int neigh_proxy_set(const char *ifname, int family, int flag)
632{
633 char path[MAXPATHLEN];
634
635 if (family != AF_INET && family != AF_INET6)
3cfc0f3a 636 return -EINVAL;
0ad19a3f 637
79e68309
MN
638 sprintf(path, "/proc/sys/net/%s/conf/%s/%s",
639 family == AF_INET?"ipv4":"ipv6" , ifname,
0ad19a3f 640 family == AF_INET?"proxy_arp":"proxy_ndp");
641
642 return proc_sys_net_write(path, flag?"1":"0");
643}
644
497353b6 645int lxc_neigh_proxy_on(const char *name, int family)
0ad19a3f 646{
647 return neigh_proxy_set(name, family, 1);
648}
649
497353b6 650int lxc_neigh_proxy_off(const char *name, int family)
0ad19a3f 651{
652 return neigh_proxy_set(name, family, 0);
653}
654
655int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
656{
657 unsigned char *data;
658 char c;
659 int i = 0;
660 unsigned val;
661
662 sockaddr->sa_family = ARPHRD_ETHER;
663 data = (unsigned char *)sockaddr->sa_data;
664
665 while ((*macaddr != '\0') && (i < ETH_ALEN)) {
666 val = 0;
667 c = *macaddr++;
668 if (isdigit(c))
669 val = c - '0';
670 else if (c >= 'a' && c <= 'f')
671 val = c - 'a' + 10;
672 else if (c >= 'A' && c <= 'F')
673 val = c - 'A' + 10;
674 else {
3cfc0f3a 675 return -EINVAL;
0ad19a3f 676 }
677 val <<= 4;
678 c = *macaddr;
679 if (isdigit(c))
680 val |= c - '0';
681 else if (c >= 'a' && c <= 'f')
682 val |= c - 'a' + 10;
683 else if (c >= 'A' && c <= 'F')
684 val |= c - 'A' + 10;
685 else if (c == ':' || c == 0)
686 val >>= 4;
687 else {
3cfc0f3a 688 return -EINVAL;
0ad19a3f 689 }
690 if (c != 0)
691 macaddr++;
692 *data++ = (unsigned char) (val & 0377);
693 i++;
694
695 if (*macaddr == ':')
696 macaddr++;
697 }
698
699 return 0;
700}
701
4bf1968d 702int lxc_ip_addr_add(int family, int ifindex, void *addr, int prefix)
0ad19a3f 703{
704 struct nl_handler nlh;
0ad19a3f 705 struct nlmsg *nlmsg = NULL, *answer = NULL;
706 struct ip_req *ip_req;
4bf1968d 707 int addrlen;
3cfc0f3a 708 int err;
0ad19a3f 709
4bf1968d
DL
710 addrlen = family == AF_INET ? sizeof(struct in_addr) :
711 sizeof(struct in6_addr);
712
3cfc0f3a
MN
713 err = netlink_open(&nlh, NETLINK_ROUTE);
714 if (err)
715 return err;
0ad19a3f 716
3cfc0f3a 717 err = -ENOMEM;
0ad19a3f 718 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
719 if (!nlmsg)
720 goto out;
721
722 answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
723 if (!answer)
724 goto out;
725
0ad19a3f 726 ip_req = (struct ip_req *)nlmsg;
727 ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
728 ip_req->nlmsg.nlmsghdr.nlmsg_flags =
729 NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
730 ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
731 ip_req->ifa.ifa_prefixlen = prefix;
732 ip_req->ifa.ifa_index = ifindex;
4bf1968d 733 ip_req->ifa.ifa_family = family;
0ad19a3f 734 ip_req->ifa.ifa_scope = 0;
735
3cfc0f3a 736 err = -EINVAL;
4bf1968d 737 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
0ad19a3f 738 goto out;
739
4bf1968d 740 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
0ad19a3f 741 goto out;
742
79e68309
MN
743/* if (in_bcast.s_addr != INADDR_ANY) */
744/* if (nla_put_buffer(nlmsg, IFA_BROADCAST, &in_bcast, */
745/* sizeof(in_bcast))) */
746/* goto out; */
0ad19a3f 747
3cfc0f3a 748 err = netlink_transaction(&nlh, nlmsg, answer);
0ad19a3f 749out:
750 netlink_close(&nlh);
751 nlmsg_free(answer);
752 nlmsg_free(nlmsg);
753 return err;
754}
755
79e68309 756static int bridge_add_del_interface(const char *bridge,
0ad19a3f 757 const char *ifname, int detach)
758{
759 int fd, index, err;
760 struct ifreq ifr;
761
762 if (strlen(ifname) > IFNAMSIZ)
3cfc0f3a 763 return -EINVAL;
0ad19a3f 764
765 index = if_nametoindex(ifname);
766 if (!index)
3cfc0f3a 767 return -EINVAL;
0ad19a3f 768
769 fd = socket(AF_INET, SOCK_STREAM, 0);
770 if (fd < 0)
3cfc0f3a 771 return -errno;
0ad19a3f 772
773 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
774 ifr.ifr_ifindex = index;
775 err = ioctl(fd, detach?SIOCBRDELIF:SIOCBRADDIF, &ifr);
776 close(fd);
3cfc0f3a
MN
777 if (err)
778 err = -errno;
0ad19a3f 779
780 return err;
781}
782
497353b6 783int lxc_bridge_attach(const char *bridge, const char *ifname)
0ad19a3f 784{
785 return bridge_add_del_interface(bridge, ifname, 0);
786}
787
497353b6 788int lxc_bridge_detach(const char *bridge, const char *ifname)
0ad19a3f 789{
790 return bridge_add_del_interface(bridge, ifname, 1);
791}