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