blob: 8d7716ca53429a99a08381f0459803731a535efe [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
9 * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/timer.h>
17#include <linux/string.h>
18#include <linux/sockios.h>
19#include <linux/net.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#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> /* For TIOCINQ/OUTQ */
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>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040040#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
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 * Add a new route to a node, and in the process add the node and the
89 * neighbour if it is new.
90 */
Ralf Baechlec9266b92006-12-14 15:49:28 -080091static 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
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) { /* Can't add routes to ourself */
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 * The L2 link to a neighbour has failed in the past
112 * and now a frame comes from this neighbour. We assume
113 * it was a temporary trouble with the link and reset the
114 * routes now (and not wait for a node broadcast).
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) {
Arnaldo Carvalho de Meloeafff862006-11-17 13:05:04 -0200160 nr_neigh->digipeat = kmemdup(ax25_digi,
161 sizeof(*ax25_digi),
162 GFP_KERNEL);
163 if (nr_neigh->digipeat == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 kfree(nr_neigh);
165 if (nr_node)
166 nr_node_put(nr_node);
167 return -ENOMEM;
168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 }
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 /* refcount initialized at 1 */
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 /* We have space at the bottom, slot it in */
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 /* It must be better than the worst */
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 /* Now re-sort the routes in quality order */
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) {
Joe Perchesc4855382011-07-01 09:43:10 +0000261 case 0:
262 nr_node->which = 1;
263 break;
264 case 1:
265 nr_node->which = 0;
266 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 }
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 * "Delete" a node. Strictly speaking remove a route to a node. The node
354 * is only deleted if no routes are left to it.
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 * Lock a neighbour with a quality.
413 */
Ralf Baechlec9266b92006-12-14 15:49:28 -0800414static int __must_check nr_add_neigh(ax25_address *callsign,
415 ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416{
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) {
Arnaldo Carvalho de Meloeafff862006-11-17 13:05:04 -0200442 nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
443 GFP_KERNEL);
444 if (nr_neigh->digipeat == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 kfree(nr_neigh);
446 return -ENOMEM;
447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 }
449
450 spin_lock_bh(&nr_neigh_list_lock);
451 hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
452 /* refcount is initialized at 1 */
453 spin_unlock_bh(&nr_neigh_list_lock);
454
455 return 0;
456}
457
458/*
459 * "Delete" a neighbour. The neighbour is only removed if the number
460 * of nodes that may use it is zero.
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 * Decrement the obsolescence count by one. If a route is reduced to a
482 * count of zero, remove it. Also remove any unlocked neighbours with
483 * zero nodes routing via it.
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: /* A locked entry */
498 break;
499
500 case 1: /* From 1 -> 0 */
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) {
Joe Perchesc4855382011-07-01 09:43:10 +0000512 case 0:
513 s->routes[0] = s->routes[1];
514 /* Fallthrough */
515 case 1:
516 s->routes[1] = s->routes[2];
517 case 2:
518 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
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 * A device has been removed. Remove its routes and neighbours.
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 * Check that the device given is a valid AX.25 interface that is "up".
583 * Or a valid ethernet interface with an AX.25 callsign binding.
584 */
585static struct net_device *nr_ax25_dev_get(char *devname)
586{
587 struct net_device *dev;
588
Eric W. Biederman881d9662007-09-17 11:56:21 -0700589 if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 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 * Find the first active NET/ROM device, usually "nr0".
601 */
602struct net_device *nr_dev_first(void)
603{
604 struct net_device *dev, *first = NULL;
605
Eric Dumazetc6d14c82009-11-04 05:43:23 -0800606 rcu_read_lock();
607 for_each_netdev_rcu(&init_net, dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 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);
Eric Dumazetc6d14c82009-11-04 05:43:23 -0800614 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
616 return first;
617}
618
619/*
620 * Find the NET/ROM device for the given callsign.
621 */
622struct net_device *nr_dev_get(ax25_address *addr)
623{
624 struct net_device *dev;
625
Eric Dumazetc6d14c82009-11-04 05:43:23 -0800626 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) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 dev_hold(dev);
631 goto out;
632 }
633 }
Pavel Emelianov7562f872007-05-03 15:13:45 -0700634 dev = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635out:
Eric Dumazetc6d14c82009-11-04 05:43:23 -0800636 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return dev;
638}
639
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700640static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
641 ax25_address *digipeaters)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 int i;
644
645 if (ndigis == 0)
646 return NULL;
647
648 for (i = 0; i < ndigis; i++) {
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700649 digi->calls[i] = digipeaters[i];
650 digi->repeated[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700653 digi->ndigi = ndigis;
654 digi->lastrepeat = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700656 return digi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657}
658
659/*
660 * Handle the ioctls that control the routing functions.
661 */
662int nr_rt_ioctl(unsigned int cmd, void __user *arg)
663{
664 struct nr_route_struct nr_route;
665 struct net_device *dev;
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700666 ax25_digi digi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 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:
Ralf Baechleac1a1de2011-11-24 23:08:49 +0000681 if (strnlen(nr_route.mnemonic, 7) == 7) {
682 ret = -EINVAL;
683 break;
684 }
685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 ret = nr_add_node(&nr_route.callsign,
687 nr_route.mnemonic,
688 &nr_route.neighbour,
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700689 nr_call_to_digi(&digi, nr_route.ndigis,
690 nr_route.digipeaters),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 dev, nr_route.quality,
692 nr_route.obs_count);
693 break;
694 case NETROM_NEIGH:
695 ret = nr_add_neigh(&nr_route.callsign,
Ralf Baechlec6ba9732009-08-17 18:05:32 -0700696 nr_call_to_digi(&digi, nr_route.ndigis,
697 nr_route.digipeaters),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 dev, nr_route.quality);
699 break;
700 default:
701 ret = -EINVAL;
702 }
703 dev_put(dev);
704 return ret;
705
706 case SIOCDELRT:
707 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
708 return -EFAULT;
709 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
710 return -EINVAL;
711 switch (nr_route.type) {
712 case NETROM_NODE:
713 ret = nr_del_node(&nr_route.callsign,
714 &nr_route.neighbour, dev);
715 break;
716 case NETROM_NEIGH:
717 ret = nr_del_neigh(&nr_route.callsign,
718 dev, nr_route.quality);
719 break;
720 default:
721 ret = -EINVAL;
722 }
723 dev_put(dev);
724 return ret;
725
726 case SIOCNRDECOBS:
727 return nr_dec_obs();
728
729 default:
730 return -EINVAL;
731 }
732
733 return 0;
734}
735
736/*
737 * A level 2 link has timed out, therefore it appears to be a poor link,
738 * then don't use that neighbour until it is reset.
739 */
740void nr_link_failed(ax25_cb *ax25, int reason)
741{
742 struct nr_neigh *s, *nr_neigh = NULL;
743 struct hlist_node *node;
744 struct nr_node *nr_node = NULL;
745
746 spin_lock_bh(&nr_neigh_list_lock);
Ralf Baechle52383672006-06-26 00:05:23 -0700747 nr_neigh_for_each(s, node, &nr_neigh_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 if (s->ax25 == ax25) {
749 nr_neigh_hold(s);
750 nr_neigh = s;
751 break;
752 }
Ralf Baechle52383672006-06-26 00:05:23 -0700753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 spin_unlock_bh(&nr_neigh_list_lock);
755
Ralf Baechle52383672006-06-26 00:05:23 -0700756 if (nr_neigh == NULL)
757 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
759 nr_neigh->ax25 = NULL;
760 ax25_cb_put(ax25);
761
762 if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
763 nr_neigh_put(nr_neigh);
764 return;
765 }
766 spin_lock_bh(&nr_node_list_lock);
Ralf Baechle52383672006-06-26 00:05:23 -0700767 nr_node_for_each(nr_node, node, &nr_node_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 nr_node_lock(nr_node);
Ralf Baechle52383672006-06-26 00:05:23 -0700769 if (nr_node->which < nr_node->count &&
770 nr_node->routes[nr_node->which].neighbour == nr_neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 nr_node->which++;
772 nr_node_unlock(nr_node);
Ralf Baechle52383672006-06-26 00:05:23 -0700773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 spin_unlock_bh(&nr_node_list_lock);
775 nr_neigh_put(nr_neigh);
776}
777
778/*
779 * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
780 * indicates an internally generated frame.
781 */
782int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
783{
784 ax25_address *nr_src, *nr_dest;
785 struct nr_neigh *nr_neigh;
786 struct nr_node *nr_node;
787 struct net_device *dev;
788 unsigned char *dptr;
789 ax25_cb *ax25s;
790 int ret;
791 struct sk_buff *skbn;
792
793
794 nr_src = (ax25_address *)(skb->data + 0);
795 nr_dest = (ax25_address *)(skb->data + 7);
796
Ralf Baechle58bc5742006-12-14 15:50:58 -0800797 if (ax25 != NULL) {
798 ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
YOSHIFUJI Hideaki5f8f59d2007-02-09 23:25:09 +0900799 ax25->ax25_dev->dev, 0,
800 sysctl_netrom_obsolescence_count_initialiser);
Ralf Baechle58bc5742006-12-14 15:50:58 -0800801 if (ret)
802 return ret;
803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
805 if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */
806 if (ax25 == NULL) /* Its from me */
807 ret = nr_loopback_queue(skb);
808 else
809 ret = nr_rx_frame(skb, dev);
810 dev_put(dev);
811 return ret;
812 }
813
814 if (!sysctl_netrom_routing_control && ax25 != NULL)
815 return 0;
816
817 /* Its Time-To-Live has expired */
818 if (skb->data[14] == 1) {
819 return 0;
820 }
821
822 nr_node = nr_node_get(nr_dest);
823 if (nr_node == NULL)
824 return 0;
825 nr_node_lock(nr_node);
826
827 if (nr_node->which >= nr_node->count) {
828 nr_node_unlock(nr_node);
829 nr_node_put(nr_node);
830 return 0;
831 }
832
833 nr_neigh = nr_node->routes[nr_node->which].neighbour;
834
835 if ((dev = nr_dev_first()) == NULL) {
836 nr_node_unlock(nr_node);
837 nr_node_put(nr_node);
838 return 0;
839 }
840
841 /* We are going to change the netrom headers so we should get our
842 own skb, we also did not know until now how much header space
843 we had to reserve... - RXQ */
844 if ((skbn=skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC)) == NULL) {
845 nr_node_unlock(nr_node);
846 nr_node_put(nr_node);
847 dev_put(dev);
848 return 0;
849 }
850 kfree_skb(skb);
851 skb=skbn;
852 skb->data[14]--;
853
854 dptr = skb_push(skb, 1);
855 *dptr = AX25_P_NETROM;
856
Jarek Poplawskid00c3622010-01-16 01:04:04 -0800857 ax25s = nr_neigh->ax25;
858 nr_neigh->ax25 = ax25_send_frame(skb, 256,
859 (ax25_address *)dev->dev_addr,
860 &nr_neigh->callsign,
861 nr_neigh->digipeat, nr_neigh->dev);
862 if (ax25s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 ax25_cb_put(ax25s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
865 dev_put(dev);
866 ret = (nr_neigh->ax25 != NULL);
867 nr_node_unlock(nr_node);
868 nr_node_put(nr_node);
Ralf Baechle58bc5742006-12-14 15:50:58 -0800869
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return ret;
871}
872
873#ifdef CONFIG_PROC_FS
874
875static void *nr_node_start(struct seq_file *seq, loff_t *pos)
876{
YOSHIFUJI Hideaki5f8f59d2007-02-09 23:25:09 +0900877 spin_lock_bh(&nr_node_list_lock);
Li Zefan90dd7f52010-02-08 23:19:42 +0000878 return seq_hlist_start_head(&nr_node_list, *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879}
880
881static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
882{
Li Zefan90dd7f52010-02-08 23:19:42 +0000883 return seq_hlist_next(v, &nr_node_list, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884}
885
886static void nr_node_stop(struct seq_file *seq, void *v)
887{
888 spin_unlock_bh(&nr_node_list_lock);
889}
890
891static int nr_node_show(struct seq_file *seq, void *v)
892{
Ralf Baechlef75268c2005-09-06 15:49:39 -0700893 char buf[11];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 int i;
895
896 if (v == SEQ_START_TOKEN)
897 seq_puts(seq,
898 "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
899 else {
Li Zefan90dd7f52010-02-08 23:19:42 +0000900 struct nr_node *nr_node = hlist_entry(v, struct nr_node,
901 node_node);
902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 nr_node_lock(nr_node);
904 seq_printf(seq, "%-9s %-7s %d %d",
Ralf Baechlef75268c2005-09-06 15:49:39 -0700905 ax2asc(buf, &nr_node->callsign),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
907 nr_node->which + 1,
908 nr_node->count);
909
910 for (i = 0; i < nr_node->count; i++) {
911 seq_printf(seq, " %3d %d %05d",
912 nr_node->routes[i].quality,
913 nr_node->routes[i].obs_count,
914 nr_node->routes[i].neighbour->number);
915 }
916 nr_node_unlock(nr_node);
917
918 seq_puts(seq, "\n");
919 }
920 return 0;
921}
922
Philippe De Muyter56b3d972007-07-10 23:07:31 -0700923static const struct seq_operations nr_node_seqops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 .start = nr_node_start,
925 .next = nr_node_next,
926 .stop = nr_node_stop,
927 .show = nr_node_show,
928};
929
930static int nr_node_info_open(struct inode *inode, struct file *file)
931{
932 return seq_open(file, &nr_node_seqops);
933}
934
Arjan van de Venda7071d2007-02-12 00:55:36 -0800935const struct file_operations nr_nodes_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 .owner = THIS_MODULE,
937 .open = nr_node_info_open,
938 .read = seq_read,
939 .llseek = seq_lseek,
940 .release = seq_release,
941};
942
943static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
944{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 spin_lock_bh(&nr_neigh_list_lock);
Li Zefan90dd7f52010-02-08 23:19:42 +0000946 return seq_hlist_start_head(&nr_neigh_list, *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947}
948
949static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
950{
Li Zefan90dd7f52010-02-08 23:19:42 +0000951 return seq_hlist_next(v, &nr_neigh_list, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952}
953
954static void nr_neigh_stop(struct seq_file *seq, void *v)
955{
956 spin_unlock_bh(&nr_neigh_list_lock);
957}
958
959static int nr_neigh_show(struct seq_file *seq, void *v)
960{
Ralf Baechlef75268c2005-09-06 15:49:39 -0700961 char buf[11];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 int i;
963
964 if (v == SEQ_START_TOKEN)
965 seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n");
966 else {
Li Zefan90dd7f52010-02-08 23:19:42 +0000967 struct nr_neigh *nr_neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Li Zefan90dd7f52010-02-08 23:19:42 +0000969 nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",
971 nr_neigh->number,
Ralf Baechlef75268c2005-09-06 15:49:39 -0700972 ax2asc(buf, &nr_neigh->callsign),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 nr_neigh->dev ? nr_neigh->dev->name : "???",
974 nr_neigh->quality,
975 nr_neigh->locked,
976 nr_neigh->count,
977 nr_neigh->failed);
978
979 if (nr_neigh->digipeat != NULL) {
980 for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
YOSHIFUJI Hideaki5f8f59d2007-02-09 23:25:09 +0900981 seq_printf(seq, " %s",
Ralf Baechlef75268c2005-09-06 15:49:39 -0700982 ax2asc(buf, &nr_neigh->digipeat->calls[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984
985 seq_puts(seq, "\n");
986 }
987 return 0;
988}
989
Philippe De Muyter56b3d972007-07-10 23:07:31 -0700990static const struct seq_operations nr_neigh_seqops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 .start = nr_neigh_start,
992 .next = nr_neigh_next,
993 .stop = nr_neigh_stop,
994 .show = nr_neigh_show,
995};
996
997static int nr_neigh_info_open(struct inode *inode, struct file *file)
998{
999 return seq_open(file, &nr_neigh_seqops);
1000}
1001
Arjan van de Venda7071d2007-02-12 00:55:36 -08001002const struct file_operations nr_neigh_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 .owner = THIS_MODULE,
1004 .open = nr_neigh_info_open,
1005 .read = seq_read,
1006 .llseek = seq_lseek,
1007 .release = seq_release,
1008};
1009
1010#endif
1011
1012/*
1013 * Free all memory associated with the nodes and routes lists.
1014 */
1015void __exit nr_rt_free(void)
1016{
1017 struct nr_neigh *s = NULL;
1018 struct nr_node *t = NULL;
1019 struct hlist_node *node, *nodet;
1020
1021 spin_lock_bh(&nr_neigh_list_lock);
1022 spin_lock_bh(&nr_node_list_lock);
1023 nr_node_for_each_safe(t, node, nodet, &nr_node_list) {
1024 nr_node_lock(t);
1025 nr_remove_node_locked(t);
1026 nr_node_unlock(t);
1027 }
1028 nr_neigh_for_each_safe(s, node, nodet, &nr_neigh_list) {
1029 while(s->count) {
1030 s->count--;
1031 nr_neigh_put(s);
1032 }
1033 nr_remove_neigh_locked(s);
1034 }
1035 spin_unlock_bh(&nr_node_list_lock);
1036 spin_unlock_bh(&nr_neigh_list_lock);
1037}