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>
This commit is contained in:
parent
4286c84825
commit
a78b74784d
1 changed files with 32 additions and 27 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <netinet/ether.h>
|
#include <netinet/ether.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/if_packet.h>
|
#include <linux/if_packet.h>
|
||||||
|
@ -222,6 +223,14 @@ readstr(const char *fmt, ...)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ea_empty(struct ether_addr *ea)
|
||||||
|
{
|
||||||
|
struct ether_addr empty = { 0 };
|
||||||
|
|
||||||
|
return !memcmp(ea, &empty, sizeof(empty));
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ea2str(struct ether_addr *ea)
|
ea2str(struct ether_addr *ea)
|
||||||
{
|
{
|
||||||
|
@ -452,9 +461,9 @@ lease_next(void)
|
||||||
char *p;
|
char *p;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
memset(&e, 0, sizeof(e));
|
|
||||||
|
|
||||||
while (lease_state.off < lease_state.num) {
|
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)) {
|
while (fgets(e.buf, sizeof(e.buf), lease_state.files[lease_state.off].fh)) {
|
||||||
if (lease_state.files[lease_state.off].odhcpd) {
|
if (lease_state.files[lease_state.off].odhcpd) {
|
||||||
strtok(e.buf, " \t\n"); /* # */
|
strtok(e.buf, " \t\n"); /* # */
|
||||||
|
@ -1185,9 +1194,8 @@ struct host_hint {
|
||||||
#define HOST_HINT_PRIO_NL 10 /* neighbor table */
|
#define HOST_HINT_PRIO_NL 10 /* neighbor table */
|
||||||
#define HOST_HINT_PRIO_ETHER 50 /* /etc/ethers */
|
#define HOST_HINT_PRIO_ETHER 50 /* /etc/ethers */
|
||||||
#define HOST_HINT_PRIO_LEASEFILE 100 /* dhcp leasefile */
|
#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_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 host_hint_addr {
|
||||||
struct avl_node avl;
|
struct avl_node avl;
|
||||||
|
@ -1538,6 +1546,9 @@ rpc_luci_get_host_hints_uci(struct reply_context *rctx)
|
||||||
lease_open();
|
lease_open();
|
||||||
|
|
||||||
while ((lease = lease_next()) != NULL) {
|
while ((lease = lease_next()) != NULL) {
|
||||||
|
if (ea_empty(&lease->mac))
|
||||||
|
continue;
|
||||||
|
|
||||||
hint = rpc_luci_get_host_hint(rctx, &lease->mac);
|
hint = rpc_luci_get_host_hint(rctx, &lease->mac);
|
||||||
|
|
||||||
if (!hint)
|
if (!hint)
|
||||||
|
@ -1564,8 +1575,6 @@ out:
|
||||||
static void
|
static void
|
||||||
rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx)
|
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 ifaddrs *ifaddr, *ifa;
|
||||||
struct sockaddr_ll *sll;
|
struct sockaddr_ll *sll;
|
||||||
struct avl_tree devices;
|
struct avl_tree devices;
|
||||||
|
@ -1621,8 +1630,8 @@ rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx)
|
||||||
freeifaddrs(ifaddr);
|
freeifaddrs(ifaddr);
|
||||||
|
|
||||||
avl_remove_all_elements(&devices, device, avl, nextdevice) {
|
avl_remove_all_elements(&devices, device, avl, nextdevice) {
|
||||||
if (memcmp(&device->ea, &empty_ea, sizeof(empty_ea)) &&
|
if (!ea_empty(&device->ea) &&
|
||||||
(memcmp(&device->in6, &empty_in6, sizeof(empty_in6)) ||
|
(!IN6_IS_ADDR_UNSPECIFIED(&device->in6) ||
|
||||||
device->in.s_addr != 0)) {
|
device->in.s_addr != 0)) {
|
||||||
hint = rpc_luci_get_host_hint(rctx, &device->ea);
|
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)
|
if (device->in.s_addr != 0)
|
||||||
rpc_luci_add_host_hint_ipaddr(hint, HOST_HINT_PRIO_IFADDRS, &device->in);
|
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);
|
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 blob_attr *msg)
|
||||||
{
|
{
|
||||||
struct reply_context *rctx = req->priv;
|
struct reply_context *rctx = req->priv;
|
||||||
|
struct host_hint_addr *addr;
|
||||||
struct host_hint *hint;
|
struct host_hint *hint;
|
||||||
struct blob_attr *cur;
|
struct blob_attr *cur;
|
||||||
struct in6_addr in6;
|
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) {
|
if (inet_pton(AF_INET6, blobmsg_name(cur), &in6) == 1) {
|
||||||
avl_for_each_element(&rctx->avl, hint, avl) {
|
avl_for_each_element(&rctx->avl, hint, avl) {
|
||||||
rpc_luci_add_host_hint_ip6addr(hint, HOST_HINT_PRIO_RRDNS, &in6);
|
avl_for_each_element(&hint->ip6addrs, addr, avl) {
|
||||||
if (!avl_is_empty(&hint->ip6addrs)) {
|
if (!memcmp(&addr->addr.in6, &in6, sizeof(in6))) {
|
||||||
if (hint->hostname)
|
|
||||||
free(hint->hostname);
|
free(hint->hostname);
|
||||||
|
hint->hostname = strdup(blobmsg_get_string(cur));
|
||||||
hint->hostname = strdup(blobmsg_get_string(cur));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (inet_pton(AF_INET, blobmsg_name(cur), &in) == 1) {
|
else if (inet_pton(AF_INET, blobmsg_name(cur), &in) == 1) {
|
||||||
avl_for_each_element(&rctx->avl, hint, avl) {
|
avl_for_each_element(&rctx->avl, hint, avl) {
|
||||||
rpc_luci_add_host_hint_ipaddr(hint, HOST_HINT_PRIO_RRDNS, &in);
|
avl_for_each_element(&hint->ipaddrs, addr, avl) {
|
||||||
if (!avl_is_empty(&hint->ipaddrs)) {
|
if (addr->addr.in.s_addr == in.s_addr) {
|
||||||
if (hint->hostname)
|
|
||||||
free(hint->hostname);
|
free(hint->hostname);
|
||||||
|
hint->hostname = strdup(blobmsg_get_string(cur));
|
||||||
hint->hostname = strdup(blobmsg_get_string(cur));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1691,7 +1699,6 @@ rpc_luci_get_host_hints_rrdns_cb(struct ubus_request *req, int type,
|
||||||
static void
|
static void
|
||||||
rpc_luci_get_host_hints_rrdns(struct reply_context *rctx)
|
rpc_luci_get_host_hints_rrdns(struct reply_context *rctx)
|
||||||
{
|
{
|
||||||
struct in6_addr empty_in6 = {};
|
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[INET6_ADDRSTRLEN];
|
||||||
struct blob_buf req = {};
|
struct blob_buf req = {};
|
||||||
struct host_hint *hint;
|
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) {
|
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));
|
inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf));
|
||||||
blobmsg_add_string(&req, NULL, buf);
|
blobmsg_add_string(&req, NULL, buf);
|
||||||
n++;
|
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;
|
struct { struct avl_node avl; } *e, *next;
|
||||||
char s[INET6_ADDRSTRLEN], *p;
|
char s[INET6_ADDRSTRLEN], *p;
|
||||||
struct ether_addr empty = {};
|
|
||||||
struct lease_entry *lease;
|
struct lease_entry *lease;
|
||||||
struct avl_tree avl;
|
struct avl_tree avl;
|
||||||
void *o, *a;
|
void *o, *a;
|
||||||
|
@ -1857,7 +1863,7 @@ rpc_luci_get_duid_hints(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
if (lease->hostname)
|
if (lease->hostname)
|
||||||
blobmsg_add_string(&blob, "hostname", 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_add_string(&blob, "macaddr", ea2str(&lease->mac));
|
||||||
|
|
||||||
blobmsg_close_table(&blob, o);
|
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 *msg)
|
||||||
{
|
{
|
||||||
struct blob_attr *tb[__RPC_L_MAX];
|
struct blob_attr *tb[__RPC_L_MAX];
|
||||||
struct ether_addr emptymac = {};
|
|
||||||
struct lease_entry *lease;
|
struct lease_entry *lease;
|
||||||
char s[INET6_ADDRSTRLEN];
|
char s[INET6_ADDRSTRLEN];
|
||||||
int af, family = 0;
|
int af, family = 0;
|
||||||
|
@ -1958,7 +1963,7 @@ rpc_luci_get_dhcp_leases(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
if (lease->hostname)
|
if (lease->hostname)
|
||||||
blobmsg_add_string(&blob, "hostname", 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));
|
blobmsg_add_string(&blob, "macaddr", ea2str(&lease->mac));
|
||||||
|
|
||||||
if (lease->duid)
|
if (lease->duid)
|
||||||
|
|
Loading…
Reference in a new issue