~ubuntu-branches/ubuntu/quantal/lxc/quantal-201208232243

« back to all changes in this revision

Viewing changes to .pc/0098-config-file-includes/src/lxc/confile.c

  • Committer: Serge Hallyn
  • Date: 2012-08-14 19:11:24 UTC
  • Revision ID: serge.hallyn@ubuntu.com-20120814191124-g8tigwsx9pwelhof
Tags: 0.8.0~rc1-4ubuntu24
* lxc-start-ephemeral: use unionfs only for the rootfs itself
  (LP: #959352)
* allow config files to include other config files.

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
 
 
46
lxc_log_define(lxc_confile, lxc);
 
47
 
 
48
static int config_personality(const char *, char *, struct lxc_conf *);
 
49
static int config_pts(const char *, char *, struct lxc_conf *);
 
50
static int config_tty(const char *, char *, struct lxc_conf *);
 
51
static int config_ttydir(const char *, char *, struct lxc_conf *);
 
52
static int config_aa_profile(const char *, char *, struct lxc_conf *);
 
53
static int config_cgroup(const char *, char *, struct lxc_conf *);
 
54
static int config_mount(const char *, char *, struct lxc_conf *);
 
55
static int config_rootfs(const char *, char *, struct lxc_conf *);
 
56
static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
 
57
static int config_pivotdir(const char *, char *, struct lxc_conf *);
 
58
static int config_utsname(const char *, char *, struct lxc_conf *);
 
59
static int config_hook(const char *key, char *value, struct lxc_conf *lxc_conf);
 
60
static int config_network_type(const char *, char *, struct lxc_conf *);
 
61
static int config_network_flags(const char *, char *, struct lxc_conf *);
 
62
static int config_network_link(const char *, char *, struct lxc_conf *);
 
63
static int config_network_name(const char *, char *, struct lxc_conf *);
 
64
static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
 
65
static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
 
66
static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
 
67
static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
 
68
static int config_network_mtu(const char *, char *, struct lxc_conf *);
 
69
static int config_network_ipv4(const char *, char *, struct lxc_conf *);
 
70
static int config_network_ipv4_gateway(const char *, char *, struct lxc_conf *);
 
71
static int config_network_script(const char *, char *, struct lxc_conf *);
 
72
static int config_network_ipv6(const char *, char *, struct lxc_conf *);
 
73
static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf *);
 
74
static int config_cap_drop(const char *, char *, struct lxc_conf *);
 
75
static int config_console(const char *, char *, struct lxc_conf *);
 
76
static int config_seccomp(const char *, char *, struct lxc_conf *);
 
77
 
 
78
typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
 
79
 
 
80
struct config {
 
81
        char *name;
 
82
        config_cb cb;
 
83
};
 
