📄 device.c
字号:
if (copy_to_user((void*)ifr->ifr_data, (void*)&parm, \ sizeof(parm))) \ e=-EFAULT; \ goto out; \ }#else if (!suser()) return -EPERM;#define doioctl(nam,fun,str) { \ struct str parm; \ dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name)); \ if ((e=verify_area(VERIFY_READ, ifr->ifr_data, sizeof(parm)))<0) \ goto out; \ memcpy_fromfs((void*)&parm, (void*)ifr->ifr_data, sizeof(parm)); \ if (parm.magic!=VERSION_MAGIC) { \ printk(KERN_WARNING "%s: ciped version mismatch\n", dev->name); \ e=-EINVAL; goto out; } \ if ((e=fun(dev, &parm))<0) \ goto out; \ if ((e=verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(parm)))<0) \ goto out; \ memcpy_tofs((void*)ifr->ifr_data, (void*)&parm, sizeof(parm)); \ goto out; \ }#endif /*cipe_use_module();*/ switch (cmd) {#ifdef SIOCGIFCIPPAR case SIOCGIFCIPPAR: doioctl("getpar", cipe_getpar, siocgifcippar);#endif case SIOCSIFCIPPAR: doioctl("setpar", cipe_setpar, siocsifcippar); case SIOCSIFCIPKEY: doioctl("setkey", cipe_setkey, siocsifcipkey); case SIOCSIFCIPATT: doioctl("attach", cipe_attach, siocsifcipatt); case SIOCSIFCIPALL: doioctl("alloc", cipe_alloc, siocsifcipall); case SIOCSIFCIPUNA: doioctl("unalloc", cipe_unalloc, siocsifcipall); /* default: e=-EINVAL; */ } out: /*cipe_unuse_module();*/ return e;#undef doioctl}int cipe_dev_open(struct NET_DEVICE *dev){ DEVTOCIPE(dev,c,-ENODEV); if (!c->sock) return -ENXIO; dprintk(DEB_CALL, (KERN_INFO "%s: opened\n", dev->name)); return 0;}void cipe_close(struct cipe *c){ dprintk(DEB_CALL, (KERN_INFO "%s: closed\n", c->dev->name)); cipe_zero_c(c); cipe_unuse_module();}int cipe_dev_close(struct NET_DEVICE *dev){ struct cipe *c = (struct cipe*)(dev->priv); if ((!c) || (c->magic!=CIPE_MAGIC)) { printk(KERN_WARNING "%s: cipe_dev_close: no valid struct\n", dev->name); return 0; } if (c->sock) { dprintk(DEB_CALL, (KERN_INFO "%s: closing\n", c->dev->name)); /* Tell the attached socket we're going down */ SOCK(c)->sk_shutdown=SHUTDOWN_MASK; SOCK(c)->sk_zapped=1; SOCK(c)->sk_err=ENXIO; SOCK(c)->sk_error_report(SOCK(c));#ifdef LINUX_21 if (!cipe_owner(c)) { /* SHOULD NOT HAPPEN. Socket is probably left orphaned. This is really only an emergency path to allow closing the device after an Oops. */ printk(KERN_ERR "cipe_dev_close: not owned??\n"); cipe_close(c); }#endif } else { cipe_close(c); } return 0;}struct DEV_STATS *cipe_get_stats(struct NET_DEVICE *dev){ DEVTOCIPE(dev,c,NULL); return &(c->stat);}int cipe_set_mac(struct NET_DEVICE *dev, void *p){ struct sockaddr *addr=p; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); return 0;}/*** Initialization and finalization stuff ***/#ifndef LINUX_21static inline void dev_init_buffers(struct NET_DEVICE *dev){ int i; for (i = 0; i < DEV_NUMBUFFS; i++) { skb_queue_head_init(&dev->buffs[i]); }}#endifstatic int cipe_init_dev(struct NET_DEVICE *dev){ struct cipe *c = (struct cipe*)(dev->priv); if (!c) return -ENODEV; memset(c, 0, sizeof(struct cipe)); /* zero the device struct along */ c->magic = CIPE_MAGIC; c->dev = dev; cipe_zero_c(c); /* Device parameters. */#ifdef VER_ETH ether_setup(dev); /* sets hard_header etc. */#endif /* Procedural */ dev->open = cipe_dev_open; dev->stop = cipe_dev_close; dev->hard_start_xmit = cipe_xmit; dev->set_mac_address = cipe_set_mac; dev->do_ioctl = cipe_dev_ioctl; dev->get_stats = cipe_get_stats; /* "Hardware" */#ifndef VER_ETH dev->type = ARPHRD_TUNNEL; dev->hard_header_len = 0; /* we copy anyway to expand */ dev->tx_queue_len = 100; /* matches ethernet */#endif dev->mtu = ETH_DATA_LEN -sizeof(struct sockshdr) -cipehdrlen -cipefootlen -MAXIVSIZE; /* cannot use c->cipher->ivsize here because not initialized */#ifdef LINUX_21 dev->iflink = -1;#else dev->family = AF_INET; dev->pa_alen = 4; dev->metric = 1;#endif#ifndef LINUX_25 dev_init_buffers(dev);#endif /* New-style flags */#ifndef VER_ETH dev->flags = IFF_POINTOPOINT|IFF_NOARP;#endif return 0;}#ifndef LINUX_21struct semaphore cipe_alloc_sem=MUTEX;#endifstatic int cipe_alloc_dev(int n){ int e=0; struct cipe_ctrl *cc; struct NET_DEVICE *d; dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_alloc_dev %d\n", n)); if (!(cc=kmalloc(sizeof(struct cipe_ctrl), GFP_KERNEL))) { cipe_ctrls[n]=NULL; printk(KERN_ERR DEVNAME ": failed to allocate device %d\n", n); return -ENOMEM; } memset((void *)cc, 0, sizeof(*cc));/* If this doesn't compile, define or undefine HAVE_DEVNAME_ARRAY in cipe.h accordingly. */#ifdef HAVE_DEVNAME_ARRAY sprintf(cc->dev.name, DEVNAME "%d", n);#else sprintf(cc->name, DEVNAME "%d", n); cc->dev.name = cc->name;#endif cc->dev.base_addr = n; /* dummy */ cc->dev.priv = (void*)cc; cc->dev.next = NULL; cc->dev.init = cipe_init_dev; /* called by register_netdevice */#if 1 /* Generate a dummy MAC address. This code seems to be in accordance to the address assignments as of RFC1700, pp.172f. We use 00-00-5E-vv-nn-zz with vv=1pppccc0, p=protocol, c=crypto, nn=device number, zz=from MAC of first eth device. */ cc->dev.dev_addr[2]=0x5E; cc->dev.dev_addr[3]=0x80+(ProtocolVersion<<4)+(CRNUM<<1); cc->dev.dev_addr[4]=n; for (d=dev_base; d; d=d->next) if (d->type==ARPHRD_ETHER) { cc->dev.dev_addr[5]=d->dev_addr[5]; break; }#else /* MAC address will be generated from IP as with PLIP. FC-FC-ip-ip-ip-ip */ cc->dev.dev_addr[1]=cc->dev.dev_addr[0]=0xFC;#endif memset(cc->dev.broadcast, 0xFF, ETH_ALEN); cc->dev.addr_len=ETH_ALEN; e=register_netdevice(&(cc->dev)); if (e<0) { kfree(cc); printk(KERN_ERR "%s: register_netdevice() failed\n", cc->dev.name); cc=NULL; } else { cc->cipe.owner=current->pid; } cipe_ctrls[n]=cc; return e;}static void cipe_unalloc_dev(int n){ struct cipe_ctrl *cc=cipe_ctrls[n]; if (!cc) return; dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_unalloc_dev %d\n", n)); if (cc->cipe.magic!=CIPE_MAGIC) { printk(KERN_WARNING DEVNAME ": Ouch: cipe_unalloc_dev() wrong struct\n"); return; } unregister_netdevice(&(cc->dev)); cipe_ctrls[n]=NULL;#ifndef LINUX_21 kfree(cc);#endif}/* For Linux 2.2 and later, the struct cipe_ctrl is freed via a notifier. */#ifdef LINUX_21static int cipe_netdev_event(struct notifier_block *this, unsigned long event, void *ptr){ struct NET_DEVICE *dev = ptr; if (event == NETDEV_UNREGISTER) { struct cipe_ctrl *cc = (struct cipe_ctrl *)dev->priv; if (cc->cipe.magic!=CIPE_MAGIC) { printk(KERN_WARNING DEVNAME ": Ouch: cipe_netdev_event() wrong struct\n"); } else { printk(KERN_DEBUG DEVNAME ": freeing %s\n", cc->dev.name); kfree(cc); } } return NOTIFY_DONE;}static struct notifier_block netdev_notifier = { .notifier_call = cipe_netdev_event,};#endifint init_module(void){ int e=cipe_check_kernel(); if (e<0) return e; /* sanity check on insmod-provided data */ if (cipe_maxdev<1) cipe_maxdev=1;#ifdef NO_DYNDEV if (cipe_maxdev>100) cipe_maxdev=100;#else if (cipe_maxdev>10000) cipe_maxdev=10000;#endif#ifdef DEBUG printk(KERN_INFO DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2003, %d channels, debug=%d\n", driver_version, cipe_maxdev, cipe_debug);#else printk(KERN_INFO DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2003, %d channels\n", driver_version, cipe_maxdev);#endif prnseed=(~jiffies)^CURRENT_TIME_SEC; cipe_ctrls = (struct cipe_ctrl **) kmalloc(sizeof(void*)*cipe_maxdev, GFP_KERNEL); if (!cipe_ctrls) { printk(KERN_ERR DEVNAME ": failed to allocate master control structure\n"); return -ENOMEM; } memset(cipe_ctrls, 0, sizeof(void*)*cipe_maxdev);#ifdef LINUX_21 register_netdevice_notifier(&netdev_notifier);#endif#ifdef NO_DYNDEV { int i; rtnl_LOCK(); for (i=0; i<cipe_maxdev; ++i) if ((e=cipe_alloc_dev(i))) { rtnl_UNLOCK(); return e; } rtnl_UNLOCK(); return 0; }#else rtnl_LOCK(); e=cipe_alloc_dev(0); rtnl_UNLOCK(); return e;#endif}void cleanup_module(void){ int i; rtnl_LOCK(); for (i=0; i<cipe_maxdev; ++i) cipe_unalloc_dev(i); rtnl_UNLOCK();#ifdef LINUX_21 unregister_netdevice_notifier(&netdev_notifier);#endif kfree(cipe_ctrls);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -