From daniel@insu.com Thu Apr 27 14:14:55 2000
Sender: root@iNsu.COM
Message-ID: <39075669.FAEB20F2@insu.com>
Date: Wed, 26 Apr 2000 16:49:45 -0400
From: Daniel Shane <daniel@insu.com>
X-Mailer: Mozilla 4.72 [en] (X11; U; Linux 2.2.14-5.0 i686)
X-Accept-Language: en
MIME-Version: 1.0
Subject: Re: New feature added to etherboot
References: <20000425170804.6677127D8A@Goffman.iNsu.COM>
Content-Type: multipart/mixed;
 boundary="------------4734FDA0BF2F2FBDF8EB8DF6"

This is a multi-part message in MIME format.
--------------4734FDA0BF2F2FBDF8EB8DF6
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Ok, here is a diff for etherboot 4.6.0 that adds identifiers.

To test this you need to use a class in the dhcpd.conf file and
also send back a string in option 208.

These identifiers prevent a client from booting from other DHCP
servers when you have more than 1 in your network.

In will also prevent any client, except the valid ones, to use this
DHCP server.

Here is a subset of my dhcpd.conf :

option iNdiskless-state code 208 = text;

class "iNdiskless-boot" {
    match if substring(option iNdiskless-state,0,4) = "BOOT";
}
class "iNdiskless-setup" {
    match if substring(option iNdiskless-state,0,5) = "SETUP";
}           

subnet 10.4.1.0 netmask 255.255.255.0 {
pool {
  allow members of "iNdiskless-boot";
  deny unknown clients;
  range 10.4.1.2 10.4.1.200;
  next-server 10.4.1.1;

# Identify ourselves to the etherboot/DHCP client
  option iNdiskless-state       "BOOT"; 

  host labo01 {
       hardware ethernet 00:80:c8:ec:04:1b;
     }
  host labo02 {
       hardware ethernet 00:4f:4c:04:45:d6;
     }
  host labo03 {
       hardware ethernet 00:50:ba:c8:db:d6;
  }
}
pool {
  allow members of "iNdiskless-setup";
  range 10.4.1.201 10.4.1.254;
  option iNdiskless-state       "SETUP";

# send another kernel to setup the diskless workstation
  }
}    

Daniel Shane.
--------------4734FDA0BF2F2FBDF8EB8DF6
Content-Type: text/plain; charset=us-ascii;
 name="main.c.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="main.c.diff"

--- etherboot-4.6.0/src/main.c	Tue Apr 25 08:30:01 2000
+++ etherboot-4.5.6-new/src/main.c	Wed Apr 26 16:17:09 2000
@@ -42,6 +42,23 @@ char	*motd[RFC1533_VENDOR_NUMOFMOTD];
 #ifdef	IMAGE_FREEBSD
 int freebsd_howto = 0;
 #endif
+
+#ifdef SERVER_IDENT 
+#ifdef DEFAULT_SERVER_IDENT
+char server_ident[9] = DEFAULT_SERVER_IDENT;
+#else
+char server_ident[9] = {};
+#endif   
+#endif
+
+#ifdef CLIENT_IDENT 
+#ifdef DEFAULT_CLIENT_IDENT
+char client_ident[9] = DEFAULT_CLIENT_IDENT;
+#else
+char client_ident[9] = {};
+#endif
+#endif
+
 int     vendorext_isvalid;
 char	config_buffer[TFTP_MAX_PACKET+1];	/* +1 for null byte */
 unsigned long	netmask;
