]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/network.c
lxc: remove perror call in nl.c (V2)
[mirror_lxc.git] / src / lxc / network.c
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
66 #ifndef IFLA_VLAN_ID
67 # define IFLA_VLAN_ID 1
68 #endif
69
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
78 #ifndef IFLA_MACVLAN_MODE
79 # define IFLA_MACVLAN_MODE 1
80 #endif
81
82 struct link_req {
83 struct nlmsg nlmsg;
84 struct ifinfomsg ifinfomsg;
85 };
86
87 struct ip_req {
88 struct nlmsg nlmsg;
89 struct ifaddrmsg ifa;
90 };
91
92 int lxc_device_move(int ifindex, pid_t pid)
93 {
94 struct nl_handler nlh;
95 struct nlmsg *nlmsg = NULL;
96 struct link_req *link_req;
97 int err;
98
99 err = netlink_open(&nlh, NETLINK_ROUTE);
100 if (err)
101 return err;
102
103 err = -ENOMEM;
104 nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
105 if (!nlmsg)
106 goto out;
107
108 link_req = (struct link_req *)nlmsg;
109 link_req->ifinfomsg.ifi_family = AF_UNSPEC;
110 link_req->ifinfomsg.ifi_index = ifindex;
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
118 err = netlink_transaction(&nlh, nlmsg, nlmsg);
119 out:
120 netlink_close(&nlh);
121 nlmsg_free(nlmsg);
122 return err;
123 }
124
125 int lxc_device_delete(const char *name)
126 {
127 struct nl_handler nlh;
128 struct nlmsg *nlmsg = NULL, *answer = NULL;
129 struct link_req *link_req;
130 int index, len, err;
131
132 err = netlink_open(&nlh, NETLINK_ROUTE);
133 if (err)
134 return err;
135
136 err = -EINVAL;
137 len = strlen(name);
138 if (len == 1 || len > IFNAMSIZ)
139 goto out;
140
141 err = -ENOMEM;
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
150 err = -EINVAL;
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
165 err = netlink_transaction(&nlh, nlmsg, answer);
166 out:
167 netlink_close(&nlh);
168 nlmsg_free(answer);
169 nlmsg_free(nlmsg);
170 return err;
171 }
172
173 int 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;
178 int err;
179
180 err = netlink_open(&nlh, NETLINK_ROUTE);
181 if (err)
182 return err;
183
184 err = -ENOMEM;
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
200 err = netlink_transaction(&nlh, nlmsg, answer);
201 out:
202 netlink_close(&nlh);
203 nlmsg_free(answer);
204 nlmsg_free(nlmsg);
205 return err;
206 }
207
208 static 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;
213 int index, len, err;
214
215 err = netlink_open(&nlh, NETLINK_ROUTE);
216 if (err)
217 return err;
218
219 err = -EINVAL;
220 len = strlen(name);
221 if (len == 1 || len > IFNAMSIZ)
222 goto out;
223
224 err = -ENOMEM;
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
233 err = -EINVAL;
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);
248 out:
249 netlink_close(&nlh);
250 nlmsg_free(nlmsg);
251 nlmsg_free(answer);
252 return err;
253 }
254
255 int lxc_device_set_mtu(const char *name, int mtu)
256 {
257 struct nl_handler nlh;
258 struct nlmsg *nlmsg = NULL, *answer = NULL;
259 struct link_req *link_req;
260 int index, len, err;
261
262 err = netlink_open(&nlh, NETLINK_ROUTE);
263 if (err)
264 return err;
265
266 err = -EINVAL;
267 len = strlen(name);
268 if (len == 1 || len > IFNAMSIZ)
269 goto out;
270
271 err = -ENOMEM;
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
280 err = -EINVAL;
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);
296 out:
297 netlink_close(&nlh);
298 nlmsg_free(nlmsg);
299 nlmsg_free(answer);
300 return err;
301 }
302
303 int lxc_device_up(const char *name)
304 {
305 return device_set_flag(name, IFF_UP);
306 }
307
308 int lxc_device_down(const char *name)
309 {
310 return device_set_flag(name, 0);
311 }
312
313 int lxc_device_rename(const char *oldname, const char *newname)
314 {
315 struct nl_handler nlh;
316 struct nlmsg *nlmsg = NULL, *answer = NULL;
317 struct link_req *link_req;
318 int index, len, err;
319
320 err = netlink_open(&nlh, NETLINK_ROUTE);
321 if (err)
322 return err;
323
324 err = -EINVAL;
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
333 err = -ENOMEM;
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
342 err = -EINVAL;
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
357 err = netlink_transaction(&nlh, nlmsg, answer);
358 out:
359 netlink_close(&nlh);
360 nlmsg_free(answer);
361 nlmsg_free(nlmsg);
362 return err;
363 }
364
365 int lxc_veth_create(const char *name1, const char *name2)
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;
371 int len, err;
372
373 err = netlink_open(&nlh, NETLINK_ROUTE);
374 if (err)
375 return err;
376
377 err = -EINVAL;
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
386 err = -ENOMEM;
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));
398 nlmsg->nlmsghdr.nlmsg_flags =
399 NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
400 nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
401
402 err = -EINVAL;
403 nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
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
432 err = netlink_transaction(&nlh, nlmsg, answer);
433 out:
434 netlink_close(&nlh);
435 nlmsg_free(answer);
436 nlmsg_free(nlmsg);
437 return err;
438 }
439
440 /* XXX: merge with lxc_macvlan_create */
441 int 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;
447 int lindex, len, err;
448
449 err = netlink_open(&nlh, NETLINK_ROUTE);
450 if (err)
451 return err;
452
453 err = -EINVAL;
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
462 err = -ENOMEM;
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
471 err = -EINVAL;
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
483 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
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;
493
494 if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
495 goto err1;
496
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
507 err = netlink_transaction(&nlh, nlmsg, answer);
508 err1:
509 nlmsg_free(answer);
510 err2:
511 nlmsg_free(nlmsg);
512 err3:
513 netlink_close(&nlh);
514 return err;
515 }
516
517 int lxc_macvlan_create(const char *master, const char *name, int mode)
518 {
519 struct nl_handler nlh;
520 struct nlmsg *nlmsg = NULL, *answer = NULL;
521 struct link_req *link_req;
522 struct rtattr *nest, *nest2;
523 int index, len, err;
524
525 err = netlink_open(&nlh, NETLINK_ROUTE);
526 if (err)
527 return err;
528
529 err = -EINVAL;
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
538 err = -ENOMEM;
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
547 err = -EINVAL;
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
559 nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
560 if (!nest)
561 goto out;
562
563 if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
564 goto out;
565
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
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
585 err = netlink_transaction(&nlh, nlmsg, answer);
586 out:
587 netlink_close(&nlh);
588 nlmsg_free(answer);
589 nlmsg_free(nlmsg);
590 return err;
591 }
592
593 static 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
608 static int ip_forward_set(const char *ifname, int family, int flag)
609 {
610 char path[MAXPATHLEN];
611
612 if (family != AF_INET && family != AF_INET6)
613 return -EINVAL;
614
615 snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
616 family == AF_INET?"ipv4":"ipv6" , ifname);
617
618 return proc_sys_net_write(path, flag?"1":"0");
619 }
620
621 int lxc_ip_forward_on(const char *ifname, int family)
622 {
623 return ip_forward_set(ifname, family, 1);
624 }
625
626 int lxc_ip_forward_off(const char *ifname, int family)
627 {
628 return ip_forward_set(ifname, family, 0);
629 }
630
631 static 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)
636 return -EINVAL;
637
638 sprintf(path, "/proc/sys/net/%s/conf/%s/%s",
639 family == AF_INET?"ipv4":"ipv6" , ifname,
640 family == AF_INET?"proxy_arp":"proxy_ndp");
641
642 return proc_sys_net_write(path, flag?"1":"0");
643 }
644
645 int lxc_neigh_proxy_on(const char *name, int family)
646 {
647 return neigh_proxy_set(name, family, 1);
648 }
649
650 int lxc_neigh_proxy_off(const char *name, int family)
651 {
652 return neigh_proxy_set(name, family, 0);
653 }
654
655 int 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 {
675 return -EINVAL;
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 {
688 return -EINVAL;
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
702 int lxc_ip_addr_add(int family, int ifindex, void *addr, int prefix)
703 {
704 struct nl_handler nlh;
705 struct nlmsg *nlmsg = NULL, *answer = NULL;
706 struct ip_req *ip_req;
707 int addrlen;
708 int err;
709
710 addrlen = family == AF_INET ? sizeof(struct in_addr) :
711 sizeof(struct in6_addr);
712
713 err = netlink_open(&nlh, NETLINK_ROUTE);
714 if (err)
715 return err;
716
717 err = -ENOMEM;
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
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;
733 ip_req->ifa.ifa_family = family;
734 ip_req->ifa.ifa_scope = 0;
735
736 err = -EINVAL;
737 if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
738 goto out;
739
740 if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
741 goto out;
742
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; */
747
748 err = netlink_transaction(&nlh, nlmsg, answer);
749 out:
750 netlink_close(&nlh);
751 nlmsg_free(answer);
752 nlmsg_free(nlmsg);
753 return err;
754 }
755
756 static int bridge_add_del_interface(const char *bridge,
757 const char *ifname, int detach)
758 {
759 int fd, index, err;
760 struct ifreq ifr;
761
762 if (strlen(ifname) > IFNAMSIZ)
763 return -EINVAL;
764
765 index = if_nametoindex(ifname);
766 if (!index)
767 return -EINVAL;
768
769 fd = socket(AF_INET, SOCK_STREAM, 0);
770 if (fd < 0)
771 return -errno;
772
773 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
774 ifr.ifr_ifindex = index;
775 err = ioctl(fd, detach?SIOCBRDELIF:SIOCBRADDIF, &ifr);
776 close(fd);
777 if (err)
778 err = -errno;
779
780 return err;
781 }
782
783 int lxc_bridge_attach(const char *bridge, const char *ifname)
784 {
785 return bridge_add_del_interface(bridge, ifname, 0);
786 }
787
788 int lxc_bridge_detach(const char *bridge, const char *ifname)
789 {
790 return bridge_add_del_interface(bridge, ifname, 1);
791 }