diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-06-14 20:47:11 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2021-06-14 21:52:56 +0200 |
commit | a78b74784dc1d4a4007e3e21a79228d5192f0dad (patch) | |
tree | 377ab536f5a9162775ba260a383634035e7f10e9 /libs/rpcd-mod-luci/src | |
parent | 4286c84825c15f4d36f294b2ea28071667a4be7e (diff) |
rpcd-mod-luci: refactor host hint gathering
- Do not incorrectly put the IP addresses from the rrdns reply into the
first hint, instead distribute hostnames to the appropriate hints.
- Avoid returning stale lease information from previously parsed records
by clearing the static struct before each parse attempt.
- Improve existing checks for empty MAC addresses and unspecified IPv6
addresses.
Fixes: #5126
Fixes: 87bcf9e923 ("rpcd-mod-luci: Return array of addresses in getHostHints")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'libs/rpcd-mod-luci/src')
-rw-r--r-- | libs/rpcd-mod-luci/src/luci.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/libs/rpcd-mod-luci/src/luci.c b/libs/rpcd-mod-luci/src/luci.c index 613cea5e73..eb6f58803e 100644 --- a/libs/rpcd-mod-luci/src/luci.c +++ b/libs/rpcd-mod-luci/src/luci.c @@ -31,6 +31,7 @@ #include <net/if.h> #include <arpa/inet.h> #include <sys/types.h> +#include <netinet/in.h> #include <netinet/ether.h> #include <linux/rtnetlink.h> #include <linux/if_packet.h> @@ -222,6 +223,14 @@ readstr(const char *fmt, ...) return data; } +static bool +ea_empty(struct ether_addr *ea) +{ + struct ether_addr empty = { 0 }; + + return !memcmp(ea, &empty, sizeof(empty)); +} + static char * ea2str(struct ether_addr *ea) { @@ -452,9 +461,9 @@ lease_next(void) char *p; int n; - memset(&e, 0, sizeof(e)); - while (lease_state.off < lease_state.num) { + memset(&e, 0, sizeof(e)); + while (fgets(e.buf, sizeof(e.buf), lease_state.files[lease_state.off].fh)) { if (lease_state.files[lease_state.off].odhcpd) { strtok(e.buf, " \t\n"); /* # */ @@ -1185,9 +1194,8 @@ struct host_hint { #define HOST_HINT_PRIO_NL 10 /* neighbor table */ #define HOST_HINT_PRIO_ETHER 50 /* /etc/ethers */ #define HOST_HINT_PRIO_LEASEFILE 100 /* dhcp leasefile */ -#define HOST_HINT_PRIO_RRDNS 100 /* rrdns */ #define HOST_HINT_PRIO_IFADDRS 200 /* getifaddrs() */ -#define HOST_HINT_PRIO_STATIC_LEASE 200 /* uci static leases */ +#define HOST_HINT_PRIO_STATIC_LEASE 250 /* uci static leases */ struct host_hint_addr { struct avl_node avl; @@ -1538,6 +1546,9 @@ rpc_luci_get_host_hints_uci(struct reply_context *rctx) lease_open(); while ((lease = lease_next()) != NULL) { + if (ea_empty(&lease->mac)) + continue; + hint = rpc_luci_get_host_hint(rctx, &lease->mac); if (!hint) @@ -1564,8 +1575,6 @@ out: static void rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx) { - struct ether_addr empty_ea = {}; - struct in6_addr empty_in6 = {}; struct ifaddrs *ifaddr, *ifa; struct sockaddr_ll *sll; struct avl_tree devices; @@ -1621,8 +1630,8 @@ rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx) freeifaddrs(ifaddr); avl_remove_all_elements(&devices, device, avl, nextdevice) { - if (memcmp(&device->ea, &empty_ea, sizeof(empty_ea)) && - (memcmp(&device->in6, &empty_in6, sizeof(empty_in6)) || + if (!ea_empty(&device->ea) && + (!IN6_IS_ADDR_UNSPECIFIED(&device->in6) || device->in.s_addr != 0)) { hint = rpc_luci_get_host_hint(rctx, &device->ea); @@ -1630,7 +1639,7 @@ rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx) if (device->in.s_addr != 0) rpc_luci_add_host_hint_ipaddr(hint, HOST_HINT_PRIO_IFADDRS, &device->in); - if (memcmp(&device->in6, &empty_in6, sizeof(empty_in6)) != 0) + if (!IN6_IS_ADDR_UNSPECIFIED(&device->in6)) rpc_luci_add_host_hint_ip6addr(hint, HOST_HINT_PRIO_IFADDRS, &device->in6); } } @@ -1647,6 +1656,7 @@ rpc_luci_get_host_hints_rrdns_cb(struct ubus_request *req, int type, struct blob_attr *msg) { struct reply_context *rctx = req->priv; + struct host_hint_addr *addr; struct host_hint *hint; struct blob_attr *cur; struct in6_addr in6; @@ -1660,25 +1670,23 @@ rpc_luci_get_host_hints_rrdns_cb(struct ubus_request *req, int type, if (inet_pton(AF_INET6, blobmsg_name(cur), &in6) == 1) { avl_for_each_element(&rctx->avl, hint, avl) { - rpc_luci_add_host_hint_ip6addr(hint, HOST_HINT_PRIO_RRDNS, &in6); - if (!avl_is_empty(&hint->ip6addrs)) { - if (hint->hostname) + avl_for_each_element(&hint->ip6addrs, addr, avl) { + if (!memcmp(&addr->addr.in6, &in6, sizeof(in6))) { free(hint->hostname); - - hint->hostname = strdup(blobmsg_get_string(cur)); - break; + hint->hostname = strdup(blobmsg_get_string(cur)); + break; + } } } } else if (inet_pton(AF_INET, blobmsg_name(cur), &in) == 1) { avl_for_each_element(&rctx->avl, hint, avl) { - rpc_luci_add_host_hint_ipaddr(hint, HOST_HINT_PRIO_RRDNS, &in); - if (!avl_is_empty(&hint->ipaddrs)) { - if (hint->hostname) + avl_for_each_element(&hint->ipaddrs, addr, avl) { + if (addr->addr.in.s_addr == in.s_addr) { free(hint->hostname); - - hint->hostname = strdup(blobmsg_get_string(cur)); - break; + hint->hostname = strdup(blobmsg_get_string(cur)); + break; + } } } } @@ -1691,7 +1699,6 @@ rpc_luci_get_host_hints_rrdns_cb(struct ubus_request *req, int type, static void rpc_luci_get_host_hints_rrdns(struct reply_context *rctx) { - struct in6_addr empty_in6 = {}; char buf[INET6_ADDRSTRLEN]; struct blob_buf req = {}; struct host_hint *hint; @@ -1712,7 +1719,7 @@ rpc_luci_get_host_hints_rrdns(struct reply_context *rctx) } } avl_for_each_element(&hint->ip6addrs, addr, avl) { - if (memcmp(&addr->addr.in6, &empty_in6, sizeof(empty_in6))) { + if (!IN6_IS_ADDR_UNSPECIFIED(&addr->addr.in6)) { inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)); blobmsg_add_string(&req, NULL, buf); n++; @@ -1815,7 +1822,6 @@ rpc_luci_get_duid_hints(struct ubus_context *ctx, struct ubus_object *obj, { struct { struct avl_node avl; } *e, *next; char s[INET6_ADDRSTRLEN], *p; - struct ether_addr empty = {}; struct lease_entry *lease; struct avl_tree avl; void *o, *a; @@ -1857,7 +1863,7 @@ rpc_luci_get_duid_hints(struct ubus_context *ctx, struct ubus_object *obj, if (lease->hostname) blobmsg_add_string(&blob, "hostname", lease->hostname); - if (memcmp(&lease->mac, &empty, sizeof(empty))) + if (!ea_empty(&lease->mac)) blobmsg_add_string(&blob, "macaddr", ea2str(&lease->mac)); blobmsg_close_table(&blob, o); @@ -1906,7 +1912,6 @@ rpc_luci_get_dhcp_leases(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct blob_attr *tb[__RPC_L_MAX]; - struct ether_addr emptymac = {}; struct lease_entry *lease; char s[INET6_ADDRSTRLEN]; int af, family = 0; @@ -1958,7 +1963,7 @@ rpc_luci_get_dhcp_leases(struct ubus_context *ctx, struct ubus_object *obj, if (lease->hostname) blobmsg_add_string(&blob, "hostname", lease->hostname); - if (memcmp(&lease->mac, &emptymac, sizeof(emptymac))) + if (!ea_empty(&lease->mac)) blobmsg_add_string(&blob, "macaddr", ea2str(&lease->mac)); if (lease->duid) |