config: fix feature for enabling service only when interface RUNNING
authorChristian Marangi <ansuelsmth@gmail.com>
Tue, 28 Mar 2023 22:16:46 +0000 (00:16 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Mon, 3 Apr 2023 19:19:18 +0000 (21:19 +0200)
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 <ansuelsmth@gmail.com>
src/config.c
src/netlink.c
src/odhcpd.h

index 27e7f0375adf30a29388215f1fd142f6da4d4b47..85d77b06986588dc55ceaf1ed9a8a774472e4953 100644 (file)
@@ -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);
        }
index 0a2da03bbc165c1fb34012e22923cfa98b908f0c..9b9fdb862b0aef8343478ebb4095e2fbe384b88d 100644 (file)
@@ -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;
index 0550bc28d4ebfcad87c46f41ac157cd9964d0ca5..bd61b012ff3fa89d0289946408d16513a2921b3c 100644 (file)
@@ -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);