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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*****************************************************************************
2
* wanmain.c     WAN Multiprotocol Router Module. Main code.
3
*
4
*               This module is completely hardware-independent and provides
5
*               the following common services for the WAN Link Drivers:
6
*                o WAN device managenment (registering, unregistering)
7
*                o Network interface management
8
*                o Physical connection management (dial-up, incoming calls)
9
*                o Logical connection management (switched virtual circuits)
10
*                o Protocol encapsulation/decapsulation
11
*
12
* Author:       Gideon Hack
13
*
14
* Copyright:    (c) 1995-1999 Sangoma Technologies Inc.
15
*
16
*               This program is free software; you can redistribute it and/or
17
*               modify it under the terms of the GNU General Public License
18
*               as published by the Free Software Foundation; either version
19
*               2 of the License, or (at your option) any later version.
20
* ============================================================================
21
* Nov 24, 2000  Nenad Corbic    Updated for 2.4.X kernels
22
* Nov 07, 2000  Nenad Corbic    Fixed the Mulit-Port PPP for kernels 2.2.16 and
23
*                               greater.
24
* Aug 2,  2000  Nenad Corbic    Block the Multi-Port PPP from running on
25
*                               kernels 2.2.16 or greater.  The SyncPPP
26
*                               has changed.
27
* Jul 13, 2000  Nenad Corbic    Added SyncPPP support
28
*                               Added extra debugging in device_setup().
29
* Oct 01, 1999  Gideon Hack     Update for s514 PCI card
30
* Dec 27, 1996  Gene Kozin      Initial version (based on Sangoma's WANPIPE)
31
* Jan 16, 1997  Gene Kozin      router_devlist made public
32
* Jan 31, 1997  Alan Cox        Hacked it about a bit for 2.1
33
* Jun 27, 1997  Alan Cox        realigned with vendor code
34
* Oct 15, 1997  Farhan Thawar   changed wan_encapsulate to add a pad byte of 0
35
* Apr 20, 1998  Alan Cox        Fixed 2.1 symbols
36
* May 17, 1998  K. Baranowski   Fixed SNAP encapsulation in wan_encapsulate
37
* Dec 15, 1998  Arnaldo Melo    support for firmwares of up to 128000 bytes
38
*                               check wandev->setup return value
39
* Dec 22, 1998  Arnaldo Melo    vmalloc/vfree used in device_setup to allocate
40
*                               kernel memory and copy configuration data to
41
*                               kernel space (for big firmwares)
42
* Jun 02, 1999  Gideon Hack     Updates for Linux 2.0.X and 2.2.X kernels.
43
*****************************************************************************/
44
 
45
#include <linux/version.h>
46
#include <linux/config.h>
47
#include <linux/stddef.h>       /* offsetof(), etc. */
48
#include <linux/errno.h>        /* return codes */
49
#include <linux/kernel.h>
50
#include <linux/module.h>       /* support for loadable modules */
51
#include <linux/slab.h> /* kmalloc(), kfree() */
52
#include <linux/mm.h>           /* verify_area(), etc. */
53
#include <linux/string.h>       /* inline mem*, str* functions */
54
 
55
#include <asm/byteorder.h>      /* htons(), etc. */
56
#include <linux/wanrouter.h>    /* WAN router API definitions */
57
 
58
 
59
#if defined(LINUX_2_4)
60
 #include <linux/vmalloc.h>     /* vmalloc, vfree */
61
 #include <asm/uaccess.h>        /* copy_to/from_user */
62
 #include <linux/init.h>         /* __initfunc et al. */
63
 
64
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
65
 #include <net/syncppp.h>
66
#else
67
 #include <../drivers/net/wan/syncppp.h>
68
#endif
69
 
70
#elif defined(LINUX_2_1) 
71
 #define LINUX_2_1
72
 #include <linux/vmalloc.h>     /* vmalloc, vfree */
73
 #include <asm/uaccess.h>        /* copy_to/from_user */
74
 #include <linux/init.h>         /* __initfunc et al. */
75
 #include <../drivers/net/syncppp.h>
76
 
77
#else
78
 #include <asm/segment.h>       /* kernel <-> user copy */
79
#endif
80
 
81
#define KMEM_SAFETYZONE 8
82
 
83
/***********FOR DEBUGGING PURPOSES*********************************************
84
static void * dbg_kmalloc(unsigned int size, int prio, int line) {
85
        int i = 0;
86
        void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
87
        char * c1 = v;
88
        c1 += sizeof(unsigned int);
89
        *((unsigned int *)v) = size;
90
 
91
        for (i = 0; i < KMEM_SAFETYZONE; i++) {
92
                c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
93
                c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
94
                c1 += 8;
95
        }
96
        c1 += size;
97
        for (i = 0; i < KMEM_SAFETYZONE; i++) {
98
                c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
99
                c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
100
                c1 += 8;
101
        }
102
        v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
103
        printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
104
        return v;
105
}
106
static void dbg_kfree(void * v, int line) {
107
        unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
108
        unsigned int size = *sp;
109
        char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
110
        int i = 0;
111
        for (i = 0; i < KMEM_SAFETYZONE; i++) {
112
                if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
113
                    || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
114
                        printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
115
                        printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
116
                                        c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
117
                }
118
                c1 += 8;
119
        }
120
        c1 += size;
121
        for (i = 0; i < KMEM_SAFETYZONE; i++) {
122
                if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
123
                    || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
124
                   ) {
125
                        printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
126
                        printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
127
                                        c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
128
                }
129
                c1 += 8;
130
        }
131
        printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
132
        v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
133
        kfree(v);
134
}
135
 
136
#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
137
#define kfree(x) dbg_kfree(x,__LINE__)
138
*****************************************************************************/
139
 
140
 
141
/*
142
 *      Function Prototypes
143
 */
144
 
145
/*
146
 *      Kernel loadable module interface.
147
 */
148
#ifdef MODULE
149
int init_module (void);
150
void cleanup_module (void);
151
#endif
152
 
153
/*
154
 *      WAN device IOCTL handlers
155
 */
156
 
157
static int device_setup(wan_device_t *wandev, wandev_conf_t *u_conf);
158
static int device_stat(wan_device_t *wandev, wandev_stat_t *u_stat);
159
static int device_shutdown(wan_device_t *wandev);
160
static int device_new_if(wan_device_t *wandev, wanif_conf_t *u_conf);
161
static int device_del_if(wan_device_t *wandev, char *u_name);
162
 
163
/*
164
 *      Miscellaneous
165
 */
166
 
167
static wan_device_t *find_device (char *name);
168
static int delete_interface (wan_device_t *wandev, char *name);
169
void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
170
void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
171
 
172
 
173
 
174
/*
175
 *      Global Data
176
 */
177
 
178
static char fullname[]          = "Sangoma WANPIPE Router";
179
static char copyright[]         = "(c) 1995-2000 Sangoma Technologies Inc.";
180
static char modname[]           = ROUTER_NAME;  /* short module name */
181
wan_device_t* router_devlist    = NULL; /* list of registered devices */
182
static int devcnt               = 0;
183
 
184
/*
185
 *      Organize Unique Identifiers for encapsulation/decapsulation
186
 */
187
 
188
static unsigned char oui_ether[] = { 0x00, 0x00, 0x00 };
189
#if 0
190
static unsigned char oui_802_2[] = { 0x00, 0x80, 0xC2 };
191
#endif
192
 
193
#ifndef MODULE
194
 
195
int wanrouter_init(void)
196
{
197
        int err;
198
        extern int wanpipe_init(void);
199
        extern int sdladrv_init(void);
200
 
201
        printk(KERN_INFO "%s v%u.%u %s\n",
202
                fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
203
 
204
        err = wanrouter_proc_init();
205
        if (err){
206
                printk(KERN_INFO "%s: can't create entry in proc filesystem!\n", modname);
207
        }
208
 
209
        /*
210
         *      Initialise compiled in boards
211
         */
212
 
213
#ifdef CONFIG_VENDOR_SANGOMA
214
        sdladrv_init();
215
        wanpipe_init();
216
#endif  
217
 
218
        return err;
219
}
220
 
221
 
222
#ifdef LINUX_2_4
223
static void __exit wanrouter_cleanup (void)
224
{
225
        wanrouter_proc_cleanup();
226
}
227
#endif
228
 
229
#else
230
 
231
/*
232
 *      Kernel Loadable Module Entry Points
233
 */
234
 
235
/*
236
 *      Module 'insert' entry point.
237
 *      o print announcement
238
 *      o initialize static data
239
 *      o create /proc/net/router directory and static entries
240
 *
241
 *      Return: 0        Ok
242
 *              < 0     error.
243
 *      Context:        process
244
 */
245
 
246
int init_module (void)
247
{
248
        int err;
249
 
250
        printk(KERN_INFO "%s v%u.%u %s\n",
251
                fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
252
 
253
        err = wanrouter_proc_init();
254
 
255
        if (err){
256
                printk(KERN_INFO
257
                "%s: can't create entry in proc filesystem!\n", modname);
258
        }
259
        return err;
260
}
261
 
262
/*
263
 *      Module 'remove' entry point.
264
 *      o delete /proc/net/router directory and static entries.
265
 */
266
 
267
void cleanup_module (void)
268
{
269
        wanrouter_proc_cleanup();
270
}
271
 
272
#endif
273
 
274
/*
275
 *      Kernel APIs
276
 */
277
 
278
/*
279
 *      Register WAN device.
280
 *      o verify device credentials
281
 *      o create an entry for the device in the /proc/net/router directory
282
 *      o initialize internally maintained fields of the wan_device structure
283
 *      o link device data space to a singly-linked list
284
 *      o if it's the first device, then start kernel 'thread'
285
 *      o increment module use count
286
 *
287
 *      Return:
288
 *      0        Ok
289
 *      < 0     error.
290
 *
291
 *      Context:        process
292
 */
293
 
294
 
295
int register_wan_device(wan_device_t *wandev)
296
{
297
        int err, namelen;
298
 
299
        if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC) ||
300
            (wandev->name == NULL))
301
                return -EINVAL;
302
 
303
        namelen = strlen(wandev->name);
304
        if (!namelen || (namelen > WAN_DRVNAME_SZ))
305
                return -EINVAL;
306
 
307
        if (find_device(wandev->name) != NULL)
308
                return -EEXIST;
309
 
310
#ifdef WANDEBUG         
311
        printk(KERN_INFO "%s: registering WAN device %s\n",
312
                modname, wandev->name);
313
#endif
314
 
315
        /*
316
         *      Register /proc directory entry
317
         */
318
        err = wanrouter_proc_add(wandev);
319
        if (err) {
320
                printk(KERN_INFO
321
                        "%s: can't create /proc/net/router/%s entry!\n",
322
                        modname, wandev->name);
323
                return err;
324
        }
325
 
326
        /*
327
         *      Initialize fields of the wan_device structure maintained by the
328
         *      router and update local data.
329
         */
330
 
331
        wandev->ndev = 0;
332
        wandev->dev  = NULL;
333
        wandev->next = router_devlist;
334
        router_devlist = wandev;
335
        ++devcnt;
336
        MOD_INC_USE_COUNT;      /* prevent module from unloading */
337
        return 0;
338
}
339
 
340
/*
341
 *      Unregister WAN device.
342
 *      o shut down device
343
 *      o unlink device data space from the linked list
344
 *      o delete device entry in the /proc/net/router directory
345
 *      o decrement module use count
346
 *
347
 *      Return:         0        Ok
348
 *                      <0       error.
349
 *      Context:        process
350
 */
351
 
352
 
353
int unregister_wan_device(char *name)
354
{
355
        wan_device_t *wandev, *prev;
356
 
357
        if (name == NULL)
358
                return -EINVAL;
359
 
360
        for (wandev = router_devlist, prev = NULL;
361
                wandev && strcmp(wandev->name, name);
362
                prev = wandev, wandev = wandev->next)
363
                ;
364
        if (wandev == NULL)
365
                return -ENODEV;
366
 
367
#ifdef WANDEBUG         
368
        printk(KERN_INFO "%s: unregistering WAN device %s\n", modname, name);
369
#endif
370
 
371
        if (wandev->state != WAN_UNCONFIGURED) {
372
                device_shutdown(wandev);
373
        }
374
 
375
        if (prev){
376
                prev->next = wandev->next;
377
        }else{
378
                router_devlist = wandev->next;
379
        }
380
 
381
        --devcnt;
382
        wanrouter_proc_delete(wandev);
383
        MOD_DEC_USE_COUNT;
384
        return 0;
385
}
386
 
387
/*
388
 *      Encapsulate packet.
389
 *
390
 *      Return: encapsulation header size
391
 *              < 0     - unsupported Ethertype
392
 *
393
 *      Notes:
394
 *      1. This function may be called on interrupt context.
395
 */
396
 
397
 
398
int wanrouter_encapsulate (struct sk_buff *skb, netdevice_t *dev,
399
        unsigned short type)
400
{
401
        int hdr_len = 0;
402
 
403
        switch (type) {
404
        case ETH_P_IP:          /* IP datagram encapsulation */
405
                hdr_len += 1;
406
                skb_push(skb, 1);
407
                skb->data[0] = NLPID_IP;
408
                break;
409
 
410
        case ETH_P_IPX:         /* SNAP encapsulation */
411
        case ETH_P_ARP:
412
                hdr_len += 7;
413
                skb_push(skb, 7);
414
                skb->data[0] = 0;
415
                skb->data[1] = NLPID_SNAP;
416
                memcpy(&skb->data[2], oui_ether, sizeof(oui_ether));
417
                *((unsigned short*)&skb->data[5]) = htons(type);
418
                break;
419
 
420
        default:                /* Unknown packet type */
421
                printk(KERN_INFO
422
                        "%s: unsupported Ethertype 0x%04X on interface %s!\n",
423
                        modname, type, dev->name);
424
                hdr_len = -EINVAL;
425
        }
426
        return hdr_len;
427
}
428
 
429
 
430
/*
431
 *      Decapsulate packet.
432
 *
433
 *      Return: Ethertype (in network order)
434
 *                      0        unknown encapsulation
435
 *
436
 *      Notes:
437
 *      1. This function may be called on interrupt context.
438
 */
439
 
440
 
441
unsigned short wanrouter_type_trans (struct sk_buff *skb, netdevice_t *dev)
442
{
443
        int cnt = skb->data[0] ? 0 : 1;   /* there may be a pad present */
444
        unsigned short ethertype;
445
 
446
        switch (skb->data[cnt]) {
447
        case NLPID_IP:          /* IP datagramm */
448
                ethertype = htons(ETH_P_IP);
449
                cnt += 1;
450
                break;
451
 
452
        case NLPID_SNAP:        /* SNAP encapsulation */
453
                if (memcmp(&skb->data[cnt + 1], oui_ether, sizeof(oui_ether))){
454
                        printk(KERN_INFO
455
                                "%s: unsupported SNAP OUI %02X-%02X-%02X "
456
                                "on interface %s!\n", modname,
457
                                skb->data[cnt+1], skb->data[cnt+2],
458
                                skb->data[cnt+3], dev->name);
459
                        return 0;
460
                }
461
                ethertype = *((unsigned short*)&skb->data[cnt+4]);
462
                cnt += 6;
463
                break;
464
 
465
        /* add other protocols, e.g. CLNP, ESIS, ISIS, if needed */
466
 
467
        default:
468
                printk(KERN_INFO
469
                        "%s: unsupported NLPID 0x%02X on interface %s!\n",
470
                        modname, skb->data[cnt], dev->name);
471
                return 0;
472
        }
473
        skb->protocol = ethertype;
474
        skb->pkt_type = PACKET_HOST;    /*      Physically point to point */
475
        skb_pull(skb, cnt);
476
        skb->mac.raw  = skb->data;
477
        return ethertype;
478
}
479
 
480
 
481
/*
482
 *      WAN device IOCTL.
483
 *      o find WAN device associated with this node
484
 *      o execute requested action or pass command to the device driver
485
 */
486
 
487
int wanrouter_ioctl(struct inode *inode, struct file *file,
488
                unsigned int cmd, unsigned long arg)
489
{
490
        int err = 0;
491
        struct proc_dir_entry *dent;
492
        wan_device_t *wandev;
493
 
494
      #if defined (LINUX_2_1) || defined (LINUX_2_4)
495
        if (!capable(CAP_NET_ADMIN)){
496
                return -EPERM;
497
        }
498
      #endif
499
 
500
        if ((cmd >> 8) != ROUTER_IOCTL)
501
                return -EINVAL;
502
 
503
        dent = inode->u.generic_ip;
504
        if ((dent == NULL) || (dent->data == NULL))
505
                return -EINVAL;
506
 
507
        wandev = dent->data;
508
        if (wandev->magic != ROUTER_MAGIC)
509
                return -EINVAL;
510
 
511
        switch (cmd) {
512
        case ROUTER_SETUP:
513
                err = device_setup(wandev, (void*)arg);
514
                break;
515
 
516
        case ROUTER_DOWN:
517
                err = device_shutdown(wandev);
518
                break;
519
 
520
        case ROUTER_STAT:
521
                err = device_stat(wandev, (void*)arg);
522
                break;
523
 
524
        case ROUTER_IFNEW:
525
                err = device_new_if(wandev, (void*)arg);
526
                break;
527
 
528
        case ROUTER_IFDEL:
529
                err = device_del_if(wandev, (void*)arg);
530
                break;
531
 
532
        case ROUTER_IFSTAT:
533
                break;
534
 
535
        default:
536
                if ((cmd >= ROUTER_USER) &&
537
                    (cmd <= ROUTER_USER_MAX) &&
538
                    wandev->ioctl)
539
                        err = wandev->ioctl(wandev, cmd, arg);
540
                else err = -EINVAL;
541
        }
542
        return err;
543
}
544
 
545
/*
546
 *      WAN Driver IOCTL Handlers
547
 */
548
 
549
/*
550
 *      Setup WAN link device.
551
 *      o verify user address space
552
 *      o allocate kernel memory and copy configuration data to kernel space
553
 *      o if configuration data includes extension, copy it to kernel space too
554
 *      o call driver's setup() entry point
555
 */
556
 
557
static int device_setup (wan_device_t *wandev, wandev_conf_t *u_conf)
558
{
559
        void *data = NULL;
560
        wandev_conf_t *conf;
561
        int err = -EINVAL;
562
 
563
        if (wandev->setup == NULL){     /* Nothing to do ? */
564
                printk(KERN_INFO "%s: ERROR, No setup script: wandev->setup()\n",
565
                                wandev->name);
566
                return 0;
567
        }
568
 
569
      #ifdef LINUX_2_0 
570
        err = verify_area (VERIFY_READ, u_conf, sizeof(wandev_conf_t));
571
        if(err){
572
                return err;
573
        }
574
      #endif    
575
 
576
        conf = kmalloc(sizeof(wandev_conf_t), GFP_KERNEL);
577
        if (conf == NULL){
578
                printk(KERN_INFO "%s: ERROR, Failed to allocate kernel memory !\n",
579
                                wandev->name);
580
                return -ENOBUFS;
581
        }
582
 
583
      #if defined (LINUX_2_1) || defined (LINUX_2_4)            
584
        if(copy_from_user(conf, u_conf, sizeof(wandev_conf_t))) {
585
                printk(KERN_INFO "%s: Failed to copy user config data to kernel space!\n",
586
                                wandev->name);
587
                kfree(conf);
588
                return -EFAULT;
589
        }
590
      #else
591
        memcpy_fromfs ((void *)conf, (void *)u_conf, sizeof(wandev_conf_t));
592
      #endif
593
 
594
        if (conf->magic != ROUTER_MAGIC){
595
                kfree(conf);
596
                printk(KERN_INFO "%s: ERROR, Invalid MAGIC Number\n",
597
                                wandev->name);
598
                return -EINVAL;
599
        }
600
 
601
        if (conf->data_size && conf->data){
602
                if(conf->data_size > 128000 || conf->data_size < 0) {
603
                        printk(KERN_INFO
604
                            "%s: ERROR, Invalid firmware data size %i !\n",
605
                                        wandev->name, conf->data_size);
606
                        kfree(conf);
607
                        return -EINVAL;;
608
                }
609
 
610
#if defined (LINUX_2_1) || defined (LINUX_2_4)
611
                data = vmalloc(conf->data_size);
612
                if (data) {
613
                        if(!copy_from_user(data, conf->data, conf->data_size)){
614
                                conf->data=data;
615
                                err = wandev->setup(wandev,conf);
616
                        }else{
617
                                printk(KERN_INFO
618
                                     "%s: ERROR, Faild to copy from user data !\n",
619
                                       wandev->name);
620
                                err = -EFAULT;
621
                        }
622
                }else{
623
                        printk(KERN_INFO
624
                                "%s: ERROR, Faild allocate kernel memory !\n",
625
                                wandev->name);
626
                        err = -ENOBUFS;
627
                }
628
 
629
                if (data){
630
                        vfree(data);
631
                }
632
#else
633
                err = verify_area(VERIFY_READ, conf->data, conf->data_size);
634
                if (!err) {
635
                        data = kmalloc(conf->data_size, GFP_KERNEL);
636
                        if (data) {
637
                                memcpy_fromfs(data, (void*)conf->data,
638
                                        conf->data_size);
639
                                conf->data = data;
640
                        }else{
641
                                printk(KERN_INFO
642
                                    "%s: ERROR, Faild allocate kernel memory !\n",wandev->name);
643
                                err = -ENOMEM;
644
                        }
645
                }else{
646
                        printk(KERN_INFO
647
                                "%s: ERROR, Faild to copy from user data !\n",wandev->name);
648
                }
649
 
650
                if (!err){
651
                        err = wandev->setup(wandev, conf);
652
                }
653
 
654
                if (data){
655
                        kfree(data);
656
                }
657
#endif
658
        }else{
659
                printk(KERN_INFO
660
                    "%s: ERROR, No firmware found ! Firmware size = %i !\n",
661
                                wandev->name, conf->data_size);
662
        }
663
 
664
        kfree(conf);
665
        return err;
666
}
667
 
668
/*
669
 *      Shutdown WAN device.
670
 *      o delete all not opened logical channels for this device
671
 *      o call driver's shutdown() entry point
672
 */
673
 
674
static int device_shutdown (wan_device_t *wandev)
675
{
676
        netdevice_t *dev;
677
        int err=0;
678
 
679
        if (wandev->state == WAN_UNCONFIGURED){
680
                return 0;
681
        }
682
 
683
        printk(KERN_INFO "\n%s: Shutting Down!\n",wandev->name);
684
 
685
        for (dev = wandev->dev; dev;) {
686
                if ((err=delete_interface(wandev, dev->name)) != 0){
687
                        return err;
688
                }
689
 
690
                /* The above function deallocates the current dev
691
                 * structure. Therefore, we cannot use dev->priv
692
                 * as the next element: wandev->dev points to the
693
                 * next element */
694
                dev = wandev->dev;
695
        }
696
 
697
        if (wandev->ndev){
698
                return -EBUSY;  /* there are opened interfaces  */
699
        }
700
 
701
        if (wandev->shutdown)
702
                err=wandev->shutdown(wandev);
703
 
704
        return err;
705
}
706
 
707
/*
708
 *      Get WAN device status & statistics.
709
 */
710
 
711
static int device_stat (wan_device_t *wandev, wandev_stat_t *u_stat)
712
{
713
        wandev_stat_t stat;
714
 
715
      #ifdef LINUX_2_0
716
        int err;
717
        err = verify_area(VERIFY_WRITE, u_stat, sizeof(wandev_stat_t));
718
        if (err)
719
                return err;
720
      #endif
721
 
722
        memset(&stat, 0, sizeof(stat));
723
 
724
        /* Ask device driver to update device statistics */
725
        if ((wandev->state != WAN_UNCONFIGURED) && wandev->update)
726
                wandev->update(wandev);
727
 
728
        /* Fill out structure */
729
        stat.ndev  = wandev->ndev;
730
        stat.state = wandev->state;
731
 
732
      #if defined (LINUX_2_1) || defined (LINUX_2_4)
733
        if(copy_to_user(u_stat, &stat, sizeof(stat)))
734
                return -EFAULT;
735
      #else
736
        memcpy_tofs((void*)u_stat, (void*)&stat, sizeof(stat));
737
      #endif
738
 
739
        return 0;
740
}
741
 
742
/*
743
 *      Create new WAN interface.
744
 *      o verify user address space
745
 *      o copy configuration data to kernel address space
746
 *      o allocate network interface data space
747
 *      o call driver's new_if() entry point
748
 *      o make sure there is no interface name conflict
749
 *      o register network interface
750
 */
751
 
752
static int device_new_if (wan_device_t *wandev, wanif_conf_t *u_conf)
753
{
754
        wanif_conf_t conf;
755
        netdevice_t *dev=NULL;
756
#ifdef CONFIG_WANPIPE_MULTPPP
757
        struct ppp_device *pppdev=NULL;
758
#endif
759
        int err;
760
 
761
        if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL))
