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