Merge pull request #119 from ifupdown-ng/feature/explicit-guard
guard auto and explicitly configured interfaces from inappropriate deconfiguration
This commit is contained in:
commit
90453f1412
8 changed files with 52 additions and 13 deletions
|
@ -182,7 +182,8 @@ list_state(struct lif_dict *state, struct match_options *opts)
|
||||||
if (listing_running)
|
if (listing_running)
|
||||||
printf("%s\n", entry->key);
|
printf("%s\n", entry->key);
|
||||||
else
|
else
|
||||||
printf("%s=%s %zu\n", entry->key, rec->mapped_if, rec->refcount);
|
printf("%s=%s %zu%s\n", entry->key, rec->mapped_if, rec->refcount,
|
||||||
|
rec->is_explicit ? " explicit" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ acquire_state_lock(const char *state_path, const char *lifname)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
skip_interface(struct lif_interface *iface, const char *ifname)
|
skip_interface(struct lif_interface *iface, const char *ifname, struct lif_dict *state, bool update_state)
|
||||||
{
|
{
|
||||||
if (iface->is_template)
|
if (iface->is_template)
|
||||||
{
|
{
|
||||||
|
@ -123,16 +123,23 @@ skip_interface(struct lif_interface *iface, const char *ifname)
|
||||||
if (up && iface->refcount > 0)
|
if (up && iface->refcount > 0)
|
||||||
{
|
{
|
||||||
if (exec_opts.verbose)
|
if (exec_opts.verbose)
|
||||||
fprintf(stderr, "%s: skipping auto interface %s (already configured), use --force to force configuration\n",
|
fprintf(stderr, "%s: skipping %sinterface %s (already configured), use --force to force configuration\n",
|
||||||
argv0, ifname);
|
argv0, iface->is_auto ? "auto " : "", ifname);
|
||||||
|
|
||||||
|
if (update_state)
|
||||||
|
{
|
||||||
|
iface->is_explicit = true;
|
||||||
|
lif_state_upsert(state, ifname, iface);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!up && iface->refcount == 0)
|
if (!up && iface->refcount == 0)
|
||||||
{
|
{
|
||||||
if (exec_opts.verbose)
|
if (exec_opts.verbose)
|
||||||
fprintf(stderr, "%s: skipping auto interface %s (already deconfigured), use --force to force deconfiguration\n",
|
fprintf(stderr, "%s: skipping %sinterface %s (already deconfigured), use --force to force deconfiguration\n",
|
||||||
argv0, ifname);
|
argv0, iface->is_auto ? "auto " : "", ifname);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +147,7 @@ skip_interface(struct lif_interface *iface, const char *ifname)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
change_interface(struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *ifname)
|
change_interface(struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *ifname, bool update_state)
|
||||||
{
|
{
|
||||||
int lockfd = acquire_state_lock(exec_opts.state_file, ifname);
|
int lockfd = acquire_state_lock(exec_opts.state_file, ifname);
|
||||||
|
|
||||||
|
@ -150,7 +157,7 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip_interface(iface, ifname))
|
if (skip_interface(iface, ifname, state, update_state))
|
||||||
{
|
{
|
||||||
if (lockfd != -1)
|
if (lockfd != -1)
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
|
@ -178,6 +185,12 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc
|
||||||
if (lockfd != -1)
|
if (lockfd != -1)
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
|
|
||||||
|
if (up && update_state)
|
||||||
|
{
|
||||||
|
iface->is_explicit = true;
|
||||||
|
lif_state_upsert(state, ifname, iface);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +215,7 @@ change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, stru
|
||||||
fnmatch(opts->include_pattern, iface->ifname, 0))
|
fnmatch(opts->include_pattern, iface->ifname, 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!change_interface(iface, collection, state, iface->ifname))
|
if (!change_interface(iface, collection, state, iface->ifname, false))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +326,7 @@ ifupdown_main(int argc, char *argv[])
|
||||||
iface = entry->data;
|
iface = entry->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!change_interface(iface, &collection, &state, ifname))
|
if (!change_interface(iface, &collection, &state, ifname, true))
|
||||||
return update_state_file_and_exit(EXIT_FAILURE, &state);
|
return update_state_file_and_exit(EXIT_FAILURE, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,9 @@ handle_auto(struct lif_interface_file_parse_state *state, char *token, char *buf
|
||||||
if (!state->cur_iface->is_template)
|
if (!state->cur_iface->is_template)
|
||||||
state->cur_iface->is_auto = true;
|
state->cur_iface->is_auto = true;
|
||||||
|
|
||||||
|
if (state->cur_iface->is_auto)
|
||||||
|
state->cur_iface->is_explicit = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,7 @@ lif_interface_collection_init(struct lif_dict *collection)
|
||||||
/* always enable loopback interface as part of a collection */
|
/* always enable loopback interface as part of a collection */
|
||||||
if_lo = lif_interface_collection_find(collection, "lo");
|
if_lo = lif_interface_collection_find(collection, "lo");
|
||||||
if_lo->is_auto = true;
|
if_lo->is_auto = true;
|
||||||
|
if_lo->is_explicit = true;
|
||||||
lif_interface_use_executor(if_lo, "loopback");
|
lif_interface_use_executor(if_lo, "loopback");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct lif_interface {
|
||||||
bool is_bond;
|
bool is_bond;
|
||||||
bool is_template;
|
bool is_template;
|
||||||
bool is_pending;
|
bool is_pending;
|
||||||
|
bool is_explicit;
|
||||||
|
|
||||||
bool has_config_error; /* error found in interface configuration */
|
bool has_config_error; /* error found in interface configuration */
|
||||||
|
|
||||||
|
|
|
@ -396,6 +396,15 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!up && iface->is_explicit)
|
||||||
|
{
|
||||||
|
if (opts->verbose)
|
||||||
|
fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s) -- interface is marked as explicitly configured\n",
|
||||||
|
iface->ifname, parent->ifname);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->verbose)
|
if (opts->verbose)
|
||||||
fprintf(stderr, "ifupdown: changing state of dependent interface %s (of %s) to %s\n",
|
fprintf(stderr, "ifupdown: changing state of dependent interface %s (of %s) to %s\n",
|
||||||
iface->ifname, parent->ifname, up ? "up" : "down");
|
iface->ifname, parent->ifname, up ? "up" : "down");
|
||||||
|
|
|
@ -29,8 +29,13 @@ lif_state_read(struct lif_dict *state, FILE *fd)
|
||||||
char *bufp = linebuf;
|
char *bufp = linebuf;
|
||||||
char *ifname = lif_next_token(&bufp);
|
char *ifname = lif_next_token(&bufp);
|
||||||
char *refcount = lif_next_token(&bufp);
|
char *refcount = lif_next_token(&bufp);
|
||||||
|
char *explicit = lif_next_token(&bufp);
|
||||||
size_t rc = 1;
|
size_t rc = 1;
|
||||||
char *equals_p = strchr(linebuf, '=');
|
char *equals_p = strchr(linebuf, '=');
|
||||||
|
bool is_explicit = false;
|
||||||
|
|
||||||
|
if (*explicit && !strcmp(explicit, "explicit"))
|
||||||
|
is_explicit = true;
|
||||||
|
|
||||||
if (*refcount)
|
if (*refcount)
|
||||||
{
|
{
|
||||||
|
@ -42,12 +47,12 @@ lif_state_read(struct lif_dict *state, FILE *fd)
|
||||||
|
|
||||||
if (equals_p == NULL)
|
if (equals_p == NULL)
|
||||||
{
|
{
|
||||||
lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = ifname, .refcount = rc });
|
lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = ifname, .refcount = rc, .is_explicit = is_explicit });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*equals_p++ = '\0';
|
*equals_p++ = '\0';
|
||||||
lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = equals_p, .refcount = rc });
|
lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = equals_p, .refcount = rc, .is_explicit = is_explicit });
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -99,6 +104,7 @@ lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interfac
|
||||||
|
|
||||||
rec->mapped_if = strdup(iface->ifname);
|
rec->mapped_if = strdup(iface->ifname);
|
||||||
rec->refcount = iface->refcount;
|
rec->refcount = iface->refcount;
|
||||||
|
rec->is_explicit = iface->is_explicit;
|
||||||
|
|
||||||
lif_dict_add(state, ifname, rec);
|
lif_dict_add(state, ifname, rec);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +134,8 @@ lif_state_write(const struct lif_dict *state, FILE *f)
|
||||||
struct lif_dict_entry *entry = iter->data;
|
struct lif_dict_entry *entry = iter->data;
|
||||||
struct lif_state_record *rec = entry->data;
|
struct lif_state_record *rec = entry->data;
|
||||||
|
|
||||||
fprintf(f, "%s=%s %zu\n", entry->key, rec->mapped_if, rec->refcount);
|
fprintf(f, "%s=%s %zu%s\n", entry->key, rec->mapped_if, rec->refcount,
|
||||||
|
rec->is_explicit ? " explicit" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +182,7 @@ lif_state_sync(struct lif_dict *state, struct lif_dict *if_collection)
|
||||||
struct lif_interface *iface = lif_interface_collection_find(if_collection, rec->mapped_if);
|
struct lif_interface *iface = lif_interface_collection_find(if_collection, rec->mapped_if);
|
||||||
|
|
||||||
iface->refcount = rec->refcount;
|
iface->refcount = rec->refcount;
|
||||||
|
iface->is_explicit = rec->is_explicit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -17,11 +17,14 @@
|
||||||
#define LIBIFUPDOWN_STATE_H__GUARD
|
#define LIBIFUPDOWN_STATE_H__GUARD
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "libifupdown/interface.h"
|
#include "libifupdown/interface.h"
|
||||||
|
|
||||||
struct lif_state_record {
|
struct lif_state_record {
|
||||||
char *mapped_if;
|
char *mapped_if;
|
||||||
size_t refcount;
|
size_t refcount;
|
||||||
|
|
||||||
|
bool is_explicit;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool lif_state_read(struct lif_dict *state, FILE *f);
|
extern bool lif_state_read(struct lif_dict *state, FILE *f);
|
||||||
|
|
Loading…
Reference in a new issue