]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
lxc-ubuntu.in: drop duplicate code
[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
CLG
64
65lxc_log_define(lxc_conf, lxc);
e5bda9ee 66
0ad19a3f 67#define MAXHWLEN 18
68#define MAXINDEXLEN 20
442cbbe6 69#define MAXMTULEN 16
0ad19a3f 70#define MAXLINELEN 128
71
968fbd36
SK
72#ifndef MS_DIRSYNC
73#define MS_DIRSYNC 128
74#endif
75
fdc03323
DL
76#ifndef MS_REC
77#define MS_REC 16384
78#endif
79
c08556c6
DL
80#ifndef MNT_DETACH
81#define MNT_DETACH 2
82#endif
83
88d413d5
SW
84#ifndef MS_RELATIME
85#define MS_RELATIME (1 << 21)
86#endif
87
88#ifndef MS_STRICTATIME
89#define MS_STRICTATIME (1 << 24)
90#endif
91
b09094da
MN
92#ifndef CAP_SETFCAP
93#define CAP_SETFCAP 31
94#endif
95
96#ifndef CAP_MAC_OVERRIDE
97#define CAP_MAC_OVERRIDE 32
98#endif
99
100#ifndef CAP_MAC_ADMIN
101#define CAP_MAC_ADMIN 33
102#endif
103
104#ifndef PR_CAPBSET_DROP
105#define PR_CAPBSET_DROP 24
106#endif
107
bf601689
MH
108extern int pivot_root(const char * new_root, const char * put_old);
109
e3b4c4c4 110typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
0ad19a3f 111
998ac676
RT
112struct mount_opt {
113 char *name;
114 int clear;
115 int flag;
116};
117
81810dd1
DL
118struct caps_opt {
119 char *name;
120 int value;
121};
122
e3b4c4c4
ST
123static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
124static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
125static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
126static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
127static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
82d5ae15 128
24654103
DL
129static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
130 [LXC_NET_VETH] = instanciate_veth,
131 [LXC_NET_MACVLAN] = instanciate_macvlan,
132 [LXC_NET_VLAN] = instanciate_vlan,
133 [LXC_NET_PHYS] = instanciate_phys,
134 [LXC_NET_EMPTY] = instanciate_empty,
0ad19a3f 135};
136
998ac676 137static struct mount_opt mount_opt[] = {
88d413d5
SW
138 { "defaults", 0, 0 },
139 { "ro", 0, MS_RDONLY },
140 { "rw", 1, MS_RDONLY },
141 { "suid", 1, MS_NOSUID },
142 { "nosuid", 0, MS_NOSUID },
143 { "dev", 1, MS_NODEV },
144 { "nodev", 0, MS_NODEV },
145 { "exec", 1, MS_NOEXEC },
146 { "noexec", 0, MS_NOEXEC },
147 { "sync", 0, MS_SYNCHRONOUS },
148 { "async", 1, MS_SYNCHRONOUS },
149 { "dirsync", 0, MS_DIRSYNC },
150 { "remount", 0, MS_REMOUNT },
151 { "mand", 0, MS_MANDLOCK },
152 { "nomand", 1, MS_MANDLOCK },
153 { "atime", 1, MS_NOATIME },
154 { "noatime", 0, MS_NOATIME },
155 { "diratime", 1, MS_NODIRATIME },
156 { "nodiratime", 0, MS_NODIRATIME },
157 { "bind", 0, MS_BIND },
158 { "rbind", 0, MS_BIND|MS_REC },
159 { "relatime", 0, MS_RELATIME },
160 { "norelatime", 1, MS_RELATIME },
161 { "strictatime", 0, MS_STRICTATIME },
162 { "nostrictatime", 1, MS_STRICTATIME },
163 { NULL, 0, 0 },
998ac676
RT
164};
165
81810dd1 166static struct caps_opt caps_opt[] = {
a6afdde9 167 { "chown", CAP_CHOWN },
1e11be34
DL
168 { "dac_override", CAP_DAC_OVERRIDE },
169 { "dac_read_search", CAP_DAC_READ_SEARCH },
170 { "fowner", CAP_FOWNER },
171 { "fsetid", CAP_FSETID },
81810dd1
DL
172 { "kill", CAP_KILL },
173 { "setgid", CAP_SETGID },
174 { "setuid", CAP_SETUID },
175 { "setpcap", CAP_SETPCAP },
176 { "linux_immutable", CAP_LINUX_IMMUTABLE },
177 { "net_bind_service", CAP_NET_BIND_SERVICE },
178 { "net_broadcast", CAP_NET_BROADCAST },
179 { "net_admin", CAP_NET_ADMIN },
180 { "net_raw", CAP_NET_RAW },
181 { "ipc_lock", CAP_IPC_LOCK },
182 { "ipc_owner", CAP_IPC_OWNER },
183 { "sys_module", CAP_SYS_MODULE },
184 { "sys_rawio", CAP_SYS_RAWIO },
185 { "sys_chroot", CAP_SYS_CHROOT },
186 { "sys_ptrace", CAP_SYS_PTRACE },
187 { "sys_pacct", CAP_SYS_PACCT },
188 { "sys_admin", CAP_SYS_ADMIN },
189 { "sys_boot", CAP_SYS_BOOT },
190 { "sys_nice", CAP_SYS_NICE },
191 { "sys_resource", CAP_SYS_RESOURCE },
192 { "sys_time", CAP_SYS_TIME },
193 { "sys_tty_config", CAP_SYS_TTY_CONFIG },
194 { "mknod", CAP_MKNOD },
195 { "lease", CAP_LEASE },
9527e566 196#ifdef CAP_AUDIT_WRITE
81810dd1 197 { "audit_write", CAP_AUDIT_WRITE },
9527e566
FW
198#endif
199#ifdef CAP_AUDIT_CONTROL
81810dd1 200 { "audit_control", CAP_AUDIT_CONTROL },
9527e566 201#endif
81810dd1
DL
202 { "setfcap", CAP_SETFCAP },
203 { "mac_override", CAP_MAC_OVERRIDE },
204 { "mac_admin", CAP_MAC_ADMIN },
5170c716
CS
205#ifdef CAP_SYSLOG
206 { "syslog", CAP_SYSLOG },
207#endif
208#ifdef CAP_WAKE_ALARM
209 { "wake_alarm", CAP_WAKE_ALARM },
210#endif
81810dd1
DL
211};
212
751d9dcd
DL
213static int run_script(const char *name, const char *section,
214 const char *script, ...)
e3b4c4c4 215{
abbfd20b
DL
216 int ret;
217 FILE *f;
218 char *buffer, *p, *output;
219 size_t size = 0;
220 va_list ap;
751d9dcd
DL
221
222 INFO("Executing script '%s' for container '%s', config section '%s'",
223 script, name, section);
e3b4c4c4 224
abbfd20b
DL
225 va_start(ap, script);
226 while ((p = va_arg(ap, char *)))
95642a10 227 size += strlen(p) + 1;
abbfd20b
DL
228 va_end(ap);
229
230 size += strlen(script);
231 size += strlen(name);
232 size += strlen(section);
95642a10 233 size += 3;
abbfd20b 234
95642a10
MS
235 if (size > INT_MAX)
236 return -1;
237
238 buffer = alloca(size);
abbfd20b
DL
239 if (!buffer) {
240 ERROR("failed to allocate memory");
751d9dcd
DL
241 return -1;
242 }
243
9ba8130c
SH
244 ret = snprintf(buffer, size, "%s %s %s", script, name, section);
245 if (ret < 0 || ret >= size) {
246 ERROR("Script name too long");
247 free(buffer);
248 return -1;
249 }
751d9dcd 250
abbfd20b 251 va_start(ap, script);
9ba8130c
SH
252 while ((p = va_arg(ap, char *))) {
253 int len = size-ret;
254 int rc;
255 rc = snprintf(buffer + ret, len, " %s", p);
256 if (rc < 0 || rc >= len) {
257 free(buffer);
258 ERROR("Script args too long");
259 return -1;
260 }
261 ret += rc;
262 }
abbfd20b 263 va_end(ap);
751d9dcd 264
abbfd20b
DL
265 f = popen(buffer, "r");
266 if (!f) {
267 SYSERROR("popen failed");
268 return -1;
269 }
e3b4c4c4 270
abbfd20b
DL
271 output = malloc(LXC_LOG_BUFFER_SIZE);
272 if (!output) {
273 ERROR("failed to allocate memory for script output");
274 return -1;
e3b4c4c4 275 }
751d9dcd 276
abbfd20b
DL
277 while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
278 DEBUG("script output: %s", output);
279
280 free(output);
281
282 if (pclose(f)) {
283 ERROR("Script exited on error");
751d9dcd
DL
284 return -1;
285 }
286
287 return 0;
e3b4c4c4
ST
288}
289
a6afdde9 290static int find_fstype_cb(char* buffer, void *data)
78ae2fcc 291{
292 struct cbarg {
293 const char *rootfs;
a6afdde9 294 const char *target;
78ae2fcc 295 int mntopt;
296 } *cbarg = data;
297
298 char *fstype;
299
300 /* we don't try 'nodev' entries */
301 if (strstr(buffer, "nodev"))
302 return 0;
303
304 fstype = buffer;
b2718c72 305 fstype += lxc_char_left_gc(fstype, strlen(fstype));
306 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
78ae2fcc 307
a6afdde9
DL
308 DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
309 cbarg->rootfs, cbarg->target, fstype);
310
311 if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
312 DEBUG("mount failed with error: %s", strerror(errno));
78ae2fcc 313 return 0;
a6afdde9 314 }
78ae2fcc 315
a6afdde9
DL
316 INFO("mounted '%s' on '%s', with fstype '%s'",
317 cbarg->rootfs, cbarg->target, fstype);
78ae2fcc 318
319 return 1;
320}
321
2656d231 322static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
78ae2fcc 323{
a6afdde9 324 int i;
78ae2fcc 325
326 struct cbarg {
327 const char *rootfs;
a6afdde9 328 const char *target;
78ae2fcc 329 int mntopt;
330 } cbarg = {
331 .rootfs = rootfs,
a6afdde9 332 .target = target,
78ae2fcc 333 .mntopt = mntopt,
334 };
335
a6afdde9
DL
336 /*
337 * find the filesystem type with brute force:
338 * first we check with /etc/filesystems, in case the modules
78ae2fcc 339 * are auto-loaded and fall back to the supported kernel fs
340 */
341 char *fsfile[] = {
342 "/etc/filesystems",
343 "/proc/filesystems",
344 };
345
a6afdde9
DL
346 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
347
348 int ret;
349
350 if (access(fsfile[i], F_OK))
351 continue;
352
353 ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
354 if (ret < 0) {
355 ERROR("failed to parse '%s'", fsfile[i]);
356 return -1;
357 }
358
359 if (ret)
360 return 0;
78ae2fcc 361 }
362
a6afdde9
DL
363 ERROR("failed to determine fs type for '%s'", rootfs);
364 return -1;
365}
366
2656d231 367static int mount_rootfs_dir(const char *rootfs, const char *target)
a6afdde9
DL
368{
369 return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
370}
371
372static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
373{
374 int rfd;
375 int ret = -1;
376
377 rfd = open(rootfs, O_RDWR);
378 if (rfd < 0) {
379 SYSERROR("failed to open '%s'", rootfs);
78ae2fcc 380 return -1;
381 }
382
a6afdde9 383 memset(loinfo, 0, sizeof(*loinfo));
78ae2fcc 384
a6afdde9 385 loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
78ae2fcc 386
a6afdde9
DL
387 if (ioctl(fd, LOOP_SET_FD, rfd)) {
388 SYSERROR("failed to LOOP_SET_FD");
389 goto out;
78ae2fcc 390 }
391
a6afdde9
DL
392 if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
393 SYSERROR("failed to LOOP_SET_STATUS64");
78ae2fcc 394 goto out;
395 }
396
a6afdde9 397 ret = 0;
78ae2fcc 398out:
a6afdde9 399 close(rfd);
78ae2fcc 400
a6afdde9 401 return ret;
78ae2fcc 402}
403
2656d231 404static int mount_rootfs_file(const char *rootfs, const char *target)
78ae2fcc 405{
a6afdde9
DL
406 struct dirent dirent, *direntp;
407 struct loop_info64 loinfo;
9ba8130c 408 int ret = -1, fd = -1, rc;
a6afdde9
DL
409 DIR *dir;
410 char path[MAXPATHLEN];
78ae2fcc 411
a6afdde9
DL
412 dir = opendir("/dev");
413 if (!dir) {
414 SYSERROR("failed to open '/dev'");
78ae2fcc 415 return -1;
416 }
417
a6afdde9
DL
418 while (!readdir_r(dir, &dirent, &direntp)) {
419
420 if (!direntp)
421 break;
422
423 if (!strcmp(direntp->d_name, "."))
424 continue;
425
426 if (!strcmp(direntp->d_name, ".."))
427 continue;
428
429 if (strncmp(direntp->d_name, "loop", 4))
430 continue;
431
9ba8130c
SH
432 rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
433 if (rc < 0 || rc >= MAXPATHLEN)
434 continue;
435
a6afdde9
DL
436 fd = open(path, O_RDWR);
437 if (fd < 0)
438 continue;
439
440 if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
441 close(fd);
442 continue;
443 }
444
445 if (errno != ENXIO) {
446 WARN("unexpected error for ioctl on '%s': %m",
447 direntp->d_name);
448 continue;
449 }
450
451 DEBUG("found '%s' free lodev", path);
452
453 ret = setup_lodev(rootfs, fd, &loinfo);
454 if (!ret)
2656d231 455 ret = mount_unknow_fs(path, target, 0);
a6afdde9
DL
456 close(fd);
457
458 break;
459 }
460
461 if (closedir(dir))
462 WARN("failed to close directory");
463
464 return ret;
78ae2fcc 465}
466
2656d231 467static int mount_rootfs_block(const char *rootfs, const char *target)
a6afdde9 468{
2656d231 469 return mount_unknow_fs(rootfs, target, 0);
a6afdde9
DL
470}
471
0c547523
SH
472/*
473 * pin_rootfs
474 * if rootfs is a directory, then open ${rootfs}.hold for writing for the
475 * duration of the container run, to prevent the container from marking the
476 * underlying fs readonly on shutdown.
477 * return -1 on error.
478 * return -2 if nothing needed to be pinned.
479 * return an open fd (>=0) if we pinned it.
480 */
481int pin_rootfs(const char *rootfs)
482{
483 char absrootfs[MAXPATHLEN];
484 char absrootfspin[MAXPATHLEN];
485 struct stat s;
486 int ret, fd;
487
e99ee0de
SH
488 if (rootfs == NULL || strlen(rootfs) == 0)
489 return 0;
490
0c547523
SH
491 if (!realpath(rootfs, absrootfs)) {
492 SYSERROR("failed to get real path for '%s'", rootfs);
493 return -1;
494 }
495
496 if (access(absrootfs, F_OK)) {
497 SYSERROR("'%s' is not accessible", absrootfs);
498 return -1;
499 }
500
501 if (stat(absrootfs, &s)) {
502 SYSERROR("failed to stat '%s'", absrootfs);
503 return -1;
504 }
505
506 if (!__S_ISTYPE(s.st_mode, S_IFDIR))
507 return -2;
508
509 ret = snprintf(absrootfspin, MAXPATHLEN, "%s%s", absrootfs, ".hold");
510 if (ret >= MAXPATHLEN) {
511 SYSERROR("pathname too long for rootfs hold file");
512 return -1;
513 }
514
515 fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
516 INFO("opened %s as fd %d\n", absrootfspin, fd);
517 return fd;
518}
519
2656d231 520static int mount_rootfs(const char *rootfs, const char *target)
0ad19a3f 521{
b09ef133 522 char absrootfs[MAXPATHLEN];
78ae2fcc 523 struct stat s;
a6afdde9 524 int i;
78ae2fcc 525
a6afdde9 526 typedef int (*rootfs_cb)(const char *, const char *);
78ae2fcc 527
528 struct rootfs_type {
529 int type;
530 rootfs_cb cb;
531 } rtfs_type[] = {
2656d231
DL
532 { S_IFDIR, mount_rootfs_dir },
533 { S_IFBLK, mount_rootfs_block },
534 { S_IFREG, mount_rootfs_file },
78ae2fcc 535 };
0ad19a3f 536
4c8ab83b 537 if (!realpath(rootfs, absrootfs)) {
36eb9bde 538 SYSERROR("failed to get real path for '%s'", rootfs);
4c8ab83b 539 return -1;
540 }
b09ef133 541
b09ef133 542 if (access(absrootfs, F_OK)) {
36eb9bde 543 SYSERROR("'%s' is not accessible", absrootfs);
b09ef133 544 return -1;
545 }
546
78ae2fcc 547 if (stat(absrootfs, &s)) {
36eb9bde 548 SYSERROR("failed to stat '%s'", absrootfs);
9b0f0477 549 return -1;
550 }
551
78ae2fcc 552 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
9b0f0477 553
78ae2fcc 554 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
555 continue;
9b0f0477 556
a6afdde9 557 return rtfs_type[i].cb(absrootfs, target);
78ae2fcc 558 }
9b0f0477 559
36eb9bde 560 ERROR("unsupported rootfs type for '%s'", absrootfs);
78ae2fcc 561 return -1;
0ad19a3f 562}
563
4e5440c6 564static int setup_utsname(struct utsname *utsname)
0ad19a3f 565{
4e5440c6
DL
566 if (!utsname)
567 return 0;
0ad19a3f 568
4e5440c6
DL
569 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
570 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
0ad19a3f 571 return -1;
572 }
573
4e5440c6 574 INFO("'%s' hostname has been setup", utsname->nodename);
cd54d859 575
0ad19a3f 576 return 0;
577}
578
33fcb7a0 579static int setup_tty(const struct lxc_rootfs *rootfs,
7c6ef2a2 580 const struct lxc_tty_info *tty_info, char *ttydir)
b0a33c1e 581{
7c6ef2a2
SH
582 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
583 int i, ret;
b0a33c1e 584
bc9bd0e3
DL
585 if (!rootfs->path)
586 return 0;
587
b0a33c1e 588 for (i = 0; i < tty_info->nbtty; i++) {
589
590 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
591
7c6ef2a2 592 ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
12297168 593 rootfs->mount, i + 1);
7c6ef2a2
SH
594 if (ret >= sizeof(path)) {
595 ERROR("pathname too long for ttys");
596 return -1;
597 }
598 if (ttydir) {
599 /* create dev/lxc/tty%d" */
9ba8130c 600 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
7c6ef2a2
SH
601 rootfs->mount, ttydir, i + 1);
602 if (ret >= sizeof(lxcpath)) {
603 ERROR("pathname too long for ttys");
604 return -1;
605 }
606 ret = creat(lxcpath, 0660);
607 if (ret==-1 && errno != EEXIST) {
608 SYSERROR("error creating %s\n", lxcpath);
609 return -1;
610 }
611 close(ret);
612 ret = unlink(path);
613 if (ret && errno != ENOENT) {
614 SYSERROR("error unlinking %s\n", path);
615 return -1;
616 }
b0a33c1e 617
7c6ef2a2
SH
618 if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
619 WARN("failed to mount '%s'->'%s'",
620 pty_info->name, path);
621 continue;
622 }
13954cce 623
9ba8130c
SH
624 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
625 if (ret >= sizeof(lxcpath)) {
626 ERROR("tty pathname too long");
627 return -1;
628 }
7c6ef2a2
SH
629 ret = symlink(lxcpath, path);
630 if (ret) {
631 SYSERROR("failed to create symlink for tty %d\n", i+1);
632 return -1;
633 }
634 } else {
635 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
636 WARN("failed to mount '%s'->'%s'",
637 pty_info->name, path);
638 continue;
639 }
b0a33c1e 640 }
641 }
642
cd54d859
DL
643 INFO("%d tty(s) has been setup", tty_info->nbtty);
644
b0a33c1e 645 return 0;
646}
647
7a7ff0c6 648static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
bf601689
MH
649{
650 struct lxc_list *mountlist, *listentry, *iterator;
651 char *pivotdir, *mountpoint, *mountentry;
652 int found;
653 void **cbparm;
654
655 mountentry = buffer;
656 cbparm = (void **)data;
657
658 mountlist = cbparm[0];
659 pivotdir = cbparm[1];
660
661 /* parse entry, first field is mountname, ignore */
662 mountpoint = strtok(mountentry, " ");
663 if (!mountpoint)
664 return -1;
665
666 /* second field is mountpoint */
667 mountpoint = strtok(NULL, " ");
668 if (!mountpoint)
669 return -1;
670
671 /* only consider mountpoints below old root fs */
672 if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
673 return 0;
674
675 /* filter duplicate mountpoints */
676 found = 0;
677 lxc_list_for_each(iterator, mountlist) {
678 if (!strcmp(iterator->elem, mountpoint)) {
679 found = 1;
680 break;
681 }
682 }
683 if (found)
684 return 0;
685
686 /* add entry to list */
687 listentry = malloc(sizeof(*listentry));
688 if (!listentry) {
689 SYSERROR("malloc for mountpoint listentry failed");
690 return -1;
691 }
692
693 listentry->elem = strdup(mountpoint);
694 if (!listentry->elem) {
695 SYSERROR("strdup failed");
696 return -1;
697 }
698 lxc_list_add_tail(mountlist, listentry);
699
700 return 0;
701}
702
cc6f6dd7 703static int umount_oldrootfs(const char *oldrootfs)
bf601689 704{
2382ecff 705 char path[MAXPATHLEN];
bf601689
MH
706 void *cbparm[2];
707 struct lxc_list mountlist, *iterator;
708 int ok, still_mounted, last_still_mounted;
9ba8130c 709 int rc;
bf601689
MH
710
711 /* read and parse /proc/mounts in old root fs */
712 lxc_list_init(&mountlist);
713
cc6f6dd7 714 /* oldrootfs is on the top tree directory now */
9ba8130c
SH
715 rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
716 if (rc >= sizeof(path)) {
717 ERROR("rootfs name too long");
718 return -1;
719 }
bf601689 720 cbparm[0] = &mountlist;
bf601689 721
cc6f6dd7 722 cbparm[1] = strdup(path);
bf601689
MH
723 if (!cbparm[1]) {
724 SYSERROR("strdup failed");
725 return -1;
726 }
727
9ba8130c
SH
728 rc = snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
729 if (rc >= sizeof(path)) {
730 ERROR("container proc/mounts name too long");
731 return -1;
732 }
cc6f6dd7
DL
733
734 ok = lxc_file_for_each_line(path,
735 setup_rootfs_pivot_root_cb, &cbparm);
bf601689
MH
736 if (ok < 0) {
737 SYSERROR("failed to read or parse mount list '%s'", path);
738 return -1;
739 }
740
741 /* umount filesystems until none left or list no longer shrinks */
742 still_mounted = 0;
743 do {
744 last_still_mounted = still_mounted;
745 still_mounted = 0;
746
747 lxc_list_for_each(iterator, &mountlist) {
748
c08556c6 749 /* umount normally */
bf601689
MH
750 if (!umount(iterator->elem)) {
751 DEBUG("umounted '%s'", (char *)iterator->elem);
752 lxc_list_del(iterator);
753 continue;
754 }
755
bf601689
MH
756 still_mounted++;
757 }
7df119ee 758
bf601689
MH
759 } while (still_mounted > 0 && still_mounted != last_still_mounted);
760
7df119ee 761
c08556c6
DL
762 lxc_list_for_each(iterator, &mountlist) {
763
764 /* let's try a lazy umount */
765 if (!umount2(iterator->elem, MNT_DETACH)) {
766 INFO("lazy unmount of '%s'", (char *)iterator->elem);
767 continue;
768 }
769
770 /* be more brutal (nfs) */
771 if (!umount2(iterator->elem, MNT_FORCE)) {
772 INFO("forced unmount of '%s'", (char *)iterator->elem);
773 continue;
774 }
775
7df119ee 776 WARN("failed to unmount '%s'", (char *)iterator->elem);
c08556c6 777 }
bf601689 778
cc6f6dd7
DL
779 return 0;
780}
781
782static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
783{
784 char path[MAXPATHLEN];
785 int remove_pivotdir = 0;
9ba8130c 786 int rc;
cc6f6dd7
DL
787
788 /* change into new root fs */
789 if (chdir(rootfs)) {
790 SYSERROR("can't chdir to new rootfs '%s'", rootfs);
791 return -1;
792 }
793
794 if (!pivotdir)
3103609d 795 pivotdir = "mnt";
cc6f6dd7 796
4f9293b1 797 /* compute the full path to pivotdir under rootfs */
9ba8130c
SH
798 rc = snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
799 if (rc >= sizeof(path)) {
800 ERROR("pivot dir name too long");
801 return -1;
802 }
cc6f6dd7
DL
803
804 if (access(path, F_OK)) {
805
806 if (mkdir_p(path, 0755)) {
807 SYSERROR("failed to create pivotdir '%s'", path);
808 return -1;
809 }
810
811 remove_pivotdir = 1;
812 DEBUG("created '%s' directory", path);
813 }
814
815 DEBUG("mountpoint for old rootfs is '%s'", path);
816
817 /* pivot_root into our new root fs */
818 if (pivot_root(".", path)) {
819 SYSERROR("pivot_root syscall failed");
bf601689
MH
820 return -1;
821 }
cc6f6dd7
DL
822
823 if (chdir("/")) {
824 SYSERROR("can't chdir to / after pivot_root");
825 return -1;
826 }
827
828 DEBUG("pivot_root syscall to '%s' successful", rootfs);
829
830 /* we switch from absolute path to relative path */
831 if (umount_oldrootfs(pivotdir))
832 return -1;
bf601689 833
c08556c6
DL
834 /* remove temporary mount point, we don't consider the removing
835 * as fatal */
a91d897a
FW
836 if (remove_pivotdir && rmdir(pivotdir))
837 WARN("can't remove mountpoint '%s': %m", pivotdir);
bf601689 838
bf601689
MH
839 return 0;
840}
841
33fcb7a0 842static int setup_rootfs(const struct lxc_rootfs *rootfs)
0ad19a3f 843{
33fcb7a0 844 if (!rootfs->path)
c69bd12f 845 return 0;
0ad19a3f 846
12297168 847 if (access(rootfs->mount, F_OK)) {
b1789442 848 SYSERROR("failed to access to '%s', check it is present",
12297168 849 rootfs->mount);
b1789442
DL
850 return -1;
851 }
852
2656d231 853 if (mount_rootfs(rootfs->path, rootfs->mount)) {
a6afdde9 854 ERROR("failed to mount rootfs");
c3f0a28c 855 return -1;
856 }
0ad19a3f 857
12297168 858 DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
c69bd12f 859
ac778708
DL
860 return 0;
861}
862
863int setup_pivot_root(const struct lxc_rootfs *rootfs)
864{
ac778708
DL
865 if (!rootfs->path)
866 return 0;
867
12297168 868 if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
cc6f6dd7 869 ERROR("failed to setup pivot root");
25368b52 870 return -1;
c69bd12f
DL
871 }
872
25368b52 873 return 0;
0ad19a3f 874}
875
d852c78c 876static int setup_pts(int pts)
3c26f34e 877{
77890c6d
SW
878 char target[PATH_MAX];
879
d852c78c
DL
880 if (!pts)
881 return 0;
3c26f34e 882
883 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 884 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 885 return -1;
886 }
887
a6afdde9
DL
888 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
889 "newinstance,ptmxmode=0666")) {
36eb9bde 890 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 891 return -1;
892 }
893
3c26f34e 894 if (access("/dev/ptmx", F_OK)) {
895 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
896 goto out;
36eb9bde 897 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 898 return -1;
899 }
900
77890c6d
SW
901 if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
902 goto out;
903
3c26f34e 904 /* fallback here, /dev/pts/ptmx exists just mount bind */
905 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 906 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 907 return -1;
908 }
cd54d859
DL
909
910 INFO("created new pts instance");
d852c78c 911
3c26f34e 912out:
913 return 0;
914}
915
cccc74b5
DL
916static int setup_personality(int persona)
917{
918 if (persona == -1)
919 return 0;
920
921 if (personality(persona) < 0) {
922 SYSERROR("failed to set personality to '0x%x'", persona);
923 return -1;
924 }
925
926 INFO("set personality to '0x%x'", persona);
927
928 return 0;
929}
930
7c6ef2a2 931static int setup_dev_console(const struct lxc_rootfs *rootfs,
33fcb7a0 932 const struct lxc_console *console)
6e590161 933{
63376d7d
DL
934 char path[MAXPATHLEN];
935 struct stat s;
7c6ef2a2 936 int ret;
52e35957 937
7c6ef2a2
SH
938 ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
939 if (ret >= sizeof(path)) {
940 ERROR("console path too long\n");
941 return -1;
942 }
52e35957 943
63376d7d 944 if (access(path, F_OK)) {
466978b0 945 WARN("rootfs specified but no console found at '%s'", path);
63376d7d 946 return 0;
52e35957
DL
947 }
948
f78a1f32 949 if (console->peer == -1) {
63376d7d 950 INFO("no console output required");
f78a1f32
DL
951 return 0;
952 }
ed502555 953
63376d7d
DL
954 if (stat(path, &s)) {
955 SYSERROR("failed to stat '%s'", path);
956 return -1;
957 }
958
959 if (chmod(console->name, s.st_mode)) {
960 SYSERROR("failed to set mode '0%o' to '%s'",
961 s.st_mode, console->name);
962 return -1;
963 }
13954cce 964
63376d7d
DL
965 if (mount(console->name, path, "none", MS_BIND, 0)) {
966 ERROR("failed to mount '%s' on '%s'", console->name, path);
6e590161 967 return -1;
968 }
969
63376d7d 970 INFO("console has been setup");
7c6ef2a2
SH
971 return 0;
972}
973
974static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
975 const struct lxc_console *console,
976 char *ttydir)
977{
978 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
979 int ret;
980
981 /* create rootfs/dev/<ttydir> directory */
982 ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
983 ttydir);
984 if (ret >= sizeof(path))
985 return -1;
986 ret = mkdir(path, 0755);
987 if (ret && errno != EEXIST) {
988 SYSERROR("failed with errno %d to create %s\n", errno, path);
989 return -1;
990 }
991 INFO("created %s\n", path);
992
993 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
994 rootfs->mount, ttydir);
995 if (ret >= sizeof(lxcpath)) {
996 ERROR("console path too long\n");
997 return -1;
998 }
999
1000 snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1001 ret = unlink(path);
1002 if (ret && errno != ENOENT) {
1003 SYSERROR("error unlinking %s\n", path);
1004 return -1;
1005 }
1006
1007 ret = creat(lxcpath, 0660);
1008 if (ret==-1 && errno != EEXIST) {
1009 SYSERROR("error %d creating %s\n", errno, lxcpath);
1010 return -1;
1011 }
1012 close(ret);
1013
1014 if (console->peer == -1) {
1015 INFO("no console output required");
1016 return 0;
1017 }
1018
1019 if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
1020 ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
1021 return -1;
1022 }
1023
1024 /* create symlink from rootfs/dev/console to 'lxc/console' */
9ba8130c
SH
1025 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
1026 if (ret >= sizeof(lxcpath)) {
1027 ERROR("lxc/console path too long");
1028 return -1;
1029 }
7c6ef2a2
SH
1030 ret = symlink(lxcpath, path);
1031 if (ret) {
1032 SYSERROR("failed to create symlink for console");
1033 return -1;
1034 }
1035
1036 INFO("console has been setup on %s", lxcpath);
cd54d859 1037
6e590161 1038 return 0;
1039}
1040
7c6ef2a2
SH
1041static int setup_console(const struct lxc_rootfs *rootfs,
1042 const struct lxc_console *console,
1043 char *ttydir)
1044{
1045 /* We don't have a rootfs, /dev/console will be shared */
1046 if (!rootfs->path)
1047 return 0;
1048 if (!ttydir)
1049 return setup_dev_console(rootfs, console);
1050
1051 return setup_ttydir_console(rootfs, console, ttydir);
1052}
1053
102a5303 1054static int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 1055{
102a5303
DL
1056 struct lxc_list *iterator;
1057 struct lxc_cgroup *cg;
88329c69 1058 int ret = -1;
6f4a3756 1059
102a5303
DL
1060 if (lxc_list_empty(cgroups))
1061 return 0;
6f4a3756 1062
102a5303 1063 lxc_list_for_each(iterator, cgroups) {
13954cce 1064
102a5303 1065 cg = iterator->elem;
6f4a3756 1066
102a5303 1067 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 1068 goto out;
6f4a3756 1069
102a5303 1070 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 1071 }
13954cce 1072
88329c69 1073 ret = 0;
cd54d859 1074 INFO("cgroup has been setup");
88329c69
MN
1075out:
1076 return ret;
576f946d 1077}
1078
998ac676
RT
1079static void parse_mntopt(char *opt, unsigned long *flags, char **data)
1080{
1081 struct mount_opt *mo;
1082
1083 /* If opt is found in mount_opt, set or clear flags.
1084 * Otherwise append it to data. */
1085
1086 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
1087 if (!strncmp(opt, mo->name, strlen(mo->name))) {
1088 if (mo->clear)
1089 *flags &= ~mo->flag;
1090 else
1091 *flags |= mo->flag;
1092 return;
1093 }
1094 }
1095
1096 if (strlen(*data))
1097 strcat(*data, ",");
1098 strcat(*data, opt);
1099}
1100
911324ef 1101static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
998ac676
RT
1102 char **mntdata)
1103{
1104 char *s, *data;
1105 char *p, *saveptr = NULL;
1106
911324ef 1107 *mntdata = NULL;
91656ce5 1108 *mntflags = 0L;
911324ef
DL
1109
1110 if (!mntopts)
998ac676
RT
1111 return 0;
1112
911324ef 1113 s = strdup(mntopts);
998ac676 1114 if (!s) {
36eb9bde 1115 SYSERROR("failed to allocate memory");
998ac676
RT
1116 return -1;
1117 }
1118
1119 data = malloc(strlen(s) + 1);
1120 if (!data) {
36eb9bde 1121 SYSERROR("failed to allocate memory");
998ac676
RT
1122 free(s);
1123 return -1;
1124 }
1125 *data = 0;
1126
1127 for (p = strtok_r(s, ",", &saveptr); p != NULL;
1128 p = strtok_r(NULL, ",", &saveptr))
1129 parse_mntopt(p, mntflags, &data);
1130
1131 if (*data)
1132 *mntdata = data;
1133 else
1134 free(data);
1135 free(s);
1136
1137 return 0;
1138}
1139
911324ef
DL
1140static int mount_entry(const char *fsname, const char *target,
1141 const char *fstype, unsigned long mountflags,
1142 const char *data)
1143{
1144 if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
1145 SYSERROR("failed to mount '%s' on '%s'", fsname, target);
1146 return -1;
1147 }
1148
1149 if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
1150
1151 DEBUG("remounting %s on %s to respect bind or remount options",
1152 fsname, target);
1153
1154 if (mount(fsname, target, fstype,
1155 mountflags | MS_REMOUNT, data)) {
1156 SYSERROR("failed to mount '%s' on '%s'",
1157 fsname, target);
1158 return -1;
1159 }
1160 }
1161
1162 DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
1163
1164 return 0;
1165}
1166
1167static inline int mount_entry_on_systemfs(struct mntent *mntent)
0ad19a3f 1168{
998ac676
RT
1169 unsigned long mntflags;
1170 char *mntdata;
911324ef
DL
1171 int ret;
1172
1173 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1174 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1175 return -1;
1176 }
1177
1178 ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
1179 mntent->mnt_type, mntflags, mntdata);
1180
1181 free(mntdata);
1182
1183 return ret;
1184}
1185
1186static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
80a881b2
SH
1187 const struct lxc_rootfs *rootfs,
1188 const char *lxc_name)
911324ef 1189{
013bd428 1190 char *aux;
59760f5d 1191 char path[MAXPATHLEN];
911324ef
DL
1192 unsigned long mntflags;
1193 char *mntdata;
80a881b2 1194 int r, ret = 0, offset;
0ad19a3f 1195
911324ef
DL
1196 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1197 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1198 return -1;
1199 }
1bc60a65 1200
80a881b2
SH
1201 /* if rootfs->path is a blockdev path, allow container fstab to
1202 * use /var/lib/lxc/CN/rootfs as the target prefix */
1203 r = snprintf(path, MAXPATHLEN, "/var/lib/lxc/%s/rootfs", lxc_name);
1204 if (r < 0 || r >= MAXPATHLEN)
1205 goto skipvarlib;
1206
1207 aux = strstr(mntent->mnt_dir, path);
1208 if (aux) {
1209 offset = strlen(path);
1210 goto skipabs;
1211 }
1212
1213skipvarlib:
013bd428
DL
1214 aux = strstr(mntent->mnt_dir, rootfs->path);
1215 if (!aux) {
1216 WARN("ignoring mount point '%s'", mntent->mnt_dir);
1217 goto out;
1218 }
80a881b2
SH
1219 offset = strlen(rootfs->path);
1220
1221skipabs:
013bd428 1222
9ba8130c 1223 r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
80a881b2
SH
1224 aux + offset);
1225 if (r < 0 || r >= MAXPATHLEN) {
1226 WARN("pathnme too long for '%s'", mntent->mnt_dir);
1227 ret = -1;
1228 goto out;
1229 }
1230
d330fe7b 1231
013bd428 1232 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
911324ef 1233 mntflags, mntdata);
0ad19a3f 1234
013bd428 1235out:
911324ef
DL
1236 free(mntdata);
1237 return ret;
1238}
d330fe7b 1239
911324ef
DL
1240static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1241 const char *rootfs)
1242{
1243 char path[MAXPATHLEN];
1244 unsigned long mntflags;
1245 char *mntdata;
1246 int ret;
d330fe7b 1247
911324ef
DL
1248 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1249 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1250 return -1;
1251 }
d330fe7b 1252
911324ef 1253 /* relative to root mount point */
9ba8130c
SH
1254 ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1255 if (ret >= sizeof(path)) {
1256 ERROR("path name too long");
1257 return -1;
1258 }
911324ef
DL
1259
1260 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1261 mntflags, mntdata);
1262
1263 free(mntdata);
998ac676 1264
911324ef
DL
1265 return ret;
1266}
1267
80a881b2
SH
1268static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
1269 const char *lxc_name)
911324ef
DL
1270{
1271 struct mntent *mntent;
1272 int ret = -1;
e76b8764 1273
911324ef 1274 while ((mntent = getmntent(file))) {
e76b8764 1275
911324ef
DL
1276 if (!rootfs->path) {
1277 if (mount_entry_on_systemfs(mntent))
e76b8764 1278 goto out;
911324ef 1279 continue;
e76b8764
CDC
1280 }
1281
911324ef
DL
1282 /* We have a separate root, mounts are relative to it */
1283 if (mntent->mnt_dir[0] != '/') {
1284 if (mount_entry_on_relative_rootfs(mntent,
1285 rootfs->mount))
1286 goto out;
1287 continue;
1288 }
cd54d859 1289
80a881b2 1290 if (mount_entry_on_absolute_rootfs(mntent, rootfs, lxc_name))
911324ef 1291 goto out;
0ad19a3f 1292 }
cd54d859 1293
0ad19a3f 1294 ret = 0;
cd54d859
DL
1295
1296 INFO("mount points have been setup");
0ad19a3f 1297out:
e7938e9e
MN
1298 return ret;
1299}
1300
80a881b2
SH
1301static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
1302 const char *lxc_name)
e7938e9e
MN
1303{
1304 FILE *file;
1305 int ret;
1306
1307 if (!fstab)
1308 return 0;
1309
1310 file = setmntent(fstab, "r");
1311 if (!file) {
1312 SYSERROR("failed to use '%s'", fstab);
1313 return -1;
1314 }
1315
80a881b2 1316 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e 1317
0ad19a3f 1318 endmntent(file);
1319 return ret;
1320}
1321
80a881b2
SH
1322static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
1323 const char *lxc_name)
e7938e9e
MN
1324{
1325 FILE *file;
1326 struct lxc_list *iterator;
1327 char *mount_entry;
1328 int ret;
1329
1330 file = tmpfile();
1331 if (!file) {
1332 ERROR("tmpfile error: %m");
1333 return -1;
1334 }
1335
1336 lxc_list_for_each(iterator, mount) {
1337 mount_entry = iterator->elem;
1d6b1976 1338 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
1339 }
1340
1341 rewind(file);
1342
80a881b2 1343 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e
MN
1344
1345 fclose(file);
1346 return ret;
1347}
1348
81810dd1
DL
1349static int setup_caps(struct lxc_list *caps)
1350{
1351 struct lxc_list *iterator;
1352 char *drop_entry;
d55bc1ad 1353 char *ptr;
81810dd1
DL
1354 int i, capid;
1355
1356 lxc_list_for_each(iterator, caps) {
1357
1358 drop_entry = iterator->elem;
1359
1360 capid = -1;
1361
1362 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1363
1364 if (strcmp(drop_entry, caps_opt[i].name))
1365 continue;
1366
1367 capid = caps_opt[i].value;
1368 break;
1369 }
1370
d55bc1ad
CS
1371 if (capid < 0) {
1372 /* try to see if it's numeric, so the user may specify
1373 * capabilities that the running kernel knows about but
1374 * we don't */
1375 capid = strtol(drop_entry, &ptr, 10);
1376 if (!ptr || *ptr != '\0' ||
1377 capid == LONG_MIN || capid == LONG_MAX)
1378 /* not a valid number */
1379 capid = -1;
1380 else if (capid > lxc_caps_last_cap())
1381 /* we have a number but it's not a valid
1382 * capability */
1383 capid = -1;
1384 }
1385
81810dd1 1386 if (capid < 0) {
1e11be34
DL
1387 ERROR("unknown capability %s", drop_entry);
1388 return -1;
81810dd1
DL
1389 }
1390
1391 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1392
1393 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1394 SYSERROR("failed to remove %s capability", drop_entry);
1395 return -1;
1396 }
1397
1398 }
1399
1400 DEBUG("capabilities has been setup");
1401
1402 return 0;
1403}
1404
0ad19a3f 1405static int setup_hw_addr(char *hwaddr, const char *ifname)
1406{
1407 struct sockaddr sockaddr;
1408 struct ifreq ifr;
1409 int ret, fd;
1410
3cfc0f3a
MN
1411 ret = lxc_convert_mac(hwaddr, &sockaddr);
1412 if (ret) {
1413 ERROR("mac address '%s' conversion failed : %s",
1414 hwaddr, strerror(-ret));
0ad19a3f 1415 return -1;
1416 }
1417
1418 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1419 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1420
1421 fd = socket(AF_INET, SOCK_DGRAM, 0);
1422 if (fd < 0) {
3ab87b66 1423 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 1424 return -1;
1425 }
1426
1427 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1428 close(fd);
1429 if (ret)
3ab87b66 1430 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 1431
cd54d859
DL
1432 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1433
0ad19a3f 1434 return ret;
1435}
1436
82d5ae15 1437static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1438{
82d5ae15
DL
1439 struct lxc_list *iterator;
1440 struct lxc_inetdev *inetdev;
3cfc0f3a 1441 int err;
0ad19a3f 1442
82d5ae15
DL
1443 lxc_list_for_each(iterator, ip) {
1444
1445 inetdev = iterator->elem;
1446
0093bb8c
DL
1447 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1448 &inetdev->bcast, inetdev->prefix);
3cfc0f3a
MN
1449 if (err) {
1450 ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1451 ifindex, strerror(-err));
82d5ae15
DL
1452 return -1;
1453 }
1454 }
1455
1456 return 0;
0ad19a3f 1457}
1458
82d5ae15 1459static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1460{
82d5ae15 1461 struct lxc_list *iterator;
7fa9074f 1462 struct lxc_inet6dev *inet6dev;
3cfc0f3a 1463 int err;
0ad19a3f 1464
82d5ae15
DL
1465 lxc_list_for_each(iterator, ip) {
1466
1467 inet6dev = iterator->elem;
1468
b3df193c 1469 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
0093bb8c
DL
1470 &inet6dev->mcast, &inet6dev->acast,
1471 inet6dev->prefix);
3cfc0f3a
MN
1472 if (err) {
1473 ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1474 ifindex, strerror(-err));
82d5ae15 1475 return -1;
3cfc0f3a 1476 }
82d5ae15
DL
1477 }
1478
1479 return 0;
0ad19a3f 1480}
1481
82d5ae15 1482static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 1483{
0ad19a3f 1484 char ifname[IFNAMSIZ];
0ad19a3f 1485 char *current_ifname = ifname;
3cfc0f3a 1486 int err;
0ad19a3f 1487
82d5ae15
DL
1488 /* empty network namespace */
1489 if (!netdev->ifindex) {
b0efbac4 1490 if (netdev->flags & IFF_UP) {
d472214b 1491 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1492 if (err) {
1493 ERROR("failed to set the loopback up : %s",
1494 strerror(-err));
82d5ae15
DL
1495 return -1;
1496 }
82d5ae15 1497 }
7b57e8b6 1498 return 0;
0ad19a3f 1499 }
13954cce 1500
82d5ae15
DL
1501 /* retrieve the name of the interface */
1502 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 1503 ERROR("no interface corresponding to index '%d'",
82d5ae15 1504 netdev->ifindex);
0ad19a3f 1505 return -1;
1506 }
13954cce 1507
018ef520 1508 /* default: let the system to choose one interface name */
9d083402 1509 if (!netdev->name)
fb6d9b2f
DL
1510 netdev->name = netdev->type == LXC_NET_PHYS ?
1511 netdev->link : "eth%d";
018ef520 1512
82d5ae15 1513 /* rename the interface name */
b84f58b9 1514 err = lxc_netdev_rename_by_name(ifname, netdev->name);
3cfc0f3a
MN
1515 if (err) {
1516 ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1517 strerror(-err));
018ef520
DL
1518 return -1;
1519 }
1520
1521 /* Re-read the name of the interface because its name has changed
1522 * and would be automatically allocated by the system
1523 */
82d5ae15 1524 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 1525 ERROR("no interface corresponding to index '%d'",
82d5ae15 1526 netdev->ifindex);
018ef520 1527 return -1;
0ad19a3f 1528 }
1529
82d5ae15
DL
1530 /* set a mac address */
1531 if (netdev->hwaddr) {
1532 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 1533 ERROR("failed to setup hw address for '%s'",
82d5ae15 1534 current_ifname);
0ad19a3f 1535 return -1;
1536 }
1537 }
1538
82d5ae15
DL
1539 /* setup ipv4 addresses on the interface */
1540 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 1541 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 1542 ifname);
1543 return -1;
1544 }
1545
82d5ae15
DL
1546 /* setup ipv6 addresses on the interface */
1547 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1548 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1549 ifname);
1550 return -1;
1551 }
1552
82d5ae15 1553 /* set the network device up */
b0efbac4 1554 if (netdev->flags & IFF_UP) {
3cfc0f3a
MN
1555 int err;
1556
d472214b 1557 err = lxc_netdev_up(current_ifname);
3cfc0f3a
MN
1558 if (err) {
1559 ERROR("failed to set '%s' up : %s", current_ifname,
1560 strerror(-err));
0ad19a3f 1561 return -1;
1562 }
1563
1564 /* the network is up, make the loopback up too */
d472214b 1565 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1566 if (err) {
1567 ERROR("failed to set the loopback up : %s",
1568 strerror(-err));
0ad19a3f 1569 return -1;
1570 }
1571 }
1572
f8fee0e2
MK
1573 /* We can only set up the default routes after bringing
1574 * up the interface, sine bringing up the interface adds
1575 * the link-local routes and we can't add a default
1576 * route if the gateway is not reachable. */
1577
1578 /* setup ipv4 gateway on the interface */
1579 if (netdev->ipv4_gateway) {
1580 if (!(netdev->flags & IFF_UP)) {
1581 ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
1582 return -1;
1583 }
1584
1585 if (lxc_list_empty(&netdev->ipv4)) {
1586 ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
1587 return -1;
1588 }
1589
1590 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
1591 if (err) {
1592 ERROR("failed to setup ipv4 gateway for '%s': %s",
1593 ifname, strerror(-err));
19a26f82
MK
1594 if (netdev->ipv4_gateway_auto) {
1595 char buf[INET_ADDRSTRLEN];
1596 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1597 ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
1598 }
f8fee0e2
MK
1599 return -1;
1600 }
1601 }
1602
1603 /* setup ipv6 gateway on the interface */
1604 if (netdev->ipv6_gateway) {
1605 if (!(netdev->flags & IFF_UP)) {
1606 ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
1607 return -1;
1608 }
1609
1610 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
1611 ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
1612 return -1;
1613 }
1614
1615 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
1616 if (err) {
1617 ERROR("failed to setup ipv6 gateway for '%s': %s",
1618 ifname, strerror(-err));
19a26f82
MK
1619 if (netdev->ipv6_gateway_auto) {
1620 char buf[INET6_ADDRSTRLEN];
1621 inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
1622 ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
1623 }
f8fee0e2
MK
1624 return -1;
1625 }
1626 }
1627
cd54d859
DL
1628 DEBUG("'%s' has been setup", current_ifname);
1629
0ad19a3f 1630 return 0;
1631}
1632
5f4535a3 1633static int setup_network(struct lxc_list *network)
0ad19a3f 1634{
82d5ae15 1635 struct lxc_list *iterator;
82d5ae15 1636 struct lxc_netdev *netdev;
0ad19a3f 1637
5f4535a3 1638 lxc_list_for_each(iterator, network) {
cd54d859 1639
5f4535a3 1640 netdev = iterator->elem;
82d5ae15
DL
1641
1642 if (setup_netdev(netdev)) {
1643 ERROR("failed to setup netdev");
1644 return -1;
1645 }
1646 }
cd54d859 1647
5f4535a3
DL
1648 if (!lxc_list_empty(network))
1649 INFO("network has been setup");
cd54d859
DL
1650
1651 return 0;
0ad19a3f 1652}
1653
49684c0b
CS
1654static int setup_private_host_hw_addr(char *veth1)
1655{
1656 struct ifreq ifr;
1657 int err;
1658 int sockfd;
1659
1660 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1661 if (sockfd < 0)
1662 return -errno;
1663
1664 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1665 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1666 if (err < 0) {
1667 close(sockfd);
1668 return -errno;
1669 }
1670
1671 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1672 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
1673 close(sockfd);
1674 if (err < 0)
1675 return -errno;
1676
7ad84da7
DL
1677 DEBUG("mac address of host interface '%s' changed to private "
1678 "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
1679 ifr.ifr_hwaddr.sa_data[0] & 0xff,
1680 ifr.ifr_hwaddr.sa_data[1] & 0xff,
1681 ifr.ifr_hwaddr.sa_data[2] & 0xff,
1682 ifr.ifr_hwaddr.sa_data[3] & 0xff,
1683 ifr.ifr_hwaddr.sa_data[4] & 0xff,
1684 ifr.ifr_hwaddr.sa_data[5] & 0xff);
49684c0b
CS
1685
1686 return 0;
1687}
1688
7b379ab3 1689struct lxc_conf *lxc_conf_init(void)
089cd8b8 1690{
7b379ab3 1691 struct lxc_conf *new;
26ddeedd 1692 int i;
7b379ab3
MN
1693
1694 new = malloc(sizeof(*new));
1695 if (!new) {
1696 ERROR("lxc_conf_init : %m");
1697 return NULL;
1698 }
1699 memset(new, 0, sizeof(*new));
1700
cccc74b5 1701 new->personality = -1;
28a4b0e5 1702 new->console.path = NULL;
63376d7d
DL
1703 new->console.peer = -1;
1704 new->console.master = -1;
1705 new->console.slave = -1;
1706 new->console.name[0] = '\0';
12297168 1707 new->rootfs.mount = LXCROOTFSMOUNT;
7b379ab3
MN
1708 lxc_list_init(&new->cgroup);
1709 lxc_list_init(&new->network);
1710 lxc_list_init(&new->mount_list);
81810dd1 1711 lxc_list_init(&new->caps);
26ddeedd
SH
1712 for (i=0; i<NUM_LXC_HOOKS; i++)
1713 lxc_list_init(&new->hooks[i]);
e075f5d9
SH
1714#if HAVE_APPARMOR
1715 new->aa_profile = NULL;
1716#endif
1717#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
1718 new->lsm_umount_proc = 0;
1719#endif
7b379ab3
MN
1720
1721 return new;
089cd8b8
DL
1722}
1723
e3b4c4c4 1724static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1725{
8634bc19 1726 char veth1buf[IFNAMSIZ], *veth1;
0e391e57 1727 char veth2buf[IFNAMSIZ], *veth2;
3cfc0f3a 1728 int err;
13954cce 1729
e892973e
DL
1730 if (netdev->priv.veth_attr.pair)
1731 veth1 = netdev->priv.veth_attr.pair;
8634bc19 1732 else {
9ba8130c
SH
1733 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
1734 if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
1735 ERROR("veth1 name too long");
1736 return -1;
1737 }
0e391e57 1738 veth1 = mktemp(veth1buf);
8634bc19 1739 }
82d5ae15 1740
0e391e57
DL
1741 snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
1742 veth2 = mktemp(veth2buf);
82d5ae15
DL
1743
1744 if (!strlen(veth1) || !strlen(veth2)) {
1745 ERROR("failed to allocate a temporary name");
1746 return -1;
0ad19a3f 1747 }
1748
3cfc0f3a
MN
1749 err = lxc_veth_create(veth1, veth2);
1750 if (err) {
1751 ERROR("failed to create %s-%s : %s", veth1, veth2,
1752 strerror(-err));
6ab9ab6d 1753 return -1;
0ad19a3f 1754 }
13954cce 1755
49684c0b
CS
1756 /* changing the high byte of the mac address to 0xfe, the bridge interface
1757 * will always keep the host's mac address and not take the mac address
1758 * of a container */
1759 err = setup_private_host_hw_addr(veth1);
1760 if (err) {
1761 ERROR("failed to change mac address of host interface '%s' : %s",
1762 veth1, strerror(-err));
1763 goto out_delete;
1764 }
1765
82d5ae15 1766 if (netdev->mtu) {
d472214b 1767 err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
3cfc0f3a 1768 if (!err)
d472214b 1769 err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
3cfc0f3a
MN
1770 if (err) {
1771 ERROR("failed to set mtu '%s' for %s-%s : %s",
1772 netdev->mtu, veth1, veth2, strerror(-err));
eb14c10a 1773 goto out_delete;
75d09f83
DL
1774 }
1775 }
1776
3cfc0f3a
MN
1777 if (netdev->link) {
1778 err = lxc_bridge_attach(netdev->link, veth1);
1779 if (err) {
1780 ERROR("failed to attach '%s' to the bridge '%s' : %s",
1781 veth1, netdev->link, strerror(-err));
1782 goto out_delete;
1783 }
eb14c10a
DL
1784 }
1785
82d5ae15
DL
1786 netdev->ifindex = if_nametoindex(veth2);
1787 if (!netdev->ifindex) {
36eb9bde 1788 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
1789 goto out_delete;
1790 }
1791
d472214b 1792 err = lxc_netdev_up(veth1);
6e35af2e
DL
1793 if (err) {
1794 ERROR("failed to set %s up : %s", veth1, strerror(-err));
1795 goto out_delete;
0ad19a3f 1796 }
1797
e3b4c4c4 1798 if (netdev->upscript) {
751d9dcd
DL
1799 err = run_script(handler->name, "net", netdev->upscript, "up",
1800 "veth", veth1, (char*) NULL);
1801 if (err)
e3b4c4c4 1802 goto out_delete;
e3b4c4c4
ST
1803 }
1804
82d5ae15
DL
1805 DEBUG("instanciated veth '%s/%s', index is '%d'",
1806 veth1, veth2, netdev->ifindex);
1807
6ab9ab6d 1808 return 0;
eb14c10a
DL
1809
1810out_delete:
b84f58b9 1811 lxc_netdev_delete_by_name(veth1);
6ab9ab6d 1812 return -1;
13954cce 1813}
d957ae2d 1814
e3b4c4c4 1815static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1816{
0e391e57 1817 char peerbuf[IFNAMSIZ], *peer;
3cfc0f3a 1818 int err;
d957ae2d
MT
1819
1820 if (!netdev->link) {
1821 ERROR("no link specified for macvlan netdev");
1822 return -1;
1823 }
13954cce 1824
9ba8130c
SH
1825 err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
1826 if (err >= sizeof(peerbuf))
1827 return -1;
82d5ae15 1828
0e391e57 1829 peer = mktemp(peerbuf);
82d5ae15
DL
1830 if (!strlen(peer)) {
1831 ERROR("failed to make a temporary name");
1832 return -1;
0ad19a3f 1833 }
1834
3cfc0f3a
MN
1835 err = lxc_macvlan_create(netdev->link, peer,
1836 netdev->priv.macvlan_attr.mode);
1837 if (err) {
1838 ERROR("failed to create macvlan interface '%s' on '%s' : %s",
1839 peer, netdev->link, strerror(-err));
d957ae2d 1840 return -1;
0ad19a3f 1841 }
1842
82d5ae15
DL
1843 netdev->ifindex = if_nametoindex(peer);
1844 if (!netdev->ifindex) {
36eb9bde 1845 ERROR("failed to retrieve the index for %s", peer);
b84f58b9 1846 lxc_netdev_delete_by_name(peer);
d957ae2d 1847 return -1;
22ebac19 1848 }
1849
e3b4c4c4 1850 if (netdev->upscript) {
751d9dcd
DL
1851 err = run_script(handler->name, "net", netdev->upscript, "up",
1852 "macvlan", netdev->link, (char*) NULL);
1853 if (err)
e3b4c4c4 1854 return -1;
e3b4c4c4
ST
1855 }
1856
e892973e
DL
1857 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
1858 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 1859
d957ae2d 1860 return 0;
0ad19a3f 1861}
1862
26c39028 1863/* XXX: merge with instanciate_macvlan */
e3b4c4c4 1864static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
26c39028
JHS
1865{
1866 char peer[IFNAMSIZ];
3cfc0f3a 1867 int err;
26c39028
JHS
1868
1869 if (!netdev->link) {
1870 ERROR("no link specified for vlan netdev");
1871 return -1;
1872 }
1873
9ba8130c
SH
1874 err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
1875 if (err >= sizeof(peer)) {
1876 ERROR("peer name too long");
1877 return -1;
1878 }
26c39028 1879
3cfc0f3a
MN
1880 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
1881 if (err) {
1882 ERROR("failed to create vlan interface '%s' on '%s' : %s",
1883 peer, netdev->link, strerror(-err));
26c39028
JHS
1884 return -1;
1885 }
1886
1887 netdev->ifindex = if_nametoindex(peer);
1888 if (!netdev->ifindex) {
1889 ERROR("failed to retrieve the ifindex for %s", peer);
b84f58b9 1890 lxc_netdev_delete_by_name(peer);
26c39028
JHS
1891 return -1;
1892 }
1893
e892973e
DL
1894 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
1895 netdev->ifindex);
1896
26c39028
JHS
1897 return 0;
1898}
1899
e3b4c4c4 1900static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1901{
6168e99f
DL
1902 if (!netdev->link) {
1903 ERROR("no link specified for the physical interface");
1904 return -1;
1905 }
1906
9d083402 1907 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 1908 if (!netdev->ifindex) {
9d083402 1909 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 1910 return -1;
1911 }
1912
e3b4c4c4
ST
1913 if (netdev->upscript) {
1914 int err;
751d9dcd
DL
1915 err = run_script(handler->name, "net", netdev->upscript,
1916 "up", "phys", netdev->link, (char*) NULL);
1917 if (err)
e3b4c4c4 1918 return -1;
e3b4c4c4
ST
1919 }
1920
82d5ae15 1921 return 0;
0ad19a3f 1922}
1923
e3b4c4c4 1924static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1925{
82d5ae15 1926 netdev->ifindex = 0;
e3b4c4c4
ST
1927 if (netdev->upscript) {
1928 int err;
751d9dcd
DL
1929 err = run_script(handler->name, "net", netdev->upscript,
1930 "up", "empty", (char*) NULL);
1931 if (err)
e3b4c4c4 1932 return -1;
e3b4c4c4 1933 }
82d5ae15 1934 return 0;
0ad19a3f 1935}
1936
e3b4c4c4 1937int lxc_create_network(struct lxc_handler *handler)
0ad19a3f 1938{
e3b4c4c4 1939 struct lxc_list *network = &handler->conf->network;
82d5ae15 1940 struct lxc_list *iterator;
82d5ae15 1941 struct lxc_netdev *netdev;
0ad19a3f 1942
5f4535a3 1943 lxc_list_for_each(iterator, network) {
0ad19a3f 1944
5f4535a3 1945 netdev = iterator->elem;
13954cce 1946
24654103 1947 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
82d5ae15 1948 ERROR("invalid network configuration type '%d'",
5f4535a3 1949 netdev->type);
82d5ae15
DL
1950 return -1;
1951 }
0ad19a3f 1952
e3b4c4c4 1953 if (netdev_conf[netdev->type](handler, netdev)) {
82d5ae15
DL
1954 ERROR("failed to create netdev");
1955 return -1;
1956 }
e3b4c4c4 1957
0ad19a3f 1958 }
1959
1960 return 0;
1961}
1962
7fef7a06
DL
1963void lxc_delete_network(struct lxc_list *network)
1964{
1965 struct lxc_list *iterator;
1966 struct lxc_netdev *netdev;
1967
1968 lxc_list_for_each(iterator, network) {
1969 netdev = iterator->elem;
d472214b
DL
1970 if (netdev->ifindex == 0)
1971 continue;
1972
d8f8e352
DL
1973 if (netdev->type == LXC_NET_PHYS) {
1974 if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
1975 WARN("failed to rename to the initial name the " \
1976 "netdev '%s'", netdev->link);
d472214b 1977 continue;
d8f8e352 1978 }
d472214b 1979
d8f8e352
DL
1980 /* Recent kernel remove the virtual interfaces when the network
1981 * namespace is destroyed but in case we did not moved the
1982 * interface to the network namespace, we have to destroy it
1983 */
1984 if (lxc_netdev_delete_by_index(netdev->ifindex))
1985 WARN("failed to remove interface '%s'", netdev->name);
7fef7a06
DL
1986 }
1987}
1988
5f4535a3 1989int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 1990{
82d5ae15 1991 struct lxc_list *iterator;
82d5ae15 1992 struct lxc_netdev *netdev;
3cfc0f3a 1993 int err;
0ad19a3f 1994
5f4535a3 1995 lxc_list_for_each(iterator, network) {
82d5ae15 1996
5f4535a3 1997 netdev = iterator->elem;
82d5ae15 1998
236087a6
DL
1999 /* empty network namespace, nothing to move */
2000 if (!netdev->ifindex)
2001 continue;
2002
d472214b 2003 err = lxc_netdev_move_by_index(netdev->ifindex, pid);
3cfc0f3a
MN
2004 if (err) {
2005 ERROR("failed to move '%s' to the container : %s",
2006 netdev->link, strerror(-err));
82d5ae15
DL
2007 return -1;
2008 }
2009
c1c75c04 2010 DEBUG("move '%s' to '%d'", netdev->name, pid);
0ad19a3f 2011 }
2012
2013 return 0;
2014}
2015
19a26f82
MK
2016int lxc_find_gateway_addresses(struct lxc_handler *handler)
2017{
2018 struct lxc_list *network = &handler->conf->network;
2019 struct lxc_list *iterator;
2020 struct lxc_netdev *netdev;
2021 int link_index;
2022
2023 lxc_list_for_each(iterator, network) {
2024 netdev = iterator->elem;
2025
2026 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2027 continue;
2028
2029 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
2030 ERROR("gateway = auto only supported for "
2031 "veth and macvlan");
2032 return -1;
2033 }
2034
2035 if (!netdev->link) {
2036 ERROR("gateway = auto needs a link interface");
2037 return -1;
2038 }
2039
2040 link_index = if_nametoindex(netdev->link);
2041 if (!link_index)
2042 return -EINVAL;
2043
2044 if (netdev->ipv4_gateway_auto) {
2045 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
2046 ERROR("failed to automatically find ipv4 gateway "
2047 "address from link interface '%s'", netdev->link);
2048 return -1;
2049 }
2050 }
2051
2052 if (netdev->ipv6_gateway_auto) {
2053 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
2054 ERROR("failed to automatically find ipv6 gateway "
2055 "address from link interface '%s'", netdev->link);
2056 return -1;
2057 }
2058 }
2059 }
2060
2061 return 0;
2062}
2063
5e4a62bf 2064int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 2065{
5e4a62bf 2066 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 2067 int i;
b0a33c1e 2068
5e4a62bf
DL
2069 /* no tty in the configuration */
2070 if (!conf->tty)
b0a33c1e 2071 return 0;
2072
13954cce 2073 tty_info->pty_info =
e4e7d59d 2074 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 2075 if (!tty_info->pty_info) {
36eb9bde 2076 SYSERROR("failed to allocate pty_info");
985d15b1 2077 return -1;
b0a33c1e 2078 }
2079
985d15b1 2080 for (i = 0; i < conf->tty; i++) {
13954cce 2081
b0a33c1e 2082 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2083
13954cce 2084 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 2085 pty_info->name, NULL, NULL)) {
36eb9bde 2086 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
2087 tty_info->nbtty = i;
2088 lxc_delete_tty(tty_info);
2089 return -1;
b0a33c1e 2090 }
2091
5332bb84
DL
2092 DEBUG("allocated pty '%s' (%d/%d)",
2093 pty_info->name, pty_info->master, pty_info->slave);
2094
b035ad62
MS
2095 /* Prevent leaking the file descriptors to the container */
2096 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
2097 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
2098
b0a33c1e 2099 pty_info->busy = 0;
2100 }
2101
985d15b1 2102 tty_info->nbtty = conf->tty;
1ac470c0
DL
2103
2104 INFO("tty's configured");
2105
985d15b1 2106 return 0;
b0a33c1e 2107}
2108
2109void lxc_delete_tty(struct lxc_tty_info *tty_info)
2110{
2111 int i;
2112
2113 for (i = 0; i < tty_info->nbtty; i++) {
2114 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2115
2116 close(pty_info->master);
2117 close(pty_info->slave);
2118 }
2119
2120 free(tty_info->pty_info);
2121 tty_info->nbtty = 0;
2122}
2123
571e6ec8 2124int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 2125{
e075f5d9
SH
2126#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2127 int mounted;
2128#endif
2129
571e6ec8 2130 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 2131 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 2132 return -1;
0ad19a3f 2133 }
2134
5f4535a3 2135 if (setup_network(&lxc_conf->network)) {
36eb9bde 2136 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 2137 return -1;
0ad19a3f 2138 }
2139
ac778708
DL
2140 if (setup_rootfs(&lxc_conf->rootfs)) {
2141 ERROR("failed to setup rootfs for '%s'", name);
95b5ffaf 2142 return -1;
0ad19a3f 2143 }
2144
80a881b2 2145 if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
36eb9bde 2146 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 2147 return -1;
576f946d 2148 }
2149
80a881b2 2150 if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name)) {
e7938e9e
MN
2151 ERROR("failed to setup the mount entries for '%s'", name);
2152 return -1;
2153 }
2154
26ddeedd 2155 HOOK(name, "mount", lxc_conf);
ac778708
DL
2156 if (setup_cgroup(name, &lxc_conf->cgroup)) {
2157 ERROR("failed to setup the cgroups for '%s'", name);
2158 return -1;
2159 }
2160
7c6ef2a2 2161 if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
36eb9bde 2162 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 2163 return -1;
6e590161 2164 }
2165
7c6ef2a2 2166 if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
36eb9bde 2167 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 2168 return -1;
b0a33c1e 2169 }
2170
e075f5d9
SH
2171#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2172 mounted = lsm_mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
2173 if (mounted == -1) {
2174 SYSERROR("failed to mount /proc in the container.");
2175 return -1;
2176 } else if (mounted == 1) {
2177 lxc_conf->lsm_umount_proc = 1;
2178 }
2179#endif
2180
ac778708 2181 if (setup_pivot_root(&lxc_conf->rootfs)) {
36eb9bde 2182 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 2183 return -1;
ed502555 2184 }
2185
571e6ec8 2186 if (setup_pts(lxc_conf->pts)) {
36eb9bde 2187 ERROR("failed to setup the new pts instance");
95b5ffaf 2188 return -1;
3c26f34e 2189 }
2190
cccc74b5
DL
2191 if (setup_personality(lxc_conf->personality)) {
2192 ERROR("failed to setup personality");
2193 return -1;
2194 }
2195
81810dd1
DL
2196 if (setup_caps(&lxc_conf->caps)) {
2197 ERROR("failed to drop capabilities");
2198 return -1;
2199 }
2200
cd54d859
DL
2201 NOTICE("'%s' is setup.", name);
2202
0ad19a3f 2203 return 0;
2204}
26ddeedd
SH
2205
2206int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
2207{
2208 int which = -1;
2209 struct lxc_list *it;
2210
2211 if (strcmp(hook, "pre-start") == 0)
2212 which = LXCHOOK_PRESTART;
2213 else if (strcmp(hook, "mount") == 0)
2214 which = LXCHOOK_MOUNT;
2215 else if (strcmp(hook, "start") == 0)
2216 which = LXCHOOK_START;
2217 else if (strcmp(hook, "post-stop") == 0)
2218 which = LXCHOOK_POSTSTOP;
2219 else
2220 return -1;
2221 lxc_list_for_each(it, &conf->hooks[which]) {
2222 int ret;
2223 char *hookname = it->elem;
2224 ret = run_script(name, "lxc", hookname, hook, NULL);
2225 if (ret)
2226 return ret;
2227 }
2228 return 0;
2229}