OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [rose/] [rose_route.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      ROSE release 003
3
 *
4
 *      This code REQUIRES 2.1.15 or higher/ NET3.038
5
 *
6
 *      This module:
7
 *              This module is free software; you can redistribute it and/or
8
 *              modify it under the terms of the GNU General Public License
9
 *              as published by the Free Software Foundation; either version
10
 *              2 of the License, or (at your option) any later version.
11
 *
12
 *      History
13
 *      ROSE 001        Jonathan(G4KLX) Cloned from nr_route.c.
14
 *                      Terry(VK2KTJ)   Added support for variable length
15
 *                                      address masks.
16
 *      ROSE 002        Jonathan(G4KLX) Uprated through routing of packets.
17
 *                                      Routing loop detection.
18
 *      ROSE 003        Jonathan(G4KLX) New timer architecture.
19
 *                                      Added use count to neighbours.
20
 */
21
 
22
#include <linux/errno.h>
23
#include <linux/types.h>
24
#include <linux/socket.h>
25
#include <linux/in.h>
26
#include <linux/kernel.h>
27
#include <linux/sched.h>
28
#include <linux/timer.h>
29
#include <linux/string.h>
30
#include <linux/sockios.h>
31
#include <linux/net.h>
32
#include <net/ax25.h>
33
#include <linux/inet.h>
34
#include <linux/netdevice.h>
35
#include <net/arp.h>
36
#include <linux/if_arp.h>
37
#include <linux/skbuff.h>
38
#include <net/sock.h>
39
#include <asm/segment.h>
40
#include <asm/system.h>
41
#include <asm/uaccess.h>
42
#include <linux/fcntl.h>
43
#include <linux/termios.h>      /* For TIOCINQ/OUTQ */
44
#include <linux/mm.h>
45
#include <linux/interrupt.h>
46
#include <linux/notifier.h>
47
#include <linux/netfilter.h>
48
#include <linux/init.h>
49
#include <net/rose.h>
50
 
51
static unsigned int rose_neigh_no = 1;
52
 
53
static struct rose_node  *rose_node_list;
54
static struct rose_neigh *rose_neigh_list;
55
static struct rose_route *rose_route_list;
56
 
57
struct rose_neigh *rose_loopback_neigh;
58
 
59
static void rose_remove_neigh(struct rose_neigh *);
60
 
61
/*
62
 *      Add a new route to a node, and in the process add the node and the
63
 *      neighbour if it is new.
64
 */
65
static int rose_add_node(struct rose_route_struct *rose_route, struct net_device *dev)
66
{
67
        struct rose_node  *rose_node, *rose_tmpn, *rose_tmpp;
68
        struct rose_neigh *rose_neigh;
69
        unsigned long flags;
70
        int i;
71
 
72
        for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
73
                if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0))
74
                        break;
75
 
76
        if (rose_node != NULL && rose_node->loopback)
77
                return -EINVAL;
78
 
79
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next)
80
                if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev)
81
                        break;
82
 
83
        if (rose_neigh == NULL) {
84
                if ((rose_neigh = kmalloc(sizeof(*rose_neigh), GFP_ATOMIC)) == NULL)
85
                        return -ENOMEM;
86
 
87
                rose_neigh->callsign  = rose_route->neighbour;
88
                rose_neigh->digipeat  = NULL;
89
                rose_neigh->ax25      = NULL;
90
                rose_neigh->dev       = dev;
91
                rose_neigh->count     = 0;
92
                rose_neigh->use       = 0;
93
                rose_neigh->dce_mode  = 0;
94
                rose_neigh->loopback  = 0;
95
                rose_neigh->number    = rose_neigh_no++;
96
                rose_neigh->restarted = 0;
97
 
98
                skb_queue_head_init(&rose_neigh->queue);
99
 
100
                init_timer(&rose_neigh->ftimer);
101
                init_timer(&rose_neigh->t0timer);
102
 
103
                if (rose_route->ndigis != 0) {
104
                        if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
105
                                kfree(rose_neigh);
106
                                return -ENOMEM;
107
                        }
108
 
109
                        rose_neigh->digipeat->ndigi      = rose_route->ndigis;
110
                        rose_neigh->digipeat->lastrepeat = -1;
111
 
112
                        for (i = 0; i < rose_route->ndigis; i++) {
113
                                rose_neigh->digipeat->calls[i]    = rose_route->digipeaters[i];
114
                                rose_neigh->digipeat->repeated[i] = 0;
115
                        }
116
                }
117
 
118
                save_flags(flags); cli();
119
                rose_neigh->next = rose_neigh_list;
120
                rose_neigh_list  = rose_neigh;
121
                restore_flags(flags);
122
        }
123
 
