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