~serge-hallyn/ubuntu/quantal/lxc/lxc-user-ns

« back to all changes in this revision

Viewing changes to .pc/lxc-use-user-namespace.patch/src/lxc/confile.c

  • Committer: Serge Hallyn
  • Date: 2012-10-29 16:51:57 UTC
  • Revision ID: serge.hallyn@ubuntu.com-20121029165157-xw2nxym7eo0ocxu4
Add user namespaces patch.

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
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <unistd.h>
 
27
#include <errno.h>
 
28
#include <fcntl.h>
 
29
#include <pty.h>
 
30
#include <sys/stat.h>
 
31
#include <sys/types.h>
 
32
#include <sys/param.h>
 
33
#include <sys/utsname.h>
 
34
#include <sys/personality.h>
 
35
#include <arpa/inet.h>
 
36
#include <netinet/in.h>
 
37
#include <net/if.h>
 
38
 
 
39
#include "parse.h"
 
40
#include "confile.h"
 
41
#include "utils.h"
 
42
 
 
43
#include <lxc/log.h>
 
44
#include <lxc/conf.h>
 
45
#include "network.h"
 
46
 
 
47
lxc_log_define(lxc_confile, lxc);
 
48
 
 
49
static int config_personality(const char *, char *, struct lxc_conf *);
 
50
static int config_pts(const char *, char *, struct lxc_conf *);
 
51
static int config_tty(const char *, char *, struct lxc_conf *);
 
52
static int config_ttydir(const char *, char *, struct lxc_conf *);
 
53
static int config_aa_profile(const char *, char *, struct lxc_conf *);
 
54
static int config_cgroup(const char *, char *, struct lxc_conf *);
 
55
static int config_mount(const char *, char *, struct lxc_conf *);
 
56
static int config_rootfs(const char *, char *, struct lxc_conf *);
 
57
static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
 
58
static int config_pivotdir(const char *, char *, struct lxc_conf *);
 
59
static int config_utsname(const char *, char *, struct lxc_conf *);
 
60
static int config_hook(const char *key, char *value, struct lxc_conf *lxc_conf);
 
61
static int config_network_type(const char *, char *, struct lxc_conf *);
 
62
static int config_network_flags(const char *, char *, struct lxc_conf *);
 
63
static int config_network_link(const char *, char *, struct lxc_conf *);
 
64
static int config_network_name(const char *, char *, struct lxc_conf *);
 
65
static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
 
66
static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
 
67
static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
 
68
static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
 
69
static int config_network_mtu(const char *, char *, struct lxc_conf *);
 
70
static int config_network_ipv4(const char *, char *, struct lxc_conf *);
 
71
static int config_network_ipv4_gateway(const char *, char *, struct lxc_conf *);
 
72
static int config_network_script(const char *, char *, struct lxc_conf *);
 
73
static int config_network_ipv6(const char *, char *, struct lxc_conf *);
 
74
static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf *);
 
75
static int config_cap_drop(const char *, char *, struct lxc_conf *);
 
76
static int config_console(const char *, char *, struct lxc_conf *);
 
77
static int config_seccomp(const char *, char *, struct lxc_conf *);
 
78
static int config_includefile(const char *, char *, struct lxc_conf *);
 
79
static int config_network_nic(const char *, char *, struct lxc_conf *);
 
80
 
 
81
typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
 