@@ -63,61 +80,85 @@ char    rfc1533_cookie[5] = { RFC1533_CO
 char    rfc1533_cookie[] = { RFC1533_COOKIE};
 char    rfc1533_end[]={RFC1533_END };
 static const char dhcpdiscover[]={
-		RFC2132_MSG_TYPE,1,DHCPDISCOVER,
-		RFC2132_MAX_SIZE,2,2,64,
-		RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY,
-		RFC1533_HOSTNAME,RFC1533_EXTENSIONPATH
-	};
-static const char dhcprequest []={
-		RFC2132_MSG_TYPE,1,DHCPREQUEST,
-		RFC2132_SRV_ID,4,0,0,0,0,
-		RFC2132_REQ_ADDR,4,0,0,0,0,
-		RFC2132_MAX_SIZE,2,2,64,
-		/* request parameters */
-		RFC2132_PARAM_LIST,
-#ifdef	IMAGE_FREEBSD
-		/* 4 standard + 4 vendortags + 8 motd + 16 menu items */
-		4 + 4 + 8 + 16,
+	RFC2132_MSG_TYPE,1,DHCPDISCOVER,
+	RFC2132_MAX_SIZE,2,2,64,
+#ifdef CLIENT_IDENT 
+	RFC1533_VENDOR_CLIENT_IDENT,8,0,0,0,0,0,0,0,0,
+#endif
+	RFC2132_PARAM_LIST,
+#ifdef SERVER_IDENT 
+	5,
 #else
-		/* 4 standard + 3 vendortags + 8 motd + 16 menu items */
-		4 + 3 + 8 + 16,
+	4,
 #endif
-		/* Standard parameters */
-		RFC1533_NETMASK, RFC1533_GATEWAY,
-		RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
-		/* Etherboot vendortags */
-		RFC1533_VENDOR_MAGIC,
+#ifdef SERVER_IDENT 
+	RFC1533_VENDOR_SERVER_IDENT,   
+#endif
+	RFC1533_NETMASK,
+	RFC1533_GATEWAY,
+	RFC1533_HOSTNAME,
+	RFC1533_EXTENSIONPATH
+};
+static const char dhcprequest []={
+	RFC2132_MSG_TYPE,1,DHCPREQUEST,
+	RFC2132_SRV_ID,4,0,0,0,0,
+	RFC2132_REQ_ADDR,4,0,0,0,0,
+#ifdef CLIENT_IDENT 
+	RFC1533_VENDOR_CLIENT_IDENT,8,0,0,0,0,0,0,0,0,
+#endif
+	RFC2132_MAX_SIZE,2,2,64,
+	/* request parameters */
+	RFC2132_PARAM_LIST,
+	/* 4 standard + 3 vendortags + 8 motd + 16 menu items */
+	4 + 
+	3 + 
+#ifdef  IMAGE_FREEBSD
+	1 + /* One more vendortags for VENDOR_HOWTO */
+#endif
+#ifdef SERVER_IDENT 
+	1 + /* One more vendortags for VENDOR_SERVER_IDENT */
+#endif
+	8 + 
+	16,
+	/* Standard parameters */
+	RFC1533_NETMASK, RFC1533_GATEWAY,
+	RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
+	/* Etherboot vendortags */
+	RFC1533_VENDOR_MAGIC,
 #ifdef	IMAGE_FREEBSD
-		RFC1533_VENDOR_HOWTO,
+	RFC1533_VENDOR_HOWTO,
 #endif
-		RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
-		/* 8 MOTD entries */
-		RFC1533_VENDOR_MOTD,
-		RFC1533_VENDOR_MOTD+1,
-		RFC1533_VENDOR_MOTD+2,
-		RFC1533_VENDOR_MOTD+3,
-		RFC1533_VENDOR_MOTD+4,
-		RFC1533_VENDOR_MOTD+5,
-		RFC1533_VENDOR_MOTD+6,
-		RFC1533_VENDOR_MOTD+7,
-		/* 16 image entries */
-		RFC1533_VENDOR_IMG,
-		RFC1533_VENDOR_IMG+1,
-		RFC1533_VENDOR_IMG+2,
-		RFC1533_VENDOR_IMG+3,
-		RFC1533_VENDOR_IMG+4,
-		RFC1533_VENDOR_IMG+5,
-		RFC1533_VENDOR_IMG+6,
-		RFC1533_VENDOR_IMG+7,
-		RFC1533_VENDOR_IMG+8,
-		RFC1533_VENDOR_IMG+9,
-		RFC1533_VENDOR_IMG+10,
-		RFC1533_VENDOR_IMG+11,
-		RFC1533_VENDOR_IMG+12,
-		RFC1533_VENDOR_IMG+13,
-		RFC1533_VENDOR_IMG+14,
-		RFC1533_VENDOR_IMG+15,
-	};
+#ifdef SERVER_IDENT
+	RFC1533_VENDOR_SERVER_IDENT,
+#endif
+	RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
+	/* 8 MOTD entries */
+	RFC1533_VENDOR_MOTD,
+	RFC1533_VENDOR_MOTD+1,
+	RFC1533_VENDOR_MOTD+2,
+	RFC1533_VENDOR_MOTD+3,
+	RFC1533_VENDOR_MOTD+4,
+	RFC1533_VENDOR_MOTD+5,
+	RFC1533_VENDOR_MOTD+6,
+	RFC1533_VENDOR_MOTD+7,
+	/* 16 image entries */
+	RFC1533_VENDOR_IMG,
+	RFC1533_VENDOR_IMG+1,
+	RFC1533_VENDOR_IMG+2,
+	RFC1533_VENDOR_IMG+3,
+	RFC1533_VENDOR_IMG+4,
+	RFC1533_VENDOR_IMG+5,
+	RFC1533_VENDOR_IMG+6,
+	RFC1533_VENDOR_IMG+7,
+	RFC1533_VENDOR_IMG+8,
+	RFC1533_VENDOR_IMG+9,
+	RFC1533_VENDOR_IMG+10,
+	RFC1533_VENDOR_IMG+11,
+	RFC1533_VENDOR_IMG+12,
+	RFC1533_VENDOR_IMG+13,
+	RFC1533_VENDOR_IMG+14,
+	RFC1533_VENDOR_IMG+15,
+};
 
 #endif	/* NO_DHCP_SUPPORT */
 static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -176,6 +217,55 @@ done:
 			break;
 	}
 #endif
