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

📄 ethernet.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * above the monRecvEnetPkt() function.
	 */
	if (AppPktPtr) {
		memcpy(AppPktPtr,(char *)ehdr,size > AppPktLen ? AppPktLen : size);
		AppPktPtr = 0;
		AppPktLen = size;
		return;
	}

	if (ehdr->ether_type == ecs(ETHERTYPE_ARP)) {
		processARP(ehdr,size);
		return;
	}
	else if (ehdr->ether_type == ecs(ETHERTYPE_REVARP)) {
		processRARP(ehdr,size);
		return;
	}
	else if (ehdr->ether_type != ecs(ETHERTYPE_IP)) {
		return;
	}

	/* If source MAC address is this board, then assume we received our
	 * own outgoing broadcast message...
	 */
	if (!memcmp((char *)&(ehdr->ether_shost),BinEnetAddr,6)) {
		return;
	}

	ihdr = (struct ip *) (ehdr + 1);

	/* If not version # 4, return now... */
	if (getIP_V(ihdr->ip_vhl) != 4) {
		return;
	}

	/* IP address filtering:
	 * At this point, the only packets accepted are those destined for this
	 * board's IP address or broadcast to the subnet, plus DHCP, if active,
	 */
	if (memcmp((char *)&(ihdr->ip_dst),BinIpAddr,4)) {
		long net_mask, sub_net_addr;

		GetBinNetMask( (uchar *) &net_mask );
		sub_net_addr = ihdr->ip_dst.s_addr & ~net_mask;	/* x.x.x.255 */
		uhdr = (struct Udphdr *)(ihdr+1);

		if ( ihdr->ip_p != IP_UDP
				|| ecs(uhdr->uh_dport) != MoncmdPort
				|| sub_net_addr != ~net_mask ) {
#if INCLUDE_DHCPBOOT	
			if (DHCPState == DHCPSTATE_NOTUSED)
				return;
			if (ihdr->ip_p != IP_UDP)
				return;
			uhdr = (struct Udphdr *)(ihdr+1);
			if (uhdr->uh_dport != ecs(DhcpClientPort)) {
				return;
			}
#else
			return;
#endif
		}
	}

	/* Verify incoming IP header checksum...
	 * Refer to section 3.2 of TCP/IP Illustrated, Vol 1 for details.
	 */
	csum = 0;
	datap = (ushort *) ihdr;
	for (i=0;i<(sizeof(struct ip)/sizeof(ushort));i++,datap++)
		csum += *datap;
	csum = (csum & 0xffff) + (csum >> 16);
	if (csum != 0xffff) {
		EtherIPERRCnt++;
		if (EtherVerbose & SHOW_BADCSUM) {
			printf("IP csum error: 0x%04x != 0xffff\n",(ushort)csum);
			if (EtherVerbose & SHOW_BADCSUMV) {
				int overbose = EtherVerbose;

				EtherVerbose = SHOW_ALL;
				printPkt(ehdr,size,ETHER_INCOMING);
				EtherVerbose = overbose;
			}
		}	
		return;
	}
	
	if (ihdr->ip_p == IP_ICMP) {
		processICMP(ehdr,size);
		return;
	}
	else if (ihdr->ip_p == IP_TCP) {
		processTCP(ehdr,size);
		return;
	}
	else if (ihdr->ip_p != IP_UDP) {
		int	j;

		SendICMPUnreachable(ehdr,ICMP_UNREACHABLE_PROTOCOL);
		if (!(EtherVerbose & SHOW_INCOMING))
			return;
		for(j=0;protocols[j].pname;j++) {
			if (ihdr->ip_p == protocols[j].pnum) {
				printf("%s not supported\n",
				    protocols[j].pname);
				return;
			}
		}
		printf("<%02x> protocol unrecognized\n", ihdr->ip_p);
		return;
	}

	uhdr = (struct Udphdr *)(ihdr+1);

	/* If non-zero, verify incoming UDP packet checksum...
	 * Refer to section 11.3 of TCP/IP Illustrated, Vol 1 for details.
	 */
	if (uhdr->uh_sum) {
		int	 	len;
		struct	UdpPseudohdr	pseudohdr;

		memcpy((char *)&pseudohdr.ip_src.s_addr,(char *)&ihdr->ip_src.s_addr,4);
		memcpy((char *)&pseudohdr.ip_dst.s_addr,(char *)&ihdr->ip_dst.s_addr,4);
		pseudohdr.zero = 0;
		pseudohdr.proto = ihdr->ip_p;
		pseudohdr.ulen = uhdr->uh_ulen;

		csum = 0;
		datap = (ushort *) &pseudohdr;
		for (i=0;i<(sizeof(struct UdpPseudohdr)/sizeof(ushort));i++)
			csum += *datap++;

		/* If length is odd, pad and add one. */
		len = ecs(uhdr->uh_ulen);
		if (len & 1) {
			uchar	*ucp;
			ucp = (uchar *)uhdr;
			ucp[len] = 0;
			len++;
		}
		len >>= 1;

		datap = (ushort *) uhdr;
		for (i=0;i<len;i++)
			csum += *datap++;
		csum = (csum & 0xffff) + (csum >> 16);
		if (csum != 0xffff) {
			EtherUDPERRCnt++;
			if (EtherVerbose & SHOW_BADCSUM) {
				printf("UDP csum error: 0x%04x != 0xffff\n",(ushort)csum);
				if (EtherVerbose & SHOW_BADCSUMV) {
					int overbose = EtherVerbose;

					EtherVerbose = SHOW_ALL;
					printPkt(ehdr,size,ETHER_INCOMING);
					printf("pseudohdr.ip_src: 0x%08lx\n",
						pseudohdr.ip_src.s_addr);
					printf("pseudohdr.ip_dst: 0x%08lx\n",
						pseudohdr.ip_dst.s_addr);
					printf("pseudohdr.zero: 0x%02x\n", pseudohdr.zero);
					printf("pseudohdr.proto: 0x%02x\n", pseudohdr.proto);
					printf("pseudohdr.ulen: 0x%04x\n", pseudohdr.ulen);
					EtherVerbose = overbose;
				}
			}	
			return;
		}
	}
	udpport = ecs(uhdr->uh_dport);

	if (udpport == MoncmdPort)
		processMONCMD(ehdr,size);
