Compare commits

..

20 commits

Author SHA1 Message Date
Ariadne Conill
975e4f1bea ifupdown-ng 0.10.2. 2020-12-02 11:52:01 -07:00
Ariadne Conill
bcf090f7ad tests: ifquery: add tests to verify stanza merging works as expected 2020-12-02 11:51:34 -07:00
Ariadne Conill
f671e2d410 interface: add lif_interface_finalize() which rewrites addresses as CIDR when an interface stanza ends 2020-12-02 11:51:27 -07:00
Ariadne Conill
6da55d9299 tests: add fixture illustrating how smart stanza merging should work 2020-12-02 11:51:14 -07:00
Ariadne Conill
726a888c8d interface: fix default netmask size for AF_INET6 addresses (closes #130) 2020-12-02 11:10:00 -07:00
Ariadne Conill
b425ad75e3 tests: ifquery: add tests for checking the default netmasks 2020-12-02 11:08:48 -07:00
Ariadne Conill
bd730bece4 interface: learn hostname from uname(2) only if an interface requests the dhcp executor
Closes #74.
2020-12-02 10:50:38 -07:00
Ariadne Conill
9e859d458b tests: add getopt regression test for multicall stub 2020-12-02 10:49:13 -07:00
Ariadne Conill
40c7ed53e1 multicall: do not call getopt_long() inside the stub applet 2020-12-02 10:49:09 -07:00
Ariadne Conill
42836934e9 ifupdown-ng 0.10.1. 2020-10-21 09:21:21 -06:00
Ariadne Conill
93dff79567 state: explicitly check for explicit keyword when loading from the ifstate file 2020-10-21 09:19:55 -06:00
Ariadne Conill
61da61dfdb ifupdown: upgrade dependent interfaces to explicit interfaces if explicitly requested 2020-10-21 09:19:45 -06:00
Ariadne Conill
e16c24203e ifupdown: record explicitly configured interfaces as explicit in ifstate 2020-10-21 09:19:32 -06:00
Ariadne Conill
ebae949462 ifquery: when querying state, denote presence of the explicit flag 2020-10-21 09:19:15 -06:00
Ariadne Conill
0464118429 state: synchronize is_explicit from state records to parsed interface collections 2020-10-21 09:19:09 -06:00
Ariadne Conill
69999cd357 state: write and restore explicit flag from ifstate 2020-10-21 09:19:03 -06:00
Ariadne Conill
d92cfdd184 state: add lif_state_record::is_explicit 2020-10-21 09:18:58 -06:00
Ariadne Conill
045211514b lifecycle: skip parent interfaces marked as explicitly configured when going down
these interfaces will be taken down by ifdown itself when appropriate
2020-10-21 09:18:54 -06:00
Ariadne Conill
0d28f94a47 interface: auto interfaces are always explicit 2020-10-21 09:18:30 -06:00
Ariadne Conill
0abafedb9a interface: add lif_interface::is_explicit 2020-10-21 09:18:18 -06:00
77 changed files with 301 additions and 2515 deletions

View file

@ -10,7 +10,7 @@ jobs:
- name: Update system and add dependencies
run: |
apk upgrade -Ua
apk add build-base git kyua atf scdoc
apk add build-base git kyua atf
- name: Checkout
uses: actions/checkout@v2
@ -18,8 +18,5 @@ jobs:
- name: Build
run: make
- name: Build documentation
run: make docs
- name: Run tests
run: make check

1
.gitignore vendored
View file

@ -13,5 +13,4 @@ ifquery
ifup
ifdown
ifctrstat
ifparse
*.lock

View file

@ -1,5 +1,4 @@
Copyright (c) 2020-2021 Ariadne Conill <ariadne@dereferenced.org>
Copyright (c) 2020-2021 Maximilian Wilhelm <max@sdn.clinic>
Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -4,7 +4,7 @@ LIBBSD_CFLAGS =
LIBBSD_LIBS =
PACKAGE_NAME := ifupdown-ng
PACKAGE_VERSION := 0.11.3
PACKAGE_VERSION := 0.10.2
PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new
@ -14,8 +14,7 @@ CONFIG_FILE := /etc/network/ifupdown-ng.conf
EXECUTOR_PATH := /usr/libexec/ifupdown-ng
CFLAGS ?= -ggdb3 -Os
CFLAGS += -Wall -Wextra -Werror
CFLAGS += -Wmissing-declarations -Wmissing-prototypes -Wcast-align -Wpointer-arith -Wreturn-type
CFLAGS += -Wall -Wextra
CFLAGS += ${LIBBSD_CFLAGS}
CPPFLAGS = -I.
CPPFLAGS += -DINTERFACES_FILE=\"${INTERFACES_FILE}\"
@ -39,8 +38,8 @@ LIBIFUPDOWN_SRC = \
libifupdown/execute.c \
libifupdown/lifecycle.c \
libifupdown/config-parser.c \
libifupdown/config-file.c \
libifupdown/compat.c
libifupdown/config-file.c
LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o}
LIBIFUPDOWN_LIB = libifupdown.a
@ -48,8 +47,7 @@ MULTICALL_SRC = \
cmd/multicall.c \
cmd/multicall-options.c \
cmd/multicall-exec-options.c \
cmd/multicall-match-options.c \
cmd/pretty-print-iface.c
cmd/multicall-match-options.c
MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o}
MULTICALL = ifupdown
@ -75,22 +73,6 @@ MULTICALL_${CONFIG_IFCTRSTAT}_OBJ += ${IFCTRSTAT_SRC:.c=.o}
CMDS_${CONFIG_IFCTRSTAT} += ifctrstat
CPPFLAGS_${CONFIG_IFCTRSTAT} += -DCONFIG_IFCTRSTAT
# enable ifparse applet (+1 KB)
CONFIG_IFPARSE ?= Y
IFPARSE_SRC = cmd/ifparse.c
MULTICALL_${CONFIG_IFPARSE}_OBJ += ${IFPARSE_SRC:.c=.o}
CMDS_${CONFIG_IFPARSE} += ifparse
CPPFLAGS_${CONFIG_IFPARSE} += -DCONFIG_IFPARSE
# enable YAML support (+2 KB)
CONFIG_YAML ?= Y
YAML_SRC = \
libifupdown/yaml-base.c \
libifupdown/yaml-writer.c
LIBIFUPDOWN_${CONFIG_YAML}_OBJ += ${YAML_SRC:.c=.o}
CPPFLAGS_${CONFIG_YAML} += -DCONFIG_YAML
LIBIFUPDOWN_OBJ += ${LIBIFUPDOWN_Y_OBJ}
MULTICALL_OBJ += ${MULTICALL_Y_OBJ}
CMDS += ${CMDS_Y}
CPPFLAGS += ${CPPFLAGS_Y}
@ -100,28 +82,21 @@ EXECUTOR_SCRIPTS_CORE ?= \
ipv6-ra \
static \
link \
ppp \
forward
ppp
EXECUTOR_SCRIPTS_OPT ?= \
batman \
bond \
bridge \
ethtool \
gre \
mpls \
tunnel \
vrf \
vxlan \
wifi \
wireguard
tunnel \
gre \
wireguard \
ethtool \
batman
EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT}
EXECUTOR_SCRIPTS_STUB ?=
EXECUTOR_SCRIPTS_NATIVE ?=
TARGET_LIBS = ${LIBIFUPDOWN_LIB}
LIBS += ${TARGET_LIBS} ${LIBBSD_LIBS}
@ -156,27 +131,19 @@ install: all
for i in ${EXECUTOR_SCRIPTS_STUB}; do \
install -D -m755 executor-scripts/stub/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \
done
for i in ${EXECUTOR_SCRIPTS_NATIVE}; do \
install -D -m755 executor-scripts/${LAYOUT}-native/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \
done
install -D -m644 dist/ifupdown-ng.conf.example ${DESTDIR}${CONFIG_FILE}.example
.scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8:
${SCDOC} < $< > $@
MANPAGES_5 = \
doc/ifstate.5 \
doc/ifupdown-ng.conf.5 \
doc/interfaces.5 \
doc/interfaces-bond.5 \
doc/interfaces-batman.5 \
doc/interfaces-bridge.5 \
doc/interfaces-forward.5 \
doc/interfaces-ppp.5 \
doc/interfaces-tunnel.5 \
doc/interfaces-vrf.5 \
doc/interfaces-vxlan.5 \
doc/interfaces-wifi.5 \
doc/interfaces-wireguard.5
MANPAGES_7 = \
@ -186,8 +153,7 @@ MANPAGES_8 = \
doc/ifquery.8 \
doc/ifup.8 \
doc/ifdown.8 \
doc/ifctrstat.8 \
doc/ifparse.8
doc/ifctrstat.8
MANPAGES = ${MANPAGES_5} ${MANPAGES_7} ${MANPAGES_8}

View file

@ -39,11 +39,11 @@ On glibc systems, you must install `libbsd-dev` or equivalent and additionally d
make LIBBSD_CFLAGS="$(pkg-config --cflags libbsd-overlay)" LIBBSD_LIBS="$(pkg-config --cflags --libs libbsd-overlay)"
make install
To run the tests, do `make check`. Running the checks requires `kyua` (`apk add kyua` / `apt install kyua`).
To run the tests, do `make check`. Running the checks requires `kyua` (`apk add kyua`, not packaged for Debian).
To build the documentation, do `make docs` and `make install_docs`. Building
the documentation requires scdoc (`apk add scdoc` / `apt install scdoc`).
## Discussion
Discuss ifupdown-ng on IRC: irc.oftc.net #ifupdown-ng
Discuss ifupdown-ng on IRC: irc.as7007.net #ifupdown-ng

View file

@ -17,8 +17,7 @@
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "cmd/multicall.h"
#include "cmd/ifctrstat-linux.h"
#include "multicall.h"
struct counter_desc {
const char *name;
@ -42,7 +41,7 @@ counter_compare(const void *key, const void *candidate)
return strcasecmp((const char *)key, ((struct counter_desc *)candidate)->name);
}
const char *
char *
read_counter(const char *interface, const char *counter)
{
FILE *fp;

View file

@ -1,22 +0,0 @@
/*
* cmd/ifctrstat-linux.c
* Purpose: Implement ifctrstat system-specific routines for Linux
*
* Copyright (c) 2021 Maximilian Wilhelm <max@sdn.clinic>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef IFUPDOWN_IFCTRSTAT_LINUX__H__GUARD
#define IFUPDOWN_IFCTRSTAT_LINUX__H__GUARD
extern const char * read_counter(const char *interface, const char *counter);
#endif

View file

@ -20,11 +20,12 @@
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "cmd/multicall.h"
#include "cmd/ifctrstat-linux.h"
extern struct counter_desc { const char *name; const void *data; } avail_counters[];
extern int avail_counters_count;
extern const char *read_counter(const char *interface, const char *counter);
static bool show_label = true;
static bool
@ -95,7 +96,7 @@ ifctrstat_set_nolabel(const char *opt_arg)
show_label = false;
}
static int
int
ifctrstat_main(int argc, char *argv[])
{
if (optind >= argc)
@ -151,7 +152,7 @@ static struct if_option_group local_option_group = {
struct if_applet ifctrstat_applet = {
.name = "ifctrstat",
.desc = "display statistics about an interface",
.desc = "Display statistics about an interface",
.main = ifctrstat_main,
.usage = "ifctrstat [options] <interface> <counter>\n ifctrstat [options] --list",
.manpage = "8 ifctrstat",

View file

@ -1,224 +0,0 @@
/*
* cmd/ifparse.c
* Purpose: Redisplay /e/n/i in alternative formats.
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <fnmatch.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include "libifupdown/libifupdown.h"
#ifdef CONFIG_YAML
# include "libifupdown/yaml-base.h"
# include "libifupdown/yaml-writer.h"
#endif
#include "cmd/multicall.h"
#include "cmd/pretty-print-iface.h"
static bool show_all = false;
static bool allow_undefined = false;
static void
set_show_all(const char *arg)
{
(void) arg;
show_all = true;
}
static void
set_allow_undefined(const char *arg)
{
(void) arg;
allow_undefined = true;
}
static const char *output_fmt = "ifupdown";
static void
set_output_fmt(const char *arg)
{
output_fmt = arg;
}
static struct if_option local_options[] = {
{'F', "format", NULL, "output format to use", true, set_output_fmt},
{'A', "all", NULL, "show all interfaces", false, set_show_all},
{'U', "allow-undefined", NULL, "allow querying undefined (virtual) interfaces", false, set_allow_undefined},
};
static struct if_option_group local_option_group = {
.desc = "Program-specific options",
.group_size = ARRAY_SIZE(local_options),
.group = local_options
};
#ifdef CONFIG_YAML
static void
prettyprint_interface_yaml(struct lif_interface *iface)
{
struct lif_yaml_node doc = {};
lif_yaml_document_init(&doc, "interfaces");
struct lif_yaml_node *iface_node = lif_yaml_node_new_list(iface->ifname);
lif_yaml_node_append_child(&doc, iface_node);
if (iface->is_auto)
{
struct lif_yaml_node *iface_entry_node = lif_yaml_node_new_boolean("auto", true);
lif_yaml_node_append_child(iface_node, iface_entry_node);
}
struct lif_node *iter;
LIF_DICT_FOREACH(iter, &iface->vars)
{
struct lif_dict_entry *entry = iter->data;
const char *value = entry->data;
char addr_buf[512];
if (!strcmp(entry->key, "address"))
{
struct lif_address *addr = entry->data;
if (!lif_address_unparse(addr, addr_buf, sizeof addr_buf, true))
continue;
value = addr_buf;
}
struct lif_yaml_node *iface_entry_node = lif_yaml_node_new_string(entry->key, value);
lif_yaml_node_append_child(iface_node, iface_entry_node);
}
lif_yaml_write(iface_node, stdout, true);
lif_yaml_node_free(&doc);
}
#endif
struct prettyprint_impl_map {
const char *name;
void (*handle)(struct lif_interface *iface);
};
struct prettyprint_impl_map pp_impl_map[] = {
{"ifupdown", prettyprint_interface_eni},
#ifdef CONFIG_YAML
{"yaml-raw", prettyprint_interface_yaml},
#endif
};
static int
pp_impl_cmp(const void *a, const void *b)
{
const char *key = a;
const struct prettyprint_impl_map *impl = b;
return strcmp(key, impl->name);
}
static int
ifparse_main(int argc, char *argv[])
{
struct lif_dict state = {};
struct lif_dict collection = {};
struct lif_interface_file_parse_state parse_state = {
.collection = &collection,
};
lif_interface_collection_init(&collection);
if (!lif_state_read_path(&state, exec_opts.state_file))
{
fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.state_file);
return EXIT_FAILURE;
}
if (!lif_interface_file_parse(&parse_state, exec_opts.interfaces_file))
{
fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.interfaces_file);
return EXIT_FAILURE;
}
if (match_opts.property == NULL && lif_lifecycle_count_rdepends(&exec_opts, &collection) == -1)
{
fprintf(stderr, "%s: could not validate dependency tree\n", argv0);
return EXIT_FAILURE;
}
if (!lif_compat_apply(&collection))
{
fprintf(stderr, "%s: failed to apply compatibility glue\n", argv0);
return EXIT_FAILURE;
}
struct prettyprint_impl_map *m = bsearch(output_fmt, pp_impl_map, ARRAY_SIZE(pp_impl_map), sizeof(*m), pp_impl_cmp);
if (m == NULL)
{
fprintf(stderr, "%s: %s: output format not supported\n", argv0, output_fmt);
return EXIT_FAILURE;
}
if (show_all)
{
struct lif_node *n;
LIF_DICT_FOREACH(n, &collection)
{
struct lif_dict_entry *entry = n->data;
m->handle(entry->data);
}
return EXIT_SUCCESS;
}
if (optind >= argc)
generic_usage(self_applet, EXIT_FAILURE);
int idx = optind;
for (; idx < argc; idx++)
{
struct lif_dict_entry *entry = lif_dict_find(&collection, argv[idx]);
struct lif_interface *iface = NULL;
if (entry != NULL)
iface = entry->data;
if (entry == NULL && allow_undefined)
iface = lif_interface_collection_find(&collection, argv[idx]);
if (iface == NULL)
{
fprintf(stderr, "%s: unknown interface %s\n", argv0, argv[idx]);
return EXIT_FAILURE;
}
m->handle(iface);
}
return EXIT_SUCCESS;
}
struct if_applet ifparse_applet = {
.name = "ifparse",
.desc = "redisplay interface configuration",
.main = ifparse_main,
.usage = "ifparse [options] <interfaces>\n ifparse [options] --all",
.manpage = "8 ifparse",
.groups = { &global_option_group, &match_option_group, &exec_option_group, &local_option_group },
};

View file

@ -20,9 +20,44 @@
#include <getopt.h>
#include "libifupdown/libifupdown.h"
#include "cmd/multicall.h"
#include "cmd/pretty-print-iface.h"
static void
void
print_interface(struct lif_interface *iface)
{
if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname))
return;
if (iface->is_auto)
printf("auto %s\n", iface->ifname);
printf("%s %s\n", iface->is_template ? "template" : "iface", iface->ifname);
struct lif_node *iter;
LIF_DICT_FOREACH(iter, &iface->vars)
{
struct lif_dict_entry *entry = iter->data;
if (!strcmp(entry->key, "address"))
{
struct lif_address *addr = entry->data;
char addr_buf[512];
if (!lif_address_unparse(addr, addr_buf, sizeof addr_buf, true))
{
printf(" # warning: failed to unparse address\n");
continue;
}
printf(" %s %s\n", entry->key, addr_buf);
}
else
printf(" %s %s\n", entry->key, (const char *) entry->data);
}
printf("\n");
}
void
print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, struct lif_interface *parent)
{
if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname))
@ -57,7 +92,7 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st
}
}
static void
void
print_interface_property(struct lif_interface *iface, const char *property)
{
struct lif_node *iter;
@ -83,16 +118,16 @@ print_interface_property(struct lif_interface *iface, const char *property)
}
}
static void
void
list_interfaces(struct lif_dict *collection, struct match_options *opts)
{
struct lif_node *iter;
if (opts->dot)
{
printf("digraph interfaces {\n"
"edge [color=blue fontname=Sans fontsize=10]\n"
"node [fontname=Sans fontsize=10]\n");
printf("digraph interfaces {\n");
printf("edge [color=blue fontname=Sans fontsize=10]\n");
printf("node [fontname=Sans fontsize=10]\n");
}
LIF_DICT_FOREACH(iter, collection)
@ -112,7 +147,7 @@ list_interfaces(struct lif_dict *collection, struct match_options *opts)
continue;
if (opts->pretty_print)
prettyprint_interface_eni(iface);
print_interface(iface);
else if (opts->dot)
print_interface_dot(collection, iface, NULL);
else
@ -124,9 +159,8 @@ list_interfaces(struct lif_dict *collection, struct match_options *opts)
}
static bool listing = false, listing_stat = false, listing_running = false;
static bool allow_undefined = false;
static void
void
list_state(struct lif_dict *state, struct match_options *opts)
{
struct lif_node *iter;
@ -194,13 +228,6 @@ set_property(const char *opt_arg)
match_opts.property = opt_arg;
}
static void
set_allow_undefined(const char *opt_arg)
{
(void) opt_arg;
allow_undefined = true;
}
static struct if_option local_options[] = {
{'r', "running", NULL, "show configured (running) interfaces", false, set_show_running},
{'s', "state", NULL, "show configured state", false, set_show_state},
@ -208,7 +235,6 @@ static struct if_option local_options[] = {
{'D', "dot", NULL, "generate a dependency graph", false, set_output_dot},
{'L', "list", NULL, "list matching interfaces", false, set_listing},
{'P', "pretty-print", NULL, "pretty print the interfaces instead of just listing", false, set_pretty_print},
{'U', "allow-undefined", NULL, "allow querying undefined (virtual) interfaces", false, set_allow_undefined},
};
static struct if_option_group local_option_group = {
@ -217,7 +243,7 @@ static struct if_option_group local_option_group = {
.group = local_options
};
static int
int
ifquery_main(int argc, char *argv[])
{
struct lif_dict state = {};
@ -246,12 +272,6 @@ ifquery_main(int argc, char *argv[])
return EXIT_FAILURE;
}
if (!lif_compat_apply(&collection))
{
fprintf(stderr, "%s: failed to apply compatibility glue\n", argv0);
return EXIT_FAILURE;
}
/* --list --state is not allowed */
if (listing && (listing_stat || listing_running))
generic_usage(self_applet, EXIT_FAILURE);
@ -281,9 +301,6 @@ ifquery_main(int argc, char *argv[])
if (entry != NULL)
iface = entry->data;
if (entry == NULL && allow_undefined)
iface = lif_interface_collection_find(&collection, argv[idx]);
}
if (iface == NULL)
@ -295,7 +312,7 @@ ifquery_main(int argc, char *argv[])
if (match_opts.property != NULL)
print_interface_property(iface, match_opts.property);
else
prettyprint_interface_eni(iface);
print_interface(iface);
}
return EXIT_SUCCESS;

