mirror of
https://github.com/outbackdingo/udevmand.git
synced 2026-01-27 10:20:51 +00:00
135 lines
3.0 KiB
C
135 lines
3.0 KiB
C
#include "udevmand.h"
|
|
|
|
int
|
|
avl_mac_cmp(const void *k1, const void *k2, void *ptr)
|
|
{
|
|
return memcmp(k1, k2, ETH_ALEN);
|
|
}
|
|
|
|
struct avl_tree mac_tree = AVL_TREE_INIT(mac_tree, avl_mac_cmp, false, NULL);
|
|
|
|
struct mac*
|
|
mac_find(uint8_t *addr)
|
|
{
|
|
struct mac *mac;
|
|
uint8_t *addr_buf;
|
|
|
|
mac = avl_find_element(&mac_tree, addr, mac, avl);
|
|
|
|
if (mac)
|
|
return mac;
|
|
|
|
mac = calloc_a(sizeof(struct mac), &addr_buf, 6);
|
|
if (!mac)
|
|
return NULL;
|
|
mac->addr = memcpy(addr_buf, addr, ETH_ALEN);
|
|
mac->avl.key = mac->addr;
|
|
mac->ethers = NULL;
|
|
*mac->interface = '\0';
|
|
INIT_LIST_HEAD(&mac->neigh4);
|
|
INIT_LIST_HEAD(&mac->neigh6);
|
|
INIT_LIST_HEAD(&mac->wifi);
|
|
INIT_LIST_HEAD(&mac->dhcpv4);
|
|
INIT_LIST_HEAD(&mac->bridge_mac);
|
|
|
|
avl_insert(&mac_tree, &mac->avl);
|
|
ULOG_INFO("new mac "MAC_FMT"\n", MAC_VAR(mac->addr));
|
|
|
|
return mac;
|
|
}
|
|
|
|
void
|
|
mac_update(struct mac *mac, char *iface)
|
|
{
|
|
char *interface = interface_resolve(iface);
|
|
|
|
if (iface && *iface)
|
|
strncpy(mac->interface, interface, sizeof(mac->interface));
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &mac->ts);
|
|
}
|
|
|
|
void
|
|
mac_dump(struct mac *mac, int interface)
|
|
{
|
|
struct timespec ts;
|
|
time_t last_seen;
|
|
char buf[18];
|
|
void *c, *d;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
last_seen = ts.tv_sec - mac->ts.tv_sec;
|
|
snprintf(buf, sizeof(buf), MAC_FMT, MAC_VAR(mac->addr));
|
|
c = blobmsg_open_table(&b, buf);
|
|
if (interface && *mac->interface)
|
|
blobmsg_add_string(&b, "interface", mac->interface);
|
|
if (mac->ethers)
|
|
blobmsg_add_string(&b, "ethers", mac->ethers);
|
|
if (last_seen < 5 * 60)
|
|
blobmsg_add_u32(&b, "last_seen", last_seen);
|
|
else
|
|
blobmsg_add_u8(&b, "offline", 1);
|
|
if (!list_empty(&mac->neigh4)) {
|
|
struct neigh *neigh;
|
|
|
|
d = blobmsg_open_array(&b, "ipv4");
|
|
list_for_each_entry(neigh, &mac->neigh4, list)
|
|
blobmsg_add_ipv4(&b, NULL, neigh->ip);
|
|
blobmsg_close_array(&b, d);
|
|
}
|
|
|
|
if (!list_empty(&mac->neigh6)) {
|
|
struct neigh *neigh;
|
|
|
|
d = blobmsg_open_array(&b, "ipv6");
|
|
list_for_each_entry(neigh, &mac->neigh6, list)
|
|
blobmsg_add_ipv6(&b, NULL, neigh->ip);
|
|
blobmsg_close_array(&b, d);
|
|
}
|
|
|
|
if (!list_empty(&mac->wifi)) {
|
|
struct wifi_station *sta;
|
|
|
|
sta = list_first_entry(&mac->wifi, struct wifi_station, mac);
|
|
blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "wifi",
|
|
blobmsg_data(sta->info), blobmsg_data_len(sta->info));
|
|
}
|
|
|
|
if (!list_empty(&mac->dhcpv4)) {
|
|
struct dhcpv4 *dhcpv4;
|
|
|
|
d = blobmsg_open_array(&b, "dhcpv4");
|
|
list_for_each_entry(dhcpv4, &mac->dhcpv4, mac) {
|
|
blobmsg_add_ipv4(&b, NULL, dhcpv4->ip);
|
|
if (strlen(dhcpv4->name) > 0)
|
|
blobmsg_add_string(&b, NULL, dhcpv4->name);
|
|
break;
|
|
}
|
|
blobmsg_close_array(&b, d);
|
|
}
|
|
|
|
if (!list_empty(&mac->bridge_mac)) {
|
|
struct bridge_mac *bridge_mac;
|
|
|
|
d = blobmsg_open_array(&b, "fdb");
|
|
list_for_each_entry(bridge_mac, &mac->bridge_mac, mac)
|
|
blobmsg_add_string(&b, NULL, bridge_mac->ifname);
|
|
blobmsg_close_array(&b, d);
|
|
}
|
|
|
|
blobmsg_close_array(&b, c);
|
|
}
|
|
|
|
int
|
|
mac_dump_all(void)
|
|
{
|
|
struct mac *mac;
|
|
|
|
blob_buf_init(&b, 0);
|
|
|
|
avl_for_each_element(&mac_tree, mac, avl)
|
|
mac_dump(mac, 1);
|
|
return 0;
|
|
}
|