⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev.c

📁 完整的1.0代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	  if (backlog != NULL)	      return(1);	  printk("INET: dev_rint: no longer dropping packets.\n");	  dropping = 0;	}	skb = alloc_skb(sizeof(*skb) + len, GFP_ATOMIC);	if (skb == NULL) {		printk("dev_rint: packet dropped on %s (no memory) !\n",		       dev->name);		dropping = 1;		return(1);	}	skb->mem_len = sizeof(*skb) + len;	skb->mem_addr = (struct sk_buff *) skb;	/* First we copy the packet into a buffer, and save it for later. */	to = skb->data;	left = len;	len2 = len;	while (len2 > 0) {		amount = min(len2, (unsigned long) dev->rmem_end -						(unsigned long) buff);		memcpy(to, buff, amount);		len2 -= amount;		left -= amount;		buff += amount;		to += amount;		if ((unsigned long) buff == dev->rmem_end)			buff = (unsigned char *) dev->rmem_start;	}  }  skb->len = len;  skb->dev = dev;  skb->free = 1;  netif_rx(skb);  /* OK, all done. */  return(0);}/* This routine causes all interfaces to try to send some data. */voiddev_transmit(void){  struct device *dev;  for (dev = dev_base; dev != NULL; dev = dev->next) {	if (!dev->tbusy) {		dev_tint(dev);	}  }}static volatile char in_bh = 0;int in_inet_bh()	/* Used by timer.c */{	return(in_bh==0?0:1);}/* * This function gets called periodically, to see if we can * process any data that came in from some interface. * */voidinet_bh(void *tmp){  struct sk_buff *skb;  struct packet_type *ptype;  unsigned short type;  unsigned char flag = 0;  int nitcount;  /* Atomically check and mark our BUSY state. */  if (set_bit(1, (void*)&in_bh))      return;  /* Can we send anything now? */  dev_transmit();    /* Any data left to process? */  while((skb=skb_dequeue(&backlog))!=NULL)  {  	nitcount=dev_nit;	flag=0;	sti();       /*	* Bump the pointer to the next structure.	* This assumes that the basic 'skb' pointer points to	* the MAC header, if any (as indicated by its "length"	* field).  Take care now!	*/       skb->h.raw = skb->data + skb->dev->hard_header_len;       skb->len -= skb->dev->hard_header_len;       /*	* Fetch the packet protocol ID.  This is also quite ugly, as	* it depends on the protocol driver (the interface itself) to	* know what the type is, or where to get it from.  The Ethernet	* interfaces fetch the ID from the two bytes in the Ethernet MAC	* header (the h_proto field in struct ethhdr), but drivers like	* SLIP and PLIP have no alternative but to force the type to be	* IP or something like that.  Sigh- FvK	*/       type = skb->dev->type_trans(skb, skb->dev);	/*	 * We got a packet ID.  Now loop over the "known protocols"	 * table (which is actually a linked list, but this will	 * change soon if I get my way- FvK), and forward the packet	 * to anyone who wants it.	 */	for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) {		if (ptype->type == type || ptype->type == NET16(ETH_P_ALL)) {			struct sk_buff *skb2;			if (ptype->type==NET16(ETH_P_ALL))				nitcount--;			if (ptype->copy || nitcount) {	/* copy if we need to	*/				skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);				if (skb2 == NULL) 					continue;				memcpy(skb2, (const void *) skb, skb->mem_len);				skb2->mem_addr = skb2;				skb2->h.raw = (unsigned char *)(				    (unsigned long) skb2 +				    (unsigned long) skb->h.raw -				    (unsigned long) skb				);				skb2->free = 1;			} else {				skb2 = skb;			}			/* This used to be in the 'else' part, but then			 * we don't have this flag set when we get a			 * protocol that *does* require copying... -FvK			 */			flag = 1;			/* Kick the protocol handler. */			ptype->func(skb2, skb->dev, ptype);		}	}	/*	 * That's odd.  We got an unknown packet.  Who's using	 * stuff like Novell or Amoeba on this network??	 */	if (!flag) {		DPRINTF((DBG_DEV,			"INET: unknown packet type 0x%04X (ignored)\n", type));		skb->sk = NULL;		kfree_skb(skb, FREE_WRITE);	}	/* Again, see if we can transmit anything now. */	dev_transmit();	cli();  }  in_bh = 0;  sti();  dev_transmit();}/* * This routine is called when an device driver (i.e. an * interface) is * ready to transmit a packet. */ void dev_tint(struct device *dev){	int i;	struct sk_buff *skb;		for(i = 0;i < DEV_NUMBUFFS; i++) {		while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)		{			skb->magic = 0;			skb->next = NULL;			skb->prev = NULL;			dev->queue_xmit(skb,dev,-i - 1);			if (dev->tbusy)				return;		}	}}/* Perform a SIOCGIFCONF call. */static intdev_ifconf(char *arg){  struct ifconf ifc;  struct ifreq ifr;  struct device *dev;  char *pos;  int len;  int err;  /* Fetch the caller's info block. */  err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));  if(err)  	return err;  memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));  len = ifc.ifc_len;  pos = ifc.ifc_buf;  /* Loop over the interfaces, and write an info block for each. */  for (dev = dev_base; dev != NULL; dev = dev->next) {        if(!(dev->flags & IFF_UP))        	continue;	memset(&ifr, 0, sizeof(struct ifreq));	strcpy(ifr.ifr_name, dev->name);	(*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;	(*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;	/* Write this block to the caller's space. */	memcpy_tofs(pos, &ifr, sizeof(struct ifreq));	pos += sizeof(struct ifreq);	len -= sizeof(struct ifreq);	if (len < sizeof(struct ifreq)) break;  }  /* All done.  Write the updated control block back to the caller. */  ifc.ifc_len = (pos - ifc.ifc_buf);  ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;  memcpy_tofs(arg, &ifc, sizeof(struct ifconf));  return(pos - arg);}/* Print device statistics. */char *sprintf_stats(char *buffer, struct device *dev){  char *pos = buffer;  struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);  if (stats)    pos += sprintf(pos, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",		   dev->name,		   stats->rx_packets, stats->rx_errors,		   stats->rx_dropped + stats->rx_missed_errors,		   stats->rx_fifo_errors,		   stats->rx_length_errors + stats->rx_over_errors		   + stats->rx_crc_errors + stats->rx_frame_errors,		   stats->tx_packets, stats->tx_errors, stats->tx_dropped,		   stats->tx_fifo_errors, stats->collisions,		   stats->tx_carrier_errors + stats->tx_aborted_errors		   + stats->tx_window_errors + stats->tx_heartbeat_errors);  else      pos += sprintf(pos, "%6s: No statistics available.\n", dev->name);  return pos;}/* Called from the PROCfs module. */intdev_get_info(char *buffer){  char *pos = buffer;  struct device *dev;  pos +=      sprintf(pos,	      "Inter-|   Receive                  |  Transmit\n"	      " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");  for (dev = dev_base; dev != NULL; dev = dev->next) {      pos = sprintf_stats(pos, dev);  }  return pos - buffer;}static inline int bad_mask(unsigned long mask, unsigned long addr){	if (addr & (mask = ~mask))		return 1;	mask = ntohl(mask);	if (mask & (mask+1))		return 1;	return 0;}/* Perform the SIOCxIFxxx calls. */static intdev_ifsioc(void *arg, unsigned int getset){  struct ifreq ifr;  struct device *dev;  int ret;  /* Fetch the caller's info block. */  int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));  if(err)  	return err;  memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));  /* See which interface the caller is talking about. */  if ((dev = dev_get(ifr.ifr_name)) == NULL) return(-EINVAL);  switch(getset) {	case SIOCGIFFLAGS:		ifr.ifr_flags = dev->flags;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFFLAGS:		{		  int old_flags = dev->flags;		  dev->flags = ifr.ifr_flags & (			IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |			IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |			IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI);					  if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))		  	dev->set_multicast_list(dev,0,NULL);		  if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))		  	dev->set_multicast_list(dev,-1,NULL);		  if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) {			ret = dev_close(dev);		  } else		  {		      ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))			? dev_open(dev) : 0;		      if(ret<0)		      	dev->flags&=~IFF_UP;	/* Didnt open so down the if */		  }	        }		break;	case SIOCGIFADDR:		(*(struct sockaddr_in *)		  &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;		(*(struct sockaddr_in *)		  &ifr.ifr_addr).sin_family = dev->family;		(*(struct sockaddr_in *)		  &ifr.ifr_addr).sin_port = 0;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFADDR:		dev->pa_addr = (*(struct sockaddr_in *)				 &ifr.ifr_addr).sin_addr.s_addr;		dev->family = ifr.ifr_addr.sa_family;		dev->pa_mask = get_mask(dev->pa_addr);		dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;		ret = 0;		break;	case SIOCGIFBRDADDR:		(*(struct sockaddr_in *)		  &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr;		(*(struct sockaddr_in *)		  &ifr.ifr_broadaddr).sin_family = dev->family;		(*(struct sockaddr_in *)		  &ifr.ifr_broadaddr).sin_port = 0;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFBRDADDR:		dev->pa_brdaddr = (*(struct sockaddr_in *)				    &ifr.ifr_broadaddr).sin_addr.s_addr;		ret = 0;		break;	case SIOCGIFDSTADDR:		(*(struct sockaddr_in *)		  &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr;		(*(struct sockaddr_in *)		  &ifr.ifr_broadaddr).sin_family = dev->family;		(*(struct sockaddr_in *)		  &ifr.ifr_broadaddr).sin_port = 0;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFDSTADDR:		dev->pa_dstaddr = (*(struct sockaddr_in *)				    &ifr.ifr_dstaddr).sin_addr.s_addr;		ret = 0;		break;	case SIOCGIFNETMASK:		(*(struct sockaddr_in *)		  &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask;		(*(struct sockaddr_in *)		  &ifr.ifr_netmask).sin_family = dev->family;		(*(struct sockaddr_in *)		  &ifr.ifr_netmask).sin_port = 0;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFNETMASK: {		unsigned long mask = (*(struct sockaddr_in *)			&ifr.ifr_netmask).sin_addr.s_addr;		ret = -EINVAL;		if (bad_mask(mask,0))			break;		dev->pa_mask = mask;		ret = 0;		break;	}	case SIOCGIFMETRIC:		ifr.ifr_metric = dev->metric;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFMETRIC:		dev->metric = ifr.ifr_metric;		ret = 0;		break;	case SIOCGIFMTU:		ifr.ifr_mtu = dev->mtu;		memcpy_tofs(arg, &ifr, sizeof(struct ifreq));		ret = 0;		break;	case SIOCSIFMTU:		dev->mtu = ifr.ifr_mtu;		ret = 0;		break;	case SIOCGIFMEM:		printk("NET: ioctl(SIOCGIFMEM, 0x%08X)\n", (int)arg);		ret = -EINVAL;		break;	case SIOCSIFMEM:		printk("NET: ioctl(SIOCSIFMEM, 0x%08X)\n", (int)arg);		ret = -EINVAL;		break;	case SIOCGIFHWADDR:		memcpy(ifr.ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN);		memcpy_tofs(arg,&ifr,sizeof(struct ifreq));		ret=0;		break;	default:		ret = -EINVAL;  }  return(ret);}/* This function handles all "interface"-type I/O control requests. */intdev_ioctl(unsigned int cmd, void *arg){  struct iflink iflink;  struct ddi_device *dev;  switch(cmd) {	case IP_SET_DEV:		printk("Your network configuration program needs upgrading.\n");		return -EINVAL;	case SIOCGIFCONF:		(void) dev_ifconf((char *) arg);		return 0;	case SIOCGIFFLAGS:	case SIOCGIFADDR:	case SIOCGIFDSTADDR:	case SIOCGIFBRDADDR:	case SIOCGIFNETMASK:	case SIOCGIFMETRIC:	case SIOCGIFMTU:	case SIOCGIFMEM:	case SIOCGIFHWADDR:		return dev_ifsioc(arg, cmd);	case SIOCSIFFLAGS:	case SIOCSIFADDR:	case SIOCSIFDSTADDR:	case SIOCSIFBRDADDR:	case SIOCSIFNETMASK:	case SIOCSIFMETRIC:	case SIOCSIFMTU:	case SIOCSIFMEM:		if (!suser())			return -EPERM;		return dev_ifsioc(arg, cmd);	case SIOCSIFLINK:		if (!suser())			return -EPERM;		memcpy_fromfs(&iflink, arg, sizeof(iflink));		dev = ddi_map(iflink.id);		if (dev == NULL)			return -EINVAL;		/* Now allocate an interface and connect it. */		printk("AF_INET: DDI \"%s\" linked to stream \"%s\"\n",						dev->name, iflink.stream);		return 0;	default:		return -EINVAL;  }}/* Initialize the DEV module. */voiddev_init(void){  struct device *dev, *dev2;  /* Add the devices.   * If the call to dev->init fails, the dev is removed   * from the chain disconnecting the device until the   * next reboot.   */  dev2 = NULL;  for (dev = dev_base; dev != NULL; dev=dev->next) {	if (dev->init && dev->init(dev)) {		if (dev2 == NULL) dev_base = dev->next;		  else dev2->next = dev->next;	} else {		dev2 = dev;	}  }  /* Set up some IP addresses. */  ip_bcast = in_aton("255.255.255.255");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -