diff --git a/src/history.c b/src/history.c index 242a23b8b5e760ca7584f696a998d5061e5969c8..a3ab57f78bf62829ea97e3b8f1df384266b8076d 100644 --- a/src/history.c +++ b/src/history.c @@ -30,6 +30,7 @@ int neigh_history_add_entry_json(struct json_object *jarray, { struct json_object *e, *es; char macstr[18] = {0}; + char ipstr[128] = {0}; int remtime; if (!jarray || json_object_get_type(jarray) != json_type_array) @@ -37,11 +38,14 @@ int neigh_history_add_entry_json(struct json_object *jarray, hwaddr_ntoa(he->macaddr, macstr); remtime = timer_remaining_ms(&he->delete_timer) / 1000; + inet_ntop(he->ip.family, &he->ip.addr, ipstr, sizeof(ipstr)); e = json_object_new_object(); es = json_object_new_object(); json_object_object_add(e, "macaddress", json_object_new_string(macstr)); json_object_object_add(e, "hostname", json_object_new_string(he->hostname)); + json_object_object_add(e, "ipaddr", json_object_new_string(ipstr)); + json_object_object_add(e, "device", json_object_new_string(he->ifname)); json_object_object_add(e, "first_seen", json_object_new_int(he->createtime)); json_object_object_add(e, "last_seen", json_object_new_int(he->lastseen)); json_object_object_add(e, "ageout", json_object_new_int(remtime)); @@ -150,6 +154,7 @@ int neigh_history_load_from_json_file(void *priv, const char *file) struct neigh_history_entry he = {0}; struct json_object *je, *je_ws; char macstr[18] = {0}; + char ipstr[128] = {0}; int createtime = 0; int lastseen = 0; int timeout = 0; @@ -162,6 +167,8 @@ int neigh_history_load_from_json_file(void *priv, const char *file) return -1; } json_get_key_value(je, "hostname", he.hostname); + json_get_key_value(je, "ipaddr", ipstr); + json_get_key_value(je, "device", he.ifname); json_get_key_value(je, "first_seen", &createtime); json_get_key_value(je, "last_seen", &lastseen); json_get_key_value(je, "ageout", &timeout); @@ -172,6 +179,14 @@ int neigh_history_load_from_json_file(void *priv, const char *file) json_get_key_value(je_ws, "rx_packets", &he.ws.dl_packets); json_get_key_value(je_ws, "rx_bytes", &he.ws.dl_bytes); + if (strlen(ipstr) == 16) { + if (inet_pton(AF_INET, ipstr, &he.ip.addr.ip4) == 1) + he.ip.family = AF_INET; + } else { + if (inet_pton(AF_INET6, ipstr, &he.ip.addr.ip6) == 1) + he.ip.family = AF_INET6; + } + he.createtime = createtime; he.lastseen = lastseen; he.timeout = timeout; @@ -179,6 +194,7 @@ int neigh_history_load_from_json_file(void *priv, const char *file) dbg("macstr = '%s' (macaddr = " MACFMT" )\n", macstr, MAC2STR(he.macaddr)); dbg("hostname = %s\n", he.hostname); + dbg("device = %s\n", he.ifname); dbg("firstseen = %jd\n", (intmax_t)he.createtime); dbg("lastseen = %jd\n", (intmax_t)he.lastseen); dbg("remtime = %u\n", he.timeout); diff --git a/src/neigh.c b/src/neigh.c index 1d42f3c93e25b85072d6c343d52fb2e1ebd7bcbf..0ba1a82fa5945c71eef6c35de1ae82dd26e84053 100644 --- a/src/neigh.c +++ b/src/neigh.c @@ -181,9 +181,17 @@ int neigh_history_enqueue(void *priv, struct neigh_entry *n, uint32_t timeout) if (n->type == NEIGH_TYPE_WIFI) he->type = n->type; + if (n->ipv4.family == AF_INET || n->ipv4.family == AF_INET6) + memcpy(&he->ip, &n->ipv4, sizeof(struct ip_address)); + if (n->hostname && n->hostname[0] != '\0') strncpy(he->hostname, n->hostname, 255); + if (n->ifname[0] != '\0') { + memset(he->ifname, 0, 16); + strncpy(he->ifname, n->ifname, 16); + } + dbg("Update history stats: +ul-pkts = %ju, +dl-pkts = %ju\n", (uintmax_t)n->ws.ul_packets, (uintmax_t)n->ws.dl_packets); @@ -201,6 +209,14 @@ int neigh_history_enqueue(void *priv, struct neigh_entry *n, uint32_t timeout) if (he) { int idx = neigh_hash(n->macaddr); + if (n->ipv4.family == AF_INET || n->ipv4.family == AF_INET6) + memcpy(&he->ip, &n->ipv4, sizeof(struct ip_address)); + + if (n->ifname[0] != '\0') { + memset(he->ifname, 0, 16); + strncpy(he->ifname, n->ifname, 16); + } + /* stop ageing history as neigh is live */ he->timeout = timeout; timer_del(&he->delete_timer); @@ -241,6 +257,13 @@ int neigh_history_entry_add(void *priv, struct neigh_history_entry *he) return -1; e->alive = false; /* because no neigh entry yet for this */ + + + if (he->ip.family == AF_INET || he->ip.family == AF_INET6) + memcpy(&e->ip, &he->ip, sizeof(struct ip_address)); + + strncpy(e->ifname, he->ifname, 16); + e->ws.ul_packets = he->ws.ul_packets; e->ws.ul_bytes = he->ws.ul_bytes; e->ws.dl_packets = he->ws.dl_packets; diff --git a/src/neigh.h b/src/neigh.h index 6a9296b9f8f915d415fc89bb35fdeeb9f9ba4d0f..c124d61165817ead110fedec458745ac9490b9fe 100644 --- a/src/neigh.h +++ b/src/neigh.h @@ -95,9 +95,13 @@ struct neigh_entry { struct neigh_history_entry { time_t createtime; time_t lastseen; + time_t lastchange; bool alive; uint8_t macaddr[6]; char hostname[256]; + char ifname[16]; + struct ip_address ip; + int ipv4_type_dhcp; enum neigh_type type; struct neigh_wanstats ws; uint32_t timeout; /* in secs */ diff --git a/src/netlink.c b/src/netlink.c index 048e0fc71eb85606ff2b2925ee8713456c076ffa..7710c926c8a7ff87cc9d363fa48afc68ca4a3ece 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -207,6 +207,12 @@ static int hostmngr_handle_neigh_tbl_change(struct hostmngr_private *priv, bool new = neigh_enqueue(&priv->neigh_q, macaddr, state, ifname, NEIGH_TYPE_UNKNOWN, ip, NEIGH_AGEOUT_DEFAULT, NULL); + /* update bridge port_nos on which the hosts are last seen */ + if (if_isbridge(ifname)) { + dbg("%s: update brport number\n", __func__); + hostmngr_update_neigh_brport(priv, ifname); + } + if (new) { /* new neigh added */ hostmngr_get_neigh_hostname(&priv->neigh_q, macaddr); @@ -215,11 +221,6 @@ static int hostmngr_handle_neigh_tbl_change(struct hostmngr_private *priv, bool neigh_history_enqueue(priv, new, NEIGH_HISTORY_AGEOUT_DEFAULT); } - /* update bridge port_nos on which the hosts are last seen */ - if (if_isbridge(ifname)) { - dbg("%s: update brport number\n", __func__); - hostmngr_update_neigh_brport(priv, ifname); - } #if 1 //def NEIGH_DEBUG if (priv->neigh_q.pending_cnt > 0) { diff --git a/src/ubus.c b/src/ubus.c index 080f1f62b6f402e594969e8ca3490f1499073bb2..227fa1ff78003ec6dbe5649635b3ca734a9a6a25 100644 --- a/src/ubus.c +++ b/src/ubus.c @@ -474,11 +474,11 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj, hlist_for_each_entry(e, &q->table[i], hlist) { struct ip_address_entry *ipv4, *ipv6; - long leasetime_rem; char statestr[128] = {0}; - char ip4buf[32] = {0}; + char ipstr[128] = {0}; char *ifname = NULL; char tbuf[64] = {0}; + long leasetime_rem; char *net = NULL; uint16_t brport; struct tm *t; @@ -490,17 +490,18 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj, neigh_update_ip_entry_stats(p, &e->ipv4, e); aa = blobmsg_open_table(&bb, ""); + + hwaddr_ntoa(e->macaddr, macstr); + blobmsg_add_string(&bb, "macaddr", macstr); + blobmsg_add_string(&bb, "hostname", e->hostname); blobmsg_add_u8(&bb, "active", e->unreachable ? false : true); t = localtime(&e->lastchange); strftime(tbuf, sizeof(tbuf), "%Y-%m-%dT%H:%M:%S", t); blobmsg_add_string(&bb, "active_last_change", tbuf); - hwaddr_ntoa(e->macaddr, macstr); - blobmsg_add_string(&bb, "macaddr", macstr); - blobmsg_add_string(&bb, "hostname", e->hostname); - inet_ntop(e->ipv4.family, &e->ipv4.addr, ip4buf, sizeof(ip4buf)); - blobmsg_add_string(&bb, "ipaddr", ip4buf); + inet_ntop(e->ipv4.family, &e->ipv4.addr, ipstr, sizeof(ipstr)); + blobmsg_add_string(&bb, "ipaddr", ipstr); leasetime_rem = e->leasetime ? e->leasetime - (unsigned long)time(NULL) : 0; if (leasetime_rem < 0) { leasetime_rem = 0; @@ -563,6 +564,60 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_close_table(&bb, aa); } } + + /* also show history entries that are not live now */ + for (i = 0; i < NEIGH_ENTRIES_MAX; i++) { + struct neigh_history_entry *he = NULL; + char macstr[18] = {0}; + + if (hlist_empty(&q->history[i])) + continue; + + hlist_for_each_entry(he, &q->history[i], hlist) { + char ipstr[128] = {0}; + char tbuf[64] = {0}; + char *net = NULL; + struct tm *t; + void *wt; + + + if (he->alive) + continue; + + aa = blobmsg_open_table(&bb, ""); + hwaddr_ntoa(he->macaddr, macstr); + blobmsg_add_string(&bb, "macaddress", macstr); + blobmsg_add_string(&bb, "hostname", he->hostname); + + t = localtime(&he->lastchange); + strftime(tbuf, sizeof(tbuf), "%Y-%m-%dT%H:%M:%S", t); + blobmsg_add_string(&bb, "active_last_change", tbuf); + + inet_ntop(he->ip.family, &he->ip.addr, ipstr, sizeof(ipstr)); + blobmsg_add_string(&bb, "ipaddr", ipstr); + + blobmsg_add_string(&bb, "address_source", he->ipv4_type_dhcp ? "DHCP": "Static"); + blobmsg_add_u32(&bb, "lease_time_remaining", 0); + blobmsg_add_string(&bb, "interface_type", interface_type2str(he->type)); + blobmsg_add_string(&bb, "link_macaddr", ""); //TODO + + blobmsg_add_string(&bb, "device", he->ifname); + + net = hostmngr_ifname_to_network(p, he->ifname); + blobmsg_add_string(&bb, "network", net ? net : ""); + + blobmsg_add_u64(&bb, "active_connections", 0); + + wt = blobmsg_open_table(&bb, "stats"); + blobmsg_add_u64(&bb, "tx_packets", he->ws.ul_packets); + blobmsg_add_u64(&bb, "tx_bytes", he->ws.ul_bytes); + blobmsg_add_u64(&bb, "rx_packets", he->ws.dl_packets); + blobmsg_add_u64(&bb, "rx_bytes", he->ws.dl_bytes); + blobmsg_close_table(&bb, wt); + + blobmsg_close_table(&bb, aa); + } + } blobmsg_close_array(&bb, a); ubus_send_reply(ctx, req, bb.head);