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

📄 dhcpboot.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 3 页
字号:
			*dhcpOptions++ = 1;
			*dhcpOptions++ = DHCPDISCOVER;
			dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions);
			*dhcpOptions++ = 0xff;
	
			/* Calculate ip and udp lengths after all DHCP options are loaded
			 * so that the size is easily computed based on the value of the
			 * dhcpOptions pointer.  Apparently, the minimum size of the
			 * options space is 64 bytes, we determined this simply because
			 * the DHCP	server we are using complains if the size is smaller.
			 * Also, NULL out the space that is added to get a minimum option
			 * size of 64 bytes, 
			 */
			optlen = dhcpOptions - dhcpOptionsBase;
			if (optlen < 64) {
				memset(dhcpOptions,0,64-optlen);
				optlen = 64;
			}
			uh_ulen = sizeof(struct Udphdr)+sizeof(struct dhcphdr)+optlen;
			tu->uh_ulen = ecs(uh_ulen);
		}
	}
	ti->ip_len = ecs((sizeof(struct ip) + uh_ulen));

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

	if (bootp) {
		DHCPState = BOOTPSTATE_REQUEST;
		sendBuffer(BOOTPSIZE);
	}
	else {
		DHCPState = DHCPSTATE_SELECT;
		sendBuffer(DHCPSIZE+optlen);
	}
	if (EtherVerbose & SHOW_DHCP)
		printf("  %s startup (%d elapsed secs)\n",
			bootp ? "BOOTP" : "DHCP",seconds);
	return(0);
}

/* SendDHCPRequest()
 *	The DHCP request is broadcast back with the "server identifier" option
 *	set to indicate which server has been selected (in case more than one
 *	has offered).
 */
int
SendDHCPRequest(struct dhcphdr *dhdr)
{
	uchar	*op;
	struct	dhcphdr *dhcpdata;
	struct	ether_header *te;
	struct	ip *ti;
	struct	Udphdr *tu;
	int		optlen;
	uchar	*dhcpOptions, *dhcpOptionsBase;
	ushort	uh_ulen;
	ulong	cookie;

	if (EtherVerbose & SHOW_DHCP)
		printf("  DHCP request\n");

	te = (struct ether_header *) getXmitBuffer();
	memcpy((char *)&te->ether_shost,BinEnetAddr,6);
	memcpy((char *)&te->ether_dhost,BroadcastAddr,6);
	te->ether_type = ecs(ETHERTYPE_IP);

	ti = (struct ip *) (te + 1);
	ti->ip_vhl = IP_HDR_VER_LEN;
	ti->ip_tos = 0;
	ti->ip_id = 0;
	ti->ip_off = ecs(0x4000);	/* No fragmentation allowed */
	ti->ip_ttl = UDP_TTL;
	ti->ip_p = IP_UDP;
	memset((char *)&ti->ip_src.s_addr,0,4);
	memset((char *)&ti->ip_dst.s_addr,0xff,4);

	tu = (struct Udphdr *) (ti + 1);
	tu->uh_sport = ecs(DhcpClientPort);
	tu->uh_dport = ecs(DhcpServerPort);

	dhcpdata = (struct dhcphdr *)(tu+1);
	dhcpdata->op = DHCPBOOTP_REQUEST;
	dhcpdata->htype = 1;
	dhcpdata->hlen = 6;
	dhcpdata->hops = 0;
	dhcpdata->seconds = ecs(DHCPElapsedSecs);
	/* Use the same xid for the request as was used for the discover...
	 * (rfc2131 section 4.4.1)
	 */
	memcpy((char *)&dhcpdata->transaction_id,(char *)&dhdr->transaction_id,4);

	dhcpdata->flags = dhdr->flags;
	memset((char *)&dhcpdata->client_ip,0,4);
	memcpy((char *)&dhcpdata->your_ip,(char *)&dhdr->your_ip,4);
	memset((char *)&dhcpdata->server_ip,0,4);
	memset((char *)&dhcpdata->router_ip,0,4);
	cookie = ecl(STANDARD_MAGIC_COOKIE);
	memcpy((char *)&dhcpdata->magic_cookie,(char *)&cookie,4);
	memcpy(dhcpdata->client_macaddr,BinEnetAddr,6);

	dhcpOptionsBase = (uchar *)(dhcpdata+1);
	dhcpOptions = dhcpOptionsBase;
	*dhcpOptions++ = DHCPOPT_MESSAGETYPE;
	*dhcpOptions++ = 1;
	*dhcpOptions++ = DHCPREQUEST;

	*dhcpOptions++ = DHCPOPT_SERVERID;		/* Server id ID */
	*dhcpOptions++ = 4;
	op = DhcpGetOption(DHCPOPT_SERVERID,(char *)(dhdr+1));
	if (op)
		memcpy(dhcpOptions,op+2,4);
	else
		memset(dhcpOptions,0,4);
	dhcpOptions+=4;

	*dhcpOptions++ = DHCPOPT_REQUESTEDIP;		/* Requested IP */
	*dhcpOptions++ = 4;
	memcpy(dhcpOptions,(char *)&dhdr->your_ip,4);
	dhcpOptions += 4;
	dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions);
	*dhcpOptions++ = 0xff;

	/* See note in SendDHCPDiscover() regarding the computation of the
	 * ip and udp lengths.
	 */
	optlen = dhcpOptions - dhcpOptionsBase;
	if (optlen < 64)
		optlen = 64;
	uh_ulen = sizeof(struct Udphdr) + sizeof(struct dhcphdr) + optlen;
	tu->uh_ulen = ecs(uh_ulen);
	ti->ip_len = ecs((sizeof(struct ip) + uh_ulen));

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

	DHCPState = DHCPSTATE_REQUEST;
	sendBuffer(DHCPSIZE+optlen);
	return(0);
}

