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