124
        /*
125
         * This is a new node to be inserted into the list. Find where it needs
126
         * to be inserted into the list, and insert it. We want to be sure
127
         * to order the list in descending order of mask size to ensure that
128
         * later when we are searching this list the first match will be the
129
         * best match.
130
         */
131
        if (rose_node == NULL) {
132
                rose_tmpn = rose_node_list;
133
                rose_tmpp = NULL;
134
 
135
                while (rose_tmpn != NULL) {
136
                        if (rose_tmpn->mask > rose_route->mask) {
137
                                rose_tmpp = rose_tmpn;
138
                                rose_tmpn = rose_tmpn->next;
139
                        } else {
140
                                break;
141
                        }
142
                }
143
 
144
                /* create new node */
145
                if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL)
146
                        return -ENOMEM;
147
 
148
                rose_node->address      = rose_route->address;
149
                rose_node->mask         = rose_route->mask;
150
                rose_node->count        = 1;
151
                rose_node->loopback     = 0;
152
                rose_node->neighbour[0] = rose_neigh;
153
 
154
                save_flags(flags); cli();
155
 
156
                if (rose_tmpn == NULL) {
157
                        if (rose_tmpp == NULL) {        /* Empty list */
158
                                rose_node_list  = rose_node;
159
                                rose_node->next = NULL;
160
                        } else {
161
                                rose_tmpp->next = rose_node;
162
                                rose_node->next = NULL;
163
                        }
164
                } else {
165
                        if (rose_tmpp == NULL) {        /* 1st node */
166
                                rose_node->next = rose_node_list;
167
                                rose_node_list  = rose_node;
168
                        } else {
169
                                rose_tmpp->next = rose_node;
170
                                rose_node->next = rose_tmpn;
171
                        }
172
                }
173
 
174
                restore_flags(flags);
175
 
176
                rose_neigh->count++;
177
 
178
                return 0;
179
        }
180
 
181
        /* We have space, slot it in */
182
        if (rose_node->count < 3) {
183
                rose_node->neighbour[rose_node->count] = rose_neigh;
184
                rose_node->count++;
185
                rose_neigh->count++;
186
        }
187
 
188
        return 0;
189
}
190
 
191
static void rose_remove_node(struct rose_node *rose_node)
192
{
193
        struct rose_node *s;
194
        unsigned long flags;
195
 
196
        save_flags(flags);
197
        cli();
198
 
199
        if ((s = rose_node_list) == rose_node) {
200
                rose_node_list = rose_node->next;
201
                restore_flags(flags);
202
                kfree(rose_node);
203
                return;
204
        }
205
 
206
        while (s != NULL && s->next != NULL) {
207
                if (s->next == rose_node) {
208
                        s->next = rose_node->next;
209
                        restore_flags(flags);
210
                        kfree(rose_node);
211
                        return;
212
                }
213
 
214
                s = s->next;
215
        }
216
 
217
        restore_flags(flags);
218
}
219
 
220
static void rose_remove_neigh(struct rose_neigh *rose_neigh)
221
{
222
        struct rose_neigh *s;
223
        unsigned long flags;
224
 
225
        rose_stop_ftimer(rose_neigh);
226
        rose_stop_t0timer(rose_neigh);
227
 
228
        skb_queue_purge(&rose_neigh->queue);
229
 
230
        save_flags(flags); cli();
231
 
232
        if ((s = rose_neigh_list) == rose_neigh) {
233
                rose_neigh_list = rose_neigh->next;
234
                restore_flags(flags);
235
                if (rose_neigh->digipeat != NULL)
236
                        kfree(rose_neigh->digipeat);
237
                kfree(rose_neigh);
238
                return;
239
        }
240
 
241
        while (s != NULL && s->next != NULL) {
242
                if (s->next == rose_neigh) {
243
                        s->next = rose_neigh->next;
244
                        restore_flags(flags);
245
                        if (rose_neigh->digipeat != NULL)
246
                                kfree(rose_neigh->digipeat);
247
                        kfree(rose_neigh);
248
                        return;
249
                }
250
 
251
                s = s->next;
252
        }
253
 
254
        restore_flags(flags);
255
}
256
 
257
static void rose_remove_route(struct rose_route *rose_route)
258
{
259
        struct rose_route *s;
260
        unsigned long flags;
261
 
262
        if (rose_route->neigh1 != NULL)
263
                rose_route->neigh1->use--;
264
 
265
        if (rose_route->neigh2 != NULL)
266
                rose_route->neigh2->use--;
267
 
268
        save_flags(flags); cli();
269
 
270
        if ((s = rose_route_list) == rose_route) {
271
                rose_route_list = rose_route->next;
272
                restore_flags(flags);
273
                kfree(rose_route);
274
                return;
275
        }
276
 
277
        while (s != NULL && s->next != NULL) {
278
                if (s->next == rose_route) {
279
                        s->next = rose_route->next;
280
                        restore_flags(flags);
281
                        kfree(rose_route);
282
                        return;
283
                }
284
 
285
                s = s->next;
286
        }
287
 
288
        restore_flags(flags);
289
}
290
 
