~ubuntu-branches/ubuntu/oneiric/lxc/oneiric

« back to all changes in this revision

Viewing changes to src/lxc/network.c

  • Committer: Bazaar Package Importer
  • Author(s): Guido Trotter
  • Date: 2009-04-29 17:49:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090429174913-jvahs1ykizqtodje
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

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