/* randomDhcpStartupDelay():
 *	Randomize the startup for DHCP/BOOTP (see RFC2131 Sec 4.4.1)...
 *	Return a value between 1 and 10 based on the last 4 bits of the 
 *	board's MAC address.
 *	The presence of the DHCPSTARTUPDELAY shell variable overrides
 *	this random value.
 */
int
randomDhcpStartupDelay()
{
	char *env;
	int	randomsec;

	env = getenv("DHCPSTARTUPDELAY");
	if (env) {
		randomsec = (int)strtol(env,0,0);
	}
	else {
		randomsec = (BinEnetAddr[5] & 0xf);
		if (randomsec > 10)
			randomsec -= 7;
		else if (randomsec == 0)
			randomsec = 10;
	}
	return(randomsec);
}

/* dhcpStateCheck():
 *	Called by pollethernet() to monitor the progress of DHCPState.
 *	The retry rate is "almost" what is specified in the RFC...
 *	Refer to the RetransmitDelay() function for details.
 *
 *	Regarding timing...
 *	The DHCP startup may be running without an accurate measure of elapsed
 *	time.  The value of LoopsPerMillisecond is used as an approximation of
 *	the number of times this function must be called for one second to 
 *	pass (dependent on network traffic, etc...).  RetransmitDelay() is
 *	called to retrieve the number of seconds that must elapse prior to 
 *	retransmitting the last DHCP message.  The static variables in this
 *	function are used to keep track of that timeout.
 */
