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

📄 strip.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* * This function parses the response to the ATS300? command, * extracting the radio version and serial number. */static void get_radio_version(struct strip *strip_info, __u8 * ptr, __u8 * end){	__u8 *p, *value_begin, *value_end;	int len;	/* Determine the beginning of the second line of the payload */	p = ptr;	while (p < end && *p != 10)		p++;	if (p >= end)		return;	p++;	value_begin = p;	/* Determine the end of line */	while (p < end && *p != 10)		p++;	if (p >= end)		return;	value_end = p;	p++;	len = value_end - value_begin;	len = min_t(int, len, sizeof(FirmwareVersion) - 1);	if (strip_info->firmware_version.c[0] == 0)		printk(KERN_INFO "%s: Radio Firmware: %.*s\n",		       strip_info->dev->name, len, value_begin);	sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin);	/* Look for the first colon */	while (p < end && *p != ':')		p++;	if (p >= end)		return;	/* Skip over the space */	p += 2;	len = sizeof(SerialNumber) - 1;	if (p + len <= end) {		sprintf(strip_info->serial_number.c, "%.*s", len, p);	} else {		printk(KERN_DEBUG		       "STRIP: radio serial number shorter (%zd) than expected (%d)\n",		       end - p, len);	}}/* * This function parses the response to the ATS325? command, * extracting the radio battery voltage. */static void get_radio_voltage(struct strip *strip_info, __u8 * ptr, __u8 * end){	int len;	len = sizeof(BatteryVoltage) - 1;	if (ptr + len <= end) {		sprintf(strip_info->battery_voltage.c, "%.*s", len, ptr);	} else {		printk(KERN_DEBUG		       "STRIP: radio voltage string shorter (%zd) than expected (%d)\n",		       end - ptr, len);	}}/* * This function parses the responses to the AT~LA and ATS311 commands, * which list the radio's neighbours. */static void get_radio_neighbours(MetricomNodeTable * table, __u8 * ptr, __u8 * end){	table->num_nodes = 0;	while (ptr < end && table->num_nodes < NODE_TABLE_SIZE) {		MetricomNode *node = &table->node[table->num_nodes++];		char *dst = node->c, *limit = dst + sizeof(*node) - 1;		while (ptr < end && *ptr <= 32)			ptr++;		while (ptr < end && dst < limit && *ptr != 10)			*dst++ = *ptr++;		*dst++ = 0;		while (ptr < end && ptr[-1] != 10)			ptr++;	}	do_gettimeofday(&table->timestamp);}static int get_radio_address(struct strip *strip_info, __u8 * p){	MetricomAddress addr;	if (string_to_radio_address(&addr, p))		return (1);	/* See if our radio address has changed */	if (memcmp(strip_info->true_dev_addr.c, addr.c, sizeof(addr))) {		MetricomAddressString addr_string;		radio_address_to_string(&addr, &addr_string);		printk(KERN_INFO "%s: Radio address = %s\n",		       strip_info->dev->name, addr_string.c);		strip_info->true_dev_addr = addr;		if (!strip_info->manual_dev_addr)			*(MetricomAddress *) strip_info->dev->dev_addr =			    addr;		/* Give the radio a few seconds to get its head straight, then send an arp */		strip_info->gratuitous_arp = jiffies + 15 * HZ;		strip_info->arp_interval = 1 * HZ;	}	return (0);}static int verify_checksum(struct strip *strip_info){	__u8 *p = strip_info->sx_buff;	__u8 *end = strip_info->sx_buff + strip_info->sx_count - 4;	u_short sum =	    (READHEX16(end[0]) << 12) | (READHEX16(end[1]) << 8) |	    (READHEX16(end[2]) << 4) | (READHEX16(end[3]));	while (p < end)		sum -= *p++;	if (sum == 0 && strip_info->firmware_level == StructuredMessages) {		strip_info->firmware_level = ChecksummedMessages;		printk(KERN_INFO "%s: Radio provides message checksums\n",		       strip_info->dev->name);	}	return (sum == 0);}static void RecvErr(char *msg, struct strip *strip_info){	__u8 *ptr = strip_info->sx_buff;	__u8 *end = strip_info->sx_buff + strip_info->sx_count;	DumpData(msg, strip_info, ptr, end);	strip_info->rx_errors++;}static void RecvErr_Message(struct strip *strip_info, __u8 * sendername,			    const __u8 * msg, u_long len){	if (has_prefix(msg, len, "001")) {	/* Not in StarMode! */		RecvErr("Error Msg:", strip_info);		printk(KERN_INFO "%s: Radio %s is not in StarMode\n",		       strip_info->dev->name, sendername);	}	else if (has_prefix(msg, len, "002")) {	/* Remap handle */		/* We ignore "Remap handle" messages for now */	}	else if (has_prefix(msg, len, "003")) {	/* Can't resolve name */		RecvErr("Error Msg:", strip_info);		printk(KERN_INFO "%s: Destination radio name is unknown\n",		       strip_info->dev->name);	}	else if (has_prefix(msg, len, "004")) {	/* Name too small or missing */		strip_info->watchdog_doreset = jiffies + LongTime;#if TICKLE_TIMERS		{			struct timeval tv;			do_gettimeofday(&tv);			printk(KERN_INFO			       "**** Got ERR_004 response         at %02d.%06d\n",			       tv.tv_sec % 100, tv.tv_usec);		}#endif		if (!strip_info->working) {			strip_info->working = TRUE;			printk(KERN_INFO "%s: Radio now in starmode\n",			       strip_info->dev->name);			/*			 * If the radio has just entered a working state, we should do our first			 * probe ASAP, so that we find out our radio address etc. without delay.			 */			strip_info->watchdog_doprobe = jiffies;		}		if (strip_info->firmware_level == NoStructure && sendername) {			strip_info->firmware_level = StructuredMessages;			strip_info->next_command = 0;	/* Try to enable checksums ASAP */			printk(KERN_INFO			       "%s: Radio provides structured messages\n",			       strip_info->dev->name);		}		if (strip_info->firmware_level >= StructuredMessages) {			/*			 * If this message has a valid checksum on the end, then the call to verify_checksum			 * will elevate the firmware_level to ChecksummedMessages for us. (The actual return			 * code from verify_checksum is ignored here.)			 */			verify_checksum(strip_info);			/*			 * If the radio has structured messages but we don't yet have all our information about it,			 * we should do probes without delay, until we have gathered all the information			 */			if (!GOT_ALL_RADIO_INFO(strip_info))				strip_info->watchdog_doprobe = jiffies;		}	}	else if (has_prefix(msg, len, "005"))	/* Bad count specification */		RecvErr("Error Msg:", strip_info);	else if (has_prefix(msg, len, "006"))	/* Header too big */		RecvErr("Error Msg:", strip_info);	else if (has_prefix(msg, len, "007")) {	/* Body too big */		RecvErr("Error Msg:", strip_info);		printk(KERN_ERR		       "%s: Error! Packet size too big for radio.\n",		       strip_info->dev->name);	}	else if (has_prefix(msg, len, "008")) {	/* Bad character in name */		RecvErr("Error Msg:", strip_info);		printk(KERN_ERR		       "%s: Radio name contains illegal character\n",		       strip_info->dev->name);	}	else if (has_prefix(msg, len, "009"))	/* No count or line terminator */		RecvErr("Error Msg:", strip_info);	else if (has_prefix(msg, len, "010"))	/* Invalid checksum */		RecvErr("Error Msg:", strip_info);	else if (has_prefix(msg, len, "011"))	/* Checksum didn't match */		RecvErr("Error Msg:", strip_info);	else if (has_prefix(msg, len, "012"))	/* Failed to transmit packet */		RecvErr("Error Msg:", strip_info);	else		RecvErr("Error Msg:", strip_info);}static void process_AT_response(struct strip *strip_info, __u8 * ptr,				__u8 * end){	u_long len;	__u8 *p = ptr;	while (p < end && p[-1] != 10)		p++;		/* Skip past first newline character */	/* Now ptr points to the AT command, and p points to the text of the response. */	len = p - ptr;#if TICKLE_TIMERS	{		struct timeval tv;		do_gettimeofday(&tv);		printk(KERN_INFO "**** Got AT response %.7s      at %02d.%06d\n",		       ptr, tv.tv_sec % 100, tv.tv_usec);	}#endif	if (has_prefix(ptr, len, "ATS300?"))		get_radio_version(strip_info, p, end);	else if (has_prefix(ptr, len, "ATS305?"))		get_radio_address(strip_info, p);	else if (has_prefix(ptr, len, "ATS311?"))		get_radio_neighbours(&strip_info->poletops, p, end);	else if (has_prefix(ptr, len, "ATS319=7"))		verify_checksum(strip_info);	else if (has_prefix(ptr, len, "ATS325?"))		get_radio_voltage(strip_info, p, end);	else if (has_prefix(ptr, len, "AT~LA"))		get_radio_neighbours(&strip_info->portables, p, end);	else		RecvErr("Unknown AT Response:", strip_info);}static void process_ACK(struct strip *strip_info, __u8 * ptr, __u8 * end){	/* Currently we don't do anything with ACKs from the radio */}static void process_Info(struct strip *strip_info, __u8 * ptr, __u8 * end){	if (ptr + 16 > end)		RecvErr("Bad Info Msg:", strip_info);}static struct net_device *get_strip_dev(struct strip *strip_info){	/* If our hardware address is *manually set* to zero, and we know our */	/* real radio hardware address, try to find another strip device that has been */	/* manually set to that address that we can 'transfer ownership' of this packet to  */	if (strip_info->manual_dev_addr &&	    !memcmp(strip_info->dev->dev_addr, zero_address.c,		    sizeof(zero_address))	    && memcmp(&strip_info->true_dev_addr, zero_address.c,		      sizeof(zero_address))) {		struct net_device *dev;		read_lock_bh(&dev_base_lock);		dev = dev_base;		while (dev) {			if (dev->type == strip_info->dev->type &&			    !memcmp(dev->dev_addr,				    &strip_info->true_dev_addr,				    sizeof(MetricomAddress))) {				printk(KERN_INFO				       "%s: Transferred packet ownership to %s.\n",				       strip_info->dev->name, dev->name);				read_unlock_bh(&dev_base_lock);				return (dev);			}			dev = dev->next;		}		read_unlock_bh(&dev_base_lock);	}	return (strip_info->dev);}/* * Send one completely decapsulated datagram to the next layer. */static void deliver_packet(struct strip *strip_info, STRIP_Header * header,			   __u16 packetlen){	struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen);	if (!skb) {		printk(KERN_ERR "%s: memory squeeze, dropping packet.\n",		       strip_info->dev->name);		strip_info->rx_dropped++;	} else {		memcpy(skb_put(skb, sizeof(STRIP_Header)), header,		       sizeof(STRIP_Header));		memcpy(skb_put(skb, packetlen), strip_info->rx_buff,		       packetlen);		skb->dev = get_strip_dev(strip_info);		skb->protocol = header->protocol;		skb->mac.raw = skb->data;		/* Having put a fake header on the front of the sk_buff for the */		/* benefit of tools like tcpdump, skb_pull now 'consumes' that  */		/* fake header before we hand the packet up to the next layer.  */		skb_pull(skb, sizeof(STRIP_Header));		/* Finally, hand the packet up to the next layer (e.g. IP or ARP, etc.) */		strip_info->rx_packets++;		strip_info->rx_pps_count++;#ifdef EXT_COUNTERS		strip_info->rx_bytes += packetlen;#endif		skb->dev->last_rx = jiffies;		netif_rx(skb);	}}static void process_IP_packet(struct strip *strip_info,			      STRIP_Header * header, __u8 * ptr,			      __u8 * end){	__u16 packetlen;	/* Decode start of the IP packet header */	ptr = UnStuffData(ptr, end, strip_info->rx_buff, 4);	if (!ptr) {		RecvErr("IP Packet too short", strip_info);		return;	}	packetlen = ((__u16) strip_info->rx_buff[2] << 8) | strip_info->rx_buff[3];	if (packetlen > MAX_RECV_MTU) {		printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n",		       strip_info->dev->name, packetlen);		strip_info->rx_dropped++;		return;	}	/*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */	/* Decode remainder of the IP packet */	ptr =	    UnStuffData(ptr, end, strip_info->rx_buff + 4, packetlen - 4);	if (!ptr) {		RecvErr("IP Packet too short", strip_info);		return;	}	if (ptr < end) {		RecvErr("IP Packet too long", strip_info);		return;	}	header->protocol = htons(ETH_P_IP);	deliver_packet(strip_info, header, packetlen);}static void process_ARP_packet(struct strip *strip_info,			       STRIP_Header * header, __u8 * ptr,			       __u8 * end){	__u16 packetlen;	struct arphdr *arphdr = (struct arphdr *) strip_info->rx_buff;	/* Decode start of the ARP packet */	ptr = UnStuffData(ptr, end, strip_info->rx_buff, 8);	if (!ptr) {		RecvErr("ARP Packet too short", strip_info);		return;	}	packetlen = 8 + (arphdr->ar_hln + arphdr->ar_pln) * 2;	if (packetlen > MAX_RECV_MTU) {		printk(KERN_INFO		       "%s: Dropping oversized received ARP packet: %d bytes\n",		       strip_info->dev->name, packetlen);		strip_info->rx_dropped+

⌨️ 快捷键说明

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