📄 vnet.c
字号:
struct vnet_bolt *bolt; if(!gif){ printk(KERN_INFO "vnet: vnet_chr_write gif is NULL!!!\n"); return -EBADF; } bolt=&(gif->bolt); return vnet_guestif_write(bolt, file, buf, count); }/* Put packet to the user space buffer (already verified) */static __inline__ ssize_t vnet_put_user(struct vnet_struct *vnet, struct sk_buff *skb, struct iovec *iv, int len){ struct vnet_pi pi = { 0, skb->protocol }; ssize_t total = 0; if (!(vnet->flags & VNET_NO_PI)) { if ((len -= sizeof(pi)) < 0) return -EINVAL; if (len < skb->len) { /* Packet will be striped */ pi.flags |= VNET_PKT_STRIP; } memcpy_toiovec(iv, (void *) &pi, sizeof(pi)); total += sizeof(pi); } len = MIN(skb->len, len); skb_copy_datagram_iovec(skb, 0, iv, len); total += len; vnet->stats.tx_packets++; vnet->stats.tx_bytes += len; return total;}/* Read */static ssize_t vnet_chr_read(struct file * file, char * buf, size_t count, loff_t *pos){ struct vnet_guestif *gif = (struct vnet_guestif *)file->private_data; struct vnet_bolt *bolt; if(!gif){ printk(KERN_INFO "vnet: vnet_chr_read gif is NULL!!!\n"); return -EBADF; } bolt=&(gif->bolt); return vnet_guestif_read(bolt, file, buf, count); }void vnet_hostif_free(struct vnet_nut *nut){ struct vnet_hostif *hif=(struct vnet_hostif *)nut; DBG(KERN_INFO "vnet: vnet_hostif_free begin\n"); unregister_netdev(&hif->dev); if(nut->procEntry) { vnet_procfs_removeentry(hif->bolt.nut.procEntry,NULL); } kfree(hif); DBG(KERN_INFO "vnet: vnet_hostif_free end\n");}static int vnet_hostif_create(struct inode *inode, struct file *file, struct ifreq *ifr){ struct vnet_guestif *guif = (struct vnet_guestif *)file->private_data; struct vnet_bolt *bolt; struct vnet_nut *peer, *nut; struct vnet_hostif *hif; struct net_device *dev; static unsigned id=0; int hubnum,err; //chy:at first, free already alloced guestif //not very good, will change ????!!!! DBG(KERN_INFO "vnet: vnet_hostif_create begin\n"); if(!guif) { printk(KERN_DEBUG "vnet:vnet_hostif_create gif is null, bad file pointer on close\n"); return -EBADF; } bolt=&(guif->bolt); peer = vnet_hub_disconnect(&bolt->nut); vnet_bolt_removefromlist(bolt); vnet_guestif_free(guif); bolt=NULL; peer=nut=NULL; DBG(KERN_INFO "vnet: vnet_hostif_create: free guestif over\n"); //alloc hif and net_device dev = __dev_get_by_name(ifr->ifr_name); if (dev) { /* Device exist */ hif = dev->priv; bolt=&(hif->bolt); /* if (dev->init != vnet_hostif_init || hif->attached) return -EBUSY; */ /* Check permissions */ /* if (hif->owner != -1) if (current->euid != vnet->owner && !capable(CAP_NET_ADMIN)) return -EPERM; */ } else { char *name; /* Allocate new device */ if (!(hif = kmalloc(sizeof(struct vnet_hostif), GFP_KERNEL)) ) return -ENOMEM; memset(hif, 0, sizeof(struct vnet_hostif)); /* skb_queue_head_init(&hif->readq); init_waitqueue_head(&hif->read_wait); */ hif->bolt.nut.type=VNET_HOSTIF_NUT; hif->bolt.id = id ++; hif->bolt.nut.peer = NULL; hif->bolt.nut.numbolts =1; sprintf(hif->bolt.nut.name,"hif%d",hif->bolt.id); hif->bolt.nut.private=hif; hif->bolt.nut.refCount =0; hif->bolt.nut.connected = FALSE; hif->bolt.nut.index = 0; hif->bolt.nut.procEntry = NULL; hif->bolt.nut.free = vnet_hostif_free; init_waitqueue_head(&hif->bolt.nut.waitQueue); hif->bolt.nut.rcv = vnet_hostif_recv; hif->bolt.nut.cycleDetect = NULL; hif->bolt.nut.boltsChanged = NULL; hif->bolt.nut.isBridged = NULL; /* hif->pollPtr = NULL; hif->clusterCount = 0; hif->pollMask = 0; */ memset(hif->bolt.paddr, 0, sizeof hif->bolt.paddr); memset(hif->bolt.ladrf, 0, sizeof hif->bolt.ladrf); hif->owner = -1; hif->dev.init = vnet_hostif_init; hif->dev.priv = hif; bolt=&hif->bolt; err = -EINVAL; /* Set dev type */ if (ifr->ifr_flags & IFF_VNET) { /* TUN device */ hif->flags |= VNET_VNET_DEV; name = "vnet%d"; } else goto failed; if (*ifr->ifr_name) name = ifr->ifr_name; if ((err = dev_alloc_name(&hif->dev, name)) < 0) goto failed; if ((err = register_netdevice(&hif->dev))) goto failed; //MOD_INC_USE_COUNT; //hif->devName = hif->dev.name; } DBG(KERN_INFO "vnet: vnet_hif_create hostif->name %s\n", hif->dev.name);//chy: different process opens different file for the same dev file. file->private_data = hif; hif->attached = 1; strcpy(ifr->ifr_name, hif->dev.name); //chy connect to a hut bolt hubnum = minor(inode->i_rdev); hubnum = hubnum-VNET_MINOR; DBG(KERN_INFO "vnet: vnet_hif_create hubnum is %d\n",hubnum); if ((hubnum < 0) || (hubnum >= VNET_NUM_HUBS)) { vnet_hub_free_nut(&bolt->nut); printk(KERN_ERR "vnet_hif_create: hubnum error\n"); err= -ENODEV; goto failed; } nut=vnet_hub_alloc_nut(hubnum); if (!nut) { vnet_hub_free_nut(&bolt->nut); printk(KERN_ERR "vnet_hif_create: vnet_hub_alloc_nut error\n"); err=-EBUSY; goto failed; } DBG(KERN_INFO "vnet: vnet_hif_create: call vnet_hub_alloc_nut over.\n"); err = vnet_hub_connect(bolt, nut); if (err) { vnet_hub_free_nut(&bolt->nut); vnet_hub_free_nut(nut); printk(KERN_ERR "vnet_hif_create: vnet_hub_connect error\n"); goto failed; } DBG(KERN_INFO "vnet: vnet_chr_open call vnet_hub_connect over.\n"); vnet_bolt_addtolist(bolt); //chy: store bolt in file pointer private field for later use. file->private_data = bolt; DBG(KERN_INFO "vnet:vnet_hif_create: bolt inserted on hub %d successfully \n", hubnum); /* make proc entry for this nutl */ err=vnet_procfs_makeentry(NULL,hif->bolt.nut.name, S_IFREG, &hif->bolt.nut.procEntry); if(err) goto failed; else { hif->bolt.nut.procEntry->read_proc=vnet_hostif_procread; hif->bolt.nut.procEntry->data=hif; } DBG(KERN_ERR "vnet: vnet_hif_create end\n"); return 0;failed: kfree(hif); DBG(KERN_ERR "vnet_hif_create error end\n"); return err;}static int vnet_chr_ioctl(struct inode *inode, struct file *file, unsigned int iocmd, unsigned long ioarg){ //chy: file->private_data maybe vnet_guestif or vnet_hif struct vnet_bolt * bolt = (struct vnet_bolt *)file->private_data; uint8 paddr[6]; int retval; struct ifreq ifr; DBG(KERN_INFO "vnet: vnet_chr_ioctl begin.\n"); if (!bolt) { printk(KERN_INFO "vnet: vnet_chr_ioctl bad file pointer\n"); return -EBADF; } switch (iocmd) { case VNETSETIFF: if(!bolt) return -EBADFD; if(copy_from_user(&ifr,(void *)ioarg,sizeof(ifr))) return -EFAULT; ifr.ifr_name[IFNAMSIZ-1] = '\0'; rtnl_lock(); retval = vnet_hostif_create(inode, file, &ifr); rtnl_unlock(); if(retval) return retval; copy_to_user((void *)ioarg, &ifr, sizeof(ifr)); break; case SIOCGIFADDR: retval = verify_area(VERIFY_WRITE, (void*)ioarg, ETH_ALEN); if (retval) { return retval; } copy_to_user((void*)ioarg, bolt->paddr, ETH_ALEN); break; case SIOCSIFADDR: retval = verify_area(VERIFY_READ, (void*)ioarg, ETH_ALEN); if (retval) { return retval; } copy_from_user(paddr, (void*)ioarg, ETH_ALEN); memcpy(bolt->paddr, paddr, ETH_ALEN); break; case SIOCGIFFLAGS: retval = verify_area(VERIFY_WRITE, (void*)ioarg, 4); if (retval) { return retval; } put_user(bolt->flags, (uint32*)ioarg); break; case SIOCSIFFLAGS: get_user(bolt->flags,(uint32*)ioarg); bolt->flags = ((bolt->flags & (IFF_UP|IFF_BROADCAST|IFF_DEBUG |IFF_PROMISC|IFF_MULTICAST|IFF_ALLMULTI)) | IFF_RUNNING); break; default: printk(KERN_INFO "vnet: vnet_chr_ioctl unknown iocmd!!!\n"); return -EINVAL; }; return 0;}static int vnet_chr_fasync(int fd, struct file *file, int on){ struct vnet_struct *vnet = (struct vnet_struct *)file->private_data; int ret; if (!vnet) return -EBADFD; DBG(KERN_INFO "%s: vnet_chr_fasync %d\n", vnet->name, on); if ((ret = fasync_helper(fd, file, on, &vnet->fasync)) < 0) return ret; if (on) { vnet->flags |= VNET_FASYNC; if (!file->f_owner.pid) { file->f_owner.pid = current->pid; file->f_owner.uid = current->uid; file->f_owner.euid = current->euid; } } else vnet->flags &= ~VNET_FASYNC; return 0;}static int vnet_chr_open(struct inode *inode, struct file * file){ struct vnet_bolt *bolt; struct vnet_nut *nut; int hubnum; int retval; DBG(KERN_INFO "vnet: vnet_chr_open by PID %d (%s)\n",current->pid, current->comm); DBG(KERN_INFO "vnet: vnet_chr_open file addr is %x, file->f_count.counter %d\n", (unsigned int)file, atomic_read(&file->f_count)); file->private_data = NULL; //chy: allocate bolt if((retval = vnet_guestif_create(&bolt))) return -retval; DBG(KERN_INFO "vnet: vnet_chr_open call vnet_guestif_create over.\n"); //chy:connect to a hub hubnum = minor(inode->i_rdev); hubnum=hubnum-VNET_MINOR; DBG(KERN_INFO "vnet: vnet_chr_open hubnum is %d\n",hubnum); if ((hubnum < 0) || (hubnum >= VNET_NUM_HUBS)) { vnet_hub_free_nut(&bolt->nut); return -ENODEV; } nut=vnet_hub_alloc_nut(hubnum); if (!nut) { vnet_hub_free_nut(&bolt->nut); return -EBUSY; } DBG(KERN_INFO "vnet: vnet_chr_open call vnet_hub_alloc_nut over.\n"); retval = vnet_hub_connect(bolt, nut); if (retval) { vnet_hub_free_nut(&bolt->nut); vnet_hub_free_nut(nut); return retval; } DBG(KERN_INFO "vnet: vnet_chr_open call vnet_hub_connect over.\n"); vnet_bolt_addtolist(bolt); //chy: store bolt in file pointer private field for later use. file->private_data = bolt; DBG(KERN_INFO "vnet: bolt inserted on hub %d successfully \n", hubnum); return 0;}static int vnet_chr_close(struct inode *inode, struct file *filp){ //struct vnet_guestif *gif = (struct vnet_guestif *)filp->private_data; struct vnet_nut *nut = (struct vnet_nut *)filp->private_data; struct vnet_bolt *bolt; struct vnet_nut *peer; struct vnet_guestif *gif; struct vnet_hostif *hif; DBG(KERN_INFO "vnet: vnet_chr_close begin\n"); if(!nut) { printk(KERN_DEBUG "vnet: gif is null, bad file pointer on close\n"); return -EBADF; } if(nut->type==VNET_GUESTIF_NUT){ gif=(struct vnet_guestif *) nut; bolt=&(gif->bolt); peer = vnet_hub_disconnect(&bolt->nut); vnet_bolt_removefromlist(bolt); vnet_guestif_free(gif); //VNetFree(peer); }else if(nut->type==VNET_HOSTIF_NUT){ hif=(struct vnet_hostif *) nut; bolt=&(hif->bolt); peer=vnet_hub_disconnect(&bolt->nut); vnet_bolt_removefromlist(bolt); vnet_hostif_free(nut); }else{ printk("vnet: vnet_chr_close: unkown nut->type !!!!\n"); return -EFAULT; } DBG(KERN_INFO "vnet: vnet_chr_close end\n"); return 0;}void vnet_gusetif_free(struct vnet_nut *this){}void vnet_guestif_recv( struct vnet_nut *nut,struct sk_buff *skb){ struct vnet_guestif *gif= (struct vnet_guestif *)nut->private; uint8 *dest =((struct ethhdr *)(((skb)->data)))->h_dest; uint8 *src=gif->bolt.paddr; DBG(KERN_INFO "vnet: vnet_guestif_recv begin\n"); if (!VNET_UP_AND_RUNNING(gif->bolt.flags)) { gif->stats.droppedDown++; goto drop_packet; } if (!vnet_packetmatch(dest, gif->bolt.paddr, gif->bolt.ladrf, gif->bolt.flags)) { DBG(KERN_INFO "vnet: vnet_guestif_recv mismatch\n"); DBG(KERN_INFO " dest %x:%x:%x:%x:%x:%x\n",dest[0],dest[1],dest[2],dest[3],dest[4],dest[5]); DBG(KERN_INFO " src %x:%x:%x:%x:%x:%x\n",src[0],src[1],src[2],src[3],src[4],src[5]); gif->stats.droppedMismatch++; goto drop_packet; } if (skb_queue_len(&gif->packetQueue) >= VNET_MAX_QLEN) { gif->stats.droppedOverflow++; goto drop_packet; } gif->stats.queued++;//chy: ????/*#ifndef KERNEL_2_1 start_bh_atomic();#endif*/ skb_queue_tail(&gif->packetQueue, skb); //chy:??? /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -