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