Merge pull request #100 from BarbarossaTM/chore/addresses-and-gateways-env

Expose all adresses and gateways as environment variables
This commit is contained in:
Ariadne Conill 2020-10-05 23:46:15 -04:00 committed by GitHub
commit 5b6cb5a128
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 92 additions and 28 deletions

View file

@ -2,12 +2,13 @@
set -e set -e
[ -z "$VERBOSE" ] || set -x [ -z "${VERBOSE}" ] || set -x
[ -z "${IF_METRIC}" ] && IF_METRIC="1"
[ -n "${IF_VRF_TABLE}" ] && VRF_TABLE="table ${IF_VRF_TABLE}"
[ -n "${IF_VRF_MEMBER}" ] && VRF_TABLE="vrf ${IF_VRF_MEMBER}"
[ -n "${IF_METRIC}" ] && METRIC="metric ${IF_METRIC}"
[ -z "$IF_METRIC" ] && IF_METRIC="1"
[ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE"
[ -n "$IF_VRF_MEMBER" ] && VRF_TABLE="vrf $IF_VRF_MEMBER"
[ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC"
addr_family() { addr_family() {
if [ "$1" != "${1#*[0-9].[0-9]}" ]; then if [ "$1" != "${1#*[0-9].[0-9]}" ]; then
@ -20,22 +21,31 @@ addr_family() {
} }
configure_addresses() { configure_addresses() {
for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do for addr in ${IF_ADDRESSES}; do
addrfam=$(addr_family $i) addrfam=$(addr_family ${addr})
if [ "${IF_POINT_TO_POINT}" -a "${addrfam}" = "-4" ]; then if [ "${IF_POINT_TO_POINT}" -a "${addrfam}" = "-4" ]; then
PEER="peer ${IF_POINT_TO_POINT}" PEER="peer ${IF_POINT_TO_POINT}"
else else
PEER="" PEER=""
fi fi
${MOCK} ip $addrfam addr $1 $i $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 done
} }
configure_gateways() { configure_gateways() {
for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do for gw in ${IF_GATEWAYS}; do
addrfam=$(addr_family $i) addrfam=$(addr_family ${gw})
${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE $METRIC dev $IFACE ${MOCK} ip "${addrfam}" route "${1}" default via "${gw}" ${VRF_TABLE} ${METRIC} dev "${IFACE}"
done done
} }

View file

@ -28,6 +28,8 @@
#include "libifupdown/tokenize.h" #include "libifupdown/tokenize.h"
#include "libifupdown/config-file.h" #include "libifupdown/config-file.h"
#define BUFFER_LEN 4096
static bool static bool
handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, const char *phase) handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, const char *phase)
{ {
@ -112,6 +114,34 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const
return true; return true;
} }
bool
append_to_buffer(char **buffer, size_t *buffer_len, char **end, const char *value)
{
size_t value_len = strlen (value);
/* Make sure there is enough room to add the value to the buffer */
if (*buffer_len < strlen (*buffer) + value_len + 2)
{
*buffer = realloc (*buffer, *buffer_len * 2);
if (*buffer == NULL)
/* XXX Here be dragons */
return false;
*buffer_len = *buffer_len * 2;
}
/* Append value to buffer */
size_t printed = snprintf (*end, value_len + 2, "%s ", value);
if (printed < value_len + 1)
/* Here be dragons */
return false;
/* Move end pointer to last printed byte */
*end += printed;
return true;
}
static void static void
build_environment(char **envp[], const struct lif_execute_opts *opts, const struct lif_interface *iface, const char *lifname, const char *phase, const char *mode) build_environment(char **envp[], const struct lif_execute_opts *opts, const struct lif_interface *iface, const char *lifname, const char *phase, const char *mode)
{ {
@ -132,21 +162,35 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, const stru
const struct lif_node *iter; const struct lif_node *iter;
bool did_address = false, did_gateway = false; bool did_address = false, did_gateway = false;
/* Allocate a buffer for all possible addresses, if any */
char *addresses = calloc (BUFFER_LEN, 1);
size_t addresses_size = BUFFER_LEN;
char *addresses_end = addresses;
/* Allocate a buffer for all possible gateways, if any */
char *gateways = calloc (BUFFER_LEN, 1);
size_t gateways_size = BUFFER_LEN;
char *gateways_end = gateways;
LIF_DICT_FOREACH(iter, &iface->vars) LIF_DICT_FOREACH(iter, &iface->vars)
{ {
const struct lif_dict_entry *entry = iter->data; const struct lif_dict_entry *entry = iter->data;
if (!strcmp(entry->key, "address")) if (!strcmp(entry->key, "address"))
{ {
if (did_address)
continue;
struct lif_address *addr = entry->data; struct lif_address *addr = entry->data;
char addrbuf[4096]; char addrbuf[4096];
if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true))
continue; continue;
/* Append address to buffer */
append_to_buffer(&addresses, &addresses_size, &addresses_end, addrbuf);
/* Only print IF_ADDRESS once */
if (did_address)
continue;
lif_environment_push(envp, "IF_ADDRESS", addrbuf); lif_environment_push(envp, "IF_ADDRESS", addrbuf);
did_address = true; did_address = true;
@ -154,6 +198,9 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, const stru
} }
else if (!strcmp(entry->key, "gateway")) else if (!strcmp(entry->key, "gateway"))
{ {
/* Append address to buffer */
append_to_buffer(&gateways, &gateways_size, &gateways_end, entry->data);
if (did_gateway) if (did_gateway)
continue; continue;
@ -179,6 +226,15 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, const stru
lif_environment_push(envp, envkey, (const char *) entry->data); lif_environment_push(envp, envkey, (const char *) entry->data);
} }
if (addresses != NULL)
lif_environment_push(envp, "IF_ADDRESSES", addresses);
if (gateways != NULL)
lif_environment_push(envp, "IF_GATEWAYS", gateways);
/* Clean up */
free (addresses);
free (gateways);
} }
bool bool

View file

@ -23,7 +23,8 @@ lif_common_version(void)
{ {
printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
printf("\nCopyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>\n\n"); 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("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("purpose with or without fee is hereby granted, provided that the above\n");

View file

@ -2,7 +2,6 @@
. $(atf_get_srcdir)/../test_env.sh . $(atf_get_srcdir)/../test_env.sh
EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static"
FIXTURES="$(atf_get_srcdir)/../fixtures"
tests_init \ tests_init \
up \ up \
@ -14,7 +13,8 @@ tests_init \
metric_down metric_down
up_body() { up_body() {
export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" export IFACE=eth0 PHASE=up 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 \ atf_check -s exit:0 \
-o match:'addr add 203.0.113.2/24 dev eth0' \ -o match:'addr add 203.0.113.2/24 dev eth0' \
-o match:'addr add 2001:db8:1000:2::2/64 dev eth0' \ -o match:'addr add 2001:db8:1000:2::2/64 dev eth0' \
@ -24,8 +24,8 @@ up_body() {
} }
up_ptp_body() { up_ptp_body() {
export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0-ptp.interfaces" \ export IFACE=eth0 PHASE=up MOCK=echo IF_ADDRESSES="203.0.113.2/32 2001:db8:1000:2::2/64" \
IF_POINT_TO_POINT="192.0.2.1" IF_GATEWAYS="192.0.2.1 2001:db8:1000:2::1" IF_POINT_TO_POINT="192.0.2.1"
atf_check -s exit:0 \ atf_check -s exit:0 \
-o match:'addr add 203.0.113.2/32 peer 192.0.2.1 dev eth0' \ -o match:'addr add 203.0.113.2/32 peer 192.0.2.1 dev eth0' \
-o match:'route add default via 192.0.2.1 metric 1 dev eth0' \ -o match:'route add default via 192.0.2.1 metric 1 dev eth0' \
@ -35,7 +35,8 @@ up_ptp_body() {
} }
down_body() { down_body() {
export IFACE=eth0 PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" 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 \ atf_check -s exit:0 \
-o match:'addr del 203.0.113.2/24 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:'addr del 2001:db8:1000:2::2/64 dev eth0' \
@ -45,32 +46,28 @@ down_body() {
} }
vrf_up_body() { vrf_up_body() {
export IFACE=vrf-red PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ export IFACE=vrf-red PHASE=up MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1
IF_VRF_TABLE=1
atf_check -s exit:0 \ atf_check -s exit:0 \
-o match:'route add default via 203.0.113.2 table 1' \ -o match:'route add default via 203.0.113.2 table 1' \
${EXECUTOR} ${EXECUTOR}
} }
vrf_down_body() { vrf_down_body() {
export IFACE=vrf-red PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ export IFACE=vrf-red PHASE=down MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1
IF_VRF_TABLE=1
atf_check -s exit:0 \ atf_check -s exit:0 \
-o match:'route del default via 203.0.113.2 table 1' \ -o match:'route del default via 203.0.113.2 table 1' \
${EXECUTOR} ${EXECUTOR}
} }
metric_up_body() { metric_up_body() {
export IFACE=vrf-red PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ export IFACE=vrf-red PHASE=up MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1 IF_METRIC=20
IF_VRF_TABLE=1 IF_METRIC=20
atf_check -s exit:0 \ atf_check -s exit:0 \
-o match:'route add default via 203.0.113.2 table 1 metric 20' \ -o match:'route add default via 203.0.113.2 table 1 metric 20' \
${EXECUTOR} ${EXECUTOR}
} }
metric_down_body() { metric_down_body() {
export IFACE=vrf-red PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ export IFACE=vrf-red PHASE=down MOCK=echo IF_GATEWAYS=203.0.113.2 IF_VRF_TABLE=1 IF_METRIC=20
IF_VRF_TABLE=1 IF_METRIC=20
atf_check -s exit:0 \ atf_check -s exit:0 \
-o match:'route del default via 203.0.113.2 table 1 metric 20' \ -o match:'route del default via 203.0.113.2 table 1 metric 20' \
${EXECUTOR} ${EXECUTOR}