From 979aca4764c10312b62b4e34c7e9f58e22f86b76 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 15 Mar 2023 15:21:44 +0100 Subject: [PATCH] mac addresses were never flushed Signed-off-by: John Crispin --- CMakeLists.txt | 2 ++ bridge.c | 35 ++++++++++++++++++++++++++++++++--- dhcp.c | 22 ++++++++++++++++++++++ mac.c | 32 +++++++++++++++++++++++++++++++- main.c | 6 ++++++ neigh.c | 6 ++++++ netdev.c | 11 +++++++++++ netifd.c | 10 ++++++++++ udevmand.h | 11 +++++++++-- 9 files changed, 129 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f58965..d424e16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 2.6) +include_directories(/usr/local/include/libnl-tiny) + PROJECT(udevmand C) INCLUDE(GNUInstallDirs) ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations) diff --git a/bridge.c b/bridge.c index e00ffd7..68e1218 100644 --- a/bridge.c +++ b/bridge.c @@ -81,6 +81,8 @@ bridge_dump_if(const char *bridge) } if (c) blobmsg_close_array(&b, c); + + globfree(&gl); } static void @@ -110,14 +112,14 @@ bridge_read_if(const char *bridge) continue; brif = malloc(sizeof(*brif)); if (!brif) - return; + goto out; strcpy(brif->name, basename(gl.gl_pathv[i])); brif->port_no = port_no; list_add(&brif->list, &bridge_if); } +out: globfree(&gl); - } static void bridge_tout(struct uloop_timeout *t) @@ -128,7 +130,7 @@ static void bridge_tout(struct uloop_timeout *t) int i; if (glob("/sys/class/net/*", GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT, NULL, &gl)) - return; + goto out; list_for_each_entry_safe(brif, tmp, &bridge_if, list) { list_del(&brif->list); @@ -143,6 +145,7 @@ static void bridge_tout(struct uloop_timeout *t) vlist_flush(&bridge_mac); globfree(&gl); +out: uloop_timeout_set(&bridge_timer, 1000); } @@ -187,3 +190,29 @@ void bridge_init(void) uloop_timeout_set(&bridge_timer, 1000); vlist_init(&bridge_mac, bridge_cmp, bridge_update); } + +void bridge_flush(void) +{ + struct bridge_if *brif, *tmp; + struct bridge_mac *b, *p; + + vlist_for_each_element_safe(&bridge_mac, b, vlist, p) { + vlist_delete(&bridge_mac, &b->vlist); + free(b); + } + + list_for_each_entry_safe(brif, tmp, &bridge_if, list) { + list_del(&brif->list); + free(brif); + } +} + +void +bridge_mac_del(struct bridge_mac *b) +{ + list_del(&b->mac); + vlist_delete(&bridge_mac, &b->vlist); + free(b); +} + + diff --git a/dhcp.c b/dhcp.c index 829b2ac..c219a32 100644 --- a/dhcp.c +++ b/dhcp.c @@ -111,6 +111,14 @@ dhcpv4_release(struct blob_attr *msg) free(dhcpv4); } +void +dhcpv4_del(struct dhcpv4 *dhcpv4) +{ + list_del(&dhcpv4->mac); + avl_delete(&dhcpv4_tree, &dhcpv4->avl); + free(dhcpv4); +} + void dhcp_init(void) { @@ -136,4 +144,18 @@ dhcp_init(void) dhcpv4_add(addr, ip, hostname, NULL); } + + fclose(fp); } + +void +dhcp_done(void) +{ + struct dhcpv4 *d, *t; + + avl_for_each_element_safe(&dhcpv4_tree, d, avl, t) { + avl_delete(&dhcpv4_tree, &d->avl); + free(d); + } +} + diff --git a/mac.c b/mac.c index 6e5993f..deadd15 100644 --- a/mac.c +++ b/mac.c @@ -115,14 +115,44 @@ mac_dump(struct mac *mac, int interface) neigh_flush(); } +static void +mac_flush(struct mac *mac, struct timespec ts) +{ + time_t last_seen; + + last_seen = ts.tv_sec - mac->ts.tv_sec; + if (last_seen < 60 * 60) + return; + + if (!list_empty(&mac->dhcpv4)) { + struct dhcpv4 *dhcpv4, *t; + + list_for_each_entry_safe(dhcpv4, t, &mac->dhcpv4, mac) + dhcpv4_del(dhcpv4); + } + + if (!list_empty(&mac->bridge_mac)) { + struct bridge_mac *bridge_mac, *t; + + list_for_each_entry_safe(bridge_mac, t, &mac->bridge_mac, mac) + bridge_mac_del(bridge_mac); + } +} + int mac_dump_all(void) { - struct mac *mac; + struct mac *mac, *t; + struct timespec ts; blob_buf_init(&b, 0); avl_for_each_element(&mac_tree, mac, avl) mac_dump(mac, 1); + + clock_gettime(CLOCK_MONOTONIC, &ts); + avl_for_each_element_safe(&mac_tree, mac, avl, t) + mac_flush(mac, ts); + return 0; } diff --git a/main.c b/main.c index f5e266a..948b923 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,12 @@ int main(int argc, char **argv) uloop_run(); uloop_done(); ubus_uninit(); + bridge_flush(); + blob_buf_free(&b); + neigh_done(); + interface_done(); + dhcp_done(); + iface_done(); return 0; } diff --git a/neigh.c b/neigh.c index 6660cf2..0eff545 100644 --- a/neigh.c +++ b/neigh.c @@ -181,3 +181,9 @@ neigh_init(void) return 0; } + +void +neigh_done(void) +{ + nl_socket_free(rtnl_sock.sock); +} diff --git a/netdev.c b/netdev.c index 542ff42..b75d48d 100644 --- a/netdev.c +++ b/netdev.c @@ -38,6 +38,17 @@ iface_find(char *name) return iface; } +void +iface_done(void) +{ + struct iface *i, *t; + + avl_for_each_element_safe(&iface_tree, i, avl, t) { + avl_delete(&iface_tree, &i->avl); + free(i); + } +} + static void iface_get(void) { diff --git a/netifd.c b/netifd.c index 2b4cf48..9db4d2c 100644 --- a/netifd.c +++ b/netifd.c @@ -104,3 +104,13 @@ interface_dump(void) } return 0; } + +void +interface_done(void) +{ + struct interface *i, *t; + + avl_for_each_element_safe(&interface_tree, i, avl, t) + free(i); +} + diff --git a/udevmand.h b/udevmand.h index 3781a47..ce506df 100644 --- a/udevmand.h +++ b/udevmand.h @@ -102,7 +102,7 @@ struct bridge_mac { int avl_mac_cmp(const void *k1, const void *k2, void *ptr); -struct avl_tree mac_tree; +extern struct avl_tree mac_tree; int mac_dump_all(void); void mac_dump(struct mac *mac, int interface); struct mac* mac_find(uint8_t *addr); @@ -111,12 +111,13 @@ void mac_update(struct mac *mac, char *iface); int neigh_init(void); void neigh_enum(void); void neigh_flush(void); +void neigh_done(void); bool nl_status_socket(struct nl_socket *ev, int protocol, int (*cb)(struct nl_msg *msg, void *arg), void *priv); int genl_send_and_recv(struct nl_socket *ev, struct nl_msg * msg); -struct blob_buf b; +extern struct blob_buf b; void blobmsg_add_iface(struct blob_buf *bbuf, char *name, int index); void blobmsg_add_iftype(struct blob_buf *bbuf, const char *name, const uint32_t iftype); void blobmsg_add_ipv4(struct blob_buf *bbuf, const char *name, const uint8_t* addr); @@ -128,16 +129,22 @@ void ubus_uninit(void); void bridge_init(void); void bridge_dump_if(const char *bridge); +void bridge_flush(void); +void bridge_mac_del(struct bridge_mac *b); void dhcpv4_ack(struct blob_attr *msg); void dhcpv4_release(struct blob_attr *msg); void dhcp_init(void); +void dhcp_done(void); +void dhcpv4_del(struct dhcpv4 *dhcpv4); int interface_dump(void); void interface_update(struct blob_attr *msg, int raw); void interface_down(struct blob_attr *msg); char *interface_resolve(char *device); +void interface_done(void); void ethers_init(void); +void iface_done(void); void iface_dump(int delta);