84
 
 
85
static struct config config[] = {
 
86
 
 
87
        { "lxc.arch",                 config_personality          },
 
88
        { "lxc.pts",                  config_pts                  },
 
89
        { "lxc.tty",                  config_tty                  },
 
90
        { "lxc.devttydir",            config_ttydir               },
 
91
        { "lxc.aa_profile",            config_aa_profile          },
 
92
        { "lxc.cgroup",               config_cgroup               },
 
93
        { "lxc.mount",                config_mount                },
 
94
        { "lxc.rootfs.mount",         config_rootfs_mount         },
 
95
        { "lxc.rootfs",               config_rootfs               },
 
96
        { "lxc.pivotdir",             config_pivotdir             },
 
97
        { "lxc.utsname",              config_utsname              },
 
98
        { "lxc.hook.pre-start",       config_hook                 },
 
99
        { "lxc.hook.mount",           config_hook                 },
 
100
        { "lxc.hook.start",           config_hook                 },
 
101
        { "lxc.hook.post-stop",       config_hook                 },
 
102
        { "lxc.network.type",         config_network_type         },
 
103
        { "lxc.network.flags",        config_network_flags        },
 
104
        { "lxc.network.link",         config_network_link         },
 
105
        { "lxc.network.name",         config_network_name         },
 
106
        { "lxc.network.macvlan.mode", config_network_macvlan_mode },
 
107
        { "lxc.network.veth.pair",    config_network_veth_pair    },
 
108
        { "lxc.network.script.up",    config_network_script       },
 
109
        { "lxc.network.hwaddr",       config_network_hwaddr       },
 
110
        { "lxc.network.mtu",          config_network_mtu          },
 
111
        { "lxc.network.vlan.id",      config_network_vlan_id      },
 
112
        { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
 
113
        { "lxc.network.ipv4",         config_network_ipv4         },
 
114
        { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
 
115
        { "lxc.network.ipv6",         config_network_ipv6         },
 
116
        { "lxc.cap.drop",             config_cap_drop             },
 
117
        { "lxc.console",              config_console              },
 
118
        { "lxc.seccomp",              config_seccomp              },
 
119
};
 
120
 
 
121
static const size_t config_size = sizeof(config)/sizeof(struct config);
 
122
 
 
123
static struct config *getconfig(const char *key)
 
124
{
 
125
        int i;
 
126
 
 
127
        for (i = 0; i < config_size; i++)
 
128
                if (!strncmp(config[i].name, key,
 
129
                             strlen(config[i].name)))
 
130
                        return &config[i];
 
131
        return NULL;
 
132
}
 
133
 
 
134
static int config_network_type(const char *key, char *value,
 
135
                               struct lxc_conf *lxc_conf)
 
136
{
 
137
        struct lxc_list *network = &lxc_conf->network;
 
138
        struct lxc_netdev *netdev;
 
139
        struct lxc_list *list;
 
140
 
 
141
        netdev = malloc(sizeof(*netdev));
 
142
        if (!netdev) {
 
143
                SYSERROR("failed to allocate memory");
 
144
                return -1;
 
145
        }
 
146
 
 
147
        memset(netdev, 0, sizeof(*netdev));
 
148
        lxc_list_init(&netdev->ipv4);
 
149
        lxc_list_init(&netdev->ipv6);
 
150
 
 
151
        list = malloc(sizeof(*list));
 
152
        if (!list) {
 
153
                SYSERROR("failed to allocate memory");
 
154
                return -1;
 
155
        }
 
156
 
 
157
        lxc_list_init(list);
 
158
        list->elem = netdev;
 
159
 
 
160
        lxc_list_add_tail(network, list);
 
161
 
 
162
        if (!strcmp(value, "veth"))
 
163
                netdev->type = LXC_NET_VETH;
 
164
        else if (!strcmp(value, "macvlan"))
 
165
                netdev->type = LXC_NET_MACVLAN;
 
166
        else if (!strcmp(value, "vlan"))
 
167
                netdev->type = LXC_NET_VLAN;
 
168
        else if (!strcmp(value, "phys"))
 
169
                netdev->type = LXC_NET_PHYS;
 
170
        else if (!strcmp(value, "empty"))
 
171
                netdev->type = LXC_NET_EMPTY;
 
172
        else {
 
173
                ERROR("invalid network type %s", value);
 
174
                return -1;
 
175
        }
 
176
        return 0;
 
177
}
 
178
 
 
179
static int config_ip_prefix(struct in_addr *addr)
 
180
{
 
181
        if (IN_CLASSA(addr->s_addr))
 
182
                return 32 - IN_CLASSA_NSHIFT;
 
183
        if (IN_CLASSB(addr->s_addr))
 
184
                return 32 - IN_CLASSB_NSHIFT;
 
185
        if (IN_CLASSC(addr->s_addr))
 
186
                return 32 - IN_CLASSC_NSHIFT;
 
187
 
 
188
        return 0;
 
189
}
 
190
 
 
191
static struct lxc_netdev *network_netdev(const char *key, const char *value,
 
192
                                         struct lxc_list *network)
 
193
{
 
194
        struct lxc_netdev *netdev;
 
195
 
 
196
        if (lxc_list_empty(network)) {
 
197
                ERROR("network is not created for '%s' = '%s' option",
 
198
                      key, value);
 
199
                return NULL;
 
200
        }
 
201
 
 
202
        netdev = lxc_list_last_elem(network);
 
203
        if (!netdev) {
 
204
                ERROR("no network device defined for '%s' = '%s' option",
 
205
                      key, value);
 
206
                return NULL;
 
207
        }
 
208
 
 
209
        return netdev;
 
210
}
 
211
 
 
212
static int network_ifname(char **valuep, char *value)
 
213
{
 
214
        if (strlen(value) >= IFNAMSIZ) {
 
215
                ERROR("invalid interface name: %s", value);
 
216
                return -1;
 
217
        }
 
218
 
 
219
        *valuep = strdup(value);
 
220
        if (!*valuep) {
 
221
                ERROR("failed to dup string '%s'", value);
 
222
                return -1;
 
223
        }
 
224
 
 
225
        return 0;
 
226
}
 
227
 
 
228
#ifndef MACVLAN_MODE_PRIVATE
 
229
#  define MACVLAN_MODE_PRIVATE 1
 
230
#endif
 
231
 
 
232
#ifndef MACVLAN_MODE_VEPA
 
233
#  define MACVLAN_MODE_VEPA 2
 
234
#endif
 
235
 
 
236
#ifndef MACVLAN_MODE_BRIDGE
 
237
#  define MACVLAN_MODE_BRIDGE 4
 
238
#endif
 
239
 
 
240
static int macvlan_mode(int *valuep, char *value)
 
241
{
 
242
        struct mc_mode {
 
243
                char *name;
 
244
                int mode;
 
245
        } m[] = {
 
246
                { "private", MACVLAN_MODE_PRIVATE },
 
247
                { "vepa", MACVLAN_MODE_VEPA },
 
248
                { "bridge", MACVLAN_MODE_BRIDGE },
 
249
        };
 
250
 
 
251
        int i;
 
252
 
 
253
        for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
 
254
                if (strcmp(m[i].name, value))
 
255
                        continue;
 
256
 
 
257
                *valuep = m[i].mode;
 
258
                return 0;
 
259
        }
 
260
 
 
261
        return -1;
 
262
}
 
263
 
 
264
static int config_network_flags(const char *key, char *value,
 
265
                                struct lxc_conf *lxc_conf)
 
266
{
 
267
        struct lxc_netdev *netdev;
 
268
 
 
269
        netdev = network_netdev(key, value, &lxc_conf->network);
 
270
        if (!netdev)
 
271
                return -1;
 
272
 
 
273
        netdev->flags |= IFF_UP;
 
274
 
 
275
        return 0;
 
276
}
 
277
 
 
278
static int config_network_link(const char *key, char *value,
 
279
                               struct lxc_conf *lxc_conf)
 
280
{
 
281
        struct lxc_netdev *netdev;
 
282
 
 
283
        netdev = network_netdev(key, value, &lxc_conf->network);
 
284
        if (!netdev)
 
285
                return -1;
 
286
 
 
287
        return network_ifname(&netdev->link, value);
 
288
}
 
289
 
 
290
static int config_network_name(const char *key, char *value,
 
291
                               struct lxc_conf *lxc_conf)
 
292
{
 
293
        struct lxc_netdev *netdev;
 
294
 
 
295
        netdev = network_netdev(key, value, &lxc_conf->network);
 
296
        if (!netdev)
 
297
                return -1;
 
298
 
 
299
        return network_ifname(&netdev->name, value);
 
300
}
 
301
 
 
302
static int config_network_veth_pair(const char *key, char *value,
 
303
                                    struct lxc_conf *lxc_conf)
 
304
{
 
305
        struct lxc_netdev *netdev;
 
306
 
 
307
        netdev = network_netdev(key, value, &lxc_conf->network);
 
308
        if (!netdev)
 
309
                return -1;
 
310
 
 
311
        return network_ifname(&netdev->priv.veth_attr.pair, value);
 
312
}
 
313
 
 
314
static int config_network_macvlan_mode(const char *key, char *value,
 
315
                                       struct lxc_conf *lxc_conf)
 
316
{
 
317
        struct lxc_netdev *netdev;
 
318
 
 
319
        netdev = network_netdev(key, value, &lxc_conf->network);
 
320
        if (!netdev)
 
321
                return -1;
 
322
 
 
323
        return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
 
324
}
 
325
 
 
326
static int config_network_hwaddr(const char *key, char *value,
 
327
                                 struct lxc_conf *lxc_conf)
 
328
{
 
329
        struct lxc_netdev *netdev;
 
330
 
 
331
        netdev = network_netdev(key, value, &lxc_conf->network);
 
332
        if (!netdev)
 
333
                return -1;
 
334
 
 
335
        netdev->hwaddr = strdup(value);
 
336
        if (!netdev->hwaddr) {
 
337
                SYSERROR("failed to dup string '%s'", value);
 
338
                return -1;
 
339
        }
 
340
 
 
341
        return 0;
 
342
}
 
343
 
 
344
static int config_network_vlan_id(const char *key, char *value,
 
345
                               struct lxc_conf *lxc_conf)
 
346
{
 
347
        struct lxc_netdev *netdev;
 
348
 
 
349
        netdev = network_netdev(key, value, &lxc_conf->network);
 
350
        if (!netdev)
 
351
                return -1;
 
352
 
 
353
        if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
 
354
                return -1;
 
355
 
 
356
        return 0;
 
357
}
 
358
 
 
359
static int config_network_mtu(const char *key, char *value,
 
360
                              struct lxc_conf *lxc_conf)
 
361
{
 
362
        struct lxc_netdev *netdev;
 
363
 
 
364
        netdev = network_netdev(key, value, &lxc_conf->network);
 
365
        if (!netdev)
 
366
                return -1;
 
367
 
 
368
        netdev->mtu = strdup(value);
 
369
        if (!netdev->mtu) {
 
370
                SYSERROR("failed to dup string '%s'", value);
 
371
                return -1;
 
372
        }
 
373
 
 
374
        return 0;
 
375
}
 
376
 
 
377
static int config_network_ipv4(const char *key, char *value,
 
378
                               struct lxc_conf *lxc_conf)
 
379
{
 
380
        struct lxc_netdev *netdev;
 
381
        struct lxc_inetdev *inetdev;
 
382
        struct lxc_list *list;
 
383
        char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
 
384
 
 
385
        netdev = network_netdev(key, value, &lxc_conf->network);
 
386
        if (!netdev)
 
387
                return -1;
 
388
 
 
389
        inetdev = malloc(sizeof(*inetdev));
 
390
        if (!inetdev) {
 
391
                SYSERROR("failed to allocate ipv4 address");
 
392
                return -1;
 
393
        }
 
394
        memset(inetdev, 0, sizeof(*inetdev));
 
395
 
 
396
        list = malloc(sizeof(*list));
 
397
        if (!list) {
 
398
                SYSERROR("failed to allocate memory");
 
399
                return -1;
 
400
        }
 
401
 
 
402
        lxc_list_init(list);
 
403
        list->elem = inetdev;
 
404
 
 
405
        addr = value;
 
406
 
 
407
        cursor = strstr(addr, " ");
 
408
        if (cursor) {
 
409
                *cursor = '\0';
 
410
                bcast = cursor + 1;
 
411
        }
 
412
 
 
413
        slash = strstr(addr, "/");
 
414
        if (slash) {
 
415
                *slash = '\0';
 
416
                prefix = slash + 1;
 
417
        }
 
418
 
 
419
        if (!addr) {
 
420
                ERROR("no address specified");
 
421
                return -1;
 
422
        }
 
423
 
 
424
        if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
 
425
                SYSERROR("invalid ipv4 address: %s", value);
 
426
                return -1;
 
427
        }
 
428
 
 
429
        if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
 
430
                SYSERROR("invalid ipv4 broadcast address: %s", value);
 
431
                return -1;
 
432
        }
 