#if INCLUDE_DHCPBOOT
	else if (udpport == DhcpClientPort)
		processDHCP(ehdr,size);
#endif
#if INCLUDE_TFTP
	else if ((udpport == TftpPort) || (udpport == TftpSrcPort))
		processTFTP(ehdr,size);
#endif
#if INCLUDE_GDB
	else if (udpport == GdbPort)
		processGDB(ehdr,size);
#endif
	else {
		if (EtherVerbose & SHOW_INCOMING) {
			uchar *cp;
			cp = (uchar *)&(ihdr->ip_src);
			printf("  Unexpected IP pkt from %d.%d.%d.%d ",
			    cp[0],cp[1],cp[2],cp[3]);
			printf("(sport=0x%x,dport=0x%x)\n",
			    ecs(uhdr->uh_sport),ecs(uhdr->uh_dport));
		}
		SendICMPUnreachable(ehdr,ICMP_UNREACHABLE_PORT);
	}
}

#define MONCMD_SRCIP_VARNAME	"MONCMD_SRCIP"
#define MONCMD_SRCPORT_VARNAME	"MONCMD_SRCPORT"

/* processMONCMD():
 * This function is called as a result of receiving a packet on port 
 * 777.  It will process the incoming packet as if it was an ASCII
 * command destined for MicroMonitor's CLI.
 *
 * As of Aug 16, 2004, support for NETCAT is also in this function.
 * Differentiating between netcat and moncmd is done by looking
 * for the terminating newline character which is only present with
 * netcat.  For example:
 * The following host command line:  <netcat -u 135.222.140.72 777>
 * puts the netcat user into an interactive mode with uMon so
 * normal uMon commands can be issued through netcat (until interrupted).
 * 
 * As of Aug 5, 2005, another change has been made to uMon's MONCMD
 * server as a result of a bug reported by Leon Pollack.  The change
 * breaks up the processing of the incoming moncmd request into two
 * parts processMONCMD() and executeMONCMD() (refer to CVS log for
 * more details):
 * 
 * 1. processMONCMD():
 *    Retrieve the incoming message from the ethernet interface and
 *    store the message in a local buffer to be processed later.
 * 2. executeMONCMD():
 *    After the ethernet packet has been properly dequeued, then
 *    process the remote command appropriately.
 */

