[PATCH] md: check return value of write_page, rather than ignore it
[linux-2.6] / net / wanrouter / wanmain.c
1 /*****************************************************************************
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/config.h>
46 #include <linux/stddef.h>       /* offsetof(), etc. */
47 #include <linux/errno.h>        /* return codes */
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/module.h>       /* support for loadable modules */
51 #include <linux/slab.h>         /* kmalloc(), kfree() */
52 #include <linux/mm.h>
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 #include <linux/vmalloc.h>      /* vmalloc, vfree */
59 #include <asm/uaccess.h>        /* copy_to/from_user */
60 #include <linux/init.h>         /* __initfunc et al. */
61 #include <net/syncppp.h>
62
63 #define KMEM_SAFETYZONE 8
64
65 /***********FOR DEBUGGING PURPOSES*********************************************
66 static void * dbg_kmalloc(unsigned int size, int prio, int line) {
67         int i = 0;
68         void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
69         char * c1 = v;
70         c1 += sizeof(unsigned int);
71         *((unsigned int *)v) = size;
72
73         for (i = 0; i < KMEM_SAFETYZONE; i++) {
74                 c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
75                 c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
76                 c1 += 8;
77         }
78         c1 += size;
79         for (i = 0; i < KMEM_SAFETYZONE; i++) {
80                 c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
81                 c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
82                 c1 += 8;
83         }
84         v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
85         printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
86         return v;
87 }
88 static void dbg_kfree(void * v, int line) {
89         unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
90         unsigned int size = *sp;
91         char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
92         int i = 0;
93         for (i = 0; i < KMEM_SAFETYZONE; i++) {
94                 if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
95                     || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
96                         printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
97                         printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
98                                         c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
99                 }
100                 c1 += 8;
101         }
102         c1 += size;
103         for (i = 0; i < KMEM_SAFETYZONE; i++) {
104                 if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
105                     || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
106                    ) {
107                         printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
108                         printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
109                                         c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
110                 }
111                 c1 += 8;
112         }
113         printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
114         v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
115         kfree(v);
116 }
117
118 #define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
119 #define kfree(x) dbg_kfree(x,__LINE__)
120 *****************************************************************************/
121
122 /*
123  *      Function Prototypes
124  */
125
126 /*
127  *      WAN device IOCTL handlers
128  */
129
130 static int wanrouter_device_setup(struct wan_device *wandev,
131                                   wandev_conf_t __user *u_conf);
132 static int wanrouter_device_stat(struct wan_device *wandev,
133                                  wandev_stat_t __user *u_stat);
134 static int wanrouter_device_shutdown(struct wan_device *wandev);
135 static int wanrouter_device_new_if(struct wan_device *wandev,
136                                    wanif_conf_t __user *u_conf);
137 static int wanrouter_device_del_if(struct wan_device *wandev,
138                                    char __user *u_name);
139
140 /*
141  *      Miscellaneous
142  */
143
144 static struct wan_device *wanrouter_find_device(char *name);
145 static int wanrouter_delete_interface(struct wan_device *wandev, char *name);
146 void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
147 void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
148
149
150
151 /*
152  *      Global Data
153  */
154
155 static char wanrouter_fullname[]  = "Sangoma WANPIPE Router";
156 static char wanrouter_copyright[] = "(c) 1995-2000 Sangoma Technologies Inc.";
157 static char wanrouter_modname[] = ROUTER_NAME; /* short module name */
158 struct wan_device* wanrouter_router_devlist; /* list of registered devices */
159
160 /*
161  *      Organize Unique Identifiers for encapsulation/decapsulation
162  */
163
164 static unsigned char wanrouter_oui_ether[] = { 0x00, 0x00, 0x00 };
165 #if 0
166 static unsigned char wanrouter_oui_802_2[] = { 0x00, 0x80, 0xC2 };
167 #endif
168
169 static int __init wanrouter_init(void)
170 {
171         int err;
172
173         printk(KERN_INFO "%s v%u.%u %s\n",
174                wanrouter_fullname, ROUTER_VERSION, ROUTER_RELEASE,
175                wanrouter_copyright);
176
177         err = wanrouter_proc_init();
178         if (err)
179                 printk(KERN_INFO "%s: can't create entry in proc filesystem!\n",
180                        wanrouter_modname);
181
182         return err;
183 }
184
185 static void __exit wanrouter_cleanup (void)
186 {
187         wanrouter_proc_cleanup();
188 }
189
190 /*
191  * This is just plain dumb.  We should move the bugger to drivers/net/wan,
192  * slap it first in directory and make it module_init().  The only reason
193  * for subsys_initcall() here is that net goes after drivers (why, BTW?)
194  */
195 subsys_initcall(wanrouter_init);
196 module_exit(wanrouter_cleanup);
197
198 /*
199  *      Kernel APIs
200  */
201
202 /*
203  *      Register WAN device.
204  *      o verify device credentials
205  *      o create an entry for the device in the /proc/net/router directory
206  *      o initialize internally maintained fields of the wan_device structure
207  *      o link device data space to a singly-linked list
208  *      o if it's the first device, then start kernel 'thread'
209  *      o increment module use count
210  *
211  *      Return:
212  *      0       Ok
213  *      < 0     error.
214  *
215  *      Context:        process
216  */
217
218
219 int register_wan_device(struct wan_device *wandev)
220 {
221         int err, namelen;
222
223         if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC) ||
224             (wandev->name == NULL))
225                 return -EINVAL;
226
227         namelen = strlen(wandev->name);
228         if (!namelen || (namelen > WAN_DRVNAME_SZ))
229                 return -EINVAL;
230
231         if (wanrouter_find_device(wandev->name))
232                 return -EEXIST;
233
234 #ifdef WANDEBUG
235         printk(KERN_INFO "%s: registering WAN device %s\n",
236                wanrouter_modname, wandev->name);
237 #endif
238
239         /*
240          *      Register /proc directory entry
241          */
242         err = wanrouter_proc_add(wandev);
243         if (err) {
244                 printk(KERN_INFO
245                         "%s: can't create /proc/net/router/%s entry!\n",
246                         wanrouter_modname, wandev->name);
247                 return err;
248         }
249
250         /*
251          *      Initialize fields of the wan_device structure maintained by the
252          *      router and update local data.
253          */
254
255         wandev->ndev = 0;
256         wandev->dev  = NULL;
257         wandev->next = wanrouter_router_devlist;
258         wanrouter_router_devlist = wandev;
259         return 0;
260 }
261
262 /*
263  *      Unregister WAN device.
264  *      o shut down device
265  *      o unlink device data space from the linked list
266  *      o delete device entry in the /proc/net/router directory
267  *      o decrement module use count
268  *
269  *      Return:         0       Ok
270  *                      <0      error.
271  *      Context:        process
272  */
273
274
275 int unregister_wan_device(char *name)
276 {
277         struct wan_device *wandev, *prev;
278
279         if (name == NULL)
280                 return -EINVAL;
281
282         for (wandev = wanrouter_router_devlist, prev = NULL;
283                 wandev && strcmp(wandev->name, name);
284                 prev = wandev, wandev = wandev->next)
285                 ;
286         if (wandev == NULL)
287                 return -ENODEV;
288
289 #ifdef WANDEBUG
290         printk(KERN_INFO "%s: unregistering WAN device %s\n",
291                wanrouter_modname, name);
292 #endif
293
294         if (wandev->state != WAN_UNCONFIGURED)
295                 wanrouter_device_shutdown(wandev);
296
297         if (prev)
298                 prev->next = wandev->next;
299         else
300                 wanrouter_router_devlist = wandev->next;
301
302         wanrouter_proc_delete(wandev);
303         return 0;
304 }
305
306 /*
307  *      Encapsulate packet.
308  *
309  *      Return: encapsulation header size
310  *              < 0     - unsupported Ethertype
311  *
312  *      Notes:
313  *      1. This function may be called on interrupt context.
314  */
315
316
317 int wanrouter_encapsulate(struct sk_buff *skb, struct net_device *dev,
318                           unsigned short type)
319 {
320         int hdr_len = 0;
321
322         switch (type) {
323         case ETH_P_IP:          /* IP datagram encapsulation */
324                 hdr_len += 1;
325                 skb_push(skb, 1);
326                 skb->data[0] = NLPID_IP;
327                 break;
328
329         case ETH_P_IPX:         /* SNAP encapsulation */
330         case ETH_P_ARP:
331                 hdr_len += 7;
332                 skb_push(skb, 7);
333                 skb->data[0] = 0;
334                 skb->data[1] = NLPID_SNAP;
335                 memcpy(&skb->data[2], wanrouter_oui_ether,
336                        sizeof(wanrouter_oui_ether));
337                 *((unsigned short*)&skb->data[5]) = htons(type);
338                 break;
339
340         default:                /* Unknown packet type */
341                 printk(KERN_INFO
342                         "%s: unsupported Ethertype 0x%04X on interface %s!\n",
343                         wanrouter_modname, type, dev->name);
344                 hdr_len = -EINVAL;
345         }
346         return hdr_len;
347 }
348
349
350 /*
351  *      Decapsulate packet.
352  *
353  *      Return: Ethertype (in network order)
354  *                      0       unknown encapsulation
355  *
356  *      Notes:
357  *      1. This function may be called on interrupt context.
358  */
359
360
361 unsigned short wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev)
362 {
363         int cnt = skb->data[0] ? 0 : 1; /* there may be a pad present */
364         unsigned short ethertype;
365
366         switch (skb->data[cnt]) {
367         case NLPID_IP:          /* IP datagramm */
368                 ethertype = htons(ETH_P_IP);
369                 cnt += 1;
370                 break;
371
372         case NLPID_SNAP:        /* SNAP encapsulation */
373                 if (memcmp(&skb->data[cnt + 1], wanrouter_oui_ether,
374                            sizeof(wanrouter_oui_ether))){
375                         printk(KERN_INFO
376                                 "%s: unsupported SNAP OUI %02X-%02X-%02X "
377                                 "on interface %s!\n", wanrouter_modname,
378                                 skb->data[cnt+1], skb->data[cnt+2],
379                                 skb->data[cnt+3], dev->name);
380                         return 0;
381                 }
382                 ethertype = *((unsigned short*)&skb->data[cnt+4]);
383                 cnt += 6;
384                 break;
385
386         /* add other protocols, e.g. CLNP, ESIS, ISIS, if needed */
387
388         default:
389                 printk(KERN_INFO
390                         "%s: unsupported NLPID 0x%02X on interface %s!\n",
391                         wanrouter_modname, skb->data[cnt], dev->name);
392                 return 0;
393         }
394         skb->protocol = ethertype;
395         skb->pkt_type = PACKET_HOST;    /*      Physically point to point */
396         skb_pull(skb, cnt);
397         skb->mac.raw  = skb->data;
398         return ethertype;
399 }
400
401
402 /*
403  *      WAN device IOCTL.
404  *      o find WAN device associated with this node
405  *      o execute requested action or pass command to the device driver
406  */
407
408 int wanrouter_ioctl(struct inode *inode, struct file *file,
409                 unsigned int cmd, unsigned long arg)
410 {
411         int err = 0;
412         struct proc_dir_entry *dent;
413         struct wan_device *wandev;
414         void __user *data = (void __user *)arg;
415
416         if (!capable(CAP_NET_ADMIN))
417                 return -EPERM;
418
419         if ((cmd >> 8) != ROUTER_IOCTL)
420                 return -EINVAL;
421
422         dent = PDE(inode);
423         if ((dent == NULL) || (dent->data == NULL))
424                 return -EINVAL;
425
426         wandev = dent->data;
427         if (wandev->magic != ROUTER_MAGIC)
428                 return -EINVAL;
429
430         switch (cmd) {
431         case ROUTER_SETUP:
432                 err = wanrouter_device_setup(wandev, data);
433                 break;
434
435         case ROUTER_DOWN:
436                 err = wanrouter_device_shutdown(wandev);
437                 break;
438
439         case ROUTER_STAT:
440                 err = wanrouter_device_stat(wandev, data);
441                 break;
442
443         case ROUTER_IFNEW:
444                 err = wanrouter_device_new_if(wandev, data);
445                 break;
446
447         case ROUTER_IFDEL:
448                 err = wanrouter_device_del_if(wandev, data);
449                 break;
450
451         case ROUTER_IFSTAT:
452                 break;
453
454         default:
455                 if ((cmd >= ROUTER_USER) &&
456                     (cmd <= ROUTER_USER_MAX) &&
457                     wandev->ioctl)
458                         err = wandev->ioctl(wandev, cmd, arg);
459                 else err = -EINVAL;
460         }
461         return err;
462 }
463
464 /*
465  *      WAN Driver IOCTL Handlers
466  */
467
468 /*
469  *      Setup WAN link device.
470  *      o verify user address space
471  *      o allocate kernel memory and copy configuration data to kernel space
472  *      o if configuration data includes extension, copy it to kernel space too
473  *      o call driver's setup() entry point
474  */
475
476 static int wanrouter_device_setup(struct wan_device *wandev,
477                                   wandev_conf_t __user *u_conf)
478 {
479         void *data = NULL;
480         wandev_conf_t *conf;
481         int err = -EINVAL;
482
483         if (wandev->setup == NULL) {    /* Nothing to do ? */
484                 printk(KERN_INFO "%s: ERROR, No setup script: wandev->setup()\n",
485                                 wandev->name);
486                 return 0;
487         }
488
489         conf = kmalloc(sizeof(wandev_conf_t), GFP_KERNEL);
490         if (conf == NULL){
491                 printk(KERN_INFO "%s: ERROR, Failed to allocate kernel memory !\n",
492                                 wandev->name);
493                 return -ENOBUFS;
494         }
495
496         if (copy_from_user(conf, u_conf, sizeof(wandev_conf_t))) {
497                 printk(KERN_INFO "%s: Failed to copy user config data to kernel space!\n",
498                                 wandev->name);
499                 kfree(conf);
500                 return -EFAULT;
501         }
502
503         if (conf->magic != ROUTER_MAGIC) {
504                 kfree(conf);
505                 printk(KERN_INFO "%s: ERROR, Invalid MAGIC Number\n",
506                                 wandev->name);
507                 return -EINVAL;
508         }
509
510         if (conf->data_size && conf->data) {
511                 if (conf->data_size > 128000 || conf->data_size < 0) {
512                         printk(KERN_INFO
513                             "%s: ERROR, Invalid firmware data size %i !\n",
514                                         wandev->name, conf->data_size);
515                         kfree(conf);
516                         return -EINVAL;
517                 }
518
519                 data = vmalloc(conf->data_size);
520                 if (!data) {
521                         printk(KERN_INFO
522                                 "%s: ERROR, Faild allocate kernel memory !\n",
523                                 wandev->name);
524                         kfree(conf);
525                         return -ENOBUFS;
526                 }
527                 if (!copy_from_user(data, conf->data, conf->data_size)) {
528                         conf->data = data;
529                         err = wandev->setup(wandev, conf);
530                 } else {
531                         printk(KERN_INFO
532                              "%s: ERROR, Faild to copy from user data !\n",
533                                wandev->name);
534                         err = -EFAULT;
535                 }
536                 vfree(data);
537         } else {
538                 printk(KERN_INFO
539                     "%s: ERROR, No firmware found ! Firmware size = %i !\n",
540                                 wandev->name, conf->data_size);
541         }
542
543         kfree(conf);
544         return err;
545 }
546
547 /*
548  *      Shutdown WAN device.
549  *      o delete all not opened logical channels for this device
550  *      o call driver's shutdown() entry point
551  */
552
553 static int wanrouter_device_shutdown(struct wan_device *wandev)
554 {
555         struct net_device *dev;
556         int err=0;
557
558         if (wandev->state == WAN_UNCONFIGURED)
559                 return 0;
560
561         printk(KERN_INFO "\n%s: Shutting Down!\n",wandev->name);
562
563         for (dev = wandev->dev; dev;) {
564                 err = wanrouter_delete_interface(wandev, dev->name);
565                 if (err)
566                         return err;
567                 /* The above function deallocates the current dev
568                  * structure. Therefore, we cannot use dev->priv
569                  * as the next element: wandev->dev points to the
570                  * next element */
571                 dev = wandev->dev;
572         }
573
574         if (wandev->ndev)
575                 return -EBUSY;  /* there are opened interfaces  */
576
577         if (wandev->shutdown)
578                 err=wandev->shutdown(wandev);
579
580         return err;
581 }
582
583 /*
584  *      Get WAN device status & statistics.
585  */
586
587 static int wanrouter_device_stat(struct wan_device *wandev,
588                                  wandev_stat_t __user *u_stat)
589 {
590         wandev_stat_t stat;
591
592         memset(&stat, 0, sizeof(stat));
593
594         /* Ask device driver to update device statistics */
595         if ((wandev->state != WAN_UNCONFIGURED) && wandev->update)
596                 wandev->update(wandev);
597
598         /* Fill out structure */
599         stat.ndev  = wandev->ndev;
600         stat.state = wandev->state;
601
602         if (copy_to_user(u_stat, &stat, sizeof(stat)))
603                 return -EFAULT;
604
605         return 0;
606 }
607
608 /*
609  *      Create new WAN interface.
610  *      o verify user address space
611  *      o copy configuration data to kernel address space
612  *      o allocate network interface data space
613  *      o call driver's new_if() entry point
614  *      o make sure there is no interface name conflict
615  *      o register network interface
616  */
617
618 static int wanrouter_device_new_if(struct wan_device *wandev,
619                                    wanif_conf_t __user *u_conf)
620 {
621         wanif_conf_t *cnf;
622         struct net_device *dev = NULL;
623 #ifdef CONFIG_WANPIPE_MULTPPP
624         struct ppp_device *pppdev=NULL;
625 #endif
626         int err;
627
628         if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL))
629                 return -ENODEV;
630
631         cnf = kmalloc(sizeof(wanif_conf_t), GFP_KERNEL);
632         if (!cnf)
633                 return -ENOBUFS;
634
635         err = -EFAULT;
636         if (copy_from_user(cnf, u_conf, sizeof(wanif_conf_t)))
637                 goto out;
638
639         err = -EINVAL;
640         if (cnf->magic != ROUTER_MAGIC)
641                 goto out;
642
643         if (cnf->config_id == WANCONFIG_MPPP) {
644 #ifdef CONFIG_WANPIPE_MULTPPP
645                 pppdev = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
646                 err = -ENOBUFS;
647                 if (pppdev == NULL)
648                         goto out;
649                 memset(pppdev, 0, sizeof(struct ppp_device));
650                 pppdev->dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
651                 if (pppdev->dev == NULL) {
652                         kfree(pppdev);
653                         err = -ENOBUFS;
654                         goto out;
655                 }
656                 memset(pppdev->dev, 0, sizeof(struct net_device));
657                 err = wandev->new_if(wandev, (struct net_device *)pppdev, cnf);
658                 dev = pppdev->dev;
659 #else
660                 printk(KERN_INFO "%s: Wanpipe Mulit-Port PPP support has not been compiled in!\n",
661                                 wandev->name);
662                 err = -EPROTONOSUPPORT;
663                 goto out;
664 #endif
665         } else {
666                 dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
667                 err = -ENOBUFS;
668                 if (dev == NULL)
669                         goto out;
670                 memset(dev, 0, sizeof(struct net_device));
671                 err = wandev->new_if(wandev, dev, cnf);
672         }
673
674         if (!err) {
675                 /* Register network interface. This will invoke init()
676                  * function supplied by the driver.  If device registered
677                  * successfully, add it to the interface list.
678                  */
679
680                 if (dev->name == NULL) {
681                         err = -EINVAL;
682                 } else {
683
684                         #ifdef WANDEBUG
685                         printk(KERN_INFO "%s: registering interface %s...\n",
686                                 wanrouter_modname, dev->name);
687                         #endif
688
689                         err = register_netdev(dev);
690                         if (!err) {
691                                 struct net_device *slave = NULL;
692                                 unsigned long smp_flags=0;
693
694                                 lock_adapter_irq(&wandev->lock, &smp_flags);
695
696                                 if (wandev->dev == NULL) {
697                                         wandev->dev = dev;
698                                 } else {
699                                         for (slave=wandev->dev;
700                                          *((struct net_device **)slave->priv);
701                                  slave = *((struct net_device **)slave->priv));
702
703                                      *((struct net_device **)slave->priv) = dev;
704                                 }
705                                 ++wandev->ndev;
706
707                                 unlock_adapter_irq(&wandev->lock, &smp_flags);
708                                 err = 0;        /* done !!! */
709                                 goto out;
710                         }
711                 }
712                 if (wandev->del_if)
713                         wandev->del_if(wandev, dev);
714         }
715
716         /* This code has moved from del_if() function */
717         if (dev->priv) {
718                 kfree(dev->priv);
719                 dev->priv = NULL;
720         }
721
722 #ifdef CONFIG_WANPIPE_MULTPPP
723         if (cnf->config_id == WANCONFIG_MPPP)
724                 kfree(pppdev);
725         else
726                 kfree(dev);
727 #else
728         /* Sync PPP is disabled */
729         if (cnf->config_id != WANCONFIG_MPPP)
730                 kfree(dev);
731 #endif
732
733 out:
734         kfree(cnf);
735         return err;
736 }
737
738
739 /*
740  *      Delete WAN logical channel.
741  *       o verify user address space
742  *       o copy configuration data to kernel address space
743  */
744
745 static int wanrouter_device_del_if(struct wan_device *wandev, char __user *u_name)
746 {
747         char name[WAN_IFNAME_SZ + 1];
748         int err = 0;
749
750         if (wandev->state == WAN_UNCONFIGURED)
751                 return -ENODEV;
752
753         memset(name, 0, sizeof(name));
754
755         if (copy_from_user(name, u_name, WAN_IFNAME_SZ))
756                 return -EFAULT;
757
758         err = wanrouter_delete_interface(wandev, name);
759         if (err)
760                 return err;
761
762         /* If last interface being deleted, shutdown card
763          * This helps with administration at leaf nodes
764          * (You can tell if the person at the other end of the phone
765          * has an interface configured) and avoids DoS vulnerabilities
766          * in binary driver files - this fixes a problem with the current
767          * Sangoma driver going into strange states when all the network
768          * interfaces are deleted and the link irrecoverably disconnected.
769          */
770
771         if (!wandev->ndev && wandev->shutdown)
772                 err = wandev->shutdown(wandev);
773
774         return err;
775 }
776
777 /*
778  *      Miscellaneous Functions
779  */
780
781 /*
782  *      Find WAN device by name.
783  *      Return pointer to the WAN device data space or NULL if device not found.
784  */
785
786 static struct wan_device *wanrouter_find_device(char *name)
787 {
788         struct wan_device *wandev;
789
790         for (wandev = wanrouter_router_devlist;
791              wandev && strcmp(wandev->name, name);
792                 wandev = wandev->next);
793         return wandev;
794 }
795
796 /*
797  *      Delete WAN logical channel identified by its name.
798  *      o find logical channel by its name
799  *      o call driver's del_if() entry point
800  *      o unregister network interface
801  *      o unlink channel data space from linked list of channels
802  *      o release channel data space
803  *
804  *      Return: 0               success
805  *              -ENODEV         channel not found.
806  *              -EBUSY          interface is open
807  *
808  *      Note: If (force != 0), then device will be destroyed even if interface
809  *      associated with it is open. It's caller's responsibility to make
810  *      sure that opened interfaces are not removed!
811  */
812
813 static int wanrouter_delete_interface(struct wan_device *wandev, char *name)
814 {
815         struct net_device *dev = NULL, *prev = NULL;
816         unsigned long smp_flags=0;
817
818         lock_adapter_irq(&wandev->lock, &smp_flags);
819         dev = wandev->dev;
820         prev = NULL;
821         while (dev && strcmp(name, dev->name)) {
822                 struct net_device **slave = dev->priv;
823                 prev = dev;
824                 dev = *slave;
825         }
826         unlock_adapter_irq(&wandev->lock, &smp_flags);
827
828         if (dev == NULL)
829                 return -ENODEV; /* interface not found */
830
831         if (netif_running(dev))
832                 return -EBUSY;  /* interface in use */
833
834         if (wandev->del_if)
835                 wandev->del_if(wandev, dev);
836
837         lock_adapter_irq(&wandev->lock, &smp_flags);
838         if (prev) {
839                 struct net_device **prev_slave = prev->priv;
840                 struct net_device **slave = dev->priv;
841
842                 *prev_slave = *slave;
843         } else {
844                 struct net_device **slave = dev->priv;
845                 wandev->dev = *slave;
846         }
847         --wandev->ndev;
848         unlock_adapter_irq(&wandev->lock, &smp_flags);
849
850         printk(KERN_INFO "%s: unregistering '%s'\n", wandev->name, dev->name);
851
852         /* Due to new interface linking method using dev->priv,
853          * this code has moved from del_if() function.*/
854         if (dev->priv){
855                 kfree(dev->priv);
856                 dev->priv=NULL;
857         }
858
859         unregister_netdev(dev);
860
861         free_netdev(dev);
862
863         return 0;
864 }
865
866 void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
867 {
868         spin_lock_irqsave(lock, *smp_flags);
869 }
870
871
872 void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
873 {
874         spin_unlock_irqrestore(lock, *smp_flags);
875 }
876
877 EXPORT_SYMBOL(register_wan_device);
878 EXPORT_SYMBOL(unregister_wan_device);
879 EXPORT_SYMBOL(wanrouter_encapsulate);
880 EXPORT_SYMBOL(wanrouter_type_trans);
881 EXPORT_SYMBOL(lock_adapter_irq);
882 EXPORT_SYMBOL(unlock_adapter_irq);
883
884 MODULE_LICENSE("GPL");
885
886 /*
887  *      End
888  */