From 7561f11b8b7eaee554f5c047b02a292099e92564 Mon Sep 17 00:00:00 2001
From: Anjan Chanda <anjan.chanda@iopsys.eu>
Date: Wed, 6 Sep 2023 14:47:54 +0200
Subject: [PATCH] update link macaddress and link mediatype of 1905 host

---
 src/hostmngr.c |  2 ++
 src/hostmngr.h |  2 ++
 src/neigh.c    | 32 +++++++++++++++++++++++++
 src/neigh.h    |  5 +++-
 src/ubus.c     | 63 +++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/src/hostmngr.c b/src/hostmngr.c
index 659cc5e..22700c4 100644
--- a/src/hostmngr.c
+++ b/src/hostmngr.c
@@ -693,6 +693,7 @@ static void hostmngr_periodic_refresh(atimer_t *t)
 {
 	struct hostmngr_private *p = container_of(t, struct hostmngr_private, refreshtimer);
 
+	hostmngr_get_1905_aladdr(p);
 	hostmngr_get_1905_topology(p);
 	timer_set(t, 11000);
 }
@@ -726,6 +727,7 @@ int hostmngr_init_private(struct hostmngr_private *priv, void *useropts)
 	hostmngr_exclude_interfaces(priv, useropts);
 	hostmngr_init_interface_private(priv);
 	hostmngr_get_interface_network(priv);
+	hostmngr_get_1905_aladdr(priv);
 
 	neigh_queue_init(&priv->neigh_q);
 
diff --git a/src/hostmngr.h b/src/hostmngr.h
index 05f7506..4075896 100644
--- a/src/hostmngr.h
+++ b/src/hostmngr.h
@@ -280,6 +280,7 @@ struct hostmngr_private {
 	bool use_ieee1905;
 	uint32_t i1905;
 	uint32_t i1905_topology;
+	uint8_t ieee1905id[6];
 
 	struct ubus_context *bus;
 	struct ubus_object obj;
@@ -307,6 +308,7 @@ void hostmngr_unregister_nlevents(struct hostmngr_private *priv);
 
 uint32_t lookup_object(void *bus, const char *objname);
 int hostmngr_get_1905_topology(struct hostmngr_private *p);
+int hostmngr_get_1905_aladdr(struct hostmngr_private *p);
 int hostmngr_get_interface_network(struct hostmngr_private *priv);
 int hostmngr_publish_object(struct hostmngr_private *p, const char *objname);
 int hostmngr_remove_object(struct hostmngr_private *p);
diff --git a/src/neigh.c b/src/neigh.c
index 758e584..e30ffb7 100644
--- a/src/neigh.c
+++ b/src/neigh.c
@@ -897,6 +897,38 @@ int neigh_set_1905(void *nq, uint8_t *macaddr, uint8_t val)
 	return 0;
 }
 