433
 
 
434
        /* no prefix specified, determine it from the network class */
 
435
        inetdev->prefix = prefix ? atoi(prefix) :
 
436
                config_ip_prefix(&inetdev->addr);
 
437
 
 
438
        /* if no broadcast address, let compute one from the
 
439
         * prefix and address
 
440
         */
 
441
        if (!bcast) {
 
442
                inetdev->bcast.s_addr = inetdev->addr.s_addr;
 
443
                inetdev->bcast.s_addr |=
 
444
                        htonl(INADDR_BROADCAST >>  inetdev->prefix);
 
445
        }
 
446
 
 
447
        lxc_list_add(&netdev->ipv4, list);
 
448
 
 
449
        return 0;
 
450
}
 
451
 
 
452
static int config_network_ipv4_gateway(const char *key, char *value,
 
453
                                       struct lxc_conf *lxc_conf)
 
454
{
 
455
        struct lxc_netdev *netdev;
 
456
        struct in_addr *gw;
 
457
 
 
458
        netdev = network_netdev(key, value, &lxc_conf->network);
 
459
        if (!netdev)
 
460
                return -1;
 
461
 
 
462
        gw = malloc(sizeof(*gw));
 
463
        if (!gw) {
 
464
                SYSERROR("failed to allocate ipv4 gateway address");
 
465
                return -1;
 
466
        }
 
467
 
 
468
        if (!value) {
 
469
                ERROR("no ipv4 gateway address specified");
 
470
                return -1;
 
471
        }
 
472
 
 
473
        if (!strcmp(value, "auto")) {
 
474
                netdev->ipv4_gateway = NULL;
 
475
                netdev->ipv4_gateway_auto = true;
 
476
        } else {
 
477
                if (!inet_pton(AF_INET, value, gw)) {
 
478
                        SYSERROR("invalid ipv4 gateway address: %s", value);
 
479
                        return -1;
 
480
                }
 
481
 
 
482
                netdev->ipv4_gateway = gw;
 
483
                netdev->ipv4_gateway_auto = false;
 
484
        }
 
485
 
 
486
        return 0;
 
487
}
 