82
 
 
83
static struct lxc_config_t config[] = {
 
84
 
 
85
        { "lxc.arch",                 config_personality          },
 
86
        { "lxc.pts",                  config_pts                  },
 
87
        { "lxc.tty",                  config_tty                  },
 
88
        { "lxc.devttydir",            config_ttydir               },
 
89
        { "lxc.aa_profile",            config_aa_profile          },
 
90
        { "lxc.cgroup",               config_cgroup               },
 
91
        { "lxc.mount",                config_mount                },
 
92
        { "lxc.rootfs.mount",         config_rootfs_mount         },
 
93
        { "lxc.rootfs",               config_rootfs               },
 
94
        { "lxc.pivotdir",             config_pivotdir             },
 
95
        { "lxc.utsname",              config_utsname              },
 
96
        { "lxc.hook.pre-start",       config_hook                 },
 
97
        { "lxc.hook.pre-mount",       config_hook                 },
 
98
        { "lxc.hook.mount",           config_hook                 },
 
99
        { "lxc.hook.start",           config_hook                 },
 
100
        { "lxc.hook.post-stop",       config_hook                 },
 
101
        { "lxc.network.type",         config_network_type         },
 
102
        { "lxc.network.flags",        config_network_flags        },
 
103
        { "lxc.network.link",         config_network_link         },
 
104
        { "lxc.network.name",         config_network_name         },
 
105
        { "lxc.network.macvlan.mode", config_network_macvlan_mode },
 
106
        { "lxc.network.veth.pair",    config_network_veth_pair    },
 
107
        { "lxc.network.script.up",    config_network_script       },
 
108
        { "lxc.network.hwaddr",       config_network_hwaddr       },
 
109
        { "lxc.network.mtu",          config_network_mtu          },
 
110
        { "lxc.network.vlan.id",      config_network_vlan_id      },
 
111
        { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
 
112
        { "lxc.network.ipv4",         config_network_ipv4         },
 
113
        { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
 
114
        { "lxc.network.ipv6",         config_network_ipv6         },
 
115
        /* config_network_nic must come after all other 'lxc.network.*' entries */
 
116
        { "lxc.network.",             config_network_nic          },
 
117
        { "lxc.cap.drop",             config_cap_drop             },
 
118
        { "lxc.console",              config_console              },
 
119
        { "lxc.seccomp",              config_seccomp              },
 
120
        { "lxc.include",              config_includefile          },
 
121
};
 
122
 
 
123
static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
 
124
 
 
125
extern struct lxc_config_t *lxc_getconfig(const char *key)
 
126
{
 
127
        int i;
 
128
 
 
129
        for (i = 0; i < config_size; i++)
 
130
                if (!strncmp(config[i].name, key,
 
131
                             strlen(config[i].name)))
 
132
                        return &config[i];
 
133
        return NULL;
 
134
}
 
135
 
 
136
#define strprint(str, inlen, ...) \
 
137
        do { \
 
138
                len = snprintf(str, inlen, ##__VA_ARGS__); \
 
139
                if (len < 0) { SYSERROR("snprintf"); return -1; }; \
 
140
                fulllen += len; \
 
141
                if (inlen > 0) { \
 
142
                        if (str) str += len; \
 
143
                        inlen -= len; \
 
144
                        if (inlen < 0) inlen = 0; \
 
145
                } \
 
146
        } while (0);
 
147
 
 
148
int lxc_listconfigs(char *retv, int inlen)
 
149
{
 
150
        int i, fulllen = 0, len;
 
151
 
 
152
        if (!retv)
 
153
                inlen = 0;
 
154
        else
 
155
                memset(retv, 0, inlen);
 
156
        for (i = 0; i < config_size; i++) {
 
157
                char *s = config[i].name;
 
158
                if (s[strlen(s)-1] == '.')
 
159
                        continue;
 
160
                strprint(retv, inlen, "%s\n", s);
 
161
        }
 
162
        return fulllen;
 
163
}
 
164
 
 
165
/*
 
166
 * config entry is something like "lxc.network.0.ipv4"
 
167
 * the key 'lxc.network.' was found.  So we make sure next
 
168
 * comes an integer, find the right callback (by rewriting
 
169
 * the key), and call it.
 
170
 */
 
171
static int config_network_nic(const char *key, char *value,
 
172
                               struct lxc_conf *lxc_conf)
 
173
{
 
174
        char *copy = strdup(key), *p;
 
175
        int ret = -1;
 
176
        struct lxc_config_t *config;
 
177
 
 
178
        if (!copy) {
 
179
                SYSERROR("failed to allocate memory");
 
180
                return -1;
 
181
        }
 
182
        /*
 
183
         * ok we know that to get here we've got "lxc.network."
 
184
         * and it isn't any of the other network entries.  So
 
185
         * after the second . should come an integer (# of defined
 
186
         * nic) followed by a valid entry.
 
187
         */
 
188
        if (*(key+12) < '0' || *(key+12) > '9')
 
189
                goto out;
 
190
        p = index(key+12, '.');
 
191
        if (!p)
 
192
                goto out;
 
193
        strcpy(copy+12, p+1);
 
194
        config = lxc_getconfig(copy);
 
195
        if (!config) {
 
196
                ERROR("unknown key %s", key);
 
197
                goto out;
 
198
        }
 
199
        ret = config->cb(key, value, lxc_conf);
 
200
 
 
201
out:
 
202
        free(copy);
 
203
        return ret;
 
204
}
 
205
 
 
206
static int config_network_type(const char *key, char *value,
 
207
                               struct lxc_conf *lxc_conf)
 
208
{
 
209
        struct lxc_list *network = &lxc_conf->network;
 
210
        struct lxc_netdev *netdev;
 
211
        struct lxc_list *list;
 
212
 
 
213
        netdev = malloc(sizeof(*netdev));
 
214
        if (!netdev) {
 
215
                SYSERROR("failed to allocate memory");
 
216
                return -1;
 
217
        }
 
218
 
 
219
        memset(netdev, 0, sizeof(*netdev));
 
220
        lxc_list_init(&netdev->ipv4);
 
221
        lxc_list_init(&netdev->ipv6);
 
222
 
 
223
        list = malloc(sizeof(*list));
 
224
        if (!list) {
 
225
                SYSERROR("failed to allocate memory");
 
226
                return -1;
 
227
        }
 
228
 
 
229
        lxc_list_init(list);
 
230
        list->elem = netdev;
 
231
 
 
232
        lxc_list_add_tail(network, list);
 
233
 
 
234
        if (!strcmp(value, "veth"))
 
235
                netdev->type = LXC_NET_VETH;
 
236
        else if (!strcmp(value, "macvlan"))
 
237
                netdev->type = LXC_NET_MACVLAN;
 
238
        else if (!strcmp(value, "vlan"))
 
239
                netdev->type = LXC_NET_VLAN;
 
240
        else if (!strcmp(value, "phys"))
 
241
                netdev->type = LXC_NET_PHYS;
 
242
        else if (!strcmp(value, "empty"))
 
243
                netdev->type = LXC_NET_EMPTY;
 
244
        else {
 
245
                ERROR("invalid network type %s", value);
 
246
                return -1;
 
247
        }
 
248
        return 0;
 
249
}
 
250
 
 
251
static int config_ip_prefix(struct in_addr *addr)
 
252
{
 
253
        if (IN_CLASSA(addr->s_addr))
 
254
                return 32 - IN_CLASSA_NSHIFT;
 
255
        if (IN_CLASSB(addr->s_addr))
 
256
                return 32 - IN_CLASSB_NSHIFT;
 
257
        if (IN_CLASSC(addr->s_addr))
 
258
                return 32 - IN_CLASSC_NSHIFT;
 
259
 
 
260
        return 0;
 
261
}
 
262
 
 
263
/*
 
264
 * if you have p="lxc.network.0.link", pass it p+12
 
265
 * to get back '0' (the index of the nic)
 
266
 */
 
267
static int get_network_netdev_idx(const char *key)
 
268
{
 
269
        int ret, idx;
 
270
 
 
271
        if (*key < '0' || *key > '9')
 
272
                return -1;
 
273
        ret = sscanf(key, "%d", &idx);
 
274
        if (ret != 1)
 
275
                return -1;
 
276
        return idx;
 
277
}
 
278
 
 
279
/*
 
280
 * if you have p="lxc.network.0", pass this p+12 and it will return
 
281
 * the netdev of the first configured nic
 
282
 */
 
283
static struct lxc_netdev *get_netdev_from_key(const char *key,
 
284
                                              struct lxc_list *network)
 
285
{
 
286
        int i = 0, idx = get_network_netdev_idx(key);
 
287
        struct lxc_netdev *netdev = NULL;
 
288
        struct lxc_list *it;
 
289
        if (idx == -1)
 
290
                return NULL;
 
291
        lxc_list_for_each(it, network) {
 
292
                if (idx == i++) {
 
293
                        netdev = it->elem;
 
294
                        break;
 
295
                }
 
296
        }
 
297
        return netdev;
 
298
}
 
299
 
 
300
extern int lxc_list_nicconfigs(struct lxc_conf *c, char *key, char *retv, int inlen)
 
301
{
 
302
        struct lxc_netdev *netdev;
 
303
        int fulllen = 0, len;
 
304
 
 
305
        netdev = get_netdev_from_key(key+12, &c->network);
 
306
        if (!netdev)
 
307
                return -1;
 
308
 
 
309
        if (!retv)
 
310
                inlen = 0;
 
311
        else
 
312
                memset(retv, 0, inlen);
 
313
 
 
314
        strprint(retv, inlen, "script.up\n");
 
315
        if (netdev->type != LXC_NET_EMPTY) {
 
316
                strprint(retv, inlen, "flags\n");
 
317
                strprint(retv, inlen, "link\n");
 
318
                strprint(retv, inlen, "name\n");
 
319
                strprint(retv, inlen, "hwaddr\n");
 
320
                strprint(retv, inlen, "mtu\n");
 
321
                strprint(retv, inlen, "ipv6\n");
 
322
                strprint(retv, inlen, "ipv6_gateway\n");
 
323
                strprint(retv, inlen, "ipv4\n");
 
324
                strprint(retv, inlen, "ipv4_gateway\n");
 
325
        }
 
326
        switch(netdev->type) {
 
327
        case LXC_NET_VETH:
 
328
                strprint(retv, inlen, "veth.pair\n");
 
329
                break;
 
330
        case LXC_NET_MACVLAN:
 
331
                strprint(retv, inlen, "macvlan.mode\n");
 
332
                break;
 
333
        case LXC_NET_VLAN:
 
334
                strprint(retv, inlen, "vlan.id\n");
 
335
                break;
 
336
        case LXC_NET_PHYS:
 
337
                break;
 
338
        }
 
339
        return fulllen;
 
340
}
 
341
 
 
342
static struct lxc_netdev *network_netdev(const char *key, const char *value,
 
343
                                         struct lxc_list *network)
 
344
{
 
345
        struct lxc_netdev *netdev = NULL;
 
346
 
 
347
        if (lxc_list_empty(network)) {
 
348
                ERROR("network is not created for '%s' = '%s' option",
 
349
                      key, value);
 
350
                return NULL;
 
351
        }
 
352
 
 
353
        if (get_network_netdev_idx(key+12) == -1)
 
354
                netdev = lxc_list_last_elem(network);
 
355
        else
 
356
                netdev = get_netdev_from_key(key+12, network);
 
357
 
 
358
        if (!netdev) {
 
359
                ERROR("no network device defined for '%s' = '%s' option",
 
360
                      key, value);
 
361
                return NULL;
 
362
        }
 
363
 
 
364
        return netdev;
 
365
}
 
366
 
 
367
static int network_ifname(char **valuep, char *value)
 
368
{
 
369
        if (strlen(value) >= IFNAMSIZ) {
 
370
                ERROR("invalid interface name: %s", value);
 
371
                return -1;
 
372
        }
 
373
 
 
374
        *valuep = strdup(value);
 
375
        if (!*valuep) {
 
376
                ERROR("failed to dup string '%s'", value);
 
377
                return -1;
 
378
        }
 
379
 
 
380
        return 0;
 
381
}
 
382
 
 
383
#ifndef MACVLAN_MODE_PRIVATE
 
384
#  define MACVLAN_MODE_PRIVATE 1
 
385
#endif
 
386
 
 
387
#ifndef MACVLAN_MODE_VEPA
 
388
#  define MACVLAN_MODE_VEPA 2
 
389
#endif
 
390
 
 
391
#ifndef MACVLAN_MODE_BRIDGE
 
392
#  define MACVLAN_MODE_BRIDGE 4
 
393
#endif
 
394
 
 
395
static int macvlan_mode(int *valuep, char *value)
 
396
{
 
397
        struct mc_mode {
 
398
                char *name;
 
399
                int mode;
 
400
        } m[] = {
 
401
                { "private", MACVLAN_MODE_PRIVATE },
 
402
                { "vepa", MACVLAN_MODE_VEPA },
 
403
                { "bridge", MACVLAN_MODE_BRIDGE },
 
404
        };
 
405
 
 
406
        int i;
 
407
 
 
408
        for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
 
409
                if (strcmp(m[i].name, value))
 
410
                        continue;
 
411
 
 
412
                *valuep = m[i].mode;
 
413
                return 0;
 
414
        }
 
415
 
 
416
        return -1;
 
417
}
 
418
 
 
419
static int config_network_flags(const char *key, char *value,
 
420
                                struct lxc_conf *lxc_conf)
 
421
{
 
422
        struct lxc_netdev *netdev;
 
423
 
 
424
        netdev = network_netdev(key, value, &lxc_conf->network);
 
425
        if (!netdev)
 
426
                return -1;
 
427
 
 
428
        netdev->flags |= IFF_UP;
 
429
 
 
430
        return 0;
 
431
}
 
432
 
 
433
static int config_network_link(const char *key, char *value,
 
434
                               struct lxc_conf *lxc_conf)
 
435
{
 
436
        struct lxc_netdev *netdev;
 
437
 
 
438
        netdev = network_netdev(key, value, &lxc_conf->network);
 
439
        if (!netdev)
 
440
                return -1;
 
441
 
 
442
        return network_ifname(&netdev->link, value);
 
443
}
 
444
 
 
445
static int config_network_name(const char *key, char *value,
 
446
                               struct lxc_conf *lxc_conf)
 
447
{
 
448
        struct lxc_netdev *netdev;
 
449
 
 
450
        netdev = network_netdev(key, value, &lxc_conf->network);
 
451
        if (!netdev)
 
452
                return -1;
 
453
 
 
454
        return network_ifname(&netdev->name, value);
 
455
}
 
456
 
 
457
static int config_network_veth_pair(const char *key, char *value,
 
458
                                    struct lxc_conf *lxc_conf)
 
459
{
 
460
        struct lxc_netdev *netdev;
 
461
 
 
462
        netdev = network_netdev(key, value, &lxc_conf->network);
 
463
        if (!netdev)
 
464
                return -1;
 
465
 
 
466
        return network_ifname(&netdev->priv.veth_attr.pair, value);
 
467
}
 
468
 
 
469
static int config_network_macvlan_mode(const char *key, char *value,
 
470
                                       struct lxc_conf *lxc_conf)
 
471
{
 
472
        struct lxc_netdev *netdev;
 
473
 
 
474
        netdev = network_netdev(key, value, &lxc_conf->network);
 
475
        if (!netdev)
 
476
                return -1;
 
477
 
 
478
        return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
 
479
}
 
480
 
 
481
static int config_network_hwaddr(const char *key, char *value,
 
482
                                 struct lxc_conf *lxc_conf)
 
483
{
 
484
        struct lxc_netdev *netdev;
 
485
 
 
486
        netdev = network_netdev(key, value, &lxc_conf->network);
 
487
        if (!netdev)
 
488
                return -1;
 
489
 
 
490
        netdev->hwaddr = strdup(value);
 
491
        if (!netdev->hwaddr) {
 
492
                SYSERROR("failed to dup string '%s'", value);
 
493
                return -1;
 
494
        }
 
495
 
 
496
        return 0;
 
497
}
 
498
 
 
499
static int config_network_vlan_id(const char *key, char *value,
 
500
                               struct lxc_conf *lxc_conf)
 
501
{
 
502
        struct lxc_netdev *netdev;
 
503
 
 
504
        netdev = network_netdev(key, value, &lxc_conf->network);
 
505
        if (!netdev)
 
506
                return -1;
 
507
 
 
508
        if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
 
509
                return -1;
 
510
 
 
511
        return 0;
 
512
}
 
513
 
 
514
static int config_network_mtu(const char *key, char *value,
 
515
                              struct lxc_conf *lxc_conf)
 
516
{
 
517
        struct lxc_netdev *netdev;
 
518
 
 
519
        netdev = network_netdev(key, value, &lxc_conf->network);
 
520
        if (!netdev)
 
521
                return -1;
 
522
 
 
523
        netdev->mtu = strdup(value);
 
524
        if (!netdev->mtu) {
 
525
                SYSERROR("failed to dup string '%s'", value);
 
526
                return -1;
 
527
        }
 
528
 
 
529
        return 0;
 
530
}
 
531
 
 
532
static int config_network_ipv4(const char *key, char *value,
 
533
                               struct lxc_conf *lxc_conf)
 
534
{
 
535
        struct lxc_netdev *netdev;
 
536
        struct lxc_inetdev *inetdev;
 
537
        struct lxc_list *list;
 
538
        char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
 
539
 
 
540
        netdev = network_netdev(key, value, &lxc_conf->network);
 
541
        if (!netdev)
 
542
                return -1;
 
543
 
 
544
        inetdev = malloc(sizeof(*inetdev));
 
545
        if (!inetdev) {
 
546
                SYSERROR("failed to allocate ipv4 address");
 
547
                return -1;
 
548
        }
 
549
        memset(inetdev, 0, sizeof(*inetdev));
 
550
 
 
551
        list = malloc(sizeof(*list));
 
552
        if (!list) {
 
553
                SYSERROR("failed to allocate memory");
 
554
                return -1;
 
555
        }
 
556
 
 
557
        lxc_list_init(list);
 
558
        list->elem = inetdev;
 
559
 
 
560
        addr = value;
 
561
 
 
562
        cursor = strstr(addr, " ");
 
563
        if (cursor) {
 
564
                *cursor = '\0';
 
565
                bcast = cursor + 1;
 
566
        }
 
567
 
 
568
        slash = strstr(addr, "/");
 
569
        if (slash) {
 
570
                *slash = '\0';
 
571
                prefix = slash + 1;
 
572
        }
 
573
 
 
574
        if (!addr) {
 
575
                ERROR("no address specified");
 
576
                return -1;
 
577
        }
 
578
 
 
579
        if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
 
580
                SYSERROR("invalid ipv4 address: %s", value);
 
581
                return -1;
 
582
        }
 
583
 
 
584
        if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
 
585
                SYSERROR("invalid ipv4 broadcast address: %s", value);
 
586
                return -1;
 
587
        }
 
588
 
 
589
        /* no prefix specified, determine it from the network class */
 
590
        inetdev->prefix = prefix ? atoi(prefix) :
 
591
                config_ip_prefix(&inetdev->addr);
 
592
 
 
593
        /* if no broadcast address, let compute one from the
 
594
         * prefix and address
 
595
         */
 
596
        if (!bcast) {
 
597
                inetdev->bcast.s_addr = inetdev->addr.s_addr;
 
598
                inetdev->bcast.s_addr |=
 
599
                        htonl(INADDR_BROADCAST >>  inetdev->prefix);
 
600
        }
 
601
 
 
602
        lxc_list_add(&netdev->ipv4, list);
 
603
 
 
604
        return 0;
 
605
}
 