762
                return -ENODEV;
763
 
764
#if defined (LINUX_2_1) || defined (LINUX_2_4)  
765
        if(copy_from_user(&conf, u_conf, sizeof(wanif_conf_t)))
766
                return -EFAULT;
767
#else
768
        err = verify_area(VERIFY_READ, u_conf, sizeof(wanif_conf_t));
769
        if (err)
770
                return err;
771
        memcpy_fromfs((void*)&conf, (void*)u_conf, sizeof(wanif_conf_t));
772
#endif
773
 
774
        if (conf.magic != ROUTER_MAGIC)
775
                return -EINVAL;
776
 
777
        err = -EPROTONOSUPPORT;
778
 
779
 
780
#ifdef CONFIG_WANPIPE_MULTPPP
781
        if (conf.config_id == WANCONFIG_MPPP){
782
 
783
                pppdev = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
784
                if (pppdev == NULL){
785
                        return -ENOBUFS;
786
                }
787
                memset(pppdev, 0, sizeof(struct ppp_device));
788
 
789
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
790
                pppdev->dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
791
                if (pppdev->dev == NULL){
792
                        kfree(pppdev);
793
                        return -ENOBUFS;
794
                }
795
                memset(pppdev->dev, 0, sizeof(netdevice_t));
796
#endif
797
 
798
                err = wandev->new_if(wandev, (netdevice_t *)pppdev, &conf);
799
 
800
                      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
801
                        dev = pppdev->dev;
802
                      #else
803
                        dev = &pppdev->dev;
804
                      #endif
805
 
806
        }else{
807
 
808
                dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
809
                if (dev == NULL){
810
                        return -ENOBUFS;
811
                }
812
                memset(dev, 0, sizeof(netdevice_t));
813
                err = wandev->new_if(wandev, dev, &conf);
814
        }
815
 
816
#else
817
        /* Sync PPP is disabled */
818
        if (conf.config_id != WANCONFIG_MPPP){
819
 
820
                dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
821
                if (dev == NULL){
822
                        return -ENOBUFS;
823
                }
824
                memset(dev, 0, sizeof(netdevice_t));
825
                err = wandev->new_if(wandev, dev, &conf);
826
        }else{
827
                printk(KERN_INFO "%s: Wanpipe Mulit-Port PPP support has not been compiled in!\n",
828
                                wandev->name);
829
                return err;
830
        }
831
#endif
832
 
833
        if (!err) {
834
                /* Register network interface. This will invoke init()
835
                 * function supplied by the driver.  If device registered
836
                 * successfully, add it to the interface list.
837
                 */
838
 
839
                if (dev->name == NULL){
840
                        err = -EINVAL;
841
                }else if (dev_get(dev->name)){
842
                        err = -EEXIST;  /* name already exists */
843
                }else{
844
 
845
                        #ifdef WANDEBUG         
846
                        printk(KERN_INFO "%s: registering interface %s...\n",
847
                                modname, dev->name);
848
                        #endif                          
849
 
850
                        err = register_netdev(dev);
851
                        if (!err) {
852
                                netdevice_t *slave=NULL;
853
                                unsigned long smp_flags=0;
854
 
855
                                lock_adapter_irq(&wandev->lock, &smp_flags);
856
 
857
                                if (wandev->dev == NULL){
858
                                        wandev->dev = dev;
859
                                }else{
860
                                        for (slave=wandev->dev;
861
                                             *((netdevice_t**)slave->priv);
862
                                             slave=*((netdevice_t**)slave->priv));
863
 
864
                                        *((netdevice_t**)slave->priv) = dev;
865
                                }
866
                                ++wandev->ndev;
867
 
868
                                unlock_adapter_irq(&wandev->lock, &smp_flags);
869
                                return 0;        /* done !!! */
870
                        }
871
                }
872
                if (wandev->del_if)
873
                        wandev->del_if(wandev, dev);
874
        }