+
+#ifdef SHIFTED_IDENT_INPUT
+	if (getshift() & 3)
+		{
+#endif
+	
+#ifdef  CLIENT_IDENT
+#   ifdef ASK_CLIENT_IDENT
+			{
+				char tmp_ident[9] = {};
+#      ifdef  DEFAULT_CLIENT_IDENT
+				printf("Enter the client identifier (8 char max.) default [%s] : ",client_ident);
+#      else
+				printf("Enter the client identifier (8 char max.) : ");
+#      endif
+				getstr(tmp_ident,8);
+				if (strlen(tmp_ident) != 0)
+					memcpy(client_ident,tmp_ident,8);
+				else
+					printf("%s",client_ident);
+				putchar('\n');
+			}
+#   endif
+#endif
+
+#ifdef  SERVER_IDENT
+#   ifdef ASK_SERVER_IDENT
+			{
+				char tmp_ident[9] = {};
+#      ifdef  DEFAULT_SERVER_IDENT
+				printf("Enter the server identifier (8 char max.) default [%s] : ",server_ident);
+#      else
+				printf("Enter the server identifier (8 char max.) : ");
+#      endif
+				getstr(tmp_ident,8);
+				if (strlen(tmp_ident) != 0)
+					memcpy(server_ident,tmp_ident,8);
+				else
+					printf("%s",server_ident);
+				putchar('\n');
+			}
+#   endif
+#endif
+
+#ifdef SHIFTED_IDENT_INPUT
+		}
+#endif
+
+	print_config();
 #if	(TRY_FLOPPY_FIRST > 0) && defined(FLOPPY)
 	disk_init();
 	printf("Trying floppy");
@@ -188,7 +278,7 @@ done:
 	}
 	printf("no floppy\n");
 #endif	/* TRY_FLOPPY_FIRST && FLOPPY */
