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

📄 strip.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* First make sure we're connected. */	if (!strip_info || strip_info->magic != STRIP_MAGIC ||	    !netif_running(strip_info->dev))		return;	if (strip_info->tx_left > 0) {		int num_written =		    tty->driver->write(tty, strip_info->tx_head,				      strip_info->tx_left);		strip_info->tx_left -= num_written;		strip_info->tx_head += num_written;#ifdef EXT_COUNTERS		strip_info->tx_sbytes += num_written;#endif	} else {		/* Else start transmission of another packet */		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);		strip_unlock(strip_info);	}}static __u8 *add_checksum(__u8 * buffer, __u8 * end){	__u16 sum = 0;	__u8 *p = buffer;	while (p < end)		sum += *p++;	end[3] = hextable[sum & 0xF];	sum >>= 4;	end[2] = hextable[sum & 0xF];	sum >>= 4;	end[1] = hextable[sum & 0xF];	sum >>= 4;	end[0] = hextable[sum & 0xF];	return (end + 4);}static unsigned char *strip_make_packet(unsigned char *buffer,					struct strip *strip_info,					struct sk_buff *skb){	__u8 *ptr = buffer;	__u8 *stuffstate = NULL;	STRIP_Header *header = (STRIP_Header *) skb->data;	MetricomAddress haddr = header->dst_addr;	int len = skb->len - sizeof(STRIP_Header);	MetricomKey key;	/*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len); */	if (header->protocol == htons(ETH_P_IP))		key = SIP0Key;	else if (header->protocol == htons(ETH_P_ARP))		key = ARP0Key;	else {		printk(KERN_ERR		       "%s: strip_make_packet: Unknown packet type 0x%04X\n",		       strip_info->dev->name, ntohs(header->protocol));		return (NULL);	}	if (len > strip_info->mtu) {		printk(KERN_ERR		       "%s: Dropping oversized transmit packet: %d bytes\n",		       strip_info->dev->name, len);		return (NULL);	}	/*	 * If we're sending to ourselves, discard the packet.	 * (Metricom radios choke if they try to send a packet to their own address.)	 */	if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) {		printk(KERN_ERR "%s: Dropping packet addressed to self\n",		       strip_info->dev->name);		return (NULL);	}	/*	 * If this is a broadcast packet, send it to our designated Metricom	 * 'broadcast hub' radio (First byte of address being 0xFF means broadcast)	 */	if (haddr.c[0] == 0xFF) {		u32 brd = 0;		struct in_device *in_dev;		rcu_read_lock();		in_dev = __in_dev_get_rcu(strip_info->dev);		if (in_dev == NULL) {			rcu_read_unlock();			return NULL;		}		if (in_dev->ifa_list)			brd = in_dev->ifa_list->ifa_broadcast;		rcu_read_unlock();		/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */		if (!arp_query(haddr.c, brd, strip_info->dev)) {			printk(KERN_ERR			       "%s: Unable to send packet (no broadcast hub configured)\n",			       strip_info->dev->name);			return (NULL);		}		/*		 * If we are the broadcast hub, don't bother sending to ourselves.		 * (Metricom radios choke if they try to send a packet to their own address.)		 */		if (!memcmp		    (haddr.c, strip_info->true_dev_addr.c, sizeof(haddr)))			return (NULL);	}	*ptr++ = 0x0D;	*ptr++ = '*';	*ptr++ = hextable[haddr.c[2] >> 4];	*ptr++ = hextable[haddr.c[2] & 0xF];	*ptr++ = hextable[haddr.c[3] >> 4];	*ptr++ = hextable[haddr.c[3] & 0xF];	*ptr++ = '-';	*ptr++ = hextable[haddr.c[4] >> 4];	*ptr++ = hextable[haddr.c[4] & 0xF];	*ptr++ = hextable[haddr.c[5] >> 4];	*ptr++ = hextable[haddr.c[5] & 0xF];	*ptr++ = '*';	*ptr++ = key.c[0];	*ptr++ = key.c[1];	*ptr++ = key.c[2];	*ptr++ = key.c[3];	ptr =	    StuffData(skb->data + sizeof(STRIP_Header), len, ptr,		      &stuffstate);	if (strip_info->firmware_level >= ChecksummedMessages)		ptr = add_checksum(buffer + 1, ptr);	*ptr++ = 0x0D;	return (ptr);}static void strip_send(struct strip *strip_info, struct sk_buff *skb){	MetricomAddress haddr;	unsigned char *ptr = strip_info->tx_buff;	int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0;	int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0	    && !doreset;	u32 addr, brd;	/*	 * 1. If we have a packet, encapsulate it and put it in the buffer	 */	if (skb) {		char *newptr = strip_make_packet(ptr, strip_info, skb);		strip_info->tx_pps_count++;		if (!newptr)			strip_info->tx_dropped++;		else {			ptr = newptr;			strip_info->sx_pps_count++;			strip_info->tx_packets++;	/* Count another successful packet */#ifdef EXT_COUNTERS			strip_info->tx_bytes += skb->len;			strip_info->tx_rbytes += ptr - strip_info->tx_buff;#endif			/*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr); */			/*HexDump("Sending", strip_info, strip_info->tx_buff, ptr); */		}	}	/*	 * 2. If it is time for another tickle, tack it on, after the packet	 */	if (doprobe) {		StringDescriptor ts = CommandString[strip_info->next_command];#if TICKLE_TIMERS		{			struct timeval tv;			do_gettimeofday(&tv);			printk(KERN_INFO "**** Sending tickle string %d      at %02d.%06d\n",			       strip_info->next_command, tv.tv_sec % 100,			       tv.tv_usec);		}#endif		if (ptr == strip_info->tx_buff)			*ptr++ = 0x0D;		*ptr++ = '*';	/* First send "**" to provoke an error message */		*ptr++ = '*';		/* Then add the command */		memcpy(ptr, ts.string, ts.length);		/* Add a checksum ? */		if (strip_info->firmware_level < ChecksummedMessages)			ptr += ts.length;		else			ptr = add_checksum(ptr, ptr + ts.length);		*ptr++ = 0x0D;	/* Terminate the command with a <CR> */		/* Cycle to next periodic command? */		if (strip_info->firmware_level >= StructuredMessages)			if (++strip_info->next_command >=			    ARRAY_SIZE(CommandString))				strip_info->next_command = 0;#ifdef EXT_COUNTERS		strip_info->tx_ebytes += ts.length;#endif		strip_info->watchdog_doprobe = jiffies + 10 * HZ;		strip_info->watchdog_doreset = jiffies + 1 * HZ;		/*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */	}	/*	 * 3. Set up the strip_info ready to send the data (if any).	 */	strip_info->tx_head = strip_info->tx_buff;	strip_info->tx_left = ptr - strip_info->tx_buff;	strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);	/*	 * 4. Debugging check to make sure we're not overflowing the buffer.	 */	if (strip_info->tx_size - strip_info->tx_left < 20)		printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n",		       strip_info->dev->name, strip_info->tx_left,		       strip_info->tx_size - strip_info->tx_left);	/*	 * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in	 * the buffer, strip_write_some_more will send it after the reset has finished	 */	if (doreset) {		ResetRadio(strip_info);		return;	}	if (1) {		struct in_device *in_dev;		brd = addr = 0;		rcu_read_lock();		in_dev = __in_dev_get_rcu(strip_info->dev);		if (in_dev) {			if (in_dev->ifa_list) {				brd = in_dev->ifa_list->ifa_broadcast;				addr = in_dev->ifa_list->ifa_local;			}		}		rcu_read_unlock();	}	/*	 * 6. If it is time for a periodic ARP, queue one up to be sent.	 * We only do this if:	 *  1. The radio is working	 *  2. It's time to send another periodic ARP	 *  3. We really know what our address is (and it is not manually set to zero)	 *  4. We have a designated broadcast address configured	 * If we queue up an ARP packet when we don't have a designated broadcast	 * address configured, then the packet will just have to be discarded in	 * strip_make_packet. This is not fatal, but it causes misleading information	 * to be displayed in tcpdump. tcpdump will report that periodic APRs are	 * being sent, when in fact they are not, because they are all being dropped	 * in the strip_make_packet routine.	 */	if (strip_info->working	    && (long) jiffies - strip_info->gratuitous_arp >= 0	    && memcmp(strip_info->dev->dev_addr, zero_address.c,		      sizeof(zero_address))	    && arp_query(haddr.c, brd, strip_info->dev)) {		/*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n",		   strip_info->dev->name, strip_info->arp_interval / HZ); */		strip_info->gratuitous_arp =		    jiffies + strip_info->arp_interval;		strip_info->arp_interval *= 2;		if (strip_info->arp_interval > MaxARPInterval)			strip_info->arp_interval = MaxARPInterval;		if (addr)			arp_send(ARPOP_REPLY, ETH_P_ARP, addr,	/* Target address of ARP packet is our address */				 strip_info->dev,	/* Device to send packet on */				 addr,	/* Source IP address this ARP packet comes from */				 NULL,	/* Destination HW address is NULL (broadcast it) */				 strip_info->dev->dev_addr,	/* Source HW address is our HW address */				 strip_info->dev->dev_addr);	/* Target HW address is our HW address (redundant) */	}	/*	 * 7. All ready. Start the transmission	 */	strip_write_some_more(strip_info->tty);}/* Encapsulate a datagram and kick it into a TTY queue. */static int strip_xmit(struct sk_buff *skb, struct net_device *dev){	struct strip *strip_info = netdev_priv(dev);	if (!netif_running(dev)) {		printk(KERN_ERR "%s: xmit call when iface is down\n",		       dev->name);		return (1);	}	netif_stop_queue(dev);	del_timer(&strip_info->idle_timer);	if (jiffies - strip_info->pps_timer > HZ) {		unsigned long t = jiffies - strip_info->pps_timer;		unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;		unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;		unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t;		strip_info->pps_timer = jiffies;		strip_info->rx_pps_count = 0;		strip_info->tx_pps_count = 0;		strip_info->sx_pps_count = 0;		strip_info->rx_average_pps = (strip_info->rx_average_pps + rx_pps_count + 1) / 2;		strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2;		strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2;		if (rx_pps_count / 8 >= 10)			printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n",			       strip_info->dev->name, rx_pps_count / 8);		if (tx_pps_count / 8 >= 10)			printk(KERN_INFO "%s: WARNING: Tx        %ld packets per second.\n",			       strip_info->dev->name, tx_pps_count / 8);		if (sx_pps_count / 8 >= 10)			printk(KERN_INFO "%s: WARNING: Sending   %ld packets per second.\n",			       strip_info->dev->name, sx_pps_count / 8);	}	spin_lock_bh(&strip_lock);	strip_send(strip_info, skb);	spin_unlock_bh(&strip_lock);	if (skb)		dev_kfree_skb(skb);	return 0;}/* * IdleTask periodically calls strip_xmit, so even when we have no IP packets * to send for an extended period of time, the watchdog processing still gets * done to ensure that the radio stays in Starmode */static void strip_IdleTask(unsigned long parameter){	strip_xmit(NULL, (struct net_device *) parameter);}/* * Create the MAC header for an arbitrary protocol layer * * saddr!=NULL        means use this specific address (n/a for Metricom) * saddr==NULL        means use default device source address * daddr!=NULL        means use this destination address * daddr==NULL        means leave destination address alone *                 (e.g. unresolved arp -- kernel will call *                 rebuild_header later to fill in the address) */static int strip_header(struct sk_buff *skb, struct net_device *dev,			unsigned short type, void *daddr, void *saddr,			unsigned len){	struct strip *strip_info = netdev_priv(dev);	STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header));	/*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type,	   type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : ""); */	header->src_addr = strip_info->true_dev_addr;	header->protocol = htons(type);	/*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */	if (!daddr)		return (-dev->hard_header_len);	header->dst_addr = *(MetricomAddress *) daddr;	return (dev->hard_header_len);}/* * Rebuild the MAC header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. * I think this should return zero if packet is ready to send, * or non-zero if it needs more time to do an address lookup */static int strip_rebuild_header(struct sk_buff *skb){#ifdef CONFIG_INET	STRIP_Header *header = (STRIP_Header *) skb->data;	/* Arp find returns zero if if knows the address, */	/* or if it doesn't know the address it sends an ARP packet and returns non-zero */	return arp_find(header->dst_addr.c, skb) ? 1 : 0;#else	return 0;#endif}/************************************************************************//* Receiving routines							*/static int strip_receive_room(struct tty_struct *tty){	return 0x10000;		/* We can handle an infinite amount of data. :-) */

⌨️ 快捷键说明

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