void
processMONCMD(struct ether_header *ehdr,ushort size)
{
	int		verbose = 0;
	struct	ip *ihdr;
	struct	Udphdr *uhdr;
	char	*moncmd;
	uchar	*src;

	if (size > sizeof(IPMonCmdHdrBuf))
		return;

	ihdr = (struct ip *)(ehdr + 1);
	uhdr = (struct Udphdr *)(ihdr + 1);
	moncmd = (char *)(uhdr + 1);
	memcpy((char *)IPMonCmdHdrBuf,(char *)ehdr,size);
	IPMonCmdHdr = (struct ether_header *)&IPMonCmdHdrBuf;
	src = (uchar *)&ihdr->ip_src;

	/* Keep track of who sent the most recent moncmd request:
	 */
	shell_sprintf(MONCMD_SRCIP_VARNAME,"%d.%d.%d.%d",
		src[0],src[1],src[2],src[3]);
	shell_sprintf(MONCMD_SRCPORT_VARNAME,"%d",ecs(uhdr->uh_sport));

	if (!MFLAGS_NOMONCMDPRN()) {
		printf("MONCMD (from %s): ",getenv(MONCMD_SRCIP_VARNAME));
		verbose = 1;
	}

	if (strlen(moncmd) >= (sizeof(IPMonCmdLine) - 2)) {
		printf("MONCMD (from %s): too long\n",getenv(MONCMD_SRCIP_VARNAME));
		return;
	}

	strcpy(IPMonCmdLine+1,moncmd);
	IPMonCmdLine[0] = '+';
	IPMonCmdVerbose = verbose;
}

void
executeMONCMD(void)
{
	char	*ncnl;			/* netcat newline */
	char	*moncmd;

	/* Clear the initial '+' character so that this function is
	 * never executed multiple times because of calls to
	 * polletherdev() during the MONCMD transaction.
	 */
	IPMonCmdLine[0] = 0;

	/* If the first character of the incoming command is an '@', then
	 * the response is not sent back to the client...
	 */
	moncmd = IPMonCmdLine + 1;
	if (*moncmd == '@') {
		IPMonCmdActive = 0;
		moncmd++;
	}
	else 
		IPMonCmdActive = 1;

	/* Added to support netcat...
	 */
	ncnl = strchr(moncmd,0x0a);
	if (ncnl)
		*ncnl = 0;

	docommand(moncmd,IPMonCmdVerbose);

	if (ncnl)
		writeprompt();
	
	if (IPMonCmdActive) {
		SendIPMonChar(0,1);
		IPMonCmdActive = 0;
	}

	stkchk("Post-sendIPmonchar");
	if (!ncnl)
		writeprompt();

	IPMonCmdLine[0] = 0;
}

int
SendIPMonChar(uchar c, int done)
{
	static	int idx;
	static	char linebuf[128];
	int len, hdrlen;
	struct ether_header *te;
	struct ip *ti, *ri;
	struct Udphdr *tu, *ru;

	if (!IPMonCmdActive)
		return(0);

	/* Check for overflow and if detected, reset the buffer pointer...
	 */
	if (idx >= sizeof(linebuf))
		idx = 0;

	linebuf[idx++] = c;
	if ((!done) && (c != '\n'))
		return(0);

	/* Once inside the meat of this function, clear the IPMonCmdActive flag
	 * to avoid recursion if an error message is to be printed by some 
	 * called by this function...
	 */
	IPMonCmdActive = 0;

	hdrlen = sizeof(struct ip) + sizeof(struct Udphdr);
	len = idx + hdrlen ;

	te = EtherCopy(IPMonCmdHdr);

	ti = (struct ip *) (te + 1);
	ri = (struct ip *) (IPMonCmdHdr + 1);
	ti->ip_vhl = ri->ip_vhl;
	ti->ip_tos = ri->ip_tos;
	ti->ip_len = ecs(len);
	ti->ip_id = ipId();
	ti->ip_off = ri->ip_off;
	ti->ip_ttl = UDP_TTL;
	ti->ip_p = IP_UDP;
	memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr,
		sizeof(struct in_addr));
	memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
		sizeof(struct in_addr));

	tu = (struct Udphdr *) (ti + 1);
	ru = (struct Udphdr *) (ri + 1);
	tu->uh_sport = ru->uh_dport;
	tu->uh_dport = ru->uh_sport;
	tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + idx));
	memcpy((char *)(tu+1),linebuf,idx);

	ipChksum(ti);		/* Compute checksum of ip hdr */
	udpChksum(ti);		/* Compute UDP checksum */

	sendBuffer(MONRESPSIZE);
	idx = 0;
	IPMonCmdActive = 1;
	return(1);
}

/*
 *  printPkt(ehdr,len)
 */
