Thread (11 messages) 11 messages, 3 authors, 12d ago
COOLING12d

[RFC PATCH net-next v0 4/6] net: even further fix GeoNetworking

From: Simon Dietz <hidden>
Date: 2026-07-16 16:14:11
Also in: linux-wireless
Subsystem: networking [general], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

From: Simon Dietz <redacted>

Include another set of fixes, including:
- gn_find_interface improvements
- move of timer setup to gn_init
- fix for missing packets
- kfree_skb fixes
- fixed return value in gn_sendmsg
- fixed error handling near register_snap_client
- uses hlist_for_each_entry_safe
- support for NETDEV_UNREGISTER
- timer improvements

Signed-off-by: Simon Dietz <redacted>
---
 include/linux/gn_routing.h |  1 +
 net/gn/gn_prot.c           | 67 +++++++++++++++++++++++++++-----------
 net/gn/gn_routing.c        |  4 +++
 3 files changed, 53 insertions(+), 19 deletions(-)
diff --git a/include/linux/gn_routing.h b/include/linux/gn_routing.h
index 9384bbc4b288..64ccc80f5a90 100644
--- a/include/linux/gn_routing.h
+++ b/include/linux/gn_routing.h
@@ -55,6 +55,7 @@ struct loc_te {
 s64 gn_F(struct gn_coord self, struct gn_geo_scope scope);
 int gn_gxc_forward(struct gn_iface *gnif, s64 f, u8 *addr, struct gn_lpv *depv);
 
+struct gn_iface *gn_find_interface(gn_address_t addr);
 struct gn_iface *gn_find_interface_by_dev(struct net_device *dev);
 int gn_query_ll_address(gn_address_t addr, u8 *ll_address);
 int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_address);
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index 3c4e1157fbde..90ecbd67b64d 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -30,6 +30,7 @@
 
 struct datalink_proto *gn_dl;
 static const struct proto_ops gn_dgram_ops;
+static struct timer_list gn_beacon_timer;
 
 /* Handlers for the socket list. */
 
@@ -114,6 +115,9 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
 	hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
 		if (gnif->dev == dev) {
 			// Replace existing interface address
+			atomic_set(&new_gnif->local_sn,
+				   atomic_read(&gnif->local_sn));
+			memcpy(&new_gnif->pos, &gnif->pos, sizeof(gnif->pos));
 			hlist_replace_rcu(&gnif->hnode, &new_gnif->hnode);
 			spin_unlock_bh(&gn_interfaces_lock);
 			kfree_rcu(gnif, rcu);
@@ -135,12 +139,14 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
 static void gn_if_drop_device(struct net_device *dev)
 {
 	struct gn_iface *gnif;
+	struct hlist_node *tmp;
 
 	spin_lock_bh(&gn_interfaces_lock);
-	hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
+	hlist_for_each_entry_safe(gnif, tmp, &gn_interfaces, hnode) {
 		if (gnif->dev == dev) {
 			hlist_del_rcu(&gnif->hnode);
 			kfree_rcu(gnif, rcu);
+			break;
 		}
 	}
 	spin_unlock_bh(&gn_interfaces_lock);
@@ -162,7 +168,7 @@ static void gn_interfaces_clear(void)
 /*
  * find the interface to which the socketaddress is bound
  */
-static struct gn_iface *gn_find_interface(gn_address_t addr)
+struct gn_iface *gn_find_interface(gn_address_t addr)
 {
 	struct gn_iface *gnif;
 	bool found = false;
@@ -212,7 +218,7 @@ static int gn_device_event(struct notifier_block *this, unsigned long event,
 	if (dev->type != ARPHRD_ETHER)
 		return NOTIFY_DONE;
 
-	if (event == NETDEV_DOWN)
+	if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER)
 		gn_if_drop_device(dev);
 
 	return NOTIFY_DONE;
@@ -475,7 +481,7 @@ void gn_fill_sopv(struct gn_iface *gnif, struct gn_lpv *sopv, gn_address_t addr)
 
 	ktime_t tst = ktime_set(gnif->pos.tst.tv_sec, gnif->pos.tst.tv_nsec);
 	// fill empty timestamp with current timestamp
-	if (tst == 0)
+	if (tst == 0 || ktime_before(tst, ms_to_ktime(1072915232000LLU)))
 		sopv->tst = cpu_to_be32(gn_timestamp_now());
 	else
 		sopv->tst = cpu_to_be32(gn_tai_to_gn(tst));
@@ -825,7 +831,7 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
 			pr_warn("dropping packet");
 			goto drop;
 		}
-		fwd_gb_h = (struct gn_basic_header *)skb_transport_header(
+		fwd_gb_h = (struct gn_basic_header *)skb_network_header(
 			forward_skb);
 		fwd_gb_h->rhl--;
 
@@ -839,19 +845,24 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
 			break;
 		case GN_FORWARD_BUFFER:
 			pr_warn("forwarding buffers not implemented");
+			kfree_skb(forward_skb);
 			break;
 		case GN_FORWARD_DISCARD:
+			kfree_skb(forward_skb);
 			break;
 		default:
 			WARN_ONCE(1, "internal error: unexpected return value");
+			kfree_skb(forward_skb);
 			goto drop;
 		}
 	}
 
 	// Local delivery
-	if (f_value >= 0 &&
-	    gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS) {
-		goto drop;
+	if (f_value >= 0) {
+		if (gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS)
+			goto drop;
+	} else {
+		kfree_skb(skb);
 	}
 
 	return NET_RX_SUCCESS;
@@ -938,6 +949,7 @@ static int gn_process_beacon_packet(struct sk_buff *skb, const u8 *llc)
 	}
 
 	gn_ls_flush(gh->beacon_h.sopv.addr);
+	kfree_skb(skb);
 	return NET_RX_SUCCESS;
 }
 
