From 4b38e6b5bb967f0ee2e378a9016a5adaaa90eba5 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 29 Mar 2023 00:16:46 +0200 Subject: [PATCH] config: fix feature for enabling service only when interface RUNNING With ba30afcfec0a26ce4bcd96ea4d687c498b0ba4df it was found that odhcpd service are setup even if an interface had no connection and was not running. The commit introduced the change but required more fixup for the feature to work correctly. The close_interface() remove the interface from the avl list and this cause the interface to be missing later in the code flow. The intention of the commit was to just disable the service and enable them later when the interface is correctly set to running with the flag IFF_RUNNING. Change the logic and introduce a new function reload_servies() that will check IFF_RUNNING and enable or disable odhcp services. This function is called on odhcpd_reload() for each interface. In odhcpd_reload() also restore the original pattern with calling close_interface() only when the interface is not inuse for odhcp. Also call reload_services() on the single interface when a RTM_NEWLINK event is fired reacting to a link change of an odhcp interface and enabling the services if IFF_RUNNING is set. Fixes ba30afcfec0a ("config: skip interface setup if interface not IFF_RUNNING") Signed-off-by: Christian Marangi --- src/config.c | 28 ++++++++++++++++++++++------ src/netlink.c | 9 ++++++++- src/odhcpd.h | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/config.c b/src/config.c index 27e7f03..85d77b0 100644 --- a/src/config.c +++ b/src/config.c @@ -1209,6 +1209,27 @@ struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr) return NULL; } +void reload_services(struct interface *iface) +{ + if (iface->ifflags & IFF_RUNNING) { + syslog(LOG_DEBUG, "Enabling services with %s running", iface->ifname); + router_setup_interface(iface, iface->ra != MODE_DISABLED); + dhcpv6_setup_interface(iface, iface->dhcpv6 != MODE_DISABLED); + ndp_setup_interface(iface, iface->ndp != MODE_DISABLED); +#ifdef DHCPV4_SUPPORT + dhcpv4_setup_interface(iface, iface->dhcpv4 != MODE_DISABLED); +#endif + } else { + syslog(LOG_DEBUG, "Disabling services with %s not running", iface->ifname); + router_setup_interface(iface, false); + dhcpv6_setup_interface(iface, false); + ndp_setup_interface(iface, false); +#ifdef DHCPV4_SUPPORT + dhcpv4_setup_interface(iface, false); +#endif + } +} + void odhcpd_reload(void) { struct uci_context *uci = uci_alloc_context(); @@ -1326,12 +1347,7 @@ void odhcpd_reload(void) i->ndp = (master && master->ndp == MODE_RELAY) ? MODE_RELAY : MODE_DISABLED; - router_setup_interface(i, i->ra != MODE_DISABLED); - dhcpv6_setup_interface(i, i->dhcpv6 != MODE_DISABLED); - ndp_setup_interface(i, i->ndp != MODE_DISABLED); -#ifdef DHCPV4_SUPPORT - dhcpv4_setup_interface(i, i->dhcpv4 != MODE_DISABLED); -#endif + reload_services(i); } else close_interface(i); } diff --git a/src/netlink.c b/src/netlink.c index 0a2da03..9b9fdb8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -313,8 +313,15 @@ static int handle_rtm_link(struct nlmsghdr *hdr) iface->ifflags = ifi->ifi_flags; - if (iface->ifindex == ifi->ifi_index) + /* + * Assume for link event of the same index, that link changed + * and reload services to enable or disable them based on the + * RUNNING state of the interface. + */ + if (iface->ifindex == ifi->ifi_index) { + reload_services(iface); continue; + } iface->ifindex = ifi->ifi_index; event_info.iface = iface; diff --git a/src/odhcpd.h b/src/odhcpd.h index 0550bc2..bd61b01 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -475,5 +475,6 @@ void dhcpv4_handle_msg(void *addr, void *data, size_t len, int router_setup_interface(struct interface *iface, bool enable); int dhcpv6_setup_interface(struct interface *iface, bool enable); int ndp_setup_interface(struct interface *iface, bool enable); +void reload_services(struct interface *iface); void odhcpd_reload(void); -- 2.30.2