confile.c revision df2d4205073d3f57543951ca7ffabf891b230634
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * lxc: linux Container library
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen * (C) Copyright IBM Corp. 2007, 2008
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Authors:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Daniel Lezcano <daniel.lezcano at free.fr>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * This library is free software; you can redistribute it and/or
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen * modify it under the terms of the GNU Lesser General Public
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * License as published by the Free Software Foundation; either
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen * version 2.1 of the License, or (at your option) any later version.
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen *
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen * This library is distributed in the hope that it will be useful,
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen * but WITHOUT ANY WARRANTY; without even the implied warranty of
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen * Lesser General Public License for more details.
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen *
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen * You should have received a copy of the GNU Lesser General Public
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen * License along with this library; if not, write to the Free Software
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen */
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#define _GNU_SOURCE
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <stdio.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <stdlib.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <string.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <unistd.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <errno.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <fcntl.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <ctype.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <signal.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <sys/stat.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <sys/types.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <sys/param.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <sys/utsname.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <arpa/inet.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <netinet/in.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <net/if.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include "parse.h"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include "config.h"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include "confile.h"
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#include "utils.h"
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen#include "log.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "conf.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "network.h"
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen#if HAVE_SYS_PERSONALITY_H
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include <sys/personality.h>
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen#endif
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenlxc_log_define(lxc_confile, lxc);
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstatic int config_personality(const char *, const char *, struct lxc_conf *);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainenstatic int config_pts(const char *, const char *, struct lxc_conf *);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int config_tty(const char *, const char *, struct lxc_conf *);
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainenstatic int config_ttydir(const char *, const char *, struct lxc_conf *);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainenstatic int config_kmsg(const char *, const char *, struct lxc_conf *);
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainenstatic int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainenstatic int config_cgroup(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_idmap(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_loglevel(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_logfile(const char *, const char *, struct lxc_conf *);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic int config_mount(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_rootfs(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_pivotdir(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_utsname(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_type(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_flags(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_link(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_name(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_mtu(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_ipv4(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_network_script_up(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_script_down(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_ipv6(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int config_cap_drop(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_cap_keep(const char *, const char *, struct lxc_conf *);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_console(const char *, const char *, struct lxc_conf *);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int config_seccomp(const char *, const char *, struct lxc_conf *);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int config_includefile(const char *, const char *, struct lxc_conf *);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic int config_network_nic(const char *, const char *, struct lxc_conf *);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic int config_autodev(const char *, const char *, struct lxc_conf *);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic int config_haltsignal(const char *, const char *, struct lxc_conf *);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic int config_stopsignal(const char *, const char *, struct lxc_conf *);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int config_start(const char *, const char *, struct lxc_conf *);
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainenstatic int config_group(const char *, const char *, struct lxc_conf *);
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic struct lxc_config_t config[] = {
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.arch", config_personality },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.pts", config_pts },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.tty", config_tty },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.devttydir", config_ttydir },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.kmsg", config_kmsg },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.aa_profile", config_lsm_aa_profile },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.se_context", config_lsm_se_context },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.cgroup", config_cgroup },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.id_map", config_idmap },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.loglevel", config_loglevel },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.logfile", config_logfile },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.mount", config_mount },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.rootfs.mount", config_rootfs_mount },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.rootfs", config_rootfs },
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen { "lxc.pivotdir", config_pivotdir },
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen { "lxc.utsname", config_utsname },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.hook.pre-start", config_hook },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.hook.pre-mount", config_hook },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.hook.mount", config_hook },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.hook.autodev", config_hook },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.hook.start", config_hook },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.hook.post-stop", config_hook },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.hook.clone", config_hook },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.network.type", config_network_type },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.flags", config_network_flags },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.link", config_network_link },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.name", config_network_name },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.macvlan.mode", config_network_macvlan_mode },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.veth.pair", config_network_veth_pair },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.script.up", config_network_script_up },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.script.down", config_network_script_down },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.hwaddr", config_network_hwaddr },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.mtu", config_network_mtu },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.network.vlan.id", config_network_vlan_id },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.network.ipv4", config_network_ipv4 },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.ipv6", config_network_ipv6 },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* config_network_nic must come after all other 'lxc.network.*' entries */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.network.", config_network_nic },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.cap.drop", config_cap_drop },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.cap.keep", config_cap_keep },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.console", config_console },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.seccomp", config_seccomp },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.include", config_includefile },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.autodev", config_autodev },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.haltsignal", config_haltsignal },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.stopsignal", config_stopsignal },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.start.auto", config_start },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.start.delay", config_start },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.start.order", config_start },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen { "lxc.group", config_group },
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstruct signame {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int num;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *name;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic const struct signame signames[] = {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { SIGHUP, "HUP" },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { SIGINT, "INT" },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { SIGQUIT, "QUIT" },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { SIGILL, "ILL" },
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen { SIGABRT, "ABRT" },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { SIGFPE, "FPE" },
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen { SIGKILL, "KILL" },
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen { SIGSEGV, "SEGV" },
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen { SIGPIPE, "PIPE" },
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen { SIGALRM, "ALRM" },
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen { SIGTERM, "TERM" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGUSR1, "USR1" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGUSR2, "USR2" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGCHLD, "CHLD" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGCONT, "CONT" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGSTOP, "STOP" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGTSTP, "TSTP" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGTTIN, "TTIN" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { SIGTTOU, "TTOU" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenextern struct lxc_config_t *lxc_getconfig(const char *key)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < config_size; i++)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!strncmp(config[i].name, key,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen strlen(config[i].name)))
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return &config[i];
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen return NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen#define strprint(str, inlen, ...) \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen do { \
7889c9f65e23c83fc31cecf304cab4ab070d6aa1Timo Sirainen len = snprintf(str, inlen, ##__VA_ARGS__); \
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (len < 0) { SYSERROR("snprintf"); return -1; }; \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen fulllen += len; \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (inlen > 0) { \
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (str) str += len; \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inlen -= len; \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (inlen < 0) inlen = 0; \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } \
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } while (0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint lxc_listconfigs(char *retv, int inlen)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen int i, fulllen = 0, len;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!retv)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inlen = 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen else
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(retv, 0, inlen);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < config_size; i++) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char *s = config[i].name;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (s[strlen(s)-1] == '.')
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen continue;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen strprint(retv, inlen, "%s\n", s);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return fulllen;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_string_item(char **conf_item, const char *value)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char *new_value;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!value || strlen(value) == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*conf_item)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(*conf_item);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *conf_item = NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen new_value = strdup(value);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!new_value) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("failed to strdup '%s': %m", value);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen if (*conf_item)
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen free(*conf_item);
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen *conf_item = new_value;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_string_item_max(char **conf_item, const char *value,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen size_t max)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (strlen(value) >= max) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return config_string_item(conf_item, value);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int config_path_item(char **conf_item, const char *value)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return config_string_item_max(conf_item, value, PATH_MAX);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen/*
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen * config entry is something like "lxc.network.0.ipv4"
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen * the key 'lxc.network.' was found. So we make sure next
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen * comes an integer, find the right callback (by rewriting
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen * the key), and call it.
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen */
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainenstatic int config_network_nic(const char *key, const char *value,
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen struct lxc_conf *lxc_conf)
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen{
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen char *copy = strdup(key), *p;
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen int ret = -1;
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen struct lxc_config_t *config;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen if (!copy) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen SYSERROR("failed to allocate memory");
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen /*
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen * ok we know that to get here we've got "lxc.network."
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen * and it isn't any of the other network entries. So
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen * after the second . should come an integer (# of defined
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen * nic) followed by a valid entry.
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (*(key+12) < '0' || *(key+12) > '9')
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen goto out;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen p = index(key+12, '.');
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!p)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen goto out;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen strcpy(copy+12, p+1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen config = lxc_getconfig(copy);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!config) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ERROR("unknown key %s", key);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen goto out;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = config->cb(key, value, lxc_conf);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenout:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(copy);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int config_network_type(const char *key, const char *value,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct lxc_conf *lxc_conf)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen struct lxc_list *network = &lxc_conf->network;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct lxc_netdev *netdev;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_list *list;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen if (!value || strlen(value) == 0)
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen return lxc_clear_config_network(lxc_conf);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen netdev = malloc(sizeof(*netdev));
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen if (!netdev) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("failed to allocate memory");
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen memset(netdev, 0, sizeof(*netdev));
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen lxc_list_init(&netdev->ipv4);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lxc_list_init(&netdev->ipv6);
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen list = malloc(sizeof(*list));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!list) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen SYSERROR("failed to allocate memory");
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen free(netdev);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return -1;
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen }
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen lxc_list_init(list);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen list->elem = netdev;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen lxc_list_add_tail(network, list);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!strcmp(value, "veth"))
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen netdev->type = LXC_NET_VETH;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen else if (!strcmp(value, "macvlan"))
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen netdev->type = LXC_NET_MACVLAN;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else if (!strcmp(value, "vlan"))
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen netdev->type = LXC_NET_VLAN;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else if (!strcmp(value, "phys"))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen netdev->type = LXC_NET_PHYS;
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen else if (!strcmp(value, "empty"))
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen netdev->type = LXC_NET_EMPTY;
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen else if (!strcmp(value, "none"))
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen netdev->type = LXC_NET_NONE;
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen else {
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen ERROR("invalid network type %s", value);
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen return -1;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen }
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen return 0;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainenstatic int config_ip_prefix(struct in_addr *addr)
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen{
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (IN_CLASSA(addr->s_addr))
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen return 32 - IN_CLASSA_NSHIFT;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (IN_CLASSB(addr->s_addr))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 32 - IN_CLASSB_NSHIFT;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (IN_CLASSC(addr->s_addr))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 32 - IN_CLASSC_NSHIFT;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen/*
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen * if you have p="lxc.network.0.link", pass it p+12
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen * to get back '0' (the index of the nic)
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int get_network_netdev_idx(const char *key)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen int ret, idx;
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (*key < '0' || *key > '9')
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = sscanf(key, "%d", &idx);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ret != 1)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return idx;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen/*
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen * if you have p="lxc.network.0", pass this p+12 and it will return
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen * the netdev of the first configured nic
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenstatic struct lxc_netdev *get_netdev_from_key(const char *key,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct lxc_list *network)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen int i = 0, idx = get_network_netdev_idx(key);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct lxc_netdev *netdev = NULL;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen struct lxc_list *it;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen if (idx == -1)
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen return NULL;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen lxc_list_for_each(it, network) {
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen if (idx == i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen netdev = it->elem;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen break;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return netdev;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenextern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen char *retv, int inlen)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_netdev *netdev;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int fulllen = 0, len;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen netdev = get_netdev_from_key(key+12, &c->network);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (!netdev)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (!retv)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen inlen = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen else
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen memset(retv, 0, inlen);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "script.up\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "script.down\n");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (netdev->type != LXC_NET_EMPTY) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "flags\n");
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen strprint(retv, inlen, "link\n");
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen strprint(retv, inlen, "name\n");
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen strprint(retv, inlen, "hwaddr\n");
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen strprint(retv, inlen, "mtu\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "ipv6\n");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen strprint(retv, inlen, "ipv6_gateway\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "ipv4\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "ipv4_gateway\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen switch(netdev->type) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case LXC_NET_VETH:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "veth.pair\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case LXC_NET_MACVLAN:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "macvlan.mode\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case LXC_NET_VLAN:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen strprint(retv, inlen, "vlan.id\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case LXC_NET_PHYS:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return fulllen;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic struct lxc_netdev *network_netdev(const char *key, const char *value,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_list *network)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_netdev *netdev = NULL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (lxc_list_empty(network)) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ERROR("network is not created for '%s' = '%s' option",
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen key, value);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return NULL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (get_network_netdev_idx(key+12) == -1)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen netdev = lxc_list_last_elem(network);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen else
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen netdev = get_netdev_from_key(key+12, network);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen if (!netdev) {
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen ERROR("no network device defined for '%s' = '%s' option",
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen key, value);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen return NULL;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return netdev;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int network_ifname(char **valuep, const char *value)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return config_string_item_max(valuep, value, IFNAMSIZ);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#ifndef MACVLAN_MODE_PRIVATE
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen# define MACVLAN_MODE_PRIVATE 1
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#ifndef MACVLAN_MODE_VEPA
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen# define MACVLAN_MODE_VEPA 2
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#endif
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifndef MACVLAN_MODE_BRIDGE
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen# define MACVLAN_MODE_BRIDGE 4
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int macvlan_mode(int *valuep, const char *value)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mc_mode {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen char *name;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int mode;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } m[] = {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen { "private", MACVLAN_MODE_PRIVATE },
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen { "vepa", MACVLAN_MODE_VEPA },
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen { "bridge", MACVLAN_MODE_BRIDGE },
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen };
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen int i;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen if (strcmp(m[i].name, value))
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen continue;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen *valuep = m[i].mode;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainenstatic int config_network_flags(const char *key, const char *value,
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen struct lxc_conf *lxc_conf)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen{
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen struct lxc_netdev *netdev;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (!netdev)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return -1;
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen netdev->flags |= IFF_UP;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int config_network_link(const char *key, const char *value,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_conf *lxc_conf)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_netdev *netdev;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (!netdev)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return network_ifname(&netdev->link, value);
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen}
86d52f310fe939090c66b780a3b6ffe5d10dc8faTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int config_network_name(const char *key, const char *value,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct lxc_conf *lxc_conf)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct lxc_netdev *netdev;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!netdev)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return network_ifname(&netdev->name, value);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainenstatic int config_network_veth_pair(const char *key, const char *value,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_conf *lxc_conf)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen{
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen struct lxc_netdev *netdev;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (!netdev)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return -1;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return network_ifname(&netdev->priv.veth_attr.pair, value);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen}
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainenstatic int config_network_macvlan_mode(const char *key, const char *value,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_conf *lxc_conf)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_netdev *netdev;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (!netdev)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return -1;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic int config_network_hwaddr(const char *key, const char *value,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct lxc_conf *lxc_conf)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen{
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct lxc_netdev *netdev;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (!netdev)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return config_string_item(&netdev->hwaddr, value);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainenstatic int config_network_vlan_id(const char *key, const char *value,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_conf *lxc_conf)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct lxc_netdev *netdev;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (!netdev)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen return -1;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen return 0;
190237ce467d2389dfb809874b0fec86d3c7968dTimo Sirainen}
190237ce467d2389dfb809874b0fec86d3c7968dTimo Sirainen
190237ce467d2389dfb809874b0fec86d3c7968dTimo Sirainenstatic int config_network_mtu(const char *key, const char *value,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen struct lxc_conf *lxc_conf)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen{
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen struct lxc_netdev *netdev;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (!netdev)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen return -1;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return config_string_item(&netdev->mtu, value);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainenstatic int config_network_ipv4(const char *key, const char *value,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_conf *lxc_conf)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen struct lxc_netdev *netdev;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_inetdev *inetdev;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_list *list;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!netdev)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inetdev = malloc(sizeof(*inetdev));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!inetdev) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("failed to allocate ipv4 address");
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen return -1;
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen }
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen memset(inetdev, 0, sizeof(*inetdev));
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen list = malloc(sizeof(*list));
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (!list) {
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen SYSERROR("failed to allocate memory");
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen free(inetdev);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen return -1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen }
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen lxc_list_init(list);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen list->elem = inetdev;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen addr = strdup(value);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (!addr) {
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen ERROR("no address specified");
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen free(inetdev);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen free(list);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen return -1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen }
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen cursor = strstr(addr, " ");
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (cursor) {
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen *cursor = '\0';
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen bcast = cursor + 1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen }
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen slash = strstr(addr, "/");
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (slash) {
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen *slash = '\0';
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen prefix = slash + 1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen }
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen SYSERROR("invalid ipv4 address: %s", value);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(inetdev);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen free(addr);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(list);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
c3248869ddd406a7a46b8c05633f0cccc72fcb77Timo Sirainen if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
c3248869ddd406a7a46b8c05633f0cccc72fcb77Timo Sirainen SYSERROR("invalid ipv4 broadcast address: %s", value);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen free(inetdev);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen free(list);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(addr);
5c7aa03f959b8b9cab3eba8a585a90f4b50a4cdfTimo Sirainen return -1;
5c7aa03f959b8b9cab3eba8a585a90f4b50a4cdfTimo Sirainen }
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen /* no prefix specified, determine it from the network class */
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen inetdev->prefix = prefix ? atoi(prefix) :
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen config_ip_prefix(&inetdev->addr);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* if no broadcast address, let compute one from the
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen * prefix and address
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen if (!bcast) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inetdev->bcast.s_addr = inetdev->addr.s_addr;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inetdev->bcast.s_addr |=
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen htonl(INADDR_BROADCAST >> inetdev->prefix);
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen }
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen lxc_list_add_tail(&netdev->ipv4, list);
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen free(addr);
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen return 0;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen}
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_ipv4_gateway(const char *key, const char *value,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_conf *lxc_conf)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct lxc_netdev *netdev;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen struct in_addr *gw;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!netdev)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen gw = malloc(sizeof(*gw));
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen if (!gw) {
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen SYSERROR("failed to allocate ipv4 gateway address");
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen return -1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen if (!value) {
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen ERROR("no ipv4 gateway address specified");
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen free(gw);
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!strcmp(value, "auto")) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev->ipv4_gateway = NULL;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen netdev->ipv4_gateway_auto = true;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!inet_pton(AF_INET, value, gw)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("invalid ipv4 gateway address: %s", value);
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen free(gw);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev->ipv4_gateway = gw;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev->ipv4_gateway_auto = false;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int config_network_ipv6(const char *key, const char *value,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct lxc_conf *lxc_conf)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct lxc_netdev *netdev;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct lxc_inet6dev *inet6dev;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct lxc_list *list;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen char *slash,*valdup;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char *netmask;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (!netdev)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen inet6dev = malloc(sizeof(*inet6dev));
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (!inet6dev) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen SYSERROR("failed to allocate ipv6 address");
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen memset(inet6dev, 0, sizeof(*inet6dev));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen list = malloc(sizeof(*list));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!list) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("failed to allocate memory");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(inet6dev);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen lxc_list_init(list);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen list->elem = inet6dev;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen valdup = strdup(value);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen if (!valdup) {
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen ERROR("no address specified");
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen free(list);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen free(inet6dev);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen return -1;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen }
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen inet6dev->prefix = 64;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen slash = strstr(valdup, "/");
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (slash) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen *slash = '\0';
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netmask = slash + 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen inet6dev->prefix = atoi(netmask);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("invalid ipv6 address: %s", valdup);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen free(list);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen free(inet6dev);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen free(valdup);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen return -1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen }
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen lxc_list_add_tail(&netdev->ipv6, list);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen free(valdup);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen return 0;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen}
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainenstatic int config_network_ipv6_gateway(const char *key, const char *value,
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen struct lxc_conf *lxc_conf)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen struct lxc_netdev *netdev;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen netdev = network_netdev(key, value, &lxc_conf->network);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (!netdev)
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen return -1;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (!value) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen ERROR("no ipv6 gateway address specified");
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen return -1;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen }
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!strcmp(value, "auto")) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev->ipv6_gateway = NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen netdev->ipv6_gateway_auto = true;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
1b317fe22572738681d34d80da8012638e1e1281Timo Sirainen struct in6_addr *gw;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
5c7aa03f959b8b9cab3eba8a585a90f4b50a4cdfTimo Sirainen gw = malloc(sizeof(*gw));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!gw) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen SYSERROR("failed to allocate ipv6 gateway address");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
if (!inet_pton(AF_INET6, value, gw)) {
SYSERROR("invalid ipv6 gateway address: %s", value);
free(gw);
return -1;
}
netdev->ipv6_gateway = gw;
netdev->ipv6_gateway_auto = false;
}
return 0;
}
static int config_network_script_up(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
struct lxc_netdev *netdev;
netdev = network_netdev(key, value, &lxc_conf->network);
if (!netdev)
return -1;
return config_string_item(&netdev->upscript, value);
}
static int config_network_script_down(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
struct lxc_netdev *netdev;
netdev = network_netdev(key, value, &lxc_conf->network);
if (!netdev)
return -1;
return config_string_item(&netdev->downscript, value);
}
static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
{
struct lxc_list *hooklist;
hooklist = malloc(sizeof(*hooklist));
if (!hooklist) {
free(hook);
return -1;
}
hooklist->elem = hook;
lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
return 0;
}
static int config_seccomp(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->seccomp, value);
}
static int config_hook(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *copy;
if (!value || strlen(value) == 0)
return lxc_clear_hooks(lxc_conf, key);
copy = strdup(value);
if (!copy) {
SYSERROR("failed to dup string '%s'", value);
return -1;
}
if (strcmp(key, "lxc.hook.pre-start") == 0)
return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
else if (strcmp(key, "lxc.hook.pre-mount") == 0)
return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
else if (strcmp(key, "lxc.hook.autodev") == 0)
return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
else if (strcmp(key, "lxc.hook.mount") == 0)
return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
else if (strcmp(key, "lxc.hook.start") == 0)
return add_hook(lxc_conf, LXCHOOK_START, copy);
else if (strcmp(key, "lxc.hook.post-stop") == 0)
return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
else if (strcmp(key, "lxc.hook.clone") == 0)
return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
SYSERROR("Unknown key: %s", key);
free(copy);
return -1;
}
static int config_personality(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
signed long personality = lxc_config_parse_arch(value);
if (personality >= 0)
lxc_conf->personality = personality;
else
WARN("unsupported personality '%s'", value);
return 0;
}
static int config_pts(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int maxpts = atoi(value);
lxc_conf->pts = maxpts;
return 0;
}
static int config_start(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
if(strcmp(key, "lxc.start.auto") == 0) {
lxc_conf->start_auto = atoi(value);
return 0;
}
else if (strcmp(key, "lxc.start.delay") == 0) {
lxc_conf->start_delay = atoi(value);
return 0;
}
else if (strcmp(key, "lxc.start.order") == 0) {
lxc_conf->start_order = atoi(value);
return 0;
}
SYSERROR("Unknown key: %s", key);
return -1;
}
static int config_group(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *groups, *groupptr, *sptr, *token;
struct lxc_list *grouplist;
int ret = -1;
if (!strlen(value))
return lxc_clear_groups(lxc_conf);
groups = strdup(value);
if (!groups) {
SYSERROR("failed to dup '%s'", value);
return -1;
}
/* in case several groups are specified in a single line
* split these groups in a single element for the list */
for (groupptr = groups;;groupptr = NULL) {
token = strtok_r(groupptr, " \t", &sptr);
if (!token) {
ret = 0;
break;
}
grouplist = malloc(sizeof(*grouplist));
if (!grouplist) {
SYSERROR("failed to allocate groups list");
break;
}
grouplist->elem = strdup(token);
if (!grouplist->elem) {
SYSERROR("failed to dup '%s'", token);
free(grouplist);
break;
}
lxc_list_add_tail(&lxc_conf->groups, grouplist);
}
free(groups);
return ret;
}
static int config_tty(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int nbtty = atoi(value);
lxc_conf->tty = nbtty;
return 0;
}
static int config_ttydir(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1);
}
static int config_kmsg(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int v = atoi(value);
lxc_conf->kmsg = v;
return 0;
}
static int config_lsm_aa_profile(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_string_item(&lxc_conf->lsm_aa_profile, value);
}
static int config_lsm_se_context(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_string_item(&lxc_conf->lsm_se_context, value);
}
static int config_logfile(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int ret;
// store these values in the lxc_conf, and then try to set for
// actual current logging.
ret = config_path_item(&lxc_conf->logfile, value);
if (ret == 0)
ret = lxc_log_set_file(lxc_conf->logfile);
return ret;
}
static int config_loglevel(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int newlevel;
if (!value || strlen(value) == 0)
return 0;
if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET) {
DEBUG("Log level already set - ignoring new value");
return 0;
}
if (value[0] >= '0' && value[0] <= '9')
newlevel = atoi(value);
else
newlevel = lxc_log_priority_to_int(value);
// store these values in the lxc_conf, and then try to set for
// actual current logging.
lxc_conf->loglevel = newlevel;
return lxc_log_set_level(newlevel);
}
static int config_autodev(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int v = atoi(value);
lxc_conf->autodev = v;
return 0;
}
static int sig_num(const char *sig)
{
int n;
char *endp = NULL;
errno = 0;
n = strtol(sig, &endp, 10);
if (sig == endp || n < 0 || errno != 0)
return -1;
return n;
}
static int rt_sig_num(const char *signame)
{
int sig_n = 0;
int rtmax = 0;
if (strncasecmp(signame, "max-", 4) == 0) {
rtmax = 1;
}
signame += 4;
if (!isdigit(*signame))
return -1;
sig_n = sig_num(signame);
sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
return -1;
return sig_n;
}
static const char *sig_name(int signum) {
int n;
for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
if (n == signames[n].num)
return signames[n].name;
}
return "";
}
static int sig_parse(const char *signame) {
int n;
if (isdigit(*signame)) {
return sig_num(signame);
} else if (strncasecmp(signame, "sig", 3) == 0) {
signame += 3;
if (strncasecmp(signame, "rt", 2) == 0)
return rt_sig_num(signame + 2);
for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
if (strcasecmp (signames[n].name, signame) == 0)
return signames[n].num;
}
}
return -1;
}
static int config_haltsignal(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int sig_n = sig_parse(value);
if (sig_n < 0)
return -1;
lxc_conf->haltsignal = sig_n;
return 0;
}
static int config_stopsignal(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
int sig_n = sig_parse(value);
if (sig_n < 0)
return -1;
lxc_conf->stopsignal = sig_n;
return 0;
}
static int config_cgroup(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *token = "lxc.cgroup.";
char *subkey;
struct lxc_list *cglist = NULL;
struct lxc_cgroup *cgelem = NULL;
if (!value || strlen(value) == 0)
return lxc_clear_cgroups(lxc_conf, key);
subkey = strstr(key, token);
if (!subkey)
return -1;
if (!strlen(subkey))
return -1;
if (strlen(subkey) == strlen(token))
return -1;
subkey += strlen(token);
cglist = malloc(sizeof(*cglist));
if (!cglist)
goto out;
cgelem = malloc(sizeof(*cgelem));
if (!cgelem)
goto out;
memset(cgelem, 0, sizeof(*cgelem));
cgelem->subsystem = strdup(subkey);
cgelem->value = strdup(value);
if (!cgelem->subsystem || !cgelem->value)
goto out;
cglist->elem = cgelem;
lxc_list_add_tail(&lxc_conf->cgroup, cglist);
return 0;
out:
if (cglist)
free(cglist);
if (cgelem) {
if (cgelem->subsystem)
free(cgelem->subsystem);
if (cgelem->value)
free(cgelem->value);
free(cgelem);
}
return -1;
}
static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf)
{
char *token = "lxc.id_map";
char *subkey;
struct lxc_list *idmaplist = NULL;
struct id_map *idmap = NULL;
unsigned long hostid, nsid, range;
char type;
int ret;
if (!value || strlen(value) == 0)
return lxc_clear_idmaps(lxc_conf);
subkey = strstr(key, token);
if (!subkey)
return -1;
if (!strlen(subkey))
return -1;
idmaplist = malloc(sizeof(*idmaplist));
if (!idmaplist)
goto out;
idmap = malloc(sizeof(*idmap));
if (!idmap)
goto out;
memset(idmap, 0, sizeof(*idmap));
idmaplist->elem = idmap;
lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range);
if (ret != 4)
goto out;
INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
if (type == 'u')
idmap->idtype = ID_TYPE_UID;
else if (type == 'g')
idmap->idtype = ID_TYPE_GID;
else
goto out;
idmap->hostid = hostid;
idmap->nsid = nsid;
idmap->range = range;
return 0;
out:
if (idmaplist)
free(idmaplist);
if (idmap) {
free(idmap);
}
return -1;
}
static int config_fstab(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->fstab, value);
}
static int config_mount_auto(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *autos, *autoptr, *sptr, *token;
static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
{ "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
{ "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
{ "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
{ "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
{ "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
{ "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
{ "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
{ "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
{ "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
{ "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
{ "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
{ "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
{ "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
/* NB: For adding anything that ist just a single on/off, but has
* no options: keep mask and flag identical and just define the
* enum value as an unused bit so far
*/
{ NULL, 0 }
};
int i;
int ret = -1;
if (!strlen(value))
return -1;
autos = strdup(value);
if (!autos) {
SYSERROR("failed to dup '%s'", value);
return -1;
}
for (autoptr = autos; ; autoptr = NULL) {
token = strtok_r(autoptr, " \t", &sptr);
if (!token) {
ret = 0;
break;
}
for (i = 0; allowed_auto_mounts[i].token; i++) {
if (!strcmp(allowed_auto_mounts[i].token, token))
break;
}
if (!allowed_auto_mounts[i].token) {
ERROR("Invalid filesystem to automount: %s", token);
break;
}
lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
}
free(autos);
return ret;
}
static int config_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *fstab_token = "lxc.mount";
char *token = "lxc.mount.entry";
char *auto_token = "lxc.mount.auto";
char *subkey;
char *mntelem;
struct lxc_list *mntlist;
if (!value || strlen(value) == 0)
return lxc_clear_mount_entries(lxc_conf);
subkey = strstr(key, token);
if (!subkey) {
subkey = strstr(key, auto_token);
if (!subkey) {
subkey = strstr(key, fstab_token);
if (!subkey)
return -1;
return config_fstab(key, value, lxc_conf);
}
return config_mount_auto(key, value, lxc_conf);
}
if (!strlen(subkey))
return -1;
mntlist = malloc(sizeof(*mntlist));
if (!mntlist)
return -1;
mntelem = strdup(value);
if (!mntelem) {
free(mntlist);
return -1;
}
mntlist->elem = mntelem;
lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
return 0;
}
static int config_cap_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *keepcaps, *keepptr, *sptr, *token;
struct lxc_list *keeplist;
int ret = -1;
if (!strlen(value))
return lxc_clear_config_keepcaps(lxc_conf);
keepcaps = strdup(value);
if (!keepcaps) {
SYSERROR("failed to dup '%s'", value);
return -1;
}
/* in case several capability keep is specified in a single line
* split these caps in a single element for the list */
for (keepptr = keepcaps;;keepptr = NULL) {
token = strtok_r(keepptr, " \t", &sptr);
if (!token) {
ret = 0;
break;
}
keeplist = malloc(sizeof(*keeplist));
if (!keeplist) {
SYSERROR("failed to allocate keepcap list");
break;
}
keeplist->elem = strdup(token);
if (!keeplist->elem) {
SYSERROR("failed to dup '%s'", token);
free(keeplist);
break;
}
lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
}
free(keepcaps);
return ret;
}
static int config_cap_drop(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
char *dropcaps, *dropptr, *sptr, *token;
struct lxc_list *droplist;
int ret = -1;
if (!strlen(value))
return lxc_clear_config_caps(lxc_conf);
dropcaps = strdup(value);
if (!dropcaps) {
SYSERROR("failed to dup '%s'", value);
return -1;
}
/* in case several capability drop is specified in a single line
* split these caps in a single element for the list */
for (dropptr = dropcaps;;dropptr = NULL) {
token = strtok_r(dropptr, " \t", &sptr);
if (!token) {
ret = 0;
break;
}
droplist = malloc(sizeof(*droplist));
if (!droplist) {
SYSERROR("failed to allocate drop list");
break;
}
droplist->elem = strdup(token);
if (!droplist->elem) {
SYSERROR("failed to dup '%s'", token);
free(droplist);
break;
}
lxc_list_add_tail(&lxc_conf->caps, droplist);
}
free(dropcaps);
return ret;
}
static int config_console(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->console.path, value);
}
static int config_includefile(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return lxc_config_read(value, lxc_conf);
}
static int config_rootfs(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->rootfs.path, value);
}
static int config_rootfs_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->rootfs.mount, value);
}
static int config_pivotdir(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_path_item(&lxc_conf->rootfs.pivot, value);
}
static int config_utsname(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
struct utsname *utsname;
utsname = malloc(sizeof(*utsname));
if (!utsname) {
SYSERROR("failed to allocate memory");
return -1;
}
if (strlen(value) >= sizeof(utsname->nodename)) {
ERROR("node name '%s' is too long",
utsname->nodename);
free(utsname);
return -1;
}
strcpy(utsname->nodename, value);
if (lxc_conf->utsname)
free(lxc_conf->utsname);
lxc_conf->utsname = utsname;
return 0;
}
static int parse_line(char *buffer, void *data)
{
struct lxc_config_t *config;
char *line, *linep;
char *dot;
char *key;
char *value;
int ret = 0;
if (lxc_is_line_empty(buffer))
return 0;
/* we have to dup the buffer otherwise, at the re-exec for
* reboot we modified the original string on the stack by
* replacing '=' by '\0' below
*/
linep = line = strdup(buffer);
if (!line) {
SYSERROR("failed to allocate memory for '%s'", buffer);
return -1;
}
line += lxc_char_left_gc(line, strlen(line));
/* martian option - ignoring it, the commented lines beginning by '#'
* fall in this case
*/
if (strncmp(line, "lxc.", 4))
goto out;
ret = -1;
dot = strstr(line, "=");
if (!dot) {
ERROR("invalid configuration line: %s", line);
goto out;
}
*dot = '\0';
value = dot + 1;
key = line;
key[lxc_char_right_gc(key, strlen(key))] = '\0';
value += lxc_char_left_gc(value, strlen(value));
value[lxc_char_right_gc(value, strlen(value))] = '\0';
config = lxc_getconfig(key);
if (!config) {
ERROR("unknown key %s", key);
goto out;
}
ret = config->cb(key, value, data);
out:
free(linep);
return ret;
}
static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
{
return parse_line(buffer, conf);
}
int lxc_config_read(const char *file, struct lxc_conf *conf)
{
if( access(file, R_OK) == -1 ) {
return -1;
}
/* Catch only the top level config file name in the structure */
if( ! conf->rcfile ) {
conf->rcfile = strdup( file );
}
return lxc_file_for_each_line(file, parse_line, conf);
}
int lxc_config_define_add(struct lxc_list *defines, char* arg)
{
struct lxc_list *dent;
dent = malloc(sizeof(struct lxc_list));
if (!dent)
return -1;
dent->elem = arg;
lxc_list_add_tail(defines, dent);
return 0;
}
int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
{
struct lxc_list *it,*next;
int ret = 0;
lxc_list_for_each(it, defines) {
ret = lxc_config_readline(it->elem, conf);
if (ret)
break;
}
lxc_list_for_each_safe(it, defines, next) {
lxc_list_del(it);
free(it);
}
return ret;
}
signed long lxc_config_parse_arch(const char *arch)
{
#if HAVE_SYS_PERSONALITY_H
struct per_name {
char *name;
unsigned long per;
} pername[4] = {
{ "x86", PER_LINUX32 },
{ "i686", PER_LINUX32 },
{ "x86_64", PER_LINUX },
{ "amd64", PER_LINUX },
};
size_t len = sizeof(pername) / sizeof(pername[0]);
int i;
for (i = 0; i < len; i++) {
if (!strcmp(pername[i].name, arch))
return pername[i].per;
}
#endif
return -1;
}
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int i, aflag;
struct { const char *token; int flag; } all_privs[] = {
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
};
if (!flaglist) {
/* for the sake of backward compatibility, drop all privileges
if none is specified */
for (i = 0; all_privs[i].token; i++) {
*flags |= all_privs[i].flag;
}
return 0;
}
token = strtok_r(flaglist, "|", &saveptr);
while (token) {
aflag = -1;
for (i = 0; all_privs[i].token; i++) {
if (!strcmp(all_privs[i].token, token))
aflag = all_privs[i].flag;
}
if (aflag < 0)
return -1;
*flags |= aflag;
token = strtok_r(NULL, "|", &saveptr);
}
return 0;
}
static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
{
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
return snprintf(retv, inlen, "%d", v);
}
static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
{
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
#if HAVE_SYS_PERSONALITY_H
int len = 0;
switch(c->personality) {
case PER_LINUX32: strprint(retv, inlen, "x86"); break;
case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
default: break;
}
#endif
return fulllen;
}
/*
* If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
* then just the value(s) will be printed. Since there still could be
* more than one, it is newline-separated.
* (Maybe that's ambigous, since some values, i.e. devices.list, will
* already have newlines?)
* If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
* in 'lxc.cgroup.subsystem.key = value' format.
*/
static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
const char *key)
{
int fulllen = 0, len;
int all = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
if (strcmp(key, "all") == 0)
all = 1;
lxc_list_for_each(it, &c->cgroup) {
struct lxc_cgroup *cg = it->elem;
if (all) {
strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
} else if (strcmp(cg->subsystem, key) == 0) {
strprint(retv, inlen, "%s\n", cg->value);
}
}
return fulllen;
}
static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
const char *key)
{
char *subkey;
int len, fulllen = 0, found = -1;
struct lxc_list *it;
int i;
/* "lxc.hook.mount" */
subkey = index(key, '.');
if (subkey) subkey = index(subkey+1, '.');
if (!subkey)
return -1;
subkey++;
if (!*subkey)
return -1;
for (i=0; i<NUM_LXC_HOOKS; i++) {
if (strcmp(lxchook_names[i], subkey) == 0) {
found=i;
break;
}
}
if (found == -1)
return -1;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->hooks[found]) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen)
{
int len, fulllen = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->groups) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
{
int len, fulllen = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->caps) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen)
{
int len, fulllen = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->keepcaps) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
{
int len, fulllen = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->mount_list) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
/*
* lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
* macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
* ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
* of an address. ipv4 and ipv6 return lists (newline-separated).
* things like veth.pair return '' if invalid (i.e. if called for vlan
* type).
*/
static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
const char *key)
{
char *p1;
int len, fulllen = 0;
struct lxc_netdev *netdev;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
p1 = index(key, '.');
if (!p1 || *(p1+1) == '\0') return -1;
p1++;
netdev = get_netdev_from_key(key, &c->network);
if (!netdev)
return -1;
if (strcmp(p1, "name") == 0) {
if (netdev->name)
strprint(retv, inlen, "%s", netdev->name);
} else if (strcmp(p1, "type") == 0) {
strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
} else if (strcmp(p1, "link") == 0) {
if (netdev->link)
strprint(retv, inlen, "%s", netdev->link);
} else if (strcmp(p1, "flags") == 0) {
if (netdev->flags & IFF_UP)
strprint(retv, inlen, "up");
} else if (strcmp(p1, "script.up") == 0) {
if (netdev->upscript)
strprint(retv, inlen, "%s", netdev->upscript);
} else if (strcmp(p1, "script.down") == 0) {
if (netdev->downscript)
strprint(retv, inlen, "%s", netdev->downscript);
} else if (strcmp(p1, "hwaddr") == 0) {
if (netdev->hwaddr)
strprint(retv, inlen, "%s", netdev->hwaddr);
} else if (strcmp(p1, "mtu") == 0) {
if (netdev->mtu)
strprint(retv, inlen, "%s", netdev->mtu);
} else if (strcmp(p1, "macvlan.mode") == 0) {
if (netdev->type == LXC_NET_MACVLAN) {
const char *mode;
switch (netdev->priv.macvlan_attr.mode) {
case MACVLAN_MODE_PRIVATE: mode = "private"; break;
case MACVLAN_MODE_VEPA: mode = "vepa"; break;
case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
default: mode = "(invalid)"; break;
}
strprint(retv, inlen, "%s", mode);
}
} else if (strcmp(p1, "veth.pair") == 0) {
if (netdev->type == LXC_NET_VETH) {
strprint(retv, inlen, "%s",
netdev->priv.veth_attr.pair ?
netdev->priv.veth_attr.pair :
netdev->priv.veth_attr.veth1);
}
} else if (strcmp(p1, "vlan") == 0) {
if (netdev->type == LXC_NET_VLAN) {
strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
}
} else if (strcmp(p1, "ipv4_gateway") == 0) {
if (netdev->ipv4_gateway_auto) {
strprint(retv, inlen, "auto");
} else if (netdev->ipv4_gateway) {
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
strprint(retv, inlen, "%s", buf);
}
} else if (strcmp(p1, "ipv4") == 0) {
struct lxc_list *it2;
lxc_list_for_each(it2, &netdev->ipv4) {
struct lxc_inetdev *i = it2->elem;
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
strprint(retv, inlen, "%s\n", buf);
}
} else if (strcmp(p1, "ipv6_gateway") == 0) {
if (netdev->ipv6_gateway_auto) {
strprint(retv, inlen, "auto");
} else if (netdev->ipv6_gateway) {
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
strprint(retv, inlen, "%s", buf);
}
} else if (strcmp(p1, "ipv6") == 0) {
struct lxc_list *it2;
lxc_list_for_each(it2, &netdev->ipv6) {
struct lxc_inetdev *i = it2->elem;
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
strprint(retv, inlen, "%s\n", buf);
}
}
return fulllen;
}
static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
{
int len, fulllen = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->network) {
struct lxc_netdev *n = it->elem;
const char *t = lxc_net_type_to_str(n->type);
strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
}
return fulllen;
}
int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
int inlen)
{
const char *v = NULL;
if (strcmp(key, "lxc.mount.entry") == 0)
return lxc_get_mount_entries(c, retv, inlen);
else if (strcmp(key, "lxc.mount") == 0)
v = c->fstab;
else if (strcmp(key, "lxc.tty") == 0)
return lxc_get_conf_int(c, retv, inlen, c->tty);
else if (strcmp(key, "lxc.pts") == 0)
return lxc_get_conf_int(c, retv, inlen, c->pts);
else if (strcmp(key, "lxc.devttydir") == 0)
v = c->ttydir;
else if (strcmp(key, "lxc.arch") == 0)
return lxc_get_arch_entry(c, retv, inlen);
else if (strcmp(key, "lxc.aa_profile") == 0)
v = c->lsm_aa_profile;
else if (strcmp(key, "lxc.se_context") == 0)
v = c->lsm_se_context;
else if (strcmp(key, "lxc.logfile") == 0)
v = lxc_log_get_file();
else if (strcmp(key, "lxc.loglevel") == 0)
v = lxc_log_priority_to_string(lxc_log_get_level());
else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
return lxc_get_cgroup_entry(c, retv, inlen, "all");
else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
else if (strcmp(key, "lxc.utsname") == 0)
v = c->utsname ? c->utsname->nodename : NULL;
else if (strcmp(key, "lxc.console") == 0)
v = c->console.path;
else if (strcmp(key, "lxc.rootfs.mount") == 0)
v = c->rootfs.mount;
else if (strcmp(key, "lxc.rootfs") == 0)
v = c->rootfs.path;
else if (strcmp(key, "lxc.pivotdir") == 0)
v = c->rootfs.pivot;
else if (strcmp(key, "lxc.cap.drop") == 0)
return lxc_get_item_cap_drop(c, retv, inlen);
else if (strcmp(key, "lxc.cap.keep") == 0)
return lxc_get_item_cap_keep(c, retv, inlen);
else if (strncmp(key, "lxc.hook", 8) == 0)
return lxc_get_item_hooks(c, retv, inlen, key);
else if (strcmp(key, "lxc.network") == 0)
return lxc_get_item_network(c, retv, inlen);
else if (strncmp(key, "lxc.network.", 12) == 0)
return lxc_get_item_nic(c, retv, inlen, key + 12);
else if (strcmp(key, "lxc.start.auto") == 0)
return lxc_get_conf_int(c, retv, inlen, c->start_auto);
else if (strcmp(key, "lxc.start.delay") == 0)
return lxc_get_conf_int(c, retv, inlen, c->start_delay);
else if (strcmp(key, "lxc.start.order") == 0)
return lxc_get_conf_int(c, retv, inlen, c->start_order);
else if (strcmp(key, "lxc.group") == 0)
return lxc_get_item_groups(c, retv, inlen);
else return -1;
if (!v)
return 0;
if (retv && inlen >= strlen(v) + 1)
strncpy(retv, v, strlen(v)+1);
return strlen(v);
}
int lxc_clear_config_item(struct lxc_conf *c, const char *key)
{
if (strcmp(key, "lxc.network") == 0)
return lxc_clear_config_network(c);
else if (strncmp(key, "lxc.network.", 12) == 0)
return lxc_clear_nic(c, key + 12);
else if (strcmp(key, "lxc.cap.drop") == 0)
return lxc_clear_config_caps(c);
else if (strcmp(key, "lxc.cap.keep") == 0)
return lxc_clear_config_keepcaps(c);
else if (strncmp(key, "lxc.cgroup", 10) == 0)
return lxc_clear_cgroups(c, key);
else if (strcmp(key, "lxc.mount.entries") == 0)
return lxc_clear_mount_entries(c);
else if (strncmp(key, "lxc.hook", 8) == 0)
return lxc_clear_hooks(c, key);
else if (strncmp(key, "lxc.group", 9) == 0)
return lxc_clear_groups(c);
return -1;
}
/*
* writing out a confile.
*/
void write_config(FILE *fout, struct lxc_conf *c)
{
struct lxc_list *it;
int i;
if (c->fstab)
fprintf(fout, "lxc.mount = %s\n", c->fstab);
lxc_list_for_each(it, &c->mount_list) {
fprintf(fout, "lxc.mount.entry = %s\n", (char *)it->elem);
}
if (c->auto_mounts & LXC_AUTO_ALL_MASK) {
fprintf(fout, "lxc.mount.auto =");
switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
case LXC_AUTO_PROC_MIXED: fprintf(fout, " proc:mixed"); break;
case LXC_AUTO_PROC_RW: fprintf(fout, " proc:rw"); break;
default: break;
}
switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
case LXC_AUTO_SYS_RO: fprintf(fout, " sys:ro"); break;
case LXC_AUTO_SYS_RW: fprintf(fout, " sys:rw"); break;
default: break;
}
switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
case LXC_AUTO_CGROUP_MIXED: fprintf(fout, " cgroup:mixed"); break;
case LXC_AUTO_CGROUP_RO: fprintf(fout, " cgroup:ro"); break;
case LXC_AUTO_CGROUP_RW: fprintf(fout, " cgroup:rw"); break;
case LXC_AUTO_CGROUP_FULL_MIXED: fprintf(fout, " cgroup-full:mixed"); break;
case LXC_AUTO_CGROUP_FULL_RO: fprintf(fout, " cgroup-full:ro"); break;
case LXC_AUTO_CGROUP_FULL_RW: fprintf(fout, " cgroup-full:rw"); break;
default: break;
}
fprintf(fout, "\n");
}
if (c->tty)
fprintf(fout, "lxc.tty = %d\n", c->tty);
if (c->pts)
fprintf(fout, "lxc.pts = %d\n", c->pts);
if (c->ttydir)
fprintf(fout, "lxc.devttydir = %s\n", c->ttydir);
if (c->haltsignal)
fprintf(fout, "lxc.haltsignal = SIG%s\n", sig_name(c->haltsignal));
if (c->stopsignal)
fprintf(fout, "lxc.stopsignal = SIG%s\n", sig_name(c->stopsignal));
#if HAVE_SYS_PERSONALITY_H
switch(c->personality) {
case PER_LINUX32: fprintf(fout, "lxc.arch = x86\n"); break;
case PER_LINUX: fprintf(fout, "lxc.arch = x86_64\n"); break;
default: break;
}
#endif
if (c->lsm_aa_profile)
fprintf(fout, "lxc.aa_profile = %s\n", c->lsm_aa_profile);
if (c->lsm_se_context)
fprintf(fout, "lxc.se_context = %s\n", c->lsm_se_context);
if (c->seccomp)
fprintf(fout, "lxc.seccomp = %s\n", c->seccomp);
if (c->kmsg == 0)
fprintf(fout, "lxc.kmsg = 0\n");
if (c->autodev)
fprintf(fout, "lxc.autodev = 1\n");
if (c->loglevel != LXC_LOG_PRIORITY_NOTSET)
fprintf(fout, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c->loglevel));
if (c->logfile)
fprintf(fout, "lxc.logfile = %s\n", c->logfile);
lxc_list_for_each(it, &c->cgroup) {
struct lxc_cgroup *cg = it->elem;
fprintf(fout, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
}
if (c->utsname)
fprintf(fout, "lxc.utsname = %s\n", c->utsname->nodename);
lxc_list_for_each(it, &c->network) {
struct lxc_netdev *n = it->elem;
const char *t = lxc_net_type_to_str(n->type);
struct lxc_list *it2;
fprintf(fout, "lxc.network.type = %s\n", t ? t : "(invalid)");
if (n->flags & IFF_UP)
fprintf(fout, "lxc.network.flags = up\n");
if (n->link)
fprintf(fout, "lxc.network.link = %s\n", n->link);
if (n->name)
fprintf(fout, "lxc.network.name = %s\n", n->name);
if (n->type == LXC_NET_MACVLAN) {
const char *mode;
switch (n->priv.macvlan_attr.mode) {
case MACVLAN_MODE_PRIVATE: mode = "private"; break;
case MACVLAN_MODE_VEPA: mode = "vepa"; break;
case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
default: mode = "(invalid)"; break;
}
fprintf(fout, "lxc.network.macvlan.mode = %s\n", mode);
} else if (n->type == LXC_NET_VETH) {
if (n->priv.veth_attr.pair)
fprintf(fout, "lxc.network.veth.pair = %s\n",
n->priv.veth_attr.pair);
} else if (n->type == LXC_NET_VLAN) {
fprintf(fout, "lxc.network.vlan.id = %d\n", n->priv.vlan_attr.vid);
}
if (n->upscript)
fprintf(fout, "lxc.network.script.up = %s\n", n->upscript);
if (n->downscript)
fprintf(fout, "lxc.network.script.down = %s\n", n->downscript);
if (n->hwaddr)
fprintf(fout, "lxc.network.hwaddr = %s\n", n->hwaddr);
if (n->mtu)
fprintf(fout, "lxc.network.mtu = %s\n", n->mtu);
if (n->ipv4_gateway_auto)
fprintf(fout, "lxc.network.ipv4.gateway = auto\n");
else if (n->ipv4_gateway) {
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, n->ipv4_gateway, buf, sizeof(buf));
fprintf(fout, "lxc.network.ipv4.gateway = %s\n", buf);
}
lxc_list_for_each(it2, &n->ipv4) {
struct lxc_inetdev *i = it2->elem;
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
fprintf(fout, "lxc.network.ipv4 = %s\n", buf);
}
if (n->ipv6_gateway_auto)
fprintf(fout, "lxc.network.ipv6.gateway = auto\n");
else if (n->ipv6_gateway) {
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, n->ipv6_gateway, buf, sizeof(buf));
fprintf(fout, "lxc.network.ipv6.gateway = %s\n", buf);
}
lxc_list_for_each(it2, &n->ipv6) {
struct lxc_inet6dev *i = it2->elem;
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
fprintf(fout, "lxc.network.ipv6 = %s\n", buf);
}
}
lxc_list_for_each(it, &c->caps)
fprintf(fout, "lxc.cap.drop = %s\n", (char *)it->elem);
lxc_list_for_each(it, &c->keepcaps)
fprintf(fout, "lxc.cap.keep = %s\n", (char *)it->elem);
lxc_list_for_each(it, &c->id_map) {
struct id_map *idmap = it->elem;
fprintf(fout, "lxc.id_map = %c %lu %lu %lu\n",
idmap->idtype == ID_TYPE_UID ? 'u' : 'g', idmap->nsid,
idmap->hostid, idmap->range);
}
for (i=0; i<NUM_LXC_HOOKS; i++) {
lxc_list_for_each(it, &c->hooks[i])
fprintf(fout, "lxc.hook.%s = %s\n",
lxchook_names[i], (char *)it->elem);
}
if (c->console.path)
fprintf(fout, "lxc.console = %s\n", c->console.path);
if (c->rootfs.path)
fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path);
if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0)
fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount);
if (c->rootfs.pivot)
fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot);
if (c->start_auto)
fprintf(fout, "lxc.start.auto = %d\n", c->start_auto);
if (c->start_delay)
fprintf(fout, "lxc.start.delay = %d\n", c->start_delay);
if (c->start_order)
fprintf(fout, "lxc.start.order = %d\n", c->start_order);
lxc_list_for_each(it, &c->groups)
fprintf(fout, "lxc.group = %s\n", (char *)it->elem);
}