Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Oct 2000 22:10:10 +0100
From:      Tor.Egge@fast.no
To:        perhov@math.ntnu.no
Cc:        cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/sys/nfs bootp_subr.c
Message-ID:  <200010312110.WAA56137@midten.fast.no>
In-Reply-To: Your message of "Tue, 31 Oct 2000 14:52:15 %2B0100 (MET)"
References:  <Pine.GS4.4.21.0010311439500.29970-100000@martens.math.ntnu.no>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Tue_Oct_31_22:09:58_2000)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> [Tor Egge]
> 
> |  tegge       2000/10/28 18:19:33 PDT
> |  
> |    Modified files:
> |      sys/nfs              bootp_subr.c 
> 
> Hi. Would it be much work to back-port the changes from NetBSD
> that enables the DHCP extensions? (NetBSD's bootp support was
> originally ported from FreeBSD's bootp_subr.c, wasn't it?)

FreeBSD's bootp_subr.c is ported from NetBSD's nfs_boot.c.
(cf. NetBSD PR kern/2351).


> If it's not too much work, do you think I would succeed in
> convincing you to do it? (if I ask nicely and politely, of
> course:-).

Something like the enclosed patch ?

- Tor Egge


----Next_Part(Tue_Oct_31_22:09:58_2000)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Index: sys/nfs/bootp_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/nfs/bootp_subr.c,v
retrieving revision 1.26
diff -u -r1.26 bootp_subr.c
--- sys/nfs/bootp_subr.c	2000/10/29 13:57:13	1.26
+++ sys/nfs/bootp_subr.c	2000/10/31 20:39:52
@@ -126,10 +126,15 @@
 	enum {
 		IF_BOOTP_UNRESOLVED,
 		IF_BOOTP_RESOLVED,
+		IF_BOOTP_FAILED,
+		IF_DHCP_UNRESOLVED,
 		IF_DHCP_OFFERED,
 		IF_DHCP_RESOLVED,
-		IF_BOOTP_FAILED
+		IF_DHCP_FAILED,
 	} state;
+	int dhcpquerytype;		/* dhcp type sent */
+	struct in_addr dhcpserver;
+	int gotdhcpserver;
 };
 
 #define TAG_MAXLEN 1024
@@ -191,6 +196,17 @@
 #define TAG_ROOTOPTS	130
 #define TAG_SWAPOPTS	131
 
+#define TAG_DHCP_MSGTYPE 53
+#define TAG_DHCP_REQ_ADDR 50
+#define TAG_DHCP_SERVERID 54
+#define TAG_DHCP_LEASETIME 51
+
+#define DHCP_NOMSG    0
+#define DHCP_DISCOVER 1
+#define DHCP_OFFER    2
+#define DHCP_REQUEST  3
+#define DHCP_ACK      5
+
 extern int nfs_diskless_valid;
 extern struct nfsv3_diskless nfsv3_diskless;
 
@@ -418,6 +434,11 @@
 	
 	bzero(ifctx, sizeof(*ifctx));
 	ifctx->xid = gctx->xid;
+#ifdef BOOTP_NO_DHCP
+	ifctx->state = IF_BOOTP_UNRESOLVED;
+#else
+	ifctx->state = IF_DHCP_UNRESOLVED;
+#endif
 	gctx->xid += 0x100;
 	return ifctx;
 }
@@ -427,6 +448,8 @@
 bootpc_received(struct bootpc_globalcontext *gctx,
 		struct bootpc_ifcontext *ifctx)
 {
+	unsigned char dhcpreplytype;
+	char *p;
 	/*
 	 * Need timeout for fallback to less
 	 * desirable alternative.
@@ -442,9 +465,35 @@
 	if (gctx->tmptag.badopt != 0)
 		return 0;
 	
+	p = bootpc_tag(&gctx->tmptag, &gctx->reply,
+		       gctx->replylen, TAG_DHCP_MSGTYPE);
+	if (p != NULL)
+		dhcpreplytype = *p;
+	else
+		dhcpreplytype = DHCP_NOMSG;
+	
+	switch (ifctx->dhcpquerytype) {
+	case DHCP_DISCOVER:
+		if (dhcpreplytype != DHCP_OFFER 	/* Normal DHCP offer */
+#ifndef BOOTP_FORCE_DHCP
+		    && dhcpreplytype != DHCP_NOMSG	/* Fallback to BOOTP */
+#endif
+			)
+			return 0;
+		break;
+	case DHCP_REQUEST:
+		if (dhcpreplytype != DHCP_ACK)
+			return 0;
+	case DHCP_NOMSG:
+	}
+		
+	
 	/* Ignore packet unless it gives us a root tag we didn't have */
 	
-	if (ifctx->state == IF_BOOTP_RESOLVED &&
+	if ((ifctx->state == IF_BOOTP_RESOLVED ||
+	     (ifctx->dhcpquerytype == DHCP_DISCOVER &&
+	      (ifctx->state == IF_DHCP_OFFERED ||
+	       ifctx->state == IF_DHCP_RESOLVED))) &&
 	    (bootpc_tag(&gctx->tmptag, &ifctx->reply,
 			ifctx->replylen,
 			TAG_ROOT) != NULL ||
@@ -459,7 +508,31 @@
 	ifctx->replylen = gctx->replylen;
 	
 	/* XXX: Only reset if 'perfect' response */
-	ifctx->state = IF_BOOTP_RESOLVED;
+	if (ifctx->state == IF_BOOTP_UNRESOLVED)
+		ifctx->state = IF_BOOTP_RESOLVED;
+	else if (ifctx->state == IF_DHCP_UNRESOLVED &&
+		 ifctx->dhcpquerytype == DHCP_DISCOVER) {
+		if (dhcpreplytype == DHCP_OFFER)
+			ifctx->state = IF_DHCP_OFFERED;
+		else
+			ifctx->state = IF_BOOTP_RESOLVED;	/* Fallback */
+	} else if (ifctx->state == IF_DHCP_OFFERED &&
+		   ifctx->dhcpquerytype == DHCP_REQUEST)
+		ifctx->state = IF_DHCP_RESOLVED;
+	
+	
+	if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
+	    ifctx->state != IF_BOOTP_RESOLVED) {
+		p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
+			       ifctx->replylen, TAG_DHCP_SERVERID);
+		if (p != NULL && gctx->tmptag.taglen == 4) {
+			memcpy(&ifctx->dhcpserver, p, 4);
+			ifctx->gotdhcpserver = 1;
+		} else
+			ifctx->gotdhcpserver = 0;
+		return 1;
+	}
+	
 	ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
 					 ifctx->replylen,
 					 TAG_ROOT) != NULL);
@@ -488,6 +561,8 @@
 	struct bootpc_ifcontext *ifctx;
 	int outstanding;
 	int gotrootpath;
+	int retry;
+	const char *s;
 	
 	/*
 	 * Create socket and set its recieve timeout.
@@ -568,7 +643,8 @@
 		for (ifctx = gctx->interfaces;
 		     ifctx != NULL;
 		     ifctx = ifctx->next) {
-			if (ifctx->state == IF_BOOTP_RESOLVED &&
+			if ((ifctx->state == IF_BOOTP_RESOLVED ||
+			     ifctx->state == IF_DHCP_RESOLVED) &&
 			    bootpc_tag(&gctx->tmptag, &ifctx->reply,
 				       ifctx->replylen,
 				       TAG_ROOT) != NULL)
@@ -579,21 +655,47 @@
 		     ifctx != NULL;
 		     ifctx = ifctx->next) {
 			ifctx->outstanding = 0;
-			if (ifctx->state == IF_BOOTP_RESOLVED &&
+			if ((ifctx->state == IF_BOOTP_RESOLVED ||
+			     ifctx->state == IF_DHCP_RESOLVED) &&
 			    gotrootpath != 0) {
 				continue;
 			}
-			if (ifctx->state == IF_BOOTP_FAILED)
+			if (ifctx->state == IF_BOOTP_FAILED ||
+			    ifctx->state == IF_DHCP_FAILED)
 				continue;
 
 			outstanding++;
 			ifctx->outstanding = 1;
 
+			/* Proceed to next step in DHCP negotiation */
+			if ((ifctx->state == IF_DHCP_OFFERED &&
+			     ifctx->dhcpquerytype != DHCP_REQUEST) ||
+			    (ifctx->state == IF_DHCP_UNRESOLVED &&
+			     ifctx->dhcpquerytype != DHCP_DISCOVER) ||
+			    (ifctx->state == IF_BOOTP_UNRESOLVED &&
+			     ifctx->dhcpquerytype != DHCP_NOMSG)) {
+				ifctx->sentmsg = 0;
+				bootpc_compose_query(ifctx, gctx, procp);
+			}
+			
 			/* Send BOOTP request (or re-send). */
 		
 			if (ifctx->sentmsg == 0) {
-				printf("Sending BOOTP Query packet from "
+				switch(ifctx->dhcpquerytype) {
+				case DHCP_DISCOVER:
+					s = "DHCP Discover";
+					break;
+				case DHCP_REQUEST:
+					s = "DHCP Request";
+					break;
+				case DHCP_NOMSG:
+				default:
+					s = "BOOTP Query";
+					break;
+				}
+				printf("Sending %s packet from "
 				       "interface %s (%*D)\n",
+				       s,
 				       ifctx->ireq.ifr_name,
 				       ifctx->sdl->sdl_alen,
 				       (unsigned char *) LLADDR(ifctx->sdl),
@@ -657,7 +759,7 @@
 		if (timo < MAX_RESEND_DELAY)
 			timo++;
 		else {
-			printf("BOOTP timeout for server ");
+			printf("DHCP/BOOTP timeout for server ");
 			print_sin_addr(&dst);
 			printf("\n");
 		}
@@ -686,10 +788,12 @@
 			for (ifctx = gctx->interfaces;
 			     ifctx != NULL;
 			     ifctx = ifctx->next) {
-				if (ifctx->state == IF_BOOTP_RESOLVED)
-					continue;
-				if (ifctx->state == IF_BOOTP_FAILED)
+				if (ifctx->state == IF_BOOTP_RESOLVED ||
+				    ifctx->state == IF_BOOTP_FAILED ||
+				    ifctx->state == IF_DHCP_RESOLVED ||
+				    ifctx->state == IF_DHCP_FAILED)
 					continue;
+				
 				ifctx->call.secs = htons(gctx->secs);
 			}
 			if (error == EWOULDBLOCK)
@@ -728,8 +832,28 @@
 			}
 
 			if (ifctx != NULL) {
-				printf("Received BOOTP Reply packet"
+				s =  bootpc_tag(&gctx->tmptag,
+						&gctx->reply,
+						gctx->replylen,
+						TAG_DHCP_MSGTYPE);
+				if (s != NULL) {
+					switch (*s) {
+					case DHCP_OFFER:
+						s = "DHCP Offer";
+						break;
+					case DHCP_ACK:
+						s = "DHCP Ack";
+						break;
+					default:
+						s = "DHCP (unexcpected)";
+						break;
+					}
+				} else
+					s = "BOOTP Reply";
+
+				printf("Received %s packet"
 				       " on %s from ",
+				       s,
 				       ifctx->ireq.ifr_name);
 				print_in_addr(gctx->reply.siaddr);
 				if (gctx->reply.giaddr.s_addr !=
@@ -763,6 +887,21 @@
 		if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
 			break;
 #endif
+		/* Force a retry if halfway in DHCP negotiation */
+		retry = 0;
+		for (ifctx = gctx->interfaces; ifctx != NULL;
+		     ifctx = ifctx->next) {
+			if (ifctx->state == IF_DHCP_OFFERED) {
+				if (ifctx->dhcpquerytype == DHCP_DISCOVER)
+					retry = 1;
+				else
+					ifctx->state = IF_DHCP_UNRESOLVED;
+			}
+		}
+		
+		if (retry != 0)
+			continue;
+		
 		if (gotrootpath != 0) {
 			gctx->gotrootpath = gotrootpath;
 			if (rtimo != 0 && time_second >= rtimo)
@@ -776,8 +915,11 @@
 	 */
 
 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
-		if (ifctx->state != IF_BOOTP_RESOLVED) {
-			printf("BOOTP timeout for interface %s\n",
+		if (ifctx->state != IF_BOOTP_RESOLVED &&
+		    ifctx->state != IF_DHCP_RESOLVED) {
+			printf("%s timeout for interface %s\n",
+			       ifctx->dhcpquerytype != DHCP_NOMSG ?
+			       "DHCP" : "BOOTP",
 			       ifctx->ireq.ifr_name);
 		}
 	}
@@ -790,7 +932,8 @@
 	}
 #ifndef BOOTP_NFSROOT
 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
-		if (ifctx->state == IF_BOOTP_RESOLVED) {
+		if (ifctx->state == IF_BOOTP_RESOLVED ||
+		    ifctx->state == IF_DHCP_RESOLVED) {
 			error = 0;
 			goto out;
 		}
@@ -920,7 +1063,8 @@
 	netmask = &ifctx->netmask;
 	gw = &ifctx->gw;
 
-	if (ifctx->state != IF_BOOTP_RESOLVED) {
+	if (ifctx->state != IF_BOOTP_RESOLVED &&
+	    ifctx->state != IF_DHCP_RESOLVED) {
 
 		/* Shutdown interfaces where BOOTP failed */
 		
@@ -1161,12 +1305,11 @@
 	struct bootpc_globalcontext *gctx;
 	struct proc *procp;
 {
-	
-	gctx->gotrootpath = 0;
-	gctx->gotswappath = 0;
-	gctx->gotgw = 0;
+	unsigned char *vendp;
+	uint32_t leasetime;
+
 	ifctx->gotrootpath = 0;
-	
+
 	bzero((caddr_t) &ifctx->call, sizeof(ifctx->call));
 	
 	/* bootpc part */
@@ -1174,19 +1317,54 @@
 	ifctx->call.htype = 1;			/* 10mb ethernet */
 	ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */
 	ifctx->call.hops = 0;
-	ifctx->xid++;
+	if (ifctx->state == IF_DHCP_UNRESOLVED ||
+	    ifctx->state == IF_BOOTP_UNRESOLVED)
+		ifctx->xid++;
 	ifctx->call.xid = txdr_unsigned(ifctx->xid);
 	bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen);
 	
-	ifctx->call.vend[0] = 99;		/* RFC1048 cookie */
-	ifctx->call.vend[1] = 130;
-	ifctx->call.vend[2] = 83;
-	ifctx->call.vend[3] = 99;
-	ifctx->call.vend[4] = TAG_MAXMSGSIZE;
-	ifctx->call.vend[5] = 2;
-	ifctx->call.vend[6] = (sizeof(struct bootp_packet) >> 8) & 255;
-	ifctx->call.vend[7] = sizeof(struct bootp_packet) & 255;
-	ifctx->call.vend[8] = TAG_END;
+	vendp = ifctx->call.vend;
+	*vendp++ = 99;		/* RFC1048 cookie */
+	*vendp++ = 130;
+	*vendp++ = 83;
+	*vendp++ = 99;
+	*vendp++ = TAG_MAXMSGSIZE;
+	*vendp++ = 2;
+	*vendp++ = (sizeof(struct bootp_packet) >> 8) & 255;
+	*vendp++ = sizeof(struct bootp_packet) & 255;
+	ifctx->dhcpquerytype = DHCP_NOMSG;
+	switch (ifctx->state) {
+	case IF_DHCP_UNRESOLVED:
+		*vendp++ = TAG_DHCP_MSGTYPE;
+		*vendp++ = 1;
+		*vendp++ = DHCP_DISCOVER;
+		ifctx->dhcpquerytype = DHCP_DISCOVER;
+		ifctx->gotdhcpserver = 0;
+		break;
+	case IF_DHCP_OFFERED:
+		*vendp++ = TAG_DHCP_MSGTYPE;
+		*vendp++ = 1;
+		*vendp++ = DHCP_REQUEST;
+		ifctx->dhcpquerytype = DHCP_REQUEST;
+		*vendp++ = TAG_DHCP_REQ_ADDR;
+		*vendp++ = 4;
+		memcpy(vendp, &ifctx->reply.yiaddr, 4);
+		vendp += 4;
+		if (ifctx->gotdhcpserver != 0) {
+			*vendp++ = TAG_DHCP_SERVERID;
+			*vendp++ = 4;
+			memcpy(vendp, &ifctx->dhcpserver, 4);
+			vendp += 4;
+		}
+		*vendp++ = TAG_DHCP_LEASETIME;
+		*vendp++ = 4;
+		leasetime = htonl(300);
+		memcpy(vendp, &leasetime, 4);
+		vendp += 4;
+	default:
+		;
+	}
+	*vendp = TAG_END;
 	
 	ifctx->call.secs = 0;
 	ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */
@@ -1537,6 +1715,10 @@
 #endif
 	}
 		
+	gctx->gotrootpath = 0;
+	gctx->gotswappath = 0;
+	gctx->gotgw = 0;
+	
 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
 		bootpc_fakeup_interface(ifctx, gctx, procp);
 	
@@ -1559,7 +1741,8 @@
 	mountopts(&nd->swap_args, NULL);
 
 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
-		if (ifctx->state == IF_BOOTP_RESOLVED)
+		if (ifctx->state == IF_BOOTP_RESOLVED ||
+		    ifctx->state == IF_DHCP_RESOLVED)
 			bootpc_decode_reply(nd, ifctx, gctx);
 	
 	if (gctx->gotswappath == 0)
@@ -1582,7 +1765,8 @@
 		for (ifctx = gctx->interfaces;
 		     ifctx != NULL;
 		     ifctx = ifctx->next)
-			if (ifctx->state == IF_BOOTP_RESOLVED)
+			if (ifctx->state == IF_BOOTP_RESOLVED ||
+			    ifctx->state == IF_DHCP_RESOLVED)
 				break;
 	}
 	if (ifctx == NULL)

----Next_Part(Tue_Oct_31_22:09:58_2000)----


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010312110.WAA56137>