From 6992f37e080ef1a648bb1c1eac7870a7e26869da Mon Sep 17 00:00:00 2001
From: Anjan Chanda <anjan.chanda@iopsys.eu>
Date: Wed, 5 May 2021 21:21:12 +0200
Subject: [PATCH] record al-macaddress in received cmdu_buff and notify

---
 src/cmdu.h                |  3 ++-
 src/cmdu_input.c          | 31 +++++++++++++++++++--
 src/cmdu_output.c         | 57 ++++++++++++++++++++++++---------------
 src/extensions/map/map2.c |  3 +++
 src/i1905.h               |  4 +++
 src/i1905_dm.c            | 18 +++++++++++++
 6 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/src/cmdu.h b/src/cmdu.h
index 47673cc1..9146775d 100644
--- a/src/cmdu.h
+++ b/src/cmdu.h
@@ -81,7 +81,8 @@ struct cmdu_buff {
 	uint8_t *end;
 	uint8_t dev_macaddr[6];
 	char dev_ifname[16];
-	uint8_t origin[6];
+	uint8_t origin[6];	/* source address of sender */
+	uint8_t aladdr[6];	/* AL address of sender (when available) */
 	uint32_t flags;
 	uint16_t datalen;
 	uint16_t len;
diff --git a/src/cmdu_input.c b/src/cmdu_input.c
index 4706e689..c030452a 100644
--- a/src/cmdu_input.c
+++ b/src/cmdu_input.c
@@ -185,6 +185,10 @@ int i1905_handle_topology_query(const char *ifname, uint8_t *from,
 	struct i1905_interface *iface;
 
 
+	//TODO: processed by extensions; use meaningful flag
+	if (rxf->flags == 1)
+		return 0;
+
 	iface = i1905_ifname_to_interface(priv, ifname);
 	if (!iface) {
 		fprintf(stderr, "Error! ifname_to_interface(%s)\n", ifname);
@@ -296,6 +300,11 @@ int i1905_handle_link_metric_query(const char *ifname, uint8_t *from,
 	int ret;
 
 
+
+	//TODO: processed by extensions; use meaningful flag
+	if (rxf->flags == 1)
+		return 0;
+
 	cmdu_parse_tlvs(rxf, tv, a_policy, 1);
 
 	if (!tv[0][0]) {
@@ -954,6 +963,10 @@ int i1905_handle_higherlayer_query(const char *ifname, uint8_t *from,
 	struct i1905_interface *iface;
 
 
+	//TODO: processed by extensions; use meaningful flag
+	if (rxf->flags == 1)
+		return 0;
+
 	iface = i1905_ifname_to_interface(priv, ifname);
 	if (!iface) {
 		fprintf(stderr, "Error! ifname_to_interface(%s)\n", ifname);
@@ -1111,8 +1124,22 @@ int i1905_process_cmdu(struct i1905_private *priv, struct cmdu_buff *rxf)
 	mid = cmdu_get_mid(rxf);
 	src = rxf->head + 6;
 
-	fprintf(stderr, "%s: src = " MACFMT ", type = %s (mid = %hu)\n",
-		__func__, MAC2STR(src), cmdu_type2str(type), mid);
+	/* update with origin's aladdr if available */
+	if (rxf->dev_ifname) {
+		struct i1905_neighbor_interface *peer = NULL;
+		struct i1905_interface *iface = NULL;
+
+		iface = i1905_ifname_to_interface(priv, rxf->dev_ifname);
+		if (iface) {
+			peer = i1905_dm_peer_lookup(iface, src);
+			if (peer && peer->aladdr)
+				memcpy(rxf->aladdr, peer->aladdr, 6);
+		}
+	}
+
+
+	dbg("%s: src = " MACFMT ", aladdr = " MACFMT " type = %s (mid = %hu)\n",
+	    __func__, MAC2STR(src), MAC2STR(rxf->aladdr), cmdu_type2str(type), mid);
 
 
 	res = extmodule_maybe_process_cmdu(&priv->extlist, rxf);
diff --git a/src/cmdu_output.c b/src/cmdu_output.c
index 6eeb7359..fd57f505 100644
--- a/src/cmdu_output.c
+++ b/src/cmdu_output.c
@@ -381,10 +381,12 @@ struct cmdu_buff *i1905_build_topology_response(struct i1905_interface *iface)
 
 	/* append non-1905 neighbors */
 	list_for_each_entry(lif, &self->iflist, list) {
-		dbg("%s: Adding non-1905nbr for iface " MACFMT "\n", __func__,
-		    MAC2STR(lif->macaddr));
+		int rem = 256;
 
-		t = cmdu_reserve_tlv(resp, 256);
+		dbg("%s: Adding non-1905nbr for iface %s (" MACFMT ")\n", __func__,
+		    lif->ifname, MAC2STR(lif->macaddr));
+
+		t = cmdu_reserve_tlv(resp, rem);
 		if (!t) {
 			cmdu_free(resp);
 			return NULL;
@@ -395,27 +397,34 @@ struct cmdu_buff *i1905_build_topology_response(struct i1905_interface *iface)
 		non1905 = (struct tlv_non1905_neighbor *)t->data;
 		memcpy(non1905->local_macaddr, lif->macaddr, 6);
 		i = 0;
+		rem -= 6;
 
 		list_for_each_entry(nnbr, &lif->non1905_nbrlist, list) {
 			struct non1905_neighbor *non = &non1905->non1905_nbr[i++];
 
-			t->len += sizeof(*non);
-			memcpy(non->macaddr, nnbr->macaddr, 6);
-			ret = cmdu_put_tlv(resp, t);
-			if (ret) {
-				fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__);
-				cmdu_free(resp);
-				return NULL;
+			if (rem >= sizeof(*non)) {
+				t->len += sizeof(*non);
+				memcpy(non->macaddr, nnbr->macaddr, 6);
+				rem -= sizeof(*non);
 			}
 		}
+
+		ret = cmdu_put_tlv(resp, t);
+		if (ret) {
+			fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__);
+			cmdu_free(resp);
+			return NULL;
+		}
 	}
 
 	/* append 1905 neighbors */
 	list_for_each_entry(lif, &self->iflist, list) {
-		dbg("%s: Adding 1905nbr for iface " MACFMT "\n", __func__,
-		    MAC2STR(lif->macaddr));
+		int rem = 256;
 
-		t = cmdu_reserve_tlv(resp, 256);
+		dbg("%s: Adding 1905nbr for iface %s (" MACFMT ")\n", __func__,
+		    lif->ifname, MAC2STR(lif->macaddr));
+
+		t = cmdu_reserve_tlv(resp, rem);
 		if (!t) {
 			cmdu_free(resp);
 			return NULL;
@@ -426,21 +435,25 @@ struct cmdu_buff *i1905_build_topology_response(struct i1905_interface *iface)
 		nbrs = (struct tlv_1905neighbor *)t->data;
 		memcpy(nbrs->local_macaddr, lif->macaddr, 6);
 		i = 0;
+		rem -= 6;
 
 		list_for_each_entry(nif, &lif->nbriflist, list) {
 			struct i1905_neighbor *nbr = &nbrs->nbr[i++];
 
-			t->len += sizeof(*nbr);
-			memcpy(nbr->aladdr, nif->aladdr, 6);
-			nbr->has_bridge = nif->has_bridge ? 0x8 : 0;
-
-			ret = cmdu_put_tlv(resp, t);
-			if (ret) {
-				fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__);
-				cmdu_free(resp);
-				return NULL;
+			if (rem >= sizeof(*nbr)) {
+				t->len += sizeof(*nbr);
+				memcpy(nbr->aladdr, nif->aladdr, 6);
+				nbr->has_bridge = nif->has_bridge ? 0x8 : 0;
+				rem -= sizeof(*nbr);
 			}
 		}
+
+		ret = cmdu_put_tlv(resp, t);
+		if (ret) {
+			fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__);
+			cmdu_free(resp);
+			return NULL;
+		}
 	}
 
 	cmdu_put_eom(resp);
diff --git a/src/extensions/map/map2.c b/src/extensions/map/map2.c
index d798983c..2d46019c 100644
--- a/src/extensions/map/map2.c
+++ b/src/extensions/map/map2.c
@@ -57,6 +57,7 @@ int map_notify_clients(void *priv, struct cmdu_buff *frm)
 	uint16_t type = cmdu_get_type(frm);
 	uint16_t mid = cmdu_get_mid(frm);
 	char originstr[18] = {0};
+	char alstr[18] = {0};
 	int ret = 0;
 
 
@@ -76,6 +77,8 @@ int map_notify_clients(void *priv, struct cmdu_buff *frm)
 		blobmsg_add_string(&bb, "ifname", frm->dev_ifname);
 		hwaddr_ntoa(frm->origin, originstr);
 		blobmsg_add_string(&bb, "source", originstr);
+		hwaddr_ntoa(frm->aladdr, alstr);
+		blobmsg_add_string(&bb, "origin", alstr);
 		blobmsg_add_string(&bb, "cmdu", frmbuffer);
 		ret = ubus_notify(p->ctx, &m->notify, "i1905.cmdu", bb.head, -1);
 		if (ret)
diff --git a/src/i1905.h b/src/i1905.h
index 75993b32..cf3d7af5 100644
--- a/src/i1905.h
+++ b/src/i1905.h
@@ -232,4 +232,8 @@ struct i1905_device *i1905_dm_neighbor_lookup(struct i1905_interface *iface,
 struct i1905_interface *i1905_dm_neighbor_interface_lookup(struct i1905_device *rdev,
 							   uint8_t *ifmacaddr);
 
+
+struct i1905_neighbor_interface *i1905_dm_peer_lookup(struct i1905_interface *iface,
+						      uint8_t *macaddr);
+
 #endif /* I1905_H */
diff --git a/src/i1905_dm.c b/src/i1905_dm.c
index bdd0de9e..fd9d4136 100644
--- a/src/i1905_dm.c
+++ b/src/i1905_dm.c
@@ -159,6 +159,22 @@ struct i1905_neighbor_interface *i1905_dm_interface_peer_lookup(struct i1905_int
 	return NULL;
 }
 
+struct i1905_neighbor_interface *i1905_dm_peer_lookup(struct i1905_interface *iface,
+						      uint8_t *macaddr)
+{
+	struct i1905_neighbor_interface *ifpeer = NULL;
+
+	list_for_each_entry(ifpeer, &iface->nbriflist, list) {
+		if (hwaddr_equal(ifpeer->macaddr, macaddr) ||
+		    hwaddr_equal(ifpeer->aladdr, macaddr)) {
+
+			return ifpeer;
+		}
+	}
+
+	return NULL;
+}
+
 struct i1905_interface *i1905_dm_neighbor_interface_create(void)
 {
 	struct i1905_interface *rif;
@@ -821,6 +837,8 @@ int i1905_dm_neighbor_discovered(struct i1905_interface *iface, uint8_t *aladdr,
 		if (!if_peer) {
 			if_peer = i1905_dm_interface_peer_create();
 			if (if_peer) {
+				fprintf(stderr, "+++ NBR aladdr = " MACFMT " if-macaddr = " MACFMT "\n",
+					MAC2STR(aladdr), MAC2STR(macaddr));
 				memcpy(if_peer->macaddr, macaddr, 6);
 				memcpy(if_peer->aladdr, aladdr, 6);
 				/* other fields like media, genphy and metric
-- 
GitLab