📄 wanmain.c
字号:
default: printk(KERN_INFO "%s: unsupported NLPID 0x%02X on interface %s!\n", modname, skb->data[cnt], dev->name); return 0; } skb->protocol = ethertype; skb->pkt_type = PACKET_HOST; /* Physically point to point */ skb->mac.raw = skb->data; skb_pull(skb, cnt); return ethertype;}/* * 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; wan_device_t *wandev; if (!capable(CAP_NET_ADMIN)){ return -EPERM; } if ((cmd >> 8) != ROUTER_IOCTL) return -EINVAL; dent = inode->u.generic_ip; if ((dent == NULL) || (dent->data == NULL)) return -EINVAL; wandev = dent->data; if (wandev->magic != ROUTER_MAGIC) return -EINVAL; switch (cmd) { case ROUTER_SETUP: err = device_setup(wandev, (void*)arg); break; case ROUTER_DOWN: err = device_shutdown(wandev); break; case ROUTER_STAT: err = device_stat(wandev, (void*)arg); break; case ROUTER_IFNEW: err = device_new_if(wandev, (void*)arg); break; case ROUTER_IFDEL: err = device_del_if(wandev, (void*)arg); 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 *//* * Setup WAN link device. * o verify user address space * o allocate kernel memory and copy configuration data to kernel space * o if configuration data includes extension, copy it to kernel space too * o call driver's setup() entry point */static int device_setup (wan_device_t *wandev, wandev_conf_t *u_conf){ void *data = NULL; wandev_conf_t *conf; int err = -EINVAL; if (wandev->setup == NULL) /* Nothing to do ? */ return 0; conf = kmalloc(sizeof(wandev_conf_t), GFP_KERNEL); if (conf == NULL) return -ENOBUFS; if(copy_from_user(conf, u_conf, sizeof(wandev_conf_t))) { kfree(conf); return -EFAULT; } if (conf->magic != ROUTER_MAGIC) { kfree(conf); return -EINVAL; } if (conf->data_size && conf->data) { if(conf->data_size > 128000 || conf->data_size < 0) { kfree(conf); return -EINVAL;; } data = vmalloc(conf->data_size); if (data) { if(!copy_from_user(data, conf->data, conf->data_size)){ conf->data=data; err = wandev->setup(wandev,conf); } else err = -EFAULT; } else err = -ENOBUFS; if (data) vfree(data); } kfree(conf); return err;}/* * Shutdown WAN device. * o delete all not opened logical channels for this device * o call driver's shutdown() entry point */ static int device_shutdown (wan_device_t* wandev){ struct net_device* dev; if (wandev->state == WAN_UNCONFIGURED) return 0; for (dev = wandev->dev; dev;) { if (delete_interface(wandev, dev->name, 0)) { struct net_device **slave = dev->priv; dev = *slave; } } if (wandev->ndev) return -EBUSY; /* there are opened interfaces */ if (wandev->shutdown) return wandev->shutdown(wandev); return 0;}/* * Get WAN device status & statistics. */static int device_stat (wan_device_t *wandev, wandev_stat_t *u_stat){ wandev_stat_t stat; memset(&stat, 0, sizeof(stat)); /* Ask device driver to update device statistics */ if ((wandev->state != WAN_UNCONFIGURED) && wandev->update) wandev->update(wandev); /* Fill out structure */ stat.ndev = wandev->ndev; stat.state = wandev->state; if(copy_to_user(u_stat, &stat, sizeof(stat))) return -EFAULT; return 0;}/* * Create new WAN interface. * o verify user address space * o copy configuration data to kernel address space * o allocate network interface data space * o call driver's new_if() entry point * o make sure there is no interface name conflict * o register network interface */static int device_new_if (wan_device_t* wandev, wanif_conf_t* u_conf){ wanif_conf_t conf; struct net_device *dev; int err; if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL)) return -ENODEV; if(copy_from_user(&conf, u_conf, sizeof(wanif_conf_t))) return -EFAULT; if (conf.magic != ROUTER_MAGIC) return -EINVAL; dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); if (dev == NULL) return -ENOBUFS; memset(dev, 0, sizeof(struct net_device)); err = wandev->new_if(wandev, dev, &conf); if (!err) { /* Register network interface. This will invoke init() * function supplied by the driver. If device registered * successfully, add it to the interface list. */ if (dev->name == NULL) err = -EINVAL; else if (dev_get(dev->name)) err = -EEXIST; /* name already exists */ else {#ifdef WANDEBUG printk(KERN_INFO "%s: registering interface %s...\n", modname, dev->name);#endif err = register_netdev(dev); if (!err) { struct net_device **slave = dev->priv; cli(); /***** critical section start *****/ *slave = wandev->dev; wandev->dev = dev; ++wandev->ndev; sti(); /****** critical section end ******/ return 0; /* done !!! */ } } if (wandev->del_if) wandev->del_if(wandev, dev); } kfree(dev); return err;}/* * Delete WAN logical channel. * o verify user address space * o copy configuration data to kernel address space */static int device_del_if (wan_device_t *wandev, char *u_name){ char name[WAN_IFNAME_SZ + 1]; if (wandev->state == WAN_UNCONFIGURED) return -ENODEV; memset(name, 0, sizeof(name)); if(copy_from_user(name, u_name, WAN_IFNAME_SZ)) return -EFAULT; return delete_interface(wandev, name, 0);}/* * Miscellaneous Functions *//* * Find WAN device by name. * Return pointer to the WAN device data space or NULL if device not found. */static wan_device_t *find_device(char *name){ wan_device_t *wandev; for (wandev = router_devlist;wandev && strcmp(wandev->name, name); wandev = wandev->next); return wandev;}/* * Delete WAN logical channel identified by its name. * o find logical channel by its name * o call driver's del_if() entry point * o unregister network interface * o unlink channel data space from linked list of channels * o release channel data space * * Return: 0 success * -ENODEV channel not found. * -EBUSY interface is open * * Note: If (force != 0), then device will be destroyed even if interface * associated with it is open. It's caller's responsibility to make * sure that opened interfaces are not removed! */static int delete_interface (wan_device_t *wandev, char *name, int force){ struct net_device *dev, *prev; dev = wandev->dev; prev = NULL; while (dev && strcmp(name, dev->name)) { struct net_device **slave = dev->priv; prev = dev; dev = *slave; } if (dev == NULL) return -ENODEV; /* interface not found */ if (netif_running(dev)) { if (force) { printk(KERN_WARNING "%s: deleting opened interface %s!\n", modname, name); } else return -EBUSY; /* interface in use */ } if (wandev->del_if) wandev->del_if(wandev, dev); cli(); /***** critical section start *****/ if (prev) { struct net_device **prev_slave = prev->priv; struct net_device **slave = dev->priv; *prev_slave = *slave; } else { struct net_device **slave = dev->priv; wandev->dev = *slave; } --wandev->ndev; sti(); /****** critical section end ******/ printk("Unregistering '%s'\n", dev->name); unregister_netdev(dev); kfree(dev); return 0;}EXPORT_SYMBOL(register_wan_device);EXPORT_SYMBOL(unregister_wan_device);EXPORT_SYMBOL(wanrouter_encapsulate);EXPORT_SYMBOL(wanrouter_type_trans);/* * End */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -