summaryrefslogtreecommitdiffstats
path: root/contrib/dhcpid/dhcpid.txt
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/dhcpid/dhcpid.txt')
-rw-r--r--contrib/dhcpid/dhcpid.txt884
1 files changed, 884 insertions, 0 deletions
diff --git a/contrib/dhcpid/dhcpid.txt b/contrib/dhcpid/dhcpid.txt
new file mode 100644
index 00000000..e6b5d277
--- /dev/null
+++ b/contrib/dhcpid/dhcpid.txt
@@ -0,0 +1,884 @@
+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--
+