+//TODO:
+int neigh_set_1905_linkaddr(void *nq, uint8_t *aladdr, uint8_t *linkaddr)
+{
+	struct neigh_queue *q = (struct neigh_queue *)nq;
+	struct neigh_entry *e = NULL;
+	enum neigh_type linktype = 0;
+	struct neigh_entry *le;
+	int ret = -1;
+	int idx;
+
+
+	le = neigh_lookup(nq, linkaddr);
+	if (le)
+		linktype = le->type;
+
+	for (idx = 0; idx < NEIGH_ENTRIES_MAX; idx++) {
+		if (hlist_empty(&q->table[idx]))
+			continue;
+
+		hlist_for_each_entry(e, &q->table[idx], hlist) {
+			if (!memcmp(e->aladdr, aladdr, 6) && e->is1905_link) {
+				dbg("%s: matched neigh 1905-aladdr; update linkaddr\n", __func__);
+				memcpy(e->linkaddr, linkaddr, 6);
+				e->type = linktype;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
 int neigh_set_1905_slave(void *nq, uint8_t *macaddr, uint8_t *aladdr, uint8_t val)
 {
 	struct neigh_entry *e = NULL;
diff --git a/src/neigh.h b/src/neigh.h
index 1f8e8c2..0049e2f 100644
--- a/src/neigh.h
+++ b/src/neigh.h
@@ -67,7 +67,8 @@ struct neigh_entry {
 	uint8_t is1905;
 	uint8_t is1905_slave;		/* member interface of 1905 device */
 	uint8_t is1905_link;		/* 1905 interface forming link with nbr */
-	uint8_t aladdr[6];
+	uint8_t aladdr[6];		/* AL-address of neigh if 1905 device */
+	uint8_t linkaddr[6];		/* 1905 interface of neigh through which connected */
 	void *cookie;
 	char hostname[256];
 	struct ip_address ipv4;		/* from dhcp-lease table or neigh cache */
@@ -104,6 +105,7 @@ struct neigh_history_entry {
 	uint8_t is1905_slave;
 	uint8_t is1905_link;
 	uint8_t aladdr[6];
+	//uint8_t linkaddr[6];
 	uint8_t macaddr[6];
 	char hostname[256];
 	char ifname[16];
@@ -185,6 +187,7 @@ uint16_t neigh_get_brport(void *q, uint8_t *macaddr);
 int neigh_set_1905(void *q, uint8_t *macaddr, uint8_t val);
 int neigh_set_1905_slave(void *nq, uint8_t *macaddr, uint8_t *aladdr, uint8_t val);
 int neigh_set_1905_link(void *nq, uint8_t *macaddr, uint8_t *aladdr, uint8_t val);
+int neigh_set_1905_linkaddr(void *nq, uint8_t *aladdr, uint8_t *linkaddr);
 bool is_neigh_1905(void *q, uint8_t *macaddr);
 bool is_neigh_1905_slave(void *q, uint8_t *macaddr);
 
diff --git a/src/ubus.c b/src/ubus.c
index e884150..f3c6799 100644
--- a/src/ubus.c
+++ b/src/ubus.c
@@ -332,8 +332,11 @@ static void hostmngr_1905topology_cb(struct ubus_request *req, int type,
 
 			dbg("%s: Nbr " MACFMT "\n", __func__, MAC2STR(nbr_macaddr));
 			dbg("%s: Nif " MACFMT "\n", __func__, MAC2STR(nbr_viaaddr));
-			iter++;
 
+			if (hwaddr_equal(nbr_macaddr, priv->ieee1905id))
+				neigh_set_1905_linkaddr(&priv->neigh_q, node_aladdr, nbr_viaaddr);
+
+			iter++;
 		}
 
 		if (num_neighbor_1905 != iter) {
@@ -413,6 +416,56 @@ int hostmngr_get_1905_topology(struct hostmngr_private *p)
 	return ret;
 }
 
+static void hostmngr_1905aladdr_cb(struct ubus_request *req, int type,
+			       struct blob_attr *msg)
+{
+	const struct blobmsg_policy attrs[1] = {
+		[0] = { .name = "ieee1905id", .type = BLOBMSG_TYPE_STRING },
+	};
+	struct hostmngr_private *priv;
+	struct blob_attr *tb[1];
+	uint8_t aladdr[6] = {0};
+	char alstr[18] = {0};
+
+	if (!msg || !req->priv)
+		return;
+
+	blobmsg_parse(attrs, 1, tb, blob_data(msg), blob_len(msg));
+	if (!tb[0])
+		return;
+
+	priv = req->priv;
+	strncpy(alstr, blobmsg_data(tb[0]), sizeof(alstr) - 1);
+	if (!hwaddr_aton(alstr, aladdr)) {
+		fprintf(stderr, "%s: %d: error\n", __func__, __LINE__);
+		return;
+	}
+	memcpy(priv->ieee1905id, aladdr, 6);
+}
+
+int hostmngr_get_1905_aladdr(struct hostmngr_private *p)
+{
+	const char *objname = "ieee1905";
+	struct blob_buf bb = {0};
+	uint32_t id;
+	int ret;
+
+	id = lookup_object(p->bus, objname);
+	if (id == OBJECT_INVALID)
+		return UBUS_STATUS_OK;
+
+	blob_buf_init(&bb, 0);
+	ret = ubus_invoke(p->bus, id, "id", bb.head,
+			  hostmngr_1905aladdr_cb, p, 2000);
+	if (ret) {
+		dbg("Failed 'ieee1905 id' (ret = %s)\n",
+		    ubus_strerror(ret));
+	}
+
+	blob_buf_free(&bb);
+	return ret;
+}
+
 static void hostmngr_network_interface_dump_cb(struct ubus_request *req,
 						int mtype,
 						struct blob_attr *msg)
@@ -616,6 +669,7 @@ 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;
 			char statestr[128] = {0};
+			char linkstr[18] = {0};
 			char ipstr[128] = {0};
 			char *ifname = NULL;
 			char alstr[18] = {0};
@@ -660,12 +714,13 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj,
 			if (e->is1905_link) {
 				blobmsg_add_u8(&bb, "is1905", true);
 				hwaddr_ntoa(e->aladdr, alstr);
+				hwaddr_ntoa(e->linkaddr, linkstr);
 				blobmsg_add_string(&bb, "ieee1905id", alstr);
+				blobmsg_add_string(&bb, "link_macaddr", linkstr);
 			} else {
 				blobmsg_add_u8(&bb, "is1905", false);
 			}
 
-			blobmsg_add_string(&bb, "link_macaddr", "");	//TODO
 			rtnl_neigh_state2str(e->state, statestr, sizeof(statestr));
 			blobmsg_add_string(&bb, "ndm_state", statestr);
 			blobmsg_add_u32(&bb, "num_tcp", e->num_tcp);
@@ -729,6 +784,7 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj,
 
 		hlist_for_each_entry(he, &q->history[i], hlist) {
 			struct ip_address_entry *ipv4, *ipv6;
+			char linkstr[18] = {0};
 			char ipstr[128] = {0};
 			char alstr[18] = {0};
 			char tbuf[64] = {0};
@@ -769,11 +825,12 @@ int hostmngr_ubus_show_hosts(struct ubus_context *ctx, struct ubus_object *obj,
 			if (he->is1905_link) {
 				blobmsg_add_u8(&bb, "is1905", true);
 				hwaddr_ntoa(he->aladdr, alstr);
+				//hwaddr_ntoa(he->linkaddr, linkstr);
 				blobmsg_add_string(&bb, "ieee1905id", alstr);
+				blobmsg_add_string(&bb, "link_macaddr", linkstr);
 			} else {
 				blobmsg_add_u8(&bb, "is1905", false);
 			}
-			blobmsg_add_string(&bb, "link_macaddr", "");	//TODO
 			blobmsg_add_string(&bb, "ndm_state", "Unknown");
 			blobmsg_add_u32(&bb, "num_tcp", 0);
 			blobmsg_add_u32(&bb, "num_udp", 0);
-- 
GitLab