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
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: nr_node->which = 1; break;
261 case 1: nr_node->which = 0; break;
262 default: 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 *node, *nodet;
486 int i;
487
488 spin_lock_bh(&nr_node_list_lock);
489 nr_node_for_each_safe(s, node, 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 case 1:
511 s->routes[1] = s->routes[2];
512 case 2:
513 break;
514 }
515 break;
516
517 default:
518 s->routes[i].obs_count--;
519 break;
520
521 }
522 }
523
524 if (s->count <= 0)
525 nr_remove_node_locked(s);
526 nr_node_unlock(s);
527 }
528 spin_unlock_bh(&nr_node_list_lock);
529
530 return 0;
531}
532
533
534
535
536void nr_rt_device_down(struct net_device *dev)
537{
538 struct nr_neigh *s;
539 struct hlist_node *node, *nodet, *node2, *node2t;
540 struct nr_node *t;
541 int i;
542
543 spin_lock_bh(&nr_neigh_list_lock);
544 nr_neigh_for_each_safe(s, node, nodet, &nr_neigh_list) {
545 if (s->dev == dev) {
546 spin_lock_bh(&nr_node_list_lock);
547 nr_node_for_each_safe(t, node2, node2t, &nr_node_list) {
548 nr_node_lock(t);
549 for (i = 0; i < t->count; i++) {
550 if (t->routes[i].neighbour == s) {
551 t->count--;
552
553 switch (i) {
554 case 0:
555 t->routes[0] = t->routes[1];
556 case 1:
557 t->routes[1] = t->routes[2];
558 case 2:
559 break;
560 }
561 }
562 }
563
564 if (t->count <= 0)
565 nr_remove_node_locked(t);
566 nr_node_unlock(t);
567 }
568 spin_unlock_bh(&nr_node_list_lock);
569
570 nr_remove_neigh_locked(s);
571 }
572 }
573 spin_unlock_bh(&nr_neigh_list_lock);
574}
575
576
577
578
579
580static struct net_device *nr_ax25_dev_get(char *devname)
581{
582 struct net_device *dev;
583
584 if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
585 return NULL;
586
587 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
588 return dev;
589
590 dev_put(dev);
591 return NULL;
592}
593
594
595
596
597struct net_device *nr_dev_first(void)
598{
599 struct net_device *dev, *first = NULL;
600
601 rcu_read_lock();
602 for_each_netdev_rcu(&init_net, dev) {
603 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
604 if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
605 first = dev;
606 }
607 if (first)
608 dev_hold(first);
609 rcu_read_unlock();
610
611 return first;
612}
613
614
615
616
617struct net_device *nr_dev_get(ax25_address *addr)
618{
619 struct net_device *dev;
620
621 rcu_read_lock();
622 for_each_netdev_rcu(&init_net, dev) {
623 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&
624 ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
625 dev_hold(dev);
626 goto out;
627 }
628 }
629 dev = NULL;
630out:
631 rcu_read_unlock();
632 return dev;
633}
634
635static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
636 ax25_address *digipeaters)
637{
638 int i;
639
640 if (ndigis == 0)
641 return NULL;
642
643 for (i = 0; i < ndigis; i++) {
644 digi->calls[i] = digipeaters[i];
645 digi->repeated[i] = 0;
646 }
647
648 digi->ndigi = ndigis;
649 digi->lastrepeat = -1;
650
651 return digi;
652}
653
654
655
656
657int nr_rt_ioctl(unsigned int cmd, void __user *arg)
658{
659 struct nr_route_struct nr_route;
660 struct net_device *dev;
661 ax25_digi digi;
662 int ret;
663
664 switch (cmd) {
665 case SIOCADDRT:
666 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
667 return -EFAULT;
668 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
669 return -EINVAL;
670 if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS) {
671 dev_put(dev);
672 return -EINVAL;
673 }
674 switch (nr_route.type) {
675 case NETROM_NODE:
676 ret = nr_add_node(&nr_route.callsign,
677 nr_route.mnemonic,
678 &nr_route.neighbour,
679 nr_call_to_digi(&digi, nr_route.ndigis,
680 nr_route.digipeaters),
681 dev, nr_route.quality,
682 nr_route.obs_count);
683 break;
684 case NETROM_NEIGH:
685 ret = nr_add_neigh(&nr_route.callsign,
686 nr_call_to_digi(&digi, nr_route.ndigis,
687 nr_route.digipeaters),
688 dev, nr_route.quality);
689 break;
690 default:
691 ret = -EINVAL;
692 }
693 dev_put(dev);
694 return ret;
695
696 case SIOCDELRT:
697 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
698 return -EFAULT;
699 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
700 return -EINVAL;
701 switch (nr_route.type) {
702 case NETROM_NODE:
703 ret = nr_del_node(&nr_route.callsign,
704 &nr_route.neighbour, dev);
705 break;
706 case NETROM_NEIGH:
707 ret = nr_del_neigh(&nr_route.callsign,
708 dev, nr_route.quality);
709 break;
710 default:
711 ret = -EINVAL;
712 }
713 dev_put(dev);
714 return ret;
715
716 case SIOCNRDECOBS:
717 return nr_dec_obs();
718
719 default:
720 return -EINVAL;
721 }
722
723 return 0;
724}
725
726
727
728
729
730void nr_link_failed(ax25_cb *ax25, int reason)
731{
732 struct nr_neigh *s, *nr_neigh = NULL;
733 struct hlist_node *node;
734 struct nr_node *nr_node = NULL;
735
736 spin_lock_bh(&nr_neigh_list_lock);
737 nr_neigh_for_each(s, node, &nr_neigh_list) {
738 if (s->ax25 == ax25) {
739 nr_neigh_hold(s);
740 nr_neigh = s;
741 break;
742 }
743 }
744 spin_unlock_bh(&nr_neigh_list_lock);
745
746 if (nr_neigh == NULL)
747 return;
748
749 nr_neigh->ax25 = NULL;
750 ax25_cb_put(ax25);
751
752 if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
753 nr_neigh_put(nr_neigh);
754 return;
755 }
756 spin_lock_bh(&nr_node_list_lock);
757 nr_node_for_each(nr_node, node, &nr_node_list) {
758 nr_node_lock(nr_node);
759 if (nr_node->which < nr_node->count &&
760 nr_node->routes[nr_node->which].neighbour == nr_neigh)
761 nr_node->which++;
762 nr_node_unlock(nr_node);
763 }
764 spin_unlock_bh(&nr_node_list_lock);
765 nr_neigh_put(nr_neigh);
766}
767
768
769
770
771
772int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
773{
774 ax25_address *nr_src, *nr_dest;
775 struct nr_neigh *nr_neigh;
776 struct nr_node *nr_node;
777 struct net_device *dev;
778 unsigned char *dptr;
779 ax25_cb *ax25s;
780 int ret;
781 struct sk_buff *skbn;
782
783
784 nr_src = (ax25_address *)(skb->data + 0);
785 nr_dest = (ax25_address *)(skb->data + 7);
786
787 if (ax25 != NULL) {
788 ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
789 ax25->ax25_dev->dev, 0,
790 sysctl_netrom_obsolescence_count_initialiser);
791 if (ret)
792 return ret;
793 }
794
795 if ((dev = nr_dev_get(nr_dest)) != NULL) {
796 if (ax25 == NULL)
797 ret = nr_loopback_queue(skb);
798 else
799 ret = nr_rx_frame(skb, dev);
800 dev_put(dev);
801 return ret;
802 }
803
804 if (!sysctl_netrom_routing_control && ax25 != NULL)
805 return 0;
806
807
808 if (skb->data[14] == 1) {
809 return 0;
810 }
811
812 nr_node = nr_node_get(nr_dest);
813 if (nr_node == NULL)
814 return 0;
815 nr_node_lock(nr_node);
816
817 if (nr_node->which >= nr_node->count) {
818 nr_node_unlock(nr_node);
819 nr_node_put(nr_node);
820 return 0;
821 }
822
823 nr_neigh = nr_node->routes[nr_node->which].neighbour;
824
825 if ((dev = nr_dev_first()) == NULL) {
826 nr_node_unlock(nr_node);
827 nr_node_put(nr_node);
828 return 0;
829 }
830
831
832
833
834 if ((skbn=skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC)) == NULL) {
835 nr_node_unlock(nr_node);
836 nr_node_put(nr_node);
837 dev_put(dev);
838 return 0;
839 }
840 kfree_skb(skb);
841 skb=skbn;
842 skb->data[14]--;
843
844 dptr = skb_push(skb, 1);
845 *dptr = AX25_P_NETROM;
846
847 ax25s = nr_neigh->ax25;
848 nr_neigh->ax25 = ax25_send_frame(skb, 256,
849 (ax25_address *)dev->dev_addr,
850 &nr_neigh->callsign,
851 nr_neigh->digipeat, nr_neigh->dev);
852 if (ax25s)
853 ax25_cb_put(ax25s);
854
855 dev_put(dev);
856 ret = (nr_neigh->ax25 != NULL);
857 nr_node_unlock(nr_node);
858 nr_node_put(nr_node);
859
860 return ret;
861}
862
863#ifdef CONFIG_PROC_FS
864
865static void *nr_node_start(struct seq_file *seq, loff_t *pos)
866{
867 spin_lock_bh(&nr_node_list_lock);
868 return seq_hlist_start_head(&nr_node_list, *pos);
869}
870
871static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
872{
873 return seq_hlist_next(v, &nr_node_list, pos);
874}
875
876static void nr_node_stop(struct seq_file *seq, void *v)
877{
878 spin_unlock_bh(&nr_node_list_lock);
879}
880
881static int nr_node_show(struct seq_file *seq, void *v)
882{
883 char buf[11];
884 int i;
885
886 if (v == SEQ_START_TOKEN)
887 seq_puts(seq,
888 "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
889 else {
890 struct nr_node *nr_node = hlist_entry(v, struct nr_node,
891 node_node);
892
893 nr_node_lock(nr_node);
894 seq_printf(seq, "%-9s %-7s %d %d",
895 ax2asc(buf, &nr_node->callsign),
896 (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
897 nr_node->which + 1,
898 nr_node->count);
899
900 for (i = 0; i < nr_node->count; i++) {
901 seq_printf(seq, " %3d %d %05d",
902 nr_node->routes[i].quality,
903 nr_node->routes[i].obs_count,
904 nr_node->routes[i].neighbour->number);
905 }
906 nr_node_unlock(nr_node);
907
908 seq_puts(seq, "\n");
909 }
910 return 0;
911}
912
913static const struct seq_operations nr_node_seqops = {
914 .start = nr_node_start,
915 .next = nr_node_next,
916 .stop = nr_node_stop,
917 .show = nr_node_show,
918};
919
920static int nr_node_info_open(struct inode *inode, struct file *file)
921{
922 return seq_open(file, &nr_node_seqops);
923}
924
925const struct file_operations nr_nodes_fops = {
926 .owner = THIS_MODULE,
927 .open = nr_node_info_open,
928 .read = seq_read,
929 .llseek = seq_lseek,
930 .release = seq_release,
931};
932
933static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
934{
935 spin_lock_bh(&nr_neigh_list_lock);
936 return seq_hlist_start_head(&nr_neigh_list, *pos);
937}
938
939static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
940{
941 return seq_hlist_next(v, &nr_neigh_list, pos);
942}
943
944static void nr_neigh_stop(struct seq_file *seq, void *v)
945{
946 spin_unlock_bh(&nr_neigh_list_lock);
947}
948
949static int nr_neigh_show(struct seq_file *seq, void *v)
950{
951 char buf[11];
952 int i;
953
954 if (v == SEQ_START_TOKEN)
955 seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n");
956 else {
957 struct nr_neigh *nr_neigh;
958
959 nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);
960 seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",
961 nr_neigh->number,
962 ax2asc(buf, &nr_neigh->callsign),
963 nr_neigh->dev ? nr_neigh->dev->name : "???",
964 nr_neigh->quality,
965 nr_neigh->locked,
966 nr_neigh->count,
967 nr_neigh->failed);
968
969 if (nr_neigh->digipeat != NULL) {
970 for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
971 seq_printf(seq, " %s",
972 ax2asc(buf, &nr_neigh->digipeat->calls[i]));
973 }
974
975 seq_puts(seq, "\n");
976 }
977 return 0;
978}
979
980static const struct seq_operations nr_neigh_seqops = {
981 .start = nr_neigh_start,
982 .next = nr_neigh_next,
983 .stop = nr_neigh_stop,
984 .show = nr_neigh_show,
985};
986
987static int nr_neigh_info_open(struct inode *inode, struct file *file)
988{
989 return seq_open(file, &nr_neigh_seqops);
990}
991
992const struct file_operations nr_neigh_fops = {
993 .owner = THIS_MODULE,
994 .open = nr_neigh_info_open,
995 .read = seq_read,
996 .llseek = seq_lseek,
997 .release = seq_release,
998};
999
1000#endif
1001
1002
1003
1004
1005void __exit nr_rt_free(void)
1006{
1007 struct nr_neigh *s = NULL;
1008 struct nr_node *t = NULL;
1009 struct hlist_node *node, *nodet;
1010
1011 spin_lock_bh(&nr_neigh_list_lock);
1012 spin_lock_bh(&nr_node_list_lock);
1013 nr_node_for_each_safe(t, node, nodet, &nr_node_list) {
1014 nr_node_lock(t);
1015 nr_remove_node_locked(t);
1016 nr_node_unlock(t);
1017 }
1018 nr_neigh_for_each_safe(s, node, nodet, &nr_neigh_list) {
1019 while(s->count) {
1020 s->count--;
1021 nr_neigh_put(s);
1022 }
1023 nr_remove_neigh_locked(s);
1024 }
1025 spin_unlock_bh(&nr_node_list_lock);
1026 spin_unlock_bh(&nr_neigh_list_lock);
1027}
1028