488
 
 
489
static int config_network_ipv6(const char *key, char *value,
 
490
                               struct lxc_conf *lxc_conf)
 
491
{
 
492
        struct lxc_netdev *netdev;
 
493
        struct lxc_inet6dev *inet6dev;
 
494
        struct lxc_list *list;
 
495
        char *slash;
 
496
        char *netmask;
 
497
 
 
498
        netdev = network_netdev(key, value, &lxc_conf->network);
 
499
        if (!netdev)
 
500
                return -1;
 
501
 
 
502
        inet6dev = malloc(sizeof(*inet6dev));
 
503
        if (!inet6dev) {
 
504
                SYSERROR("failed to allocate ipv6 address");
 
505
                return -1;
 
506
        }
 
507
        memset(inet6dev, 0, sizeof(*inet6dev));
 
508
 
 
509
        list = malloc(sizeof(*list));
 
510
        if (!list) {
 
511
                SYSERROR("failed to allocate memory");
 
512
                return -1;
 
513
        }
 
514
 
 
515
        lxc_list_init(list);
 
516
        list->elem = inet6dev;
 
517
 
 
518
        inet6dev->prefix = 64;
 
519
        slash = strstr(value, "/");
 
520
        if (slash) {
 
521
                *slash = '\0';
 
522
                netmask = slash + 1;
 
523
                inet6dev->prefix = atoi(netmask);
 
524
        }
 
525
 
 
526
        if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
 
527
                SYSERROR("invalid ipv6 address: %s", value);
 
528
                return -1;
 
529
        }
 