875
 
876
        /* This code has moved from del_if() function */
877
        if (dev->priv){
878
                kfree(dev->priv);
879
                dev->priv=NULL;
880
        }
881
 
882
 
883
      #ifdef CONFIG_WANPIPE_MULTPPP
884
        if (conf.config_id == WANCONFIG_MPPP){
885
                kfree(pppdev);
886
        }else{
887
                kfree(dev);
888
        }
889
      #else
890
        /* Sync PPP is disabled */
891
        if (conf.config_id != WANCONFIG_MPPP){
892
                kfree(dev);
893
        }
894
      #endif
895
 
896
        return err;
897
}
898
 
899
 
900
/*
901
 *      Delete WAN logical channel.
902
 *       o verify user address space
903
 *       o copy configuration data to kernel address space
904
 */
905
 
906
static int device_del_if (wan_device_t *wandev, char *u_name)
907
{
908
        char name[WAN_IFNAME_SZ + 1];
909
        int err = 0;
910
 
911
        if (wandev->state == WAN_UNCONFIGURED)
912
                return -ENODEV;
913
 
914
      #ifdef LINUX_2_0
915
        err = verify_area(VERIFY_READ, u_name, WAN_IFNAME_SZ);
916
        if (err)
917
                return err;
918
      #endif    
919
 
920
        memset(name, 0, sizeof(name));
921
 
922
      #if defined (LINUX_2_1) || defined (LINUX_2_4)
923
        if(copy_from_user(name, u_name, WAN_IFNAME_SZ))
924
                return -EFAULT;
925
      #else
926
        memcpy_fromfs((void*)name, (void*)u_name, WAN_IFNAME_SZ);
927
      #endif
928
 
929
        err = delete_interface(wandev, name);
930
        if (err)
931
                return(err);
932
 
933
        /* If last interface being deleted, shutdown card
934
         * This helps with administration at leaf nodes
935
         * (You can tell if the person at the other end of the phone
936
         * has an interface configured) and avoids DoS vulnerabilities
937
         * in binary driver files - this fixes a problem with the current
938
         * Sangoma driver going into strange states when all the network
939
         * interfaces are deleted and the link irrecoverably disconnected.
940
         */
941
 
942
        if (!wandev->ndev && wandev->shutdown){
943
                err = wandev->shutdown(wandev);
944
        }
945
        return err;
946
}
947
 