291
/*
292
 *      "Delete" a node. Strictly speaking remove a route to a node. The node
293
 *      is only deleted if no routes are left to it.
294
 */
295
static int rose_del_node(struct rose_route_struct *rose_route, struct net_device *dev)
296
{
297
        struct rose_node  *rose_node;
298
        struct rose_neigh *rose_neigh;
299
        int i;
300
 
301
        for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
302
                if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0))
303
                        break;
304
 
305
        if (rose_node == NULL) return -EINVAL;
306
 
307
        if (rose_node->loopback) return -EINVAL;
308
 
309
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next)
310
                if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev)
311
                        break;
312
 
313
        if (rose_neigh == NULL) return -EINVAL;
314
 
315
        for (i = 0; i < rose_node->count; i++) {
316
                if (rose_node->neighbour[i] == rose_neigh) {
317
                        rose_neigh->count--;
318
 
319
                        if (rose_neigh->count == 0 && rose_neigh->use == 0)
320
                                rose_remove_neigh(rose_neigh);
321
 
322
                        rose_node->count--;
323
 
324
                        if (rose_node->count == 0) {
325
                                rose_remove_node(rose_node);
326
                        } else {
327
                                switch (i) {
328
                                        case 0:
329
                                                rose_node->neighbour[0] = rose_node->neighbour[1];
330
                                        case 1:
331
                                                rose_node->neighbour[1] = rose_node->neighbour[2];
332
                                        case 2:
333
                                                break;
334
                                }
335
                        }
336
 
337
                        return 0;
338
                }
339
        }
340
 
341
        return -EINVAL;
342
}
343
 
344
/*
345
 *      Add the loopback neighbour.
346
 */
347
int rose_add_loopback_neigh(void)
348
{
349
        unsigned long flags;
350
 
351
        if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL)
352
                return -ENOMEM;
353
 
354
        rose_loopback_neigh->callsign  = null_ax25_address;
355
        rose_loopback_neigh->digipeat  = NULL;
356
        rose_loopback_neigh->ax25      = NULL;
357
        rose_loopback_neigh->dev       = NULL;
358
        rose_loopback_neigh->count     = 0;
359
        rose_loopback_neigh->use       = 0;
360
        rose_loopback_neigh->dce_mode  = 1;
361
        rose_loopback_neigh->loopback  = 1;
362
        rose_loopback_neigh->number    = rose_neigh_no++;
363
        rose_loopback_neigh->restarted = 1;
364
 
365
        skb_queue_head_init(&rose_loopback_neigh->queue);
366
 
367
        init_timer(&rose_loopback_neigh->ftimer);
368
        init_timer(&rose_loopback_neigh->t0timer);
369
 
370
        save_flags(flags); cli();
371
        rose_loopback_neigh->next = rose_neigh_list;
372
        rose_neigh_list           = rose_loopback_neigh;
373
        restore_flags(flags);
374
 
375
        return 0;
376
}
377
 
378
/*
379
 *      Add a loopback node.
380
 */
381
int rose_add_loopback_node(rose_address *address)
382
{
383
        struct rose_node *rose_node;
384
        unsigned long flags;
385
 
386
        for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
387
                if ((rose_node->mask == 10) && (rosecmpm(address, &rose_node->address, 10) == 0) && rose_node->loopback)
388
                        break;
389
 
390
        if (rose_node != NULL) return 0;
391
 
392
        if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL)
393
                return -ENOMEM;
394
 
395
        rose_node->address      = *address;
396
        rose_node->mask         = 10;
397
        rose_node->count        = 1;
398
        rose_node->loopback     = 1;
399
        rose_node->neighbour[0] = rose_loopback_neigh;
400
 
401
        /* Insert at the head of list. Address is always mask=10 */
402
        save_flags(flags); cli();
403
        rose_node->next = rose_node_list;
404
        rose_node_list  = rose_node;
405
        restore_flags(flags);
406
 
407
        rose_loopback_neigh->count++;
408
 
409
        return 0;
410
}
411
 
412
/*
413
 *      Delete a loopback node.
414
 */
415
void rose_del_loopback_node(rose_address *address)
416
{
417
        struct rose_node *rose_node;
418
 
419
        for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
420
                if ((rose_node->mask == 10) && (rosecmpm(address, &rose_node->address, 10) == 0) && rose_node->loopback)
421
                        break;
422
 
423
        if (rose_node == NULL) return;
424
 
425
        rose_remove_node(rose_node);
426
 
427
        rose_loopback_neigh->count--;
428
}
429
 
