interface: add lif_interface_finalize() which rewrites addresses as CIDR when an interface stanza ends

This commit is contained in:
Ariadne Conill 2020-12-02 11:38:39 -07:00
parent 0dd7756df2
commit c4d9d6fd06
3 changed files with 56 additions and 8 deletions

View file

@ -263,6 +263,12 @@ handle_iface(struct lif_interface_file_parse_state *state, char *token, char *bu
return true; 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); state->cur_iface = lif_interface_collection_find(state->collection, ifname);
if (state->cur_iface == NULL) if (state->cur_iface == NULL)
{ {
@ -501,6 +507,11 @@ lif_interface_file_parse(struct lif_interface_file_parse_state *state, const cha
} }
fclose(f); fclose(f);
/* finalize any open interface */
if (state->cur_iface != NULL)
lif_interface_finalize(state->cur_iface);
state->cur_filename = old_filename; state->cur_filename = old_filename;
state->cur_lineno = old_lineno; state->cur_lineno = old_lineno;
return true; return true;

View file

@ -84,6 +84,19 @@ count_set_bits(const char *netmask)
return r; 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 bool
lif_address_format_cidr(const struct lif_interface *iface, struct lif_dict_entry *entry, char *buf, size_t buflen) 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; size_t orig_netmask = addr->netmask;
if (!addr->netmask) if (!addr->netmask)
{ addr->netmask = determine_interface_netmask(iface, addr);
/* 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);
}
if (!lif_address_unparse(addr, buf, buflen, true)) 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)); 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 void
lif_interface_collection_init(struct lif_dict *collection) lif_interface_collection_init(struct lif_dict *collection)
{ {

View file

@ -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_address_delete(struct lif_interface *interface, const char *address);
extern void lif_interface_fini(struct lif_interface *interface); 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_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_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);