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