430
/*
431
 *      A device has been removed. Remove its routes and neighbours.
432
 */
433
void rose_rt_device_down(struct net_device *dev)
434
{
435
        struct rose_neigh *s, *rose_neigh = rose_neigh_list;
436
        struct rose_node  *t, *rose_node;
437
        int i;
438
 
439
        while (rose_neigh != NULL) {
440
                s          = rose_neigh;
441
                rose_neigh = rose_neigh->next;
442
 
443
                if (s->dev == dev) {
444
                        rose_node = rose_node_list;
445
 
446
                        while (rose_node != NULL) {
447
                                t         = rose_node;
448
                                rose_node = rose_node->next;
449
 
450
                                for (i = 0; i < t->count; i++) {
451
                                        if (t->neighbour[i] == s) {
452
                                                t->count--;
453
 
454
                                                switch (i) {
455
                                                        case 0:
456
                                                                t->neighbour[0] = t->neighbour[1];
457
                                                        case 1:
458
                                                                t->neighbour[1] = t->neighbour[2];
459
                                                        case 2:
460
                                                                break;
461
                                                }
462
                                        }
463
                                }
464
 
465
                                if (t->count <= 0)
466
                                        rose_remove_node(t);
467
                        }
468
 
469
                        rose_remove_neigh(s);
470
                }
471
        }
472
}
473
 
474
/*
475
 *      A device has been removed. Remove its links.
476
 */
477
void rose_route_device_down(struct net_device *dev)
478
{
479
        struct rose_route *s, *rose_route = rose_route_list;
480
 
481
        while (rose_route != NULL) {
482
                s          = rose_route;
483
                rose_route = rose_route->next;
484
 
485
                if (s->neigh1->dev == dev || s->neigh2->dev == dev)
486
                        rose_remove_route(s);
487
        }
488
}
489
 
490
/*
491
 *      Clear all nodes and neighbours out, except for neighbours with
492
 *      active connections going through them.
493
 *  Do not clear loopback neighbour and nodes.
494
 */
495
static int rose_clear_routes(void)
496
{
497
        struct rose_neigh *s, *rose_neigh = rose_neigh_list;
498
        struct rose_node  *t, *rose_node  = rose_node_list;
499
 
500
        while (rose_node != NULL) {
501
                t         = rose_node;
502
                rose_node = rose_node->next;
503
                if (!t->loopback)
504
                        rose_remove_node(t);
505
        }
506
 
507
        while (rose_neigh != NULL) {
508
                s          = rose_neigh;
509
                rose_neigh = rose_neigh->next;
510
 
511
                if (s->use == 0 && !s->loopback) {
512
                        s->count = 0;
513
                        rose_remove_neigh(s);
514
                }
515
        }
516
 
517
        return 0;
518
}
519
 
520
/*
521
 *      Check that the device given is a valid AX.25 interface that is "up".
522
 */
523
struct net_device *rose_ax25_dev_get(char *devname)
524
{
525
        struct net_device *dev;
526
 
527
        if ((dev = dev_get_by_name(devname)) == NULL)
528
                return NULL;
529
 
530
        if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
531
                return dev;
532
 
533
        dev_put(dev);
534
        return NULL;
535
}
536
 
537
/*
538
 *      Find the first active ROSE device, usually "rose0".
539
 */
540
struct net_device *rose_dev_first(void)
541
{
542
        struct net_device *dev, *first = NULL;
543
 
544
        read_lock(&dev_base_lock);
545
        for (dev = dev_base; dev != NULL; dev = dev->next) {
546
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
547
                        if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
548
                                first = dev;
549
        }
550
        read_unlock(&dev_base_lock);
551
 
552
        return first;
553
}
554
 
555
/*
556
 *      Find the ROSE device for the given address.
557
 */
558
struct net_device *rose_dev_get(rose_address *addr)
559
{
560
        struct net_device *dev;
561
 
562
        read_lock(&dev_base_lock);
563
        for (dev = dev_base; dev != NULL; dev = dev->next) {
564
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
565
                        dev_hold(dev);
566
                        goto out;
567
                }
568
        }
569
out:
570
        read_unlock(&dev_base_lock);
571
        return dev;
572
}
573
 
574
static int rose_dev_exists(rose_address *addr)
575
{
576
        struct net_device *dev;
577
 
578
        read_lock(&dev_base_lock);
579
        for (dev = dev_base; dev != NULL; dev = dev->next) {
580
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
581
                        goto out;
582
        }
583
out:
584
        read_unlock(&dev_base_lock);
585
        return dev != NULL;
586
}
587
 