530
 
 
531
        lxc_list_add(&netdev->ipv6, list);
 
532
 
 
533
        return 0;
 
534
}
 
535
 
 
536
static int config_network_ipv6_gateway(const char *key, char *value,
 
537
                                       struct lxc_conf *lxc_conf)
 
538
{
 
539
        struct lxc_netdev *netdev;
 
540
        struct in6_addr *gw;
 
541
 
 
542
        netdev = network_netdev(key, value, &lxc_conf->network);
 
543
        if (!netdev)
 
544
                return -1;
 
545
 
 
546
        gw = malloc(sizeof(*gw));
 
547
        if (!gw) {
 
548
                SYSERROR("failed to allocate ipv6 gateway address");
 
549
                return -1;
 
550
        }
 
551
 
 
552
        if (!value) {
 
553
                ERROR("no ipv6 gateway address specified");
 
554
                return -1;
 
555
        }
 
556
 
 
557
        if (!strcmp(value, "auto")) {
 
558
                netdev->ipv6_gateway = NULL;
 
559
                netdev->ipv6_gateway_auto = true;
 
560
        } else {
 
561
                if (!inet_pton(AF_INET6, value, gw)) {
 
562
                        SYSERROR("invalid ipv6 gateway address: %s", value);
 
563
                        return -1;
 
564
                }
 
565
 
 
566
                netdev->ipv6_gateway = gw;
 
567
                netdev->ipv6_gateway_auto = false;
 
568
        }
 
569
 
 
570
        return 0;
 
571
}
 
572
 
 
573
static int config_network_script(const char *key, char *value,
 
574
                                 struct lxc_conf *lxc_conf)
 
575
{
 
576
        struct lxc_netdev *netdev;
 
577
 
 
578
        netdev = network_netdev(key, value, &lxc_conf->network);
 
579
        if (!netdev)
 
580
        return -1;
 
581
 
 
582
        char *copy = strdup(value);
 
583
        if (!copy) {
 
584
                SYSERROR("failed to dup string '%s'", value);
 
585
                return -1;
 
586
        }
 
587
        if (strcmp(key, "lxc.network.script.up") == 0) {
 
588
                netdev->upscript = copy;
 
589
                return 0;
 
590
        }
 
591
        SYSERROR("Unknown key: %s", key);
 
592
        free(copy);
 
593
        return -1;
 
594
}
 
595
 
 
596
static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
 
597
{
 
598
        struct lxc_list *hooklist;
 
599
 
 
600
        hooklist = malloc(sizeof(*hooklist));
 
601
        if (!hooklist) {
 
602
                free(hook);
 
603
                return -1;
 
604
        }
 
605
        hooklist->elem = hook;
 
606
        lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
 
607
        return 0;
 
608
}
 
609
 
 
610
static int config_seccomp(const char *key, char *value,
 
611
                                 struct lxc_conf *lxc_conf)
 
612
{
 
613
        char *path;
 
614
 
 
615
        if (lxc_conf->seccomp) {
 
616
                ERROR("seccomp already defined");
 
617
                return -1;
 
618
        }
 
619
        path = strdup(value);
 
620
        if (!path) {
 
621
                SYSERROR("failed to strdup '%s': %m", value);
 
622
                return -1;
 
623
        }
 
624
 
 
625
        lxc_conf->seccomp = path;
 
626
 
 
627
        return 0;
 
628
}
 
629
 
 
630
static int config_hook(const char *key, char *value,
 
631
                                 struct lxc_conf *lxc_conf)
 
632
{
 
633
        char *copy = strdup(value);
 
634
        if (!copy) {
 
635
                SYSERROR("failed to dup string '%s'", value);
 
636
                return -1;
 
637
        }
 
638
        if (strcmp(key, "lxc.hook.pre-start") == 0)
 
639
                return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
 
640
        else if (strcmp(key, "lxc.hook.mount") == 0)
 
641
                return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
 
642
        else if (strcmp(key, "lxc.hook.start") == 0)
 
643
                return add_hook(lxc_conf, LXCHOOK_START, copy);
 
644
        else if (strcmp(key, "lxc.hook.post-stop") == 0)
 
645
                return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
 
646
        SYSERROR("Unknown key: %s", key);
 
647
        free(copy);
 
648
        return -1;
 
649
}
 
650
 
 
651
static int config_personality(const char *key, char *value,
 
652
                              struct lxc_conf *lxc_conf)
 
653
{
 
654
        signed long personality = lxc_config_parse_arch(value);
 
655
 
 
656
        if (personality >= 0)
 
657
                lxc_conf->personality = personality;
 
658
        else
 
659
                WARN("unsupported personality '%s'", value);
 
660
 
 
661
        return 0;
 
662
}
 
663
 
 
664
static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
 
665
{
 
666
        int maxpts = atoi(value);
 
667
 
 
668
        lxc_conf->pts = maxpts;
 
669
 
 
670
        return 0;
 
671
}
 
672
 
 
673
static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
 
674
{
 
675
        int nbtty = atoi(value);
 
676
 
 
677
        lxc_conf->tty = nbtty;
 
678
 
 
679
        return 0;
 
680
}
 
681
 
 
682
static int config_ttydir(const char *key, char *value,
 
683
                          struct lxc_conf *lxc_conf)
 
684
{
 
685
        char *path;
 
686
 
 
687
        if (!value || strlen(value) == 0)
 
688
                return 0;
 
689
        path = strdup(value);
 
690
        if (!path) {
 
691
                SYSERROR("failed to strdup '%s': %m", value);
 
692
                return -1;
 
693
        }
 
694
 
 
695
        lxc_conf->ttydir = path;
 
696
 
 
697
        return 0;
 
698
}
 
699
 
 
700
static int config_aa_profile(const char *key, char *value,
 
701
                          struct lxc_conf *lxc_conf)
 
702
{
 
703
        char *path;
 
704
 
 
705
        if (!value || strlen(value) == 0)
 
706
                return 0;
 
707
        path = strdup(value);
 
708
        if (!path) {
 
709
                SYSERROR("failed to strdup '%s': %m", value);
 
710
                return -1;
 
711
        }
 
712
 
 
713
        lxc_conf->aa_profile = path;
 
714
 
 
715
        return 0;
 
716
}
 
717
 
 
718
static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
 
719
{
 
720
        char *token = "lxc.cgroup.";
 
721
        char *subkey;
 
722
        struct lxc_list *cglist = NULL;
 
723
        struct lxc_cgroup *cgelem = NULL;
 
724
 
 
725
        subkey = strstr(key, token);
 
726
 
 
727
        if (!subkey)
 
728
                return -1;
 
729
 
 
730
        if (!strlen(subkey))
 
731
                return -1;
 
732
 
 
733
        if (strlen(subkey) == strlen(token))
 
734
                return -1;
 
735
 
 
736
        subkey += strlen(token);
 
737
 
 
738
        cglist = malloc(sizeof(*cglist));
 
739
        if (!cglist)
 
740
                goto out;
 
741
 
 
742
        cgelem = malloc(sizeof(*cgelem));
 
743
        if (!cgelem)
 
744
                goto out;
 
745
        memset(cgelem, 0, sizeof(*cgelem));
 
746
 
 
747
        cgelem->subsystem = strdup(subkey);
 
748
        cgelem->value = strdup(value);
 
749
 
 
750
        if (!cgelem->subsystem || !cgelem->value)
 
751
                goto out;
 
752
 
 
753
        cglist->elem = cgelem;
 
754
 
 
755
        lxc_list_add_tail(&lxc_conf->cgroup, cglist);
 
756
 
 
757
        return 0;
 
758
 
 
759
out:
 
760
        if (cglist)
 
761
                free(cglist);
 
762
 
 
763
        if (cgelem) {
 
764
                if (cgelem->subsystem)
 
765
                        free(cgelem->subsystem);
 
766
 
 
767
                if (cgelem->value)
 
768
                        free(cgelem->value);
 
769
 
 
770
                free(cgelem);
 
771
        }
 
772
 
 
773
        return -1;
 
774
}
 
775
 
 
776
static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
 
777
{
 
778
        if (strlen(value) >= MAXPATHLEN) {
 
779
                ERROR("%s path is too long", value);
 
780
                return -1;
 
781
        }
 
782
 
 
783
        lxc_conf->fstab = strdup(value);
 
784
        if (!lxc_conf->fstab) {
 
785
                SYSERROR("failed to duplicate string %s", value);
 
786
                return -1;
 
787
        }
 
788
 
 
789
        return 0;
 
790
}
 
791
 
 
792
static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
 
793
{
 
794
        char *fstab_token = "lxc.mount";
 
795
        char *token = "lxc.mount.entry";
 
796
        char *subkey;
 
797
        char *mntelem;
 
798
        struct lxc_list *mntlist;
 
799
 
 
800
        subkey = strstr(key, token);
 
801
 
 
802
        if (!subkey) {
 
803
                subkey = strstr(key, fstab_token);
 
804
 
 
805
                if (!subkey)
 
806
                        return -1;
 
807
 
 
808
                return config_fstab(key, value, lxc_conf);
 
809
        }
 
810
 
 
811
        if (!strlen(subkey))
 
812
                return -1;
 
813
 
 
814
        mntlist = malloc(sizeof(*mntlist));
 
815
        if (!mntlist)
 
816
                return -1;
 
817
 
 
818
        mntelem = strdup(value);
 
819
        if (!mntelem)
 
820
                return -1;
 
821
        mntlist->elem = mntelem;
 
822
 
 
823
        lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
 
824
 
 
825
        return 0;
 
826
}
 
827
 
 
828
static int config_cap_drop(const char *key, char *value,
 
829
                           struct lxc_conf *lxc_conf)
 
830
{
 
831
        char *dropcaps, *sptr, *token;
 
832
        struct lxc_list *droplist;
 
833
        int ret = -1;
 
834
 
 
835
        if (!strlen(value))
 
836
                return -1;
 
837
 
 
838
        dropcaps = strdup(value);
 
839
        if (!dropcaps) {
 
840
                SYSERROR("failed to dup '%s'", value);
 
841
                return -1;
 
842
        }
 
843
 
 
844
        /* in case several capability drop is specified in a single line
 
845
         * split these caps in a single element for the list */
 
846
        for (;;) {
 
847
                token = strtok_r(dropcaps, " \t", &sptr);
 
848
                if (!token) {
 
849
                        ret = 0;
 
850
                        break;
 
851
                }
 
852
                dropcaps = NULL;
 
853
 
 
854
                droplist = malloc(sizeof(*droplist));
 
855
                if (!droplist) {
 
856
                        SYSERROR("failed to allocate drop list");
 
857
                        break;
 
858
                }
 
859
 
 
860
                droplist->elem = strdup(token);
 
861
                if (!droplist->elem) {
 
862
                        SYSERROR("failed to dup '%s'", token);
 
863
                        free(droplist);
 
864
                        break;
 
865
                }
 
866
 
 
867
                lxc_list_add_tail(&lxc_conf->caps, droplist);
 
868
        }
 
869
 
 
870
        free(dropcaps);
 
871
 
 
872
        return ret;
 
873
}
 
874
 
 
875
static int config_console(const char *key, char *value,
 
876
                          struct lxc_conf *lxc_conf)
 
877
{
 
878
        char *path;
 
879
 
 
880
        path = strdup(value);
 
881
        if (!path) {
 
882
                SYSERROR("failed to strdup '%s': %m", value);
 
883
                return -1;
 
884
        }
 
885
 
 
886
        lxc_conf->console.path = path;
 
887
 
 
888
        return 0;
 
889
}
 
890
 
 
891
static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
 
892
{
 
893
        if (strlen(value) >= MAXPATHLEN) {
 
894
                ERROR("%s path is too long", value);
 
895
                return -1;
 
896
        }
 
897
 
 
898
        lxc_conf->rootfs.path = strdup(value);
 
899
        if (!lxc_conf->rootfs.path) {
 
900
                SYSERROR("failed to duplicate string %s", value);
 
901
                return -1;
 
902
        }
 
903
 
 
904
        return 0;
 
905
}
 
906
 
 
907
static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
 
908
{
 
909
        if (strlen(value) >= MAXPATHLEN) {
 
910
                ERROR("%s path is too long", value);
 
911
                return -1;
 
912
        }
 
913
 
 
914
        lxc_conf->rootfs.mount = strdup(value);
 
915
        if (!lxc_conf->rootfs.mount) {
 
916
                SYSERROR("failed to duplicate string '%s'", value);
 
917
                return -1;
 
918
        }
 
919
 
 
920
        return 0;
 
921
}
 
922
 
 
923
static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
 
924
{
 
925
        if (strlen(value) >= MAXPATHLEN) {
 
926
                ERROR("%s path is too long", value);
 
927
                return -1;
 
928
        }
 
929
 
 
930
        lxc_conf->rootfs.pivot = strdup(value);
 
931
        if (!lxc_conf->rootfs.pivot) {
 
932
                SYSERROR("failed to duplicate string %s", value);
 
933
                return -1;
 
934
        }
 
935
 
 
936
        return 0;
 
937
}
 
938
 
 
939
static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
 