606
 
 
607
static int config_network_ipv4_gateway(const char *key, char *value,
 
608
                                       struct lxc_conf *lxc_conf)
 
609
{
 
610
        struct lxc_netdev *netdev;
 
611
        struct in_addr *gw;
 
612
 
 
613
        netdev = network_netdev(key, value, &lxc_conf->network);
 
614
        if (!netdev)
 
615
                return -1;
 
616
 
 
617
        gw = malloc(sizeof(*gw));
 
618
        if (!gw) {
 
619
                SYSERROR("failed to allocate ipv4 gateway address");
 
620
                return -1;
 
621
        }
 
622
 
 
623
        if (!value) {
 
624
                ERROR("no ipv4 gateway address specified");
 
625
                return -1;
 
626
        }
 
627
 
 
628
        if (!strcmp(value, "auto")) {
 
629
                netdev->ipv4_gateway = NULL;
 
630
                netdev->ipv4_gateway_auto = true;
 
631
        } else {
 
632
                if (!inet_pton(AF_INET, value, gw)) {
 
633
                        SYSERROR("invalid ipv4 gateway address: %s", value);
 
634
                        return -1;
 
635
                }
 
636
 
 
637
                netdev->ipv4_gateway = gw;
 
638
                netdev->ipv4_gateway_auto = false;
 
639
        }
 
640
 
 
641
        return 0;
 
642
}
 