588
 
589
 
590
 
591
struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neigh)
592
{
593
        struct rose_route *rose_route;
594
 
595
        for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next)
596
                if ((rose_route->neigh1 == neigh && rose_route->lci1 == lci) ||
597
                    (rose_route->neigh2 == neigh && rose_route->lci2 == lci))
598
                        return rose_route;
599
 
600
        return NULL;
601
}
602
 
603
/*
604
 *      Find a neighbour given a ROSE address.
605
 */
606
struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, unsigned char *diagnostic)
607
{
608
        struct rose_node *node;
609
        int failed = 0;
610
        int i;
611
 
612
        for (node = rose_node_list; node != NULL; node = node->next) {
613
                if (rosecmpm(addr, &node->address, node->mask) == 0) {
614
                        for (i = 0; i < node->count; i++) {
615
                                if (!rose_ftimer_running(node->neighbour[i])) {
616
                                        return node->neighbour[i]; }
617
                                else
618
                                        failed = 1;
619
                        }
620
                        break;
621
                }
622
        }
623
 
624
        if (failed) {
625
                *cause      = ROSE_OUT_OF_ORDER;
626
                *diagnostic = 0;
627
        } else {
628
                *cause      = ROSE_NOT_OBTAINABLE;
629
                *diagnostic = 0;
630
        }
631
 
632
        return NULL;
633
}
634
 
635
/*
636
 *      Handle the ioctls that control the routing functions.
637
 */
638
int rose_rt_ioctl(unsigned int cmd, void *arg)
639
{
640
        struct rose_route_struct rose_route;
641
        struct net_device *dev;
642
        int err;
643
 
644
        switch (cmd) {
645
 
646
                case SIOCADDRT:
647
                        if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
648
                                return -EFAULT;
649
                        if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
650
                                return -EINVAL;
651
                        if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */
652
                                dev_put(dev);
653
                                return -EINVAL;
654
                        }
655
                        if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
656
                                return -EINVAL;
657
 
658
                        err = rose_add_node(&rose_route, dev);
659
                        dev_put(dev);
660
                        return err;
661
 
662
                case SIOCDELRT:
663
                        if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
664
                                return -EFAULT;
665
                        if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
666
                                return -EINVAL;
667
                        err = rose_del_node(&rose_route, dev);
668
                        dev_put(dev);
669
                        return err;
670
 
671
 
672
                case SIOCRSCLRRT:
673
                        return rose_clear_routes();
674
 
675
                default:
676
                        return -EINVAL;
677
        }
678
 
679
        return 0;
680
}
681
 
682
static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
683
{
684
        struct rose_route *rose_route, *s;
685
 
686
        rose_neigh->restarted = 0;
687
 
688
        rose_stop_t0timer(rose_neigh);
689
        rose_start_ftimer(rose_neigh);
690
 
691
        skb_queue_purge(&rose_neigh->queue);
692
 
693
        rose_route = rose_route_list;
694
 
695
        while (rose_route != NULL) {
696
                if ((rose_route->neigh1 == rose_neigh && rose_route->neigh2 == rose_neigh) ||
697
                    (rose_route->neigh1 == rose_neigh && rose_route->neigh2 == NULL)       ||
698
                    (rose_route->neigh2 == rose_neigh && rose_route->neigh1 == NULL)) {
699
                        s = rose_route->next;
700
                        rose_remove_route(rose_route);
701
                        rose_route = s;
702
                        continue;
703
                }
704
 
705
                if (rose_route->neigh1 == rose_neigh) {
706
                        rose_route->neigh1->use--;
707
                        rose_route->neigh1 = NULL;
708
                        rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0);
709
                }
710
 
711
                if (rose_route->neigh2 == rose_neigh) {
712
                        rose_route->neigh2->use--;
713
                        rose_route->neigh2 = NULL;
714
                        rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0);
715
                }
716
 
717
                rose_route = rose_route->next;
718
        }
719
}
720
 
721
/*
722
 *      A level 2 link has timed out, therefore it appears to be a poor link,
723
 *      then don't use that neighbour until it is reset. Blow away all through
724
 *      routes and connections using this route.
725
 */
726
void rose_link_failed(ax25_cb *ax25, int reason)
727
{
728
        struct rose_neigh *rose_neigh;
729
 
730
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next)
731
                if (rose_neigh->ax25 == ax25)
732
                        break;
733
 
734
        if (rose_neigh == NULL) return;
735
 
736
        rose_neigh->ax25 = NULL;
737
 
738
        rose_del_route_by_neigh(rose_neigh);
739
        rose_kill_by_neigh(rose_neigh);
740
}
741
 
