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

📄 bootp.c

📁 SMSC LAN device linux Uboot code
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *	Based on LiMon - BOOTP.
 *
 *	Copyright 1994, 1995, 2000 Neil Russell.
 *	(See License)
 *	Copyright 2000 Roland Borde
 *	Copyright 2000 Paolo Scaffardi
 *	Copyright 2000-2004 Wolfgang Denk, wd@denx.de
 */

#if 0
#define DEBUG		1	/* general debug */
#define DEBUG_BOOTP_EXT 1	/* Debug received vendor fields */
#endif

#ifdef DEBUG_BOOTP_EXT
#define debug_ext(fmt,args...)	printf (fmt ,##args)
#else
#define debug_ext(fmt,args...)
#endif

#include <common.h>
#include <command.h>
#include <net.h>
#include "bootp.h"
#include "tftp.h"
#include "nfs.h"
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
#endif

#define BOOTP_VENDOR_MAGIC	0x63825363	/* RFC1048 Magic Cookie		*/

//#if (CONFIG_COMMANDS & CFG_CMD_NET)
//#define (CONFIG_COMMANDS & CFG_CMD_NET) 1
#define TIMEOUT		5		/* Seconds before trying BOOTP again	*/
#ifndef CONFIG_NET_RETRY_COUNT
# define TIMEOUT_COUNT	5		/* # of timeouts before giving up  */
#else
# define TIMEOUT_COUNT	(CONFIG_NET_RETRY_COUNT)
#endif

#define PORT_BOOTPS	67		/* BOOTP server UDP port		*/
#define PORT_BOOTPC	68		/* BOOTP client UDP port		*/

#ifndef CONFIG_DHCP_MIN_EXT_LEN		/* minimal length of extension list	*/
#define CONFIG_DHCP_MIN_EXT_LEN 64
#endif

ulong		BootpID;
int		BootpTry;
#ifdef CONFIG_BOOTP_RANDOM_DELAY
ulong		seed1, seed2;
#endif


////#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
dhcp_state_t dhcp_state = INIT;
unsigned long dhcp_leasetime = 0;
IPaddr_t NetDHCPServerIP = 0;
static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);

/* For Debug */
#if 1
static char *dhcpmsg2str(int type)
{
	switch (type) {
	case 1:	 return "DHCPDISCOVER"; break;
	case 2:	 return "DHCPOFFER";	break;
	case 3:	 return "DHCPREQUEST";	break;
	case 4:	 return "DHCPDECLINE";	break;
	case 5:	 return "DHCPACK";	break;
	case 6:	 return "DHCPNACK";	break;
	case 7:	 return "DHCPRELEASE";	break;
	default: return "UNKNOWN/INVALID MSG TYPE"; break;
	}
}
#endif

#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL  */
#endif

#endif	/* CFG_CMD_DHCP */

static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
{
	Bootp_t *bp = (Bootp_t *) pkt;
	int retval = 0;

	if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
		retval = -1;
	else if (len < sizeof (Bootp_t) - OPT_SIZE)
		retval = -2;
	else if (bp->bp_op != OP_BOOTREQUEST &&
	    bp->bp_op != OP_BOOTREPLY &&
	    bp->bp_op != DHCP_OFFER &&
	    bp->bp_op != DHCP_ACK &&
	    bp->bp_op != DHCP_NAK ) {
		retval = -3;
	}
	else if (bp->bp_htype != HWT_ETHER)
		retval = -4;
	else if (bp->bp_hlen != HWL_ETHER)
		retval = -5;
	else if (NetReadLong((ulong*)&bp->bp_id) != BootpID) {
		retval = -6;
	}

	debug ("Filtering pkt = %d\n", retval);

	return retval;
}

/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
static void BootpCopyNetParams(Bootp_t *bp)
{
	IPaddr_t tmp_ip;

	NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
	NetCopyIP(&tmp_ip, &bp->bp_siaddr);
	if (tmp_ip != 0)
		NetCopyIP(&NetServerIP, &bp->bp_siaddr);
	memcpy (NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);
	if (strlen(bp->bp_file) > 0)
		copy_filename (BootFile, bp->bp_file, sizeof(BootFile));

	debug ("Bootfile: %s\n", BootFile);

	/* Propagate to environment:
	 * don't delete exising entry when BOOTP / DHCP reply does
	 * not contain a new value
	 */
	if (*BootFile) {
		setenv ("bootfile", BootFile);
	}
}

static int truncate_sz (const char *name, int maxlen, int curlen)
{
	if (curlen >= maxlen) {
		printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
			name, curlen, maxlen);
		curlen = maxlen - 1;
	}
	return (curlen);
}

//#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)

static void BootpVendorFieldProcess (u8 * ext)
{
	int size = *(ext + 1);

	debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
		   *(ext + 1));

	NetBootFileSize = 0;

	switch (*ext) {
		/* Fixed length fields */
	case 1:			/* Subnet mask                                  */
		if (NetOurSubnetMask == 0)
			NetCopyIP (&NetOurSubnetMask, (IPaddr_t *) (ext + 2));
		break;
	case 2:			/* Time offset - Not yet supported              */
		break;
		/* Variable length fields */
	case 3:			/* Gateways list                                */
		if (NetOurGatewayIP == 0) {
			NetCopyIP (&NetOurGatewayIP, (IPaddr_t *) (ext + 2));
		}
		break;
	case 4:			/* Time server - Not yet supported              */
		break;
	case 5:			/* IEN-116 name server - Not yet supported      */
		break;
	case 6:
		if (NetOurDNSIP == 0) {
			NetCopyIP (&NetOurDNSIP, (IPaddr_t *) (ext + 2));
		}
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
		if ((NetOurDNS2IP == 0) && (size > 4)) {
			NetCopyIP (&NetOurDNS2IP, (IPaddr_t *) (ext + 2 + 4));
		}
#endif
		break;
	case 7:			/* Log server - Not yet supported               */
		break;
	case 8:			/* Cookie/Quote server - Not yet supported      */
		break;
	case 9:			/* LPR server - Not yet supported               */
		break;
	case 10:		/* Impress server - Not yet supported           */
		break;
	case 11:		/* RPL server - Not yet supported               */
		break;
	case 12:		/* Host name                                    */
		if (NetOurHostName[0] == 0) {
			size = truncate_sz ("Host Name", sizeof (NetOurHostName), size);
			memcpy (&NetOurHostName, ext + 2, size);
			NetOurHostName[size] = 0;
		}
		break;
	case 13:		/* Boot file size                               */
		if (size == 2)
			NetBootFileSize = ntohs (*(ushort *) (ext + 2));
		else if (size == 4)
			NetBootFileSize = ntohl (*(ulong *) (ext + 2));
		break;
	case 14:		/* Merit dump file - Not yet supported          */
		break;
	case 15:		/* Domain name - Not yet supported              */
		break;
	case 16:		/* Swap server - Not yet supported              */
		break;
	case 17:		/* Root path                                    */
		if (NetOurRootPath[0] == 0) {
			size = truncate_sz ("Root Path", sizeof (NetOurRootPath), size);
			memcpy (&NetOurRootPath, ext + 2, size);
			NetOurRootPath[size] = 0;
		}
		break;
	case 18:		/* Extension path - Not yet supported           */
		/*
		 * This can be used to send the information of the
		 * vendor area in another file that the client can
		 * access via TFTP.
		 */
		break;
		/* IP host layer fields */
	case 40:		/* NIS Domain name                              */
		if (NetOurNISDomain[0] == 0) {
			size = truncate_sz ("NIS Domain Name", sizeof (NetOurNISDomain), size);
			memcpy (&NetOurNISDomain, ext + 2, size);
			NetOurNISDomain[size] = 0;
		}
		break;
		/* Application layer fields */
	case 43:		/* Vendor specific info - Not yet supported     */
		/*
		 * Binary information to exchange specific
		 * product information.
		 */
		break;
		/* Reserved (custom) fields (128..254) */
	}
}

static void BootpVendorProcess (u8 * ext, int size)
{
	u8 *end = ext + size;

	debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);

	while ((ext < end) && (*ext != 0xff)) {
		if (*ext == 0) {
			ext++;
		} else {
			u8 *opt = ext;

			ext += ext[1] + 2;
			if (ext <= end)
				BootpVendorFieldProcess (opt);
		}
	}