948
 
949
/*
950
 *      Miscellaneous Functions
951
 */
952
 
953
/*
954
 *      Find WAN device by name.
955
 *      Return pointer to the WAN device data space or NULL if device not found.
956
 */
957
 
958
static wan_device_t *find_device(char *name)
959
{
960
        wan_device_t *wandev;
961
 
962
        for (wandev = router_devlist;wandev && strcmp(wandev->name, name);
963
                wandev = wandev->next);
964
        return wandev;
965
}
966
 
967
/*
968
 *      Delete WAN logical channel identified by its name.
969
 *      o find logical channel by its name
970
 *      o call driver's del_if() entry point
971
 *      o unregister network interface
972
 *      o unlink channel data space from linked list of channels
973
 *      o release channel data space
974
 *
975
 *      Return: 0                success
976
 *              -ENODEV         channel not found.
977
 *              -EBUSY          interface is open
978
 *
979
 *      Note: If (force != 0), then device will be destroyed even if interface
980
 *      associated with it is open. It's caller's responsibility to make
981
 *      sure that opened interfaces are not removed!
982
 */
983
 
984
static int delete_interface (wan_device_t *wandev, char *name)
985
{
986
        netdevice_t *dev=NULL, *prev=NULL;
987
        unsigned long smp_flags=0;
988
 
989
        lock_adapter_irq(&wandev->lock, &smp_flags);
990
        dev = wandev->dev;
991
        prev = NULL;
992
        while (dev && strcmp(name, dev->name)) {
993
                netdevice_t **slave = dev->priv;
994
                prev = dev;
995
                dev = *slave;
996
        }
997
        unlock_adapter_irq(&wandev->lock, &smp_flags);
998
 
999
        if (dev == NULL){
1000
                return -ENODEV; /* interface not found */
1001
        }
1002
 
1003
       #ifdef LINUX_2_4
1004
        if (netif_running(dev)){
1005
       #else
1006
        if (dev->start) {
1007
       #endif
1008
                return -EBUSY;  /* interface in use */
1009
        }
1010
 
1011
        if (wandev->del_if)
1012
                wandev->del_if(wandev, dev);
1013
 
1014
        lock_adapter_irq(&wandev->lock, &smp_flags);
1015
        if (prev) {
1016
                netdevice_t **prev_slave = prev->priv;
1017
                netdevice_t **slave = dev->priv;
1018
 
1019
                *prev_slave = *slave;
1020
        } else {
1021
                netdevice_t **slave = dev->priv;
1022
                wandev->dev = *slave;
1023
        }
1024
        --wandev->ndev;
1025
        unlock_adapter_irq(&wandev->lock, &smp_flags);
1026
 
1027
        printk(KERN_INFO "%s: unregistering '%s'\n", wandev->name, dev->name);
1028
 
1029
        /* Due to new interface linking method using dev->priv,
1030
         * this code has moved from del_if() function.*/
1031
        if (dev->priv){
1032
                kfree(dev->priv);
1033
                dev->priv=NULL;
1034
        }
1035
 
1036
        unregister_netdev(dev);
1037
 
1038
      #ifdef LINUX_2_4
1039
        kfree(dev);
1040
      #else
1041
        if (dev->name){
1042
                kfree(dev->name);
1043
        }
1044
        kfree(dev);
1045
      #endif
1046
 
1047
        return 0;
1048
}
1049
 
1050
void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
1051
{
1052
      #ifdef LINUX_2_0
1053
        save_flags(*smp_flags);
1054
        cli();
1055
      #else
1056
        spin_lock_irqsave(lock, *smp_flags);
1057
      #endif
1058
}
1059
 
1060
 
1061
void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
1062
{
1063
      #ifdef LINUX_2_0
1064
        restore_flags(*smp_flags);
1065
      #else
1066
        spin_unlock_irqrestore(lock, *smp_flags);
1067
      #endif
1068
}
1069
 
1070
 
1071
 
1072
#if defined (LINUX_2_1) || defined (LINUX_2_4)
1073
EXPORT_SYMBOL(register_wan_device);
1074
EXPORT_SYMBOL(unregister_wan_device);
1075
EXPORT_SYMBOL(wanrouter_encapsulate);
1076
EXPORT_SYMBOL(wanrouter_type_trans);
1077
EXPORT_SYMBOL(lock_adapter_irq);
1078
EXPORT_SYMBOL(unlock_adapter_irq);
1079
#endif
1080
 
1081
/*
1082
 *      End
1083
 */

powered by: WebSVN 2.1.0

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