^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/ax25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/termios.h> /* For TIOCINQ/OUTQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <net/netrom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static unsigned int nr_neigh_no = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static HLIST_HEAD(nr_node_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static DEFINE_SPINLOCK(nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static HLIST_HEAD(nr_neigh_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static DEFINE_SPINLOCK(nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static struct nr_node *nr_node_get(ax25_address *callsign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct nr_node *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct nr_node *nr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) nr_node_for_each(nr_node, &nr_node_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (ax25cmp(callsign, &nr_node->callsign) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) nr_node_hold(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) found = nr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct nr_neigh *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) nr_neigh_for_each(nr_neigh, &nr_neigh_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) nr_neigh->dev == dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) nr_neigh_hold(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) found = nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void nr_remove_neigh(struct nr_neigh *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* re-sort the routes in quality order. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void re_sort_routes(struct nr_node *nr_node, int x, int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (nr_node->routes[y].quality > nr_node->routes[x].quality) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (nr_node->which == x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) nr_node->which = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) else if (nr_node->which == y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) nr_node->which = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) swap(nr_node->routes[x], nr_node->routes[y]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Add a new route to a node, and in the process add the node and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * neighbour if it is new.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int quality, int obs_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct nr_node *nr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int i, found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct net_device *odev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if ((odev=nr_dev_get(nr)) != NULL) { /* Can't add routes to ourself */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dev_put(odev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) nr_node = nr_node_get(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) nr_neigh = nr_neigh_get_dev(ax25, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * The L2 link to a neighbour has failed in the past
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * and now a frame comes from this neighbour. We assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * it was a temporary trouble with the link and reset the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * routes now (and not wait for a node broadcast).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct nr_node *nr_nodet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) nr_node_for_each(nr_nodet, &nr_node_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) nr_node_lock(nr_nodet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) for (i = 0; i < nr_nodet->count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (nr_nodet->routes[i].neighbour == nr_neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (i < nr_nodet->which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) nr_nodet->which = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) nr_node_unlock(nr_nodet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (nr_neigh != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) nr_neigh->failed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (quality == 0 && nr_neigh != NULL && nr_node != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (nr_neigh == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (nr_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) nr_neigh->callsign = *ax25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) nr_neigh->digipeat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) nr_neigh->ax25 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) nr_neigh->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) nr_neigh->quality = sysctl_netrom_default_path_quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) nr_neigh->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) nr_neigh->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) nr_neigh->number = nr_neigh_no++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) nr_neigh->failed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) refcount_set(&nr_neigh->refcount, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) nr_neigh->digipeat = kmemdup(ax25_digi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sizeof(*ax25_digi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (nr_neigh->digipeat == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) kfree(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (nr_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) nr_neigh_hold(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) nr_neigh->quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (nr_node == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (nr_neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) nr_node->callsign = *nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) strcpy(nr_node->mnemonic, mnemonic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) nr_node->which = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) nr_node->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) refcount_set(&nr_node->refcount, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) spin_lock_init(&nr_node->node_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) nr_node->routes[0].quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) nr_node->routes[0].obs_count = obs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) nr_node->routes[0].neighbour = nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) nr_neigh_hold(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) nr_neigh->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) hlist_add_head(&nr_node->node_node, &nr_node_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* refcount initialized at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) nr_node_lock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (quality != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) strcpy(nr_node->mnemonic, mnemonic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (found = 0, i = 0; i < nr_node->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (nr_node->routes[i].neighbour == nr_neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) nr_node->routes[i].quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) nr_node->routes[i].obs_count = obs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* We have space at the bottom, slot it in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (nr_node->count < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) nr_node->routes[2] = nr_node->routes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) nr_node->routes[1] = nr_node->routes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) nr_node->routes[0].quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) nr_node->routes[0].obs_count = obs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) nr_node->routes[0].neighbour = nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) nr_node->which++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) nr_node->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) nr_neigh_hold(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) nr_neigh->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* It must be better than the worst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (quality > nr_node->routes[2].quality) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) nr_node->routes[2].neighbour->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) nr_neigh_put(nr_node->routes[2].neighbour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) nr_remove_neigh(nr_node->routes[2].neighbour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) nr_node->routes[2].quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) nr_node->routes[2].obs_count = obs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) nr_node->routes[2].neighbour = nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) nr_neigh_hold(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) nr_neigh->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Now re-sort the routes in quality order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) switch (nr_node->count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) re_sort_routes(nr_node, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) re_sort_routes(nr_node, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) re_sort_routes(nr_node, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) for (i = 0; i < nr_node->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (nr_node->routes[i].neighbour == nr_neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (i < nr_node->which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) nr_node->which = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static inline void __nr_remove_node(struct nr_node *nr_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) hlist_del_init(&nr_node->node_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define nr_remove_node_locked(__node) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) __nr_remove_node(__node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static void nr_remove_node(struct nr_node *nr_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) __nr_remove_node(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) hlist_del_init(&nr_neigh->neigh_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #define nr_remove_neigh_locked(__neigh) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) __nr_remove_neigh(__neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static void nr_remove_neigh(struct nr_neigh *nr_neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) __nr_remove_neigh(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * "Delete" a node. Strictly speaking remove a route to a node. The node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * is only deleted if no routes are left to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct nr_node *nr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) nr_node = nr_node_get(callsign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (nr_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) nr_neigh = nr_neigh_get_dev(neighbour, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (nr_neigh == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) nr_node_lock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) for (i = 0; i < nr_node->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (nr_node->routes[i].neighbour == nr_neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) nr_neigh->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (nr_neigh->count == 0 && !nr_neigh->locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) nr_remove_neigh(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) nr_node->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (nr_node->count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) nr_remove_node(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) nr_node->routes[0] = nr_node->routes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) nr_node->routes[1] = nr_node->routes[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Lock a neighbour with a quality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int __must_check nr_add_neigh(ax25_address *callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) nr_neigh = nr_neigh_get_dev(callsign, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (nr_neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) nr_neigh->quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) nr_neigh->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) nr_neigh->callsign = *callsign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) nr_neigh->digipeat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) nr_neigh->ax25 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) nr_neigh->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) nr_neigh->quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) nr_neigh->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) nr_neigh->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) nr_neigh->number = nr_neigh_no++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) nr_neigh->failed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) refcount_set(&nr_neigh->refcount, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (nr_neigh->digipeat == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) kfree(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /* refcount is initialized at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * "Delete" a neighbour. The neighbour is only removed if the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * of nodes that may use it is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) nr_neigh = nr_neigh_get_dev(callsign, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (nr_neigh == NULL) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) nr_neigh->quality = quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) nr_neigh->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (nr_neigh->count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) nr_remove_neigh(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * Decrement the obsolescence count by one. If a route is reduced to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * count of zero, remove it. Also remove any unlocked neighbours with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * zero nodes routing via it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int nr_dec_obs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct nr_node *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct hlist_node *nodet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) nr_node_for_each_safe(s, nodet, &nr_node_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) nr_node_lock(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) for (i = 0; i < s->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) switch (s->routes[i].obs_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) case 0: /* A locked entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case 1: /* From 1 -> 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) nr_neigh = s->routes[i].neighbour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) nr_neigh->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (nr_neigh->count == 0 && !nr_neigh->locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) nr_remove_neigh(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) s->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) s->routes[0] = s->routes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) s->routes[1] = s->routes[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) s->routes[i].obs_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (s->count <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) nr_remove_node_locked(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) nr_node_unlock(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * A device has been removed. Remove its routes and neighbours.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) void nr_rt_device_down(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) struct nr_neigh *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct hlist_node *nodet, *node2t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct nr_node *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (s->dev == dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) nr_node_for_each_safe(t, node2t, &nr_node_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) nr_node_lock(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) for (i = 0; i < t->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (t->routes[i].neighbour == s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) t->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) t->routes[0] = t->routes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) t->routes[1] = t->routes[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (t->count <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) nr_remove_node_locked(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) nr_node_unlock(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) nr_remove_neigh_locked(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * Check that the device given is a valid AX.25 interface that is "up".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * Or a valid ethernet interface with an AX.25 callsign binding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static struct net_device *nr_ax25_dev_get(char *devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Find the first active NET/ROM device, usually "nr0".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct net_device *nr_dev_first(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct net_device *dev, *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for_each_netdev_rcu(&init_net, dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) first = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_hold(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * Find the NET/ROM device for the given callsign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct net_device *nr_dev_get(ax25_address *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) for_each_netdev_rcu(&init_net, dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ax25_address *digipeaters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (ndigis == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) for (i = 0; i < ndigis; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) digi->calls[i] = digipeaters[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) digi->repeated[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) digi->ndigi = ndigis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) digi->lastrepeat = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return digi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * Handle the ioctls that control the routing functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int nr_rt_ioctl(unsigned int cmd, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct nr_route_struct nr_route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ax25_digi digi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) case SIOCADDRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (nr_route.ndigis > AX25_MAX_DIGIS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) switch (nr_route.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case NETROM_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (strnlen(nr_route.mnemonic, 7) == 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = nr_add_node(&nr_route.callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) nr_route.mnemonic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) &nr_route.neighbour,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) nr_call_to_digi(&digi, nr_route.ndigis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) nr_route.digipeaters),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dev, nr_route.quality,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) nr_route.obs_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case NETROM_NEIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = nr_add_neigh(&nr_route.callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) nr_call_to_digi(&digi, nr_route.ndigis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) nr_route.digipeaters),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) dev, nr_route.quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) case SIOCDELRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) switch (nr_route.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) case NETROM_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ret = nr_del_node(&nr_route.callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) &nr_route.neighbour, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case NETROM_NEIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ret = nr_del_neigh(&nr_route.callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dev, nr_route.quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) case SIOCNRDECOBS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return nr_dec_obs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * A level 2 link has timed out, therefore it appears to be a poor link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * then don't use that neighbour until it is reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) void nr_link_failed(ax25_cb *ax25, int reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct nr_neigh *s, *nr_neigh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct nr_node *nr_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) nr_neigh_for_each(s, &nr_neigh_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (s->ax25 == ax25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) nr_neigh_hold(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) nr_neigh = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (nr_neigh == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) nr_neigh->ax25 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ax25_cb_put(ax25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) nr_node_for_each(nr_node, &nr_node_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) nr_node_lock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (nr_node->which < nr_node->count &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) nr_node->routes[nr_node->which].neighbour == nr_neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) nr_node->which++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) nr_neigh_put(nr_neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * indicates an internally generated frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ax25_address *nr_src, *nr_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct nr_node *nr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) unsigned char *dptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ax25_cb *ax25s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct sk_buff *skbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) nr_src = (ax25_address *)(skb->data + 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) nr_dest = (ax25_address *)(skb->data + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (ax25 != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) ax25->ax25_dev->dev, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) sysctl_netrom_obsolescence_count_initialiser);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ax25 == NULL) /* Its from me */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) ret = nr_loopback_queue(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) ret = nr_rx_frame(skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (!sysctl_netrom_routing_control && ax25 != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* Its Time-To-Live has expired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (skb->data[14] == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) nr_node = nr_node_get(nr_dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (nr_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) nr_node_lock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (nr_node->which >= nr_node->count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) nr_neigh = nr_node->routes[nr_node->which].neighbour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if ((dev = nr_dev_first()) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /* We are going to change the netrom headers so we should get our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) own skb, we also did not know until now how much header space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) we had to reserve... - RXQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if ((skbn=skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) skb=skbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) skb->data[14]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) dptr = skb_push(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) *dptr = AX25_P_NETROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ax25s = nr_neigh->ax25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) nr_neigh->ax25 = ax25_send_frame(skb, 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) (ax25_address *)dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) &nr_neigh->callsign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) nr_neigh->digipeat, nr_neigh->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (ax25s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ax25_cb_put(ax25s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = (nr_neigh->ax25 != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) nr_node_put(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static void *nr_node_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) __acquires(&nr_node_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return seq_hlist_start_head(&nr_node_list, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return seq_hlist_next(v, &nr_node_list, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static void nr_node_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) __releases(&nr_node_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static int nr_node_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) char buf[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) seq_puts(seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct nr_node *nr_node = hlist_entry(v, struct nr_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) node_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) nr_node_lock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) seq_printf(seq, "%-9s %-7s %d %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ax2asc(buf, &nr_node->callsign),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) nr_node->which + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) nr_node->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) for (i = 0; i < nr_node->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) seq_printf(seq, " %3d %d %05d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) nr_node->routes[i].quality,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) nr_node->routes[i].obs_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) nr_node->routes[i].neighbour->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) nr_node_unlock(nr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) seq_puts(seq, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) const struct seq_operations nr_node_seqops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .start = nr_node_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .next = nr_node_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) .stop = nr_node_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .show = nr_node_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) __acquires(&nr_neigh_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return seq_hlist_start_head(&nr_neigh_list, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return seq_hlist_next(v, &nr_neigh_list, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static void nr_neigh_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) __releases(&nr_neigh_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static int nr_neigh_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) char buf[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct nr_neigh *nr_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) nr_neigh->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ax2asc(buf, &nr_neigh->callsign),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) nr_neigh->dev ? nr_neigh->dev->name : "???",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) nr_neigh->quality,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) nr_neigh->locked,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) nr_neigh->count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) nr_neigh->failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (nr_neigh->digipeat != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) seq_printf(seq, " %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ax2asc(buf, &nr_neigh->digipeat->calls[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) seq_puts(seq, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) const struct seq_operations nr_neigh_seqops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .start = nr_neigh_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .next = nr_neigh_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .stop = nr_neigh_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .show = nr_neigh_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * Free all memory associated with the nodes and routes lists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) void nr_rt_free(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct nr_neigh *s = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct nr_node *t = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct hlist_node *nodet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) spin_lock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) spin_lock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) nr_node_for_each_safe(t, nodet, &nr_node_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) nr_node_lock(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) nr_remove_node_locked(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) nr_node_unlock(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) while(s->count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) s->count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) nr_neigh_put(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) nr_remove_neigh_locked(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) spin_unlock_bh(&nr_node_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) spin_unlock_bh(&nr_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }