]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
lxc-destroy container only if it is in the STOPPED state
[mirror_lxc.git] / src / lxc / conf.c
CommitLineData
0ad19a3f 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#define _GNU_SOURCE
24#include <stdio.h>
25#undef _GNU_SOURCE
26#include <stdlib.h>
e3b4c4c4 27#include <stdarg.h>
0ad19a3f 28#include <errno.h>
29#include <string.h>
30#include <dirent.h>
31#include <mntent.h>
32#include <unistd.h>
e3b4c4c4 33#include <sys/wait.h>
b0a33c1e 34#include <pty.h>
0ad19a3f 35
b3ecde1e
DL
36#include <linux/loop.h>
37
0ad19a3f 38#include <sys/types.h>
39#include <sys/utsname.h>
40#include <sys/param.h>
41#include <sys/stat.h>
42#include <sys/socket.h>
43#include <sys/mount.h>
44#include <sys/mman.h>
81810dd1
DL
45#include <sys/prctl.h>
46#include <sys/capability.h>
cccc74b5 47#include <sys/personality.h>
0ad19a3f 48
49#include <arpa/inet.h>
50#include <fcntl.h>
51#include <netinet/in.h>
52#include <net/if.h>
6f4a3756 53#include <libgen.h>
0ad19a3f 54
e5bda9ee 55#include "network.h"
56#include "error.h"
b2718c72 57#include "parse.h"
881450bb 58#include "config.h"
1b09f2c0
DL
59#include "utils.h"
60#include "conf.h"
61#include "log.h"
62#include "lxc.h" /* for lxc_cgroup_set() */
d55bc1ad 63#include "caps.h" /* for lxc_caps_last_cap() */
36eb9bde 64
d0a36f2c
SG
65#if HAVE_APPARMOR
66#include <apparmor.h>
67#endif
68
769872f9
SH
69#include "lxcseccomp.h"
70
36eb9bde 71lxc_log_define(lxc_conf, lxc);
e5bda9ee 72
0ad19a3f 73#define MAXHWLEN 18
74#define MAXINDEXLEN 20
442cbbe6 75#define MAXMTULEN 16
0ad19a3f 76#define MAXLINELEN 128
77
968fbd36
SK
78#ifndef MS_DIRSYNC
79#define MS_DIRSYNC 128
80#endif
81
fdc03323
DL
82#ifndef MS_REC
83#define MS_REC 16384
84#endif
85
c08556c6
DL
86#ifndef MNT_DETACH
87#define MNT_DETACH 2
88#endif
89
88d413d5
SW
90#ifndef MS_RELATIME
91#define MS_RELATIME (1 << 21)
92#endif
93
94#ifndef MS_STRICTATIME
95#define MS_STRICTATIME (1 << 24)
96#endif
97
b09094da
MN
98#ifndef CAP_SETFCAP
99#define CAP_SETFCAP 31
100#endif
101
102#ifndef CAP_MAC_OVERRIDE
103#define CAP_MAC_OVERRIDE 32
104#endif
105
106#ifndef CAP_MAC_ADMIN
107#define CAP_MAC_ADMIN 33
108#endif
109
110#ifndef PR_CAPBSET_DROP
111#define PR_CAPBSET_DROP 24
112#endif
113
72d0e1cb 114char *lxchook_names[NUM_LXC_HOOKS] = {
5ea6163a 115 "pre-start", "pre-mount", "mount", "start", "post-stop" };
72d0e1cb 116
bf601689
MH
117extern int pivot_root(const char * new_root, const char * put_old);
118
e3b4c4c4 119typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
0ad19a3f 120
998ac676
RT
121struct mount_opt {
122 char *name;
123 int clear;
124 int flag;
125};
126
81810dd1
DL
127struct caps_opt {
128 char *name;
129 int value;
130};
131
e3b4c4c4
ST
132static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
133static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
134static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
135static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
136static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
82d5ae15 137
24654103
DL
138static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
139 [LXC_NET_VETH] = instanciate_veth,
140 [LXC_NET_MACVLAN] = instanciate_macvlan,
141 [LXC_NET_VLAN] = instanciate_vlan,
142 [LXC_NET_PHYS] = instanciate_phys,
143 [LXC_NET_EMPTY] = instanciate_empty,
0ad19a3f 144};
145
74a2b586
JK
146static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
147static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *);
148static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *);
149static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
150static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
151
152static instanciate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
153 [LXC_NET_VETH] = shutdown_veth,
154 [LXC_NET_MACVLAN] = shutdown_macvlan,
155 [LXC_NET_VLAN] = shutdown_vlan,
156 [LXC_NET_PHYS] = shutdown_phys,
157 [LXC_NET_EMPTY] = shutdown_empty,
158};
159
998ac676 160static struct mount_opt mount_opt[] = {
88d413d5
SW
161 { "defaults", 0, 0 },
162 { "ro", 0, MS_RDONLY },
163 { "rw", 1, MS_RDONLY },
164 { "suid", 1, MS_NOSUID },
165 { "nosuid", 0, MS_NOSUID },
166 { "dev", 1, MS_NODEV },
167 { "nodev", 0, MS_NODEV },
168 { "exec", 1, MS_NOEXEC },
169 { "noexec", 0, MS_NOEXEC },
170 { "sync", 0, MS_SYNCHRONOUS },
171 { "async", 1, MS_SYNCHRONOUS },
172 { "dirsync", 0, MS_DIRSYNC },
173 { "remount", 0, MS_REMOUNT },
174 { "mand", 0, MS_MANDLOCK },
175 { "nomand", 1, MS_MANDLOCK },
176 { "atime", 1, MS_NOATIME },
177 { "noatime", 0, MS_NOATIME },
178 { "diratime", 1, MS_NODIRATIME },
179 { "nodiratime", 0, MS_NODIRATIME },
180 { "bind", 0, MS_BIND },
181 { "rbind", 0, MS_BIND|MS_REC },
182 { "relatime", 0, MS_RELATIME },
183 { "norelatime", 1, MS_RELATIME },
184 { "strictatime", 0, MS_STRICTATIME },
185 { "nostrictatime", 1, MS_STRICTATIME },
186 { NULL, 0, 0 },
998ac676
RT
187};
188
81810dd1 189static struct caps_opt caps_opt[] = {
a6afdde9 190 { "chown", CAP_CHOWN },
1e11be34
DL
191 { "dac_override", CAP_DAC_OVERRIDE },
192 { "dac_read_search", CAP_DAC_READ_SEARCH },
193 { "fowner", CAP_FOWNER },
194 { "fsetid", CAP_FSETID },
81810dd1
DL
195 { "kill", CAP_KILL },
196 { "setgid", CAP_SETGID },
197 { "setuid", CAP_SETUID },
198 { "setpcap", CAP_SETPCAP },
199 { "linux_immutable", CAP_LINUX_IMMUTABLE },
200 { "net_bind_service", CAP_NET_BIND_SERVICE },
201 { "net_broadcast", CAP_NET_BROADCAST },
202 { "net_admin", CAP_NET_ADMIN },
203 { "net_raw", CAP_NET_RAW },
204 { "ipc_lock", CAP_IPC_LOCK },
205 { "ipc_owner", CAP_IPC_OWNER },
206 { "sys_module", CAP_SYS_MODULE },
207 { "sys_rawio", CAP_SYS_RAWIO },
208 { "sys_chroot", CAP_SYS_CHROOT },
209 { "sys_ptrace", CAP_SYS_PTRACE },
210 { "sys_pacct", CAP_SYS_PACCT },
211 { "sys_admin", CAP_SYS_ADMIN },
212 { "sys_boot", CAP_SYS_BOOT },
213 { "sys_nice", CAP_SYS_NICE },
214 { "sys_resource", CAP_SYS_RESOURCE },
215 { "sys_time", CAP_SYS_TIME },
216 { "sys_tty_config", CAP_SYS_TTY_CONFIG },
217 { "mknod", CAP_MKNOD },
218 { "lease", CAP_LEASE },
9527e566 219#ifdef CAP_AUDIT_WRITE
81810dd1 220 { "audit_write", CAP_AUDIT_WRITE },
9527e566
FW
221#endif
222#ifdef CAP_AUDIT_CONTROL
81810dd1 223 { "audit_control", CAP_AUDIT_CONTROL },
9527e566 224#endif
81810dd1
DL
225 { "setfcap", CAP_SETFCAP },
226 { "mac_override", CAP_MAC_OVERRIDE },
227 { "mac_admin", CAP_MAC_ADMIN },
5170c716
CS
228#ifdef CAP_SYSLOG
229 { "syslog", CAP_SYSLOG },
230#endif
231#ifdef CAP_WAKE_ALARM
232 { "wake_alarm", CAP_WAKE_ALARM },
233#endif
81810dd1
DL
234};
235
91c3830e
SH
236static int run_buffer(char *buffer)
237{
238 FILE *f;
239 char *output;
240
241 f = popen(buffer, "r");
242 if (!f) {
243 SYSERROR("popen failed");
244 return -1;
245 }
246
247 output = malloc(LXC_LOG_BUFFER_SIZE);
248 if (!output) {
249 ERROR("failed to allocate memory for script output");
250 return -1;
251 }
252
253 while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
254 DEBUG("script output: %s", output);
255
256 free(output);
257
258 if (pclose(f) == -1) {
259 SYSERROR("Script exited on error");
260 return -1;
261 }
262
263 return 0;
264}
265
751d9dcd
DL
266static int run_script(const char *name, const char *section,
267 const char *script, ...)
e3b4c4c4 268{
abbfd20b 269 int ret;
91c3830e 270 char *buffer, *p;
abbfd20b
DL
271 size_t size = 0;
272 va_list ap;
751d9dcd
DL
273
274 INFO("Executing script '%s' for container '%s', config section '%s'",
275 script, name, section);
e3b4c4c4 276
abbfd20b
DL
277 va_start(ap, script);
278 while ((p = va_arg(ap, char *)))
95642a10 279 size += strlen(p) + 1;
abbfd20b
DL
280 va_end(ap);
281
282 size += strlen(script);
283 size += strlen(name);
284 size += strlen(section);
95642a10 285 size += 3;
abbfd20b 286
95642a10
MS
287 if (size > INT_MAX)
288 return -1;
289
290 buffer = alloca(size);
abbfd20b
DL
291 if (!buffer) {
292 ERROR("failed to allocate memory");
751d9dcd
DL
293 return -1;
294 }
295
9ba8130c
SH
296 ret = snprintf(buffer, size, "%s %s %s", script, name, section);
297 if (ret < 0 || ret >= size) {
298 ERROR("Script name too long");
299 free(buffer);
300 return -1;
301 }
751d9dcd 302
abbfd20b 303 va_start(ap, script);
9ba8130c
SH
304 while ((p = va_arg(ap, char *))) {
305 int len = size-ret;
306 int rc;
307 rc = snprintf(buffer + ret, len, " %s", p);
308 if (rc < 0 || rc >= len) {
309 free(buffer);
310 ERROR("Script args too long");
311 return -1;
312 }
313 ret += rc;
314 }
abbfd20b 315 va_end(ap);
751d9dcd 316
91c3830e 317 return run_buffer(buffer);
e3b4c4c4
ST
318}
319
a6afdde9 320static int find_fstype_cb(char* buffer, void *data)
78ae2fcc 321{
322 struct cbarg {
323 const char *rootfs;
a6afdde9 324 const char *target;
78ae2fcc 325 int mntopt;
326 } *cbarg = data;
327
328 char *fstype;
329
330 /* we don't try 'nodev' entries */
331 if (strstr(buffer, "nodev"))
332 return 0;
333
334 fstype = buffer;
b2718c72 335 fstype += lxc_char_left_gc(fstype, strlen(fstype));
336 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
78ae2fcc 337
a6afdde9
DL
338 DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
339 cbarg->rootfs, cbarg->target, fstype);
340
341 if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
342 DEBUG("mount failed with error: %s", strerror(errno));
78ae2fcc 343 return 0;
a6afdde9 344 }
78ae2fcc 345
a6afdde9
DL
346 INFO("mounted '%s' on '%s', with fstype '%s'",
347 cbarg->rootfs, cbarg->target, fstype);
78ae2fcc 348
349 return 1;
350}
351
2656d231 352static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
78ae2fcc 353{
a6afdde9 354 int i;
78ae2fcc 355
356 struct cbarg {
357 const char *rootfs;
a6afdde9 358 const char *target;
78ae2fcc 359 int mntopt;
360 } cbarg = {
361 .rootfs = rootfs,
a6afdde9 362 .target = target,
78ae2fcc 363 .mntopt = mntopt,
364 };
365
a6afdde9
DL
366 /*
367 * find the filesystem type with brute force:
368 * first we check with /etc/filesystems, in case the modules
78ae2fcc 369 * are auto-loaded and fall back to the supported kernel fs
370 */
371 char *fsfile[] = {
372 "/etc/filesystems",
373 "/proc/filesystems",
374 };
375
a6afdde9
DL
376 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
377
378 int ret;
379
380 if (access(fsfile[i], F_OK))
381 continue;
382
383 ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
384 if (ret < 0) {
385 ERROR("failed to parse '%s'", fsfile[i]);
386 return -1;
387 }
388
389 if (ret)
390 return 0;
78ae2fcc 391 }
392
a6afdde9
DL
393 ERROR("failed to determine fs type for '%s'", rootfs);
394 return -1;
395}
396
2656d231 397static int mount_rootfs_dir(const char *rootfs, const char *target)
a6afdde9
DL
398{
399 return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
400}
401
402static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
403{
404 int rfd;
405 int ret = -1;
406
407 rfd = open(rootfs, O_RDWR);
408 if (rfd < 0) {
409 SYSERROR("failed to open '%s'", rootfs);
78ae2fcc 410 return -1;
411 }
412
a6afdde9 413 memset(loinfo, 0, sizeof(*loinfo));
78ae2fcc 414
a6afdde9 415 loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
78ae2fcc 416
a6afdde9
DL
417 if (ioctl(fd, LOOP_SET_FD, rfd)) {
418 SYSERROR("failed to LOOP_SET_FD");
419 goto out;
78ae2fcc 420 }
421
a6afdde9
DL
422 if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
423 SYSERROR("failed to LOOP_SET_STATUS64");
78ae2fcc 424 goto out;
425 }
426
a6afdde9 427 ret = 0;
78ae2fcc 428out:
a6afdde9 429 close(rfd);
78ae2fcc 430
a6afdde9 431 return ret;
78ae2fcc 432}
433
2656d231 434static int mount_rootfs_file(const char *rootfs, const char *target)
78ae2fcc 435{
a6afdde9
DL
436 struct dirent dirent, *direntp;
437 struct loop_info64 loinfo;
9ba8130c 438 int ret = -1, fd = -1, rc;
a6afdde9
DL
439 DIR *dir;
440 char path[MAXPATHLEN];
78ae2fcc 441
a6afdde9
DL
442 dir = opendir("/dev");
443 if (!dir) {
444 SYSERROR("failed to open '/dev'");
78ae2fcc 445 return -1;
446 }
447
a6afdde9
DL
448 while (!readdir_r(dir, &dirent, &direntp)) {
449
450 if (!direntp)
451 break;
452
453 if (!strcmp(direntp->d_name, "."))
454 continue;
455
456 if (!strcmp(direntp->d_name, ".."))
457 continue;
458
459 if (strncmp(direntp->d_name, "loop", 4))
460 continue;
461
9ba8130c
SH
462 rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
463 if (rc < 0 || rc >= MAXPATHLEN)
464 continue;
465
a6afdde9
DL
466 fd = open(path, O_RDWR);
467 if (fd < 0)
468 continue;
469
470 if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
471 close(fd);
472 continue;
473 }
474
475 if (errno != ENXIO) {
476 WARN("unexpected error for ioctl on '%s': %m",
477 direntp->d_name);
478 continue;
479 }
480
481 DEBUG("found '%s' free lodev", path);
482
483 ret = setup_lodev(rootfs, fd, &loinfo);
484 if (!ret)
2656d231 485 ret = mount_unknow_fs(path, target, 0);
a6afdde9
DL
486 close(fd);
487
488 break;
489 }
490
491 if (closedir(dir))
492 WARN("failed to close directory");
493
494 return ret;
78ae2fcc 495}
496
2656d231 497static int mount_rootfs_block(const char *rootfs, const char *target)
a6afdde9 498{
2656d231 499 return mount_unknow_fs(rootfs, target, 0);
a6afdde9
DL
500}
501
0c547523
SH
502/*
503 * pin_rootfs
504 * if rootfs is a directory, then open ${rootfs}.hold for writing for the
505 * duration of the container run, to prevent the container from marking the
506 * underlying fs readonly on shutdown.
507 * return -1 on error.
508 * return -2 if nothing needed to be pinned.
509 * return an open fd (>=0) if we pinned it.
510 */
511int pin_rootfs(const char *rootfs)
512{
513 char absrootfs[MAXPATHLEN];
514 char absrootfspin[MAXPATHLEN];
515 struct stat s;
516 int ret, fd;
517
e99ee0de
SH
518 if (rootfs == NULL || strlen(rootfs) == 0)
519 return 0;
520
0c547523
SH
521 if (!realpath(rootfs, absrootfs)) {
522 SYSERROR("failed to get real path for '%s'", rootfs);
523 return -1;
524 }
525
526 if (access(absrootfs, F_OK)) {
527 SYSERROR("'%s' is not accessible", absrootfs);
528 return -1;
529 }
530
531 if (stat(absrootfs, &s)) {
532 SYSERROR("failed to stat '%s'", absrootfs);
533 return -1;
534 }
535
536 if (!__S_ISTYPE(s.st_mode, S_IFDIR))
537 return -2;
538
539 ret = snprintf(absrootfspin, MAXPATHLEN, "%s%s", absrootfs, ".hold");
540 if (ret >= MAXPATHLEN) {
541 SYSERROR("pathname too long for rootfs hold file");
542 return -1;
543 }
544
545 fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
546 INFO("opened %s as fd %d\n", absrootfspin, fd);
547 return fd;
548}
549
2656d231 550static int mount_rootfs(const char *rootfs, const char *target)
0ad19a3f 551{
b09ef133 552 char absrootfs[MAXPATHLEN];
78ae2fcc 553 struct stat s;
a6afdde9 554 int i;
78ae2fcc 555
a6afdde9 556 typedef int (*rootfs_cb)(const char *, const char *);
78ae2fcc 557
558 struct rootfs_type {
559 int type;
560 rootfs_cb cb;
561 } rtfs_type[] = {
2656d231
DL
562 { S_IFDIR, mount_rootfs_dir },
563 { S_IFBLK, mount_rootfs_block },
564 { S_IFREG, mount_rootfs_file },
78ae2fcc 565 };
0ad19a3f 566
4c8ab83b 567 if (!realpath(rootfs, absrootfs)) {
36eb9bde 568 SYSERROR("failed to get real path for '%s'", rootfs);
4c8ab83b 569 return -1;
570 }
b09ef133 571
b09ef133 572 if (access(absrootfs, F_OK)) {
36eb9bde 573 SYSERROR("'%s' is not accessible", absrootfs);
b09ef133 574 return -1;
575 }
576
78ae2fcc 577 if (stat(absrootfs, &s)) {
36eb9bde 578 SYSERROR("failed to stat '%s'", absrootfs);
9b0f0477 579 return -1;
580 }
581
78ae2fcc 582 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
9b0f0477 583
78ae2fcc 584 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
585 continue;
9b0f0477 586
a6afdde9 587 return rtfs_type[i].cb(absrootfs, target);
78ae2fcc 588 }
9b0f0477 589
36eb9bde 590 ERROR("unsupported rootfs type for '%s'", absrootfs);
78ae2fcc 591 return -1;
0ad19a3f 592}
593
4e5440c6 594static int setup_utsname(struct utsname *utsname)
0ad19a3f 595{
4e5440c6
DL
596 if (!utsname)
597 return 0;
0ad19a3f 598
4e5440c6
DL
599 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
600 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
0ad19a3f 601 return -1;
602 }
603
4e5440c6 604 INFO("'%s' hostname has been setup", utsname->nodename);
cd54d859 605
0ad19a3f 606 return 0;
607}
608
33fcb7a0 609static int setup_tty(const struct lxc_rootfs *rootfs,
7c6ef2a2 610 const struct lxc_tty_info *tty_info, char *ttydir)
b0a33c1e 611{
7c6ef2a2
SH
612 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
613 int i, ret;
b0a33c1e 614
bc9bd0e3
DL
615 if (!rootfs->path)
616 return 0;
617
b0a33c1e 618 for (i = 0; i < tty_info->nbtty; i++) {
619
620 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
621
7c6ef2a2 622 ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
12297168 623 rootfs->mount, i + 1);
7c6ef2a2
SH
624 if (ret >= sizeof(path)) {
625 ERROR("pathname too long for ttys");
626 return -1;
627 }
628 if (ttydir) {
629 /* create dev/lxc/tty%d" */
9ba8130c 630 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
7c6ef2a2
SH
631 rootfs->mount, ttydir, i + 1);
632 if (ret >= sizeof(lxcpath)) {
633 ERROR("pathname too long for ttys");
634 return -1;
635 }
636 ret = creat(lxcpath, 0660);
637 if (ret==-1 && errno != EEXIST) {
638 SYSERROR("error creating %s\n", lxcpath);
639 return -1;
640 }
641 close(ret);
642 ret = unlink(path);
643 if (ret && errno != ENOENT) {
644 SYSERROR("error unlinking %s\n", path);
645 return -1;
646 }
b0a33c1e 647
7c6ef2a2
SH
648 if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
649 WARN("failed to mount '%s'->'%s'",
650 pty_info->name, path);
651 continue;
652 }
13954cce 653
9ba8130c
SH
654 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
655 if (ret >= sizeof(lxcpath)) {
656 ERROR("tty pathname too long");
657 return -1;
658 }
7c6ef2a2
SH
659 ret = symlink(lxcpath, path);
660 if (ret) {
661 SYSERROR("failed to create symlink for tty %d\n", i+1);
662 return -1;
663 }
664 } else {
c6883f38
SH
665 /* If we populated /dev, then we need to create /dev/ttyN */
666 if (access(path, F_OK)) {
667 ret = creat(path, 0660);
668 if (ret==-1) {
669 SYSERROR("error creating %s\n", path);
670 /* this isn't fatal, continue */
671 } else
672 close(ret);
673 }
7c6ef2a2
SH
674 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
675 WARN("failed to mount '%s'->'%s'",
676 pty_info->name, path);
677 continue;
678 }
b0a33c1e 679 }
680 }
681
cd54d859
DL
682 INFO("%d tty(s) has been setup", tty_info->nbtty);
683
b0a33c1e 684 return 0;
685}
686
7a7ff0c6 687static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
bf601689
MH
688{
689 struct lxc_list *mountlist, *listentry, *iterator;
690 char *pivotdir, *mountpoint, *mountentry;
691 int found;
692 void **cbparm;
693
694 mountentry = buffer;
695 cbparm = (void **)data;
696
697 mountlist = cbparm[0];
698 pivotdir = cbparm[1];
699
700 /* parse entry, first field is mountname, ignore */
701 mountpoint = strtok(mountentry, " ");
702 if (!mountpoint)
703 return -1;
704
705 /* second field is mountpoint */
706 mountpoint = strtok(NULL, " ");
707 if (!mountpoint)
708 return -1;
709
710 /* only consider mountpoints below old root fs */
711 if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
712 return 0;
713
714 /* filter duplicate mountpoints */
715 found = 0;
716 lxc_list_for_each(iterator, mountlist) {
717 if (!strcmp(iterator->elem, mountpoint)) {
718 found = 1;
719 break;
720 }
721 }
722 if (found)
723 return 0;
724
725 /* add entry to list */
726 listentry = malloc(sizeof(*listentry));
727 if (!listentry) {
728 SYSERROR("malloc for mountpoint listentry failed");
729 return -1;
730 }
731
732 listentry->elem = strdup(mountpoint);
733 if (!listentry->elem) {
734 SYSERROR("strdup failed");
735 return -1;
736 }
737 lxc_list_add_tail(mountlist, listentry);
738
739 return 0;
740}
741
cc6f6dd7 742static int umount_oldrootfs(const char *oldrootfs)
bf601689 743{
2382ecff 744 char path[MAXPATHLEN];
bf601689 745 void *cbparm[2];
9ebb03ad 746 struct lxc_list mountlist, *iterator, *next;
bf601689 747 int ok, still_mounted, last_still_mounted;
9ba8130c 748 int rc;
bf601689
MH
749
750 /* read and parse /proc/mounts in old root fs */
751 lxc_list_init(&mountlist);
752
cc6f6dd7 753 /* oldrootfs is on the top tree directory now */
9ba8130c
SH
754 rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
755 if (rc >= sizeof(path)) {
756 ERROR("rootfs name too long");
757 return -1;
758 }
bf601689 759 cbparm[0] = &mountlist;
bf601689 760
cc6f6dd7 761 cbparm[1] = strdup(path);
bf601689
MH
762 if (!cbparm[1]) {
763 SYSERROR("strdup failed");
764 return -1;
765 }
766
9ba8130c
SH
767 rc = snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
768 if (rc >= sizeof(path)) {
769 ERROR("container proc/mounts name too long");
770 return -1;
771 }
cc6f6dd7
DL
772
773 ok = lxc_file_for_each_line(path,
774 setup_rootfs_pivot_root_cb, &cbparm);
bf601689
MH
775 if (ok < 0) {
776 SYSERROR("failed to read or parse mount list '%s'", path);
777 return -1;
778 }
779
780 /* umount filesystems until none left or list no longer shrinks */
781 still_mounted = 0;
782 do {
783 last_still_mounted = still_mounted;
784 still_mounted = 0;
785
9ebb03ad 786 lxc_list_for_each_safe(iterator, &mountlist, next) {
bf601689 787
c08556c6 788 /* umount normally */
bf601689
MH
789 if (!umount(iterator->elem)) {
790 DEBUG("umounted '%s'", (char *)iterator->elem);
791 lxc_list_del(iterator);
792 continue;
793 }
794
bf601689
MH
795 still_mounted++;
796 }
7df119ee 797
bf601689
MH
798 } while (still_mounted > 0 && still_mounted != last_still_mounted);
799
7df119ee 800
c08556c6
DL
801 lxc_list_for_each(iterator, &mountlist) {
802
803 /* let's try a lazy umount */
804 if (!umount2(iterator->elem, MNT_DETACH)) {
805 INFO("lazy unmount of '%s'", (char *)iterator->elem);
806 continue;
807 }
808
809 /* be more brutal (nfs) */
810 if (!umount2(iterator->elem, MNT_FORCE)) {
811 INFO("forced unmount of '%s'", (char *)iterator->elem);
812 continue;
813 }
814
7df119ee 815 WARN("failed to unmount '%s'", (char *)iterator->elem);
c08556c6 816 }
bf601689 817
cc6f6dd7
DL
818 return 0;
819}
820
821static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
822{
823 char path[MAXPATHLEN];
824 int remove_pivotdir = 0;
9ba8130c 825 int rc;
cc6f6dd7
DL
826
827 /* change into new root fs */
828 if (chdir(rootfs)) {
829 SYSERROR("can't chdir to new rootfs '%s'", rootfs);
830 return -1;
831 }
832
833 if (!pivotdir)
30c5d292 834 pivotdir = "lxc_putold";
cc6f6dd7 835
4f9293b1 836 /* compute the full path to pivotdir under rootfs */
9ba8130c
SH
837 rc = snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
838 if (rc >= sizeof(path)) {
839 ERROR("pivot dir name too long");
840 return -1;
841 }
cc6f6dd7
DL
842
843 if (access(path, F_OK)) {
844
845 if (mkdir_p(path, 0755)) {
846 SYSERROR("failed to create pivotdir '%s'", path);
847 return -1;
848 }
849
850 remove_pivotdir = 1;
851 DEBUG("created '%s' directory", path);
852 }
853
854 DEBUG("mountpoint for old rootfs is '%s'", path);
855
856 /* pivot_root into our new root fs */
857 if (pivot_root(".", path)) {
858 SYSERROR("pivot_root syscall failed");
bf601689
MH
859 return -1;
860 }
cc6f6dd7
DL
861
862 if (chdir("/")) {
863 SYSERROR("can't chdir to / after pivot_root");
864 return -1;
865 }
866
867 DEBUG("pivot_root syscall to '%s' successful", rootfs);
868
869 /* we switch from absolute path to relative path */
870 if (umount_oldrootfs(pivotdir))
871 return -1;
bf601689 872
c08556c6
DL
873 /* remove temporary mount point, we don't consider the removing
874 * as fatal */
a91d897a
FW
875 if (remove_pivotdir && rmdir(pivotdir))
876 WARN("can't remove mountpoint '%s': %m", pivotdir);
bf601689 877
bf601689
MH
878 return 0;
879}
880
91c3830e
SH
881/*
882 * Do we want to add options for max size of /dev and a file to
883 * specify which devices to create?
884 */
885static int mount_autodev(char *root)
886{
887 int ret;
888 char path[MAXPATHLEN];
889
890 INFO("Mounting /dev under %s\n", root);
891 ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
892 if (ret < 0 || ret > MAXPATHLEN)
893 return -1;
894 ret = mount("none", path, "tmpfs", 0, "size=100000");
895 if (ret) {
896 SYSERROR("Failed to mount /dev at %s\n", root);
897 return -1;
898 }
899 ret = snprintf(path, MAXPATHLEN, "%s/dev/pts", root);
900 if (ret < 0 || ret >= MAXPATHLEN)
901 return -1;
902 ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
903 if (ret) {
904 SYSERROR("Failed to create /dev/pts in container");
905 return -1;
906 }
907
908 INFO("Mounted /dev under %s\n", root);
909 return 0;
910}
911
912/*
913 * Try to run MAKEDEV console in the container. If something fails,
914 * continue anyway as it should not be detrimental to the container.
915 * This makes sure that things like /dev/vcs* exist.
916 * (Pass devpath in to reduce stack usage)
917 */
918static void run_makedev(char *devpath)
919{
920 int curd;
921 int ret;
922
923 curd = open(".", O_RDONLY);
924 if (curd < 0)
925 return;
926 ret = chdir(devpath);
927 if (ret) {
928 close(curd);
929 return;
930 }
931 if (run_buffer("/sbin/MAKEDEV console"))
932 INFO("Error running MAKEDEV console in %s", devpath);
61435768
SH
933 ret = fchdir(curd);
934 if (ret)
935 INFO("Error returning to original directory: expect breakage");
91c3830e
SH
936 close(curd);
937}
938
c6883f38
SH
939struct lxc_devs {
940 char *name;
941 mode_t mode;
942 int maj;
943 int min;
944};
945
946struct lxc_devs lxc_devs[] = {
947 { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
948 { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
949 { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
950 { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
951 { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
952 { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
953 { "console", S_IFCHR | S_IRUSR | S_IWUSR, 5, 1 },
954};
955
c6883f38
SH
956static int setup_autodev(char *root)
957{
958 int ret;
959 struct lxc_devs *d;
960 char path[MAXPATHLEN];
961 int i;
962
91c3830e
SH
963 INFO("Creating initial consoles under %s/dev\n", root);
964
c6883f38 965 ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
91c3830e
SH
966 if (ret < 0 || ret >= MAXPATHLEN) {
967 ERROR("Error calculating container /dev location");
c6883f38 968 return -1;
91c3830e
SH
969 } else
970 run_makedev(path);
971
972 INFO("Populating /dev under %s\n", root);
c6883f38
SH
973 for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
974 d = &lxc_devs[i];
975 ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
976 if (ret < 0 || ret >= MAXPATHLEN)
977 return -1;
978 ret = mknod(path, d->mode, makedev(d->maj, d->min));
91c3830e 979 if (ret && errno != EEXIST) {
c6883f38
SH
980 SYSERROR("Error creating %s\n", d->name);
981 return -1;
982 }
983 }
c6883f38
SH
984
985 INFO("Populated /dev under %s\n", root);
986 return 0;
987}
988
33fcb7a0 989static int setup_rootfs(const struct lxc_rootfs *rootfs)
0ad19a3f 990{
33fcb7a0 991 if (!rootfs->path)
c69bd12f 992 return 0;
0ad19a3f 993
12297168 994 if (access(rootfs->mount, F_OK)) {
b1789442 995 SYSERROR("failed to access to '%s', check it is present",
12297168 996 rootfs->mount);
b1789442
DL
997 return -1;
998 }
999
2656d231 1000 if (mount_rootfs(rootfs->path, rootfs->mount)) {
a6afdde9 1001 ERROR("failed to mount rootfs");
c3f0a28c 1002 return -1;
1003 }
0ad19a3f 1004
12297168 1005 DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
c69bd12f 1006
ac778708
DL
1007 return 0;
1008}
1009
1010int setup_pivot_root(const struct lxc_rootfs *rootfs)
1011{
ac778708
DL
1012 if (!rootfs->path)
1013 return 0;
1014
12297168 1015 if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
cc6f6dd7 1016 ERROR("failed to setup pivot root");
25368b52 1017 return -1;
c69bd12f
DL
1018 }
1019
25368b52 1020 return 0;
0ad19a3f 1021}
1022
d852c78c 1023static int setup_pts(int pts)
3c26f34e 1024{
77890c6d
SW
1025 char target[PATH_MAX];
1026
d852c78c
DL
1027 if (!pts)
1028 return 0;
3c26f34e 1029
1030 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 1031 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 1032 return -1;
1033 }
1034
a6afdde9
DL
1035 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
1036 "newinstance,ptmxmode=0666")) {
36eb9bde 1037 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 1038 return -1;
1039 }
1040
3c26f34e 1041 if (access("/dev/ptmx", F_OK)) {
1042 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
1043 goto out;
36eb9bde 1044 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 1045 return -1;
1046 }
1047
77890c6d
SW
1048 if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
1049 goto out;
1050
3c26f34e 1051 /* fallback here, /dev/pts/ptmx exists just mount bind */
1052 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 1053 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 1054 return -1;
1055 }
cd54d859
DL
1056
1057 INFO("created new pts instance");
d852c78c 1058
3c26f34e 1059out:
1060 return 0;
1061}
1062
cccc74b5
DL
1063static int setup_personality(int persona)
1064{
1065 if (persona == -1)
1066 return 0;
1067
1068 if (personality(persona) < 0) {
1069 SYSERROR("failed to set personality to '0x%x'", persona);
1070 return -1;
1071 }
1072
1073 INFO("set personality to '0x%x'", persona);
1074
1075 return 0;
1076}
1077
7c6ef2a2 1078static int setup_dev_console(const struct lxc_rootfs *rootfs,
33fcb7a0 1079 const struct lxc_console *console)
6e590161 1080{
63376d7d
DL
1081 char path[MAXPATHLEN];
1082 struct stat s;
7c6ef2a2 1083 int ret;
52e35957 1084
7c6ef2a2
SH
1085 ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1086 if (ret >= sizeof(path)) {
1087 ERROR("console path too long\n");
1088 return -1;
1089 }
52e35957 1090
63376d7d 1091 if (access(path, F_OK)) {
466978b0 1092 WARN("rootfs specified but no console found at '%s'", path);
63376d7d 1093 return 0;
52e35957
DL
1094 }
1095
f78a1f32 1096 if (console->peer == -1) {
63376d7d 1097 INFO("no console output required");
f78a1f32
DL
1098 return 0;
1099 }
ed502555 1100
63376d7d
DL
1101 if (stat(path, &s)) {
1102 SYSERROR("failed to stat '%s'", path);
1103 return -1;
1104 }
1105
1106 if (chmod(console->name, s.st_mode)) {
1107 SYSERROR("failed to set mode '0%o' to '%s'",
1108 s.st_mode, console->name);
1109 return -1;
1110 }
13954cce 1111
63376d7d
DL
1112 if (mount(console->name, path, "none", MS_BIND, 0)) {
1113 ERROR("failed to mount '%s' on '%s'", console->name, path);
6e590161 1114 return -1;
1115 }
1116
63376d7d 1117 INFO("console has been setup");
7c6ef2a2
SH
1118 return 0;
1119}
1120
1121static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
1122 const struct lxc_console *console,
1123 char *ttydir)
1124{
1125 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
1126 int ret;
1127
1128 /* create rootfs/dev/<ttydir> directory */
1129 ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
1130 ttydir);
1131 if (ret >= sizeof(path))
1132 return -1;
1133 ret = mkdir(path, 0755);
1134 if (ret && errno != EEXIST) {
1135 SYSERROR("failed with errno %d to create %s\n", errno, path);
1136 return -1;
1137 }
1138 INFO("created %s\n", path);
1139
1140 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
1141 rootfs->mount, ttydir);
1142 if (ret >= sizeof(lxcpath)) {
1143 ERROR("console path too long\n");
1144 return -1;
1145 }
1146
1147 snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1148 ret = unlink(path);
1149 if (ret && errno != ENOENT) {
1150 SYSERROR("error unlinking %s\n", path);
1151 return -1;
1152 }
1153
1154 ret = creat(lxcpath, 0660);
1155 if (ret==-1 && errno != EEXIST) {
1156 SYSERROR("error %d creating %s\n", errno, lxcpath);
1157 return -1;
1158 }
1159 close(ret);
1160
1161 if (console->peer == -1) {
1162 INFO("no console output required");
1163 return 0;
1164 }
1165
1166 if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
1167 ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
1168 return -1;
1169 }
1170
1171 /* create symlink from rootfs/dev/console to 'lxc/console' */
9ba8130c
SH
1172 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
1173 if (ret >= sizeof(lxcpath)) {
1174 ERROR("lxc/console path too long");
1175 return -1;
1176 }
7c6ef2a2
SH
1177 ret = symlink(lxcpath, path);
1178 if (ret) {
1179 SYSERROR("failed to create symlink for console");
1180 return -1;
1181 }
1182
1183 INFO("console has been setup on %s", lxcpath);
cd54d859 1184
6e590161 1185 return 0;
1186}
1187
7c6ef2a2
SH
1188static int setup_console(const struct lxc_rootfs *rootfs,
1189 const struct lxc_console *console,
1190 char *ttydir)
1191{
1192 /* We don't have a rootfs, /dev/console will be shared */
1193 if (!rootfs->path)
1194 return 0;
1195 if (!ttydir)
1196 return setup_dev_console(rootfs, console);
1197
1198 return setup_ttydir_console(rootfs, console, ttydir);
1199}
1200
1bd051a6
SH
1201static int setup_kmsg(const struct lxc_rootfs *rootfs,
1202 const struct lxc_console *console)
1203{
1204 char kpath[MAXPATHLEN];
1205 int ret;
1206
222fea5a
DE
1207 if (!rootfs->path)
1208 return 0;
1bd051a6
SH
1209 ret = snprintf(kpath, sizeof(kpath), "%s/dev/kmsg", rootfs->mount);
1210 if (ret < 0 || ret >= sizeof(kpath))
1211 return -1;
1212
1213 ret = unlink(kpath);
1214 if (ret && errno != ENOENT) {
1215 SYSERROR("error unlinking %s\n", kpath);
1216 return -1;
1217 }
1218
1219 ret = symlink("console", kpath);
1220 if (ret) {
1221 SYSERROR("failed to create symlink for kmsg");
1222 return -1;
1223 }
1224
1225 return 0;
1226}
1227
102a5303 1228static int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 1229{
102a5303
DL
1230 struct lxc_list *iterator;
1231 struct lxc_cgroup *cg;
88329c69 1232 int ret = -1;
6f4a3756 1233
102a5303
DL
1234 if (lxc_list_empty(cgroups))
1235 return 0;
6f4a3756 1236
102a5303 1237 lxc_list_for_each(iterator, cgroups) {
13954cce 1238
102a5303 1239 cg = iterator->elem;
6f4a3756 1240
102a5303 1241 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 1242 goto out;
6f4a3756 1243
102a5303 1244 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 1245 }
13954cce 1246
88329c69 1247 ret = 0;
cd54d859 1248 INFO("cgroup has been setup");
88329c69
MN
1249out:
1250 return ret;
576f946d 1251}
1252
998ac676
RT
1253static void parse_mntopt(char *opt, unsigned long *flags, char **data)
1254{
1255 struct mount_opt *mo;
1256
1257 /* If opt is found in mount_opt, set or clear flags.
1258 * Otherwise append it to data. */
1259
1260 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
1261 if (!strncmp(opt, mo->name, strlen(mo->name))) {
1262 if (mo->clear)
1263 *flags &= ~mo->flag;
1264 else
1265 *flags |= mo->flag;
1266 return;
1267 }
1268 }
1269
1270 if (strlen(*data))
1271 strcat(*data, ",");
1272 strcat(*data, opt);
1273}
1274
911324ef 1275static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
998ac676
RT
1276 char **mntdata)
1277{
1278 char *s, *data;
1279 char *p, *saveptr = NULL;
1280
911324ef 1281 *mntdata = NULL;
91656ce5 1282 *mntflags = 0L;
911324ef
DL
1283
1284 if (!mntopts)
998ac676
RT
1285 return 0;
1286
911324ef 1287 s = strdup(mntopts);
998ac676 1288 if (!s) {
36eb9bde 1289 SYSERROR("failed to allocate memory");
998ac676
RT
1290 return -1;
1291 }
1292
1293 data = malloc(strlen(s) + 1);
1294 if (!data) {
36eb9bde 1295 SYSERROR("failed to allocate memory");
998ac676
RT
1296 free(s);
1297 return -1;
1298 }
1299 *data = 0;
1300
1301 for (p = strtok_r(s, ",", &saveptr); p != NULL;
1302 p = strtok_r(NULL, ",", &saveptr))
1303 parse_mntopt(p, mntflags, &data);
1304
1305 if (*data)
1306 *mntdata = data;
1307 else
1308 free(data);
1309 free(s);
1310
1311 return 0;
1312}
1313
911324ef
DL
1314static int mount_entry(const char *fsname, const char *target,
1315 const char *fstype, unsigned long mountflags,
1316 const char *data)
1317{
1318 if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
1319 SYSERROR("failed to mount '%s' on '%s'", fsname, target);
1320 return -1;
1321 }
1322
1323 if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
1324
1325 DEBUG("remounting %s on %s to respect bind or remount options",
1326 fsname, target);
1327
1328 if (mount(fsname, target, fstype,
1329 mountflags | MS_REMOUNT, data)) {
1330 SYSERROR("failed to mount '%s' on '%s'",
1331 fsname, target);
1332 return -1;
1333 }
1334 }
1335
1336 DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
1337
1338 return 0;
1339}
1340
1341static inline int mount_entry_on_systemfs(struct mntent *mntent)
0ad19a3f 1342{
998ac676
RT
1343 unsigned long mntflags;
1344 char *mntdata;
911324ef
DL
1345 int ret;
1346
1347 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1348 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1349 return -1;
1350 }
1351
1352 ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
1353 mntent->mnt_type, mntflags, mntdata);
1354
1355 free(mntdata);
1356
1357 return ret;
1358}
1359
1360static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
80a881b2
SH
1361 const struct lxc_rootfs *rootfs,
1362 const char *lxc_name)
911324ef 1363{
013bd428 1364 char *aux;
59760f5d 1365 char path[MAXPATHLEN];
911324ef
DL
1366 unsigned long mntflags;
1367 char *mntdata;
80a881b2 1368 int r, ret = 0, offset;
0ad19a3f 1369
911324ef
DL
1370 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1371 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1372 return -1;
1373 }
1bc60a65 1374
80a881b2 1375 /* if rootfs->path is a blockdev path, allow container fstab to
e29bf450
DE
1376 * use $LXCPATH/CN/rootfs as the target prefix */
1377 r = snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", lxc_name);
80a881b2
SH
1378 if (r < 0 || r >= MAXPATHLEN)
1379 goto skipvarlib;
1380
1381 aux = strstr(mntent->mnt_dir, path);
1382 if (aux) {
1383 offset = strlen(path);
1384 goto skipabs;
1385 }
1386
1387skipvarlib:
013bd428
DL
1388 aux = strstr(mntent->mnt_dir, rootfs->path);
1389 if (!aux) {
1390 WARN("ignoring mount point '%s'", mntent->mnt_dir);
1391 goto out;
1392 }
80a881b2
SH
1393 offset = strlen(rootfs->path);
1394
1395skipabs:
013bd428 1396
9ba8130c 1397 r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
80a881b2
SH
1398 aux + offset);
1399 if (r < 0 || r >= MAXPATHLEN) {
1400 WARN("pathnme too long for '%s'", mntent->mnt_dir);
1401 ret = -1;
1402 goto out;
1403 }
1404
d330fe7b 1405
013bd428 1406 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
911324ef 1407 mntflags, mntdata);
0ad19a3f 1408
013bd428 1409out:
911324ef
DL
1410 free(mntdata);
1411 return ret;
1412}
d330fe7b 1413
911324ef
DL
1414static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1415 const char *rootfs)
1416{
1417 char path[MAXPATHLEN];
1418 unsigned long mntflags;
1419 char *mntdata;
1420 int ret;
d330fe7b 1421
911324ef
DL
1422 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1423 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1424 return -1;
1425 }
d330fe7b 1426
911324ef 1427 /* relative to root mount point */
9ba8130c
SH
1428 ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1429 if (ret >= sizeof(path)) {
1430 ERROR("path name too long");
1431 return -1;
1432 }
911324ef
DL
1433
1434 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1435 mntflags, mntdata);
1436
1437 free(mntdata);
998ac676 1438
911324ef
DL
1439 return ret;
1440}
1441
80a881b2
SH
1442static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
1443 const char *lxc_name)
911324ef
DL
1444{
1445 struct mntent *mntent;
1446 int ret = -1;
e76b8764 1447
911324ef 1448 while ((mntent = getmntent(file))) {
e76b8764 1449
911324ef
DL
1450 if (!rootfs->path) {
1451 if (mount_entry_on_systemfs(mntent))
e76b8764 1452 goto out;
911324ef 1453 continue;
e76b8764
CDC
1454 }
1455
911324ef
DL
1456 /* We have a separate root, mounts are relative to it */
1457 if (mntent->mnt_dir[0] != '/') {
1458 if (mount_entry_on_relative_rootfs(mntent,
1459 rootfs->mount))
1460 goto out;
1461 continue;
1462 }
cd54d859 1463
80a881b2 1464 if (mount_entry_on_absolute_rootfs(mntent, rootfs, lxc_name))
911324ef 1465 goto out;
0ad19a3f 1466 }
cd54d859 1467
0ad19a3f 1468 ret = 0;
cd54d859
DL
1469
1470 INFO("mount points have been setup");
0ad19a3f 1471out:
e7938e9e
MN
1472 return ret;
1473}
1474
80a881b2
SH
1475static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
1476 const char *lxc_name)
e7938e9e
MN
1477{
1478 FILE *file;
1479 int ret;
1480
1481 if (!fstab)
1482 return 0;
1483
1484 file = setmntent(fstab, "r");
1485 if (!file) {
1486 SYSERROR("failed to use '%s'", fstab);
1487 return -1;
1488 }
1489
80a881b2 1490 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e 1491
0ad19a3f 1492 endmntent(file);
1493 return ret;
1494}
1495
80a881b2
SH
1496static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
1497 const char *lxc_name)
e7938e9e
MN
1498{
1499 FILE *file;
1500 struct lxc_list *iterator;
1501 char *mount_entry;
1502 int ret;
1503
1504 file = tmpfile();
1505 if (!file) {
1506 ERROR("tmpfile error: %m");
1507 return -1;
1508 }
1509
1510 lxc_list_for_each(iterator, mount) {
1511 mount_entry = iterator->elem;
1d6b1976 1512 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
1513 }
1514
1515 rewind(file);
1516
80a881b2 1517 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e
MN
1518
1519 fclose(file);
1520 return ret;
1521}
1522
81810dd1
DL
1523static int setup_caps(struct lxc_list *caps)
1524{
1525 struct lxc_list *iterator;
1526 char *drop_entry;
d55bc1ad 1527 char *ptr;
81810dd1
DL
1528 int i, capid;
1529
1530 lxc_list_for_each(iterator, caps) {
1531
1532 drop_entry = iterator->elem;
1533
1534 capid = -1;
1535
1536 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1537
1538 if (strcmp(drop_entry, caps_opt[i].name))
1539 continue;
1540
1541 capid = caps_opt[i].value;
1542 break;
1543 }
1544
d55bc1ad
CS
1545 if (capid < 0) {
1546 /* try to see if it's numeric, so the user may specify
1547 * capabilities that the running kernel knows about but
1548 * we don't */
1549 capid = strtol(drop_entry, &ptr, 10);
1550 if (!ptr || *ptr != '\0' ||
1551 capid == LONG_MIN || capid == LONG_MAX)
1552 /* not a valid number */
1553 capid = -1;
1554 else if (capid > lxc_caps_last_cap())
1555 /* we have a number but it's not a valid
1556 * capability */
1557 capid = -1;
1558 }
1559
81810dd1 1560 if (capid < 0) {
1e11be34
DL
1561 ERROR("unknown capability %s", drop_entry);
1562 return -1;
81810dd1
DL
1563 }
1564
1565 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1566
1567 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1568 SYSERROR("failed to remove %s capability", drop_entry);
1569 return -1;
1570 }
1571
1572 }
1573
1574 DEBUG("capabilities has been setup");
1575
1576 return 0;
1577}
1578
0ad19a3f 1579static int setup_hw_addr(char *hwaddr, const char *ifname)
1580{
1581 struct sockaddr sockaddr;
1582 struct ifreq ifr;
1583 int ret, fd;
1584
3cfc0f3a
MN
1585 ret = lxc_convert_mac(hwaddr, &sockaddr);
1586 if (ret) {
1587 ERROR("mac address '%s' conversion failed : %s",
1588 hwaddr, strerror(-ret));
0ad19a3f 1589 return -1;
1590 }
1591
1592 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1593 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1594
1595 fd = socket(AF_INET, SOCK_DGRAM, 0);
1596 if (fd < 0) {
3ab87b66 1597 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 1598 return -1;
1599 }
1600
1601 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1602 close(fd);
1603 if (ret)
3ab87b66 1604 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 1605
cd54d859
DL
1606 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1607
0ad19a3f 1608 return ret;
1609}
1610
82d5ae15 1611static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1612{
82d5ae15
DL
1613 struct lxc_list *iterator;
1614 struct lxc_inetdev *inetdev;
3cfc0f3a 1615 int err;
0ad19a3f 1616
82d5ae15
DL
1617 lxc_list_for_each(iterator, ip) {
1618
1619 inetdev = iterator->elem;
1620
0093bb8c
DL
1621 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1622 &inetdev->bcast, inetdev->prefix);
3cfc0f3a
MN
1623 if (err) {
1624 ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1625 ifindex, strerror(-err));
82d5ae15
DL
1626 return -1;
1627 }
1628 }
1629
1630 return 0;
0ad19a3f 1631}
1632
82d5ae15 1633static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1634{
82d5ae15 1635 struct lxc_list *iterator;
7fa9074f 1636 struct lxc_inet6dev *inet6dev;
3cfc0f3a 1637 int err;
0ad19a3f 1638
82d5ae15
DL
1639 lxc_list_for_each(iterator, ip) {
1640
1641 inet6dev = iterator->elem;
1642
b3df193c 1643 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
0093bb8c
DL
1644 &inet6dev->mcast, &inet6dev->acast,
1645 inet6dev->prefix);
3cfc0f3a
MN
1646 if (err) {
1647 ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1648 ifindex, strerror(-err));
82d5ae15 1649 return -1;
3cfc0f3a 1650 }
82d5ae15
DL
1651 }
1652
1653 return 0;
0ad19a3f 1654}
1655
82d5ae15 1656static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 1657{
0ad19a3f 1658 char ifname[IFNAMSIZ];
0ad19a3f 1659 char *current_ifname = ifname;
3cfc0f3a 1660 int err;
0ad19a3f 1661
82d5ae15
DL
1662 /* empty network namespace */
1663 if (!netdev->ifindex) {
b0efbac4 1664 if (netdev->flags & IFF_UP) {
d472214b 1665 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1666 if (err) {
1667 ERROR("failed to set the loopback up : %s",
1668 strerror(-err));
82d5ae15
DL
1669 return -1;
1670 }
82d5ae15 1671 }
7b57e8b6 1672 return 0;
0ad19a3f 1673 }
13954cce 1674
82d5ae15
DL
1675 /* retrieve the name of the interface */
1676 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 1677 ERROR("no interface corresponding to index '%d'",
82d5ae15 1678 netdev->ifindex);
0ad19a3f 1679 return -1;
1680 }
13954cce 1681
018ef520 1682 /* default: let the system to choose one interface name */
9d083402 1683 if (!netdev->name)
fb6d9b2f
DL
1684 netdev->name = netdev->type == LXC_NET_PHYS ?
1685 netdev->link : "eth%d";
018ef520 1686
82d5ae15 1687 /* rename the interface name */
b84f58b9 1688 err = lxc_netdev_rename_by_name(ifname, netdev->name);
3cfc0f3a
MN
1689 if (err) {
1690 ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1691 strerror(-err));
018ef520
DL
1692 return -1;
1693 }
1694
1695 /* Re-read the name of the interface because its name has changed
1696 * and would be automatically allocated by the system
1697 */
82d5ae15 1698 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 1699 ERROR("no interface corresponding to index '%d'",
82d5ae15 1700 netdev->ifindex);
018ef520 1701 return -1;
0ad19a3f 1702 }
1703
82d5ae15
DL
1704 /* set a mac address */
1705 if (netdev->hwaddr) {
1706 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 1707 ERROR("failed to setup hw address for '%s'",
82d5ae15 1708 current_ifname);
0ad19a3f 1709 return -1;
1710 }
1711 }
1712
82d5ae15
DL
1713 /* setup ipv4 addresses on the interface */
1714 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 1715 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 1716 ifname);
1717 return -1;
1718 }
1719
82d5ae15
DL
1720 /* setup ipv6 addresses on the interface */
1721 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1722 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1723 ifname);
1724 return -1;
1725 }
1726
82d5ae15 1727 /* set the network device up */
b0efbac4 1728 if (netdev->flags & IFF_UP) {
3cfc0f3a
MN
1729 int err;
1730
d472214b 1731 err = lxc_netdev_up(current_ifname);
3cfc0f3a
MN
1732 if (err) {
1733 ERROR("failed to set '%s' up : %s", current_ifname,
1734 strerror(-err));
0ad19a3f 1735 return -1;
1736 }
1737
1738 /* the network is up, make the loopback up too */
d472214b 1739 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1740 if (err) {
1741 ERROR("failed to set the loopback up : %s",
1742 strerror(-err));
0ad19a3f 1743 return -1;
1744 }
1745 }
1746
f8fee0e2
MK
1747 /* We can only set up the default routes after bringing
1748 * up the interface, sine bringing up the interface adds
1749 * the link-local routes and we can't add a default
1750 * route if the gateway is not reachable. */
1751
1752 /* setup ipv4 gateway on the interface */
1753 if (netdev->ipv4_gateway) {
1754 if (!(netdev->flags & IFF_UP)) {
1755 ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
1756 return -1;
1757 }
1758
1759 if (lxc_list_empty(&netdev->ipv4)) {
1760 ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
1761 return -1;
1762 }
1763
1764 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
1765 if (err) {
1766 ERROR("failed to setup ipv4 gateway for '%s': %s",
1767 ifname, strerror(-err));
19a26f82
MK
1768 if (netdev->ipv4_gateway_auto) {
1769 char buf[INET_ADDRSTRLEN];
1770 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1771 ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
1772 }
f8fee0e2
MK
1773 return -1;
1774 }
1775 }
1776
1777 /* setup ipv6 gateway on the interface */
1778 if (netdev->ipv6_gateway) {
1779 if (!(netdev->flags & IFF_UP)) {
1780 ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
1781 return -1;
1782 }
1783
1784 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
1785 ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
1786 return -1;
1787 }
1788
1789 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
1790 if (err) {
1791 ERROR("failed to setup ipv6 gateway for '%s': %s",
1792 ifname, strerror(-err));
19a26f82
MK
1793 if (netdev->ipv6_gateway_auto) {
1794 char buf[INET6_ADDRSTRLEN];
72d0e1cb 1795 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
19a26f82
MK
1796 ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
1797 }
f8fee0e2
MK
1798 return -1;
1799 }
1800 }
1801
cd54d859
DL
1802 DEBUG("'%s' has been setup", current_ifname);
1803
0ad19a3f 1804 return 0;
1805}
1806
5f4535a3 1807static int setup_network(struct lxc_list *network)
0ad19a3f 1808{
82d5ae15 1809 struct lxc_list *iterator;
82d5ae15 1810 struct lxc_netdev *netdev;
0ad19a3f 1811
5f4535a3 1812 lxc_list_for_each(iterator, network) {
cd54d859 1813
5f4535a3 1814 netdev = iterator->elem;
82d5ae15
DL
1815
1816 if (setup_netdev(netdev)) {
1817 ERROR("failed to setup netdev");
1818 return -1;
1819 }
1820 }
cd54d859 1821
5f4535a3
DL
1822 if (!lxc_list_empty(network))
1823 INFO("network has been setup");
cd54d859
DL
1824
1825 return 0;
0ad19a3f 1826}
1827
7b35f3d6
SH
1828void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf)
1829{
1830 int i;
1831
1832 INFO("running to reset %d nic names", conf->num_savednics);
1833 for (i=0; i<conf->num_savednics; i++) {
1834 struct saved_nic *s = &conf->saved_nics[i];
1835 INFO("resetting nic %d to %s\n", s->ifindex, s->orig_name);
1836 lxc_netdev_rename_by_index(s->ifindex, s->orig_name);
1837 free(s->orig_name);
1838 }
1839 conf->num_savednics = 0;
1840 free(conf->saved_nics);
1841}
1842
49684c0b
CS
1843static int setup_private_host_hw_addr(char *veth1)
1844{
1845 struct ifreq ifr;
1846 int err;
1847 int sockfd;
1848
1849 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1850 if (sockfd < 0)
1851 return -errno;
1852
1853 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1854 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1855 if (err < 0) {
1856 close(sockfd);
1857 return -errno;
1858 }
1859
1860 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1861 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
1862 close(sockfd);
1863 if (err < 0)
1864 return -errno;
1865
7ad84da7
DL
1866 DEBUG("mac address of host interface '%s' changed to private "
1867 "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
1868 ifr.ifr_hwaddr.sa_data[0] & 0xff,
1869 ifr.ifr_hwaddr.sa_data[1] & 0xff,
1870 ifr.ifr_hwaddr.sa_data[2] & 0xff,
1871 ifr.ifr_hwaddr.sa_data[3] & 0xff,
1872 ifr.ifr_hwaddr.sa_data[4] & 0xff,
1873 ifr.ifr_hwaddr.sa_data[5] & 0xff);
49684c0b
CS
1874
1875 return 0;
1876}
1877
ae9242c8
SH
1878static char *default_rootfs_mount = LXCROOTFSMOUNT;
1879
7b379ab3 1880struct lxc_conf *lxc_conf_init(void)
089cd8b8 1881{
7b379ab3 1882 struct lxc_conf *new;
26ddeedd 1883 int i;
7b379ab3
MN
1884
1885 new = malloc(sizeof(*new));
1886 if (!new) {
1887 ERROR("lxc_conf_init : %m");
1888 return NULL;
1889 }
1890 memset(new, 0, sizeof(*new));
1891
cccc74b5 1892 new->personality = -1;
28a4b0e5 1893 new->console.path = NULL;
63376d7d
DL
1894 new->console.peer = -1;
1895 new->console.master = -1;
1896 new->console.slave = -1;
1897 new->console.name[0] = '\0';
d2e30e99 1898 new->maincmd_fd = -1;
ae9242c8 1899 new->rootfs.mount = default_rootfs_mount;
4a85ce2a 1900 new->loglevel = LXC_LOG_PRIORITY_NOTSET;
7b379ab3
MN
1901 lxc_list_init(&new->cgroup);
1902 lxc_list_init(&new->network);
1903 lxc_list_init(&new->mount_list);
81810dd1 1904 lxc_list_init(&new->caps);
26ddeedd
SH
1905 for (i=0; i<NUM_LXC_HOOKS; i++)
1906 lxc_list_init(&new->hooks[i]);
e075f5d9
SH
1907#if HAVE_APPARMOR
1908 new->aa_profile = NULL;
1909#endif
1910#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
1911 new->lsm_umount_proc = 0;
1912#endif
7b379ab3
MN
1913
1914 return new;
089cd8b8
DL
1915}
1916
e3b4c4c4 1917static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1918{
8634bc19 1919 char veth1buf[IFNAMSIZ], *veth1;
0e391e57 1920 char veth2buf[IFNAMSIZ], *veth2;
3cfc0f3a 1921 int err;
13954cce 1922
e892973e
DL
1923 if (netdev->priv.veth_attr.pair)
1924 veth1 = netdev->priv.veth_attr.pair;
8634bc19 1925 else {
9ba8130c
SH
1926 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
1927 if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
1928 ERROR("veth1 name too long");
1929 return -1;
1930 }
0e391e57 1931 veth1 = mktemp(veth1buf);
74a2b586
JK
1932 /* store away for deconf */
1933 memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
8634bc19 1934 }
82d5ae15 1935
0e391e57
DL
1936 snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
1937 veth2 = mktemp(veth2buf);
82d5ae15
DL
1938
1939 if (!strlen(veth1) || !strlen(veth2)) {
1940 ERROR("failed to allocate a temporary name");
1941 return -1;
0ad19a3f 1942 }
1943
3cfc0f3a
MN
1944 err = lxc_veth_create(veth1, veth2);
1945 if (err) {
1946 ERROR("failed to create %s-%s : %s", veth1, veth2,
1947 strerror(-err));
6ab9ab6d 1948 return -1;
0ad19a3f 1949 }
13954cce 1950
49684c0b
CS
1951 /* changing the high byte of the mac address to 0xfe, the bridge interface
1952 * will always keep the host's mac address and not take the mac address
1953 * of a container */
1954 err = setup_private_host_hw_addr(veth1);
1955 if (err) {
1956 ERROR("failed to change mac address of host interface '%s' : %s",
1957 veth1, strerror(-err));
1958 goto out_delete;
1959 }
1960
82d5ae15 1961 if (netdev->mtu) {
d472214b 1962 err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
3cfc0f3a 1963 if (!err)
d472214b 1964 err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
3cfc0f3a
MN
1965 if (err) {
1966 ERROR("failed to set mtu '%s' for %s-%s : %s",
1967 netdev->mtu, veth1, veth2, strerror(-err));
eb14c10a 1968 goto out_delete;
75d09f83
DL
1969 }
1970 }
1971
3cfc0f3a
MN
1972 if (netdev->link) {
1973 err = lxc_bridge_attach(netdev->link, veth1);
1974 if (err) {
1975 ERROR("failed to attach '%s' to the bridge '%s' : %s",
1976 veth1, netdev->link, strerror(-err));
1977 goto out_delete;
1978 }
eb14c10a
DL
1979 }
1980
82d5ae15
DL
1981 netdev->ifindex = if_nametoindex(veth2);
1982 if (!netdev->ifindex) {
36eb9bde 1983 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
1984 goto out_delete;
1985 }
1986
d472214b 1987 err = lxc_netdev_up(veth1);
6e35af2e
DL
1988 if (err) {
1989 ERROR("failed to set %s up : %s", veth1, strerror(-err));
1990 goto out_delete;
0ad19a3f 1991 }
1992
e3b4c4c4 1993 if (netdev->upscript) {
751d9dcd
DL
1994 err = run_script(handler->name, "net", netdev->upscript, "up",
1995 "veth", veth1, (char*) NULL);
1996 if (err)
e3b4c4c4 1997 goto out_delete;
e3b4c4c4
ST
1998 }
1999
82d5ae15
DL
2000 DEBUG("instanciated veth '%s/%s', index is '%d'",
2001 veth1, veth2, netdev->ifindex);
2002
6ab9ab6d 2003 return 0;
eb14c10a
DL
2004
2005out_delete:
b84f58b9 2006 lxc_netdev_delete_by_name(veth1);
6ab9ab6d 2007 return -1;
13954cce 2008}
d957ae2d 2009
74a2b586
JK
2010static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
2011{
2012 char *veth1;
2013 int err;
2014
2015 if (netdev->priv.veth_attr.pair)
2016 veth1 = netdev->priv.veth_attr.pair;
2017 else
2018 veth1 = netdev->priv.veth_attr.veth1;
2019
2020 if (netdev->downscript) {
2021 err = run_script(handler->name, "net", netdev->downscript,
2022 "down", "veth", veth1, (char*) NULL);
2023 if (err)
2024 return -1;
2025 }
2026 return 0;
2027}
2028
e3b4c4c4 2029static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2030{
0e391e57 2031 char peerbuf[IFNAMSIZ], *peer;
3cfc0f3a 2032 int err;
d957ae2d
MT
2033
2034 if (!netdev->link) {
2035 ERROR("no link specified for macvlan netdev");
2036 return -1;
2037 }
13954cce 2038
9ba8130c
SH
2039 err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
2040 if (err >= sizeof(peerbuf))
2041 return -1;
82d5ae15 2042
0e391e57 2043 peer = mktemp(peerbuf);
82d5ae15
DL
2044 if (!strlen(peer)) {
2045 ERROR("failed to make a temporary name");
2046 return -1;
0ad19a3f 2047 }
2048
3cfc0f3a
MN
2049 err = lxc_macvlan_create(netdev->link, peer,
2050 netdev->priv.macvlan_attr.mode);
2051 if (err) {
2052 ERROR("failed to create macvlan interface '%s' on '%s' : %s",
2053 peer, netdev->link, strerror(-err));
d957ae2d 2054 return -1;
0ad19a3f 2055 }
2056
82d5ae15
DL
2057 netdev->ifindex = if_nametoindex(peer);
2058 if (!netdev->ifindex) {
36eb9bde 2059 ERROR("failed to retrieve the index for %s", peer);
b84f58b9 2060 lxc_netdev_delete_by_name(peer);
d957ae2d 2061 return -1;
22ebac19 2062 }
2063
e3b4c4c4 2064 if (netdev->upscript) {
751d9dcd
DL
2065 err = run_script(handler->name, "net", netdev->upscript, "up",
2066 "macvlan", netdev->link, (char*) NULL);
2067 if (err)
e3b4c4c4 2068 return -1;
e3b4c4c4
ST
2069 }
2070
e892973e
DL
2071 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
2072 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 2073
d957ae2d 2074 return 0;
0ad19a3f 2075}
2076
74a2b586
JK
2077static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2078{
2079 int err;
2080
2081 if (netdev->downscript) {
2082 err = run_script(handler->name, "net", netdev->downscript,
2083 "down", "macvlan", netdev->link,
2084 (char*) NULL);
2085 if (err)
2086 return -1;
2087 }
2088 return 0;
2089}
2090
26c39028 2091/* XXX: merge with instanciate_macvlan */
e3b4c4c4 2092static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
26c39028
JHS
2093{
2094 char peer[IFNAMSIZ];
3cfc0f3a 2095 int err;
26c39028
JHS
2096
2097 if (!netdev->link) {
2098 ERROR("no link specified for vlan netdev");
2099 return -1;
2100 }
2101
9ba8130c
SH
2102 err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
2103 if (err >= sizeof(peer)) {
2104 ERROR("peer name too long");
2105 return -1;
2106 }
26c39028 2107
3cfc0f3a
MN
2108 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
2109 if (err) {
2110 ERROR("failed to create vlan interface '%s' on '%s' : %s",
2111 peer, netdev->link, strerror(-err));
26c39028
JHS
2112 return -1;
2113 }
2114
2115 netdev->ifindex = if_nametoindex(peer);
2116 if (!netdev->ifindex) {
2117 ERROR("failed to retrieve the ifindex for %s", peer);
b84f58b9 2118 lxc_netdev_delete_by_name(peer);
26c39028
JHS
2119 return -1;
2120 }
2121
e892973e
DL
2122 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
2123 netdev->ifindex);
2124
26c39028
JHS
2125 return 0;
2126}
2127
74a2b586
JK
2128static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2129{
2130 return 0;
2131}
2132
e3b4c4c4 2133static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2134{
6168e99f
DL
2135 if (!netdev->link) {
2136 ERROR("no link specified for the physical interface");
2137 return -1;
2138 }
2139
9d083402 2140 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 2141 if (!netdev->ifindex) {
9d083402 2142 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 2143 return -1;
2144 }
2145
e3b4c4c4
ST
2146 if (netdev->upscript) {
2147 int err;
751d9dcd
DL
2148 err = run_script(handler->name, "net", netdev->upscript,
2149 "up", "phys", netdev->link, (char*) NULL);
2150 if (err)
e3b4c4c4 2151 return -1;
e3b4c4c4
ST
2152 }
2153
82d5ae15 2154 return 0;
0ad19a3f 2155}
2156
74a2b586
JK
2157static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
2158{
2159 int err;
2160
2161 if (netdev->downscript) {
2162 err = run_script(handler->name, "net", netdev->downscript,
2163 "down", "phys", netdev->link, (char*) NULL);
2164 if (err)
2165 return -1;
2166 }
2167 return 0;
2168}
2169
e3b4c4c4 2170static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2171{
82d5ae15 2172 netdev->ifindex = 0;
e3b4c4c4
ST
2173 if (netdev->upscript) {
2174 int err;
751d9dcd
DL
2175 err = run_script(handler->name, "net", netdev->upscript,
2176 "up", "empty", (char*) NULL);
2177 if (err)
e3b4c4c4 2178 return -1;
e3b4c4c4 2179 }
82d5ae15 2180 return 0;
0ad19a3f 2181}
2182
74a2b586
JK
2183static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
2184{
2185 int err;
2186
2187 if (netdev->downscript) {
2188 err = run_script(handler->name, "net", netdev->downscript,
2189 "down", "empty", (char*) NULL);
2190 if (err)
2191 return -1;
2192 }
2193 return 0;
2194}
2195
e3b4c4c4 2196int lxc_create_network(struct lxc_handler *handler)
0ad19a3f 2197{
e3b4c4c4 2198 struct lxc_list *network = &handler->conf->network;
82d5ae15 2199 struct lxc_list *iterator;
82d5ae15 2200 struct lxc_netdev *netdev;
0ad19a3f 2201
5f4535a3 2202 lxc_list_for_each(iterator, network) {
0ad19a3f 2203
5f4535a3 2204 netdev = iterator->elem;
13954cce 2205
24654103 2206 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
82d5ae15 2207 ERROR("invalid network configuration type '%d'",
5f4535a3 2208 netdev->type);
82d5ae15
DL
2209 return -1;
2210 }
0ad19a3f 2211
e3b4c4c4 2212 if (netdev_conf[netdev->type](handler, netdev)) {
82d5ae15
DL
2213 ERROR("failed to create netdev");
2214 return -1;
2215 }
e3b4c4c4 2216
0ad19a3f 2217 }
2218
2219 return 0;
2220}
2221
74a2b586 2222void lxc_delete_network(struct lxc_handler *handler)
7fef7a06 2223{
74a2b586 2224 struct lxc_list *network = &handler->conf->network;
7fef7a06
DL
2225 struct lxc_list *iterator;
2226 struct lxc_netdev *netdev;
2227
2228 lxc_list_for_each(iterator, network) {
2229 netdev = iterator->elem;
d472214b 2230
74a2b586 2231 if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
d8f8e352
DL
2232 if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
2233 WARN("failed to rename to the initial name the " \
2234 "netdev '%s'", netdev->link);
d472214b 2235 continue;
d8f8e352 2236 }
d472214b 2237
74a2b586
JK
2238 if (netdev_deconf[netdev->type](handler, netdev)) {
2239 WARN("failed to destroy netdev");
2240 }
2241
d8f8e352
DL
2242 /* Recent kernel remove the virtual interfaces when the network
2243 * namespace is destroyed but in case we did not moved the
2244 * interface to the network namespace, we have to destroy it
2245 */
74a2b586
JK
2246 if (netdev->ifindex != 0 &&
2247 lxc_netdev_delete_by_index(netdev->ifindex))
d8f8e352 2248 WARN("failed to remove interface '%s'", netdev->name);
7fef7a06
DL
2249 }
2250}
2251
5f4535a3 2252int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 2253{
82d5ae15 2254 struct lxc_list *iterator;
82d5ae15 2255 struct lxc_netdev *netdev;
3cfc0f3a 2256 int err;
0ad19a3f 2257
5f4535a3 2258 lxc_list_for_each(iterator, network) {
82d5ae15 2259
5f4535a3 2260 netdev = iterator->elem;
82d5ae15 2261
236087a6
DL
2262 /* empty network namespace, nothing to move */
2263 if (!netdev->ifindex)
2264 continue;
2265
d472214b 2266 err = lxc_netdev_move_by_index(netdev->ifindex, pid);
3cfc0f3a
MN
2267 if (err) {
2268 ERROR("failed to move '%s' to the container : %s",
2269 netdev->link, strerror(-err));
82d5ae15
DL
2270 return -1;
2271 }
2272
c1c75c04 2273 DEBUG("move '%s' to '%d'", netdev->name, pid);
0ad19a3f 2274 }
2275
2276 return 0;
2277}
2278
19a26f82
MK
2279int lxc_find_gateway_addresses(struct lxc_handler *handler)
2280{
2281 struct lxc_list *network = &handler->conf->network;
2282 struct lxc_list *iterator;
2283 struct lxc_netdev *netdev;
2284 int link_index;
2285
2286 lxc_list_for_each(iterator, network) {
2287 netdev = iterator->elem;
2288
2289 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2290 continue;
2291
2292 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
2293 ERROR("gateway = auto only supported for "
2294 "veth and macvlan");
2295 return -1;
2296 }
2297
2298 if (!netdev->link) {
2299 ERROR("gateway = auto needs a link interface");
2300 return -1;
2301 }
2302
2303 link_index = if_nametoindex(netdev->link);
2304 if (!link_index)
2305 return -EINVAL;
2306
2307 if (netdev->ipv4_gateway_auto) {
2308 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
2309 ERROR("failed to automatically find ipv4 gateway "
2310 "address from link interface '%s'", netdev->link);
2311 return -1;
2312 }
2313 }
2314
2315 if (netdev->ipv6_gateway_auto) {
2316 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
2317 ERROR("failed to automatically find ipv6 gateway "
2318 "address from link interface '%s'", netdev->link);
2319 return -1;
2320 }
2321 }
2322 }
2323
2324 return 0;
2325}
2326
5e4a62bf 2327int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 2328{
5e4a62bf 2329 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 2330 int i;
b0a33c1e 2331
5e4a62bf
DL
2332 /* no tty in the configuration */
2333 if (!conf->tty)
b0a33c1e 2334 return 0;
2335
13954cce 2336 tty_info->pty_info =
e4e7d59d 2337 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 2338 if (!tty_info->pty_info) {
36eb9bde 2339 SYSERROR("failed to allocate pty_info");
985d15b1 2340 return -1;
b0a33c1e 2341 }
2342
985d15b1 2343 for (i = 0; i < conf->tty; i++) {
13954cce 2344
b0a33c1e 2345 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2346
13954cce 2347 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 2348 pty_info->name, NULL, NULL)) {
36eb9bde 2349 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
2350 tty_info->nbtty = i;
2351 lxc_delete_tty(tty_info);
2352 return -1;
b0a33c1e 2353 }
2354
5332bb84
DL
2355 DEBUG("allocated pty '%s' (%d/%d)",
2356 pty_info->name, pty_info->master, pty_info->slave);
2357
b035ad62
MS
2358 /* Prevent leaking the file descriptors to the container */
2359 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
2360 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
2361
b0a33c1e 2362 pty_info->busy = 0;
2363 }
2364
985d15b1 2365 tty_info->nbtty = conf->tty;
1ac470c0
DL
2366
2367 INFO("tty's configured");
2368
985d15b1 2369 return 0;
b0a33c1e 2370}
2371
2372void lxc_delete_tty(struct lxc_tty_info *tty_info)
2373{
2374 int i;
2375
2376 for (i = 0; i < tty_info->nbtty; i++) {
2377 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2378
2379 close(pty_info->master);
2380 close(pty_info->slave);
2381 }
2382
2383 free(tty_info->pty_info);
2384 tty_info->nbtty = 0;
2385}
2386
571e6ec8 2387int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 2388{
e075f5d9
SH
2389#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2390 int mounted;
2391#endif
2392
571e6ec8 2393 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 2394 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 2395 return -1;
0ad19a3f 2396 }
2397
5f4535a3 2398 if (setup_network(&lxc_conf->network)) {
36eb9bde 2399 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 2400 return -1;
0ad19a3f 2401 }
2402
89eaa05e
SH
2403 if (run_lxc_hooks(name, "pre-mount", lxc_conf)) {
2404 ERROR("failed to run pre-mount hooks for container '%s'.", name);
2405 return -1;
2406 }
5ea6163a 2407
ac778708
DL
2408 if (setup_rootfs(&lxc_conf->rootfs)) {
2409 ERROR("failed to setup rootfs for '%s'", name);
95b5ffaf 2410 return -1;
0ad19a3f 2411 }
2412
c6883f38 2413 if (lxc_conf->autodev) {
91c3830e
SH
2414 if (mount_autodev(lxc_conf->rootfs.mount)) {
2415 ERROR("failed to mount /dev in the container");
c6883f38
SH
2416 return -1;
2417 }
2418 }
2419
80a881b2 2420 if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
36eb9bde 2421 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 2422 return -1;
576f946d 2423 }
2424
80a881b2 2425 if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name)) {
e7938e9e
MN
2426 ERROR("failed to setup the mount entries for '%s'", name);
2427 return -1;
2428 }
2429
773fb9ca
SH
2430 if (run_lxc_hooks(name, "mount", lxc_conf)) {
2431 ERROR("failed to run mount hooks for container '%s'.", name);
2432 return -1;
2433 }
2434
91c3830e
SH
2435 if (lxc_conf->autodev) {
2436 if (setup_autodev(lxc_conf->rootfs.mount)) {
2437 ERROR("failed to populate /dev in the container");
2438 return -1;
2439 }
2440 }
2441
ac778708
DL
2442 if (setup_cgroup(name, &lxc_conf->cgroup)) {
2443 ERROR("failed to setup the cgroups for '%s'", name);
2444 return -1;
2445 }
2446
7c6ef2a2 2447 if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
36eb9bde 2448 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 2449 return -1;
6e590161 2450 }
2451
f62b3449 2452 if (setup_kmsg(&lxc_conf->rootfs, &lxc_conf->console)) // don't fail
1bd051a6 2453 ERROR("failed to setup kmsg for '%s'", name);
1bd051a6 2454
7c6ef2a2 2455 if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
36eb9bde 2456 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 2457 return -1;
b0a33c1e 2458 }
2459
e075f5d9 2460#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
9ac3ffb5
SG
2461 INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
2462 lxc_conf->rootfs.mount);
2463 if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0)
2464 mounted = 0;
2465 else
2466 mounted = lsm_mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
e075f5d9
SH
2467 if (mounted == -1) {
2468 SYSERROR("failed to mount /proc in the container.");
2469 return -1;
2470 } else if (mounted == 1) {
2471 lxc_conf->lsm_umount_proc = 1;
2472 }
2473#endif
2474
ac778708 2475 if (setup_pivot_root(&lxc_conf->rootfs)) {
36eb9bde 2476 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 2477 return -1;
ed502555 2478 }
2479
571e6ec8 2480 if (setup_pts(lxc_conf->pts)) {
36eb9bde 2481 ERROR("failed to setup the new pts instance");
95b5ffaf 2482 return -1;
3c26f34e 2483 }
2484
cccc74b5
DL
2485 if (setup_personality(lxc_conf->personality)) {
2486 ERROR("failed to setup personality");
2487 return -1;
2488 }
2489
81810dd1
DL
2490 if (setup_caps(&lxc_conf->caps)) {
2491 ERROR("failed to drop capabilities");
2492 return -1;
2493 }
2494
cd54d859
DL
2495 NOTICE("'%s' is setup.", name);
2496
0ad19a3f 2497 return 0;
2498}
26ddeedd
SH
2499
2500int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
2501{
2502 int which = -1;
2503 struct lxc_list *it;
2504
2505 if (strcmp(hook, "pre-start") == 0)
2506 which = LXCHOOK_PRESTART;
5ea6163a
SH
2507 else if (strcmp(hook, "pre-mount") == 0)
2508 which = LXCHOOK_PREMOUNT;
26ddeedd
SH
2509 else if (strcmp(hook, "mount") == 0)
2510 which = LXCHOOK_MOUNT;
2511 else if (strcmp(hook, "start") == 0)
2512 which = LXCHOOK_START;
2513 else if (strcmp(hook, "post-stop") == 0)
2514 which = LXCHOOK_POSTSTOP;
2515 else
2516 return -1;
2517 lxc_list_for_each(it, &conf->hooks[which]) {
2518 int ret;
2519 char *hookname = it->elem;
2520 ret = run_script(name, "lxc", hookname, hook, NULL);
2521 if (ret)
2522 return ret;
2523 }
2524 return 0;
2525}
72d0e1cb 2526
427b3a21 2527static void lxc_remove_nic(struct lxc_list *it)
72d0e1cb
SG
2528{
2529 struct lxc_netdev *netdev = it->elem;
9ebb03ad 2530 struct lxc_list *it2,*next;
72d0e1cb
SG
2531
2532 lxc_list_del(it);
2533
2534 if (netdev->link)
2535 free(netdev->link);
2536 if (netdev->name)
2537 free(netdev->name);
2538 if (netdev->upscript)
2539 free(netdev->upscript);
2540 if (netdev->hwaddr)
2541 free(netdev->hwaddr);
2542 if (netdev->mtu)
2543 free(netdev->mtu);
2544 if (netdev->ipv4_gateway)
2545 free(netdev->ipv4_gateway);
2546 if (netdev->ipv6_gateway)
2547 free(netdev->ipv6_gateway);
9ebb03ad 2548 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
72d0e1cb
SG
2549 lxc_list_del(it2);
2550 free(it2->elem);
2551 free(it2);
2552 }
9ebb03ad 2553 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
72d0e1cb
SG
2554 lxc_list_del(it2);
2555 free(it2->elem);
2556 free(it2);
2557 }
d95db067 2558 free(netdev);
72d0e1cb
SG
2559 free(it);
2560}
2561
2562/* we get passed in something like '0', '0.ipv4' or '1.ipv6' */
12a50cc6 2563int lxc_clear_nic(struct lxc_conf *c, const char *key)
72d0e1cb
SG
2564{
2565 char *p1;
2566 int ret, idx, i;
2567 struct lxc_list *it;
2568 struct lxc_netdev *netdev;
2569
2570 p1 = index(key, '.');
2571 if (!p1 || *(p1+1) == '\0')
2572 p1 = NULL;
2573
2574 ret = sscanf(key, "%d", &idx);
2575 if (ret != 1) return -1;
2576 if (idx < 0)
2577 return -1;
2578
2579 i = 0;
2580 lxc_list_for_each(it, &c->network) {
2581 if (i == idx)
2582 break;
2583 i++;
2584 }
2585 if (i < idx) // we don't have that many nics defined
2586 return -1;
2587
2588 if (!it || !it->elem)
2589 return -1;
2590
2591 netdev = it->elem;
2592
2593 if (!p1) {
2594 lxc_remove_nic(it);
2595 } else if (strcmp(p1, "ipv4") == 0) {
9ebb03ad
DE
2596 struct lxc_list *it2,*next;
2597 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
72d0e1cb
SG
2598 lxc_list_del(it2);
2599 free(it2->elem);
2600 free(it2);
2601 }
2602 } else if (strcmp(p1, "ipv6") == 0) {
9ebb03ad
DE
2603 struct lxc_list *it2,*next;
2604 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
72d0e1cb
SG
2605 lxc_list_del(it2);
2606 free(it2->elem);
2607 free(it2);
2608 }
2609 } else if (strcmp(p1, "link") == 0) {
2610 if (netdev->link) {
2611 free(netdev->link);
2612 netdev->link = NULL;
2613 }
2614 } else if (strcmp(p1, "name") == 0) {
2615 if (netdev->name) {
2616 free(netdev->name);
2617 netdev->name = NULL;
2618 }
2619 } else if (strcmp(p1, "script.up") == 0) {
2620 if (netdev->upscript) {
2621 free(netdev->upscript);
2622 netdev->upscript = NULL;
2623 }
2624 } else if (strcmp(p1, "hwaddr") == 0) {
2625 if (netdev->hwaddr) {
2626 free(netdev->hwaddr);
2627 netdev->hwaddr = NULL;
2628 }
2629 } else if (strcmp(p1, "mtu") == 0) {
2630 if (netdev->mtu) {
2631 free(netdev->mtu);
2632 netdev->mtu = NULL;
2633 }
2634 } else if (strcmp(p1, "ipv4_gateway") == 0) {
2635 if (netdev->ipv4_gateway) {
2636 free(netdev->ipv4_gateway);
2637 netdev->ipv4_gateway = NULL;
2638 }
2639 } else if (strcmp(p1, "ipv6_gateway") == 0) {
2640 if (netdev->ipv6_gateway) {
2641 free(netdev->ipv6_gateway);
2642 netdev->ipv6_gateway = NULL;
2643 }
2644 }
2645 else return -1;
2646
2647 return 0;
2648}
2649
2650int lxc_clear_config_network(struct lxc_conf *c)
2651{
9ebb03ad
DE
2652 struct lxc_list *it,*next;
2653 lxc_list_for_each_safe(it, &c->network, next) {
72d0e1cb
SG
2654 lxc_remove_nic(it);
2655 }
2656 return 0;
2657}
2658
2659int lxc_clear_config_caps(struct lxc_conf *c)
2660{
9ebb03ad 2661 struct lxc_list *it,*next;
72d0e1cb 2662
9ebb03ad 2663 lxc_list_for_each_safe(it, &c->caps, next) {
72d0e1cb
SG
2664 lxc_list_del(it);
2665 free(it->elem);
2666 free(it);
2667 }
2668 return 0;
2669}
2670
12a50cc6 2671int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
72d0e1cb 2672{
9ebb03ad 2673 struct lxc_list *it,*next;
72d0e1cb 2674 bool all = false;
12a50cc6 2675 const char *k = key + 11;
72d0e1cb
SG
2676
2677 if (strcmp(key, "lxc.cgroup") == 0)
2678 all = true;
2679
9ebb03ad 2680 lxc_list_for_each_safe(it, &c->cgroup, next) {
72d0e1cb
SG
2681 struct lxc_cgroup *cg = it->elem;
2682 if (!all && strcmp(cg->subsystem, k) != 0)
2683 continue;
2684 lxc_list_del(it);
2685 free(cg->subsystem);
2686 free(cg->value);
2687 free(cg);
2688 free(it);
2689 }
2690 return 0;
2691}
2692
2693int lxc_clear_mount_entries(struct lxc_conf *c)
2694{
9ebb03ad 2695 struct lxc_list *it,*next;
72d0e1cb 2696
9ebb03ad 2697 lxc_list_for_each_safe(it, &c->mount_list, next) {
72d0e1cb
SG
2698 lxc_list_del(it);
2699 free(it->elem);
2700 free(it);
2701 }
2702 return 0;
2703}
2704
12a50cc6 2705int lxc_clear_hooks(struct lxc_conf *c, const char *key)
72d0e1cb 2706{
9ebb03ad 2707 struct lxc_list *it,*next;
17ed13a3 2708 bool all = false, done = false;
12a50cc6 2709 const char *k = key + 9;
72d0e1cb
SG
2710 int i;
2711
17ed13a3
SH
2712 if (strcmp(key, "lxc.hook") == 0)
2713 all = true;
2714
72d0e1cb 2715 for (i=0; i<NUM_LXC_HOOKS; i++) {
17ed13a3 2716 if (all || strcmp(k, lxchook_names[i]) == 0) {
9ebb03ad 2717 lxc_list_for_each_safe(it, &c->hooks[i], next) {
17ed13a3
SH
2718 lxc_list_del(it);
2719 free(it->elem);
2720 free(it);
2721 }
2722 done = true;
72d0e1cb
SG
2723 }
2724 }
17ed13a3
SH
2725
2726 if (!done) {
2727 ERROR("Invalid hook key: %s", key);
2728 return -1;
2729 }
72d0e1cb
SG
2730 return 0;
2731}
8eb5694b 2732
7b35f3d6
SH
2733void lxc_clear_saved_nics(struct lxc_conf *conf)
2734{
2735 int i;
2736
2737 if (!conf->num_savednics)
2738 return;
2739 for (i=0; i < conf->num_savednics; i++)
2740 free(conf->saved_nics[i].orig_name);
2741 conf->saved_nics = 0;
2742 free(conf->saved_nics);
2743}
2744
8eb5694b
SH
2745void lxc_conf_free(struct lxc_conf *conf)
2746{
2747 if (!conf)
2748 return;
2749 if (conf->console.path)
2750 free(conf->console.path);
ae9242c8 2751 if (conf->rootfs.mount != default_rootfs_mount)
8eb5694b 2752 free(conf->rootfs.mount);
d95db067
DE
2753 if (conf->rootfs.path)
2754 free(conf->rootfs.path);
2755 if (conf->utsname)
2756 free(conf->utsname);
2757 if (conf->ttydir)
2758 free(conf->ttydir);
2759 if (conf->fstab)
2760 free(conf->fstab);
4a85ce2a
SH
2761 if (conf->logfile)
2762 free(conf->logfile);
8eb5694b 2763 lxc_clear_config_network(conf);
1f530df6 2764#if HAVE_APPARMOR
8eb5694b
SH
2765 if (conf->aa_profile)
2766 free(conf->aa_profile);
1f530df6 2767#endif
769872f9 2768 lxc_seccomp_free(conf);
8eb5694b
SH
2769 lxc_clear_config_caps(conf);
2770 lxc_clear_cgroups(conf, "lxc.cgroup");
17ed13a3 2771 lxc_clear_hooks(conf, "lxc.hook");
8eb5694b 2772 lxc_clear_mount_entries(conf);
7b35f3d6 2773 lxc_clear_saved_nics(conf);
8eb5694b
SH
2774 free(conf);
2775}