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