View file

@ -27,7 +27,7 @@
static bool up;
static bool
bool
is_ifdown()
{
if (strstr(argv0, "ifdown") != NULL)
@ -36,7 +36,7 @@ is_ifdown()
return false;
}
static int
int
acquire_state_lock(const char *state_path, const char *lifname)
{
if (exec_opts.mock || exec_opts.no_lock)
@ -46,7 +46,7 @@ acquire_state_lock(const char *state_path, const char *lifname)
snprintf(lockpath, sizeof lockpath, "%s.%s.lock", state_path, lifname);
int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC, 0600);
int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC);
if (fd < 0)
{
if (exec_opts.verbose)
@ -94,7 +94,7 @@ acquire_state_lock(const char *state_path, const char *lifname)
return fd;
}
static bool
bool
skip_interface(struct lif_interface *iface, const char *ifname, struct lif_dict *state, bool update_state)
{
if (iface->is_template)
@ -146,7 +146,7 @@ skip_interface(struct lif_interface *iface, const char *ifname, struct lif_dict
return false;
}
static bool
bool
change_interface(struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *ifname, bool update_state)
{
int lockfd = acquire_state_lock(exec_opts.state_file, ifname);
@ -194,7 +194,7 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc
return true;
}
static bool
bool
change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, struct match_options *opts)
{
struct lif_node *iter;
@ -222,7 +222,7 @@ change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, stru
return true;
}
static int
int
update_state_file_and_exit(int rc, struct lif_dict *state)
{
if (exec_opts.mock)
@ -243,7 +243,7 @@ update_state_file_and_exit(int rc, struct lif_dict *state)
return rc;
}
static int
int
ifupdown_main(int argc, char *argv[])
{
up = !is_ifdown();
@ -274,12 +274,6 @@ ifupdown_main(int argc, char *argv[])
return EXIT_FAILURE;
}
if(!lif_compat_apply(&collection))
{
fprintf(stderr, "%s: failed to apply compatibility glue\n", argv0);
return EXIT_FAILURE;
}
if (!lif_state_sync(&state, &collection))
{
fprintf(stderr, "%s: could not sync state\n", argv0);

View file

@ -21,13 +21,10 @@
#include <getopt.h>
#include "cmd/multicall.h"
#define DEFAULT_TIMEOUT 300
struct lif_execute_opts exec_opts = {
.interfaces_file = INTERFACES_FILE,
.executor_path = EXECUTOR_PATH,
.state_file = STATE_FILE,
.timeout = DEFAULT_TIMEOUT,
.state_file = STATE_FILE
};
static void
@ -77,14 +74,6 @@ set_force(const char *opt_arg)
exec_opts.force = true;
}
static void
set_timeout(const char *opt_arg)
{
exec_opts.timeout = atoi(opt_arg);
if (exec_opts.timeout < 0)
exec_opts.timeout = DEFAULT_TIMEOUT;
}
static struct if_option exec_options[] = {
{'f', "force", NULL, "force (de)configuration", false, set_force},
{'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, set_interfaces_file},
@ -93,7 +82,6 @@ static struct if_option exec_options[] = {
{'v', "verbose", NULL, "show what commands are being run", false, set_verbose},
{'E', "executor-path", "executor-path PATH", "use PATH for executor directory", true, set_executor_path},
{'S', "state-file", "state-file FILE", "use FILE for state", true, set_state_file},
{'T', "timeout", "timeout TIMEOUT", "wait TIMEOUT seconds for executors to complete", true, set_timeout},
};
struct if_option_group exec_option_group = {

View file

@ -39,7 +39,7 @@ set_include_pattern(const char *opt_arg)
static void
set_exclude_pattern(const char *opt_arg)
{
match_opts.exclude_pattern = opt_arg;
match_opts.include_pattern = opt_arg;
}
static struct if_option match_options[] = {

View file

@ -36,10 +36,6 @@ extern struct if_applet ifdown_applet;
extern struct if_applet ifctrstat_applet;
#endif
#ifdef CONFIG_IFPARSE
extern struct if_applet ifparse_applet;
#endif
struct if_applet ifupdown_applet;
const struct if_applet *self_applet = NULL;
@ -50,9 +46,6 @@ struct if_applet *applet_table[] = {
#ifdef CONFIG_IFUPDOWN
&ifdown_applet,
#endif
#ifdef CONFIG_IFPARSE
&ifparse_applet,
#endif
#ifdef CONFIG_IFQUERY
&ifquery_applet,
#endif
@ -62,7 +55,7 @@ struct if_applet *applet_table[] = {
&ifupdown_applet,
};
static int
int
applet_cmp(const void *a, const void *b)
{
const char *key = a;
@ -101,7 +94,7 @@ main(int argc, char *argv[])
return self_applet->main(argc, argv);
}
static int
int
multicall_main(int argc, char *argv[])
{
if (argc < 2)
@ -113,20 +106,19 @@ multicall_main(int argc, char *argv[])
void
multicall_usage(int status)
{
fprintf(stderr,
PACKAGE_NAME " " PACKAGE_VERSION "\n"
"usage: ifupdown <applet> [options]\n"
"\n"
"Built-in applets:\n");
fprintf(stderr, "usage: ifupdown <applet> [options]\n");
fprintf(stderr, "\nBuilt-in applets:\n\t");
for (size_t i = 0; i < ARRAY_SIZE(applet_table); i++)
{
if (applet_table[i] == &ifupdown_applet)
continue;
if (i != 0)
fprintf(stderr, ", ");
fprintf(stderr, " %-10s %s\n", applet_table[i]->name, applet_table[i]->desc);
fprintf(stderr, "%s", applet_table[i]->name);
}
fprintf(stderr, "\n");
exit(status);
}

View file

@ -1,56 +0,0 @@
/*
* cmd/pretty-print-iface.c
* Purpose: interface pretty-printer (/e/n/i style)
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stdio.h>
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "cmd/multicall.h"
#include "cmd/pretty-print-iface.h"
void
prettyprint_interface_eni(struct lif_interface *iface)
{
if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname))
return;
if (iface->is_auto)
printf("auto %s\n", iface->ifname);
printf("%s %s\n", iface->is_template ? "template" : "iface", iface->ifname);
struct lif_node *iter;
LIF_DICT_FOREACH(iter, &iface->vars)
{
struct lif_dict_entry *entry = iter->data;
if (!strcmp(entry->key, "address"))
{
struct lif_address *addr = entry->data;
char addr_buf[512];
if (!lif_address_unparse(addr, addr_buf, sizeof addr_buf, true))
{
printf(" # warning: failed to unparse address\n");
continue;
}
printf(" %s %s\n", entry->key, addr_buf);
}
else
printf(" %s %s\n", entry->key, (const char *) entry->data);
}
printf("\n");
}

View file

@ -1,23 +0,0 @@
/*
* cmd/pretty-print-iface.h
* Purpose: interface pretty-printer (/e/n/i style)
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef IFUPDOWN_CMD_PRETTY_PRINT_IFACE_H__GUARD
#define IFUPDOWN_CMD_PRETTY_PRINT_IFACE_H__GUARD
#include "libifupdown/libifupdown.h"
extern void prettyprint_interface_eni(struct lif_interface *iface);
#endif

View file

@ -17,29 +17,6 @@ allow_addon_scripts = 1
# templates. Valid values are 0 and 1, the default is 1.
allow_any_iface_as_template = 1
# auto_executor_selection:
# Automatically determine which executors are needed to bring up an
# interface. An admin may choose to disable this setting and explicitly
# define which executors to use with `use` statements.
# Valid values are 0 and 1, the default is 1.
auto_executor_selection = 1
# compat_create_interfaces:
# Denotes where or not to create interfaces when compat_* settings are
# active and it would be necessary to create an interface to be fully
# compliant. This could happen when inheriting bridge VLAN settings to
# an interface within a bridges bridge-ports setting but no interface
# stanza is found. Valid values are 0 and 1, the default is 1.
compat_create_interfaces = 1
# compat_ifupdown2_bridge_ports_inherit_vlans:
# In ifupdown2 <bridge-vids> as well as the <bridge-pvid> set on a bridge
# interface will be inherited by all member ports if not set explicitly.
# When set to 1 ifupdown-ng behaves the same way and will internally copy
# both options from the bridge member ports if they are not set on the
# member port. Valid values are 0 and 1, the default is 1.
compat_ifupdown2_bridge_ports_inherit_vlans = 1
# implicit_template_conversion:
# In some legacy configs, a template may be declared as an iface, and
# ifupdown-ng automatically converts those declarations to a proper

View file

@ -60,26 +60,6 @@ Currently the following settings are supported in
in order to require inheritance from specified templates.
Valid values are `0` and `1`, the default is `1`.
* `auto_executor_selection`: Automatically select executors based
on the presence of their config options. An admin may choose to
disable this setting in order to require explicitly enabling
executors through `use` statements. Valid values are `0` and `1`,
the default is `1`.
* `compat_create_interfaces`:
Denotes where or not to create interfaces when compat\_* settings are
active and it would be necessary to create an interface to be fully
compliant. This could happen when inheriting bridge VLAN settings to
an interface within a bridges bridge-ports setting but no interface
stanza is found. Valid values are `0` and `1`, the default is `1`.
* `compat_ifupdown2_bridge_ports_inherit_vlans`: In ifupdown2 `bridge-vids`
as well as the <bridge-pvid> set on a bridge interface will be inherited
by all member ports if not set explicitly. When set to `1` ifupdown-ng
behaves the same way and will internally copy both options from the
bridge member ports if they are not set on the member port.
Valid values are `0` and `1`, the default is `1`.
* `implicit_template_conversion`: In some legacy configs, a template
may be declared as an iface, and ifupdown-ng automatically converts
those declarations to a proper template. If this setting is
@ -272,4 +252,4 @@ used for an interface, use the ifquery(8) command.
If you have further questions about how to use ifupdown-ng to
configure a specific scenario, drop by the
[ifupdown-ng IRC channel](irc://irc.oftc.net/#ifupdown-ng).
[ifupdown-ng IRC channel](irc://irc.as7007.net/#ifupdown-ng).

View file

@ -45,10 +45,6 @@ configured in the configuration database.
*-S, --state-file* _FILE_
Use _FILE_ as the state database.
*-T, --timeout* _TIMEOUT_
Wait up to _TIMEOUT_ seconds for executors to complete before
raising an error.
*-V, --version*
Print the ifupdown-ng version and exit.
@ -58,9 +54,8 @@ configured in the configuration database.
# SEE ALSO
*ifupdown-ng.conf*(5)
*ifup*(8)
*ifquery*(8)
*ifup*(8)++
*ifquery*(8)++
*interfaces*(5)
# AUTHORS

View file

@ -1,66 +0,0 @@
ifparse(8)
# NAME
ifparse - redisplay interface configuration in different formats
# SYNOPSIS
*ifparse* [<_options_>...] <_interfaces_...>
*ifparse* -A|--all
# DESCRIPTION
*ifparse* is used to extract information from the interface configuration
file. It is intended to be used to translate the interface configuration
stanzas between different formats.
# OPTIONS
*-a, --auto*
Only match interfaces that are marked as _auto_.
*-h, --help*
Display supported options to ifquery.
*-i, --interfaces* _FILE_
Use _FILE_ as the config database.
*-F, --format* _FORMAT_
Use _FORMAT_ to determine what format to use. *ifupdown* and
*yaml-raw* formats are available.
*-I, --include* _PATTERN_
Include _PATTERN_ when matching against the config or state
database.
*-U, --allow-undefined*
Create virtual interfaces for any interfaces not explicitly
defined in the configuration file. This is primarily useful
for property queries.
*-S, --state-file* _FILE_
Use _FILE_ as the state database.
*-T, --timeout* _TIMEOUT_
Wait up to _TIMEOUT_ seconds for executors to complete before
raising an error.
*-V, --version*
Print the ifupdown-ng version and exit.
*-X, --exclude* _PATTERN_
Exclude _PATTERN_ when matching against the config or state
database.
# SEE ALSO
*ifup*(8)++
*ifdown*(8)++
*ifquery*(8)++
*interfaces*(5)
# AUTHORS
Ariadne Conill <ariadne@dereferenced.org>

View file

@ -54,18 +54,9 @@ configuration file to the current format.
When listing interfaces, print their configuration in a format
that is compatible with *interfaces*(5) files.
*-U, --allow-undefined*
Create virtual interfaces for any interfaces not explicitly
defined in the configuration file. This is primarily useful
for property queries.
*-S, --state-file* _FILE_
Use _FILE_ as the state database.
*-T, --timeout* _TIMEOUT_
Wait up to _TIMEOUT_ seconds for executors to complete before
raising an error.
*-V, --version*
Print the ifupdown-ng version and exit.

View file

@ -1,57 +0,0 @@
ifstate(5)
# NAME
*/run/ifstate* - interface state database
# DESCRIPTION
The */run/ifstate* file describes the present state of the interface
configuration -- namely, how many interfaces are up, how many
dependencies each interface has which are up (the refcount), and
whether or not an interface was explicitly brought up due to request
or configuration.
# FILE SYNTAX
At a minimum, the */run/ifstate* file contains at least one column,
the physical to logical interface mapping. This column is formatted
as such:
```
lo=lo
eth0=eth0
wlan0=work
```
The left side of the mapping is the physical interface, while the right
side is the logical interface. This field is required to be present.
The next field is the reference count. This is a number that reflects
the number of *active* dependencies an interface has. As interfaces
are brought up and down, the refcount may change. This field is
optional.
The final field denotes whether or not an interface was brought up
explicitly -- either by being marked as _auto_ or brought up manually
using *ifup*(8). The contents of this field if present is the
_explicit_ keyword.
# EXAMPLES
An example from a typical system with localhost, eth0 and a wireguard
VPN:
```
lo=lo 1 explicit
eth0=eth0 2 explicit
wg0=wg0 1 explicit
```
# SEE ALSO
*interfaces*(5)
# AUTHORS
Ariadne Conill <ariadne@dereferenced.org>

View file

@ -48,10 +48,6 @@ configured in the configuration database.
*-S, --state-file* _FILE_
Use _FILE_ as the state database.
*-T, --timeout* _TIMEOUT_
Wait up to _TIMEOUT_ seconds for executors to complete before
raising an error.
*-V, --version*
Print the ifupdown-ng version and exit.
@ -61,9 +57,8 @@ configured in the configuration database.
# SEE ALSO
*ifupdown-ng.conf*(5)
*ifdown*(8)
*ifquery*(8)
*ifdown*(8)++
*ifquery*(8)++
*interfaces*(5)
# AUTHORS

View file

@ -1,76 +0,0 @@
ifupdown-ng.conf(5)
# NAME
*ifupdown-ng.conf* - Global configuration file for ifupdown-ng
# DESCRIPTION
ifupdown-ng allows to configure some parts of it's behaviour via global
configuration options.
# GENERAL CONFIGURATION OPTIONS
*allow_addon_scripts* _bool_
Enable support for /etc/if-X.d addon scripts. These are used for
compatibility with legacy setups, and may be disabled for
performance improvements in setups where only ifupdown-ng executors
are used. Valid values are _0_ and _1_, the default is _1_.
*auto_executor_selection* _bool_
Automatically determine which executors to use. At present, this
is done by inserting `use` statements for the namespace a config
option has. The namespace is separated from the config option with
a dash (`-`). Valid values are _0_ and _1_, the default is _1_.
*use_hostname_for_dhcp* _bool_
Automatically learn the hostname property, used for DHCP
configuration by querying the system hostname using uname(2).
This is basically equivalent to `hostname $(hostname)` without
having to specify any configuration. Valid values are _0_ and
_1_, the default is _1_.
# TEMPLATE RELATED OPTIONS
*allow_any_iface_as_template* _bool_
Enable any interface to act as a template for another interface.
This is presently the default, but is deprecated. An admin may
choose to disable this setting in order to require inheritance
from specified templates. Valid values are _0_ and _1_, the
default is _1_.
*implicit_template_conversion* _bool_
In some legacy configs, a template may be declared as an iface, and
ifupdown-ng automatically converts those declarations to a proper
template. If this setting is disabled, inheritance will continue
to work against non-template interfaces without converting them to
a template. Valid values are _0_ and _1_, the default is _1_.
# COMPATIBILITY RELATED OPTIONS
*compat_create_interfaces* _bool_
Denotes where or not to create interfaces when compat_\* settings are
active and it would be necessary to create an interface to be fully
compliant. This could happen when inheriting bridge VLAN settings to
an interface within a bridges bridge-ports setting but no interface
stanza is found. Valid values are _0_ and _1_, the default is _1_.
compat_ifupdown2_bridge_ports_inherit_vlans _bool_
In ifupdown2 <bridge-vids> as well as the <bridge-pvid> set on a
bridge interface will be inherited by all member ports if not set
explicitly. When set to 1 ifupdown-ng behaves the same way and will
internally copy both options from the bridge member ports if they
are not set on the member port. Valid values are _0_ and _1_, the
default is _1_.
# FILES
/etc/network/ifupdown-ng.conf
# SEE ALSO
*interfaces*(5)
# AUTHORS
Maximilian Wilhelm <max@sdn.clinic>

View file

@ -27,11 +27,6 @@ See *ip-link*(8) for more details about the options listed below.
removed from the Forwarding DataBase (FDB) after not having
seen a frame with this source address.
*bridge-vlan-aware* _bool_
Denotes wether or not the bridge should be aware of 802.1q VLANs.
_bool_ can be given as _yes_/_no_ or _0_/_1_. The defaul is _no_.
See related options for configuring vlan-aware bridges, below.
# SPANNING TREE RELATED BRIDGE OPTIONS
*bridge-stp* _state_
@ -57,51 +52,6 @@ See *ip-link*(8) for more details about the options listed below.
after reception of its last STP hello message. Valid values
are between 6 and 40.
# OPTIONS FOR VLAN-AWARE-BRIDGES
The following options only have an effect on vlan-aware bridges and
their ports.
All settings can be applied on the bridge interface itself and all member
port iface stanzas. If applied on the bridge interface they take effect
for the bridge interface itself and might be inherited to _bridge-ports_
depending on the compatibility settings configured in *ifupdown-ng.conf*(5).
Configuring VLAN options on the bridge interface might be required for
setting up a VLAN interface to one of the VLANs carried within the bridge.
See the EXAMPLES section for an example for this scenario.
See *ifupdown-ng.conf*(5) for more information about compatiblity settings
mentioned below.
*bridge-access* _vlan ID_
Configure the given _vlan ID_ for untagged ingress and egress
on this interface. The common description for this kind of
configuration is called "access port".
*bridge-pvid* _vlan ID_
Denotes the _vlan ID_ to considered a PVID at ingress.
Any untagged frames received on this interface will be
assigned to this _vlan ID_. The default PVID is _1_.
If compatibility to ifupdown2 bridge port inheritance is active
a _bridge-pvid_ set on the bridge will be inherited to any
interface configured in _bridge-ports_ without a _bridge-pvid_ set.
*bridge-vids* _list of vlan IDs_
Denotes the space separated list of VLANs to be allowed tagged
ingress/egress on this interface.
If compatibility to ifupdown2 bridge port inheritance is active
a _bridge-vids_ set on the bridge will be inherited to any
interface configured in _bridge-ports_ without _bridge-vids_ set.
*bridge-allow-untagged* _bool_
Denotes wether or not the bridge should allow untagged frames on
ingress as well as egress. If set to _no_ untagged frames will be
droppped on ingress and none will be sent. _bool_ can be given as
_yes_/_no_ or _0_/_1_. The defaul is _yes_.
# EXAMPLES
A simple layer 2 only bridge:
@ -127,46 +77,10 @@ iface br0
address 2001:db8::42/64
```
A layer 2 only vlan-aware bridge:
```
auto bond0
iface bond0
bond-members eth0 eth1
bridge-vids 23 42 84 1337
auto br0
iface br0
bridge-ports bond0
```
A vlan-aware bridge with a VLAN interface on top:
```
auto eth0
iface eth0
bridge-vids 23 42 84 1337
auto br0
iface br0
bridge-ports eth0
bridge-vlan-aware yes
bridge-vids 42
auto vlan42
iface vlan42
vlan-raw-device br0
#
address 192.0.2.42/24
address 2001:db8::42/64
```
# SEE ALSO
*interfaces*(5)
*ifupdown-ng.conf*(5)
*ip-link*(8)
*bridge*(8)
*interfaces*(5)
# AUTHORS

View file

@ -1,48 +0,0 @@
interfaces-forward(5)
# NAME
*interfaces-forward* - forwarding vocabulary for the interfaces(5) file format
# DESCRIPTION
Linux allows for configuration of IP packet forwarding behavior on a protocol
and interface basis. The following options allow for this configuration.
# FORWARDING-RELATED OPTIONS
The forward executor will only modify the sysctl configuration if these options
are provided, otherwise other mechanisms such as /etc/sysctl.conf may be used.
*forward-ipv4* _yes|no_
Whether the interface should forward unicast IPv4 packets.
*forward-ipv6* _yes|no_
Whether the interface should forward unicast IPv6 packets.
*forward-ipv4-mc* _yes|no_
Whether the interface should forward multicast IPv4 packets.
*forward-ipv6-mc* _yes|no_
Whether the interface should forward multicast IPv6 packets.
# EXAMPLES
The typical home router scenario will want to forward both IPv4 and IPv6
packets:
```
iface WAN
use dhcp
forward-ipv4 yes
forward-ipv6 yes
iface LAN
address 192.168.0.1/24
forward-ipv4 yes
forward-ipv6 yes
```
# AUTHORS
Ariadne Conill <ariadne@dereferenced.org>

View file

@ -1,40 +0,0 @@
interfaces-mpls(5)
# NAME
*interfaces-mpls* - MPLS vocabulary for the interfaces(5) file format
# DESCRIPTION
Linux allows has support for MultiProtocol Label Switching (MPLS) for a while
now. The following options allow for this configuration.
# MPLS-RELATED OPTIONS
The MPLS executor will only modify the sysctl configuration if these options
are provided, otherwise other mechanisms such as /etc/sysctl.conf may be used.
If MPLS is enabled on (at least) one interface the executor will load the
_mpls_iptunnel_ kernel module.
Be aware that you have to set the _platform_labels_ sysctl to make MPLS work.
See https://www.kernel.org/doc/Documentation/networking/mpls-sysctl.rst for
more details on the MPLS related knobs in the Linux kernel.
*mpls-enable* _yes|no_
Control whether packets can be input on this interface. If disabled,
packets carrying an MPLS label will be discarded without further
processing.
# EXAMPLES
```
iface eth0
address 2001:db8:08:15::42/64
#
mpls-enable yes
```
# AUTHORS
Maximilian Wilhelm <max@sdn.clinic>

View file

@ -1,161 +0,0 @@
interfaces-tunnel(5)
# NAME
*interfaces-tunnel* - Tunnel extensions for the interfaces(5) file format
# DESCRIPTION
The following options set up tunneling interfaces with ifupdown-ng.
# TUNNEL-RELATED OPTIONS
A tunnel interface must have a mode, remote IP and a local IP or device
set, all other options are optional.
*tunnel-mode* _mode_
Denotes the mode for this tunnel. Basically all tunnel modes supported
by Linux / iproute2 are supported as well. This includes but is not
limited to _gre_/_gretap_, _ip6gre_/_ip6gretap_, _ipip_/_ip6ip_/_sit_.
*tunnel-local* _IP_
Denotes the IP address used as the local tunnel endpoint. According
to the _tunnel-mode_ an IPv4 or IPv6 address has to be given.
For compatiblity to ifupdown1 _local_ is an alias for this option.
*tunnel-local-dev* _interface_
When the local IP address the tunnel should be established from isn't
static and therefore might change (e.g. configured by DHCP or PPP) it
might be desireable to just use the address configured on _interface_.
When _tunnel-local-dev_ is given instead of _tunnel-local_ ifupdown-ng
will try to determine the IP address set on the given _interface_ with
respect to the address family required to set up a tunnel of the given
_mode_ and use this to set up the tunnel.
*tunnel-remote* _IP_
Denotes the IP address used as the remote tunnel endpoint. According
to the _tunnel-mode_ an IPv4 or IPv6 address has to be given.
For compatiblity to ifupdown1 _endpoint_ is an alias for this option.
*tunnel-physdev* _interface_
Denotes the _interface_ the encapsulated packets should be sent out by.
This comes in handy when using VRFs to denote that the local tunnel
endpoint should be terminated in VRF _interface_ or the VRF associated
with _interface_.
Note: Depending on the _mode_ of the tunnel either the VRF interface
or the real underlay interface may have to given as _interface_.
*tunnel-ttl* _ttl_
Denotes the TTL value to use in outgoing packets. _ttl_ is a number in the
range 1 - 255 whereas 0 is a special value meaning that packets inherit the
TTL value. The default for IPv4 tunnels is to inherit the TTL, for IPv6
tunnels it's 64. For compatiblity to ifupdown1 _ttl_ is an alias for this option.
# IPIP/SIT-RELATED OPTIONS
*tunnel-encap* _encap_
Denotes the type of secondary UDP encapsulation to use for this tunnel
if any. Supported _encap_ values are _fou_, _gue_, and _none_.
_fou_ indicates Foo-Over-UDP, _gue_ indicates Generic UDP Encapsulation.
# GRE-RELATED OPTIONS
*tunnel-encap* _encap_
Denotes the type of secondary UDP encapsulation to use for this tunnel
if any. Supported _encap_ values are _fou_, _gue_, and _none_.
_fou_ indicates Foo-Over-UDP, _gue_ indicates Generic UDP Encapsulation.
*tunnel-key* _key_
Denotes the_key to used for keyed GRE to allow multiple tunnels between
the same two endpoints. _key_ is either a number or an IPv4 address-
like dotted quad. The key parameter specifies the same key to use in both
directions. The _tunnel-ikey_ and _tunnel-okey_ parameters specify different
keys for input and output. For compatiblity to ifupdown1 _key_ is an alias
for this option.
*tunnel-hoplimit* _ttl_
Denotes the Hop Limit value to use in outgoing packets for _ip6gre_/_ip6gretap_
tunnels.
*tunnel-ignore-df* _bool_
Denotes wether to enable/disable IPv4 DF suppression on this tunnel. Normally
datagrams that exceed the MTU will be fragmented; the presence of the DF flag
inhibits this, resulting instead in an ICMP Unreachable (Fragmentation Required)
message. Enabling this attribute causes the DF flag to be ignored.
*tunnel-ikey* _key_
Denotes the key to used for keyed GRE for packets received. See _tunnel-key_
for details.
*tunnel-okey* _key_
Denotes the key to used for keyed GRE for packets sent out. See _tunnel-key_
for details.
*tunnel-pmtudisc* _bool_
Denotes wether to enable/disable Path MTU Discovery on this tunnel. It is
enabled by default. Note that a fixed ttl is incompatible with this option:
tunneling with a fixed ttl always makes pmtu discovery.
*tunnel-tos* _tos_
Denotes the TOS value to use in outgoing packets.
# EXAMPLES
A simple GRE tunnel
```
auto gre0
iface gre0
tunnel-mode gre
tunnel-remote 198.51.100.1
tunnel-local 203.0.113.2
#
address 192.0.2.42/24
address 2001:db8::42/64
```
A GRE tunnel where the local IP is learned from _eth0_
```
auto gre1
iface gre1
tunnel-mode gre
tunnel-remote 198.51.100.1
tunnel-local-dev eth0
#
address 192.0.2.42/24
address 2001:db8::42/64
```
A GRE tunnel which transfers encapasulated packets via _eth0_ which is part
of a VRF.
```
auto eth0
iface eth0
address 203.0.113.2/24
gateway 203.0.113.1
vrf vrf_external
auto tun-vrf
iface tun-vrf
tunnel-mode gre
tunnel-remote 198.51.100.1
tunnel-local 203.0.113.2
tunnel-physdev eth0
#
address 192.0.2.42/24
address 2001:db8::42/64
auto vrf_external
iface vrf_external
vrf-table 1023
```
# AUTHORS
Maximilian Wilhelm <max@sdn.clinic>

View file

@ -32,33 +32,26 @@ other options are optional.
*vxlan-physdev* _interface_
Specifies the physical ("underlay") device to use for tunnel
endpoint communication. This is required for setups using
multicast.
endpoint communication.
*vxlan-local-ip* _address_
Specifies the source IP address to use in outgoing packets.
For compatiblity with ifupdown2 _vxlan-local-tunnelip_ is an
alias for this parameter.
*vxlan-peer-ips* _list of IP addresses_
Specifies the unicast destination IP address(es) to use in outgoing
*vxlan-remote-ip* _address_
Specifies the unicast destination IP address to use in outgoing
packets when the destination link layer address is not known in
the VXLAN device forwarding database. This option can be used to
form Point-to-Point as well as Point-to-Multipoint VXLAN tunnels/
overlays depending on how many peer IPs are given. If more than one
IP address is given a Point-to-Multipoint overlay is being set up
and ingress / head-end replication will be used by the Linux Kernel.
This option cannot be used together with _vxlan-peer-group_ option.
For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for this option
and for compatibility with previos versions of ifupdown-ng _vxlan-remote-ip_
is an alias for this option, too.
the VXLAN device forwarding database. This parameter cannot be
specified with the _vxlan-remote-group_ parameter.
For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for
this parameter.
*vxlan-peer-group* _multicast group_
Specifies the multicast group address to join, requires _vxlan-phsydev_
to be set as well. This parameter cannot be specified in combination
with the _vxlan-peer-ips_ parameter. For compatibility with ifupdown2
_vxlan-svcnodeip_ is an alias for this option and for compatibility
with previos version of ifupdown-ng _vxlan-remote-group_ is an alias, too.
*vxlan-remote-group* _multicast group_
Specifies the multicast group IP address to join. This parameter
cannot be specified with the _vxlan-remote-ip_ parameter.
For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for
this parameter.
*vxlan-learning* _on/off_
Specifies if unknown source link layer addresses and IP addresses
@ -86,46 +79,22 @@ iface vx_v1001_padcty
mtu 1560
```
The same works just fine with IPv6 in the underlay:
```
auto vx_v1400_padcty
iface vx_v1400_padcty
vxlan-id 917505
vxlan-physdev vlan1400
vxlan-peer-group ff42:1400::1
#
hwaddress f2:00:0d:01:14:00
mtu 1560
```
Note that the underlay must have an MTU of at least 1610 to
carry the encapsulated packets of the two VTEPs above.
carry the encapsulated packets.
A VTEP with one peer (unicast point-to-point configuration):
A VTEP with one peer (point-to-point configuration):
```
auto vx_ptp1
iface vx_ptp1
vxlan-id 2342
vxlan-local-ip 192.0.2.42
vxlan-peer-ips 198.51.100.23
vxlan-remote-ip 198.51.100.23
#
hwaddress f2:00:c1:01:10:01
```
A VTEP with multiple peers (unicast point-to-multipoint with ingress / head-end replication):
```
auto vx_her
iface vx_her
vxlan-id 1337
vxlan-local-ip 2001:db8:1::1
vxlan-peer-ips 2001:db8:2::23 2001:db8:3::42 2001:db8:4::84
```
# AUTHORS
Maximilian Wilhelm <max@sdn.clinic>

View file

@ -1,63 +0,0 @@
interfaces-wifi(5)
# NAME
*interfaces-wifi* - WiFi vocabulary for the interfaces(5) file format
# DESCRIPTION
Wi-Fi (the IEEE 802.11 family of protocols) is a commonly used wireless
networking standard. The following options allow for configuration of
Wi-Fi client interfaces.
WPA-secured networks are managed using *wpa_supplicant*(8), while insecure
networks are managed directly with *iwconfig*(8).
# WIFI-RELATED OPTIONS
*wifi-config-path* _path_
Denotes the absolute _path_ to a *wpa_supplicant* configuration file.
If no path is given, _/run/wpa_supplicant.<interface>.conf_ will be
used for a temporary configuration file. This option may not be used
with other configuration options.
*wifi-ssid* _ssid_
The SSID the Wi-Fi client should connect to.
*wifi-psk* _psk_
The passphrase for connecting to the Wi-Fi network. If unset, the
client will connect without WPA2 encryption.
# EXAMPLES
A typical setup may involve connecting to a home and work network. To
achieve this, we can define a pair of virtual interfaces called *wifi-home*
and *wifi-work*, which connect to their respective wifi networks:
```
iface wifi-home
use dhcp
wifi-ssid HomeNetwork
wifi-psk ExamplePassphrase
iface wifi-work
use dhcp
wifi-config-path /etc/network/wpa-work.conf
```
The virtual interfaces can be used with *ifup* and *ifdown*:
```
# ifup wlan0=wifi-home
# ifdown wlan0
# ifup wlan0=wifi-work
```
# SEE ALSO
*iwconfig*(8)++
*wpa_supplicant*(8)
# AUTHORS
Ariadne Conill <ariadne@dereferenced.org>

View file

@ -18,15 +18,6 @@ allow to set up Wireguard VPN tunnels.
used. In the latter case _use wireguard_ has to be explicitly
set to the interface configuration.
Be aware that the given configuration file will be loaded using
*wg setconf* and not with *wg-quick*. The file format for both
tools isn't compatible so you have to make sure you provide a
valid configuration file for the *wg* tool. If you already have
a configuration file for *wg-quick* you can set up the tunnel
manually once and then dump the configuration using *wg showconf*
and save this to _path_.
# EXAMPLES
A Wireguard VPN tunnel with explicit configuration file specified

View file

@ -11,7 +11,7 @@ interfaces are configured. The file is processed by *ifquery*(8),
*ifup*(8) and *ifdown*(8) to introspect and change system state.
In most cases, syntax from legacy implementations is supported as
well, but that syntax is not discussed in detail here.
well, but that syntax is not discussed here.
# FILE SYNTAX
@ -24,8 +24,6 @@ value combination that is related to an *object*. Triples which
are not associated with an *object* are considered to be part
of the root of the configuration tree.
All keywords are case-sensitive and are expected to be lower-case.
The following is a simple example of a stanza:
```
@ -66,11 +64,11 @@ the system will only respond to certain keywords by default:
*address* _address_
Associates an IPv4 or IPv6 address in CIDR notation with
the parent interface. If an IP address without a prefix
length is given a given _netmask_ attribute is used if present.
If neither a prefix length nor a _netmask_ are given a /24 or /64
prefix length is presumed for IPv4 / IPv6 as of compatibility
reasons to classic ifupdown.
the parent interface.
*gateway* _address_
Associates an IPv4 or IPv6 address with the parent interface
for use as a default route (gateway).
*netmask* _netmask_
Associates a fallback netmask with the parent interface for
@ -85,11 +83,6 @@ the system will only respond to certain keywords by default:
For compatiblity with ifupdown and ifupdown2, _pointopoint_ is
an alias for this parameter.
*gateway* _address_
Associates an IPv4 or IPv6 address with the parent interface
for use as a default route (gateway). This usually is given
once for IPv4 and once for IPv6 (in a Dual-Stack setup).
*link-type* _link-type_
Denotes the link-type of the interface. When set to _dummy_,
the interface is created as a virtual dummy interfaces.
@ -115,9 +108,9 @@ the system will only respond to certain keywords by default:
configuration data from _object_. Normally _object_
must be a *template*.
*use* _executor_
Designates that an executor should be used. See _EXECUTORS_
section for more information on executors.
*use* _option_
Designates that an option should be used. See _OPTIONS_
section for more information on options.
*pre-down* _command_
Runs _command_ before taking the interface down.
@ -140,11 +133,11 @@ the system will only respond to certain keywords by default:
Additional packages such as *bonding*, *bridge*, *tunnel*, *vrf* and
*vxlan* add additional keywords to this vocabulary.
# EXECUTORS
# OPTIONS
The *use* keyword designates that an _executor_ should be used.
The *use* keyword designates that an _option_ should be used.
This system is extendable by additional packages, but the
most common executors are:
most common options are:
*batman*
The interface is a B.A.T.M.A.N. adv. mesh interface.
@ -165,9 +158,6 @@ most common executors are:
Use a DHCP client to learn the IPv4 address of an
interface.
*forward*
Configures forwarding settings on the interface.
*loopback*
Designates the interface as a loopback device.
@ -178,8 +168,7 @@ most common executors are:
*tunnel*
The interface is a tunnel. Configuration of tunnels
requires the *tunnel* package to be installed on Alpine
Linux.
requires the *tunnel* package to be installed.
*vrf*
The interface is a VRF. Configuration of VRFs requires
@ -189,22 +178,11 @@ most common executors are:
The interface is a Virtual Extensible LAN (VXLAN) tunnel
endpoint.
*wifi*
The interface is a Wi-Fi (IEEE 802.11) client interface.
Configuration of the WiFi client interface requires the
*wireless-tools* package to be installed.
The *wpa_supplicant* package must also be installed to
connect to hotspots using WPA-based security.
*wireguard*
The interface is a Wireguard VPN tunnel endpoint.
Check *interfaces-<executor>(5)* for further informaton about a given
executor and available configuration parameters.
If the _auto\_executor\_selection_ ifupdown-ng.conf option is enabled,
*use* statements will automatically be added for executors when their
configuration statements are present in the interfaces file.
Check *interfaces-<option>(5)* for further informaton about a given
option and available configuration parameters.
# EXAMPLES
@ -238,8 +216,6 @@ iface eth0
# SEE ALSO
*ifstate*(5)
*ifupdown-ng.conf*(5)
*ifup*(8)
*ifdown*(8)
*ifquery*(8)
@ -247,13 +223,9 @@ iface eth0
*interfaces-batman*(5)
*interfaces-bond*(5)
*interfaces-bridge*(5)
*interfaces-forward*(5)
*interfaces-mpls*(5)
*interfaces-ppp*(5)
*interfaces-tunnel*(5)
*interfaces-vrf*(5)
*interfaces-vxlan*(5)
*interfaces-wifi*(5)
*interfaces-wireguard*(5)
# AUTHORS

View file

@ -8,6 +8,8 @@
#
# See interfaces-batman(5) for a list of supported options for hardifs as well as meshifs.
#
set -e
if [ "$VERBOSE" ]; then
set -x
fi

View file

@ -5,11 +5,14 @@
# Sat, 03 Oct 2020 20:42:19 +0200
# -- Maximilian Wilhelm <max@sdn.clinic>
#
set -e
[ -n "$VERBOSE" ] && set -x
get_bond_options() {
# We only care for options of format IF_BOND_<OPTION_NAME>
env | grep '^IF_BOND_[A-Z0-9_]\+' | while IFS="=" read opt value; do
env | grep '^IF_BOND_[A-Z0-9_]\+$' | while IFS="=" read opt value; do
# Members are handled seperately
if [ "${opt}" = "IF_BOND_MEMBERS" ]; then
continue
@ -41,9 +44,9 @@ case "$PHASE" in
# Add members to bundle
for member_iface in ${IF_BOND_MEMBERS}; do
# Work around the current execution order
${MOCK} ip link set "${member_iface}" down
${MOCK} ip link set master "${IFACE}" "${member_iface}"
${MOCK} ip link set "${member_iface}" up
ip link set "${member_iface}" down
ip link set master "${IFACE}" "${member_iface}"
ip link set "${member_iface}" up
done
;;

View file

@ -1,5 +1,6 @@
#!/bin/sh
[ -n "$VERBOSE" ] && set -x
set -e
# Copyright (C) 2012, 2020 Natanael Copa <ncopa@alpinelinux.org>
# Copyright (C) 2020 Ariadne Conill <ariadne@dereferenced.org>
@ -13,10 +14,6 @@
# implied. In no event shall the authors be liable for any damages arising
# from the use of this software.
################################################################################
# Bridge management functions #
################################################################################
all_ports_exist() {
local i=
for i in "$@"; do
@ -55,10 +52,13 @@ all_ports() {
add_ports() {
local port=
for port in $PORTS; do
if [ -x /etc/network/if-pre-up.d/vlan ]; then
env IFACE=$port /etc/network/if-pre-up.d/vlan
fi
if [ -n "$IF_BRIDGE_HW" ]; then
ip link set dev $port addr $IF_BRIDGE_HW
fi
ip link set dev $port master $IFACE && ip link set dev $port up
brctl addif $IFACE $port && ip link set dev $port up
done
}
@ -66,17 +66,22 @@ del_ports() {
local port=
for port in $PORTS; do
ip link set dev $port down
ip link set dev $port nomaster
brctl delif $IFACE $port
if [ -x /etc/network/ip-post-down.d/vlan ]; then
env IFACE=$port /etc/network/if-post-down.d/vlan
fi
done
}
set_bridge_opts_brctl() {
set_bridge_opts() {
[ -n "$IF_BRIDGE_AGEING" ] \
&& brctl setageing $IFACE $IF_BRIDGE_AGEING
[ -n "$IF_BRIDGE_BRIDGEPRIO" ] \
&& brctl setbridgeprio $IFACE $IF_BRIDGE_BRIDGEPRIO
[ -n "$IF_BRIDGE_FD" ] \
&& brctl setfd $IFACE $IF_BRIDGE_FD
[ -n "$IF_BRIDGE_GCINT" ] \
&& brctl setgcint $IFACE $IF_BRIDGE_GCINT
[ -n "$IF_BRIDGE_HELLO" ] \
&& brctl sethello $IFACE $IF_BRIDGE_HELLO
[ -n "$IF_BRIDGE_MAXAGE" ] \
@ -89,44 +94,6 @@ set_bridge_opts_brctl() {
&& brctl stp $IFACE $IF_BRIDGE_STP
}
yesno() {
case "$1" in
yes|YES|true|TRUE|1)
echo 1
;;
*)
echo 0
;;
esac
}
set_bridge_opts_iproute2() {
[ -n "$IF_BRIDGE_AGEING" ] \
&& ip link set dev $IFACE type bridge ageing_time $IF_BRIDGE_AGEING
[ -n "$IF_BRIDGE_BRIDGEPRIO" ] \
&& ip link set dev $IFACE type bridge priority $IF_BRIDGE_BRIDGEPRIO
[ -n "$IF_BRIDGE_FD" ] \
&& ip link set dev $IFACE type bridge forward_delay $IF_BRIDGE_FD
[ -n "$IF_BRIDGE_HELLO" ] \
&& ip link set dev $IFACE type bridge hello_time $IF_BRIDGE_HELLO
[ -n "$IF_BRIDGE_MAXAGE" ] \
&& ip link set dev $IFACE type bridge max_age $IF_BRIDGE_MAXAGE
[ -n "$IF_BRIDGE_PATHCOST" ] \
&& bridge link set dev $IFACE cost $IF_BRIDGE_PATHCOST
[ -n "$IF_BRIDGE_PORTPRIO" ] \
&& bridge link set dev $IFACE priority $IF_BRIDGE_PORTPRIO
[ -n "$IF_BRIDGE_STP" ] \
&& ip link set dev $IFACE type bridge stp $(yesno $IF_BRIDGE_STP)
[ -n "$IF_BRIDGE_VLAN_AWARE" ] \
&& ip link set dev $IFACE type bridge vlan_filtering $(yesno $IF_BRIDGE_VLAN_AWARE)
}
set_bridge_opts() {
[ -x /sbin/bridge ] && set_bridge_opts_iproute2 && return 0
[ -x /sbin/brctl ] && set_bridge_opts_brctl && return 0
}
all_ports_ready() {
local port=
for port in $PORTS; do
@ -156,92 +123,7 @@ wait_bridge() {
done
}
################################################################################
# Bridge port management functions #
################################################################################
configure_access_port() {
port="$1"
vlan="$2"
self="$3"
# Cleans all existing VLANs (probably at least VLAN 1)
bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | while read vid flags; do
bridge vlan del vid "${vid}" dev "${port}" ${self}
done
bridge vlan add vid "${vlan}" pvid untagged dev "${port}" ${self}
}
configure_trunk_port() {
port="$1"
self="$2"
# Working on the bridge itself?
if [ "${self}" ]; then
allow_untagged="${IF_BRIDGE_ALLOW_UNTAGGED}"
pvid="${IF_BRIDGE_PVID}"
vids="${IF_BRIDGE_VIDS}"
else
allow_untagged=$(ifquery -p bridge-allow-untagged ${port} 2>/dev/null || true)
pvid=$(ifquery -p bridge-pvid ${port} 2>/dev/null || true)
vids=$(ifquery -p bridge-vids ${port} 2>/dev/null || true)
fi
# If bridge-allow-untagged if set to off, remove untagged VLAN. If it's
# one of our bridge-vids, it will be set again later.
if [ "${allow_untagged}" -a "$(yesno ${allow_untagged})" = 0 ]; then
untagged_vid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/Untagged/ { print $1 }')
if [ "${untagged_vid}" ]; then
bridge vlan del vid "${untagged_vid}" dev "${port}" ${self}
fi
fi
# The vlan specified is to be considered a PVID at ingress.
# Any untagged frames will be assigned to this VLAN.
if [ "${pvid}" ]; then
cur_pvid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/PVID/ { print $1 }')
if [ "${cur_pvid}" ]; then
bridge vlan del vid ${cur_pvid} dev "${port}" ${self}
fi
bridge vlan add vid "${pvid}" dev "${port}" pvid untagged ${self}
fi
# Add regular tagged VLANs
for vid in ${vids}; do
bridge vlan add vid $vid dev "${port}" ${self}
done
}
# Configure VLANs on the bridge interface itself
set_bridge_vlans() {
# Shall the bridge interface be an untagged port?
if [ "${IF_BRIDGE_ACCESS}" ]; then
configure_access_port "${IFACE}" "${IF_BRIDGE_ACCESS}" "self"
# Configure bridge interface as trunk port
else
configure_trunk_port "${IFACE}" "self"
fi
}
# Configure VLANs on the bridge-ports
set_bridge_port_vlans() {
for port in ${PORTS}; do
access_vlan=$(ifquery -p bridge-access ${port} 2>/dev/null || true)
# Shall this prot interface be an untagged port?
if [ "${access_vlan}" ]; then
configure_access_port "${port}" "${access_vlan}"
# Configure port as trunk
else
configure_trunk_port "${port}"
fi
done
}
[ -z "$IF_BRIDGE_PORTS" ] && IF_BRIDGE_PORTS="$IF_REQUIRES"
case "$IF_BRIDGE_PORTS" in
"") ;;
@ -250,53 +132,30 @@ all) PORTS=$(all_ports);;
*) PORTS="$IF_BRIDGE_PORTS";;
esac
[ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit
case "$PHASE" in
depend)
# Called for the bridge interface
if [ "${IF_BRIDGE_PORTS}" ]; then
echo "$PORTS"
fi
echo "$PORTS"
;;
create)
# Called for the bridge interface
if [ "${IF_BRIDGE_PORTS}" -a ! -d "/sys/class/net/${IFACE}" ]; then
ip link add "${IFACE}" type bridge
if [ ! -d "/sys/class/net/${IFACE}" ]; then
brctl addbr "${IFACE}"
fi
;;
pre-up)
# Called for the bridge interface
if [ "${IF_BRIDGE_PORTS}" ]; then
wait_ports
set_bridge_opts
set_bridge_vlans
add_ports
set_bridge_port_vlans
wait_bridge
# Called for a bridge member port
elif [ "${IF_BRIDGE_VIDS}" -o "${IF_BRIDGE_PVID}" -o "${IF_BRIDGE_ACCESS}" -o "${IF_BRIDGE_ALLOW_UNTAGGED}" ]; then
# Eventually we want to configure VLAN settings of member ports here.
# The current execution model does not allow this, so this is a no-op
# for now and we work around this by configuring ports while configuring
# the bridge.
true
fi
wait_ports
set_bridge_opts
add_ports
wait_bridge
;;
post-down)
# Called for the bridge interface
if [ "${IF_BRIDGE_PORTS}" ]; then
del_ports
ip link set dev $IFACE down
fi
del_ports
ip link set dev $IFACE down
;;
destroy)
# Called for the bridge interface
if [ "${IF_BRIDGE_PORTS}" -a -d "/sys/class/net/${IFACE}" ]; then
ip link del "${IFACE}"
if [ -d "/sys/class/net/${IFACE}" ]; then
brctl delbr "${IFACE}"
fi
;;
esac

View file

@ -1,6 +1,9 @@
#!/bin/sh
set -e
# some users provide a shell fragment for the hostname property.
[ -n "$IF_DHCP_HOSTNAME" ] && IF_DHCP_HOSTNAME=$(eval echo $IF_DHCP_HOSTNAME)
[ -n "$IF_HOSTNAME" ] && IF_HOSTNAME=$(eval echo $IF_HOSTNAME)
determine_implementation() {
[ -n "$IF_DHCP_PROGRAM" ] && echo "$IF_DHCP_PROGRAM" && return
@ -14,25 +17,20 @@ determine_implementation() {
start() {
case "$1" in
dhcpcd)
[ -n "$IF_DHCP_HOSTNAME" ] && optargs="$optargs -h $IF_DHCP_HOSTNAME"
[ -n "$IF_DHCP_VENDOR" ] && optargs="$optargs -i $IF_DHCP_VENDOR"
[ -n "$IF_DHCP_CLIENT_ID" ] && optargs="$optargs -i $IF_DHCP_CLIENT_ID"
[ -n "$IF_DHCP_LEASETIME" ] && optargs="$optargs -l $IF_DHCP_LEASETIME"
[ -n "$IF_HOSTNAME" ] && optargs="$optargs -h $IF_HOSTNAME"
[ -n "$IF_VENDOR" ] && optargs="$optargs -i $IF_VENDOR"
[ -n "$IF_CLIENT" ] && optargs="$optargs -i $IF_CLIENT"
[ -n "$IF_LEASETIME" ] && optargs="$optargs -l $IF_LEASETIME"
${MOCK} /sbin/dhcpcd $optargs $IFACE
;;
dhclient)
# Specific config file given?
if [ -n "$IF_DHCP_CONFIG" ]; then
optargs="$optargs -cf $IF_DHCP_CONFIG"
fi
${MOCK} /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $optargs $IFACE
${MOCK} /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE
;;
udhcpc)
optargs=$(eval echo $IF_UDHCPC_OPTS)
[ -n "$IF_DHCP_HOSTNAME" ] && optargs="$optargs -x hostname:$IF_DHCP_HOSTNAME"
[ -n "$IF_DHCP_CLIENT_ID" ] && optargs="$optargs -c $IF_DHCP_CLIENT_ID"
[ -n "$IF_DHCP_SCRIPT" ] && optargs="$optargs -s $IF_DHCP_SCRIPT"
[ -n "$IF_HOSTNAME" ] && optargs="$optargs -x hostname:$IF_HOSTNAME"
[ -n "$IF_CLIENT" ] && optargs="$optargs -c $IF_CLIENT"
[ -n "$IF_SCRIPT" ] && optargs="$optargs -s $IF_SCRIPT"
${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE $optargs
;;
*)

View file

@ -1,4 +1,6 @@
#!/bin/sh
set -e
# gather params for a given prefix, based on executor-scripts/linux/tunnel.
gather_params() {
env | sed -E "

View file

@ -1,19 +0,0 @@
#!/bin/sh
yesno() {
case "$1" in
yes|1) echo 1 ;;
*) echo 0 ;;
esac
}
[ "$PHASE" != "up" ] && exit 0
[ -z "$VERBOSE" ] || set -x
[ -n "$IF_FORWARD_IPV4" ] && ${MOCK} /bin/sh -c "echo $(yesno $IF_FORWARD_IPV4) > /proc/sys/net/ipv4/conf/$IFACE/forwarding"
[ -n "$IF_FORWARD_IPV6" ] && ${MOCK} /bin/sh -c "echo $(yesno $IF_FORWARD_IPV6) > /proc/sys/net/ipv6/conf/$IFACE/forwarding"
[ -n "$IF_FORWARD_IPV4_MC" ] && ${MOCK} /bin/sh -c "echo $(yesno $IF_FORWARD_IPV4_MC) > /proc/sys/net/ipv4/conf/$IFACE/mc_forwarding"
[ -n "$IF_FORWARD_IPV6_MC" ] && ${MOCK} /bin/sh -c "echo $(yesno $IF_FORWARD_IPV6_MC) > /proc/sys/net/ipv6/conf/$IFACE/mc_forwarding"
exit 0

View file

@ -1,4 +1,7 @@
#!/bin/sh
set -e
# Executor for advanced GRE tunnel management.
[ -z "$IF_GRE_LOCAL" ] && exit 1

View file

@ -1,4 +1,7 @@
#!/bin/sh
set -e
start() {
${MOCK} /bin/sh -c "echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra"
}

View file

@ -1,4 +1,7 @@
#!/bin/sh
set -e
[ -n "$VERBOSE" ] && set -x
is_vlan() {

View file

@ -1,36 +0,0 @@
#!/bin/sh
#
# Maximilian Wilhelm <max@sdn.clinic>
# -- Thu, 17 Dec 2020 03:02:10 +0100
#
# This executor is responsible for setting up MPLS decapsulation on a given interface.
#
# See interfaces-mpls(5) for a list of supported options.
#
yesno() {
case "$1" in
yes|1) echo 1 ;;
*) echo 0 ;;
esac
}
[ -z "$VERBOSE" ] || set -x
# We only operate in pre-up phase
[ "$PHASE" != "pre-up" ] && exit 0
if [ "$IF_MPLS_ENABLE" ]; then
value=$(yesno $IF_MPLS_ENABLE)
# Load mpls module if we should enable MPLS decap on (at least) one interface
if [ "${value}" = 1 ]; then
${MOCK} modprobe mpls_iptunnel
fi
# If MPLS support isn't loaded and we are not MOCKing, carry on
if [ -f "/proc/sys/net/mpls/conf/$IFACE/input" -o "${MOCK}" ]; then
${MOCK} /bin/sh -c "echo ${value} > /proc/sys/net/mpls/conf/$IFACE/input"
fi
fi

View file

@ -1,4 +1,6 @@
#!/bin/sh
set -e
[ -z "$IF_PPP_PROVIDER" ] && exit 0
case "$PHASE" in

View file

@ -1,4 +1,7 @@
#!/bin/sh
set -e
[ -z "${VERBOSE}" ] || set -x
[ -z "${IF_METRIC}" ] && IF_METRIC="1"
@ -26,31 +29,34 @@ configure_addresses() {
PEER=""
fi
${MOCK} ip "${addrfam}" addr add "${addr}" ${PEER} dev "${IFACE}"
if [ -z "${MOCK}" -a "${1}" = "del" ]; then
# When having multiple addresses set from the same prefix they might/will(?) be configured
# as 'secondary' and implicitly removed when removing the non-secondary address. This
# leads ip complaining about not being able to remove the secondaries as they are already
# gone. So we ignore errors while deconfiguring addresses as they liked occur when removing
# a vanish address anyway.
${MOCK} ip "${addrfam}" addr "${1}" "${addr}" ${PEER} dev "${IFACE}" 2>/dev/null
else
${MOCK} ip "${addrfam}" addr "${1}" "${addr}" ${PEER} dev "${IFACE}"
fi
done
}
configure_gateways() {
for gw in ${IF_GATEWAYS}; do
addrfam=$(addr_family ${gw})
${MOCK} ip "${addrfam}" route add default via "${gw}" ${VRF_TABLE} ${METRIC} dev "${IFACE}"
${MOCK} ip "${addrfam}" route "${1}" default via "${gw}" ${VRF_TABLE} ${METRIC} dev "${IFACE}"
done
}
flush() {
cmd="addr"
arg="dev ${IFACE}"
${MOCK} ip ${cmd} flush ${arg}
}
case "$PHASE" in
up)
configure_addresses add
configure_gateways add
;;
down)
flush
configure_gateways del
configure_addresses del
;;
*) exit 0 ;;
esac

View file

@ -1,106 +1,27 @@
#!/bin/sh
set -e
# Based on alpine's tunnel configuration script.
# Copyright (c) 2017 Kaarle Ritvanen
# Copyright (c) 2020 Ariadne Conill (extended for ifupdown-ng)
# Copyright (c) 2021 Maximilian Wilhelm (make sure mode/type is 1st parameter, add more options)
[ -z "$IF_TUNNEL_LOCAL" -a -z "$IF_TUNNEL_LOCAL_DEV" ] && exit 1
[ -z "$IF_TUNNEL_LOCAL" ] && exit 1
[ -z "$IF_TUNNEL_REMOTE" ] && exit 1
[ -z "$IF_TUNNEL_MODE" ] && exit 1
[ -n "$VERBOSE" ] && set -x
yesno() {
case "$1" in
yes|1) echo 1 ;;
*) echo 0 ;;
esac
}
# Figure out address familiy
FAMILY="4"
COMMAND="tunnel"
FAMILY="-4"
case "$IF_TUNNEL_MODE" in
gretap)
COMMAND="link"
;;
vti6|ipip6|ip6*)
FAMILY="6"
FAMILY="-6"
;;
esac
# Figure out object type - gretap tunnels have to create using ip link
# and therefor require 'type' keyword instead of 'mode'
OBJECT="tunnel"
TYPE_KW="mode"
case "${IF_TUNNEL_MODE}" in
*gretap)
OBJECT="link"
TYPE_KW="type"
# Strip possible "ip6" from tunnel mode
TUNNEL_MODE="gretap"
;;
*)
# Store tunnel type/mode separaltely and unset input variable to exclude it
# from PARAMS below
TUNNEL_MODE="$IF_TUNNEL_MODE"
unset IF_TUNNEL_MODE
;;
esac
# If 'tunnel-local <IP>' was not given but 'tunnel-local-dev <iface>' is given try
# to figure out the IP of the underlay device (wrt the address family used for this
# tunnel) and use this to set up the tunnel
if [ ${PHASE} = "create" -a ! "${IF_TUNNEL_LOCAL}" -a "${IF_TUNNEL_LOCAL_DEV}" ]; then
if [ "${FAMILY}" = "4" ]; then
ip=$(ip -4 -brief addr show dev "${IF_TUNNEL_LOCAL_DEV}" 2>/dev/null | awk '{ print $3 }' | cut -d/ -f1)
# For IPv6 we try to use a non-temporary address (-> privacy extensions)
else
# Get all IPv6 addres configured on $IF_TUNNEL_LOCAL_DEV which are not
# temporary (due to privacy extensions). We do not filter for "mgmtaddr"
# "scope global" etc. as we don't want to make further assumptions on
# whether a user wants to use a link local address configured to this interface.
#
# The assumption that a temporary address configured by PE isn't suited
# to terminate a tunnel should hold in nearly all setups, I hope.
ip=$(ip -6 addr show dev "${IF_TUNNEL_LOCAL_DEV}" -temporary | grep inet6 | head -n1 | awk '{ print $2 }' | cut -d/ -f1)
fi
if [ ! "${ip}" ]; then
echo "Unable to determine the IPv${FAMILIY} address of tunnel-local-dev ${IF_TUNNEL_LOCAL_DEV}!"
exit 1
fi
unset IF_TUNNEL_LOCAL_DEV
export IF_TUNNEL_LOCAL="${ip}"
fi
# Handle boolean switches
MORE_PARAMS=""
if [ "${IF_TUNNEL_IGNORE_DF}" ]; then
if $(yesno "${IF_TUNNEL_IGNORE_DF}"); then
MORE_PARAMS="ignore-df"
else
MORE_PARAMS="noignore-df"
fi
unset IF_TUNNEL_IGNORE_DF
fi
if [ "${IF_TUNNEL_PMTUDISC}" ]; then
if $(yesno "${IF_TUNNEL_PMTUDISC}"); then
MORE_PARAMS="pmtudisc"
else
MORE_PARAMS="nopmtudisc"
fi
unset IF_TUNNEL_PMTUDISC
fi
# Mangle residual IF_TUNNEL_* params into single string
PARAMS=$(set | sed -E '
s/^IF_TUNNEL_([A-Z0-9_]+)=(.+)/\1\n\2/
ta
@ -117,12 +38,12 @@ PARAMS=$(set | sed -E '
case "$PHASE" in
create)
${MOCK} eval ip -$FAMILY $OBJECT add $IFACE $TYPE_KW $TUNNEL_MODE $PARAMS $MORE_PARAMS
${MOCK} eval ip $FAMILY $COMMAND add $IFACE $PARAMS
;;
destroy)
${MOCK} ip -$FAMILY $OBJECT del $IFACE
${MOCK} ip $FAMILY $COMMAND del $IFACE
;;
depend)
echo "${IF_TUNNEL_DEV}" "${IF_TUNNEL_LOCAL_DEV}"
echo "$IF_TUNNEL_DEV"
;;
esac

View file

@ -1,4 +1,6 @@
#!/bin/sh
set -e
handle_init() {
${MOCK} /sbin/ip link $1 $IFACE type vrf table $IF_VRF_TABLE
${MOCK} /sbin/ip rule $1 iif $IFACE table $IF_VRF_TABLE

View file

@ -10,12 +10,15 @@
# IF_VXLAN_ID The VXLAN Network Identifier (VNI)
# IF_VXLAN_PHYSDEV Specifies the physical device to use for tunnel endpoint communication
# IF_VXLAN_LOCAL_IP Specifies the source IP address to use in outgoing packets
# IF_VXLAN_PEER_IPS Space separated list of IPs of the remote VTEP endpoint (for ptp/ptmp mode with ingress replication)
# IF_VXLAN_PEER_GROUP Multicast group to use for this VNI (for ptmp mode with multicast)
# IF_VXLAN_REMOTE_IP IP of the remote VTEP endpoint (for ptp mode)
# IF_VXLAN_REMOTE_GROUP Multicast group to use for this VNI (for ptmp mode)
# IF_VXLAN_LEARNING Wether to activate MAC learning on this instance (on/off)
# IF_VXLAN_AGEING Specifies the lifetime in seconds of FDB entries learnt by the kernel
# IF_VXLAN_DSTPORT UDP destination port to communicate to the remote VXLAN tunnel endpoint (default 4789)
#
set -e
[ -n "$VERBOSE" ] && set -x
# No VNI, nuthin' to do for us
@ -36,27 +39,17 @@ case "$PHASE" in
fi
# Input validation
if [ "${IF_VXLAN_PEER_IPS}" -a "${IF_VXLAN_PEER_GROUP}" ]; then
echo "Error on ${IFACE} (vxlan): Only one of 'vxlan-peer-ips' and 'vxlan-peer-group' can be used!" >&2
if [ "${IF_VXLAN_REMOTE_IP}" -a "${IF_VXLAN_REMOTE_GROUP}" ]; then
echo "Error on ${IFACE} (vxlan): Only one of 'remote' and 'group' can be given!" >&2
exit 1
fi
# Check if we should operate in unicast ptp or ptmp mode
if [ "${IF_VXLAN_PEER_IPS}" ]; then
# If it's only one thing which looks like an IPv4/IPv6 address we assume it's ptp
if echo "${IF_VXLAN_PEER_IPS}" | grep -q '^[[:space:]]*[[:xdigit:].:]\+[[:space:]]*$'; then
UCAST_MODE="ptp"
else
UCAST_MODE="ptmp"
fi
fi
# Gather arguments
ARGS=""
[ "${IF_VXLAN_PHYSDEV}" ] && ARGS="${ARGS} dev ${IF_VXLAN_PHYSDEV}"
[ "${IF_VXLAN_LOCAL_IP}" ] && ARGS="${ARGS} local ${IF_VXLAN_LOCAL_IP}"
[ "${UCAST_MODE}" = "ptp" ] && ARGS="${ARGS} remote ${IF_VXLAN_PEER_IPS}"
[ "${IF_VXLAN_PEER_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_PEER_GROUP}"
[ "${IF_VXLAN_REMOTE_IP}" ] && ARGS="${ARGS} remote ${IF_VXLAN_REMOTE_IP}"
[ "${IF_VXLAN_REMOTE_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_REMOTE_GROUP}"
[ "${IF_VXLAN_AGEING}" ] && ARGS="${ARGS} ageing ${IF_VXLAN_AGEING}"
# Linux uses non-standard default port - WTF?
@ -77,13 +70,6 @@ case "$PHASE" in
esac
${MOCK} ip link add "${IFACE}" type vxlan id "${IF_VXLAN_ID}" ${ARGS}
# Set up FDB entries for peer VTEPs
if [ "${UCAST_MODE}" = "ptmp" ]; then
for peer in ${IF_VXLAN_PEER_IPS}; do
${MOCK} bridge fdb append 00:00:00:00:00:00 dev "${IFACE}" dst "${peer}" self permanent
done
fi
;;
destroy)

View file

@ -1,119 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# This software is provided 'as is' and without any warranty, express or
# implied. In no event shall the authors be liable for any damages arising
# from the use of this software.
#
# Manage wifi connections using wpa_supplicant.
#
# Vocabulary:
# wifi-ssid - The SSID name to connect to.
# wifi-psk - The pre-shared key to use.
# wifi-config - A path to a wpa_supplicant config file, for special configs.
#
# If wifi-config is not set, wifi-ssid and wifi-psk are required, and a config
# will be generated as /run/wpa_supplicant.$IFACE.conf.
#
# The wpa_supplicant PID is stored in /run/wpa_supplicant.$IFACE.pid.
die() {
printf "ERROR: %s\n" "$1" >&2
exit 1
}
[ -z "$IFACE" ] && die "IFACE not set"
[ -z "$PHASE" ] && die "PHASE not set"
PIDFILE="/run/wpa_supplicant.$IFACE.pid"
# Do not allow mixing wifi-config-path and wifi-ssid/wifi-psk.
[ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_SSID" ] && die "wifi-config-path cannot be used with wifi-ssid"
[ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_PSK" ] && die "wifi-config-path cannot be used with wifi-psk"
# Set IF_WIFI_CONFIG_PATH to the default path if not already set.
WIFI_CONFIG_PATH="$IF_WIFI_CONFIG_PATH"
[ -z "$WIFI_CONFIG_PATH" ] && WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf"
# Supplicant options.
WPA_SUPPLICANT_OPTS="-qq -B -i$IFACE -c$WIFI_CONFIG_PATH -P$PIDFILE"
# Given $IF_WIFI_SSID and $IF_WIFI_PSK, generate a config file at $WIFI_CONFIG_PATH.
generate_config() {
[ -z "$IF_WIFI_SSID" ] && die "wifi-ssid not set"
[ -z "$IF_WIFI_PSK" ] && die "wifi-psk not set"
# We use a pipeline here to avoid leaking PSK into the process name.
(echo $IF_WIFI_PSK | /sbin/wpa_passphrase $IF_WIFI_SSID) >$WIFI_CONFIG_PATH
[ ! -e "$WIFI_CONFIG_PATH" ] && die "failed to write temporary config: $WIFI_CONFIG_PATH"
}
# Should we use the supplicant?
use_supplicant() {
[ -n "$IF_WIFI_CONFIG_PATH" ] && return 0
[ -n "$IF_WIFI_PSK" ] && return 0
return 1
}
# Either start a supplicant process for $IFACE, or use iwconfig to trigger an
# association attempt.
start() {
if use_supplicant; then
# If there is no config file located at $WIFI_CONFIG_PATH, generate one.
[ ! -e "$WIFI_CONFIG_PATH" ] && generate_config
/sbin/wpa_supplicant $WPA_SUPPLICANT_OPTS
else
/usr/sbin/iwconfig $IFACE essid -- "$IF_WIFI_SSID" ap any
fi
}
# Stop wpa_supplicant safely
stop_wpa_supplicant() {
# Remove generated config file
[ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH"
# If there is no PIDFILE, there is nothing we can do
[ ! -f "$PIDFILE" ] && return
pid=$(cat "$PIDFILE")
rm -- "$PIDFILE"
# If there is no process with this PID running, we're done here
if [ ! -d "/proc/$pid/" ]; then
return
fi
# Verify that the name of the running process matches wpa_supplicant
progname_path=$(readlink -n "/proc/$pid/exe")
progname=$(basename "$progname_path")
if [ "$progname" = "wpa_supplicant" ]; then
kill -9 $pid 2>/dev/null
fi
}
# Either stop the supplicant process for $IFACE, or use iwconfig to dissociate
# from the current SSID.
stop() {
if use_supplicant; then
stop_wpa_supplicant
else
/usr/sbin/iwconfig $IFACE essid any
fi
}
[ -z "$VERBOSE" ] || set -x
case "$PHASE" in
pre-up)
start
;;
post-down)
stop
;;
esac

View file

@ -1,4 +1,7 @@
#!/bin/sh
set -e
[ -n "$VERBOSE" ] && set -x
[ -z "$IF_WIREGUARD_CONFIG_PATH" ] && IF_WIREGUARD_CONFIG_PATH="/etc/wireguard/$IFACE.conf"

View file

@ -1,4 +1,5 @@
#!/bin/sh
set -e
[ -z "$IF_BOND_MEMBERS" ] && IF_BOND_MEMBERS="$IF_BOND_SLAVES"
case "$PHASE" in
depend) echo "$IF_BOND_MEMBERS" ;;

View file

@ -1,4 +1,5 @@
#!/bin/sh
set -e
case "$PHASE" in
depend)
if [ "$IF_BRIDGE_PORTS" != "none" ]; then

View file

@ -1,114 +0,0 @@
/*
* libifupdown/compat.c
* Purpose: compatiblity glue to other implementations
*
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "libifupdown/compat.h"
#include "libifupdown/config-file.h"
#include "libifupdown/dict.h"
#include "libifupdown/interface.h"
#include "libifupdown/tokenize.h"
static bool
compat_ifupdown2_bridge_ports_inherit_vlans(struct lif_dict *collection)
{
struct lif_node *iter;
/* Loop through all interfaces and search for bridges */
LIF_DICT_FOREACH(iter, collection)
{
struct lif_dict_entry *entry = iter->data;
struct lif_interface *bridge = entry->data;
/* We only care for bridges */
if (!bridge->is_bridge)
continue;
struct lif_dict_entry *bridge_pvid = lif_dict_find(&bridge->vars, "bridge-pvid");
struct lif_dict_entry *bridge_vids = lif_dict_find(&bridge->vars, "bridge-vids");
/* If there's nothing to inherit here, carry on */
if (bridge_pvid == NULL && bridge_vids == NULL)
continue;
struct lif_dict_entry *bridge_ports_entry = lif_dict_find(&bridge->vars, "bridge-ports");
/* This SHOULD not happen, but better save than sorry */
if (bridge_ports_entry == NULL)
continue;
char bridge_ports_str[4096] = {};
strlcpy(bridge_ports_str, bridge_ports_entry->data, sizeof bridge_ports_str);
/* If there are no bridge-ports configured, carry on */
if (strcmp(bridge_ports_str, "none") == 0)
continue;
/* Loop over all bridge-ports and set bridge-pvid and bridge-vid if not set already */
char *bufp = bridge_ports_str;
for (char *tokenp = lif_next_token(&bufp); *tokenp; tokenp = lif_next_token(&bufp))
{
entry = lif_dict_find(collection, tokenp);
/* There might be interfaces give within the bridge-ports for which there is no
* interface stanza. If this is the case, we add one, so we can inherit the
* bridge-vids/pvid to it. */
struct lif_interface *bridge_port;
if (entry)
bridge_port = entry->data;
else if (lif_config.compat_create_interfaces)
{
bridge_port = lif_interface_collection_find(collection, tokenp);
if (bridge_port == NULL)
{
fprintf(stderr, "Failed to add interface \"%s\"", tokenp);
return false;
}
}
/* We would have to creaet an interface, but shouldn't */
else
{
fprintf(stderr, "compat: Missing interface stanza for bridge-port \"%s\" but should not create one.\n",
tokenp);
continue;
}
/* Maybe pimp bridge-pvid */
struct lif_dict_entry *port_pvid = lif_dict_find(&bridge_port->vars, "bridge-pvid");
if (bridge_pvid && !port_pvid)
lif_dict_add(&bridge_port->vars, "bridge-pvid", bridge_pvid->data);
/* Maybe pimp bridge-vids */
struct lif_dict_entry *port_vids = lif_dict_find(&bridge_port->vars, "bridge-vids");
if (bridge_vids && !port_vids)
lif_dict_add(&bridge_port->vars, "bridge-vids", bridge_vids->data);
}
}
return true;
}
bool
lif_compat_apply(struct lif_dict *collection)
{
if (lif_config.compat_ifupdown2_bridge_ports_inherit_vlans &&
!compat_ifupdown2_bridge_ports_inherit_vlans(collection))
return false;
return true;
}

View file

@ -1,24 +0,0 @@
/*
* libifupdown/compat.h
* Purpose: compatiblity glue to other implementations
*
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef LIBIFUPDOWN__COMPAT_H
#define LIBIFUPDOWN__COMPAT_H
#include "libifupdown/config-file.h"
#include "libifupdown/dict.h"
extern bool lif_compat_apply (struct lif_dict *collection);
#endif

View file

@ -21,9 +21,6 @@
struct lif_config_file lif_config = {
.allow_addon_scripts = true,
.allow_any_iface_as_template = true,
.auto_executor_selection = true,
.compat_create_interfaces = true,
.compat_ifupdown2_bridge_ports_inherit_vlans = true,
.implicit_template_conversion = true,
.use_hostname_for_dhcp = true,
};
@ -50,9 +47,6 @@ set_bool_value(const char *key, const char *value, void *opaque)
static struct lif_config_handler handlers[] = {
{"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts},
{"allow_any_iface_as_template", set_bool_value, &lif_config.allow_any_iface_as_template},
{"auto_executor_selection", set_bool_value, &lif_config.auto_executor_selection},
{"compat_create_interfaces", set_bool_value, &lif_config.compat_create_interfaces},
{"compat_ifupdown2_bridge_ports_inherit_vlans", set_bool_value, &lif_config.compat_ifupdown2_bridge_ports_inherit_vlans},
{"implicit_template_conversion", set_bool_value, &lif_config.implicit_template_conversion},
{"use_hostname_for_dhcp", set_bool_value, &lif_config.use_hostname_for_dhcp},
};

View file

@ -21,9 +21,6 @@
struct lif_config_file {
bool allow_addon_scripts;
bool allow_any_iface_as_template;
bool auto_executor_selection;
bool compat_create_interfaces;
bool compat_ifupdown2_bridge_ports_inherit_vlans;
bool implicit_template_conversion;
bool use_hostname_for_dhcp;
};

View file

@ -30,86 +30,6 @@
#define SHELL "/bin/sh"
#if defined(__linux__)
# include <sys/syscall.h>
#endif
/* POSIX compatible fallback using waitpid(2) and usleep(3) */
static inline bool
lif_process_monitor_busyloop(pid_t child, int timeout_sec, int *status)
{
int ticks = 0;
while (ticks < timeout_sec * 20)
{
/* Ugly hack: most executors finish very quickly,
* so give them a chance to finish before sleeping.
*/
usleep(50);
if (waitpid(child, status, WNOHANG) == child)
return true;
usleep(49950);
ticks++;
}
return false;
}
#if defined(__linux__) && defined(__NR_pidfd_open)
/* TODO: remove this wrapper once musl and glibc gain pidfd_open() directly. */
static inline int
lif_pidfd_open(pid_t pid, unsigned int flags)
{
return syscall(__NR_pidfd_open, pid, flags);
}
static inline bool
lif_process_monitor_procdesc(pid_t child, int timeout_sec, int *status)
{
int pidfd = lif_pidfd_open(child, 0);
/* pidfd_open() not available, fall back to busyloop */
if (pidfd == -1 && errno == ENOSYS)
return lif_process_monitor_busyloop(child, timeout_sec, status);
struct pollfd pfd = {
.fd = pidfd,
.events = POLLIN,
};
if (poll(&pfd, 1, timeout_sec * 1000) < 1)
return false;
waitpid(child, status, 0);
close(pidfd);
return true;
}
#endif
static inline bool
lif_process_monitor(const char *cmdbuf, pid_t child, int timeout_sec)
{
int status;
#if defined(__linux__) && defined(__NR_pidfd_open)
if (lif_process_monitor_procdesc(child, timeout_sec, &status))
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
#else
if (lif_process_monitor_busyloop(child, timeout_sec, &status))
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
#endif
fprintf(stderr, "execution of '%s': timeout after %d seconds\n", cmdbuf, timeout_sec);
kill(child, SIGKILL);
waitpid(child, &status, 0);
return false;
}
bool
lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...)
{
@ -135,7 +55,10 @@ lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const c
return false;
}
return lif_process_monitor(cmdbuf, child, opts->timeout);
int status;
waitpid(child, &status, 0);
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
}
bool
@ -195,8 +118,11 @@ lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size
return false;
}
int status;
no_result:
return lif_process_monitor(cmdbuf, child, opts->timeout);
waitpid(child, &status, 0);
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
}
bool

View file

@ -27,7 +27,6 @@ struct lif_execute_opts {
const char *executor_path;
const char *interfaces_file;
const char *state_file;
int timeout;
};
extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...);

View file

@ -32,7 +32,6 @@ struct remap_token {
static const struct remap_token tokens[] = {
{"bond-ad-sys-priority", "bond-ad-actor-sys-prio"}, /* ifupdown2 */
{"bond-slaves", "bond-members"}, /* legacy ifupdown, ifupdown2 */
{"client", "dhcp-client-id"}, /* legacy ifupdown */
{"driver-message-level", "ethtool-msglvl"}, /* Debian ethtool integration */
{"endpoint", "tunnel-remote"}, /* legacy ifupdown */
{"ethernet-autoneg", "ethtool-ethernet-autoneg"}, /* Debian ethtool integration */
@ -69,9 +68,6 @@ static const struct remap_token tokens[] = {
{"hardware-irq-coalesce-tx-usecs-high", "ethtool-coalesce-tx-usecs-high"}, /* Debian ethtool integration */
{"hardware-irq-coalesce-tx-usecs-irq", "ethtool-coalesce-tx-usecs-irq"}, /* Debian ethtool integration */
{"hardware-irq-coalesce-tx-usecs-low", "ethtool-coalesce-tx-usecs-low"}, /* Debian ethtool integration */
{"hostname", "dhcp-hostname"}, /* legacy ifupdown */
{"key", "tunnel-key"}, /* legacy ifupdown */
{"leasetime", "dhcp-leasetime"}, /* legacy ifupdown */
{"link-autoneg", "ethtool-ethernet-autoneg"}, /* ifupdown2 */
{"link-duplex", "ethtool-link-duplex"}, /* Debian ethtool integration */
{"link-fec", "ethtool-link-fec"}, /* ifupdown2 */
@ -89,7 +85,6 @@ static const struct remap_token tokens[] = {
{"offload-ufo", "ethtool-offload-ufo"}, /* Debian ethtool integration */
{"pointopoint", "point-to-point"}, /* legacy ifupdown, ifupdown2 */
{"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */
{"script", "dhcp-script"}, /* legacy ifupdown */
{"rx-offload", "ethtool-offload-rx"}, /* ifupdown2 */
{"tso-offload", "ethtool-offload-tso"}, /* ifupdown2 */
{"ttl", "tunnel-ttl"}, /* legacy ifupdown */
@ -97,13 +92,10 @@ static const struct remap_token tokens[] = {
{"tunnel-physdev", "tunnel-dev"}, /* ifupdown2 */
{"tx-offload", "ethtool-offload-tx"}, /* ifupdown2 */
{"ufo-offload", "ethtool-offload-ufo"}, /* ifupdown2 */
{"vendor", "dhcp-vendor"}, /* legacy ifupdown */
{"vrf", "vrf-member"}, /* ifupdown2 */
{"vxlan-local-tunnelip", "vxlan-local-ip"}, /* ifupdown2 */
{"vxlan-remote-group", "vxlan-peer-group"}, /* ifupdown-ng */
{"vxlan-remoteip", "vxlan-peer-ips"}, /* ifupdown2 */
{"vxlan-remote-ip", "vxlan-peer-ips"}, /* ifupdown-ng */
{"vxlan-svcnodeip", "vxlan-peer-group"}, /* ifupdown2 */
{"vxlan-remoteip", "vxlan-remote-ip"}, /* ifupdown2 */
{"vxlan-svcnodeip", "vxlan-remote-group"}, /* ifupdown2 */
};
static int
@ -214,19 +206,12 @@ handle_generic(struct lif_interface_file_parse_state *state, char *token, char *
token = maybe_remap_token(token);
/* This smells like a bridge */
if (strcmp(token, "bridge-ports") == 0)
state->cur_iface->is_bridge = true;
/* Skip any leading whitespaces in value for <token> */
while (isspace (*bufp))
bufp++;
lif_dict_add(&state->cur_iface->vars, token, strdup(bufp));
if (!lif_config.auto_executor_selection)
return true;
/* Check if token looks like <word1>-<word*> and assume <word1> is an addon */
char *word_end = strchr(token, '-');
if (word_end != NULL)
@ -252,8 +237,8 @@ handle_hostname(struct lif_interface_file_parse_state *state, char *token, char
return true;
}
lif_dict_delete(&state->cur_iface->vars, "dhcp-hostname");
lif_dict_add(&state->cur_iface->vars, "dhcp-hostname", strdup(hostname));
lif_dict_delete(&state->cur_iface->vars, token);
lif_dict_add(&state->cur_iface->vars, token, strdup(hostname));
return true;
}
@ -449,7 +434,6 @@ struct parser_keyword {
static const struct parser_keyword keywords[] = {
{"address", handle_address},
{"auto", handle_auto},
{"dhcp-hostname", handle_hostname},
{"gateway", handle_gateway},
{"hostname", handle_hostname},
{"iface", handle_iface},

View file

@ -216,7 +216,7 @@ lif_interface_use_executor(struct lif_interface *interface, const char *executor
if (uname(&un) < 0)
return;
lif_dict_add(&interface->vars, "dhcp-hostname", strdup(un.nodename));
lif_dict_add(&interface->vars, "hostname", strdup(un.nodename));
}
void

View file

@ -29,7 +29,6 @@
#include "libifupdown/tokenize.h"
#include "libifupdown/config-file.h"
#include "libifupdown/config-parser.h"
#include "libifupdown/compat.h"
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))

View file

@ -94,8 +94,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const
struct lif_execute_opts exec_opts = {
.verbose = opts->verbose,
.executor_path = opts->executor_path,
.interfaces_file = opts->interfaces_file,
.timeout = opts->timeout,
.interfaces_file = opts->interfaces_file
};
if (strcmp(entry->key, "use"))
@ -115,7 +114,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const
return true;
}
static bool
bool
append_to_buffer(char **buffer, size_t *buffer_len, char **end, const char *value)
{
size_t value_len = strlen (value);
@ -123,17 +122,12 @@ append_to_buffer(char **buffer, size_t *buffer_len, char **end, const char *valu
/* Make sure there is enough room to add the value to the buffer */
if (*buffer_len < strlen (*buffer) + value_len + 2)
{
size_t end_offset = *end - *buffer;
char *tmp = realloc (*buffer, *buffer_len * 2);
if (tmp != NULL)
{
*buffer = tmp;
*end = tmp + end_offset;
*buffer_len = *buffer_len * 2;
}
else
*buffer = realloc (*buffer, *buffer_len * 2);
if (*buffer == NULL)
/* XXX Here be dragons */
return false;
*buffer_len = *buffer_len * 2;
}
/* Append value to buffer */

View file

@ -40,7 +40,7 @@ extern void lif_node_delete(struct lif_node *node, struct lif_list *list);
for ((iter) = (head); (iter) != NULL; (iter) = (iter)->next)
#define LIF_LIST_FOREACH_SAFE(iter, iter_next, head) \
for ((iter) = (head), (iter_next) = (iter) != NULL ? (iter)->next : NULL; (iter) != NULL; (iter) = (iter_next), (iter_next) = (iter) != NULL ? (iter)->next : NULL)
for ((iter) = (head), (iter_next) = (iter)->next; (iter) != NULL; (iter) = (iter_next), (iter_next) = (iter) != NULL ? (iter)->next : NULL)
#define LIF_LIST_FOREACH_REVERSE(iter, tail) \
for ((iter) = (tail); (iter) != NULL; (iter) = (iter)->prev)

View file

@ -21,20 +21,20 @@
void
lif_common_version(void)
{
printf(PACKAGE_NAME " " PACKAGE_VERSION "\n"
"\n"
"Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>\n"
"Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>\n"
"\n"
"Permission to use, copy, modify, and/or distribute this software for any\n"
"purpose with or without fee is hereby granted, provided that the above\n"
"copyright notice and this permission notice appear in all copies.\n"
"\n"
"This software is provided 'as is' and without any warranty, express or\n"
"implied. In no event shall the authors be liable for any damages arising\n"
"from the use of this software.\n"
"\n"
"Report bugs at <" PACKAGE_BUGREPORT ">.\n");
printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
printf("\nCopyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>\n");
printf("\nCopyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>\n\n");
printf("Permission to use, copy, modify, and/or distribute this software for any\n");
printf("purpose with or without fee is hereby granted, provided that the above\n");
printf("copyright notice and this permission notice appear in all copies.\n\n");
printf("This software is provided 'as is' and without any warranty, express or\n");
printf("implied. In no event shall the authors be liable for any damages arising\n");
printf("from the use of this software.\n\n");
printf("Report bugs at <%s>.\n", PACKAGE_BUGREPORT);
exit(EXIT_SUCCESS);
}

View file

@ -1,127 +0,0 @@
/*
* libifupdown/yaml-base.c
* Purpose: YAML implementation -- base
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "libifupdown/yaml-base.h"
void
lif_yaml_document_init(struct lif_yaml_node *doc, const char *name)
{
memset(doc, '\0', sizeof *doc);
doc->value_type = LIF_YAML_OBJECT;
if (name != NULL)
doc->name = strdup(name);
}
struct lif_yaml_node *
lif_yaml_document_new(const char *name)
{
struct lif_yaml_node *doc = calloc(1, sizeof *doc);
lif_yaml_document_init(doc, name);
doc->malloced = true;
return doc;
}
struct lif_yaml_node *
lif_yaml_node_new_boolean(const char *name, bool value)
{
struct lif_yaml_node *node = calloc(1, sizeof *node);
node->malloced = true;
node->value_type = LIF_YAML_BOOLEAN;
if (name != NULL)
node->name = strdup(name);
node->value.bool_value = value;
return node;
}
struct lif_yaml_node *
lif_yaml_node_new_string(const char *name, const char *value)
{
struct lif_yaml_node *node = calloc(1, sizeof *node);
node->malloced = true;
node->value_type = LIF_YAML_STRING;
if (name != NULL)
node->name = strdup(name);
if (value != NULL)
node->value.str_value = strdup(value);
return node;
}
struct lif_yaml_node *
lif_yaml_node_new_object(const char *name)
{
struct lif_yaml_node *node = calloc(1, sizeof *node);
node->malloced = true;
node->value_type = LIF_YAML_OBJECT;
if (name != NULL)
node->name = strdup(name);
return node;
}
struct lif_yaml_node *
lif_yaml_node_new_list(const char *name)
{
struct lif_yaml_node *node = calloc(1, sizeof *node);
node->malloced = true;
node->value_type = LIF_YAML_LIST;
if (name != NULL)
node->name = strdup(name);
return node;
}
void
lif_yaml_node_free(struct lif_yaml_node *node)
{
struct lif_node *iter, *next;
LIF_LIST_FOREACH_SAFE(iter, next, node->children.head)
{
struct lif_yaml_node *iter_node = iter->data;
lif_yaml_node_free(iter_node);
}
free(node->name);
if (node->value_type == LIF_YAML_STRING)
free(node->value.str_value);
if (node->malloced)
free(node);
}
void
lif_yaml_node_append_child(struct lif_yaml_node *parent, struct lif_yaml_node *child)
{
lif_node_insert_tail(&child->node, child, &parent->children);
}

View file

@ -1,52 +0,0 @@
/*
* libifupdown/yaml-base.h
* Purpose: YAML implementation -- base
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef LIBIFUPDOWN_YAML_BASE_H__GUARD
#define LIBIFUPDOWN_YAML_BASE_H__GUARD
#include "libifupdown/libifupdown.h"
/* this is a subset of types supported by our implementation */
enum lif_yaml_value {
LIF_YAML_STRING,
LIF_YAML_LIST,
LIF_YAML_OBJECT,
LIF_YAML_BOOLEAN
};
struct lif_yaml_node {
struct lif_node node;
bool malloced;
char *name;
enum lif_yaml_value value_type;
union {
char *str_value; /* for string nodes */
bool bool_value; /* for boolean nodes */
} value;
struct lif_list children; /* for list and object nodes */
};
extern void lif_yaml_document_init(struct lif_yaml_node *doc, const char *name);
extern struct lif_yaml_node *lif_yaml_document_new(const char *name);
extern struct lif_yaml_node *lif_yaml_node_new_boolean(const char *name, bool value);
extern struct lif_yaml_node *lif_yaml_node_new_string(const char *name, const char *value);
extern struct lif_yaml_node *lif_yaml_node_new_object(const char *name);
extern struct lif_yaml_node *lif_yaml_node_new_list(const char *name);
extern void lif_yaml_node_free(struct lif_yaml_node *node);
extern void lif_yaml_node_append_child(struct lif_yaml_node *parent, struct lif_yaml_node *child);
#endif

View file

@ -1,66 +0,0 @@
/*
* libifupdown/yaml-writer.c
* Purpose: YAML implementation -- writer
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stdio.h>
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "libifupdown/yaml-base.h"
#include "libifupdown/yaml-writer.h"
static const size_t INDENT_WIDTH = 2;
static void
lif_yaml_write_node(const struct lif_yaml_node *node, FILE *f, size_t indent, bool type_annotations)
{
const struct lif_node *iter;
if (node->name != NULL)
fprintf(f, "%*s%s: ", (int) indent, "", node->name);
size_t child_indent = indent + INDENT_WIDTH;
switch (node->value_type)
{
case LIF_YAML_BOOLEAN:
fprintf(f, "%s%s\n", type_annotations ? "!!bool " : "", node->value.bool_value ? "true" : "false");
break;
case LIF_YAML_STRING:
fprintf(f, "%s%s\n", type_annotations ? "!!str " : "", node->value.str_value);
break;
case LIF_YAML_OBJECT:
fprintf(f, "\n");
break;
case LIF_YAML_LIST:
fprintf(f, "\n");
child_indent += INDENT_WIDTH;
break;
}
LIF_LIST_FOREACH(iter, node->children.head)
{
const struct lif_yaml_node *iter_node = iter->data;
if (node->value_type == LIF_YAML_LIST)
fprintf(f, "%*s-\n", (int) (child_indent - INDENT_WIDTH), "");
lif_yaml_write_node(iter_node, f, child_indent, type_annotations);
}
}
void
lif_yaml_write(const struct lif_yaml_node *doc, FILE *f, bool type_annotations)
{
lif_yaml_write_node(doc, f, 0, type_annotations);
}

View file

@ -1,24 +0,0 @@
/*
* libifupdown/yaml-writer.h
* Purpose: YAML implementation -- writer
*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef LIBIFUPDOWN_YAML_WRITER_H__GUARD
#define LIBIFUPDOWN_YAML_WRITER_H__GUARD
#include "libifupdown/libifupdown.h"
#include "libifupdown/yaml-base.h"
extern void lif_yaml_write(const struct lif_yaml_node *doc, FILE *f, bool type_annotations);
#endif

View file

@ -1,10 +0,0 @@
iface eth0
use dhcp
hostname foo
iface eth1
use dhcp
iface eth2
use dhcp
dhcp-hostname bar

View file

@ -35,15 +35,10 @@ tests_init \
vlan_guessed_learned_dependency \
vlan_complex_learned_dependency \
wireguard \
allow_undefined_positive \
allow_undefined_negative \
default_netmask_v4 \
default_netmask_v6 \
stanza_merging_with_cidr \
stanza_merging_without_cidr \
dhcp_hostname_rewrite \
dhcp_hostname_inference \
dhcp_hostname_replacement
stanza_merging_without_cidr
noargs_body() {
atf_check -s exit:1 -e ignore ifquery -S/dev/null
@ -236,20 +231,6 @@ wireguard_body() {
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/wireguard.interfaces wg0
}
allow_undefined_positive_body() {
atf_check -s exit:0 \
-o ignore \
-e ignore \
ifquery -U -i /dev/null -p address foo
}
allow_undefined_negative_body() {
atf_check -s exit:1 \
-o ignore \
-e ignore \
ifquery -i /dev/null -p address foo
}
default_netmask_v4_body() {
atf_check -s exit:0 \
-o match:"203.0.113.2/24" \
@ -275,22 +256,3 @@ stanza_merging_without_cidr_body() {
-o match:"203.0.113.2/24" \
ifquery -i $FIXTURES/stanza-merging.interfaces -p address without-cidr
}
dhcp_hostname_rewrite_body() {
atf_check -s exit:0 \
-o match:"dhcp-hostname foo" \
ifquery -i $FIXTURES/dhcp-hostname-rewrite.interfaces -P eth0
}
dhcp_hostname_inference_body() {
hostname=$(uname -n)
atf_check -s exit:0 \
-o match:"dhcp-hostname $hostname" \
ifquery -i $FIXTURES/dhcp-hostname-rewrite.interfaces -P eth1
}
dhcp_hostname_replacement_body() {
atf_check -s exit:0 \
-o match:"dhcp-hostname bar" \
ifquery -i $FIXTURES/dhcp-hostname-rewrite.interfaces -P eth2
}

View file

@ -2,17 +2,14 @@ syntax(2)
test_suite('ifupdown-ng')
atf_test_program{name='bond_test'}
atf_test_program{name='dhcp_test'}
atf_test_program{name='ethtool_test'}
atf_test_program{name='forward_test'}
atf_test_program{name='gre_test'}
atf_test_program{name='ipv6-ra_test'}
atf_test_program{name='link_test'}
atf_test_program{name='mpls_test'}
atf_test_program{name='ppp_test'}
atf_test_program{name='ipv6-ra_test'}
atf_test_program{name='dhcp_test'}
atf_test_program{name='static_test'}
atf_test_program{name='tunnel_test'}
atf_test_program{name='vrf_test'}
atf_test_program{name='vxlan_test'}
atf_test_program{name='ppp_test'}
atf_test_program{name='tunnel_test'}
atf_test_program{name='gre_test'}
atf_test_program{name='wireguard_test'}
atf_test_program{name='ethtool_test'}
atf_test_program{name='vxlan_test'}

View file

@ -1,30 +0,0 @@
#!/usr/bin/env atf-sh
. $(atf_get_srcdir)/../test_env.sh
EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/bond"
tests_init \
create_lacp_basic \
create_lacp_real
create_lacp_basic_body() {
export IFACE=bond0 PHASE=create MOCK=echo IF_BOND_MODE=802.3ad IF_BOND_MEMBERS="eth0 eth1"
atf_check -s exit:0 \
-o match:'ip link add bond0 type bond mode 802.3ad' \
-o match:'ip link set eth0 down' \
-o match:'ip link set master bond0 eth0' \
-o match:'ip link set eth0 up' \
-o match:'ip link set master bond0 eth1' \
${EXECUTOR}
}
create_lacp_real_body() {
export IFACE=bond0 PHASE=create MOCK=echo IF_BOND_MODE=802.3ad IF_BOND_MEMBERS="eth0 eth1" \
IF_BOND_MIN_LINKS="1" IF_BOND_XMIT_HASH_POLICY="layer3+4"
atf_check -s exit:0 \
-o match:'ip link add bond0 type bond' \
-o match:'mode 802.3ad' \
-o match:'min_links 1' \
-o match:'xmit_hash_policy layer3\+4' \
${EXECUTOR}
}

View file

@ -48,7 +48,7 @@ udhcpc_opts_up_subshell_body() {
}
hostname_subshell_body() {
export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc IF_DHCP_HOSTNAME="\$(echo test)"
export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc IF_HOSTNAME="\$(echo test)"
atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0 -x hostname:test' \
${EXECUTOR}
}

View file

@ -1,90 +0,0 @@
#!/usr/bin/env atf-sh
. $(atf_get_srcdir)/../test_env.sh
EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/forward"
tests_init \
up_forward_v4 \
up_forward_v6 \
up_forward_v4_mc \
up_forward_v6_mc
up_forward_v4_body() {
export IF_FORWARD_IPV4= IF_FORWARD_IPV6= IF_FORWARD_IPV4_MC= IF_FORWARD_IPV6_MC=
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4=1
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4=yes
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4=0
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv4/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4=no
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv4/conf/eth0/forwarding' \
${EXECUTOR}
}
up_forward_v6_body() {
export IF_FORWARD_IPV4= IF_FORWARD_IPV6= IF_FORWARD_IPV4_MC= IF_FORWARD_IPV6_MC=
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6=1
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv6/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6=yes
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv6/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6=0
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv6/conf/eth0/forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6=no
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv6/conf/eth0/forwarding' \
${EXECUTOR}
}
up_forward_v4_mc_body() {
export IF_FORWARD_IPV4= IF_FORWARD_IPV6= IF_FORWARD_IPV4_MC= IF_FORWARD_IPV6_MC=
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4_MC=1
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv4/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4_MC=yes
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv4/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4_MC=0
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv4/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV4_MC=no
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv4/conf/eth0/mc_forwarding' \
${EXECUTOR}
}
up_forward_v6_mc_body() {
export IF_FORWARD_IPV4= IF_FORWARD_IPV6= IF_FORWARD_IPV4_MC= IF_FORWARD_IPV6_MC=
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6_MC=1
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv6/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6_MC=yes
atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv6/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6_MC=0
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv6/conf/eth0/mc_forwarding' \
${EXECUTOR}
export IFACE=eth0 PHASE=up MOCK=echo IF_FORWARD_IPV6_MC=no
atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv6/conf/eth0/mc_forwarding' \
${EXECUTOR}
}

View file

@ -1,23 +0,0 @@
#!/usr/bin/env atf-sh
. $(atf_get_srcdir)/../test_env.sh
EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/mpls"
tests_init \
mpls_enable \
mpls_disable
mpls_enable_body() {
export MOCK=echo IFACE=vlan2342 PHASE=pre-up IF_MPLS_ENABLE=yes
atf_check -s exit:0 \
-o match:"modprobe mpls_iptunnel" \
-o match:"echo 1 > /proc/sys/net/mpls/conf/vlan2342/input" \
${EXECUTOR}
}
mpls_disable_body() {
export MOCK=echo IFACE=vlan2342 PHASE=pre-up IF_MPLS_ENABLE=no
atf_check -s exit:0 \
-o match:"echo 0 > /proc/sys/net/mpls/conf/vlan2342/input" \
${EXECUTOR}
}

View file

@ -8,7 +8,9 @@ tests_init \
up_ptp \
down \
vrf_up \
metric_up
vrf_down \
metric_up \
metric_down
up_body() {
export IFACE=eth0 PHASE=up MOCK=echo IF_ADDRESSES="203.0.113.2/24 2001:db8:1000:2::2/64" \
@ -36,7 +38,10 @@ down_body() {
export IFACE=eth0 PHASE=down MOCK=echo IF_ADDRESSES="203.0.113.2/24 2001:db8:1000:2::2/64" \
IF_GATEWAYS="203.0.113.1 2001:db8:1000:2::1"
atf_check -s exit:0 \
-o match:'addr flush dev eth0' \
-o match:'addr del 203.0.113.2/24 dev eth0' \
-o match:'addr del 2001:db8:1000:2::2/64 dev eth0' \
-o match:'route del default via 203.0.113.1 metric 1 dev eth0' \
-o match:'route del default via 2001:db8:1000:2::1 metric 1 dev eth0' \
${EXECUTOR}
}
@ -47,9 +52,23 @@ vrf_up_body() {
${EXECUTOR}
}
vrf_down_body() {
export IFACE=vrf-red PHASE=down MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1
atf_check -s exit:0 \
-o match:'route del default via 203.0.113.2 table 1' \
${EXECUTOR}
}
metric_up_body() {
export IFACE=vrf-red PHASE=up MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1 IF_METRIC=20
atf_check -s exit:0 \
-o match:'route add default via 203.0.113.2 table 1 metric 20' \
${EXECUTOR}
}
metric_down_body() {
export IFACE=vrf-red PHASE=down MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1 IF_METRIC=20
atf_check -s exit:0 \
-o match:'route del default via 203.0.113.2 table 1 metric 20' \
${EXECUTOR}
}

View file

@ -5,10 +5,7 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/tunnel"
tests_init \
tunnel_bringup \
tunnel_teardown \
gretap_up \
gretap_down \
ip6gretap_up
tunnel_teardown
tunnel_bringup_body() {
export MOCK=echo IFACE=tun0 PHASE=create IF_TUNNEL_MODE=gre \
@ -16,7 +13,7 @@ tunnel_bringup_body() {
IF_TUNNEL_TTL=255
atf_check -s exit:0 \
-o match:"ip -4 tunnel add tun0" \
-o match:"mode gre" \
-o match:"mode 'gre'" \
-o match:"ttl '255'" \
-o match:"local '1.2.3.4'" \
-o match:"remote '5.6.7.8'" \
@ -31,35 +28,3 @@ tunnel_teardown_body() {
-o match:"ip -4 tunnel del tun0" \
${EXECUTOR}
}
gretap_up_body() {
export MOCK=echo IFACE=foo PHASE=create IF_TUNNEL_MODE=gretap \
IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8
atf_check -s exit:0 \
-o match:"ip -4 link add foo" \
-o match:"type gretap" \
-o match:"local '1.2.3.4'" \
-o match:"remote '5.6.7.8'" \
${EXECUTOR}
}
gretap_down_body() {
export MOCK=echo IFACE=foo PHASE=destroy IF_TUNNEL_MODE=gretap \
IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8
atf_check -s exit:0 \
-o match:"ip -4 link del foo" \
${EXECUTOR}
}
ip6gretap_up_body() {
export MOCK=echo IFACE=foo PHASE=create IF_TUNNEL_MODE=ip6gretap \
IF_TUNNEL_LOCAL=2001:db8::aaaa IF_TUNNEL_REMOTE=2001:db8::eeee
atf_check -s exit:0 \
-o match:"ip -6 link add foo" \
-o match:"type gretap" \
-o match:"local '2001:db8::aaaa'" \
-o match:"remote '2001:db8::eeee'" \
${EXECUTOR}
}

View file

@ -5,8 +5,7 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/vxlan"
tests_init \
create_simple \
create_ucast_ptp \
create_ucast_ptmp \
create_ucast \
create_mcast \
create_physdev \
create_dstport \
@ -19,24 +18,14 @@ create_simple_body() {
${EXECUTOR}
}
create_ucast_ptp_body() {
export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PEER_IPS=192.2.0.42
create_ucast_body() {
export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_IP=192.2.0.42
atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 remote 192.2.0.42' \
${EXECUTOR}
}
create_ucast_ptmp_body() {
export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PEER_IPS="10.0.0.1 10.0.0.2 10.0.0.3"
atf_check -s exit:0 \
-o match:'ip link add vx_foo type vxlan id 2342 dstport 4789' \
-o match:'bridge fdb append 00:00:00:00:00:00 dev vx_foo dst 10.0.0.1 self permanent' \
-o match:'bridge fdb append 00:00:00:00:00:00 dev vx_foo dst 10.0.0.2 self permanent' \
-o match:'bridge fdb append 00:00:00:00:00:00 dev vx_foo dst 10.0.0.3 self permanent' \
${EXECUTOR}
}
create_mcast_body() {
export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PEER_GROUP=225.0.8.15
export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_GROUP=225.0.8.15
atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 group 225.0.8.15' \
${EXECUTOR}
}