-	print_config();
+        print_config();
 	gateA20_set();
 #ifdef	EMERGENCYDISKBOOT
 	if (!eth_probe()) {
@@ -663,6 +753,8 @@ BOOTP - Get my IP address and load infor
 int bootp()
 {
 	int retry;
+        int offset = 0;
+
 #ifndef	NO_DHCP_SUPPORT
 	int retry1;
 #endif	/* NO_DHCP_SUPPORT */
@@ -680,11 +772,18 @@ int bootp()
 	bp.bp_xid = xid = starttime = currticks();
 	memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
 #ifdef	NO_DHCP_SUPPORT
-	memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
+	memcpy(bp.bp_vend+offset, rfc1533_cookie, 5); /* request RFC-style options */
+	offset += sizeof rfc1533_cookie;
 #else
-	memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
-	memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
-	memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end);
+	memcpy(bp.bp_vend+offset, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
+	offset += sizeof rfc1533_cookie; 	
+	memcpy(bp.bp_vend+offset, dhcpdiscover, sizeof dhcpdiscover);
+	offset += sizeof dhcpdiscover;
+#ifdef CLIENT_IDENT 
+	memcpy(bp.bp_vend+13, client_ident, strlen(client_ident));
+#endif
+	memcpy(bp.bp_vend+offset, rfc1533_end, sizeof rfc1533_end);
+	offset += sizeof rfc1533_end;
 #endif	/* NO_DHCP_SUPPORT */
 
 	for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
@@ -715,19 +814,22 @@ int bootp()
 #else
 		if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){
 			if (dhcp_reply==DHCPOFFER){
-		dhcp_reply=0;
-		memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
-		memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
-		memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
-		memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
-		memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
-			for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
-			udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
-				sizeof(struct bootp_t), &bp);
 				dhcp_reply=0;
-				if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
-					if (dhcp_reply==DHCPACK)
-						return(1);
+				memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
+				memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
+				memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
+				memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
+				memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
+#ifdef CLIENT_IDENT
+				memcpy(bp.bp_vend+21, client_ident, strlen(client_ident));
+#endif
+				for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
+					udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
+						     sizeof(struct bootp_t), &bp);
+					dhcp_reply=0;
+					if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
+						if (dhcp_reply==DHCPACK)
+							return(1);
 					rfc951_sleep(++retry1);
 				}
 			} else
@@ -750,6 +852,7 @@ AWAIT_REPLY - Wait until we get a respon
 **************************************************************************/
 int await_reply(int type, int ival, void *ptr, int timeout)
 {
+	int result;
 	unsigned long time;
 	struct	iphdr *ip;
 	struct	udphdr *udp;
@@ -757,6 +860,7 @@ int await_reply(int type, int ival, void
 	struct	bootp_t *bootpreply;
 	struct	rpc_t *rpc;
 	unsigned short ptype;
+	unsigned int min_packetlen;
 
 	unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
 				sizeof(struct udphdr);
@@ -766,35 +870,35 @@ int await_reply(int type, int ival, void
 	 * needs a negligible amount of time.  */
 	for (;;) {
 		if (eth_poll()) {	/* We have something! */
-					/* Check for ARP - No IP hdr */
+			/* Check for ARP - No IP hdr */
 			if (nic.packetlen >= ETHER_HDR_SIZE) {
 				ptype = ((unsigned short) nic.packet[12]) << 8
 					| ((unsigned short) nic.packet[13]);
 			} else continue; /* what else could we do with it? */
 			if ((nic.packetlen >= ETHER_HDR_SIZE +
-				sizeof(struct arprequest)) &&
-			   (ptype == ARP) ) {
+			     sizeof(struct arprequest)) &&
+			    (ptype == ARP) ) {
 				unsigned long tmp;
-
+				
 				arpreply = (struct arprequest *)
 					&nic.packet[ETHER_HDR_SIZE];
 				if ((arpreply->opcode == ntohs(ARP_REPLY)) &&
-				   !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
-				   (type == AWAIT_ARP)) {
+				    !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
+				    (type == AWAIT_ARP)) {
 					memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
 					return(1);
 				}
 				memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
 				if ((arpreply->opcode == ntohs(ARP_REQUEST)) &&
-					(tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
+				    (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
 					arpreply->opcode = htons(ARP_REPLY);
 					memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
 					memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE);
 					memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
 					memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
 					eth_transmit(arpreply->thwaddr, ARP,
-						sizeof(struct  arprequest),
-						arpreply);
+						     sizeof(struct  arprequest),
+						     arpreply);
 #ifdef	MDEBUG
 					memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
 					printf("Sent ARP reply to: %I\n",tmp);
@@ -802,20 +906,20 @@ int await_reply(int type, int ival, void
 				}
 				continue;
 			}
-
+			
 			if (type == AWAIT_QDRAIN) {
 				continue;
 			}
-
-					/* Check for RARP - No IP hdr */
+			
+			/* Check for RARP - No IP hdr */
 			if ((type == AWAIT_RARP) &&
-			   (nic.packetlen >= ETHER_HDR_SIZE +
-				sizeof(struct arprequest)) &&
-			   (ptype == RARP)) {
+			    (nic.packetlen >= ETHER_HDR_SIZE +
+			     sizeof(struct arprequest)) &&
+			    (ptype == RARP)) {
 				arpreply = (struct arprequest *)
 					&nic.packet[ETHER_HDR_SIZE];
 				if ((arpreply->opcode == ntohs(RARP_REPLY)) &&
-				   !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
+				    !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
 					memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
 					memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
 					memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
@@ -823,64 +927,72 @@ int await_reply(int type, int ival, void
 				}
 				continue;
 			}
-
-					/* Anything else has IP header */
+			
+			/* Anything else has IP header */
 			if ((nic.packetlen < protohdrlen) ||
-			   (ptype != IP) ) continue;
+			    (ptype != IP) ) continue;
 			ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE];
 			if ((ip->verhdrlen != 0x45) ||
-				ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
-				(ip->protocol != IP_UDP)) continue;
+			    ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
+			    (ip->protocol != IP_UDP)) continue;
 			udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE +
-				sizeof(struct iphdr)];
-
-					/* BOOTP ? */
+							  sizeof(struct iphdr)];
+			
+			/* BOOTP ? */
 			bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE];
-			if ((type == AWAIT_BOOTP) &&
-			   (nic.packetlen >= (ETHER_HDR_SIZE +
-#ifdef	NO_DHCP_SUPPORT
-			     sizeof(struct bootp_t))) &&
+#ifdef  NO_DHCP_SUPPORT
+			min_packetlen = ETHER_HDR_SIZE + sizeof(struct bootp_t);
 #else
-			     sizeof(struct bootp_t))-DHCP_OPT_LEN) &&
-#endif	/* NO_DHCP_SUPPORT */
-			   (ntohs(udp->dest) == BOOTP_CLIENT) &&
-			   (bootpreply->bp_op == BOOTP_REPLY) &&
-			   (bootpreply->bp_xid == xid)) {
-				arptable[ARP_CLIENT].ipaddr.s_addr =
-					bootpreply->bp_yiaddr.s_addr;
+			min_packetlen = ETHER_HDR_SIZE + sizeof(struct bootp_t) - DHCP_OPT_LEN;
+#endif
+			if (
+			    (type == AWAIT_BOOTP) &&
+			    (nic.packetlen >= min_packetlen) &&
+			    (ntohs(udp->dest) == BOOTP_CLIENT) &&
+			    (bootpreply->bp_op == BOOTP_REPLY) &&
+			    (bootpreply->bp_xid == xid)
+			    ) {
+				arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
 #ifndef	NO_DHCP_SUPPORT
 				dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
 #endif	/* NO_DHCP_SUPPORT */
 				netmask = default_netmask();
-				arptable[ARP_SERVER].ipaddr.s_addr =
-					bootpreply->bp_siaddr.s_addr;
+				arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
 				memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE);  /* Kill arp */
-				arptable[ARP_GATEWAY].ipaddr.s_addr =
-					bootpreply->bp_giaddr.s_addr;
+				arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
 				memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE);  /* Kill arp */
 				if (bootpreply->bp_file[0]) {
 					memcpy(kernel_buf, bootpreply->bp_file, 128);
 					kernel = kernel_buf;
 				}
 				memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
-				decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
-#ifdef	NO_DHCP_SUPPORT
-					       0, BOOTP_VENDOR_LEN +
-					       MAX_BOOTP_EXTLEN, 1);
-#else
-					       0, DHCP_OPT_LEN, 1);
-#endif	/* NO_DHCP_SUPPORT */
-				return(1);
+#ifdef  NO_DHCP_SUPPORT
+				if (decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
+						   0, BOOTP_VENDOR_LEN +
+						   MAX_BOOTP_EXTLEN, 1)) {
+					return(1);
+				}
+				else {
+					continue;
+				}
+#else	
+				if (decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
+						   0, DHCP_OPT_LEN, 1)) {
+					return(1);
+				}
+				else {
+					continue;
+				}
 			}
-
+#endif	/* NO_DHCP_SUPPORT */
 #ifdef	DOWNLOAD_PROTO_TFTP
-					/* TFTP ? */
+			/* TFTP ? */
 			if ((type == AWAIT_TFTP) &&
-				(ntohs(udp->dest) == ival)) return(1);
+			    (ntohs(udp->dest) == ival)) return(1);
 #endif	/* DOWNLOAD_PROTO_TFTP */
-
+			
 #ifdef	DOWNLOAD_PROTO_NFS
-					/* RPC ? */
+			/* RPC ? */
 			rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE];
 			if ((type == AWAIT_RPC) &&
 			    (ntohs(udp->dest) == ival) &&
@@ -889,19 +1001,19 @@ int await_reply(int type, int ival, void
 				return (1);
 			}
 #endif	/* DOWNLOAD_PROTO_NFS */
-
+			
 		} else {
-			/* Check for abort key only if the Rx queue is empty -
-			 * as long as we have something to process, don't
-			 * assume that something failed.  It is unlikely that
-			 * we have no processing time left between packets.  */
+				/* Check for abort key only if the Rx queue is empty -
+				 * as long as we have something to process, don't
+				 * assume that something failed.  It is unlikely that
+				 * we have no processing time left between packets.  */
 			if (iskey() && (getchar() == ESC))
 #ifdef	EMERGENCYDISKBOOT
 				exit(0);
 #else
-				longjmp(jmp_bootmenu,1);
+			longjmp(jmp_bootmenu,1);
 #endif
-			/* Do the timeout after at least a full queue walk.  */
+				/* Do the timeout after at least a full queue walk.  */
 			if ((timeout == 0) || (currticks() > time)) {
 				break;
 			}
@@ -914,13 +1026,15 @@ int await_reply(int type, int ival, void
 DECODE_RFC1533 - Decodes RFC1533 header
 **************************************************************************/
 int decode_rfc1533(p, block, len, eof)
-	register unsigned char *p;
-	int block, len, eof;
+        register unsigned char *p;
+        int block, len, eof;  
 {
 	static unsigned char *extdata = NULL, *extend = NULL;
 	unsigned char        *extpath = NULL;
 	unsigned char        *endp;
-
+#ifdef SERVER_IDENT
+	char rcvd_server_ident[9] = {};
+#endif
 	if (block == 0) {
 #ifdef	IMAGE_MENU
 		memset(imagelist, 0, sizeof(imagelist));
@@ -1002,11 +1116,16 @@ int decode_rfc1533(p, block, len, eof)
 			}
 #endif
 #ifdef	MOTD
-			else if (c >= RFC1533_VENDOR_MOTD &&
+                        else if (c >= RFC1533_VENDOR_MOTD &&
 				 c < RFC1533_VENDOR_MOTD +
 				 RFC1533_VENDOR_NUMOFMOTD)
 				motd[c - RFC1533_VENDOR_MOTD] = p;
 #endif
+#ifdef SERVER_IDENT 
+			else if (c == RFC1533_VENDOR_SERVER_IDENT) {
+				memcpy(rcvd_server_ident,p+2,TAG_LEN(p));
+			}
+#endif
 			else {
 #if	0
 				unsigned char *q;
@@ -1018,6 +1137,30 @@ int decode_rfc1533(p, block, len, eof)
 			}
 			p += TAG_LEN(p) + 2;
 		}
+#if defined(SERVER_IDENT) && defined(DBG_IDENT)
+		if (strcasecmp(rcvd_server_ident,server_ident)) {
+			char ip[16];
+
+			inet_ntoa(dhcp_server,ip);
+			printf("[%s]: Option %d (%s), invalid response. Wanted (%s).\n",
+			       ip,
+			       RFC1533_VENDOR_SERVER_IDENT,
+			       rcvd_server_ident,
+			       server_ident);
+			strcpy(rcvd_server_ident,"");
+			return(0);
+		}
+	        else {
+			char ip[16];
+
+			inet_ntoa(dhcp_server,ip);
+			printf("[%s]: Option %d (%s), valid response.\n",
+			       ip,
+			       RFC1533_VENDOR_SERVER_IDENT,
+			       rcvd_server_ident);
+			strcpy(rcvd_server_ident,"");
+		}
+#endif
 		extdata = extend = endp;
 		if (block == 0 && extpath != NULL) {
 			char fname[64];
@@ -1103,3 +1246,4 @@ void cleanup(void)
  *  c-basic-offset: 8
  * End:
  */
+

--------------4734FDA0BF2F2FBDF8EB8DF6
Content-Type: text/plain; charset=us-ascii;
 name="misc.c.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="misc.c.diff"

--- etherboot-4.6.0/src/misc.c	Tue Apr 25 08:30:25 2000
+++ etherboot-4.5.6-new/src/misc.c	Wed Apr 26 16:26:38 2000
@@ -140,9 +140,11 @@ void printf(const char *fmt, ...)
 
 #ifdef	IMAGE_MENU
 /**************************************************************************
-INET_ATON - Convert an ascii x.x.x.x to binary form
+INET_NTOA - Convert an ascii x.x.x.x to binary form
 **************************************************************************/
-int inet_aton(char *p, in_addr *i)
+int inet_aton(p, i)
+	char *p;
+	in_addr *i;
 {
 	unsigned long ip = 0;
 	int val;
@@ -165,7 +167,19 @@ int inet_aton(char *p, in_addr *i)
 
 #endif	/* IMAGE_MENU */
 
-int getdec(char **ptr)
+#if  defined(CLIENT_IDENT) || defined (SERVER_IDENT)
+/**************************************************************************
+INET_NTOA - Convert a binary form to an ascii x.x.x.x form
+**************************************************************************/
+char *inet_ntoa(in_addr i, char *p)
+{
+	sprintf(p,"%d.%d.%d.%d",i.s_addr>>24,i.s_addr<<8>>24,i.s_addr<<16>>24,i.s_addr<<24>>24);
+	return p;
+}
+#endif
+
+int getdec(ptr)
+	char **ptr;
 {
 	char *p = *ptr;
 	int ret=0;
@@ -308,6 +322,45 @@ iskey(void)
 	return 0;
 }
 #endif	/* ETHERBOOT32 */
+
+/**************************************************************************
+GETSTR - Read a string of size bytes from the keyboard 
+(without echoing the final return)
+**************************************************************************/
+void getstr(char *s, int size)
+{
+   int i=0;
+   char c;
+
+   while(1) {
+      c = getc();
+	  
+			    
+      if (c == 13)
+         {
+	   s[i]='\0';
+	   break;
+         }
+      else if ( 
+		((c >= 'a') && (c <='z')) ||  
+		((c >= 'A') && (c <='Z')) ||
+		((c >= '0') && (c <='9'))
+	      ) {
+                 if (i==8) {
+                     putchar(8);
+                     putchar(s[i-1]=c);
+                  }
+                  else
+                     putchar(s[i++]=c);      
+                }
+     else if ( c == 8 ) {   
+	   if (i != 0) {
+		   --i;
+		   s[i]='\0';
+		   putchar(8);
+		   putchar(32);
+		   putchar(8);
+	   }
+     }
+   }
+}
 
 /*
  * Local variables:

--------------4734FDA0BF2F2FBDF8EB8DF6
Content-Type: text/plain; charset=us-ascii;
 name="Config.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Config.diff"

--- etherboot-4.6.0/src/Config	Tue Apr 25 08:30:57 2000
+++ etherboot-4.5.6-new/src/Config	Wed Apr 26 15:55:57 2000
@@ -59,6 +59,27 @@
 #			  may no longer be appropriate.  You might need to set
 #			  MAX_ARP_RETRIES, MAX_BOOTP_RETRIES, MAX_TFTP_RETRIES
 #			  and MAX_RPC_RETRIES to a larger value.
+#	-DDEFAULT_CLIENT_IDENT
+#			  The default client identifier that is sent to the
+#			  DHCP server to identify itself. 
+#	-DDEFAULT_SERVER_IDENT
+#			  The expected response that the client will wait
+#			  for when a DHCP server responds to the the initial
+#			  client discovery.
+#	-DASK_CLIENT_IDENT
+#	-DASK_SERVER_IDENT
+#			  If these are set, the boot process will include
+#			  a question period where you can manualy specify
+#			  the client and/or server identifiers.
+#	-DSHIFTED_IDENT_INPUT
+#			  If this is set then the boot process will only
+#			  ask for the identifiers if one of the shift keys
+#			  is pressed. Else it will send the default identifiers
+#			  automatically
+#	-DDBG_IDENT
+#			  This will give show all the DHCP responses with
+#			  their identifiers.
+#			  
 #
 # Etherboot/32 only options:
 #	-DAOUT_IMAGE	- Add a.out kernel boot support (generic)
@@ -147,6 +168,14 @@ CFLAGS32+=	-DASK_BOOT=3 -DANS_DEFAULT=AN
 
 # Change download protocol to NFS.  Only available for Etherboot/32 for now.
 # CFLAGS32+=	-DDOWNLOAD_PROTO_NFS
+
+# If you have more than one DHCP server you might want to
+# enable these to be able to sort out which one you want to
+# respond to.  
+CFLAGS32+= -DDEFAULT_CLIENT_IDENT=\"BOOT\" -DDEFAULT_SERVER_IDENT=\"BOOT\"
+CFLAGS32+= -DASK_CLIENT_IDENT -DASK_SERVER_IDENT
+CFLAGS32+= -DSHIFTED_IDENT_INPUT
+CFLAGS32+= -DDBG_IDENT 
 
 # These flags affect the loader that is prepended to the Etherboot image
 LCONFIG+=	-DMOVEROM

--------------4734FDA0BF2F2FBDF8EB8DF6
Content-Type: text/plain; charset=us-ascii;
 name="etherboot.h.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="etherboot.h.diff"

--- etherboot-4.6.0/src/etherboot.h	Tue Apr 25 08:30:55 2000
+++ etherboot-4.5.6-new/src/etherboot.h	Wed Apr 26 16:07:16 2000
@@ -8,6 +8,14 @@ Author: Martin Renters
 
 #include "osdep.h"
 
+#if (! defined(NO_DHCP_SUPPORT)) && (defined(ASK_CLIENT_IDENT) || defined(DEFAULT_CLIENT_IDENT))
+#   define CLIENT_IDENT
+#endif
+
+#if (! defined(NO_DHCP_SUPPORT)) && (defined(ASK_SERVER_IDENT) || defined(DEFAULT_SERVER_IDENT))
+#   define SERVER_IDENT
+#endif
+
 /* These could be customised for different languages perhaps */
 #define	ASK_PROMPT	"Boot from (N)etwork or from (L)ocal? "
 #define	ANS_NETWORK	'N'
@@ -224,6 +232,12 @@ Author: Martin Renters
 #ifdef	IMAGE_FREEBSD
 #define RFC1533_VENDOR_HOWTO    132
 #endif
+#ifdef CLIENT_IDENT
+#define RFC1533_VENDOR_CLIENT_IDENT    208
+#endif
+#ifdef SERVER_IDENT
+#define RFC1533_VENDOR_SERVER_IDENT    208
+#endif
 #define RFC1533_VENDOR_MNUOPTS	160
 #define RFC1533_VENDOR_SELECTION 176
 #define RFC1533_VENDOR_MOTD	184
@@ -477,11 +491,13 @@ extern int getdec P((char **));
 extern void printf P((const char *, ...));
 extern char *sprintf P((char *, const char *, ...));
 extern int inet_aton P((char *p, in_addr *i));
+extern char *inet_ntoa P((in_addr i, char *p));
 extern void gateA20_set P((void));
 extern void gateA20_unset P((void));
 extern void putchar P((int));
 extern int getchar P((void));
 extern int iskey P((void));
+extern void getstr P((char *s, int size));
 
 /* start*.S */
 extern int getc P((void));
@@ -528,8 +544,10 @@ extern int hostnamelen;
 extern unsigned long netmask;
 extern int jmp_bootmenu[10];
 extern struct arptable_t arptable[MAX_ARP];
-#ifdef	IMAGE_MENU
+#ifdef MOTD
 extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
+#endif
+#ifdef	IMAGE_MENU
 extern int menutmo,menudefault;
 extern unsigned char *defparams;
 extern int defparams_max;

--------------4734FDA0BF2F2FBDF8EB8DF6--