void
dhcpStateCheck(void)
{
	int delaysecs;

	/* If the DHCP command has been issued, it is assumed that the script
	 * is handling retries...
	 */
	if (DHCPCommandIssued)
		return;

	/* Return, restart or fall through; depending on DHCPState... */
	switch(DHCPState) {
		case DHCPSTATE_NOTUSED:
		case BOOTPSTATE_COMPLETE:
		case DHCPSTATE_BOUND:
			return;
		case DHCPSTATE_RESTART:
			DHCPStartup(0);
			return;
		case BOOTPSTATE_RESTART:
			BOOTPStartup(0);
			return;
		case DHCPSTATE_INITIALIZE:
		case BOOTPSTATE_INITIALIZE:
			delaysecs = randomDhcpStartupDelay();
			startElapsedTimer(&dhcpTmr,delaysecs * 1000);
			if (EtherVerbose & SHOW_DHCP)
				printf("\nDHCP/BOOTP %d sec startup delay...\n",delaysecs);
			if (DHCPState & BOOTP_MODE)
				DHCPState = BOOTPSTATE_INITDELAY;
			else
				DHCPState = DHCPSTATE_INITDELAY;
			return;
		case DHCPSTATE_INITDELAY:
		case BOOTPSTATE_INITDELAY:
			if (msecElapsed(&dhcpTmr) || (gotachar())) {
				DHCPElapsedSecs = 0;
				startElapsedTimer(&dhcpTmr,
					RetransmitDelay(DELAY_INIT_DHCP)*1000);
				if (DHCPState & BOOTP_MODE)
					BOOTPStartup(0);
				else
					DHCPStartup(0);
			}
			return;
		default:
			break;
	}

	if (msecElapsed(&dhcpTmr)) {
		int lastdelay;
		
		lastdelay = RetransmitDelay(DELAY_RETURN);
		delaysecs = RetransmitDelay(DELAY_INCREMENT);
		
		if (delaysecs != RETRANSMISSION_TIMEOUT) {
			DHCPElapsedSecs += delaysecs;
			startElapsedTimer(&dhcpTmr,delaysecs*1000);

			if (DHCPState & BOOTP_MODE)
				BOOTPStartup(DHCPElapsedSecs);
			else
				DHCPStartup(DHCPElapsedSecs);
			if (EtherVerbose & SHOW_DHCP)
				printf("  DHCP/BOOTP retry (%d secs)\n",lastdelay);
		}
		else {
			if (EtherVerbose & SHOW_DHCP)
				printf("  DHCP/BOOTP giving up\n");
		}
	}
}

/* xidCheck():
 *	Common function used for DHCP and BOOTP to verify incoming transaction
 *	id...
 */
int
xidCheck(char *id,int bootp)
{
	if (memcmp(id,(char *)&DHCPTransactionId,4)) {
		if (EtherVerbose & SHOW_DHCP) {
			printf("%s ignored: unexpected transaction id.\n",
				bootp ? "BOOTP":"DHCP");
		}
		return(-1);
	}
	return(0);
}

int
loadBootFile(int bootp)
{
#if INCLUDE_TFTP
	char	bfile[TFSNAMESIZE+TFSINFOSIZE+32];
	char	*flags, *info, *icomma, *fcomma, *argv[2];
	char	*bootfile, *tftpsrvr;
	int		err;
	ulong	addr;

	/* If both bootfile and server-ip are specified, then boot it.
	 * The name of the file must contain information that tells the monitor
	 * what type of file it is, so the first 'comma' extension is used as
	 * the flag field (if it is a valid flag set) and the second 'comma'
	 * extension is used as the info field.
	 */
	bootfile = getenv("BOOTFILE");
	tftpsrvr = getenv("BOOTSRVR");

	if (bootfile && tftpsrvr) {
		int	tftpworked;

		addr = getAppRamStart();
		info = "";
		flags = "e";
		strncpy(bfile,bootfile,sizeof(bfile));
		fcomma = strchr(bfile,',');
		if (fcomma) {
			icomma = strchr(fcomma+1,',');
			if (icomma) {
				*icomma = 0;
				info = icomma+1;
			}
			*fcomma = 0;
			if (tfsctrl(TFS_FATOB,(long)(fcomma+1),0) != 0)
				flags = fcomma+1;
		}

		/* Since we are about to transition to TFTP, match TFTP's
		 * verbosity to the verbosity currently set for DHCP...
		 */
		if (EtherVerbose & SHOW_DHCP)
			EtherVerbose |= SHOW_TFTP_STATE;

		/* If the TFTP transfer succeeds, attempt to run the boot file;
		 * if the TFTP transfer fails, then re-initialize the tftp state
		 * and set the DHCP state such that dhcpStateCheck() will
		 * cause the handshake to start over again...
		 */
		tftpworked = tftpGet(addr,tftpsrvr,"octet",bfile,bfile,flags,info);
		if (tftpworked) {
			//stone debug tftp
			docommand("call 0xa0300000",0);
			/*
			EtherVerbose = 0;
			argv[0] = bfile;
			argv[1] = 0;
			err = tfsrun(argv,0);
			if (err != TFS_OKAY) 
				printf("DHCP-invoked tfsrun(%s) failed: %s\n",
					bfile,tfserrmsg(err));
					*/
		}
		else {
			tftpInit();
			RetransmitDelay(DELAY_INIT_TFTP);
			EtherVerbose &= ~SHOW_TFTP_STATE;
			if (bootp)
				DHCPState = BOOTPSTATE_RESTART;
			else
				DHCPState = DHCPSTATE_RESTART;
		}
	}
	else
		EtherVerbose &= ~(SHOW_DHCP|DHCP_VERBOSE);
#endif
	return(0);
}