@@ -1029,6 +1041,11 @@ static int gn_rcv(struct sk_buff *skb, struct net_device *dev,
 		goto drop;
 
 	eth = (struct ethhdr *)skb_mac_header(skb);
+	// TODO: validate
+	if (skb->pkt_type == PACKET_LOOPBACK ||
+	    ether_addr_equal(eth->h_source, dev->dev_addr))
+		goto drop;
+
 	skb_reset_network_header(skb);
 
 	if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE))
@@ -1274,7 +1291,8 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	dev = gnif->dev;
 
 	packet_subtype = CH_HST_UNSPECIFIED;
-	if (0 /* is usgn unicast address? */) {
+	if (usgn->sgn_addr != 0 && usgn->sgn_addr != GNADDR_BROADCAST &&
+	    gn->scope.scope_type == GN_SCOPE_UNSPECIFIED) {
 		packet_type = CH_HT_GUC;
 	} else {
 		switch (gn->scope.scope_type) {
@@ -1402,6 +1420,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 		break;
 	default:
 		WARN_ONCE(1, "internal error");
+		kfree_skb(skb);
 		err = -EINVAL;
 		goto out;
 	}
@@ -1428,6 +1447,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 					   gn);
 		} else {
 			WARN_ONCE(1, "internal error");
+			kfree_skb(skb);
 			err = -EINVAL;
 			goto out;
 		}
@@ -1463,6 +1483,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 			break;
 		case GN_QUEUE_ERROR:
 		default:
+			kfree_skb(skb);
 			err = -ENOMEM;
 			goto out;
 		}
@@ -1473,7 +1494,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 
 	/* Destination position vector routing handled via location service queue */
 
-	err = 0;
+	err = len;
 out:
 	release_sock(sk);
 	return err;
@@ -1578,17 +1599,19 @@ static int gn_send_beacon(struct gn_iface *gnif)
 static void gn_send_beacons(struct timer_list *tl)
 {
 	struct gn_iface *gnif;
+	bool empty = true;
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
 		gn_send_beacon(gnif);
+		empty = false;
 	}
 	rcu_read_unlock();
 
-	mod_timer(tl, jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
+	if (!empty)
+		mod_timer(tl, jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
 }
 
-static DEFINE_TIMER(gn_beacon_timer, gn_send_beacons);
 
 static void gn_activate_beacon(void)
 {
@@ -1909,23 +1932,28 @@ static int __init gn_init(void)
 {
 	int rc;
 
+	timer_setup(&gn_beacon_timer, gn_send_beacons, 0);
+
 	rc = proto_register(&gn_proto, 0);
 	if (rc)
-		goto out;
+		return rc;
 
 	rc = sock_register(&gn_family_ops);
 	if (rc)
 		goto out_proto;
 
 	gn_dl = register_snap_client(gn_snap_id, gn_rcv);
-	if (!gn_dl)
+	if (!gn_dl) {
 		pr_crit("Unable to register GeoNetworking with SNAP.\n");
+		rc = -ENOMEM;
+		goto out_snap;
+	}
 
 	dev_add_pack(&gn_packet_type);
 
 	rc = register_netdevice_notifier(&gn_notifier);
 	if (rc)
-		goto out_sock;
+		goto out_dev;
 
 	rc = gn_proc_init();
 	if (rc)
@@ -1936,19 +1964,20 @@ static int __init gn_init(void)
 		goto out_proc;
 #endif
 
-out:
-	return rc;
+	return 0;
+
 out_proc:
 	gn_proc_exit();
 out_nd:
 	unregister_netdevice_notifier(&gn_notifier);
-out_sock:
+out_dev:
 	dev_remove_pack(&gn_packet_type);
 	unregister_snap_client(gn_dl);
+out_snap:
 	sock_unregister(PF_GN);
 out_proto:
 	proto_unregister(&gn_proto);
-	goto out;
+	return rc;
 }
 module_init(gn_init);
 
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index de1c77359e09..733ebd0d715a 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -333,6 +333,9 @@ int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
 	struct loc_te *entry;
 	bool found = false;
 
+	if (gn_find_interface(pv->addr))
+		return -EINVAL;
+
 	spin_lock_bh(&gn_loc_t_lock);
 	hash_for_each_possible(gn_loc_t, entry, hnode, pv->addr) {
 		if (entry->addr != pv->addr)
@@ -443,6 +446,7 @@ int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
 		} else if (entry->ls_pending == 1) {
 			// Entry is stale, but we already sent a LS request
 			rc = GN_QUEUE_LS_PENDING;
+			__ls_queue(&entry->lsb, skb);
 		} else {
 			// Entry is stale, perform LS request
 			rc = GN_QUEUE_LS_STALE;
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help