From c4d9d6fd06a1d6b486e88782fcb7965ffdbd6494 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 11:38:39 -0700 Subject: [PATCH] interface: add lif_interface_finalize() which rewrites addresses as CIDR when an interface stanza ends --- libifupdown/interface-file.c | 11 ++++++++ libifupdown/interface.c | 52 ++++++++++++++++++++++++++++++------ libifupdown/interface.h | 1 + 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index d5c9fa5..3d217a9 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -263,6 +263,12 @@ handle_iface(struct lif_interface_file_parse_state *state, char *token, char *bu return true; } + /* if we have a current interface, call lif_interface_finalize to finalize any + * address properties by converting them to CIDR and flushing the netmask property. + */ + if (state->cur_iface != NULL) + lif_interface_finalize(state->cur_iface); + state->cur_iface = lif_interface_collection_find(state->collection, ifname); if (state->cur_iface == NULL) { @@ -501,6 +507,11 @@ lif_interface_file_parse(struct lif_interface_file_parse_state *state, const cha } fclose(f); + + /* finalize any open interface */ + if (state->cur_iface != NULL) + lif_interface_finalize(state->cur_iface); + state->cur_filename = old_filename; state->cur_lineno = old_lineno; return true; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index b18e318..0294383 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -84,6 +84,19 @@ count_set_bits(const char *netmask) return r; } +static inline size_t +determine_interface_netmask(const struct lif_interface *iface, const struct lif_address *addr) +{ + /* if netmask is not set, default to /24 or /64, ifupdown does so too */ + size_t netmask = addr->domain == AF_INET6 ? 64 : 24; + + struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); + if (entry != NULL) + netmask = count_set_bits(entry->data); + + return netmask; +} + bool lif_address_format_cidr(const struct lif_interface *iface, struct lif_dict_entry *entry, char *buf, size_t buflen) { @@ -91,14 +104,7 @@ lif_address_format_cidr(const struct lif_interface *iface, struct lif_dict_entry size_t orig_netmask = addr->netmask; if (!addr->netmask) - { - /* if netmask is not set, default to 255.255.255.0, ifupdown does so too */ - addr->netmask = addr->domain == AF_INET6 ? 64 : 24; - - struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); - if (entry != NULL) - addr->netmask = count_set_bits(entry->data); - } + addr->netmask = determine_interface_netmask(iface, addr); if (!lif_address_unparse(addr, buf, buflen, true)) { @@ -213,6 +219,36 @@ lif_interface_use_executor(struct lif_interface *interface, const char *executor lif_dict_add(&interface->vars, "hostname", strdup(un.nodename)); } +void +lif_interface_finalize(struct lif_interface *interface) +{ + struct lif_node *iter; + + /* convert all addresses to CIDR notation. */ + LIF_DICT_FOREACH(iter, &interface->vars) + { + struct lif_dict_entry *entry = iter->data; + + if (strcmp(entry->key, "address")) + continue; + + struct lif_address *addr = entry->data; + + if (!addr->netmask) + addr->netmask = determine_interface_netmask(interface, addr); + } + + /* with all addresses converted to CIDR, netmask property is no longer needed. */ + struct lif_dict_entry *entry = lif_dict_find(&interface->vars, "netmask"); + + if (entry != NULL) + { + free(entry->data); + + lif_dict_delete_entry(&interface->vars, entry); + } +} + void lif_interface_collection_init(struct lif_dict *collection) { diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 0c6d8b2..49c867d 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -75,6 +75,7 @@ extern bool lif_interface_address_add(struct lif_interface *interface, const cha extern void lif_interface_address_delete(struct lif_interface *interface, const char *address); extern void lif_interface_fini(struct lif_interface *interface); extern void lif_interface_use_executor(struct lif_interface *interface, const char *executor); +extern void lif_interface_finalize(struct lif_interface *interface); extern void lif_interface_collection_init(struct lif_dict *collection); extern void lif_interface_collection_fini(struct lif_dict *collection);