#ifdef DEBUG_BOOTP_EXT
	puts ("[BOOTP] Received fields: \n");
	if (NetOurSubnetMask) {
		puts ("NetOurSubnetMask : ");
		print_IPaddr (NetOurSubnetMask);
		putc ('\n');
	}

	if (NetOurGatewayIP) {
		puts ("NetOurGatewayIP	: ");
		print_IPaddr (NetOurGatewayIP);
		putc ('\n');
	}

	if (NetBootFileSize) {
		printf ("NetBootFileSize : %d\n", NetBootFileSize);
	}

	if (NetOurHostName[0]) {
		printf ("NetOurHostName  : %s\n", NetOurHostName);
	}

	if (NetOurRootPath[0]) {
		printf ("NetOurRootPath  : %s\n", NetOurRootPath);
	}

	if (NetOurNISDomain[0]) {
		printf ("NetOurNISDomain : %s\n", NetOurNISDomain);
	}

	if (NetBootFileSize) {
		printf ("NetBootFileSize: %d\n", NetBootFileSize);
	}
#endif /* DEBUG_BOOTP_EXT */
}
/*
 *	Handle a BOOTP received packet.
 */
static void
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	Bootp_t *bp;
	char	*s;

	debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
		src, dest, len, sizeof (Bootp_t));

	bp = (Bootp_t *)pkt;

	if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
		return;

	/*
	 *	Got a good BOOTP reply.	 Copy the data into our variables.
	 */
#ifdef CONFIG_STATUS_LED
	status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
#endif

	BootpCopyNetParams(bp);		/* Store net parameters from reply */

	/* Retrieve extended information (we must parse the vendor area) */
	if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
		BootpVendorProcess(&bp->bp_vend[4], len);

	NetSetTimeout(0, (thand_f *)0);

	debug ("Got good BOOTP\n");

	if ((s = getenv("autoload")) != NULL) {
		if (*s == 'n') {
			/*
			 * Just use BOOTP to configure system;
			 * Do not use TFTP to load the bootfile.
			 */
			NetState = NETLOOP_SUCCESS;
			return;
//#if (CONFIG_COMMANDS & CFG_CMD_NFS)
		} else if (strcmp(s, "NFS") == 0) {
			/*
			 * Use NFS to load the bootfile.
			 */
			NfsStart();
			return;
#endif
		}
	}

	TftpStart();
}
#endif	/* !CFG_CMD_DHCP */

/*
 *	Timeout on BOOTP/DHCP request.
 */
static void
BootpTimeout(void)
{
	if (BootpTry >= TIMEOUT_COUNT) {
		puts ("\nRetry count exceeded; starting again\n");
		NetStartAgain ();
	} else {
		NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
		BootpRequest ();
	}
}

/*
 *	Initialize BOOTP extension fields in the request.
 */
//#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
{
	u8 *start = e;
	u8 *cnt;

#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
	u8 *x;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
	uchar *hostname;
#endif

	*e++ = 99;		/* RFC1048 Magic Cookie */
	*e++ = 130;
	*e++ = 83;
	*e++ = 99;

	*e++ = 53;		/* DHCP Message Type */
	*e++ = 1;
	*e++ = message_type;

	*e++ = 57;		/* Maximum DHCP Message Size */
	*e++ = 2;
	*e++ = (576 - 312 + OPT_SIZE) >> 8;
	*e++ = (576 - 312 + OPT_SIZE) & 0xff;

	if (ServerID) {
		int tmp = ntohl (ServerID);

		*e++ = 54;	/* ServerID */
		*e++ = 4;
		*e++ = tmp >> 24;
		*e++ = tmp >> 16;
		*e++ = tmp >> 8;
		*e++ = tmp & 0xff;
	}

	if (RequestedIP) {
		int tmp = ntohl (RequestedIP);

		*e++ = 50;	/* Requested IP */
		*e++ = 4;
		*e++ = tmp >> 24;
		*e++ = tmp >> 16;
		*e++ = tmp >> 8;
		*e++ = tmp & 0xff;
	}
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
	if ((hostname = getenv ("hostname"))) {
		int hostnamelen = strlen (hostname);

		*e++ = 12;	/* Hostname */
		*e++ = hostnamelen;
		memcpy (e, hostname, hostnamelen);
		e += hostnamelen;
	}
#endif

#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
	if ((x = dhcp_vendorex_prep (e)))
		return x - start;
#endif

	*e++ = 55;		/* Parameter Request List */
	 cnt = e++;		/* Pointer to count of requested items */
	*cnt = 0;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
	*e++  = 1;		/* Subnet Mask */
	*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
	*e++  = 3;		/* Router Option */
	*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
	*e++  = 6;		/* DNS Server(s) */
	*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
	*e++  = 12;		/* Hostname */
	*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
	*e++  = 13;		/* Boot File Size */

⌨️ 快捷键说明

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