ifupdown: Don't configure errornous interfaces.
Do not configure interfaces which have a configuration know to be broken. Currently this only happens when using "inherit" to an non-existing iface or to an iface and not a template, and having allow_any_iface_as_template set to 0. In those cases broken ifaces will not be configured unless ifup/ifdown is invoked with --force. Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
This commit is contained in:
		
							parent
							
								
									fafce2f262
								
							
						
					
					
						commit
						8dc2295006
					
				
					 5 changed files with 76 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
 | 
				
			||||||
| 
						 | 
					@ -105,6 +106,12 @@ skip_interface(struct lif_interface *iface, const char *ifname)
 | 
				
			||||||
	if (exec_opts.force)
 | 
						if (exec_opts.force)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (iface->has_config_error)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "%s: skipping interface %s due to config errors\n", argv0, ifname);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (up && iface->refcount > 0)
 | 
						if (up && iface->refcount > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (exec_opts.verbose)
 | 
							if (exec_opts.verbose)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue