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

📄 ethernet.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 3 页
字号:
	}
	for(i=0;protocols[i].pname;i++) {
		if (icpy->ip_p == protocols[i].pnum) {
			printf("  Protocol: %s\n",protocols[i].pname);
			return(0);
		}
	}
	printf("  <%02x>: unknown IP protocol\n", icpy->ip_p);
	return (1);
}

/*
 *  printUdp(p)
 */
int
printUdp(struct Udphdr *p)
{
	ushort	dport, sport;

	dport = ecs(p->uh_dport);
	sport = ecs(p->uh_sport);

#if INCLUDE_DHCPBOOT
	if ((dport == DhcpServerPort) || (dport == DhcpClientPort)) {
		printDhcp(p);
		return(0);
	}
#endif
	printf("  UDP: sport dport ulen sum\n");
	printf("       %4d  %4d  %4d %4d\n",
	    sport, dport, ecs(p->uh_ulen),ecs(p->uh_sum));
	return(0);
}

/*
 *  printIgmp(p)
 */
int
printIgmp(struct Igmphdr *p)
{
	uchar	buf[16];

	printf(" IGMP: type mrt  csum  group\n");
	printf("       x%02x  x%02x  x%04x %s\n",
	    p->type, p->mrt, p->csum, IpToString(p->group,buf));
	return(0);
}

int
IpToBin(char *ascii,uchar *binary)
{
	int	i, digit;
	char	*acpy;

	acpy = ascii;
	for(i=0;i<4;i++) {
		digit = (int)strtol(acpy,&acpy,10);
		if (((i != 3) && (*acpy++ != '.')) ||
			((i == 3) && (*acpy != 0)) ||
			(digit < 0) || (digit > 255)) {
			printf("Misformed IP addr: %s\n",ascii);
			return(-1);
		}
		binary[i] = (uchar)digit;
	}
	return(0);
}

/* IpToString():
 *	Incoming ascii pointer is assumed to be pointing to at least 16
 *	characters of available space.  Conversion from long to ascii is done
 *	and string is terminated with NULL.  The ascii pointer is returned.
 */
char *
IpToString(ulong ipadd,char *ascii)
{
	uchar	*cp;

	cp = (uchar *)&ipadd;
	sprintf(ascii,"%d.%d.%d.%d",
	    (int)cp[0],(int)cp[1],(int)cp[2],(int)cp[3]);
	return(ascii);
}

char *
EtherToString(uchar *etheradd,char *ascii)
{
	sprintf(ascii,"%02x:%02x:%02x:%02x:%02x:%02x",(int)etheradd[0],
	    (int)etheradd[1],(int)etheradd[2],(int)etheradd[3],
	    (int)etheradd[4],(int)etheradd[5]);
	return(ascii);
}

/* ipChksum():
 *	Compute the checksum of the incoming IP header.  The size of
 *	the header is variable because of the possibility of there 
 *	being options; hence, the size of the header is taken from
 *	the ip_vhl field instead of assuming sizeof(struct ip).
 *	The incoming pointer to an IP header is directly populated with
 *	the result.
 */
void
ipChksum(struct ip *ihdr)
{
	register int	i, stot;
	register ushort	*sp;
	register long	csum;

	csum = 0;
	ihdr->ip_sum = 0;
	stot = (((ihdr->ip_vhl & 0x0f) << 2) / (int)sizeof(ushort));
	sp = (ushort *) ihdr;
	for (i=0;i<stot;i++,sp++) {
		csum += *sp;
		if (csum & 0x80000000)
			csum = (csum & 0xffff) + (csum >> 16);
	}
	while(csum >> 16)
		csum = (csum & 0xffff) + (csum >> 16);
	ihdr->ip_sum = ~csum;
}

/*	udpChksum():
 *	Compute the checksum of the UDP packet.
 *	The incoming pointer is to an ip header, the udp header after that ip
 *	header is directly populated with the result.
 *	Got part of this code out of Steven's TCP/IP Illustrated Volume 2.
 */
