diff --git a/Makefile b/Makefile index 048c960..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}\" @@ -34,7 +36,9 @@ LIBIFUPDOWN_SRC = \ libifupdown/state.c \ libifupdown/environment.c \ libifupdown/execute.c \ - libifupdown/lifecycle.c + libifupdown/lifecycle.c \ + libifupdown/config-parser.c \ + libifupdown/config-file.c LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a @@ -125,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); 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 new file mode 100644 index 0000000..1844875 --- /dev/null +++ b/libifupdown/config-file.c @@ -0,0 +1,63 @@ +/* + * 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) + { +#if 0 + fprintf(stderr, "ifupdown-ng: cannot open config %s: %s\n", + filename, strerror(errno)); +#endif + 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/config-parser.c b/libifupdown/config-parser.c new file mode 100644 index 0000000..45005c6 --- /dev/null +++ b/libifupdown/config-parser.c @@ -0,0 +1,87 @@ +/* + * 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_eq(&bufp); + char *value = lif_next_token_eq(&bufp); + + lineno++; + + if (!*key || !*value) + continue; + + if (*key == '#') + 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 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)) 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]; diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index 751c2f2..f0aed3d 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -18,6 +18,24 @@ #include +static inline char * +lif_next_token_eq(char **buf) +{ + char *out = *buf; + + while (*out && (isspace(*out) || *out == '=')) + out++; + + char *end = out; + while (*end && !isspace(*end) && *end != '=') + end++; + + *end++ = '\0'; + *buf = end; + + return out; +} + static inline char * lif_next_token(char **buf) {