diff --git a/cmd/ifquery.c b/cmd/ifquery.c index fb91883..6576457 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -30,7 +30,7 @@ print_interface(struct lif_interface *iface) if (iface->is_auto) printf("auto %s\n", iface->ifname); - printf("iface %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) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index ad20df4..0a09e06 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -96,6 +96,12 @@ acquire_state_lock(const char *state_path, const char *lifname) bool skip_interface(struct lif_interface *iface, const char *ifname) { + if (iface->is_template) + { + fprintf(stderr, "%s: cannot change state on %s (template interface)\n", argv0, ifname); + return false; + } + if (exec_opts.force) return false; diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example index 1e5443c..339f568 100644 --- a/dist/ifupdown-ng.conf.example +++ b/dist/ifupdown-ng.conf.example @@ -8,3 +8,18 @@ # compatibility with legacy setups, and may be disabled for performance # improvements in setups where only ifupdown-ng executors are used. allow_addon_scripts = 1 + +# allow_any_iface_as_template: +# 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. +allow_any_iface_as_template = 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 disabled, inheritance will continue to +# work against non-template interfaces without converting them to a +# template. +implicit_template_conversion = 1 diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 17bc5aa..f8ba926 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -47,6 +47,10 @@ with an address of *203.0.113.2* and gateway of *203.0.113.1*. associated with the declaration will be stored inside _object_. +*template* _object_ + Begins a new declaration for _object_, like *iface*, except + that _object_ is defined as a *template*. + # SUPPORTED KEYWORDS FOR OBJECT TRIPLES Any keyword may be used inside an interface declaration block, but @@ -79,9 +83,10 @@ the system will only respond to certain keywords by default: Interfaces associated with the parent are taken down at the same time as the parent. -*inherit* _interface_ - Designates that the parent interface should inherit - configuration data from _interface_. +*inherit* _object_ + Designates that the configured interface should inherit + configuration data from _object_. Normally _object_ + must be a *template*. *use* _option_ Designates that an option should be used. See _OPTIONS_ diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 1844875..2628118 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -20,6 +20,7 @@ struct lif_config_file lif_config = { .allow_addon_scripts = true, + .allow_any_iface_as_template = true, }; static bool @@ -43,6 +44,8 @@ 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}, + {"implicit_template_conversion", set_bool_value, &lif_config.implicit_template_conversion}, }; bool diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h index a528636..2d05c8f 100644 --- a/libifupdown/config-file.h +++ b/libifupdown/config-file.h @@ -20,6 +20,8 @@ struct lif_config_file { bool allow_addon_scripts; + bool allow_any_iface_as_template; + bool implicit_template_conversion; }; extern struct lif_config_file lif_config; diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 32f7a7c..e6a4d09 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -162,7 +162,9 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch return false; } - cur_iface->is_auto = true; + if (!cur_iface->is_template) + cur_iface->is_auto = true; + return true; } @@ -236,6 +238,15 @@ handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, c return false; } + /* mark the cur_iface as a template iface if `template` keyword + * is used. + */ + if (!strcmp(token, "template")) + { + cur_iface->is_auto = false; + cur_iface->is_template = true; + } + /* in original ifupdown config, we can have "inet loopback" * or "inet dhcp" or such to designate hints. lets pick up * those hints here. @@ -336,7 +347,9 @@ static const struct parser_keyword keywords[] = { {"gateway", handle_gateway}, {"iface", handle_iface}, {"inherit", handle_inherit}, + {"interface", handle_iface}, {"source", handle_source}, + {"template", handle_iface}, {"use", handle_use}, }; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 4164eab..feb8b2f 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -16,6 +16,7 @@ #include #include #include "libifupdown/interface.h" +#include "libifupdown/config-file.h" bool lif_address_parse(struct lif_address *address, const char *presentation) @@ -239,6 +240,13 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic if (parent == NULL) return false; + if (!lif_config.allow_any_iface_as_template && !parent->is_template) + return false; + + /* maybe convert any interface we are inheriting from into a template */ + if (lif_config.implicit_template_conversion) + parent->is_template = true; + lif_dict_add(&interface->vars, "inherit", strdup(ifname)); interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; diff --git a/libifupdown/interface.h b/libifupdown/interface.h index d627610..c36690d 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -50,6 +50,7 @@ struct lif_interface { bool is_auto; bool is_bridge; bool is_bond; + bool is_template; struct lif_dict vars; diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index d8ab8c5..bb59a02 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -341,6 +341,9 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up) { + if (iface->is_template) + return false; + if (lifname == NULL) lifname = iface->ifname;