📄 wanmain.c
字号:
/****************************************************************************** wanmain.c WAN Multiprotocol Router Module. Main code.** This module is completely hardware-independent and provides* the following common services for the WAN Link Drivers:* o WAN device management (registering, unregistering)* o Network interface management* o Physical connection management (dial-up, incoming calls)* o Logical connection management (switched virtual circuits)* o Protocol encapsulation/decapsulation** Author: Gideon Hack** Copyright: (c) 1995-1999 Sangoma Technologies Inc.** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version* 2 of the License, or (at your option) any later version.* ============================================================================* Nov 24, 2000 Nenad Corbic Updated for 2.4.X kernels* Nov 07, 2000 Nenad Corbic Fixed the Mulit-Port PPP for kernels 2.2.16 and* greater.* Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on* kernels 2.2.16 or greater. The SyncPPP* has changed.* Jul 13, 2000 Nenad Corbic Added SyncPPP support* Added extra debugging in device_setup().* Oct 01, 1999 Gideon Hack Update for s514 PCI card* Dec 27, 1996 Gene Kozin Initial version (based on Sangoma's WANPIPE)* Jan 16, 1997 Gene Kozin router_devlist made public* Jan 31, 1997 Alan Cox Hacked it about a bit for 2.1* Jun 27, 1997 Alan Cox realigned with vendor code* Oct 15, 1997 Farhan Thawar changed wan_encapsulate to add a pad byte of 0* Apr 20, 1998 Alan Cox Fixed 2.1 symbols* May 17, 1998 K. Baranowski Fixed SNAP encapsulation in wan_encapsulate* Dec 15, 1998 Arnaldo Melo support for firmwares of up to 128000 bytes* check wandev->setup return value* Dec 22, 1998 Arnaldo Melo vmalloc/vfree used in device_setup to allocate* kernel memory and copy configuration data to* kernel space (for big firmwares)* Jun 02, 1999 Gideon Hack Updates for Linux 2.0.X and 2.2.X kernels.*****************************************************************************/#include <linux/stddef.h> /* offsetof(), etc. */#include <linux/capability.h>#include <linux/errno.h> /* return codes */#include <linux/kernel.h>#include <linux/module.h> /* support for loadable modules */#include <linux/slab.h> /* kmalloc(), kfree() */#include <linux/mm.h>#include <linux/string.h> /* inline mem*, str* functions */#include <asm/byteorder.h> /* htons(), etc. */#include <linux/wanrouter.h> /* WAN router API definitions */#include <linux/vmalloc.h> /* vmalloc, vfree */#include <asm/uaccess.h> /* copy_to/from_user */#include <linux/init.h> /* __initfunc et al. */#include <net/syncppp.h>#define KMEM_SAFETYZONE 8/* * Function Prototypes *//* * WAN device IOCTL handlers */static int wanrouter_device_setup(struct wan_device *wandev, wandev_conf_t __user *u_conf);static int wanrouter_device_stat(struct wan_device *wandev, wandev_stat_t __user *u_stat);static int wanrouter_device_shutdown(struct wan_device *wandev);static int wanrouter_device_new_if(struct wan_device *wandev, wanif_conf_t __user *u_conf);static int wanrouter_device_del_if(struct wan_device *wandev, char __user *u_name);/* * Miscellaneous */static struct wan_device *wanrouter_find_device(char *name);static int wanrouter_delete_interface(struct wan_device *wandev, char *name);static void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);static void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);/* * Global Data */static char wanrouter_fullname[] = "Sangoma WANPIPE Router";static char wanrouter_copyright[] = "(c) 1995-2000 Sangoma Technologies Inc.";static char wanrouter_modname[] = ROUTER_NAME; /* short module name */struct wan_device* wanrouter_router_devlist; /* list of registered devices *//* * Organize Unique Identifiers for encapsulation/decapsulation */#if 0static unsigned char wanrouter_oui_ether[] = { 0x00, 0x00, 0x00 };static unsigned char wanrouter_oui_802_2[] = { 0x00, 0x80, 0xC2 };#endifstatic int __init wanrouter_init(void){ int err; printk(KERN_INFO "%s v%u.%u %s\n", wanrouter_fullname, ROUTER_VERSION, ROUTER_RELEASE, wanrouter_copyright); err = wanrouter_proc_init(); if (err) printk(KERN_INFO "%s: can't create entry in proc filesystem!\n", wanrouter_modname); return err;}static void __exit wanrouter_cleanup (void){ wanrouter_proc_cleanup();}/* * This is just plain dumb. We should move the bugger to drivers/net/wan, * slap it first in directory and make it module_init(). The only reason * for subsys_initcall() here is that net goes after drivers (why, BTW?) */subsys_initcall(wanrouter_init);module_exit(wanrouter_cleanup);/* * Kernel APIs *//* * Register WAN device. * o verify device credentials * o create an entry for the device in the /proc/net/router directory * o initialize internally maintained fields of the wan_device structure * o link device data space to a singly-linked list * o if it's the first device, then start kernel 'thread' * o increment module use count * * Return: * 0 Ok * < 0 error. * * Context: process */int register_wan_device(struct wan_device *wandev){ int err, namelen; if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC) || (wandev->name == NULL)) return -EINVAL; namelen = strlen(wandev->name); if (!namelen || (namelen > WAN_DRVNAME_SZ)) return -EINVAL; if (wanrouter_find_device(wandev->name)) return -EEXIST;#ifdef WANDEBUG printk(KERN_INFO "%s: registering WAN device %s\n", wanrouter_modname, wandev->name);#endif /* * Register /proc directory entry */ err = wanrouter_proc_add(wandev); if (err) { printk(KERN_INFO "%s: can't create /proc/net/router/%s entry!\n", wanrouter_modname, wandev->name); return err; } /* * Initialize fields of the wan_device structure maintained by the * router and update local data. */ wandev->ndev = 0; wandev->dev = NULL; wandev->next = wanrouter_router_devlist; wanrouter_router_devlist = wandev; return 0;}/* * Unregister WAN device. * o shut down device * o unlink device data space from the linked list * o delete device entry in the /proc/net/router directory * o decrement module use count * * Return: 0 Ok * <0 error. * Context: process */int unregister_wan_device(char *name){ struct wan_device *wandev, *prev; if (name == NULL) return -EINVAL; for (wandev = wanrouter_router_devlist, prev = NULL; wandev && strcmp(wandev->name, name); prev = wandev, wandev = wandev->next) ; if (wandev == NULL) return -ENODEV;#ifdef WANDEBUG printk(KERN_INFO "%s: unregistering WAN device %s\n", wanrouter_modname, name);#endif if (wandev->state != WAN_UNCONFIGURED) wanrouter_device_shutdown(wandev); if (prev) prev->next = wandev->next; else wanrouter_router_devlist = wandev->next; wanrouter_proc_delete(wandev); return 0;}#if 0/* * Encapsulate packet. * * Return: encapsulation header size * < 0 - unsupported Ethertype * * Notes: * 1. This function may be called on interrupt context. */int wanrouter_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type){ int hdr_len = 0; switch (type) { case ETH_P_IP: /* IP datagram encapsulation */ hdr_len += 1; skb_push(skb, 1); skb->data[0] = NLPID_IP; break; case ETH_P_IPX: /* SNAP encapsulation */ case ETH_P_ARP: hdr_len += 7; skb_push(skb, 7); skb->data[0] = 0; skb->data[1] = NLPID_SNAP; skb_copy_to_linear_data_offset(skb, 2, wanrouter_oui_ether, sizeof(wanrouter_oui_ether)); *((unsigned short*)&skb->data[5]) = htons(type); break; default: /* Unknown packet type */ printk(KERN_INFO "%s: unsupported Ethertype 0x%04X on interface %s!\n", wanrouter_modname, type, dev->name); hdr_len = -EINVAL; } return hdr_len;}/* * Decapsulate packet. * * Return: Ethertype (in network order) * 0 unknown encapsulation * * Notes: * 1. This function may be called on interrupt context. */__be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev){ int cnt = skb->data[0] ? 0 : 1; /* there may be a pad present */ __be16 ethertype; switch (skb->data[cnt]) { case NLPID_IP: /* IP datagramm */ ethertype = htons(ETH_P_IP); cnt += 1; break; case NLPID_SNAP: /* SNAP encapsulation */ if (memcmp(&skb->data[cnt + 1], wanrouter_oui_ether, sizeof(wanrouter_oui_ether))){ printk(KERN_INFO "%s: unsupported SNAP OUI %02X-%02X-%02X " "on interface %s!\n", wanrouter_modname, skb->data[cnt+1], skb->data[cnt+2], skb->data[cnt+3], dev->name); return 0; } ethertype = *((__be16*)&skb->data[cnt+4]); cnt += 6; break; /* add other protocols, e.g. CLNP, ESIS, ISIS, if needed */ default: printk(KERN_INFO "%s: unsupported NLPID 0x%02X on interface %s!\n", wanrouter_modname, skb->data[cnt], dev->name); return 0; } skb->protocol = ethertype; skb->pkt_type = PACKET_HOST; /* Physically point to point */ skb_pull(skb, cnt); skb_reset_mac_header(skb); return ethertype;}#endif /* 0 *//* * WAN device IOCTL. * o find WAN device associated with this node * o execute requested action or pass command to the device driver */int wanrouter_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int err = 0; struct proc_dir_entry *dent; struct wan_device *wandev; void __user *data = (void __user *)arg; if (!capable(CAP_NET_ADMIN)) return -EPERM; if ((cmd >> 8) != ROUTER_IOCTL) return -EINVAL; dent = PDE(inode); if ((dent == NULL) || (dent->data == NULL)) return -EINVAL; wandev = dent->data; if (wandev->magic != ROUTER_MAGIC) return -EINVAL; switch (cmd) { case ROUTER_SETUP: err = wanrouter_device_setup(wandev, data); break; case ROUTER_DOWN: err = wanrouter_device_shutdown(wandev); break; case ROUTER_STAT: err = wanrouter_device_stat(wandev, data); break; case ROUTER_IFNEW: err = wanrouter_device_new_if(wandev, data); break; case ROUTER_IFDEL: err = wanrouter_device_del_if(wandev, data); break; case ROUTER_IFSTAT: break; default: if ((cmd >= ROUTER_USER) && (cmd <= ROUTER_USER_MAX) && wandev->ioctl) err = wandev->ioctl(wandev, cmd, arg); else err = -EINVAL; } return err;}/* * WAN Driver IOCTL Handlers */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -