Merge pull request #84 from BarbarossaTM/feature/reduce-failure.domain
ifupdown: Don't configure errornous interfaces.
This commit is contained in:
commit
9c76528fe1
5 changed files with 84 additions and 24 deletions
|
@ -3,6 +3,7 @@
|
||||||
* Purpose: bring interfaces up or down
|
* Purpose: bring interfaces up or down
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -102,6 +103,20 @@ skip_interface(struct lif_interface *iface, const char *ifname)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iface->has_config_error)
|
||||||
|
{
|
||||||
|
if (exec_opts.force)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: (de)configuring interface %s despite config errors\n", argv0, ifname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: skipping interface %s due to config errors\n", argv0, ifname);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (exec_opts.force)
|
if (exec_opts.force)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Purpose: /etc/network/interfaces parser
|
* Purpose: /etc/network/interfaces parser
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -137,7 +138,8 @@ handle_address(struct lif_dict *collection, const char *filename, size_t lineno,
|
||||||
if (cur_iface == NULL)
|
if (cur_iface == NULL)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s '%s' without interface", token, addr);
|
report_error(filename, lineno, "%s '%s' without interface", token, addr);
|
||||||
return false;
|
/* Ignore this address, but don't fail hard */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lif_interface_address_add(cur_iface, addr);
|
lif_interface_address_add(cur_iface, addr);
|
||||||
|
@ -154,7 +156,10 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch
|
||||||
|
|
||||||
char *ifname = lif_next_token(&bufp);
|
char *ifname = lif_next_token(&bufp);
|
||||||
if (!*ifname && cur_iface == NULL)
|
if (!*ifname && cur_iface == NULL)
|
||||||
return false;
|
{
|
||||||
|
report_error(filename, lineno, "auto without interface");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cur_iface = lif_interface_collection_find(collection, ifname);
|
cur_iface = lif_interface_collection_find(collection, ifname);
|
||||||
|
@ -179,7 +184,8 @@ handle_gateway(struct lif_dict *collection, const char *filename, size_t lineno,
|
||||||
if (cur_iface == NULL)
|
if (cur_iface == NULL)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s '%s' without interface", token, addr);
|
report_error(filename, lineno, "%s '%s' without interface", token, addr);
|
||||||
return false;
|
/* Ignore this gateway, but don't fail hard */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lif_interface_use_executor(cur_iface, "static");
|
lif_interface_use_executor(cur_iface, "static");
|
||||||
|
@ -228,7 +234,8 @@ handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, c
|
||||||
if (!*ifname)
|
if (!*ifname)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s without any other tokens", token);
|
report_error(filename, lineno, "%s without any other tokens", token);
|
||||||
return false;
|
/* This is broken but not fatal */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_iface = lif_interface_collection_find(collection, ifname);
|
cur_iface = lif_interface_collection_find(collection, ifname);
|
||||||
|
@ -278,19 +285,44 @@ handle_inherit(struct lif_dict *collection, const char *filename, size_t lineno,
|
||||||
if (cur_iface == NULL)
|
if (cur_iface == NULL)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s '%s' without interface", token, target);
|
report_error(filename, lineno, "%s '%s' without interface", token, target);
|
||||||
return false;
|
/* This is broken but not fatal */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*target)
|
if (!*target)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s: unspecified interface");
|
report_error(filename, lineno, "iface %s: unspecified inherit target", cur_iface->ifname);
|
||||||
return false;
|
/* Mark this interface as errornous but carry on */
|
||||||
|
cur_iface->has_config_error = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lif_interface_collection_inherit(cur_iface, collection, target))
|
struct lif_interface *parent = lif_interface_collection_find(collection, target);
|
||||||
|
if (parent == NULL)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "could not inherit %s", target);
|
report_error(filename, lineno, "iface %s: could not inherit from %s: not found",
|
||||||
return false;
|
cur_iface->ifname, target);
|
||||||
|
/* Mark this interface as errornous but carry on */
|
||||||
|
cur_iface->has_config_error = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lif_config.allow_any_iface_as_template && !parent->is_template)
|
||||||
|
{
|
||||||
|
report_error(filename, lineno, "iface %s: could not inherit from %ss: inheritence from non-template interface not allowed",
|
||||||
|
cur_iface->ifname, target);
|
||||||
|
/* Mark this interface as errornous but carry on */
|
||||||
|
cur_iface->has_config_error = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lif_interface_collection_inherit(cur_iface, parent))
|
||||||
|
{
|
||||||
|
report_error(filename, lineno, "iface %s: could not inherit from %s", cur_iface->ifname, target);
|
||||||
|
/* Mark this interface as errornous but carry on */
|
||||||
|
cur_iface->has_config_error = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -305,14 +337,16 @@ handle_source(struct lif_dict *collection, const char *filename, size_t lineno,
|
||||||
if (!*source_filename)
|
if (!*source_filename)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "missing filename to source");
|
report_error(filename, lineno, "missing filename to source");
|
||||||
return false;
|
/* Broken but not fatal */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(filename, source_filename))
|
if (!strcmp(filename, source_filename))
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "attempt to source %s would create infinite loop",
|
report_error(filename, lineno, "attempt to source %s would create infinite loop",
|
||||||
source_filename);
|
source_filename);
|
||||||
return false;
|
/* Broken but not fatal */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lif_interface_file_parse(collection, source_filename);
|
return lif_interface_file_parse(collection, source_filename);
|
||||||
|
@ -328,7 +362,8 @@ handle_use(struct lif_dict *collection, const char *filename, size_t lineno, cha
|
||||||
if (cur_iface == NULL)
|
if (cur_iface == NULL)
|
||||||
{
|
{
|
||||||
report_error(filename, lineno, "%s '%s' without interface", token, executor);
|
report_error(filename, lineno, "%s '%s' without interface", token, executor);
|
||||||
return false;
|
/* Broken but not fatal */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lif_interface_use_executor(cur_iface, executor);
|
lif_interface_use_executor(cur_iface, executor);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Purpose: interface management
|
* Purpose: interface management
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -233,21 +234,13 @@ lif_interface_collection_delete(struct lif_dict *collection, struct lif_interfac
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname)
|
lif_interface_collection_inherit(struct lif_interface *interface, struct lif_interface *parent)
|
||||||
{
|
{
|
||||||
struct lif_interface *parent = lif_interface_collection_find(collection, ifname);
|
|
||||||
|
|
||||||
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 */
|
/* maybe convert any interface we are inheriting from into a template */
|
||||||
if (lif_config.implicit_template_conversion)
|
if (lif_config.implicit_template_conversion)
|
||||||
parent->is_template = true;
|
parent->is_template = true;
|
||||||
|
|
||||||
lif_dict_add(&interface->vars, "inherit", strdup(ifname));
|
lif_dict_add(&interface->vars, "inherit", strdup(parent->ifname));
|
||||||
interface->is_bond = parent->is_bond;
|
interface->is_bond = parent->is_bond;
|
||||||
interface->is_bridge = parent->is_bridge;
|
interface->is_bridge = parent->is_bridge;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Purpose: interface management
|
* Purpose: interface management
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -52,6 +53,8 @@ struct lif_interface {
|
||||||
bool is_bond;
|
bool is_bond;
|
||||||
bool is_template;
|
bool is_template;
|
||||||
|
|
||||||
|
bool has_config_error; /* error found in interface configuration */
|
||||||
|
|
||||||
struct lif_dict vars;
|
struct lif_dict vars;
|
||||||
|
|
||||||
size_t refcount; /* > 0 if up, else 0 */
|
size_t refcount; /* > 0 if up, else 0 */
|
||||||
|
@ -74,7 +77,7 @@ extern void lif_interface_collection_init(struct lif_dict *collection);
|
||||||
extern void lif_interface_collection_fini(struct lif_dict *collection);
|
extern void lif_interface_collection_fini(struct lif_dict *collection);
|
||||||
extern struct lif_interface *lif_interface_collection_find(struct lif_dict *collection, const char *ifname);
|
extern struct lif_interface *lif_interface_collection_find(struct lif_dict *collection, const char *ifname);
|
||||||
extern struct lif_interface *lif_interface_collection_upsert(struct lif_dict *collection, struct lif_interface *interface);
|
extern struct lif_interface *lif_interface_collection_upsert(struct lif_dict *collection, struct lif_interface *interface);
|
||||||
extern bool lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname);
|
extern bool lif_interface_collection_inherit(struct lif_interface *interface, struct lif_interface *parent);
|
||||||
extern void lif_interface_collection_delete(struct lif_dict *collection, struct lif_interface *interface);
|
extern void lif_interface_collection_delete(struct lif_dict *collection, struct lif_interface *interface);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Purpose: management of interface lifecycle (bring up, takedown, reload)
|
* Purpose: management of interface lifecycle (bring up, takedown, reload)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
* Copyright (c) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -313,6 +314,19 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par
|
||||||
{
|
{
|
||||||
struct lif_interface *iface = lif_interface_collection_find(collection, tokenp);
|
struct lif_interface *iface = lif_interface_collection_find(collection, tokenp);
|
||||||
|
|
||||||
|
if (iface->has_config_error)
|
||||||
|
{
|
||||||
|
if (opts->force)
|
||||||
|
fprintf (stderr, "ifupdown: (de)configuring dependent interface %s (of %s) despite config errors\n",
|
||||||
|
iface->ifname, parent->ifname);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ifupdown: skipping dependent interface %s (of %s) as it has config errors\n",
|
||||||
|
iface->ifname, parent->ifname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* if handle_refcounting returns true, it means we've already
|
/* if handle_refcounting returns true, it means we've already
|
||||||
* configured the interface, or it is too soon to deconfigure
|
* configured the interface, or it is too soon to deconfigure
|
||||||
* the interface.
|
* the interface.
|
||||||
|
|
Loading…
Reference in a new issue