742
/*
743
 *      A device has been "downed" remove its link status. Blow away all
744
 *      through routes and connections that use this device.
745
 */
746
void rose_link_device_down(struct net_device *dev)
747
{
748
        struct rose_neigh *rose_neigh;
749
 
750
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) {
751
                if (rose_neigh->dev == dev) {
752
                        rose_del_route_by_neigh(rose_neigh);
753
                        rose_kill_by_neigh(rose_neigh);
754
                }
755
        }
756
}
757
 
758
/*
759
 *      Route a frame to an appropriate AX.25 connection.
760
 */
761
int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
762
{
763
        struct rose_neigh *rose_neigh, *new_neigh;
764
        struct rose_route *rose_route;
765
        struct rose_facilities_struct facilities;
766
        rose_address *src_addr, *dest_addr;
767
        struct sock *sk;
768
        unsigned short frametype;
769
        unsigned int lci, new_lci;
770
        unsigned char cause, diagnostic;
771
        struct net_device *dev;
772
        unsigned long flags;
773
        int len;
774
 
775
#if 0
776
        if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
777
                return 0;
778
#endif
779
 
780
        frametype = skb->data[2];
781
        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
782
        src_addr  = (rose_address *)(skb->data + 9);
783
        dest_addr = (rose_address *)(skb->data + 4);
784
 
785
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next)
786
                if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->ax25_dev->dev == rose_neigh->dev)
787
                        break;
788
 
789
        if (rose_neigh == NULL) {
790
                printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->dest_addr));
791
                return 0;
792
        }
793
 
794
        /*
795
         *      Obviously the link is working, halt the ftimer.
796
         */
797
        rose_stop_ftimer(rose_neigh);
798
 
799
        /*
800
         *      LCI of zero is always for us, and its always a restart
801
         *      frame.
802
         */
803
        if (lci == 0) {
804
                rose_link_rx_restart(skb, rose_neigh, frametype);
805
                return 0;
806
        }
807
 
808
        /*
809
         *      Find an existing socket.
810
         */
811
        if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) {
812
                if (frametype == ROSE_CALL_REQUEST) {
813
                        /* Remove an existing unused socket */
814
                        rose_clear_queues(sk);
815
                        sk->protinfo.rose->cause      = ROSE_NETWORK_CONGESTION;
816
                        sk->protinfo.rose->diagnostic = 0;
817
                        sk->protinfo.rose->neighbour->use--;
818
                        sk->protinfo.rose->neighbour = NULL;
819
                        sk->protinfo.rose->lci   = 0;
820
                        sk->protinfo.rose->state = ROSE_STATE_0;
821
                        sk->state                = TCP_CLOSE;
822
                        sk->err                  = 0;
823
                        sk->shutdown            |= SEND_SHUTDOWN;
824
                        if (!sk->dead)
825
                                sk->state_change(sk);
826
                        sk->dead                 = 1;
827
                }
828
                else {
829
                        skb->h.raw = skb->data;
830
                        return rose_process_rx_frame(sk, skb);
831
                }
832
        }
833
 
834
        /*
835
         *      Is is a Call Request and is it for us ?
836
         */
837
        if (frametype == ROSE_CALL_REQUEST)
838
                if ((dev = rose_dev_get(dest_addr)) != NULL) {
839
                        int err = rose_rx_call_request(skb, dev, rose_neigh, lci);
840
                        dev_put(dev);
841
                        return err;
842
                }
843
 
844
        if (!sysctl_rose_routing_control) {
845
                rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0);
846
                return 0;
847
        }
848
 
849
        /*
850
         *      Route it to the next in line if we have an entry for it.
851
         */
852
        for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
853
                if (rose_route->lci1 == lci && rose_route->neigh1 == rose_neigh) {
854
                        if (frametype == ROSE_CALL_REQUEST) {
855
                                /* F6FBB - Remove an existing unused route */
856
                                rose_remove_route(rose_route);
857
                                break;
858
                        } else if (rose_route->neigh2 != NULL) {
859
                                skb->data[0] &= 0xF0;
860
                                skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
861
                                skb->data[1]  = (rose_route->lci2 >> 0) & 0xFF;
862
                                rose_transmit_link(skb, rose_route->neigh2);
863
                                if (frametype == ROSE_CLEAR_CONFIRMATION)
864
                                        rose_remove_route(rose_route);
865
                                return 1;
866
                        } else {
867
                                if (frametype == ROSE_CLEAR_CONFIRMATION)
868
                                        rose_remove_route(rose_route);
869
                                return 0;
870
                        }
871
                }