940
{
 
941
        struct utsname *utsname;
 
942
 
 
943
        utsname = malloc(sizeof(*utsname));
 
944
        if (!utsname) {
 
945
                SYSERROR("failed to allocate memory");
 
946
                return -1;
 
947
        }
 
948
 
 
949
        if (strlen(value) >= sizeof(utsname->nodename)) {
 
950
                ERROR("node name '%s' is too long",
 
951
                              utsname->nodename);
 
952
                return -1;
 
953
        }
 
954
 
 
955
        strcpy(utsname->nodename, value);
 
956
        lxc_conf->utsname = utsname;
 
957
 
 
958
        return 0;
 
959
}
 
960
 
 
961
static int parse_line(char *buffer, void *data)
 
962
{
 
963
        struct config *config;
 
964
        char *line, *linep;
 
965
        char *dot;
 
966
        char *key;
 
967
        char *value;
 
968
        int ret = 0;
 
969
 
 
970
        if (lxc_is_line_empty(buffer))
 
971
                return 0;
 
972
 
 
973
        /* we have to dup the buffer otherwise, at the re-exec for
 
974
         * reboot we modified the original string on the stack by
 
975
         * replacing '=' by '\0' below
 
976
         */
 
977
        linep = line = strdup(buffer);
 
978
        if (!line) {
 
979
                SYSERROR("failed to allocate memory for '%s'", buffer);
 
980
                return -1;
 
981
        }
 
982
 
 
983
        line += lxc_char_left_gc(line, strlen(line));
 
984
 
 
985
        /* martian option - ignoring it, the commented lines beginning by '#'
 
986
         * fall in this case
 
987
         */
 
988
        if (strncmp(line, "lxc.", 4))
 
989
                goto out;
 
990
 
 
991
        ret = -1;
 
992
 
 
993
        dot = strstr(line, "=");
 
994
        if (!dot) {
 
995
                ERROR("invalid configuration line: %s", line);
 
996
                goto out;
 
997
        }
 
998
 
 
999
        *dot = '\0';
 
1000
        value = dot + 1;
 
1001
 
 
1002
        key = line;
 
1003
        key[lxc_char_right_gc(key, strlen(key))] = '\0';
 
1004
 
 
1005
        value += lxc_char_left_gc(value, strlen(value));
 
1006
        value[lxc_char_right_gc(value, strlen(value))] = '\0';
 
1007
 
 
1008
        config = getconfig(key);
 
1009
        if (!config) {
 
1010
                ERROR("unknown key %s", key);
 
1011
                goto out;
 
1012
        }
 
1013
 
 
1014
        ret = config->cb(key, value, data);
 
1015
 
 
1016
out:
 
1017
        free(linep);
 
1018
        return ret;
 
1019
}
 
1020
 
 
1021
int lxc_config_readline(char *buffer, struct lxc_conf *conf)
 
1022
{
 
1023
        return parse_line(buffer, conf);
 
1024
}
 
1025
 
 
1026
int lxc_config_read(const char *file, struct lxc_conf *conf)
 
1027
{
 
1028
        return lxc_file_for_each_line(file, parse_line, conf);
 
1029
}
 
1030
 
 
1031
int lxc_config_define_add(struct lxc_list *defines, char* arg)
 
1032
{
 
1033
        struct lxc_list *dent;
 
1034
 
 
1035
        dent = malloc(sizeof(struct lxc_list));
 
1036
        if (!dent)
 
1037
                return -1;
 
1038
 
 
1039
        dent->elem = arg;
 
1040
        lxc_list_add_tail(defines, dent);
 
1041
        return 0;
 
1042
}
 
1043
 
 
1044
int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
 
1045
{
 
1046
        struct lxc_list *it;
 
1047
        int ret = 0;
 
1048
 
 
1049
        lxc_list_for_each(it, defines) {
 
1050
                ret = lxc_config_readline(it->elem, conf);
 
1051
                if (ret)
 
1052
                        break;
 
1053
        }
 
1054
 
 
1055
        lxc_list_for_each(it, defines) {
 
1056
                lxc_list_del(it);
 
1057
                free(it);
 
1058
        }
 
1059
 
 
1060
        return ret;
 
1061
}
 
1062
 
 
1063
signed long lxc_config_parse_arch(const char *arch)
 
1064
{
 
1065
        struct per_name {
 
1066
                char *name;
 
1067
                unsigned long per;
 
1068
        } pername[4] = {
 
1069
                { "x86", PER_LINUX32 },
 
1070
                { "i686", PER_LINUX32 },
 
1071
                { "x86_64", PER_LINUX },
 
1072
                { "amd64", PER_LINUX },
 
1073
        };
 
1074
        size_t len = sizeof(pername) / sizeof(pername[0]);
 
1075
 
 
1076
        int i;
 
1077
 
 
1078
        for (i = 0; i < len; i++) {
 
1079
                if (!strcmp(pername[i].name, arch))
 
1080
                    return pername[i].per;
 
1081
        }
 
1082
 
 
1083
        return -1;
 
1084
}