diff --git a/COPYING b/COPYING index 537f879..7240951 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,5 @@ -Copyright (c) 2020 Ariadne Conill +Copyright (c) 2020-2021 Ariadne Conill +Copyright (c) 2020-2021 Maximilian Wilhelm Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/Makefile b/Makefile index f2cf08f..9fb6199 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.11.0 +PACKAGE_VERSION := 0.11.3 PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new @@ -14,7 +14,8 @@ CONFIG_FILE := /etc/network/ifupdown-ng.conf EXECUTOR_PATH := /usr/libexec/ifupdown-ng CFLAGS ?= -ggdb3 -Os -CFLAGS += -Wall -Wextra +CFLAGS += -Wall -Wextra -Werror +CFLAGS += -Wmissing-declarations -Wmissing-prototypes -Wcast-align -Wpointer-arith -Wreturn-type CFLAGS += ${LIBBSD_CFLAGS} CPPFLAGS = -I. CPPFLAGS += -DINTERFACES_FILE=\"${INTERFACES_FILE}\" @@ -119,6 +120,8 @@ EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} EXECUTOR_SCRIPTS_STUB ?= +EXECUTOR_SCRIPTS_NATIVE ?= + TARGET_LIBS = ${LIBIFUPDOWN_LIB} LIBS += ${TARGET_LIBS} ${LIBBSD_LIBS} @@ -153,6 +156,9 @@ 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: @@ -167,6 +173,7 @@ MANPAGES_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 \ diff --git a/README.md b/README.md index a3e155c..4b03d23 100644 --- a/README.md +++ b/README.md @@ -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`, not packaged for Debian). +To run the tests, do `make check`. Running the checks requires `kyua` (`apk add kyua` / `apt install kyua`). 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.as7007.net #ifupdown-ng +Discuss ifupdown-ng on IRC: irc.oftc.net #ifupdown-ng diff --git a/cmd/ifctrstat-linux.c b/cmd/ifctrstat-linux.c index e7dcfa3..8203fc4 100644 --- a/cmd/ifctrstat-linux.c +++ b/cmd/ifctrstat-linux.c @@ -17,7 +17,8 @@ #include #include #include -#include "multicall.h" +#include "cmd/multicall.h" +#include "cmd/ifctrstat-linux.h" struct counter_desc { const char *name; @@ -41,7 +42,7 @@ counter_compare(const void *key, const void *candidate) return strcasecmp((const char *)key, ((struct counter_desc *)candidate)->name); } -char * +const char * read_counter(const char *interface, const char *counter) { FILE *fp; diff --git a/cmd/ifctrstat-linux.h b/cmd/ifctrstat-linux.h new file mode 100644 index 0000000..3510013 --- /dev/null +++ b/cmd/ifctrstat-linux.h @@ -0,0 +1,22 @@ +/* + * cmd/ifctrstat-linux.c + * Purpose: Implement ifctrstat system-specific routines for Linux + * + * Copyright (c) 2021 Maximilian Wilhelm + * + * 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 diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 89aff80..8b0482f 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -20,12 +20,11 @@ #include #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 @@ -96,7 +95,7 @@ ifctrstat_set_nolabel(const char *opt_arg) show_label = false; } -int +static int ifctrstat_main(int argc, char *argv[]) { if (optind >= argc) diff --git a/cmd/ifparse.c b/cmd/ifparse.c index d39379b..e8c0535 100644 --- a/cmd/ifparse.c +++ b/cmd/ifparse.c @@ -131,7 +131,7 @@ pp_impl_cmp(const void *a, const void *b) return strcmp(key, impl->name); } -int +static int ifparse_main(int argc, char *argv[]) { struct lif_dict state = {}; diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 5931db9..86a3f64 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -22,7 +22,7 @@ #include "cmd/multicall.h" #include "cmd/pretty-print-iface.h" -void +static 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 +57,7 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st } } -void +static void print_interface_property(struct lif_interface *iface, const char *property) { struct lif_node *iter; @@ -83,7 +83,7 @@ print_interface_property(struct lif_interface *iface, const char *property) } } -void +static void list_interfaces(struct lif_dict *collection, struct match_options *opts) { struct lif_node *iter; @@ -126,7 +126,7 @@ 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; -void +static void list_state(struct lif_dict *state, struct match_options *opts) { struct lif_node *iter; @@ -217,7 +217,7 @@ static struct if_option_group local_option_group = { .group = local_options }; -int +static int ifquery_main(int argc, char *argv[]) { struct lif_dict state = {}; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 1d39cd5..7ac3c88 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -27,7 +27,7 @@ static bool up; -bool +static bool is_ifdown() { if (strstr(argv0, "ifdown") != NULL) @@ -36,7 +36,7 @@ is_ifdown() return false; } -int +static int acquire_state_lock(const char *state_path, const char *lifname) { if (exec_opts.mock || exec_opts.no_lock) @@ -94,7 +94,7 @@ acquire_state_lock(const char *state_path, const char *lifname) return fd; } -bool +static 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; } -bool +static 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; } -bool +static 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; } -int +static 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; } -int +static int ifupdown_main(int argc, char *argv[]) { up = !is_ifdown(); diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c index f56228c..5350e62 100644 --- a/cmd/multicall-exec-options.c +++ b/cmd/multicall-exec-options.c @@ -21,10 +21,13 @@ #include #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 + .state_file = STATE_FILE, + .timeout = DEFAULT_TIMEOUT, }; static void @@ -74,6 +77,14 @@ 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}, @@ -82,6 +93,7 @@ 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 = { diff --git a/cmd/multicall-match-options.c b/cmd/multicall-match-options.c index 4a03f3a..8d85d8a 100644 --- a/cmd/multicall-match-options.c +++ b/cmd/multicall-match-options.c @@ -39,7 +39,7 @@ set_include_pattern(const char *opt_arg) static void set_exclude_pattern(const char *opt_arg) { - match_opts.include_pattern = opt_arg; + match_opts.exclude_pattern = opt_arg; } static struct if_option match_options[] = { diff --git a/cmd/multicall.c b/cmd/multicall.c index 653181a..7c3c849 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -62,7 +62,7 @@ struct if_applet *applet_table[] = { &ifupdown_applet, }; -int +static int applet_cmp(const void *a, const void *b) { const char *key = a; @@ -101,7 +101,7 @@ main(int argc, char *argv[]) return self_applet->main(argc, argv); } -int +static int multicall_main(int argc, char *argv[]) { if (argc < 2) diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md index 0420e79..d3e7862 100644 --- a/doc/ADMIN-GUIDE.md +++ b/doc/ADMIN-GUIDE.md @@ -272,4 +272,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.as7007.net/#ifupdown-ng). +[ifupdown-ng IRC channel](irc://irc.oftc.net/#ifupdown-ng). diff --git a/doc/ifdown.scd b/doc/ifdown.scd index 0215954..41f3b02 100644 --- a/doc/ifdown.scd +++ b/doc/ifdown.scd @@ -45,6 +45,10 @@ 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. diff --git a/doc/ifparse.scd b/doc/ifparse.scd index 7634b71..ff7b742 100644 --- a/doc/ifparse.scd +++ b/doc/ifparse.scd @@ -43,6 +43,10 @@ stanzas between different formats. *-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. diff --git a/doc/ifquery.scd b/doc/ifquery.scd index 83c8480..b721135 100644 --- a/doc/ifquery.scd +++ b/doc/ifquery.scd @@ -62,6 +62,10 @@ configuration file to the current format. *-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. diff --git a/doc/ifup.scd b/doc/ifup.scd index 0af9150..82978f2 100644 --- a/doc/ifup.scd +++ b/doc/ifup.scd @@ -48,6 +48,10 @@ 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. diff --git a/doc/interfaces-tunnel.scd b/doc/interfaces-tunnel.scd new file mode 100644 index 0000000..b924e93 --- /dev/null +++ b/doc/interfaces-tunnel.scd @@ -0,0 +1,161 @@ +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 diff --git a/doc/interfaces-vxlan.scd b/doc/interfaces-vxlan.scd index f7f7783..a6dd8b6 100644 --- a/doc/interfaces-vxlan.scd +++ b/doc/interfaces-vxlan.scd @@ -32,26 +32,33 @@ other options are optional. *vxlan-physdev* _interface_ Specifies the physical ("underlay") device to use for tunnel - endpoint communication. + endpoint communication. This is required for setups using + multicast. *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-remote-ip* _address_ - Specifies the unicast destination IP address to use in outgoing +*vxlan-peer-ips* _list of IP addresses_ + Specifies the unicast destination IP address(es) to use in outgoing packets when the destination link layer address is not known in - 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. + 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. -*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-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-learning* _on/off_ Specifies if unknown source link layer addresses and IP addresses @@ -79,22 +86,46 @@ 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. +carry the encapsulated packets of the two VTEPs above. -A VTEP with one peer (point-to-point configuration): +A VTEP with one peer (unicast point-to-point configuration): ``` auto vx_ptp1 iface vx_ptp1 vxlan-id 2342 vxlan-local-ip 192.0.2.42 - vxlan-remote-ip 198.51.100.23 + vxlan-peer-ips 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 diff --git a/doc/interfaces-wireguard.scd b/doc/interfaces-wireguard.scd index 900b900..79f4285 100644 --- a/doc/interfaces-wireguard.scd +++ b/doc/interfaces-wireguard.scd @@ -18,6 +18,15 @@ 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 diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 24c3365..f4a6473 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -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 here. +well, but that syntax is not discussed in detail here. # FILE SYNTAX @@ -24,6 +24,8 @@ 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: ``` @@ -64,11 +66,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. - -*gateway* _address_ - Associates an IPv4 or IPv6 address with the parent interface - for use as a default route (gateway). + 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. *netmask* _netmask_ Associates a fallback netmask with the parent interface for @@ -83,6 +85,11 @@ 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. @@ -171,7 +178,8 @@ most common executors are: *tunnel* The interface is a tunnel. Configuration of tunnels - requires the *tunnel* package to be installed. + requires the *tunnel* package to be installed on Alpine + Linux. *vrf* The interface is a VRF. Configuration of VRFs requires @@ -242,6 +250,7 @@ iface eth0 *interfaces-forward*(5) *interfaces-mpls*(5) *interfaces-ppp*(5) +*interfaces-tunnel*(5) *interfaces-vrf*(5) *interfaces-vxlan*(5) *interfaces-wifi*(5) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index fb10d5e..36af638 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -26,34 +26,31 @@ configure_addresses() { PEER="" fi - 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 + ${MOCK} ip "${addrfam}" addr add "${addr}" ${PEER} dev "${IFACE}" done } configure_gateways() { for gw in ${IF_GATEWAYS}; do addrfam=$(addr_family ${gw}) - ${MOCK} ip "${addrfam}" route "${1}" default via "${gw}" ${VRF_TABLE} ${METRIC} dev "${IFACE}" + ${MOCK} ip "${addrfam}" route add 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) - configure_gateways del - configure_addresses del + flush ;; *) exit 0 ;; esac diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel index 2eec499..b69ac8c 100755 --- a/executor-scripts/linux/tunnel +++ b/executor-scripts/linux/tunnel @@ -2,20 +2,27 @@ # 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) +# Copyright (c) 2021 Maximilian Wilhelm (make sure mode/type is 1st parameter, add more options) -[ -z "$IF_TUNNEL_LOCAL" ] && exit 1 +[ -z "$IF_TUNNEL_LOCAL" -a -z "$IF_TUNNEL_LOCAL_DEV" ] && 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" +FAMILY="4" case "$IF_TUNNEL_MODE" in vti6|ipip6|ip6*) - FAMILY="-6" + FAMILY="6" ;; esac @@ -41,6 +48,58 @@ case "${IF_TUNNEL_MODE}" in esac +# If 'tunnel-local ' was not given but 'tunnel-local-dev ' 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/ @@ -58,12 +117,12 @@ PARAMS=$(set | sed -E ' case "$PHASE" in create) - ${MOCK} eval ip $FAMILY $OBJECT add $IFACE $TYPE_KW $TUNNEL_MODE $PARAMS + ${MOCK} eval ip -$FAMILY $OBJECT add $IFACE $TYPE_KW $TUNNEL_MODE $PARAMS $MORE_PARAMS ;; destroy) - ${MOCK} ip $FAMILY $OBJECT del $IFACE + ${MOCK} ip -$FAMILY $OBJECT del $IFACE ;; depend) - echo "$IF_TUNNEL_DEV" + echo "${IF_TUNNEL_DEV}" "${IF_TUNNEL_LOCAL_DEV}" ;; esac diff --git a/executor-scripts/linux/vxlan b/executor-scripts/linux/vxlan index 2a74653..2910742 100755 --- a/executor-scripts/linux/vxlan +++ b/executor-scripts/linux/vxlan @@ -10,8 +10,8 @@ # 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_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_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_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) @@ -36,17 +36,27 @@ case "$PHASE" in fi # Input validation - 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 + 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 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}" - [ "${IF_VXLAN_REMOTE_IP}" ] && ARGS="${ARGS} remote ${IF_VXLAN_REMOTE_IP}" - [ "${IF_VXLAN_REMOTE_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_REMOTE_GROUP}" + [ "${UCAST_MODE}" = "ptp" ] && ARGS="${ARGS} remote ${IF_VXLAN_PEER_IPS}" + [ "${IF_VXLAN_PEER_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_PEER_GROUP}" [ "${IF_VXLAN_AGEING}" ] && ARGS="${ARGS} ageing ${IF_VXLAN_AGEING}" # Linux uses non-standard default port - WTF? @@ -67,6 +77,13 @@ 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) diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi index 93243f1..6524aa8 100755 --- a/executor-scripts/linux/wifi +++ b/executor-scripts/linux/wifi @@ -79,7 +79,7 @@ stop_wpa_supplicant() { [ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH" # If there is no PIDFILE, there is nothing we can do - [ ! -d "$PIDFILE" ] && return + [ ! -f "$PIDFILE" ] && return pid=$(cat "$PIDFILE") rm -- "$PIDFILE" diff --git a/libifupdown/compat.c b/libifupdown/compat.c index b6e5547..1c8f233 100644 --- a/libifupdown/compat.c +++ b/libifupdown/compat.c @@ -16,6 +16,7 @@ #include #include #include +#include "libifupdown/compat.h" #include "libifupdown/config-file.h" #include "libifupdown/dict.h" #include "libifupdown/interface.h" @@ -102,7 +103,7 @@ compat_ifupdown2_bridge_ports_inherit_vlans(struct lif_dict *collection) return true; } -extern bool +bool lif_compat_apply(struct lif_dict *collection) { if (lif_config.compat_ifupdown2_bridge_ports_inherit_vlans && diff --git a/libifupdown/compat.h b/libifupdown/compat.h index ebb668b..2bdfef2 100644 --- a/libifupdown/compat.h +++ b/libifupdown/compat.h @@ -17,6 +17,7 @@ #define LIBIFUPDOWN__COMPAT_H #include "libifupdown/config-file.h" +#include "libifupdown/dict.h" extern bool lif_compat_apply (struct lif_dict *collection); diff --git a/libifupdown/execute.c b/libifupdown/execute.c index 69af1c0..538e6e6 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -30,6 +30,86 @@ #define SHELL "/bin/sh" +#if defined(__linux__) +# include +#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, ...) { @@ -55,10 +135,7 @@ lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const c return false; } - int status; - waitpid(child, &status, 0); - - return WIFEXITED(status) && WEXITSTATUS(status) == 0; + return lif_process_monitor(cmdbuf, child, opts->timeout); } bool @@ -118,11 +195,8 @@ lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size return false; } - int status; no_result: - waitpid(child, &status, 0); - - return WIFEXITED(status) && WEXITSTATUS(status) == 0; + return lif_process_monitor(cmdbuf, child, opts->timeout); } bool diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 5a871a9..905cd84 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -27,6 +27,7 @@ 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, ...); diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 79f6ab9..d0fa233 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -71,7 +71,7 @@ static const struct remap_token tokens[] = { {"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-leastime"}, /* 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 */ @@ -100,8 +100,10 @@ static const struct remap_token tokens[] = { {"vendor", "dhcp-vendor"}, /* legacy ifupdown */ {"vrf", "vrf-member"}, /* ifupdown2 */ {"vxlan-local-tunnelip", "vxlan-local-ip"}, /* ifupdown2 */ - {"vxlan-remoteip", "vxlan-remote-ip"}, /* ifupdown2 */ - {"vxlan-svcnodeip", "vxlan-remote-group"}, /* 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 */ }; static int @@ -250,8 +252,8 @@ handle_hostname(struct lif_interface_file_parse_state *state, char *token, char return true; } - lif_dict_delete(&state->cur_iface->vars, token); - lif_dict_add(&state->cur_iface->vars, token, strdup(hostname)); + lif_dict_delete(&state->cur_iface->vars, "dhcp-hostname"); + lif_dict_add(&state->cur_iface->vars, "dhcp-hostname", strdup(hostname)); return true; } @@ -447,6 +449,7 @@ 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}, diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 0294383..46462fd 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -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, "hostname", strdup(un.nodename)); + lif_dict_add(&interface->vars, "dhcp-hostname", strdup(un.nodename)); } void diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index f0bd2b3..6bc9ffe 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -94,7 +94,8 @@ 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 + .interfaces_file = opts->interfaces_file, + .timeout = opts->timeout, }; if (strcmp(entry->key, "use")) @@ -114,7 +115,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const return true; } -bool +static bool append_to_buffer(char **buffer, size_t *buffer_len, char **end, const char *value) { size_t value_len = strlen (value); diff --git a/tests/fixtures/dhcp-hostname-rewrite.interfaces b/tests/fixtures/dhcp-hostname-rewrite.interfaces new file mode 100644 index 0000000..0aa4f71 --- /dev/null +++ b/tests/fixtures/dhcp-hostname-rewrite.interfaces @@ -0,0 +1,10 @@ +iface eth0 + use dhcp + hostname foo + +iface eth1 + use dhcp + +iface eth2 + use dhcp + dhcp-hostname bar \ No newline at end of file diff --git a/tests/ifquery_test b/tests/ifquery_test index 3fac522..955bb6c 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -40,7 +40,10 @@ tests_init \ default_netmask_v4 \ default_netmask_v6 \ stanza_merging_with_cidr \ - stanza_merging_without_cidr + stanza_merging_without_cidr \ + dhcp_hostname_rewrite \ + dhcp_hostname_inference \ + dhcp_hostname_replacement noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -272,3 +275,22 @@ 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 +} \ No newline at end of file diff --git a/tests/linux/static_test b/tests/linux/static_test index 80afba0..f3912e5 100755 --- a/tests/linux/static_test +++ b/tests/linux/static_test @@ -8,9 +8,7 @@ tests_init \ up_ptp \ down \ vrf_up \ - vrf_down \ - metric_up \ - metric_down + metric_up up_body() { export IFACE=eth0 PHASE=up MOCK=echo IF_ADDRESSES="203.0.113.2/24 2001:db8:1000:2::2/64" \ @@ -38,10 +36,7 @@ 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 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' \ + -o match:'addr flush dev eth0' \ ${EXECUTOR} } @@ -52,23 +47,9 @@ 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} -} diff --git a/tests/linux/vxlan_test b/tests/linux/vxlan_test index 011a856..f667c60 100755 --- a/tests/linux/vxlan_test +++ b/tests/linux/vxlan_test @@ -5,7 +5,8 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/vxlan" tests_init \ create_simple \ - create_ucast \ + create_ucast_ptp \ + create_ucast_ptmp \ create_mcast \ create_physdev \ create_dstport \ @@ -18,14 +19,24 @@ create_simple_body() { ${EXECUTOR} } -create_ucast_body() { - export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_IP=192.2.0.42 +create_ucast_ptp_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PEER_IPS=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_REMOTE_GROUP=225.0.8.15 + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PEER_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} }