void
udpChksum(struct ip *ihdr)
{
	register int	i;
	register ushort	*datap;
	register long	sum;
	int	 	len;
	struct	Udphdr *uhdr;
	struct	UdpPseudohdr	pseudohdr;

	uhdr = (struct Udphdr *)(ihdr+1);
	uhdr->uh_sum = 0;

	/* Note that optionally, the checksum can be forced to zero here,
	 * so a return could replace the remaining code.
	 * That would be kinda dangerous, but it is an option according to
	 * the spec.
	 */

	/* Start with the checksum of the pseudo header:
	 * Note that we have to use memcpy because we don't know if the incoming
	 * stream is aligned properly.
	 */
	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;

	/* Get checksum of pseudo header: */
	sum = 0;
	datap = (ushort *) &pseudohdr;
	for (i=0;i<(sizeof(struct UdpPseudohdr)/sizeof(ushort));i++) {
		sum += *datap++;
		if (sum & 0x80000000)
			sum = (sum & 0xffff) + (sum >> 16);
	}

	len = ecs(uhdr->uh_ulen);
	datap = (ushort *) uhdr;

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

	while(len) {
		sum += *datap++;
		if (sum & 0x80000000)
			sum = (sum & 0xffff) + (sum >> 16);
		len -= 2;
	}

	while(sum >> 16)
		sum = (sum & 0xffff) + (sum >> 16);

	uhdr->uh_sum = ~sum;
}

struct	ether_header *
EtherCopy(struct ether_header *re)
{
	struct	ether_header *te;

	te = (struct ether_header *) getXmitBuffer();
	memcpy((char *)&(te->ether_shost),(char *)BinEnetAddr,6);
	memcpy((char *)&(te->ether_dhost),(char *)&(re->ether_shost),6);
	te->ether_type = re->ether_type;
	return(te);
}

ushort
ipId(void)
{
	return(++UniqueIpId);
}


/* getTuneup():
 *	The DHCP, TFTP and ARP timeout & retry mechanism can be tuned based on
 *	the content of the shell variables DHCPRETRYTUNE, TFTPRETRYTUNE and
 *	ARPRETRYTUNE respectively.
 *	Return 0 if variable is not found, -1 if there is a detected error in
 *	the content of the shell variable; else 1 indicating that the three
 *	parameters have been loaded from the content of the shell variable.
 */
int
getTuneup(char *varname,int *rexmitdelay,int *giveupcount,int *rexmitdelaymax)
{
	char *vp, *colon1, *colon2;
	
	vp = getenv(varname);
	if (!vp)
		return(0);
	colon1 = strchr(vp,':');
	if (colon1) {
		colon2 = strchr(colon1+1,':');
		if (colon2) {
			*rexmitdelay = (int)strtol(vp,0,0);
			*giveupcount = (int)strtol(colon1+1,0,0);
			*rexmitdelaymax = (int)strtol(colon2+1,0,0);
			return(1);
		}
	}
	printf("Syntax error in %s\n",varname);
	return(-1);
}

/* RetransmitDelay():
 *	This function provides a common point for retransmission delay
 *	calculation.  It is an implementation "similar" to the recommendation
 *	made in the RFC 2131 (DHCP) section 4.1 paragraph #8...
 *
 *	The delay before the first retransmission is 4 seconds randomized by
 *	the value of a uniform random number chosen from the range -1 to +2.
 *	The delay before the next retransmission is 8 seconds randomized by
 *	the same number as previous randomization.  Each subsequent retransmission
 *	delay is doubled up to a maximum of 66 seconds.  Once a delay of 66
 *	seconds is reached, return that value for 6 subsequent delay
 *	requests, then return RETRANSMISSION_TIMEOUT (-1) indicating that the
 *	requestor should give up.
 *
 *	The value of randomdelta will be 2, 1, 0 or -1 depending on the target's
 *	IP address.
 *
 *	The return values will be...
 *	4+randomdelta, 8+randomdelta, 16+randomdelta, etc... up to 64+randomdelta.
 *	Then after returning 64+randomdelta 6 times, return RETRANSMISSION_TIMEOUT.
 *
 *	NOTE: if DELAY_RETURN is the opcode, then RETRANSMISSION_TIMEOUT is
 *		  never returned, once the max is reached, it is always the value
 *		  returned;
 *		  if DELAY_OR_TIMEOUT_RETURN is the opcode, then once maxoutcount
 *		  reaches 6, RETRANSMISSION_TIMEOUT is returned.
 *
 *	NOTE1: this function supports the ability to modify the above-discussed
 *		   parameters.  Start with DELAY_INIT_DHCP to set up the parameters
 *		   discussed above; start with DELAY_INIT_XXXX for others.
 */
