From 537a56414aa28446440cba4c2f5206be0088faa7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 16:50:31 -0600 Subject: [PATCH 1/9] tokenize: consider = to be equivalent to whitespace --- libifupdown/tokenize.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index 751c2f2..288f9a1 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -23,11 +23,11 @@ lif_next_token(char **buf) { char *out = *buf; - while (*out && isspace(*out)) + while (*out && (isspace(*out) || *out == '=')) out++; char *end = out; - while (*end && !isspace(*end)) + while (*end && !isspace(*end) && *out != '=') end++; *end++ = '\0'; From fafa5ed7f979cdf15f05e4f2edf39eb58bb7a863 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:01:42 -0600 Subject: [PATCH 2/9] libifupdown: add abstract config parser implementation --- Makefile | 3 +- libifupdown/config-parser.c | 84 +++++++++++++++++++++++++++++++++++++ libifupdown/config-parser.h | 32 ++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 libifupdown/config-parser.c create mode 100644 libifupdown/config-parser.h diff --git a/Makefile b/Makefile index 048c960..6d51562 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ LIBIFUPDOWN_SRC = \ libifupdown/state.c \ libifupdown/environment.c \ libifupdown/execute.c \ - libifupdown/lifecycle.c + libifupdown/lifecycle.c \ + libifupdown/config-parser.c LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c new file mode 100644 index 0000000..0e16b70 --- /dev/null +++ b/libifupdown/config-parser.c @@ -0,0 +1,84 @@ +/* + * libifupdown/config-parser.c + * Purpose: config parsing + * + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "libifupdown/config-parser.h" +#include "libifupdown/fgetline.h" +#include "libifupdown/tokenize.h" + +static int +handler_cmp(const void *a, const void *b) +{ + const char *key = a; + const struct lif_config_handler *hdl = b; + + return strcmp(key, hdl->key); +} + +bool +lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler *handlers, size_t handler_count) +{ + char linebuf[4096]; + size_t lineno = 0; + + while (lif_fgetline(linebuf, sizeof linebuf, fd)) + { + char *bufp = linebuf; + char *key = lif_next_token(&bufp); + char *value = lif_next_token(&bufp); + + lineno++; + + if (!*key || !*value) + continue; + + struct lif_config_handler *hdl = bsearch(key, handlers, handler_count, sizeof(*handlers), + handler_cmp); + + if (hdl == NULL) + { + fprintf(stderr, "ifupdown-ng: %s:%zu: warning: unknown config setting %s\n", + filename, lineno, key); + continue; + } + + if (!hdl->handle(key, value, hdl->opaque)) + { + fclose(fd); + return false; + } + } + + fclose(fd); + return true; +} + +bool +lif_config_parse(const char *filename, struct lif_config_handler *handlers, size_t handler_count) +{ + FILE *f = fopen(filename, "r"); + + if (f == NULL) + { + fprintf(stderr, "ifupdown-ng: unable to parse %s: %s\n", filename, strerror(errno)); + return false; + } + + return lif_config_parse_file(f, filename, handlers, handler_count); +} diff --git a/libifupdown/config-parser.h b/libifupdown/config-parser.h new file mode 100644 index 0000000..86c1762 --- /dev/null +++ b/libifupdown/config-parser.h @@ -0,0 +1,32 @@ +/* + * libifupdown/config-parser.h + * Purpose: config parsing + * + * Copyright (c) 2020 Ariadne Conill + * + * 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__CONFIG_PARSER_H +#define LIBIFUPDOWN__CONFIG_PARSER_H + +#include +#include +#include + +struct lif_config_handler { + const char *key; + bool (*handle)(const char *key, const char *value, void *opaque); + void *opaque; +}; + +extern bool lif_config_parse_file(FILE *f, const char *filename, struct lif_config_handler *handlers, size_t handler_count); +extern bool lif_config_parse(const char *filename, struct lif_config_handler *handlers, size_t handler_count); + +#endif From 02d044c391d6e3c257f4658464f63723b9c28fdb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:15:18 -0600 Subject: [PATCH 3/9] libifupdown: add config file loader --- Makefile | 3 +- libifupdown/config-file.c | 61 +++++++++++++++++++++++++++++++++++++++ libifupdown/config-file.h | 29 +++++++++++++++++++ libifupdown/libifupdown.h | 2 ++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 libifupdown/config-file.c create mode 100644 libifupdown/config-file.h diff --git a/Makefile b/Makefile index 6d51562..a6fa3ff 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,8 @@ LIBIFUPDOWN_SRC = \ libifupdown/environment.c \ libifupdown/execute.c \ libifupdown/lifecycle.c \ - libifupdown/config-parser.c + libifupdown/config-parser.c \ + libifupdown/config-file.c LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c new file mode 100644 index 0000000..7f2b299 --- /dev/null +++ b/libifupdown/config-file.c @@ -0,0 +1,61 @@ +/* + * libifupdown/config-file.c + * Purpose: config file loading + * + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include +#include "libifupdown/libifupdown.h" + +struct lif_config_file lif_config = { + .allow_addon_scripts = true, +}; + +static bool +set_bool_value(const char *key, const char *value, void *opaque) +{ + (void) key; + + if (*value == '1' || + *value == 'Y' || *value == 'y' || + *value == 'T' || *value == 't') + *(bool *) opaque = true; + else if (*value == '0' || + *value == 'N' || *value == 'n' || + *value == 'F' || *value == 'f') + *(bool *) opaque = false; + else + return false; + + return true; +} + +static struct lif_config_handler handlers[] = { + {"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts}, +}; + +bool +lif_config_load(const char *filename) +{ + FILE *fd = fopen(filename, "r"); + + if (fd == NULL) + { + fprintf(stderr, "ifupdown-ng: cannot open config %s: %s\n", + filename, strerror(errno)); + return false; + } + + return lif_config_parse_file(fd, filename, handlers, ARRAY_SIZE(handlers)); +} diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h new file mode 100644 index 0000000..a528636 --- /dev/null +++ b/libifupdown/config-file.h @@ -0,0 +1,29 @@ +/* + * libifupdown/config-file.h + * Purpose: config file loading + * + * Copyright (c) 2020 Ariadne Conill + * + * 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__CONFIG_FILE_H +#define LIBIFUPDOWN__CONFIG_FILE_H + +#include + +struct lif_config_file { + bool allow_addon_scripts; +}; + +extern struct lif_config_file lif_config; + +extern bool lif_config_load(const char *filename); + +#endif diff --git a/libifupdown/libifupdown.h b/libifupdown/libifupdown.h index 33da802..6459c6a 100644 --- a/libifupdown/libifupdown.h +++ b/libifupdown/libifupdown.h @@ -27,6 +27,8 @@ #include "libifupdown/execute.h" #include "libifupdown/lifecycle.h" #include "libifupdown/tokenize.h" +#include "libifupdown/config-file.h" +#include "libifupdown/config-parser.h" #ifndef ARRAY_SIZE # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) From 5b27d8408c4bcdf31b5c0356097fc9ca66cf1c9d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:17:03 -0600 Subject: [PATCH 4/9] config file: don't print warning if config file cannot be opened --- dist/ifupdown-ng.conf.example | 10 ++++++++++ libifupdown/config-file.c | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 dist/ifupdown-ng.conf.example diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example new file mode 100644 index 0000000..1e5443c --- /dev/null +++ b/dist/ifupdown-ng.conf.example @@ -0,0 +1,10 @@ +# This is an example configuration file for ifupdown-ng, which allows +# the system administrator to configure the behaviour of ifupdown-ng. +# +# The settings specified here are the defaults of ifupdown-ng. + +# allow_addon_scripts: +# 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. +allow_addon_scripts = 1 diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 7f2b299..1844875 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -52,8 +52,10 @@ lif_config_load(const char *filename) if (fd == NULL) { +#if 0 fprintf(stderr, "ifupdown-ng: cannot open config %s: %s\n", filename, strerror(errno)); +#endif return false; } From b4e35c442e26e85c4ba9b7c73c833923291b2aed Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:18:45 -0600 Subject: [PATCH 5/9] multicall: load config file data as early as possible --- Makefile | 3 +++ cmd/multicall.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Makefile b/Makefile index a6fa3ff..4c57959 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new INTERFACES_FILE := /etc/network/interfaces STATE_FILE := /run/ifstate +CONFIG_FILE := /etc/network/ifupdown-ng.conf EXECUTOR_PATH := /usr/libexec/ifupdown-ng CFLAGS ?= -ggdb3 -Os @@ -18,6 +19,7 @@ CFLAGS += ${LIBBSD_CFLAGS} CPPFLAGS = -I. CPPFLAGS += -DINTERFACES_FILE=\"${INTERFACES_FILE}\" CPPFLAGS += -DSTATE_FILE=\"${STATE_FILE}\" +CPPFLAGS += -DCONFIG_FILE=\"${CONFIG_FILE}\" CPPFLAGS += -DPACKAGE_NAME=\"${PACKAGE_NAME}\" CPPFLAGS += -DPACKAGE_VERSION=\"${PACKAGE_VERSION}\" CPPFLAGS += -DPACKAGE_BUGREPORT=\"${PACKAGE_BUGREPORT}\" @@ -127,6 +129,7 @@ install: all for i in ${EXECUTOR_SCRIPTS_STUB}; do \ install -D -m755 executor-scripts/stub/$$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} < $< > $@ diff --git a/cmd/multicall.c b/cmd/multicall.c index 0c041ad..705000f 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -72,6 +72,8 @@ main(int argc, char *argv[]) argv0 = basename(argv[0]); const struct if_applet **app; + lif_config_load(CONFIG_FILE); + app = bsearch(argv0, applet_table, ARRAY_SIZE(applet_table), sizeof(*applet_table), applet_cmp); From c1c9115e5dff7d031ba713da17e51b5557f47b67 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:24:44 -0600 Subject: [PATCH 6/9] tokenize: fix tokenization of equals --- libifupdown/tokenize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index 288f9a1..fc7e61f 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -27,7 +27,7 @@ lif_next_token(char **buf) out++; char *end = out; - while (*end && !isspace(*end) && *out != '=') + while (*end && !isspace(*end) && *end != '=') end++; *end++ = '\0'; From 4b30dc457304ab5bcb1cad604551d103c7a04cdf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:26:45 -0600 Subject: [PATCH 7/9] lifecycle: if lif_config.allow_addon_scripts is disabled, don't run addon scripts --- libifupdown/lifecycle.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 9004e3f..d8ab8c5 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -25,6 +25,7 @@ #include "libifupdown/lifecycle.h" #include "libifupdown/state.h" #include "libifupdown/tokenize.h" +#include "libifupdown/config-file.h" static bool handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, const char *phase) @@ -240,6 +241,10 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac if (!handle_commands_for_phase(opts, envp, iface, phase)) goto handle_error; + /* if we don't need to support /etc/if-X.d we're done here */ + if (!lif_config.allow_addon_scripts) + goto out_free; + /* Check if scripts dir for this phase is present and bail out if it isn't */ struct stat dir_stat; char dir_path[4096]; From 27a383cfa7aa88b29604ca4c86faf6d99b858039 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:34:44 -0600 Subject: [PATCH 8/9] tokenizer: split out equals-as-delimiter tokenizer to its own function --- libifupdown/config-parser.c | 4 ++-- libifupdown/tokenize.h | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c index 0e16b70..f533cfb 100644 --- a/libifupdown/config-parser.c +++ b/libifupdown/config-parser.c @@ -40,8 +40,8 @@ lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler while (lif_fgetline(linebuf, sizeof linebuf, fd)) { char *bufp = linebuf; - char *key = lif_next_token(&bufp); - char *value = lif_next_token(&bufp); + char *key = lif_next_token_eq(&bufp); + char *value = lif_next_token_eq(&bufp); lineno++; diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index fc7e61f..f0aed3d 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -19,7 +19,7 @@ #include static inline char * -lif_next_token(char **buf) +lif_next_token_eq(char **buf) { char *out = *buf; @@ -36,4 +36,22 @@ lif_next_token(char **buf) return out; } +static inline char * +lif_next_token(char **buf) +{ + char *out = *buf; + + while (*out && isspace(*out)) + out++; + + char *end = out; + while (*end && !isspace(*end)) + end++; + + *end++ = '\0'; + *buf = end; + + return out; +} + #endif From d814aa754f6771e479632c0fcf4aadcd2b2e0f0c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 15 Sep 2020 05:48:54 -0600 Subject: [PATCH 9/9] config parser: explicitly skip over comments --- libifupdown/config-parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c index f533cfb..45005c6 100644 --- a/libifupdown/config-parser.c +++ b/libifupdown/config-parser.c @@ -48,6 +48,9 @@ lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler if (!*key || !*value) continue; + if (*key == '#') + continue; + struct lif_config_handler *hdl = bsearch(key, handlers, handler_count, sizeof(*handlers), handler_cmp);