📄 device.c
字号:
if (!capable(CAP_NET_ADMIN)) return -EPERM;#define doioctl(nam,fun,str) { \ struct str parm; \ dprintk(DEB_CALL, (KERN_DEBUG "%s: " nam "\n", dev->name)); \ if ((e=copy_from_user((void*)&parm,(void*)ifr->ifr_data, \ sizeof(parm)))<0) \ goto out; \ if (parm.magic!=VERSION_MAGIC) { \ printk(KERN_WARNING "%s: ciped version mismatch %lx -> %x\n", dev->name,parm.magic,VERSION_MAGIC); \ e=-EINVAL; goto out; } \ if ((e=fun(dev, &parm))<0) \ goto out; \ e=copy_to_user((void*)ifr->ifr_data, (void*)&parm, sizeof(parm)); \ goto out; \ }#else if (!suser()) return -EPERM;#define doioctl(nam,fun,str) { \ struct str parm; \ dprintk(DEB_CALL, (KERN_DEBUG "%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_DEBUG "%s: opened\n", dev->name)); return 0;}void cipe_close(struct cipe *c){ cipe_zero_c(c); dprintk(DEB_CALL, (KERN_DEBUG "%s: closed\n", c->dev->name)); 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_DEBUG "%s: closing\n", c->dev->name)); /* Tell the attached socket we're going down */ c->sock->shutdown=SHUTDOWN_MASK; c->sock->zapped=1; c->sock->err=ENXIO; c->sock->error_report(c->sock);#ifdef LINUX_21 if (!cipe_isowned(c)) { /* SHOULD NOT HAPPEN. Socket is probably left orphaned */ 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. */ /* Procedural */ dev->open = cipe_dev_open; dev->stop = cipe_dev_close; dev->hard_start_xmit = cipe_xmit; /*dev->hard_header = NULL;*/ /*dev->rebuild_header = NULL;*/ dev->set_mac_address = cipe_set_mac; dev->do_ioctl = cipe_dev_ioctl; dev->get_stats = cipe_get_stats; /* "Hardware" */ dev->type = ARPHRD_TUNNEL; dev->hard_header_len = 0; /* we copy anyway to expand */ dev->mtu = ETH_DATA_LEN -sizeof(struct sockshdr) -cipehdrlen -cipefootlen; dev->tx_queue_len = 100; /* matches ethernet */#ifdef LINUX_21 dev->iflink = -1;#else dev->family = AF_INET; dev->pa_alen = 4; dev->metric = 1;#endif dev_init_buffers(dev); /* New-style flags */ dev->flags = IFF_POINTOPOINT|IFF_NOTRAILERS|IFF_NOARP; return 0;}static int cipe_alloc_dev(int n){ int e=0; struct cipe_ctrl *cc; dprintk(DEB_CALL, (KERN_DEBUG DEVNAME ": cipe_alloc_dev %d\n", n)); if (!(cc=kmalloc(sizeof(struct cipe_ctrl), GFP_KERNEL))) { cipe_ctrls[n]=NULL; 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->cipe); cc->dev.next = NULL; cc->dev.init = cipe_init_dev; /* called by register_netdevice */ /* 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-8v-xx-nn with v=Protocol version, xx=crypto designator, nn=device number. */ cc->dev.dev_addr[2]=0x5E; cc->dev.dev_addr[3]=0x80+ProtocolVersion; cc->dev.dev_addr[4]=CRNAMEC; cc->dev.dev_addr[5]=n; cc->dev.addr_len=6; 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_DEBUG 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; kfree(cc);}static int cipe_init(void){ int e=cipe_check_kernel(); if (e<0) return e; /* sanity check on insmod-provided data */ if (cipe_maxdev<1) cipe_maxdev=1; if (cipe_maxdev>255) { cipe_maxdev=255; printk(KERN_WARNING ": Too many channels requested, setting cipe_maxdev to 255\n"); }#ifdef DEBUG printk(KERN_INFO DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels, debug=%d\n", driver_version, cipe_maxdev, cipe_debug);#else printk(KERN_INFO DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels\n", driver_version, cipe_maxdev);#endif prnseed=(~jiffies)^CURRENT_TIME; 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 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}static void cipe_cleanup(void){ int i; rtnl_LOCK(); for (i=0; i<cipe_maxdev; ++i) cipe_unalloc_dev(i); rtnl_UNLOCK(); kfree(cipe_ctrls);}module_init(cipe_init);module_exit(cipe_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -