11 #include <linux/errno.h>
12 #include <linux/types.h>
13 #include <linux/socket.h>
15 #include <linux/kernel.h>
17 #include <linux/string.h>
19 #include <linux/net.h>
20 #include <linux/slab.h>
23 #include <linux/netdevice.h>
25 #include <linux/if_arp.h>
28 #include <asm/uaccess.h>
29 #include <linux/fcntl.h>
34 #include <linux/netfilter.h>
39 #include <linux/export.h>
41 static unsigned int nr_neigh_no = 1;
54 spin_lock_bh(&nr_node_list_lock);
56 if (
ax25cmp(callsign, &nr_node->callsign) == 0) {
61 spin_unlock_bh(&nr_node_list_lock);
72 spin_lock_bh(&nr_neigh_list_lock);
74 if (
ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
75 nr_neigh->dev == dev) {
80 spin_unlock_bh(&nr_neigh_list_lock);
84 static void nr_remove_neigh(
struct nr_neigh *);
92 int quality,
int obs_count)
105 nr_node = nr_node_get(nr);
107 nr_neigh = nr_neigh_get_dev(ax25, dev);
115 if (nr_neigh !=
NULL && nr_neigh->
failed != 0 && quality == 0) {
116 struct nr_node *nr_nodet;
119 spin_lock_bh(&nr_node_list_lock);
121 nr_node_lock(nr_nodet);
122 for (i = 0; i < nr_nodet->
count; i++)
123 if (nr_nodet->
routes[i].neighbour == nr_neigh)
124 if (i < nr_nodet->which)
126 nr_node_unlock(nr_nodet);
128 spin_unlock_bh(&nr_node_list_lock);
131 if (nr_neigh !=
NULL)
134 if (quality == 0 && nr_neigh !=
NULL && nr_node !=
NULL) {
135 nr_neigh_put(nr_neigh);
136 nr_node_put(nr_node);
140 if (nr_neigh ==
NULL) {
143 nr_node_put(nr_node);
154 nr_neigh->
number = nr_neigh_no++;
158 if (ax25_digi !=
NULL && ax25_digi->
ndigi > 0) {
165 nr_node_put(nr_node);
170 spin_lock_bh(&nr_neigh_list_lock);
171 hlist_add_head(&nr_neigh->
neigh_node, &nr_neigh_list);
173 spin_unlock_bh(&nr_neigh_list_lock);
176 if (quality != 0 &&
ax25cmp(nr, ax25) == 0 && !nr_neigh->
locked)
179 if (nr_node ==
NULL) {
182 nr_neigh_put(nr_neigh);
194 nr_node->
routes[0].quality = quality;
195 nr_node->
routes[0].obs_count = obs_count;
196 nr_node->
routes[0].neighbour = nr_neigh;
201 spin_lock_bh(&nr_node_list_lock);
202 hlist_add_head(&nr_node->
node_node, &nr_node_list);
204 spin_unlock_bh(&nr_node_list_lock);
208 nr_node_lock(nr_node);
213 for (found = 0, i = 0; i < nr_node->
count; i++) {
214 if (nr_node->
routes[i].neighbour == nr_neigh) {
215 nr_node->
routes[
i].quality = quality;
216 nr_node->
routes[
i].obs_count = obs_count;
224 if (nr_node->
count < 3) {
228 nr_node->
routes[0].quality = quality;
229 nr_node->
routes[0].obs_count = obs_count;
230 nr_node->
routes[0].neighbour = nr_neigh;
238 if (quality > nr_node->
routes[2].quality) {
239 nr_node->
routes[2].neighbour->count--;
240 nr_neigh_put(nr_node->
routes[2].neighbour);
242 if (nr_node->
routes[2].neighbour->count == 0 && !nr_node->
routes[2].neighbour->locked)
243 nr_remove_neigh(nr_node->
routes[2].neighbour);
245 nr_node->
routes[2].quality = quality;
246 nr_node->
routes[2].obs_count = obs_count;
247 nr_node->
routes[2].neighbour = nr_neigh;
256 switch (nr_node->
count) {
258 if (nr_node->
routes[1].quality > nr_node->
routes[0].quality) {
259 switch (nr_node->
which) {
271 if (nr_node->
routes[2].quality > nr_node->
routes[1].quality) {
272 switch (nr_node->
which) {
273 case 1: nr_node->
which = 2;
276 case 2: nr_node->
which = 1;
287 if (nr_node->
routes[1].quality > nr_node->
routes[0].quality) {
288 switch (nr_node->
which) {
289 case 0: nr_node->
which = 1;
292 case 1: nr_node->
which = 0;
305 for (i = 0; i < nr_node->
count; i++) {
306 if (nr_node->
routes[i].neighbour == nr_neigh) {
307 if (i < nr_node->which)
313 nr_neigh_put(nr_neigh);
314 nr_node_unlock(nr_node);
315 nr_node_put(nr_node);
319 static inline void __nr_remove_node(
struct nr_node *nr_node)
322 nr_node_put(nr_node);
325 #define nr_remove_node_locked(__node) \
326 __nr_remove_node(__node)
328 static void nr_remove_node(
struct nr_node *nr_node)
330 spin_lock_bh(&nr_node_list_lock);
331 __nr_remove_node(nr_node);
332 spin_unlock_bh(&nr_node_list_lock);
335 static inline void __nr_remove_neigh(
struct nr_neigh *nr_neigh)
338 nr_neigh_put(nr_neigh);
341 #define nr_remove_neigh_locked(__neigh) \
342 __nr_remove_neigh(__neigh)
344 static void nr_remove_neigh(
struct nr_neigh *nr_neigh)
346 spin_lock_bh(&nr_neigh_list_lock);
347 __nr_remove_neigh(nr_neigh);
348 spin_unlock_bh(&nr_neigh_list_lock);
357 struct nr_node *nr_node;
358 struct nr_neigh *nr_neigh;
361 nr_node = nr_node_get(callsign);
366 nr_neigh = nr_neigh_get_dev(neighbour, dev);
368 if (nr_neigh ==
NULL) {
369 nr_node_put(nr_node);
373 nr_node_lock(nr_node);
374 for (i = 0; i < nr_node->
count; i++) {
375 if (nr_node->
routes[i].neighbour == nr_neigh) {
377 nr_neigh_put(nr_neigh);
380 nr_remove_neigh(nr_neigh);
381 nr_neigh_put(nr_neigh);
385 if (nr_node->
count == 0) {
386 nr_remove_node(nr_node);
396 nr_node_put(nr_node);
398 nr_node_unlock(nr_node);
403 nr_neigh_put(nr_neigh);
404 nr_node_unlock(nr_node);
405 nr_node_put(nr_node);
414 ax25_digi *ax25_digi,
struct net_device *dev,
unsigned int quality)
416 struct nr_neigh *nr_neigh;
418 nr_neigh = nr_neigh_get_dev(callsign, dev);
422 nr_neigh_put(nr_neigh);
436 nr_neigh->
number = nr_neigh_no++;
440 if (ax25_digi !=
NULL && ax25_digi->
ndigi > 0) {
449 spin_lock_bh(&nr_neigh_list_lock);
450 hlist_add_head(&nr_neigh->
neigh_node, &nr_neigh_list);
452 spin_unlock_bh(&nr_neigh_list_lock);
463 struct nr_neigh *nr_neigh;
465 nr_neigh = nr_neigh_get_dev(callsign, dev);
472 if (nr_neigh->
count == 0)
473 nr_remove_neigh(nr_neigh);
474 nr_neigh_put(nr_neigh);
484 static int nr_dec_obs(
void)
486 struct nr_neigh *nr_neigh;
491 spin_lock_bh(&nr_node_list_lock);
494 for (i = 0; i < s->
count; i++) {
495 switch (s->
routes[i].obs_count) {
500 nr_neigh = s->
routes[
i].neighbour;
503 nr_neigh_put(nr_neigh);
506 nr_remove_neigh(nr_neigh);
532 spin_unlock_bh(&nr_node_list_lock);
547 spin_lock_bh(&nr_neigh_list_lock);
550 spin_lock_bh(&nr_node_list_lock);
553 for (i = 0; i < t->
count; i++) {
554 if (t->
routes[i].neighbour == s) {
572 spin_unlock_bh(&nr_node_list_lock);
577 spin_unlock_bh(&nr_neigh_list_lock);
584 static struct net_device *nr_ax25_dev_get(
char *devname)
639 static ax25_digi *nr_call_to_digi(ax25_digi *digi,
int ndigis,
647 for (i = 0; i < ndigis; i++) {
648 digi->
calls[
i] = digipeaters[
i];
652 digi->
ndigi = ndigis;
674 if ((dev = nr_ax25_dev_get(nr_route.
device)) ==
NULL)
676 switch (nr_route.
type) {
683 ret = nr_add_node(&nr_route.
callsign,
686 nr_call_to_digi(&digi, nr_route.
ndigis,
692 ret = nr_add_neigh(&nr_route.
callsign,
693 nr_call_to_digi(&digi, nr_route.
ndigis,
706 if ((dev = nr_ax25_dev_get(nr_route.
device)) ==
NULL)
708 switch (nr_route.
type) {
710 ret = nr_del_node(&nr_route.
callsign,
714 ret = nr_del_neigh(&nr_route.
callsign,
739 struct nr_neigh *
s, *nr_neigh =
NULL;
741 struct nr_node *nr_node =
NULL;
743 spin_lock_bh(&nr_neigh_list_lock);
745 if (s->
ax25 == ax25) {
751 spin_unlock_bh(&nr_neigh_list_lock);
753 if (nr_neigh ==
NULL)
760 nr_neigh_put(nr_neigh);
763 spin_lock_bh(&nr_node_list_lock);
765 nr_node_lock(nr_node);
767 nr_node->
routes[nr_node->
which].neighbour == nr_neigh)
769 nr_node_unlock(nr_node);
771 spin_unlock_bh(&nr_node_list_lock);
772 nr_neigh_put(nr_neigh);
782 struct nr_neigh *nr_neigh;
783 struct nr_node *nr_node;
815 if (skb->
data[14] == 1) {
819 nr_node = nr_node_get(nr_dest);
822 nr_node_lock(nr_node);
825 nr_node_unlock(nr_node);
826 nr_node_put(nr_node);
830 nr_neigh = nr_node->
routes[nr_node->
which].neighbour;
833 nr_node_unlock(nr_node);
834 nr_node_put(nr_node);
842 nr_node_unlock(nr_node);
843 nr_node_put(nr_node);
854 ax25s = nr_neigh->
ax25;
864 nr_node_unlock(nr_node);
865 nr_node_put(nr_node);
870 #ifdef CONFIG_PROC_FS
872 static void *nr_node_start(
struct seq_file *seq, loff_t *
pos)
874 spin_lock_bh(&nr_node_list_lock);
878 static void *nr_node_next(
struct seq_file *seq,
void *
v, loff_t *
pos)
883 static void nr_node_stop(
struct seq_file *seq,
void *
v)
885 spin_unlock_bh(&nr_node_list_lock);
888 static int nr_node_show(
struct seq_file *seq,
void *
v)
895 "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
897 struct nr_node *nr_node =
hlist_entry(v,
struct nr_node,
900 nr_node_lock(nr_node);
907 for (i = 0; i < nr_node->
count; i++) {
909 nr_node->
routes[i].quality,
910 nr_node->
routes[i].obs_count,
911 nr_node->
routes[i].neighbour->number);
913 nr_node_unlock(nr_node);
921 .
start = nr_node_start,
922 .next = nr_node_next,
923 .stop = nr_node_stop,
924 .show = nr_node_show,
929 return seq_open(file, &nr_node_seqops);
934 .open = nr_node_info_open,
940 static void *nr_neigh_start(
struct seq_file *seq, loff_t *
pos)
942 spin_lock_bh(&nr_neigh_list_lock);
946 static void *nr_neigh_next(
struct seq_file *seq,
void *v, loff_t *
pos)
951 static void nr_neigh_stop(
struct seq_file *seq,
void *v)
953 spin_unlock_bh(&nr_neigh_list_lock);
956 static int nr_neigh_show(
struct seq_file *seq,
void *v)
962 seq_puts(seq,
"addr callsign dev qual lock count failed digipeaters\n");
964 struct nr_neigh *nr_neigh;
967 seq_printf(seq,
"%05d %-9s %-4s %3d %d %3d %3d",
970 nr_neigh->
dev ? nr_neigh->
dev->name :
"???",
988 .
start = nr_neigh_start,
989 .next = nr_neigh_next,
990 .stop = nr_neigh_stop,
991 .show = nr_neigh_show,
996 return seq_open(file, &nr_neigh_seqops);
1001 .open = nr_neigh_info_open,
1014 struct nr_neigh *s =
NULL;
1015 struct nr_node *
t =
NULL;
1018 spin_lock_bh(&nr_neigh_list_lock);
1019 spin_lock_bh(&nr_node_list_lock);
1032 spin_unlock_bh(&nr_node_list_lock);
1033 spin_unlock_bh(&nr_neigh_list_lock);