643
 
 
644
static int config_network_ipv6(const char *key, char *value,
 
645
                               struct lxc_conf *lxc_conf)
 
646
{
 
647
        struct lxc_netdev *netdev;
 
648
        struct lxc_inet6dev *inet6dev;
 
649
        struct lxc_list *list;
 
650
        char *slash;
 
651
        char *netmask;
 
652
 
 
653
        netdev = network_netdev(key, value, &lxc_conf->network);
 
654
        if (!netdev)
 
655
                return -1;
 
656
 
 
657
        inet6dev = malloc(sizeof(*inet6dev));
 
658
        if (!inet6dev) {
 
659
                SYSERROR("failed to allocate ipv6 address");
 
660
                return -1;
 
661
        }
 
662
        memset(inet6dev, 0, sizeof(*inet6dev));
 
663
 
 
664
        list = malloc(sizeof(*list));
 
665
        if (!list) {
 
666
                SYSERROR("failed to allocate memory");
 
667
                return -1;
 
668
        }
 
669
 
 
670
        lxc_list_init(list);
 
671
        list->elem = inet6dev;
 
672
 
 
673
        inet6dev->prefix = 64;
 
674
        slash = strstr(value, "/");
 
675
        if (slash) {
 
676
                *slash = '\0';
 
677
                netmask = slash + 1;
 
678
                inet6dev->prefix = atoi(netmask);
 
679
        }
 
680
 
 
681
        if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
 
682
                SYSERROR("invalid ipv6 address: %s", value);
 
683
                return -1;
 
684
        }
 
685
 
 
686
        lxc_list_add(&netdev->ipv6, list);
 
687
 
 
688
        return 0;
 
689
}
 
690
 
 
691
static int config_network_ipv6_gateway(const char *key, char *value,
 
692
                                       struct lxc_conf *lxc_conf)
 
693
{
 
694
        struct lxc_netdev *netdev;
 
695
        struct in6_addr *gw;
 
696
 
 
697
        netdev = network_netdev(key, value, &lxc_conf->network);
 
698
        if (!netdev)
 
699
                return -1;
 
700
 
 
701
        gw = malloc(sizeof(*gw));
 
702
        if (!gw) {
 
703
                SYSERROR("failed to allocate ipv6 gateway address");
 
704
                return -1;
 
705
        }
 
706
 
 
707
        if (!value) {
 
708
                ERROR("no ipv6 gateway address specified");
 
709
                return -1;
 
710
        }
 
711
 
 
712
        if (!strcmp(value, "auto")) {
 
713
                netdev->ipv6_gateway = NULL;
 
714
                netdev->ipv6_gateway_auto = true;
 
715
        } else {
 
716
                if (!inet_pton(AF_INET6, value, gw)) {
 
717
                        SYSERROR("invalid ipv6 gateway address: %s", value);
 
718
                        return -1;
 
719
                }
 
720
 
 
721
                netdev->ipv6_gateway = gw;
 
722
                netdev->ipv6_gateway_auto = false;
 
723
        }
 
724
 
 
725
        return 0;
 
726
}
 
727
 
 
728
static int config_network_script(const char *key, char *value,
 
729
                                 struct lxc_conf *lxc_conf)
 
730
{
 
731
        struct lxc_netdev *netdev;
 
732
 
 
733
        netdev = network_netdev(key, value, &lxc_conf->network);
 
734
        if (!netdev)
 
735
        return -1;
 
736
 
 
737
        char *copy = strdup(value);
 
738
        if (!copy) {
 
739
                SYSERROR("failed to dup string '%s'", value);
 
740
                return -1;
 
741
        }
 
742
        if (strstr(key, "script.up") != NULL) {
 
743
                netdev->upscript = copy;
 
744
                return 0;
 
745
        }
 
746
        SYSERROR("Unknown key: %s", key);
 
747
        free(copy);
 
748
        return -1;
 
749
}
 
750
 
 
751
static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
 
752
{
 
753
        struct lxc_list *hooklist;
 
754
 
 
755
        hooklist = malloc(sizeof(*hooklist));
 
756
        if (!hooklist) {
 
757
                free(hook);
 
758
                return -1;
 
759
        }
 
760
        hooklist->elem = hook;
 
761
        lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
 
762
        return 0;
 
763
}
 
764
 
 
765
static int config_seccomp(const char *key, char *value,
 
766
                                 struct lxc_conf *lxc_conf)
 
767
{
 
768
        char *path;
 
769
 
 
770
        if (lxc_conf->seccomp) {
 
771
                ERROR("seccomp already defined");
 
772
                return -1;
 
773
        }
 
774
        path = strdup(value);
 
775
        if (!path) {
 
776
                SYSERROR("failed to strdup '%s': %m", value);
 
777
                return -1;
 
778
        }
 
779
 
 
780
        lxc_conf->seccomp = path;
 
781
 
 
782
        return 0;
 
783
}
 
784
 
 
785
static int config_hook(const char *key, char *value,
 
786
                                 struct lxc_conf *lxc_conf)
 
787
{
 
788
        char *copy = strdup(value);
 
789
        if (!copy) {
 
790
                SYSERROR("failed to dup string '%s'", value);
 
791
                return -1;
 
792
        }
 
793
        if (strcmp(key, "lxc.hook.pre-start") == 0)
 
794
                return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
 
795
        else if (strcmp(key, "lxc.hook.pre-mount") == 0)
 
796
                return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
 
797
        else if (strcmp(key, "lxc.hook.mount") == 0)
 
798
                return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
 
799
        else if (strcmp(key, "lxc.hook.start") == 0)
 
800
                return add_hook(lxc_conf, LXCHOOK_START, copy);
 
801
        else if (strcmp(key, "lxc.hook.post-stop") == 0)
 
802
                return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
 
803
        SYSERROR("Unknown key: %s", key);
 
804
        free(copy);
 
805
        return -1;
 
806
}
 
807
 
 
808
static int config_personality(const char *key, char *value,
 
809
                              struct lxc_conf *lxc_conf)
 
810
{
 
811
        signed long personality = lxc_config_parse_arch(value);
 
812
 
 
813
        if (personality >= 0)
 
814
                lxc_conf->personality = personality;
 
815
        else
 
816
                WARN("unsupported personality '%s'", value);
 
817
 
 
818
        return 0;
 
819
}
 
820
 
 
821
static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
 
822
{
 
823
        int maxpts = atoi(value);
 
824
 
 
825
        lxc_conf->pts = maxpts;
 
826
 
 
827
        return 0;
 
828
}
 
829
 
 
830
static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
 
831
{
 
832
        int nbtty = atoi(value);
 
833
 
 
834
        lxc_conf->tty = nbtty;
 
835
 
 
836
        return 0;
 
837
}
 
838
 
 
839
static int config_ttydir(const char *key, char *value,
 
840
                          struct lxc_conf *lxc_conf)
 
841
{
 
842
        char *path;
 
843
 
 
844
        if (!value || strlen(value) == 0)
 
845
                return 0;
 
846
        path = strdup(value);
 
847
        if (!path) {
 
848
                SYSERROR("failed to strdup '%s': %m", value);
 
849
                return -1;
 
850
        }
 
851
 
 
852
        lxc_conf->ttydir = path;
 
853
 
 
854
        return 0;
 
855
}
 
856
 
 
857
static int config_aa_profile(const char *key, char *value,
 
858
                          struct lxc_conf *lxc_conf)
 
859
{
 
860
        char *path;
 
861
 
 
862
        if (!value || strlen(value) == 0)
 
863
                return 0;
 
864
        path = strdup(value);
 
865
        if (!path) {
 
866
                SYSERROR("failed to strdup '%s': %m", value);
 
867
                return -1;
 
868
        }
 
869
 
 
870
        lxc_conf->aa_profile = path;
 
871
 
 
872
        return 0;
 
873
}
 
874
 
 
875
static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
 
