Linux Audio

Check our new training course

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