void
printPkt(struct ether_header *ehdr, int len, int direction)
{
	struct	arphdr *arpp;
	char	*dir;

	/* Filter based on verbosity level... */
	switch(direction) {
		case ETHER_INCOMING:
			if (!(EtherVerbose & SHOW_INCOMING))
				return;
			dir = "INCOMING";
			break;
		case ETHER_OUTGOING:
			if (!(EtherVerbose & SHOW_OUTGOING))
				return;
			dir = "OUTGOING";
			break;
		default:
			printf("printPkt() direction error\n");
			dir = "???";
			break;
	}

	/* If direction is incoming and SHOW_BROADCAST is not set, then */
	/* return here if the destination host is broadcast. */
	if ((direction == ETHER_INCOMING) &&
	    (!(EtherVerbose & SHOW_BROADCAST)) &&
	    (!memcmp(ehdr->ether_dhost.ether_addr_octet,BroadcastAddr,6)))
		return;

	printf("\n%s PACKET (%d bytes):\n",dir,len);
	if (EtherVerbose & SHOW_HEX)
		printMem((char *)ehdr,len,EtherVerbose & SHOW_ASCII);
	printf("  Destination Host = %02x:%02x:%02x:%02x:%02x:%02x\n",
	    ehdr->ether_dhost.ether_addr_octet[0],
	    ehdr->ether_dhost.ether_addr_octet[1],
	    ehdr->ether_dhost.ether_addr_octet[2],
	    ehdr->ether_dhost.ether_addr_octet[3],
	    ehdr->ether_dhost.ether_addr_octet[4],
	    ehdr->ether_dhost.ether_addr_octet[5]);

	printf("  Source Host =      %02x:%02x:%02x:%02x:%02x:%02x\n",
	    ehdr->ether_shost.ether_addr_octet[0],
	    ehdr->ether_shost.ether_addr_octet[1],
	    ehdr->ether_shost.ether_addr_octet[2],
	    ehdr->ether_shost.ether_addr_octet[3],
	    ehdr->ether_shost.ether_addr_octet[4],
	    ehdr->ether_shost.ether_addr_octet[5]);


	switch (ehdr->ether_type) {
	case ecs(ETHERTYPE_IP):
		printIp((struct ip *)(ehdr+1));
		break;
	case ecs(ETHERTYPE_PUP):
		printf("  Type = PUP\n");
		break;
	case ecs(ETHERTYPE_ARP):
		arpp = (struct arphdr *)(ehdr+1);
		printf("  Type = ARP %s from IP %d.%d.%d.%d)\n",
		    arpp->operation == ecs(ARP_RESPONSE) ? "RESPONSE" : "REQUEST",
		    arpp->senderia[0],arpp->senderia[1],
		    arpp->senderia[2],arpp->senderia[3]);
		break;
	case ecs(ETHERTYPE_REVARP):
		printf("  Type = REVARP\n");
		break;
	default:
		printf("  Type = 0x%04x ???\n", ehdr->ether_type);
		break;
	}
}

void
AppPrintPkt(char *buf, int size, int incoming)
{
	int	overbose, mode;

	overbose = EtherVerbose;
	if (incoming)
		mode = ETHER_INCOMING;
	else
		mode = ETHER_OUTGOING;
	printPkt((struct ether_header *)buf,size,mode);
	EtherVerbose = overbose;
}

/*
 *  printIp(p)
 */
int
printIp(struct ip *ihdr)
{
	int	i, ipsize;
	struct ip *icpy;
	char	buf[16], buf1[16], *payload;
	ulong	tmp[sizeof(struct ip)/2];

	ipsize = ((ihdr->ip_vhl & 0x0f) << 2);

	/* Copy data to aligned memory space so printf doesn't crash. */
	memcpy((char *)tmp,(char *)ihdr,sizeof(struct ip));
	icpy = (struct ip *)tmp;
	printf("  IP:  vhl/tos  len    id     offset  ttl/proto  csum\n");
	printf("       x%02x%02x    x%04x  x%04x  x%04x   x%02x%02x      x%04x\n",
	    icpy->ip_vhl,icpy->ip_tos, ecs(icpy->ip_len),
		ecs(icpy->ip_id), ecs(icpy->ip_off),
		icpy->ip_ttl, icpy->ip_p, ecs(icpy->ip_sum));

	printf("       src/dest: %s / %s\n",
	    IpToString(icpy->ip_src.s_addr,buf),
	    IpToString(icpy->ip_dst.s_addr,buf1));

	/* Check for options...
	 */
	if (ipsize > sizeof(struct ip)) {
		printf("       IP Options: x");
		for(i=sizeof(struct ip);i<ipsize;i++)
			printf("%02x",((char *)ihdr)[i]);
		printf("\n");
	}

	payload = (char *)ihdr;
	payload += ipsize;
	if (icpy->ip_p == IP_UDP) {
		printUdp((struct Udphdr *)payload);
		return(0);
	}
	else if (icpy->ip_p == IP_IGMP) {
		printIgmp((struct Igmphdr *)payload);
		return(0);

⌨️ 快捷键说明

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