876
{
 
877
        char *token = "lxc.cgroup.";
 
878
        char *subkey;
 
879
        struct lxc_list *cglist = NULL;
 
880
        struct lxc_cgroup *cgelem = NULL;
 
881
 
 
882
        subkey = strstr(key, token);
 
883
 
 
884
        if (!subkey)
 
885
                return -1;
 
886
 
 
887
        if (!strlen(subkey))
 
888
                return -1;
 
889
 
 
890
        if (strlen(subkey) == strlen(token))
 
891
                return -1;
 
892
 
 
893
        subkey += strlen(token);
 
894
 
 
895
        cglist = malloc(sizeof(*cglist));
 
896
        if (!cglist)
 
897
                goto out;
 
898
 
 
899
        cgelem = malloc(sizeof(*cgelem));
 
900
        if (!cgelem)
 
901
                goto out;
 
902
        memset(cgelem, 0, sizeof(*cgelem));
 
903
 
 
904
        cgelem->subsystem = strdup(subkey);
 
905
        cgelem->value = strdup(value);
 
906
 
 
907
        if (!cgelem->subsystem || !cgelem->value)
 
908
                goto out;
 
909
 
 
910
        cglist->elem = cgelem;
 
911
 
 
912
        lxc_list_add_tail(&lxc_conf->cgroup, cglist);
 
913
 
 
914
        return 0;
 
915
 
 
916
out:
 
917
        if (cglist)
 
918
                free(cglist);
 
919
 
 
920
        if (cgelem) {
 
921
                if (cgelem->subsystem)
 
922
                        free(cgelem->subsystem);
 
923
 
 
924
                if (cgelem->value)
 
925
                        free(cgelem->value);
 
926
 
 
927
                free(cgelem);
 
928
        }
 
929
 
 
930
        return -1;
 
931
}
 
932
 
 
933
static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
 
934
{
 
935
        if (strlen(value) >= MAXPATHLEN) {
 
936
                ERROR("%s path is too long", value);
 
937
                return -1;
 
938
        }
 
939
 
 
940
        lxc_conf->fstab = strdup(value);
 
941
        if (!lxc_conf->fstab) {
 
942
                SYSERROR("failed to duplicate string %s", value);
 
943
                return -1;
 
944
        }
 
945
 
 
946
        return 0;
 
947
}
 
948
 
 
949
static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
 
950
{
 
951
        char *fstab_token = "lxc.mount";
 
952
        char *token = "lxc.mount.entry";
 
953
        char *subkey;
 
954
        char *mntelem;
 
955
        struct lxc_list *mntlist;
 
956
 
 
957
        subkey = strstr(key, token);
 
958
 
 
959
        if (!subkey) {
 
960
                subkey = strstr(key, fstab_token);
 
961
 
 
962
                if (!subkey)
 
963
                        return -1;
 
964
 
 
965
                return config_fstab(key, value, lxc_conf);
 
966
        }
 
967
 
 
968
        if (!strlen(subkey))
 
969
                return -1;
 
970
 
 
971
        mntlist = malloc(sizeof(*mntlist));
 
972
        if (!mntlist)
 
973
                return -1;
 
974
 
 
975
        mntelem = strdup(value);
 
976
        if (!mntelem)
 
977
                return -1;
 
978
        mntlist->elem = mntelem;
 
979
 
 
980
        lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
 
981
 
 
982
        return 0;
 
983
}
 
984
 
 
985
static int config_cap_drop(const char *key, char *value,
 
986
                           struct lxc_conf *lxc_conf)
 
987
{
 
988
        char *dropcaps, *sptr, *token;
 
989
        struct lxc_list *droplist;
 
990
        int ret = -1;
 
991
 
 
992
        if (!strlen(value))
 
993
                return -1;
 
994
 
 
995
        dropcaps = strdup(value);
 
996
        if (!dropcaps) {
 
997
                SYSERROR("failed to dup '%s'", value);
 
998
                return -1;
 
999
        }
 
1000
 
 
1001
        /* in case several capability drop is specified in a single line
 
1002
         * split these caps in a single element for the list */
 
1003
        for (;;) {
 
1004
                token = strtok_r(dropcaps, " \t", &sptr);
 
1005
                if (!token) {
 
1006
                        ret = 0;
 
1007
                        break;
 
1008
                }
 
1009
                dropcaps = NULL;
 
1010
 
 
1011
                droplist = malloc(sizeof(*droplist));
 
1012
                if (!droplist) {
 
1013
                        SYSERROR("failed to allocate drop list");
 
1014
                        break;
 
1015
                }
 
1016
 
 
1017
                /* note - i do believe we're losing memory here,
 
1018
                   note that token is already pointing into dropcaps
 
1019
                   which is strdup'd.  we never free that bit.
 
1020
                 */
 
1021
                droplist->elem = strdup(token);
 
1022
                if (!droplist->elem) {
 
1023
                        SYSERROR("failed to dup '%s'", token);
 
1024
                        free(droplist);
 
1025
                        break;
 
1026
                }
 
1027
 
 
1028
                lxc_list_add_tail(&lxc_conf->caps, droplist);
 
1029
        }
 
1030
 
 
1031
        free(dropcaps);
 
1032
 
 
1033
        return ret;
 
1034
}
 
1035
 
 
1036
static int config_console(const char *key, char *value,
 
1037
                          struct lxc_conf *lxc_conf)
 
1038
{
 
1039
        char *path;
 
1040
 
 
1041
        path = strdup(value);
 
1042
        if (!path) {
 
1043
                SYSERROR("failed to strdup '%s': %m", value);
 
1044
                return -1;
 
1045
        }
 
1046
 
 
1047
        lxc_conf->console.path = path;
 
1048
 
 
1049
        return 0;
 
1050
}
 
1051
 
 
1052
static int config_includefile(const char *key, char *value,
 
1053
                          struct lxc_conf *lxc_conf)
 
1054
{
 
1055
        return lxc_config_read(value, lxc_conf);
 
1056
}
 
1057
 
 
1058
static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
 
1059
{
 
1060
        if (strlen(value) >= MAXPATHLEN) {
 
1061
                ERROR("%s path is too long", value);
 
1062
                return -1;
 
1063
        }
 
1064
 
 
1065
        lxc_conf->rootfs.path = strdup(value);
 
1066
        if (!lxc_conf->rootfs.path) {
 
1067
                SYSERROR("failed to duplicate string %s", value);
 
1068
                return -1;
 
1069
        }
 
1070
 
 
1071
        return 0;
 
1072
}
 
1073
 
 
1074
static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
 
1075
{
 
1076
        if (strlen(value) >= MAXPATHLEN) {
 
1077
                ERROR("%s path is too long", value);
 
1078
                return -1;
 
1079
        }
 
1080
 
 
1081
        lxc_conf->rootfs.mount = strdup(value);
 
1082
        if (!lxc_conf->rootfs.mount) {
 
1083
                SYSERROR("failed to duplicate string '%s'", value);
 
1084
                return -1;
 
1085
        }
 
1086
 
 
1087
        return 0;
 
1088
}
 
1089
 
 
1090
static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
 
1091
{
 
1092
        if (strlen(value) >= MAXPATHLEN) {
 
1093
                ERROR("%s path is too long", value);
 
1094
                return -1;
 
1095
        }
 
1096
 
 
1097
        lxc_conf->rootfs.pivot = strdup(value);
 
1098
        if (!lxc_conf->rootfs.pivot) {
 
1099
                SYSERROR("failed to duplicate string %s", value);
 
1100
                return -1;
 
1101
        }
 
1102
 
 
1103
        return 0;
 
1104
}
 
1105
 
 
1106
static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
 
1107
{
 
1108
        struct utsname *utsname;
 
1109
 
 
1110
        utsname = malloc(sizeof(*utsname));
 
1111
        if (!utsname) {
 
1112
                SYSERROR("failed to allocate memory");
 
1113
                return -1;
 
1114
        }
 
1115
 
 
1116
        if (strlen(value) >= sizeof(utsname->nodename)) {
 
1117
                ERROR("node name '%s' is too long",
 
1118
                              utsname->nodename);
 
1119
                return -1;
 
1120
        }
 
1121
 
 
1122
        strcpy(utsname->nodename, value);
 
1123
        lxc_conf->utsname = utsname;
 
1124
 
 
1125
        return 0;
 
1126
}
 
1127
 
 
1128
static int parse_line(char *buffer, void *data)
 
