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