872
                if (rose_route->lci2 == lci && rose_route->neigh2 == rose_neigh) {
873
                        if (frametype == ROSE_CALL_REQUEST) {
874
                                /* F6FBB - Remove an existing unused route */
875
                                rose_remove_route(rose_route);
876
                                break;
877
                        } else if (rose_route->neigh1 != NULL) {
878
                                skb->data[0] &= 0xF0;
879
                                skb->data[0] |= (rose_route->lci1 >> 8) & 0x0F;
880
                                skb->data[1]  = (rose_route->lci1 >> 0) & 0xFF;
881
                                rose_transmit_link(skb, rose_route->neigh1);
882
                                if (frametype == ROSE_CLEAR_CONFIRMATION)
883
                                        rose_remove_route(rose_route);
884
                                return 1;
885
                        } else {
886
                                if (frametype == ROSE_CLEAR_CONFIRMATION)
887
                                        rose_remove_route(rose_route);
888
                                return 0;
889
                        }
890
                }
891
        }
892
 
893
        /*
894
         *      We know that:
895
         *      1. The frame isn't for us,
896
         *      2. It isn't "owned" by any existing route.
897
         */
898
        if (frametype != ROSE_CALL_REQUEST)     /* XXX */
899
                return 0;
900
 
901
        len  = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
902
        len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
903
 
904
        memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
905
 
906
        if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {
907
                rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
908
                return 0;
909
        }
910
 
911
        /*
912
         *      Check for routing loops.
913
         */
914
        for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
915
                if (rose_route->rand == facilities.rand &&
916
                    rosecmp(src_addr, &rose_route->src_addr) == 0 &&
917
                    ax25cmp(&facilities.dest_call, &rose_route->src_call) == 0 &&
918
                    ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) {
919
                        rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 120);
920
                        return 0;
921
                }
922
        }
923
 
924
        if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) {
925
                rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic);
926
                return 0;
927
        }
928
 
929
        if ((new_lci = rose_new_lci(new_neigh)) == 0) {
930
                rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71);
931
                return 0;
932
        }
933
 
934
        if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
935
                rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120);
936
                return 0;
937
        }
938
 
939
        rose_route->lci1      = lci;
940
        rose_route->src_addr  = *src_addr;
941
        rose_route->dest_addr = *dest_addr;
942
        rose_route->src_call  = facilities.dest_call;
943
        rose_route->dest_call = facilities.source_call;
944
        rose_route->rand      = facilities.rand;
945
        rose_route->neigh1    = rose_neigh;
946
        rose_route->lci2      = new_lci;
947
        rose_route->neigh2    = new_neigh;
948
 
949
        rose_route->neigh1->use++;
950
        rose_route->neigh2->use++;
951
 
952
        save_flags(flags); cli();
953
        rose_route->next = rose_route_list;
954
        rose_route_list  = rose_route;
955
        restore_flags(flags);
956
 
957
        skb->data[0] &= 0xF0;
958
        skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
959
        skb->data[1]  = (rose_route->lci2 >> 0) & 0xFF;
960
 
961
        rose_transmit_link(skb, rose_route->neigh2);
962
 
963
        return 1;
964
}
965
 
966
int rose_nodes_get_info(char *buffer, char **start, off_t offset, int length)
967
{
968
        struct rose_node *rose_node;
969
        int len     = 0;
970
        off_t pos   = 0;
971
        off_t begin = 0;
972
        int i;
973
 
974
        cli();
975
 
976
        len += sprintf(buffer, "address    mask n neigh neigh neigh\n");
977
 
978
        for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) {
979
                /* if (rose_node->loopback) {
980
                        len += sprintf(buffer + len, "%-10s %04d 1 loopback\n",
981
                                rose2asc(&rose_node->address),
982
                                rose_node->mask);
983
                } else { */
984
                        len += sprintf(buffer + len, "%-10s %04d %d",
985
                                rose2asc(&rose_node->address),
986
                                rose_node->mask,
987
                                rose_node->count);
988
 
989
                        for (i = 0; i < rose_node->count; i++)
990
                                len += sprintf(buffer + len, " %05d",
991
                                        rose_node->neighbour[i]->number);
992
 
993
                        len += sprintf(buffer + len, "\n");
994
                /* } */
995
 
996
                pos = begin + len;
997
 
998
                if (pos < offset) {
999
                        len   = 0;
1000
                        begin = pos;
1001
                }
1002
 
1003
                if (pos > offset + length)
1004
                        break;
1005
        }
1006
 
1007
        sti();
1008
 
1009
        *start = buffer + (offset - begin);
1010
        len   -= (offset - begin);
1011
 
1012
        if (len > length) len = length;
1013
 
1014
        return len;
1015
}
1016
 