1129
{
 
1130
        struct lxc_config_t *config;
 
1131
        char *line, *linep;
 
1132
        char *dot;
 
1133
        char *key;
 
1134
        char *value;
 
1135
        int ret = 0;
 
1136
 
 
1137
        if (lxc_is_line_empty(buffer))
 
1138
                return 0;
 
1139
 
 
1140
        /* we have to dup the buffer otherwise, at the re-exec for
 
1141
         * reboot we modified the original string on the stack by
 
1142
         * replacing '=' by '\0' below
 
1143
         */
 
1144
        linep = line = strdup(buffer);
 
1145
        if (!line) {
 
1146
                SYSERROR("failed to allocate memory for '%s'", buffer);
 
1147
                return -1;
 
1148
        }
 
1149
 
 
1150
        line += lxc_char_left_gc(line, strlen(line));
 
1151
 
 
1152
        /* martian option - ignoring it, the commented lines beginning by '#'
 
1153
         * fall in this case
 
1154
         */
 
1155
        if (strncmp(line, "lxc.", 4))
 
1156
                goto out;
 
1157
 
 
1158
        ret = -1;
 
1159
 
 
1160
        dot = strstr(line, "=");
 
1161
        if (!dot) {
 
1162
                ERROR("invalid configuration line: %s", line);
 
1163
                goto out;
 
1164
        }
 
1165
 
 
1166
        *dot = '\0';
 
1167
        value = dot + 1;
 
1168
 
 
1169
        key = line;
 
1170
        key[lxc_char_right_gc(key, strlen(key))] = '\0';
 
1171
 
 
1172
        value += lxc_char_left_gc(value, strlen(value));
 
1173
        value[lxc_char_right_gc(value, strlen(value))] = '\0';
 
1174
 
 
1175
        config = lxc_getconfig(key);
 
1176
        if (!config) {
 
1177
                ERROR("unknown key %s", key);
 
1178
                goto out;
 
1179
        }
 
1180
 
 
1181
        ret = config->cb(key, value, data);
 
1182
 
 
1183
out:
 
1184
        free(linep);
 
1185
        return ret;
 
1186
}
 
1187
 
 
1188
int lxc_config_readline(char *buffer, struct lxc_conf *conf)
 
1189
{
 
1190
        return parse_line(buffer, conf);
 
1191
}
 
1192
 
 
1193
int lxc_config_read(const char *file, struct lxc_conf *conf)
 
1194
{
 
1195
        return lxc_file_for_each_line(file, parse_line, conf);
 
1196
}
 
1197
 
 
1198
int lxc_config_define_add(struct lxc_list *defines, char* arg)
 
1199
{
 
1200
        struct lxc_list *dent;
 
1201
 
 
1202
        dent = malloc(sizeof(struct lxc_list));
 
1203
        if (!dent)
 
1204
                return -1;
 
1205
 
 
1206
        dent->elem = arg;
 
1207
        lxc_list_add_tail(defines, dent);
 
1208
        return 0;
 
1209
}
 
1210
 
 
1211
int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
 
1212
{
 
1213
        struct lxc_list *it;
 
1214
        int ret = 0;
 
1215
 
 
1216
        lxc_list_for_each(it, defines) {
 
1217
                ret = lxc_config_readline(it->elem, conf);
 
1218
                if (ret)
 
1219
                        break;
 
1220
        }
 
1221
 
 
1222
        lxc_list_for_each(it, defines) {
 
1223
                lxc_list_del(it);
 
1224
                free(it);
 
1225
        }
 
1226
 
 
1227
        return ret;
 
1228
}
 
1229
 
 
1230
signed long lxc_config_parse_arch(const char *arch)
 
1231
{
 
1232
        struct per_name {
 
1233
                char *name;
 
1234
                unsigned long per;
 
1235
        } pername[4] = {
 
1236
                { "x86", PER_LINUX32 },
 
1237
                { "i686", PER_LINUX32 },
 
1238
                { "x86_64", PER_LINUX },
 
1239
                { "amd64", PER_LINUX },
 
1240
        };
 
1241
        size_t len = sizeof(pername) / sizeof(pername[0]);
 
1242
 
 
1243
        int i;
 
1244
 
 
1245
        for (i = 0; i < len; i++) {
 
1246
                if (!strcmp(pername[i].name, arch))
 
1247
                    return pername[i].per;
 
1248
        }
 
1249
 
 
1250
        return -1;
 
1251
}
 
1252
 
 
1253
static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
 
1254
{
 
1255
        if (!retv)
 
1256
                inlen = 0;
 
1257
        else
 
1258
                memset(retv, 0, inlen);
 
1259
        return snprintf(retv, inlen, "%d", v);
 
1260
}
 
1261
 
 
1262
static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
 
1263
{
 
1264
        int len, fulllen = 0;
 
1265
 
 
1266
        if (!retv)
 
1267
                inlen = 0;
 
1268
        else
 
1269
                memset(retv, 0, inlen);
 
1270
 
 
1271
        switch(c->personality) {
 
1272
        case PER_LINUX32: strprint(retv, inlen, "x86"); break;
 
1273
        case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
 
1274
        default: break;
 
1275
        }
 
1276
 
 
1277
        return fulllen;
 
1278
}
 
1279
 
 
1280
/*
 
1281
 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
 
1282
 * then just the value(s) will be printed.  Since there still could be
 
1283
 * more than one, it is newline-separated.
 
1284
 * (Maybe that's ambigous, since some values, i.e. devices.list, will
 
1285
 * already have newlines?)
 
1286
 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
 
1287
 * in 'lxc.cgroup.subsystem.key = value' format.
 
1288
 */
 
1289
static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen, char *key)
 
1290
{
 
1291
        int fulllen = 0, len;
 
1292
        int all = 0;
 
1293
        struct lxc_list *it;
 
1294
 
 
1295
        if (!retv)
 
1296
                inlen = 0;
 
1297
        else
 
1298
                memset(retv, 0, inlen);
 
1299
 
 
1300
        if (strcmp(key, "all") == 0)
 
1301
                all = 1;
 
1302
 
 
1303
        lxc_list_for_each(it, &c->cgroup) {
 
1304
                struct lxc_cgroup *cg = it->elem;
 
1305
                if (all) {
 
1306
                        strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
 
1307
                } else if (strcmp(cg->subsystem, key) == 0) {
 
1308
                        strprint(retv, inlen, "%s\n", cg->value);
 
1309
                }
 
1310
        }
 
1311
        return fulllen;
 
1312
}
 
1313
 
 
1314
static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen, char *key)
 
1315
{
 
1316
        char *subkey;
 
1317
        int len, fulllen = 0, found = -1;
 
1318
        struct lxc_list *it;
 
1319
        int i;
 
1320
 
 
1321
        /* "lxc.hook.mount" */
 
1322
        subkey = index(key, '.');
 
1323
        if (subkey) subkey = index(subkey+1, '.');
 
1324
        if (!subkey)
 
1325
                return -1;
 
1326
        subkey++;
 
1327
        if (!*subkey)
 
1328
                return -1;
 
1329
        for (i=0; i<NUM_LXC_HOOKS; i++) {
 
1330
                if (strcmp(lxchook_names[i], subkey) == 0) {
 
1331
                        found=i;
 
1332
                        break;
 
1333
                }
 
1334
        }
 
1335
        if (found == -1)
 
1336
                return -1;
 
1337
 
 
1338
        if (!retv)
 
1339
                inlen = 0;
 
1340
        else
 
1341
                memset(retv, 0, inlen);
 
1342
 
 
1343
        lxc_list_for_each(it, &c->hooks[found]) {
 
1344
                strprint(retv, inlen, "%s\n", (char *)it->elem);
 
1345
        }
 
1346
        return fulllen;
 
1347
}
 
1348
 
 
1349
static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
 
1350
{
 
1351
        int len, fulllen = 0;
 
1352
        struct lxc_list *it;
 
1353
 
 
1354
        if (!retv)
 
1355
                inlen = 0;
 
1356
        else
 
1357
                memset(retv, 0, inlen);
 
1358
 
 
1359
        lxc_list_for_each(it, &c->caps) {
 
1360
                strprint(retv, inlen, "%s\n", (char *)it->elem);
 
1361
        }
 
1362
        return fulllen;
 
1363
}
 
1364
 
 
1365
static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
 
1366
{
 
1367
        int len, fulllen = 0;
 
1368
        struct lxc_list *it;
 
1369
 
 
1370
        if (!retv)
 
1371
                inlen = 0;
 
1372
        else
 
1373
                memset(retv, 0, inlen);
 
1374
 
 
1375
        lxc_list_for_each(it, &c->mount_list) {
 
1376
                strprint(retv, inlen, "%s\n", (char *)it->elem);
 
1377
        }
 
1378
        return fulllen;
 
1379
}
 
1380
 
 
1381
/*
 
1382
 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
 
1383
 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
 
1384
 * ipv4_gateway, ipv6_gateway.  ipvX_gateway can return 'auto' instead
 
1385
 * of an address.  ipv4 and ipv6 return lists (newline-separated).
 
1386
 * things like veth.pair return '' if invalid (i.e. if called for vlan
 
1387
 * type).
 
1388
 */
 
1389
static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen, char *key)
 
1390
{
 
1391
        char *p1;
 
1392
        int len, fulllen = 0;
 
1393
        struct lxc_netdev *netdev;
 
1394
 
 
1395
        if (!retv)
 
1396
                inlen = 0;
 
1397
        else
 
1398
                memset(retv, 0, inlen);
 
1399
 
 
1400
        p1 = index(key, '.');
 
1401
        if (!p1 || *(p1+1) == '\0') return -1;
 
1402
        p1++;
 
1403
 
 
1404
        netdev = get_netdev_from_key(key, &c->network);
 
1405
        if (!netdev)
 
1406
                return -1;
 
1407
        if (strcmp(p1, "name") == 0) {
 
1408
                if (netdev->name)
 
1409
                        strprint(retv, inlen, "%s", netdev->name);
 
1410
        } else if (strcmp(p1, "type") == 0) {
 
1411
                strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
 
1412
        } else if (strcmp(p1, "link") == 0) {
 
1413
                if (netdev->link)
 
1414
                        strprint(retv, inlen, "%s", netdev->link);
 
1415
        } else if (strcmp(p1, "flags") == 0) {
 
1416
                if (netdev->flags & IFF_UP)
 
1417
                        strprint(retv, inlen, "up");
 
1418
        } else if (strcmp(p1, "upscript") == 0) {
 
1419
                if (netdev->upscript)
 
1420
                        strprint(retv, inlen, "%s", netdev->upscript);
 
1421
        } else if (strcmp(p1, "hwaddr") == 0) {
 
1422
                if (netdev->hwaddr)
 
1423
                        strprint(retv, inlen, "%s", netdev->hwaddr);
 
1424
        } else if (strcmp(p1, "mtu") == 0) {
 
1425
                if (netdev->mtu)
 
1426
                        strprint(retv, inlen, "%s", netdev->mtu);
 
1427
        } else if (strcmp(p1, "macvlan.mode") == 0) {
 
1428
                if (netdev->type == LXC_NET_MACVLAN) {
 
1429
                        const char *mode;
 
1430
                        switch (netdev->priv.macvlan_attr.mode) {
 
1431
                        case MACVLAN_MODE_PRIVATE: mode = "private"; break;
 
1432
                        case MACVLAN_MODE_VEPA: mode = "vepa"; break;
 
1433
                        case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
 
1434
                        default: mode = "(invalid)"; break;
 
1435
                        }
 
1436
                        strprint(retv, inlen, "%s", mode);
 
1437
                }
 
1438
        } else if (strcmp(p1, "veth.pair") == 0) {
 
1439
                if (netdev->type == LXC_NET_VETH && netdev->priv.veth_attr.pair)
 
1440
                        strprint(retv, inlen, "%s", netdev->priv.veth_attr.pair);
 
1441
        } else if (strcmp(p1, "vlan") == 0) {
 
1442
                if (netdev->type == LXC_NET_VLAN) {
 
1443
                        strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
 
1444
                }
 
1445
        } else if (strcmp(p1, "ipv4_gateway") == 0) {
 
1446
                if (netdev->ipv4_gateway_auto) {
 
1447
                        strprint(retv, inlen, "auto");
 
1448
                } else if (netdev->ipv4_gateway) {
 
1449
                        char buf[INET_ADDRSTRLEN];
 
1450
                        inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
 
1451
                        strprint(retv, inlen, "%s", buf);
 
1452
                }
 
1453
        } else if (strcmp(p1, "ipv4") == 0) {
 
1454
                struct lxc_list *it2;
 
1455
                lxc_list_for_each(it2, &netdev->ipv4) {
 
1456
                        struct lxc_inetdev *i = it2->elem;
 
1457
                        char buf[INET_ADDRSTRLEN];
 
1458
                        inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
 
1459
                        strprint(retv, inlen, "%s\n", buf);
 
1460
                }
 
1461
        } else if (strcmp(p1, "ipv6_gateway") == 0) {
 
1462
                if (netdev->ipv6_gateway_auto) {
 
1463
                        strprint(retv, inlen, "auto");
 
1464
                } else if (netdev->ipv6_gateway) {
 
1465
                        char buf[INET_ADDRSTRLEN];
 
1466
                        inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
 
1467
                        strprint(retv, inlen, "%s", buf);
 
1468
                }
 
1469
        } else if (strcmp(p1, "ipv6") == 0) {
 
1470
                struct lxc_list *it2;
 
1471
                lxc_list_for_each(it2, &netdev->ipv6) {
 
1472
                        struct lxc_inetdev *i = it2->elem;
 
1473
                        char buf[INET_ADDRSTRLEN];
 
1474
                        inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
 
1475
                        strprint(retv, inlen, "%s\n", buf);
 
1476
                }
 
1477
        }
 
1478
        return fulllen;
 
1479
}
 
1480
 
 
1481
static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
 
1482
{
 
1483
        int len, fulllen = 0;
 
1484
        struct lxc_list *it;
 
1485
 
 
1486
        if (!retv)
 
1487
                inlen = 0;
 
1488
        else
 
1489
                memset(retv, 0, inlen);
 
1490
 
 
1491
        lxc_list_for_each(it, &c->network) {
 
1492
                struct lxc_netdev *n = it->elem;
 
1493
                const char *t = lxc_net_type_to_str(n->type);
 
1494
                strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
 
1495
        }
 
1496
        return fulllen;
 
1497
}
 
1498
 
 
1499
int lxc_get_config_item(struct lxc_conf *c, char *key, char *retv, int inlen)
 
1500
{
 
1501
        char *v = NULL;
 
1502
 
 
1503
        if (strcmp(key, "lxc.mount.entry") == 0)
 
1504
                return lxc_get_mount_entries(c, retv, inlen);
 
1505
        else if (strcmp(key, "lxc.mount") == 0)
 
1506
                v = c->fstab;
 
1507
        else if (strcmp(key, "lxc.tty") == 0)
 
1508
                return lxc_get_conf_int(c, retv, inlen, c->tty);
 
1509
        else if (strcmp(key, "lxc.pts") == 0)
 
1510
                return lxc_get_conf_int(c, retv, inlen, c->pts);
 
1511
        else if (strcmp(key, "lxc.devttydir") == 0)
 
1512
                v = c->ttydir;
 
1513
        else if (strcmp(key, "lxc.arch") == 0)
 
1514
                return lxc_get_arch_entry(c, retv, inlen);
 
1515
        else if (strcmp(key, "lxc.aa_profile") == 0)
 
1516
                v = c->aa_profile;
 
1517
        else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
 
1518
                return lxc_get_cgroup_entry(c, retv, inlen, "all");
 
1519
        else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
 
1520
                return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
 
1521
        else if (strcmp(key, "lxc.utsname") == 0)
 
1522
                v = c->utsname ? c->utsname->nodename : NULL;
 
1523
        else if (strcmp(key, "lxc.console") == 0)
 
1524
                v = c->console.path;
 
1525
        else if (strcmp(key, "lxc.rootfs.mount") == 0)
 
1526
                v = c->rootfs.mount;
 
1527
        else if (strcmp(key, "lxc.rootfs") == 0)
 
1528
                v = c->rootfs.path;
 
1529
        else if (strcmp(key, "lxc.pivotdir") == 0)
 
1530
                v = c->rootfs.pivot;
 
1531
        else if (strcmp(key, "lxc.cap.drop") == 0)
 
1532
                return lxc_get_item_cap_drop(c, retv, inlen);
 
1533
        else if (strncmp(key, "lxc.hook", 8) == 0)
 
1534
                return lxc_get_item_hooks(c, retv, inlen, key);
 
1535
        else if (strcmp(key, "lxc.network") == 0)
 
1536
                return lxc_get_item_network(c, retv, inlen);
 
1537
        else if (strncmp(key, "lxc.network.", 12) == 0)
 
1538
                return lxc_get_item_nic(c, retv, inlen, key + 12);
 
1539
        else return -1;
 
1540
 
 
1541
        if (!v)
 
1542
                return 0;
 
1543
        if (retv && inlen >= strlen(v) + 1)
 
1544
                strncpy(retv, v, strlen(v)+1);
 
1545
        return strlen(v);
 
1546
}
 
