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);