int
RetransmitDelay(int opcode)
{
	static int randomdelta;		/* Used to slightly randomize the delay.
								 * Taken from the 2 least-significant-bits
								 * of the IP address (range = -1 to 2).
								 */
	static int rexmitdelay;		/* Doubled each time DELAY_INCREMENT
								 * is called until it is greater than the
								 * value stored in rexmitdelaymax.
								 */
	static int rexmitdelaymax;	/* See rexmitdelay. */
	static int maxoutcount;		/* Number of times the returned delay has
								 * reached its max.
								 */
	static int giveupcount;		/* Once maxoutcount reaches this value, we
								 * give up and return TIMEOUT.
								 */
	int		rexmitstate;

	rexmitstate = RETRANSMISSION_ACTIVE;
	switch(opcode) {
		case DELAY_INIT_DHCP:		
			if (getTuneup("DHCPRETRYTUNE",&rexmitdelay,
				&giveupcount,&rexmitdelaymax) <= 0) {
				rexmitdelay = 4;
				giveupcount = 6;
				rexmitdelaymax = 64;
			}
			maxoutcount = 0;
			randomdelta = (int)(BinIpAddr[3] & 3) - 1;
			break;
		case DELAY_INIT_TFTP:
			if (getTuneup("TFTPRETRYTUNE",&rexmitdelay,
				&giveupcount,&rexmitdelaymax) <= 0) {
				rexmitdelay = 4;
				giveupcount = 3;
				rexmitdelaymax = 32;
			}
			maxoutcount = 0;
			randomdelta = (int)(BinIpAddr[3] & 3) - 1;
			break;
		case DELAY_INIT_ARP:
			if (getTuneup("ARPRETRYTUNE",&rexmitdelay,
				&giveupcount,&rexmitdelaymax) <= 0) {
				rexmitdelay = 1;	
				giveupcount = 0;
				rexmitdelaymax = 4;
			}
			maxoutcount = 0;
			randomdelta = 0;
			break;
		case DELAY_INCREMENT:
			if (rexmitdelay < rexmitdelaymax)
				rexmitdelay <<= 1;		/* double it. */
			else 
				maxoutcount++;

			if (maxoutcount > giveupcount)
				rexmitstate = RETRANSMISSION_TIMEOUT;
			break;
		case DELAY_OR_TIMEOUT_RETURN:
			if (maxoutcount > giveupcount)
				rexmitstate = RETRANSMISSION_TIMEOUT;
			break;
		case DELAY_RETURN:
			break;
		default:
			printf("\007TimeoutAlgorithm error 0x%x.\n",opcode);
			rexmitstate = RETRANSMISSION_TIMEOUT;
			break;
	}
	if (rexmitstate == RETRANSMISSION_TIMEOUT)
		return(RETRANSMISSION_TIMEOUT);
	else
		return(rexmitdelay+randomdelta);
}

/* monSendEnetPkt() & monRecvEnetPkt():
 * These two functions allow the monitor to provide a primitive
 * connect to the ethernet interface for an application (using
 * mon_sendenetpkt() and mon_recvenetpkt()).
 *
 * Note: These are obviously not very sophisticated; however, they
 * provide an immediate mechanism for LWIP to access the raw driver.
 * without the application even being aware of the type of ethernet
 * device.
 */
int
monSendEnetPkt(char *pkt, int pktlen)
{
	/* Copy the incoming packet into a packet that has been allocated
	 * by the monitor's packet allocator for this ethernet device:
	 */
	memcpy(getXmitBuffer(),pkt,pktlen);
	sendBuffer(pktlen);
	return(pktlen);
}

int
monRecvEnetPkt(char *pkt, int pktlen)
{
	int	pcnt, len;

	/* Prior to calling polletherdev(), this function sets up the globals
	 * AppPktPtr and AppPktLen so that if a packet is recived, and
	 * polletherdev() calls processPACKET(), the data will simply be
	 * copied to the requested buffer space instead of being processed
	 * by the monitor's packet handler (see the top of processPACKET()
	 * for the use of AppPktPtr & AppPktLen).
	 *
	 * NOTE: this assumes that the target-specific function polletherdev()
	 * will only process one packet per call.  If it can process more than
	 * one per call, then packets will be lost here.
	 */
	AppPktPtr = pkt;
	AppPktLen = pktlen;
	pcnt = polletherdev();
	if (pcnt == 0) {
		len = 0;
	}
	else {
		if (pcnt > 1)
			len = -AppPktLen;
		else
			len = AppPktLen;
	}
	AppPktPtr = 0;
	return(len);
}