1547
 
 
1548
int lxc_clear_config_item(struct lxc_conf *c, char *key)
 
1549
{
 
1550
        if (strcmp(key, "lxc.network") == 0)
 
1551
                return lxc_clear_config_network(c);
 
1552
        else if (strncmp(key, "lxc.network.", 12) == 0)
 
1553
                return lxc_clear_nic(c, key + 12);
 
1554
        else if (strcmp(key, "lxc.cap.drop") == 0)
 
1555
                return lxc_clear_config_caps(c);
 
1556
        else if (strncmp(key, "lxc.cgroup", 10) == 0)
 
1557
                return lxc_clear_cgroups(c, key);
 
1558
        else if (strcmp(key, "lxc.mount.entries") == 0)
 
1559
                return lxc_clear_mount_entries(c);
 
1560
        else if (strncmp(key, "lxc.hook", 8) == 0)
 
1561
                return lxc_clear_hooks(c, key);
 
1562
 
 
1563
        return -1;
 
1564
}
 
1565
 
 
1566
/*
 
1567
 * writing out a confile.
 
1568
 */
 
1569
void write_config(FILE *fout, struct lxc_conf *c)
 
1570
{
 
1571
        struct lxc_list *it;
 
1572
        int i;
 
1573
 
 
1574
        if (c->fstab)
 
1575
                fprintf(fout, "lxc.mount = %s\n", c->fstab);
 
1576
        lxc_list_for_each(it, &c->mount_list) {
 
1577
                fprintf(fout, "lxc.mount.entry = %s\n", (char *)it->elem);
 
1578
        }
 
1579
        if (c->tty)
 
1580
                fprintf(fout, "lxc.tty = %d\n", c->tty);
 
1581
        if (c->pts)
 
1582
                fprintf(fout, "lxc.pts = %d\n", c->pts);
 
1583
        if (c->ttydir)
 
1584
                fprintf(fout, "lxc.devttydir = %s\n", c->ttydir);
 
1585
        switch(c->personality) {
 
1586
        case PER_LINUX32: fprintf(fout, "lxc.arch = x86\n"); break;
 
1587
        case PER_LINUX: fprintf(fout, "lxc.arch = x86_64\n"); break;
 
1588
        default: break;
 
1589
        }
 
1590
        if (c->aa_profile)
 
1591
                fprintf(fout, "lxc.aa_profile = %s\n", c->aa_profile);
 
1592
        lxc_list_for_each(it, &c->cgroup) {
 
1593
                struct lxc_cgroup *cg = it->elem;
 
1594
                fprintf(fout, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
 
1595
        }
 
1596
        if (c->utsname)
 
1597
                fprintf(fout, "lxc.utsname = %s\n", c->utsname->nodename);
 
1598
        lxc_list_for_each(it, &c->network) {
 
1599
                struct lxc_netdev *n = it->elem;
 
1600
                const char *t = lxc_net_type_to_str(n->type);
 
1601
                struct lxc_list *it2;
 
1602
                fprintf(fout, "lxc.network.type = %s\n", t ? t : "(invalid)");
 
1603
                if (n->flags & IFF_UP)
 
1604
                        fprintf(fout, "lxc.network.flags = up\n");
 
1605
                if (n->link)
 
1606
                        fprintf(fout, "lxc.network.link = %s\n", n->link);
 
1607
                if (n->name)
 
1608
                        fprintf(fout, "lxc.network.name = %s\n", n->name);
 
1609
                if (n->type == LXC_NET_MACVLAN) {
 
1610
                        const char *mode;
 
1611
                        switch (n->priv.macvlan_attr.mode) {
 
1612
                        case MACVLAN_MODE_PRIVATE: mode = "private"; break;
 
1613
                        case MACVLAN_MODE_VEPA: mode = "vepa"; break;
 
1614
                        case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
 
1615
                        default: mode = "(invalid)"; break;
 
1616
                        }
 
1617
                        fprintf(fout, "lxc.network.macvlan.mode = %s\n", mode);
 
1618
                } else if (n->type == LXC_NET_VETH) {
 
1619
                        if (n->priv.veth_attr.pair)
 
1620
                                fprintf(fout, "lxc.network.veth.pair = %s\n",
 
1621
                                        n->priv.veth_attr.pair);
 
1622
                } else if (n->type == LXC_NET_VLAN) {
 
1623
                        fprintf(fout, "lxc.network.vlan.id = %d\n", n->priv.vlan_attr.vid);
 
1624
                }
 
1625
                if (n->upscript)
 
1626
                        fprintf(fout, "lxc.network.script.up = %s\n", n->upscript);
 
1627
                if (n->hwaddr)
 
1628
                        fprintf(fout, "lxc.network.hwaddr = %s\n", n->hwaddr);
 
1629
                if (n->mtu)
 
1630
                        fprintf(fout, "lxc.network.mtu = %s\n", n->mtu);
 
1631
                if (n->ipv4_gateway_auto)
 
1632
                        fprintf(fout, "lxc.network.ipv4.gateway = auto\n");
 
1633
                else if (n->ipv4_gateway) {
 
1634
                        char buf[INET_ADDRSTRLEN];
 
1635
                        inet_ntop(AF_INET, n->ipv4_gateway, buf, sizeof(buf));
 
1636
                        fprintf(fout, "lxc.network.ipv4.gateway = %s\n", buf);
 
1637
                }
 
1638
                lxc_list_for_each(it2, &n->ipv4) {
 
1639
                        struct lxc_inetdev *i = it2->elem;
 
1640
                        char buf[INET_ADDRSTRLEN];
 
1641
                        inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
 
1642
                        fprintf(fout, "lxc.network.ipv4 = %s\n", buf);
 
1643
                }
 
1644
                if (n->ipv6_gateway_auto)
 
1645
                        fprintf(fout, "lxc.network.ipv6.gateway = auto\n");
 
1646
                else if (n->ipv6_gateway) {
 
1647
                        char buf[INET6_ADDRSTRLEN];
 
1648
                        inet_ntop(AF_INET6, n->ipv6_gateway, buf, sizeof(buf));
 
1649
                        fprintf(fout, "lxc.network.ipv6.gateway = %s\n", buf);
 
1650
                }
 
1651
                lxc_list_for_each(it2, &n->ipv6) {
 
1652
                        struct lxc_inet6dev *i = it2->elem;
 
1653
                        char buf[INET6_ADDRSTRLEN];
 
1654
                        inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
 
1655
                        fprintf(fout, "lxc.network.ipv6 = %s\n", buf);
 
1656
                }
 
1657
        }
 
1658
        lxc_list_for_each(it, &c->caps)
 
1659
                fprintf(fout, "lxc.cap.drop = %s\n", (char *)it->elem);
 
1660
        for (i=0; i<NUM_LXC_HOOKS; i++) {
 
1661
                lxc_list_for_each(it, &c->hooks[i])
 
1662
                        fprintf(fout, "lxc.hook.%s = %s\n",
 
1663
                                lxchook_names[i], (char *)it->elem);
 
1664
        }
 
1665
        if (c->console.path)
 
1666
                fprintf(fout, "lxc.console = %s\n", c->console.path);
 
1667
        if (c->rootfs.path)
 
1668
                fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path);
 
1669
        if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0)
 
1670
                fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount);
 
1671
        if (c->rootfs.pivot)
 
1672
                fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot);
 
1673
}