1017
int rose_neigh_get_info(char *buffer, char **start, off_t offset, int length)
1018
{
1019
        struct rose_neigh *rose_neigh;
1020
        int len     = 0;
1021
        off_t pos   = 0;
1022
        off_t begin = 0;
1023
        int i;
1024
 
1025
        cli();
1026
 
1027
        len += sprintf(buffer, "addr  callsign  dev  count use mode restart  t0  tf digipeaters\n");
1028
 
1029
        for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) {
1030
                /* if (!rose_neigh->loopback) { */
1031
                        len += sprintf(buffer + len, "%05d %-9s %-4s   %3d %3d  %3s     %3s %3lu %3lu",
1032
                                rose_neigh->number,
1033
                                (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign),
1034
                                rose_neigh->dev ? rose_neigh->dev->name : "???",
1035
                                rose_neigh->count,
1036
                                rose_neigh->use,
1037
                                (rose_neigh->dce_mode) ? "DCE" : "DTE",
1038
                                (rose_neigh->restarted) ? "yes" : "no",
1039
                                ax25_display_timer(&rose_neigh->t0timer) / HZ,
1040
                                ax25_display_timer(&rose_neigh->ftimer)  / HZ);
1041
 
1042
                        if (rose_neigh->digipeat != NULL) {
1043
                                for (i = 0; i < rose_neigh->digipeat->ndigi; i++)
1044
                                        len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i]));
1045
                        }
1046
 
1047
                        len += sprintf(buffer + len, "\n");
1048
 
1049
                        pos = begin + len;
1050
 
1051
                        if (pos < offset) {
1052
                                len   = 0;
1053
                                begin = pos;
1054
                        }
1055
 
1056
                        if (pos > offset + length)
1057
                                break;
1058
                /* } */
1059
        }
1060
 
1061
        sti();
1062
 
1063
        *start = buffer + (offset - begin);
1064
        len   -= (offset - begin);
1065
 
1066
        if (len > length) len = length;
1067
 
1068
        return len;
1069
}
1070
 
1071
int rose_routes_get_info(char *buffer, char **start, off_t offset, int length)
1072
{
1073
        struct rose_route *rose_route;
1074
        int len     = 0;
1075
        off_t pos   = 0;
1076
        off_t begin = 0;
1077
 
1078
        cli();
1079
 
1080
        len += sprintf(buffer, "lci  address     callsign   neigh  <-> lci  address     callsign   neigh\n");
1081
 
1082
        for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
1083
                if (rose_route->neigh1 != NULL) {
1084
                        len += sprintf(buffer + len, "%3.3X  %-10s  %-9s  %05d      ",
1085
                                rose_route->lci1,
1086
                                rose2asc(&rose_route->src_addr),
1087
                                ax2asc(&rose_route->src_call),
1088
                                rose_route->neigh1->number);
1089
                } else {
1090
                        len += sprintf(buffer + len, "000  *           *          00000      ");
1091
                }
1092
 
1093
                if (rose_route->neigh2 != NULL) {
1094
                        len += sprintf(buffer + len, "%3.3X  %-10s  %-9s  %05d\n",
1095
                                rose_route->lci2,
1096
                                rose2asc(&rose_route->dest_addr),
1097
                                ax2asc(&rose_route->dest_call),
1098
                                rose_route->neigh2->number);
1099
                } else {
1100
                        len += sprintf(buffer + len, "000  *           *          00000\n");
1101
                }
1102
 
1103
                pos = begin + len;
1104
 
1105
                if (pos < offset) {
1106
                        len   = 0;
1107
                        begin = pos;
1108
                }
1109
 
1110
                if (pos > offset + length)
1111
                        break;
1112
        }
1113
 
1114
        sti();
1115
 
1116
        *start = buffer + (offset - begin);
1117
        len   -= (offset - begin);
1118
 
1119
        if (len > length) len = length;
1120
 
1121
        return len;
1122
}
1123
 
1124
/*
1125
 *      Release all memory associated with ROSE routing structures.
1126
 */
1127
void __exit rose_rt_free(void)
1128
{
1129
        struct rose_neigh *s, *rose_neigh = rose_neigh_list;
1130
        struct rose_node  *t, *rose_node  = rose_node_list;
1131
        struct rose_route *u, *rose_route = rose_route_list;
1132
 
1133
        while (rose_neigh != NULL) {
1134
                s          = rose_neigh;
1135
                rose_neigh = rose_neigh->next;
1136
 
1137
                rose_remove_neigh(s);
1138
        }
1139
 
1140
        while (rose_node != NULL) {
1141
                t         = rose_node;
1142
                rose_node = rose_node->next;
1143
 
1144
                rose_remove_node(t);
1145
        }
1146
 
1147
        while (rose_route != NULL) {
1148
                u          = rose_route;
1149
                rose_route = rose_route->next;
1150
 
1151
                rose_remove_route(u);
1152
        }
1153
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.