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

« back to all changes in this revision

Viewing changes to .pc/0091-introduce-container-hooks.patch/src/lxc/confile.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn, Stéphane Graber, Serge Hallyn
  • Date: 2012-06-26 13:04:01 UTC
  • Revision ID: package-import@ubuntu.com-20120626130401-8tclzscid8u2lzxu
Tags: 0.8.0~rc1-4ubuntu17
[ Stéphane Graber ]
* 0090-lxc-ubuntu-use-dpkg-add-architecture: Update lxc-ubuntu
  template to use "dpkg --add-architecture" in containers running
  dpkg >= 1.16.2. (LP: #1017862)

[ Serge Hallyn ]
* 0091-introduce-container-hooks.patch: introduce container hooks at several
  points in the container life-cycle.
* Add copyright statement to lxc-aa-custom-profile
* Add debian/hooks/mountcgroups as an example (installed under
  /usr/share/lxc/hooks)

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