Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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