/* storeMac():
 * This function can be called in system startup (after flash drivers
 * are initialized) to give the user the opportunity to program a
 * MAC address into the "etheraddr" block of flash in monitor space.
 * This is only done if that space is erased (0xff), so only on the
 * first pass will it be called.  
 * It is useful for monitors that want to exist without a monrc file,
 * but should still have a MAC address.
 * As of uMon_1.0, this function can also be called by the ether command.
 */
void
storeMac(int verbose)
{
#if INCLUDE_FLASH
	int snum, yes;
	char macascii[24], prefill[24], buf[6];

	if (etheraddr[0] != 0xff) {
		if (verbose) 
			printf("MAC store abort: etheraddr[] contains data\n");
		return;
	}

	/* If etheraddr[] is writeable (RAM), then assume that this 
	 * function is being called as part of a RAM based temporary
	 * monitor; hence, no need to do it...
	 */
	etheraddr[0] = 0;
	monDelay(100);
	if (etheraddr[0] == 0) {
		etheraddr[0] = 0xff;
		if (verbose)
			printf("MAC store abort: etheraddr[] in RAM\n");
		return;
	}	

	/* Use whatever is in config.h as the default MAC address,
	 * then allow the user to override it with getline_p()...
	 */
	strcpy(prefill,DEFAULT_ETHERADD);

	printf("\nMAC address must be configured.\n");
	printf("The system's MAC address is a 6-digit, colon-delimited string\n");
	printf("(for example: 12:34:56:78:9a:bc).  It must be unique for all\n");
	printf("ethernet controllers present on a given subnet.  MAC addresses\n");
	printf("are often allocated by a product vendor to prevent duplication,\n");
	printf("and are frequently documented on decals or other materials\n");
	printf("provided with the product.  The following prompt allows you\n");
	printf("to specify the MAC address for this device.\n");
	if (strlen(prefill) != 0)
		printf("Use backspace if the printed default needs modification...\n");
	printf("\n");

	do {
		printf("Enter MAC address (xx:xx:xx:xx:xx:xx):\n");
		if (getline_p(macascii,sizeof(macascii),0,prefill) == 0)
			return;
	} while (EtherToBin(macascii,buf) == -1);

	printf("Configuring '%s' as MAC address, ok?",macascii);
	yes =  askuser(" (y or n)");

	putchar('\n');
	if (!yes)
		return;
	
	if (addrtosector((uchar *)etheraddr,&snum,0,0) < 0)
		return;

	sprintf(buf,"%d",snum);
	sectorProtect(buf,0);
	AppFlashWrite((uchar *)etheraddr,(uchar *)macascii,strlen(macascii)+1);
	sectorProtect(buf,1);

	printf("MAC address burned in at 0x%lx\n",(long)etheraddr);
#else
	printf("Error: MAC storage requires flash driver\n");
#endif
}

#endif	/* INCLUDE_ETHERNET */

/* EtherToBin():
 *	Convert ascii MAC address string to binary.  Note that this is outside
 *	the #if INCLUDE_ETHERNET because it is used by password.c.  This correctly
 *	implies that if there is no ethernet interface, then we need a different
 *	solution for the password backdoor!.
 */
int
EtherToBin(char *ascii,uchar *binary)
{
	int	i, digit;
	char	*acpy;
	acpy = ascii;
	
	for(i=0;i<6;i++) {
		digit = (int)strtol(acpy,&acpy,16);
		if (((i != 5) && (*acpy++ != ':')) ||
			((i == 5) && (*acpy != 0)) ||
			(digit < 0) || (digit > 255)) {
			printf("Misformed ethernet addr: %s, i = %d\n",ascii,i);
			return(-1);
		}
		binary[i] = (uchar)digit;
	}
	return(0);
}

⌨️ 快捷键说明

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