[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