/* processBOOTP():
 *	A subset of processDHCP().
 *	We get here from processDHCP, because it detects that the current
 *	value of DHCPState is BOOTPSTATE_REQUEST.
 */
int
processBOOTP(ehdr,size)
struct ether_header *ehdr;
ushort size;
{
	struct	ip *ihdr;
	struct	Udphdr *uhdr;
	struct	bootphdr *bhdr;
	ulong	ip, temp_ip, cookie;
	uchar	buf[16], *op;

	if (EtherVerbose & SHOW_HEX)
		printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII);

	ihdr = (struct ip *)(ehdr + 1);
	uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr));
	bhdr = (struct bootphdr *)(uhdr+1);

	/* Verify incoming transaction id matches the previous outgoing value: */
	if (xidCheck((char *)&bhdr->transaction_id,1) < 0)
		return(-1);

	/* If bootfile is nonzero, store it into BOOTFILE shell var: */
	if (bhdr->bootfile[0])
		DhcpSetEnv("BOOTFILE",bhdr->bootfile);

	/* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */
	memcpy((char *)&temp_ip,(char *)&bhdr->server_ip,4);
	if (temp_ip)
		DhcpSetEnv("BOOTSRVR",IpToString(temp_ip,buf));

	/* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */
	memcpy((char *)&temp_ip,(char *)&bhdr->router_ip,4);
	if (temp_ip)
		DhcpSetEnv("RLYAGNT",IpToString(temp_ip,buf));

	/* Assign IP address loaded in "your_ip" to the IPADD shell var: */
	memcpy(BinIpAddr,(char *)&bhdr->your_ip,4);
	memcpy((char *)&temp_ip,(char *)&bhdr->your_ip,4);
	DhcpSetEnv("IPADD",IpToString(temp_ip,buf));

	/* If STANDARD_MAGIC_COOKIE exists, then process options... */
	memcpy((char *)&cookie,(char *)bhdr->vsa,4);
	if (cookie == ecl(STANDARD_MAGIC_COOKIE)) {
		/* Assign subnet mask option to NETMASK shell var (if found): */
		op = DhcpGetOption(DHCPOPT_SUBNETMASK,&bhdr->vsa[4]);
		if (op) {
			memcpy((char *)&ip,op+2,4);
			DhcpSetEnv("NETMASK",IpToString(ip,buf));
		}
		/* Assign first router option to GIPADD shell var (if found): */
		/* (the router option can have multiple entries, and they are */
		/* supposed to be in order of preference, so use the first one) */
		op = DhcpGetOption(DHCPOPT_ROUTER,&bhdr->vsa[4]);
		if (op) {
			memcpy((char *)&ip,op+2,4);
			DhcpSetEnv("GIPADD",IpToString(ip,buf));
		}
	}

	DhcpBootpDone(1,(struct dhcphdr *)bhdr,
		size - ((int)((int)&bhdr->vsa - (int)ehdr)));

⌨️ 快捷键说明

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