xref: /freebsd/sys/nfs/bootp_subr.c (revision 48855ec75316aaec5538ef22132f96fd04e137d4)
1 /*-
2  * Copyright (c) 1995 Gordon Ross, Adam Glass
3  * Copyright (c) 1992 Regents of the University of California.
4  * All rights reserved.
5  *
6  * This software was developed by the Computer Systems Engineering group
7  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8  * contributed to Berkeley.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Lawrence Berkeley Laboratory and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * based on:
39  *      nfs/krpc_subr.c
40  *	$NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
41  */
42 
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45 
46 #include "opt_bootp.h"
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/jail.h>
51 #include <sys/kernel.h>
52 #include <sys/sockio.h>
53 #include <sys/malloc.h>
54 #include <sys/mount.h>
55 #include <sys/mbuf.h>
56 #include <sys/proc.h>
57 #include <sys/socket.h>
58 #include <sys/socketvar.h>
59 #include <sys/sysctl.h>
60 #include <sys/uio.h>
61 
62 #include <net/if.h>
63 #include <net/route.h>
64 
65 #include <netinet/in.h>
66 #include <net/if_types.h>
67 #include <net/if_dl.h>
68 #include <net/vnet.h>
69 
70 #include <nfs/nfsproto.h>
71 #include <nfsclient/nfs.h>
72 #include <nfs/nfsdiskless.h>
73 #include <nfs/krpc.h>
74 #include <nfs/xdr_subs.h>
75 
76 
77 #define BOOTP_MIN_LEN		300	/* Minimum size of bootp udp packet */
78 
79 #ifndef BOOTP_SETTLE_DELAY
80 #define BOOTP_SETTLE_DELAY 3
81 #endif
82 
83 /*
84  * What is the longest we will wait before re-sending a request?
85  * Note this is also the frequency of "RPC timeout" messages.
86  * The re-send loop count sup linearly to this maximum, so the
87  * first complaint will happen after (1+2+3+4+5)=15 seconds.
88  */
89 #define	MAX_RESEND_DELAY 5	/* seconds */
90 
91 /* Definitions from RFC951 */
92 struct bootp_packet {
93 	u_int8_t op;
94 	u_int8_t htype;
95 	u_int8_t hlen;
96 	u_int8_t hops;
97 	u_int32_t xid;
98 	u_int16_t secs;
99 	u_int16_t flags;
100 	struct in_addr ciaddr;
101 	struct in_addr yiaddr;
102 	struct in_addr siaddr;
103 	struct in_addr giaddr;
104 	unsigned char chaddr[16];
105 	char sname[64];
106 	char file[128];
107 	unsigned char vend[1222];
108 };
109 
110 struct bootpc_ifcontext {
111 	struct bootpc_ifcontext *next;
112 	struct bootp_packet call;
113 	struct bootp_packet reply;
114 	int replylen;
115 	int overload;
116 	struct socket *so;
117 	struct ifreq ireq;
118 	struct ifnet *ifp;
119 	struct sockaddr_dl *sdl;
120 	struct sockaddr_in myaddr;
121 	struct sockaddr_in netmask;
122 	struct sockaddr_in gw;
123 	struct sockaddr_in broadcast;	/* Different for each interface */
124 	int gotgw;
125 	int gotnetmask;
126 	int gotrootpath;
127 	int outstanding;
128 	int sentmsg;
129 	u_int32_t xid;
130 	enum {
131 		IF_BOOTP_UNRESOLVED,
132 		IF_BOOTP_RESOLVED,
133 		IF_BOOTP_FAILED,
134 		IF_DHCP_UNRESOLVED,
135 		IF_DHCP_OFFERED,
136 		IF_DHCP_RESOLVED,
137 		IF_DHCP_FAILED,
138 	} state;
139 	int dhcpquerytype;		/* dhcp type sent */
140 	struct in_addr dhcpserver;
141 	int gotdhcpserver;
142 };
143 
144 #define TAG_MAXLEN 1024
145 struct bootpc_tagcontext {
146 	char buf[TAG_MAXLEN + 1];
147 	int overload;
148 	int badopt;
149 	int badtag;
150 	int foundopt;
151 	int taglen;
152 };
153 
154 struct bootpc_globalcontext {
155 	struct bootpc_ifcontext *interfaces;
156 	struct bootpc_ifcontext *lastinterface;
157 	u_int32_t xid;
158 	int gotrootpath;
159 	int gotgw;
160 	int ifnum;
161 	int secs;
162 	int starttime;
163 	struct bootp_packet reply;
164 	int replylen;
165 	struct bootpc_ifcontext *setrootfs;
166 	struct bootpc_ifcontext *sethostname;
167 	struct bootpc_tagcontext tmptag;
168 	struct bootpc_tagcontext tag;
169 };
170 
171 #define IPPORT_BOOTPC 68
172 #define IPPORT_BOOTPS 67
173 
174 #define BOOTP_REQUEST 1
175 #define BOOTP_REPLY 2
176 
177 /* Common tags */
178 #define TAG_PAD		  0  /* Pad option, implicit length 1 */
179 #define TAG_SUBNETMASK	  1  /* RFC 950 subnet mask */
180 #define TAG_ROUTERS	  3  /* Routers (in order of preference) */
181 #define TAG_HOSTNAME	 12  /* Client host name */
182 #define TAG_ROOT	 17  /* Root path */
183 
184 /* DHCP specific tags */
185 #define TAG_OVERLOAD	 52  /* Option Overload */
186 #define TAG_MAXMSGSIZE   57  /* Maximum DHCP Message Size */
187 
188 #define TAG_END		255  /* End Option (i.e. no more options) */
189 
190 /* Overload values */
191 #define OVERLOAD_FILE     1
192 #define OVERLOAD_SNAME    2
193 
194 /* Site specific tags: */
195 #define TAG_ROOTOPTS	130
196 #define TAG_COOKIE	134	/* ascii info for userland, via sysctl */
197 
198 #define TAG_DHCP_MSGTYPE 53
199 #define TAG_DHCP_REQ_ADDR 50
200 #define TAG_DHCP_SERVERID 54
201 #define TAG_DHCP_LEASETIME 51
202 
203 #define TAG_VENDOR_INDENTIFIER 60
204 
205 #define DHCP_NOMSG    0
206 #define DHCP_DISCOVER 1
207 #define DHCP_OFFER    2
208 #define DHCP_REQUEST  3
209 #define DHCP_ACK      5
210 
211 /* NFS read/write block size */
212 #ifndef BOOTP_BLOCKSIZE
213 #define	BOOTP_BLOCKSIZE	8192
214 #endif
215 
216 static char bootp_cookie[128];
217 SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
218 	bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
219 
220 /* mountd RPC */
221 static int	md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp,
222 		    int *fhsizep, struct nfs_args *args, struct thread *td);
223 static int	setfs(struct sockaddr_in *addr, char *path, char *p,
224 		    const struct in_addr *siaddr);
225 static int	getdec(char **ptr);
226 static int	getip(char **ptr, struct in_addr *ip);
227 static void	mountopts(struct nfs_args *args, char *p);
228 static int	xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
229 static int	xdr_int_decode(struct mbuf **ptr, int *iptr);
230 static void	print_in_addr(struct in_addr addr);
231 static void	print_sin_addr(struct sockaddr_in *addr);
232 static void	clear_sinaddr(struct sockaddr_in *sin);
233 static void	allocifctx(struct bootpc_globalcontext *gctx);
234 static void	bootpc_compose_query(struct bootpc_ifcontext *ifctx,
235 		    struct bootpc_globalcontext *gctx, struct thread *td);
236 static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
237 		    struct bootp_packet *bp, int len, int tag);
238 static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
239 		    unsigned char *start, int len, int tag);
240 
241 #ifdef BOOTP_DEBUG
242 void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma);
243 void bootpboot_p_rtentry(struct rtentry *rt);
244 void bootpboot_p_tree(struct radix_node *rn);
245 void bootpboot_p_rtlist(void);
246 void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
247 void bootpboot_p_iflist(void);
248 #endif
249 
250 static int	bootpc_call(struct bootpc_globalcontext *gctx,
251 		    struct thread *td);
252 
253 static int	bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
254 		    struct bootpc_globalcontext *gctx, struct thread *td);
255 
256 static int	bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
257 		    struct bootpc_globalcontext *gctx, struct thread *td);
258 
259 static void	bootpc_decode_reply(struct nfsv3_diskless *nd,
260 		    struct bootpc_ifcontext *ifctx,
261 		    struct bootpc_globalcontext *gctx);
262 
263 static int	bootpc_received(struct bootpc_globalcontext *gctx,
264 		    struct bootpc_ifcontext *ifctx);
265 
266 static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx);
267 static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx);
268 static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx);
269 
270 /*
271  * In order to have multiple active interfaces with address 0.0.0.0
272  * and be able to send data to a selected interface, we perform
273  * some tricks:
274  *
275  *  - The 'broadcast' address is different for each interface.
276  *
277  *  - We temporarily add routing pointing 255.255.255.255 to the
278  *    selected interface broadcast address, thus the packet sent
279  *    goes to that interface.
280  */
281 
282 #ifdef BOOTP_DEBUG
283 void
284 bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma)
285 {
286 
287 	if (sa == NULL) {
288 		printf("(sockaddr *) <null>");
289 		return;
290 	}
291 	switch (sa->sa_family) {
292 	case AF_INET:
293 	{
294 		struct sockaddr_in *sin;
295 
296 		sin = (struct sockaddr_in *) sa;
297 		printf("inet ");
298 		print_sin_addr(sin);
299 		if (ma != NULL) {
300 			sin = (struct sockaddr_in *) ma;
301 			printf(" mask ");
302 			print_sin_addr(sin);
303 		}
304 	}
305 	break;
306 	case AF_LINK:
307 	{
308 		struct sockaddr_dl *sli;
309 		int i;
310 
311 		sli = (struct sockaddr_dl *) sa;
312 		printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
313 		for (i = 0; i < sli->sdl_alen; i++) {
314 			if (i > 0)
315 				printf(":");
316 			printf("%x", ((unsigned char *) LLADDR(sli))[i]);
317 		}
318 	}
319 	break;
320 	default:
321 		printf("af%d", sa->sa_family);
322 	}
323 }
324 
325 void
326 bootpboot_p_rtentry(struct rtentry *rt)
327 {
328 
329 	bootpboot_p_sa(rt_key(rt), rt_mask(rt));
330 	printf(" ");
331 	bootpboot_p_sa(rt->rt_gateway, NULL);
332 	printf(" ");
333 	printf("flags %x", (unsigned short) rt->rt_flags);
334 	printf(" %d", (int) rt->rt_rmx.rmx_expire);
335 	printf(" %s\n", rt->rt_ifp->if_xname);
336 }
337 
338 void
339 bootpboot_p_tree(struct radix_node *rn)
340 {
341 
342 	while (rn != NULL) {
343 		if (rn->rn_bit < 0) {
344 			if ((rn->rn_flags & RNF_ROOT) != 0) {
345 			} else {
346 				bootpboot_p_rtentry((struct rtentry *) rn);
347 			}
348 			rn = rn->rn_dupedkey;
349 		} else {
350 			bootpboot_p_tree(rn->rn_left);
351 			bootpboot_p_tree(rn->rn_right);
352 			return;
353 		}
354 	}
355 }
356 
357 void
358 bootpboot_p_rtlist(void)
359 {
360 	struct radix_node_head *rnh;
361 
362 	printf("Routing table:\n");
363 	rnh = rt_tables_get_rnh(0, AF_INET);
364 	if (rnh == NULL)
365 		return;
366 	RADIX_NODE_HEAD_RLOCK(rnh);	/* could sleep XXX */
367 	bootpboot_p_tree(rnh->rnh_treetop);
368 	RADIX_NODE_HEAD_RUNLOCK(rnh);
369 }
370 
371 void
372 bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
373 {
374 
375 	printf("%s flags %x, addr ",
376 	       ifp->if_xname, ifp->if_flags);
377 	print_sin_addr((struct sockaddr_in *) ifa->ifa_addr);
378 	printf(", broadcast ");
379 	print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr);
380 	printf(", netmask ");
381 	print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask);
382 	printf("\n");
383 }
384 
385 void
386 bootpboot_p_iflist(void)
387 {
388 	struct ifnet *ifp;
389 	struct ifaddr *ifa;
390 
391 	printf("Interface list:\n");
392 	IFNET_RLOCK();
393 	for (ifp = TAILQ_FIRST(&V_ifnet);
394 	     ifp != NULL;
395 	     ifp = TAILQ_NEXT(ifp, if_link)) {
396 		for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
397 		     ifa != NULL;
398 		     ifa = TAILQ_NEXT(ifa, ifa_link))
399 			if (ifa->ifa_addr->sa_family == AF_INET)
400 				bootpboot_p_if(ifp, ifa);
401 	}
402 	IFNET_RUNLOCK();
403 }
404 #endif /* defined(BOOTP_DEBUG) */
405 
406 static void
407 clear_sinaddr(struct sockaddr_in *sin)
408 {
409 
410 	bzero(sin, sizeof(*sin));
411 	sin->sin_len = sizeof(*sin);
412 	sin->sin_family = AF_INET;
413 	sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */
414 	sin->sin_port = 0;
415 }
416 
417 static void
418 allocifctx(struct bootpc_globalcontext *gctx)
419 {
420 	struct bootpc_ifcontext *ifctx;
421 	ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx),
422 						   M_TEMP, M_WAITOK | M_ZERO);
423 	if (ifctx == NULL)
424 		panic("Failed to allocate bootp interface context structure");
425 
426 	ifctx->xid = gctx->xid;
427 #ifdef BOOTP_NO_DHCP
428 	ifctx->state = IF_BOOTP_UNRESOLVED;
429 #else
430 	ifctx->state = IF_DHCP_UNRESOLVED;
431 #endif
432 	gctx->xid += 0x100;
433 	if (gctx->interfaces != NULL)
434 		gctx->lastinterface->next = ifctx;
435 	else
436 		gctx->interfaces = ifctx;
437 	gctx->lastinterface = ifctx;
438 }
439 
440 static __inline int
441 bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx)
442 {
443 
444 	if (ifctx->state == IF_BOOTP_RESOLVED ||
445 	    ifctx->state == IF_DHCP_RESOLVED)
446 		return 1;
447 	return 0;
448 }
449 
450 static __inline int
451 bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx)
452 {
453 
454 	if (ifctx->state == IF_BOOTP_UNRESOLVED ||
455 	    ifctx->state == IF_DHCP_UNRESOLVED)
456 		return 1;
457 	return 0;
458 }
459 
460 static __inline int
461 bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx)
462 {
463 
464 	if (ifctx->state == IF_BOOTP_FAILED ||
465 	    ifctx->state == IF_DHCP_FAILED)
466 		return 1;
467 	return 0;
468 }
469 
470 static int
471 bootpc_received(struct bootpc_globalcontext *gctx,
472     struct bootpc_ifcontext *ifctx)
473 {
474 	unsigned char dhcpreplytype;
475 	char *p;
476 
477 	/*
478 	 * Need timeout for fallback to less
479 	 * desirable alternative.
480 	 */
481 
482 	/* This call used for the side effect (badopt flag) */
483 	(void) bootpc_tag(&gctx->tmptag, &gctx->reply,
484 			  gctx->replylen,
485 			  TAG_END);
486 
487 	/* If packet is invalid, ignore it */
488 	if (gctx->tmptag.badopt != 0)
489 		return 0;
490 
491 	p = bootpc_tag(&gctx->tmptag, &gctx->reply,
492 		       gctx->replylen, TAG_DHCP_MSGTYPE);
493 	if (p != NULL)
494 		dhcpreplytype = *p;
495 	else
496 		dhcpreplytype = DHCP_NOMSG;
497 
498 	switch (ifctx->dhcpquerytype) {
499 	case DHCP_DISCOVER:
500 		if (dhcpreplytype != DHCP_OFFER 	/* Normal DHCP offer */
501 #ifndef BOOTP_FORCE_DHCP
502 		    && dhcpreplytype != DHCP_NOMSG	/* Fallback to BOOTP */
503 #endif
504 			)
505 			return 0;
506 		break;
507 	case DHCP_REQUEST:
508 		if (dhcpreplytype != DHCP_ACK)
509 			return 0;
510 	case DHCP_NOMSG:
511 		break;
512 	}
513 
514 	/* Ignore packet unless it gives us a root tag we didn't have */
515 
516 	if ((ifctx->state == IF_BOOTP_RESOLVED ||
517 	     (ifctx->dhcpquerytype == DHCP_DISCOVER &&
518 	      (ifctx->state == IF_DHCP_OFFERED ||
519 	       ifctx->state == IF_DHCP_RESOLVED))) &&
520 	    (bootpc_tag(&gctx->tmptag, &ifctx->reply,
521 			ifctx->replylen,
522 			TAG_ROOT) != NULL ||
523 	     bootpc_tag(&gctx->tmptag, &gctx->reply,
524 			gctx->replylen,
525 			TAG_ROOT) == NULL))
526 		return 0;
527 
528 	bcopy(&gctx->reply, &ifctx->reply, gctx->replylen);
529 	ifctx->replylen = gctx->replylen;
530 
531 	/* XXX: Only reset if 'perfect' response */
532 	if (ifctx->state == IF_BOOTP_UNRESOLVED)
533 		ifctx->state = IF_BOOTP_RESOLVED;
534 	else if (ifctx->state == IF_DHCP_UNRESOLVED &&
535 		 ifctx->dhcpquerytype == DHCP_DISCOVER) {
536 		if (dhcpreplytype == DHCP_OFFER)
537 			ifctx->state = IF_DHCP_OFFERED;
538 		else
539 			ifctx->state = IF_BOOTP_RESOLVED;	/* Fallback */
540 	} else if (ifctx->state == IF_DHCP_OFFERED &&
541 		   ifctx->dhcpquerytype == DHCP_REQUEST)
542 		ifctx->state = IF_DHCP_RESOLVED;
543 
544 
545 	if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
546 	    ifctx->state != IF_BOOTP_RESOLVED) {
547 		p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
548 			       ifctx->replylen, TAG_DHCP_SERVERID);
549 		if (p != NULL && gctx->tmptag.taglen == 4) {
550 			memcpy(&ifctx->dhcpserver, p, 4);
551 			ifctx->gotdhcpserver = 1;
552 		} else
553 			ifctx->gotdhcpserver = 0;
554 		return 1;
555 	}
556 
557 	ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
558 					 ifctx->replylen,
559 					 TAG_ROOT) != NULL);
560 	ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
561 				   ifctx->replylen,
562 				   TAG_ROUTERS) != NULL);
563 	ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
564 					ifctx->replylen,
565 					TAG_SUBNETMASK) != NULL);
566 	return 1;
567 }
568 
569 static int
570 bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
571 {
572 	struct socket *so;
573 	struct sockaddr_in *sin, dst;
574 	struct uio auio;
575 	struct sockopt sopt;
576 	struct iovec aio;
577 	int error, on, rcvflg, timo, len;
578 	time_t atimo;
579 	time_t rtimo;
580 	struct timeval tv;
581 	struct bootpc_ifcontext *ifctx;
582 	int outstanding;
583 	int gotrootpath;
584 	int retry;
585 	const char *s;
586 
587 	/*
588 	 * Create socket and set its recieve timeout.
589 	 */
590 	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td);
591 	if (error != 0)
592 		goto out0;
593 
594 	tv.tv_sec = 1;
595 	tv.tv_usec = 0;
596 	bzero(&sopt, sizeof(sopt));
597 	sopt.sopt_dir = SOPT_SET;
598 	sopt.sopt_level = SOL_SOCKET;
599 	sopt.sopt_name = SO_RCVTIMEO;
600 	sopt.sopt_val = &tv;
601 	sopt.sopt_valsize = sizeof tv;
602 
603 	error = sosetopt(so, &sopt);
604 	if (error != 0)
605 		goto out;
606 
607 	/*
608 	 * Enable broadcast.
609 	 */
610 	on = 1;
611 	sopt.sopt_name = SO_BROADCAST;
612 	sopt.sopt_val = &on;
613 	sopt.sopt_valsize = sizeof on;
614 
615 	error = sosetopt(so, &sopt);
616 	if (error != 0)
617 		goto out;
618 
619 	/*
620 	 * Disable routing.
621 	 */
622 
623 	on = 1;
624 	sopt.sopt_name = SO_DONTROUTE;
625 	sopt.sopt_val = &on;
626 	sopt.sopt_valsize = sizeof on;
627 
628 	error = sosetopt(so, &sopt);
629 	if (error != 0)
630 		goto out;
631 
632 	/*
633 	 * Bind the local endpoint to a bootp client port.
634 	 */
635 	sin = &dst;
636 	clear_sinaddr(sin);
637 	sin->sin_port = htons(IPPORT_BOOTPC);
638 	error = sobind(so, (struct sockaddr *)sin, td);
639 	if (error != 0) {
640 		printf("bind failed\n");
641 		goto out;
642 	}
643 
644 	/*
645 	 * Setup socket address for the server.
646 	 */
647 	sin = &dst;
648 	clear_sinaddr(sin);
649 	sin->sin_addr.s_addr = INADDR_BROADCAST;
650 	sin->sin_port = htons(IPPORT_BOOTPS);
651 
652 	/*
653 	 * Send it, repeatedly, until a reply is received,
654 	 * but delay each re-send by an increasing amount.
655 	 * If the delay hits the maximum, start complaining.
656 	 */
657 	timo = 0;
658 	rtimo = 0;
659 	for (;;) {
660 
661 		outstanding = 0;
662 		gotrootpath = 0;
663 
664 		for (ifctx = gctx->interfaces;
665 		     ifctx != NULL;
666 		     ifctx = ifctx->next) {
667 			if (bootpc_ifctx_isresolved(ifctx) != 0 &&
668 			    bootpc_tag(&gctx->tmptag, &ifctx->reply,
669 				       ifctx->replylen,
670 				       TAG_ROOT) != NULL)
671 				gotrootpath = 1;
672 		}
673 
674 		for (ifctx = gctx->interfaces;
675 		     ifctx != NULL;
676 		     ifctx = ifctx->next) {
677 			ifctx->outstanding = 0;
678 			if (bootpc_ifctx_isresolved(ifctx)  != 0 &&
679 			    gotrootpath != 0) {
680 				continue;
681 			}
682 			if (bootpc_ifctx_isfailed(ifctx) != 0)
683 				continue;
684 
685 			outstanding++;
686 			ifctx->outstanding = 1;
687 
688 			/* Proceed to next step in DHCP negotiation */
689 			if ((ifctx->state == IF_DHCP_OFFERED &&
690 			     ifctx->dhcpquerytype != DHCP_REQUEST) ||
691 			    (ifctx->state == IF_DHCP_UNRESOLVED &&
692 			     ifctx->dhcpquerytype != DHCP_DISCOVER) ||
693 			    (ifctx->state == IF_BOOTP_UNRESOLVED &&
694 			     ifctx->dhcpquerytype != DHCP_NOMSG)) {
695 				ifctx->sentmsg = 0;
696 				bootpc_compose_query(ifctx, gctx, td);
697 			}
698 
699 			/* Send BOOTP request (or re-send). */
700 
701 			if (ifctx->sentmsg == 0) {
702 				switch(ifctx->dhcpquerytype) {
703 				case DHCP_DISCOVER:
704 					s = "DHCP Discover";
705 					break;
706 				case DHCP_REQUEST:
707 					s = "DHCP Request";
708 					break;
709 				case DHCP_NOMSG:
710 				default:
711 					s = "BOOTP Query";
712 					break;
713 				}
714 				printf("Sending %s packet from "
715 				       "interface %s (%*D)\n",
716 				       s,
717 				       ifctx->ireq.ifr_name,
718 				       ifctx->sdl->sdl_alen,
719 				       (unsigned char *) LLADDR(ifctx->sdl),
720 				       ":");
721 				ifctx->sentmsg = 1;
722 			}
723 
724 			aio.iov_base = (caddr_t) &ifctx->call;
725 			aio.iov_len = sizeof(ifctx->call);
726 
727 			auio.uio_iov = &aio;
728 			auio.uio_iovcnt = 1;
729 			auio.uio_segflg = UIO_SYSSPACE;
730 			auio.uio_rw = UIO_WRITE;
731 			auio.uio_offset = 0;
732 			auio.uio_resid = sizeof(ifctx->call);
733 			auio.uio_td = td;
734 
735 			/* Set netmask to 0.0.0.0 */
736 
737 			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
738 			clear_sinaddr(sin);
739 			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
740 					(caddr_t) &ifctx->ireq, td);
741 			if (error != 0)
742 				panic("bootpc_call:"
743 				      "set if netmask, error=%d",
744 				      error);
745 
746 			error = sosend(so, (struct sockaddr *) &dst,
747 				       &auio, NULL, NULL, 0, td);
748 			if (error != 0) {
749 				printf("bootpc_call: sosend: %d state %08x\n",
750 				       error, (int) so->so_state);
751 			}
752 
753 			/* XXX: Is this needed ? */
754 			pause("bootpw", hz/10);
755 
756 			/* Set netmask to 255.0.0.0 */
757 
758 			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
759 			clear_sinaddr(sin);
760 			sin->sin_addr.s_addr = htonl(0xff000000u);
761 			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
762 					(caddr_t) &ifctx->ireq, td);
763 			if (error != 0)
764 				panic("bootpc_call:"
765 				      "set if netmask, error=%d",
766 				      error);
767 
768 		}
769 
770 		if (outstanding == 0 &&
771 		    (rtimo == 0 || time_second >= rtimo)) {
772 			error = 0;
773 			goto gotreply;
774 		}
775 
776 		/* Determine new timeout. */
777 		if (timo < MAX_RESEND_DELAY)
778 			timo++;
779 		else {
780 			printf("DHCP/BOOTP timeout for server ");
781 			print_sin_addr(&dst);
782 			printf("\n");
783 		}
784 
785 		/*
786 		 * Wait for up to timo seconds for a reply.
787 		 * The socket receive timeout was set to 1 second.
788 		 */
789 		atimo = timo + time_second;
790 		while (time_second < atimo) {
791 			aio.iov_base = (caddr_t) &gctx->reply;
792 			aio.iov_len = sizeof(gctx->reply);
793 
794 			auio.uio_iov = &aio;
795 			auio.uio_iovcnt = 1;
796 			auio.uio_segflg = UIO_SYSSPACE;
797 			auio.uio_rw = UIO_READ;
798 			auio.uio_offset = 0;
799 			auio.uio_resid = sizeof(gctx->reply);
800 			auio.uio_td = td;
801 
802 			rcvflg = 0;
803 			error = soreceive(so, NULL, &auio,
804 					  NULL, NULL, &rcvflg);
805 			gctx->secs = time_second - gctx->starttime;
806 			for (ifctx = gctx->interfaces;
807 			     ifctx != NULL;
808 			     ifctx = ifctx->next) {
809 				if (bootpc_ifctx_isresolved(ifctx) != 0 ||
810 				    bootpc_ifctx_isfailed(ifctx) != 0)
811 					continue;
812 
813 				ifctx->call.secs = htons(gctx->secs);
814 			}
815 			if (error == EWOULDBLOCK)
816 				continue;
817 			if (error != 0)
818 				goto out;
819 			len = sizeof(gctx->reply) - auio.uio_resid;
820 
821 			/* Do we have the required number of bytes ? */
822 			if (len < BOOTP_MIN_LEN)
823 				continue;
824 			gctx->replylen = len;
825 
826 			/* Is it a reply? */
827 			if (gctx->reply.op != BOOTP_REPLY)
828 				continue;
829 
830 			/* Is this an answer to our query */
831 			for (ifctx = gctx->interfaces;
832 			     ifctx != NULL;
833 			     ifctx = ifctx->next) {
834 				if (gctx->reply.xid != ifctx->call.xid)
835 					continue;
836 
837 				/* Same HW address size ? */
838 				if (gctx->reply.hlen != ifctx->call.hlen)
839 					continue;
840 
841 				/* Correct HW address ? */
842 				if (bcmp(gctx->reply.chaddr,
843 					 ifctx->call.chaddr,
844 					 ifctx->call.hlen) != 0)
845 					continue;
846 
847 				break;
848 			}
849 
850 			if (ifctx != NULL) {
851 				s =  bootpc_tag(&gctx->tmptag,
852 						&gctx->reply,
853 						gctx->replylen,
854 						TAG_DHCP_MSGTYPE);
855 				if (s != NULL) {
856 					switch (*s) {
857 					case DHCP_OFFER:
858 						s = "DHCP Offer";
859 						break;
860 					case DHCP_ACK:
861 						s = "DHCP Ack";
862 						break;
863 					default:
864 						s = "DHCP (unexpected)";
865 						break;
866 					}
867 				} else
868 					s = "BOOTP Reply";
869 
870 				printf("Received %s packet"
871 				       " on %s from ",
872 				       s,
873 				       ifctx->ireq.ifr_name);
874 				print_in_addr(gctx->reply.siaddr);
875 				if (gctx->reply.giaddr.s_addr !=
876 				    htonl(INADDR_ANY)) {
877 					printf(" via ");
878 					print_in_addr(gctx->reply.giaddr);
879 				}
880 				if (bootpc_received(gctx, ifctx) != 0) {
881 					printf(" (accepted)");
882 					if (ifctx->outstanding) {
883 						ifctx->outstanding = 0;
884 						outstanding--;
885 					}
886 					/* Network settle delay */
887 					if (outstanding == 0)
888 						atimo = time_second +
889 							BOOTP_SETTLE_DELAY;
890 				} else
891 					printf(" (ignored)");
892 				if (ifctx->gotrootpath) {
893 					gotrootpath = 1;
894 					rtimo = time_second +
895 						BOOTP_SETTLE_DELAY;
896 					printf(" (got root path)");
897 				} else
898 					printf(" (no root path)");
899 				printf("\n");
900 			}
901 		} /* while secs */
902 #ifdef BOOTP_TIMEOUT
903 		if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
904 			break;
905 #endif
906 		/* Force a retry if halfway in DHCP negotiation */
907 		retry = 0;
908 		for (ifctx = gctx->interfaces; ifctx != NULL;
909 		     ifctx = ifctx->next) {
910 			if (ifctx->state == IF_DHCP_OFFERED) {
911 				if (ifctx->dhcpquerytype == DHCP_DISCOVER)
912 					retry = 1;
913 				else
914 					ifctx->state = IF_DHCP_UNRESOLVED;
915 			}
916 		}
917 
918 		if (retry != 0)
919 			continue;
920 
921 		if (gotrootpath != 0) {
922 			gctx->gotrootpath = gotrootpath;
923 			if (rtimo != 0 && time_second >= rtimo)
924 				break;
925 		}
926 	} /* forever send/receive */
927 
928 	/*
929 	 * XXX: These are errors of varying seriousness being silently
930 	 * ignored
931 	 */
932 
933 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
934 		if (bootpc_ifctx_isresolved(ifctx) == 0) {
935 			printf("%s timeout for interface %s\n",
936 			       ifctx->dhcpquerytype != DHCP_NOMSG ?
937 			       "DHCP" : "BOOTP",
938 			       ifctx->ireq.ifr_name);
939 		}
940 	}
941 	if (gctx->gotrootpath != 0) {
942 #if 0
943 		printf("Got a root path, ignoring remaining timeout\n");
944 #endif
945 		error = 0;
946 		goto out;
947 	}
948 #ifndef BOOTP_NFSROOT
949 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
950 		if (bootpc_ifctx_isresolved(ifctx) != 0) {
951 			error = 0;
952 			goto out;
953 		}
954 	}
955 #endif
956 	error = ETIMEDOUT;
957 	goto out;
958 
959 gotreply:
960 out:
961 	soclose(so);
962 out0:
963 	return error;
964 }
965 
966 static int
967 bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
968     struct bootpc_globalcontext *gctx, struct thread *td)
969 {
970 	struct sockaddr_in *sin;
971 	int error;
972 	struct ifreq *ireq;
973 	struct socket *so;
974 	struct ifaddr *ifa;
975 	struct sockaddr_dl *sdl;
976 
977 	error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td);
978 	if (error != 0)
979 		panic("nfs_boot: socreate, error=%d", error);
980 
981 	ireq = &ifctx->ireq;
982 	so = ifctx->so;
983 
984 	/*
985 	 * Bring up the interface.
986 	 *
987 	 * Get the old interface flags and or IFF_UP into them; if
988 	 * IFF_UP set blindly, interface selection can be clobbered.
989 	 */
990 	error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
991 	if (error != 0)
992 		panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
993 	ireq->ifr_flags |= IFF_UP;
994 	error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
995 	if (error != 0)
996 		panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
997 
998 	/*
999 	 * Do enough of ifconfig(8) so that the chosen interface
1000 	 * can talk to the servers.  (just set the address)
1001 	 */
1002 
1003 	/* addr is 0.0.0.0 */
1004 
1005 	sin = (struct sockaddr_in *) &ireq->ifr_addr;
1006 	clear_sinaddr(sin);
1007 	error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
1008 	if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
1009 		panic("bootpc_fakeup_interface: "
1010 		      "set if addr, error=%d", error);
1011 
1012 	/* netmask is 255.0.0.0 */
1013 
1014 	sin = (struct sockaddr_in *) &ireq->ifr_addr;
1015 	clear_sinaddr(sin);
1016 	sin->sin_addr.s_addr = htonl(0xff000000u);
1017 	error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td);
1018 	if (error != 0)
1019 		panic("bootpc_fakeup_interface: set if netmask, error=%d",
1020 		      error);
1021 
1022 	/* Broadcast is 255.255.255.255 */
1023 
1024 	sin = (struct sockaddr_in *)&ireq->ifr_addr;
1025 	clear_sinaddr(sin);
1026 	clear_sinaddr(&ifctx->broadcast);
1027 	sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
1028 	ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr;
1029 
1030 	error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td);
1031 	if (error != 0)
1032 		panic("bootpc_fakeup_interface: "
1033 		      "set if broadcast addr, error=%d",
1034 		      error);
1035 
1036 	/* Get HW address */
1037 
1038 	sdl = NULL;
1039 	TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link)
1040 		if (ifa->ifa_addr->sa_family == AF_LINK) {
1041 			sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1042 			if (sdl->sdl_type == IFT_ETHER)
1043 				break;
1044 		}
1045 
1046 	if (sdl == NULL)
1047 		panic("bootpc: Unable to find HW address for %s",
1048 		      ifctx->ireq.ifr_name);
1049 	ifctx->sdl = sdl;
1050 
1051 	return error;
1052 }
1053 
1054 
1055 static int
1056 bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
1057     struct bootpc_globalcontext *gctx, struct thread *td)
1058 {
1059 	int error;
1060 	struct sockaddr_in defdst;
1061 	struct sockaddr_in defmask;
1062 	struct sockaddr_in *sin;
1063 	struct ifreq *ireq;
1064 	struct socket *so;
1065 	struct sockaddr_in *myaddr;
1066 	struct sockaddr_in *netmask;
1067 	struct sockaddr_in *gw;
1068 
1069 	ireq = &ifctx->ireq;
1070 	so = ifctx->so;
1071 	myaddr = &ifctx->myaddr;
1072 	netmask = &ifctx->netmask;
1073 	gw = &ifctx->gw;
1074 
1075 	if (bootpc_ifctx_isresolved(ifctx) == 0) {
1076 
1077 		/* Shutdown interfaces where BOOTP failed */
1078 
1079 		printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
1080 		error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
1081 		if (error != 0)
1082 			panic("bootpc_adjust_interface: "
1083 			      "SIOCGIFFLAGS, error=%d", error);
1084 		ireq->ifr_flags &= ~IFF_UP;
1085 		error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
1086 		if (error != 0)
1087 			panic("bootpc_adjust_interface: "
1088 			      "SIOCSIFFLAGS, error=%d", error);
1089 
1090 		sin = (struct sockaddr_in *) &ireq->ifr_addr;
1091 		clear_sinaddr(sin);
1092 		error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td);
1093 		if (error != 0 && (error != EEXIST ||
1094 				   ifctx == gctx->interfaces))
1095 			panic("bootpc_adjust_interface: "
1096 			      "SIOCDIFADDR, error=%d", error);
1097 
1098 		return 0;
1099 	}
1100 
1101 	printf("Adjusted interface %s\n", ifctx->ireq.ifr_name);
1102 	/*
1103 	 * Do enough of ifconfig(8) so that the chosen interface
1104 	 * can talk to the servers.  (just set the address)
1105 	 */
1106 	bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask));
1107 	error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td);
1108 	if (error != 0)
1109 		panic("bootpc_adjust_interface: "
1110 		      "set if netmask, error=%d", error);
1111 
1112 	/* Broadcast is with host part of IP address all 1's */
1113 
1114 	sin = (struct sockaddr_in *) &ireq->ifr_addr;
1115 	clear_sinaddr(sin);
1116 	sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
1117 		~ netmask->sin_addr.s_addr;
1118 	error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td);
1119 	if (error != 0)
1120 		panic("bootpc_adjust_interface: "
1121 		      "set if broadcast addr, error=%d", error);
1122 
1123 	bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
1124 	error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
1125 	if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
1126 		panic("bootpc_adjust_interface: "
1127 		      "set if addr, error=%d", error);
1128 
1129 	/* Add new default route */
1130 
1131 	if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
1132 		clear_sinaddr(&defdst);
1133 		clear_sinaddr(&defmask);
1134 		/* XXX MRT just table 0 */
1135 		error = rtrequest_fib(RTM_ADD,
1136 				  (struct sockaddr *) &defdst,
1137 				  (struct sockaddr *) gw,
1138 				  (struct sockaddr *) &defmask,
1139 				  (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0);
1140 		if (error != 0) {
1141 			printf("bootpc_adjust_interface: "
1142 			       "add net route, error=%d\n", error);
1143 			return error;
1144 		}
1145 	}
1146 
1147 	return 0;
1148 }
1149 
1150 static int
1151 setfs(struct sockaddr_in *addr, char *path, char *p,
1152     const struct in_addr *siaddr)
1153 {
1154 
1155 	if (getip(&p, &addr->sin_addr) == 0) {
1156 		if (siaddr != NULL && *p == '/')
1157 			bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr));
1158 		else
1159 			return 0;
1160 	} else {
1161 		if (*p != ':')
1162 			return 0;
1163 		p++;
1164 	}
1165 
1166 	addr->sin_len = sizeof(struct sockaddr_in);
1167 	addr->sin_family = AF_INET;
1168 
1169 	strlcpy(path, p, MNAMELEN);
1170 	return 1;
1171 }
1172 
1173 static int
1174 getip(char **ptr, struct in_addr *addr)
1175 {
1176 	char *p;
1177 	unsigned int ip;
1178 	int val;
1179 
1180 	p = *ptr;
1181 	ip = 0;
1182 	if (((val = getdec(&p)) < 0) || (val > 255))
1183 		return 0;
1184 	ip = val << 24;
1185 	if (*p != '.')
1186 		return 0;
1187 	p++;
1188 	if (((val = getdec(&p)) < 0) || (val > 255))
1189 		return 0;
1190 	ip |= (val << 16);
1191 	if (*p != '.')
1192 		return 0;
1193 	p++;
1194 	if (((val = getdec(&p)) < 0) || (val > 255))
1195 		return 0;
1196 	ip |= (val << 8);
1197 	if (*p != '.')
1198 		return 0;
1199 	p++;
1200 	if (((val = getdec(&p)) < 0) || (val > 255))
1201 		return 0;
1202 	ip |= val;
1203 
1204 	addr->s_addr = htonl(ip);
1205 	*ptr = p;
1206 	return 1;
1207 }
1208 
1209 static int
1210 getdec(char **ptr)
1211 {
1212 	char *p;
1213 	int ret;
1214 
1215 	p = *ptr;
1216 	ret = 0;
1217 	if ((*p < '0') || (*p > '9'))
1218 		return -1;
1219 	while ((*p >= '0') && (*p <= '9')) {
1220 		ret = ret * 10 + (*p - '0');
1221 		p++;
1222 	}
1223 	*ptr = p;
1224 	return ret;
1225 }
1226 
1227 static void
1228 mountopts(struct nfs_args *args, char *p)
1229 {
1230 	args->version = NFS_ARGSVERSION;
1231 	args->rsize = BOOTP_BLOCKSIZE;
1232 	args->wsize = BOOTP_BLOCKSIZE;
1233 	args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
1234 	args->sotype = SOCK_DGRAM;
1235 	if (p != NULL)
1236 		nfs_parse_options(p, args);
1237 }
1238 
1239 static int
1240 xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
1241 {
1242 	struct mbuf *m;
1243 	int alignedlen;
1244 
1245 	m = *mptr;
1246 	alignedlen = ( len + 3 ) & ~3;
1247 
1248 	if (m->m_len < alignedlen) {
1249 		m = m_pullup(m, alignedlen);
1250 		if (m == NULL) {
1251 			*mptr = NULL;
1252 			return EBADRPC;
1253 		}
1254 	}
1255 	bcopy(mtod(m, u_char *), buf, len);
1256 	m_adj(m, alignedlen);
1257 	*mptr = m;
1258 	return 0;
1259 }
1260 
1261 static int
1262 xdr_int_decode(struct mbuf **mptr, int *iptr)
1263 {
1264 	u_int32_t i;
1265 
1266 	if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
1267 		return EBADRPC;
1268 	*iptr = fxdr_unsigned(u_int32_t, i);
1269 	return 0;
1270 }
1271 
1272 static void
1273 print_sin_addr(struct sockaddr_in *sin)
1274 {
1275 
1276 	print_in_addr(sin->sin_addr);
1277 }
1278 
1279 static void
1280 print_in_addr(struct in_addr addr)
1281 {
1282 	unsigned int ip;
1283 
1284 	ip = ntohl(addr.s_addr);
1285 	printf("%d.%d.%d.%d",
1286 	       ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
1287 }
1288 
1289 static void
1290 bootpc_compose_query(struct bootpc_ifcontext *ifctx,
1291     struct bootpc_globalcontext *gctx, struct thread *td)
1292 {
1293 	unsigned char *vendp;
1294 	unsigned char vendor_client[64];
1295 	uint32_t leasetime;
1296 	uint8_t vendor_client_len;
1297 
1298 	ifctx->gotrootpath = 0;
1299 
1300 	bzero((caddr_t) &ifctx->call, sizeof(ifctx->call));
1301 
1302 	/* bootpc part */
1303 	ifctx->call.op = BOOTP_REQUEST; 	/* BOOTREQUEST */
1304 	ifctx->call.htype = 1;			/* 10mb ethernet */
1305 	ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */
1306 	ifctx->call.hops = 0;
1307 	if (bootpc_ifctx_isunresolved(ifctx) != 0)
1308 		ifctx->xid++;
1309 	ifctx->call.xid = txdr_unsigned(ifctx->xid);
1310 	bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen);
1311 
1312 	vendp = ifctx->call.vend;
1313 	*vendp++ = 99;		/* RFC1048 cookie */
1314 	*vendp++ = 130;
1315 	*vendp++ = 83;
1316 	*vendp++ = 99;
1317 	*vendp++ = TAG_MAXMSGSIZE;
1318 	*vendp++ = 2;
1319 	*vendp++ = (sizeof(struct bootp_packet) >> 8) & 255;
1320 	*vendp++ = sizeof(struct bootp_packet) & 255;
1321 
1322 	snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s",
1323 		ostype, MACHINE, osrelease);
1324 	vendor_client_len = strlen(vendor_client);
1325 	*vendp++ = TAG_VENDOR_INDENTIFIER;
1326 	*vendp++ = vendor_client_len;
1327 	memcpy(vendp, vendor_client, vendor_client_len);
1328 	vendp += vendor_client_len;
1329 	ifctx->dhcpquerytype = DHCP_NOMSG;
1330 	switch (ifctx->state) {
1331 	case IF_DHCP_UNRESOLVED:
1332 		*vendp++ = TAG_DHCP_MSGTYPE;
1333 		*vendp++ = 1;
1334 		*vendp++ = DHCP_DISCOVER;
1335 		ifctx->dhcpquerytype = DHCP_DISCOVER;
1336 		ifctx->gotdhcpserver = 0;
1337 		break;
1338 	case IF_DHCP_OFFERED:
1339 		*vendp++ = TAG_DHCP_MSGTYPE;
1340 		*vendp++ = 1;
1341 		*vendp++ = DHCP_REQUEST;
1342 		ifctx->dhcpquerytype = DHCP_REQUEST;
1343 		*vendp++ = TAG_DHCP_REQ_ADDR;
1344 		*vendp++ = 4;
1345 		memcpy(vendp, &ifctx->reply.yiaddr, 4);
1346 		vendp += 4;
1347 		if (ifctx->gotdhcpserver != 0) {
1348 			*vendp++ = TAG_DHCP_SERVERID;
1349 			*vendp++ = 4;
1350 			memcpy(vendp, &ifctx->dhcpserver, 4);
1351 			vendp += 4;
1352 		}
1353 		*vendp++ = TAG_DHCP_LEASETIME;
1354 		*vendp++ = 4;
1355 		leasetime = htonl(300);
1356 		memcpy(vendp, &leasetime, 4);
1357 		vendp += 4;
1358 		break;
1359 	default:
1360 		break;
1361 	}
1362 	*vendp = TAG_END;
1363 
1364 	ifctx->call.secs = 0;
1365 	ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */
1366 }
1367 
1368 static int
1369 bootpc_hascookie(struct bootp_packet *bp)
1370 {
1371 
1372 	return (bp->vend[0] == 99 && bp->vend[1] == 130 &&
1373 		bp->vend[2] == 83 && bp->vend[3] == 99);
1374 }
1375 
1376 static void
1377 bootpc_tag_helper(struct bootpc_tagcontext *tctx,
1378     unsigned char *start, int len, int tag)
1379 {
1380 	unsigned char *j;
1381 	unsigned char *ej;
1382 	unsigned char code;
1383 
1384 	if (tctx->badtag != 0 || tctx->badopt != 0)
1385 		return;
1386 
1387 	j = start;
1388 	ej = j + len;
1389 
1390 	while (j < ej) {
1391 		code = *j++;
1392 		if (code == TAG_PAD)
1393 			continue;
1394 		if (code == TAG_END)
1395 			return;
1396 		if (j >= ej || j + *j + 1 > ej) {
1397 			tctx->badopt = 1;
1398 			return;
1399 		}
1400 		len = *j++;
1401 		if (code == tag) {
1402 			if (tctx->taglen + len > TAG_MAXLEN) {
1403 				tctx->badtag = 1;
1404 				return;
1405 			}
1406 			tctx->foundopt = 1;
1407 			if (len > 0)
1408 				memcpy(tctx->buf + tctx->taglen,
1409 				       j, len);
1410 			tctx->taglen += len;
1411 		}
1412 		if (code == TAG_OVERLOAD)
1413 			tctx->overload = *j;
1414 
1415 		j += len;
1416 	}
1417 }
1418 
1419 static unsigned char *
1420 bootpc_tag(struct bootpc_tagcontext *tctx,
1421     struct bootp_packet *bp, int len, int tag)
1422 {
1423 	tctx->overload = 0;
1424 	tctx->badopt = 0;
1425 	tctx->badtag = 0;
1426 	tctx->foundopt = 0;
1427 	tctx->taglen = 0;
1428 
1429 	if (bootpc_hascookie(bp) == 0)
1430 		return NULL;
1431 
1432 	bootpc_tag_helper(tctx, &bp->vend[4],
1433 			  (unsigned char *) bp + len - &bp->vend[4], tag);
1434 
1435 	if ((tctx->overload & OVERLOAD_FILE) != 0)
1436 		bootpc_tag_helper(tctx,
1437 				  (unsigned char *) bp->file,
1438 				  sizeof(bp->file),
1439 				  tag);
1440 	if ((tctx->overload & OVERLOAD_SNAME) != 0)
1441 		bootpc_tag_helper(tctx,
1442 				  (unsigned char *) bp->sname,
1443 				  sizeof(bp->sname),
1444 				  tag);
1445 
1446 	if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0)
1447 		return NULL;
1448 	tctx->buf[tctx->taglen] = '\0';
1449 	return tctx->buf;
1450 }
1451 
1452 static void
1453 bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
1454     struct bootpc_globalcontext *gctx)
1455 {
1456 	char *p;
1457 	unsigned int ip;
1458 
1459 	ifctx->gotgw = 0;
1460 	ifctx->gotnetmask = 0;
1461 
1462 	clear_sinaddr(&ifctx->myaddr);
1463 	clear_sinaddr(&ifctx->netmask);
1464 	clear_sinaddr(&ifctx->gw);
1465 
1466 	ifctx->myaddr.sin_addr = ifctx->reply.yiaddr;
1467 
1468 	ip = ntohl(ifctx->myaddr.sin_addr.s_addr);
1469 
1470 	printf("%s at ", ifctx->ireq.ifr_name);
1471 	print_sin_addr(&ifctx->myaddr);
1472 	printf(" server ");
1473 	print_in_addr(ifctx->reply.siaddr);
1474 
1475 	ifctx->gw.sin_addr = ifctx->reply.giaddr;
1476 	if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) {
1477 		printf(" via gateway ");
1478 		print_in_addr(ifctx->reply.giaddr);
1479 	}
1480 
1481 	/* This call used for the side effect (overload flag) */
1482 	(void) bootpc_tag(&gctx->tmptag,
1483 			  &ifctx->reply, ifctx->replylen, TAG_END);
1484 
1485 	if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0)
1486 		if (ifctx->reply.sname[0] != '\0')
1487 			printf(" server name %s", ifctx->reply.sname);
1488 	if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0)
1489 		if (ifctx->reply.file[0] != '\0')
1490 			printf(" boot file %s", ifctx->reply.file);
1491 
1492 	printf("\n");
1493 
1494 	p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1495 		       TAG_SUBNETMASK);
1496 	if (p != NULL) {
1497 		if (gctx->tag.taglen != 4)
1498 			panic("bootpc: subnet mask len is %d",
1499 			      gctx->tag.taglen);
1500 		bcopy(p, &ifctx->netmask.sin_addr, 4);
1501 		ifctx->gotnetmask = 1;
1502 		printf("subnet mask ");
1503 		print_sin_addr(&ifctx->netmask);
1504 		printf(" ");
1505 	}
1506 
1507 	p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1508 		       TAG_ROUTERS);
1509 	if (p != NULL) {
1510 		/* Routers */
1511 		if (gctx->tag.taglen % 4)
1512 			panic("bootpc: Router Len is %d", gctx->tag.taglen);
1513 		if (gctx->tag.taglen > 0) {
1514 			bcopy(p, &ifctx->gw.sin_addr, 4);
1515 			printf("router ");
1516 			print_sin_addr(&ifctx->gw);
1517 			printf(" ");
1518 			ifctx->gotgw = 1;
1519 			gctx->gotgw = 1;
1520 		}
1521 	}
1522 
1523 	p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1524 		       TAG_ROOT);
1525 	if (p != NULL) {
1526 		if (gctx->setrootfs != NULL) {
1527 			printf("rootfs %s (ignored) ", p);
1528 		} else 	if (setfs(&nd->root_saddr,
1529 				  nd->root_hostnam, p, &ifctx->reply.siaddr)) {
1530 			if (*p == '/') {
1531 				printf("root_server ");
1532 				print_sin_addr(&nd->root_saddr);
1533 				printf(" ");
1534 			}
1535 			printf("rootfs %s ", p);
1536 			gctx->gotrootpath = 1;
1537 			ifctx->gotrootpath = 1;
1538 			gctx->setrootfs = ifctx;
1539 
1540 			p = bootpc_tag(&gctx->tag, &ifctx->reply,
1541 				       ifctx->replylen,
1542 				       TAG_ROOTOPTS);
1543 			if (p != NULL) {
1544 				mountopts(&nd->root_args, p);
1545 				printf("rootopts %s ", p);
1546 			}
1547 		} else
1548 			panic("Failed to set rootfs to %s", p);
1549 	}
1550 
1551 	p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1552 		       TAG_HOSTNAME);
1553 	if (p != NULL) {
1554 		if (gctx->tag.taglen >= MAXHOSTNAMELEN)
1555 			panic("bootpc: hostname >= %d bytes",
1556 			      MAXHOSTNAMELEN);
1557 		if (gctx->sethostname != NULL) {
1558 			printf("hostname %s (ignored) ", p);
1559 		} else {
1560 			strcpy(nd->my_hostnam, p);
1561 			mtx_lock(&prison0.pr_mtx);
1562 			strcpy(prison0.pr_hostname, p);
1563 			mtx_unlock(&prison0.pr_mtx);
1564 			printf("hostname %s ", p);
1565 			gctx->sethostname = ifctx;
1566 		}
1567 	}
1568 	p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1569 			TAG_COOKIE);
1570 	if (p != NULL) {        /* store in a sysctl variable */
1571 		int i, l = sizeof(bootp_cookie) - 1;
1572 		for (i = 0; i < l && p[i] != '\0'; i++)
1573 			bootp_cookie[i] = p[i];
1574 		p[i] = '\0';
1575 	}
1576 
1577 
1578 	printf("\n");
1579 
1580 	if (ifctx->gotnetmask == 0) {
1581 		if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr)))
1582 			ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
1583 		else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr)))
1584 			ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
1585 		else
1586 			ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
1587 	}
1588 	if (ifctx->gotgw == 0) {
1589 		/* Use proxyarp */
1590 		ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr;
1591 	}
1592 }
1593 
1594 void
1595 bootpc_init(void)
1596 {
1597 	struct bootpc_ifcontext *ifctx, *nctx;	/* Interface BOOTP contexts */
1598 	struct bootpc_globalcontext *gctx; 	/* Global BOOTP context */
1599 	struct ifnet *ifp;
1600 	int error;
1601 #ifndef BOOTP_WIRED_TO
1602 	int ifcnt;
1603 #endif
1604 	struct nfsv3_diskless *nd;
1605 	struct thread *td;
1606 
1607 	nd = &nfsv3_diskless;
1608 	td = curthread;
1609 
1610 	/*
1611 	 * If already filled in, don't touch it here
1612 	 */
1613 	if (nfs_diskless_valid != 0)
1614 		return;
1615 
1616 	gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
1617 	if (gctx == NULL)
1618 		panic("Failed to allocate bootp global context structure");
1619 
1620 	gctx->xid = ~0xFFFF;
1621 	gctx->starttime = time_second;
1622 
1623 	/*
1624 	 * Find a network interface.
1625 	 */
1626 	CURVNET_SET(TD_TO_VNET(td));
1627 #ifdef BOOTP_WIRED_TO
1628 	printf("bootpc_init: wired to interface '%s'\n",
1629 	       __XSTRING(BOOTP_WIRED_TO));
1630 	allocifctx(gctx);
1631 #else
1632 	/*
1633 	 * Preallocate interface context storage, if another interface
1634 	 * attaches and wins the race, it won't be eligible for bootp.
1635 	 */
1636 	IFNET_RLOCK();
1637 	for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0;
1638 	     ifp != NULL;
1639 	     ifp = TAILQ_NEXT(ifp, if_link)) {
1640 		if ((ifp->if_flags &
1641 		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
1642 		    IFF_BROADCAST)
1643 			continue;
1644 		ifcnt++;
1645 	}
1646 	IFNET_RUNLOCK();
1647 	if (ifcnt == 0)
1648 		panic("bootpc_init: no eligible interfaces");
1649 	for (; ifcnt > 0; ifcnt--)
1650 		allocifctx(gctx);
1651 #endif
1652 
1653 	IFNET_RLOCK();
1654 	for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces;
1655 	     ifp != NULL && ifctx != NULL;
1656 	     ifp = TAILQ_NEXT(ifp, if_link)) {
1657 		strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
1658 		    sizeof(ifctx->ireq.ifr_name));
1659 #ifdef BOOTP_WIRED_TO
1660 		if (strcmp(ifctx->ireq.ifr_name,
1661 			   __XSTRING(BOOTP_WIRED_TO)) != 0)
1662 			continue;
1663 #else
1664 		if ((ifp->if_flags &
1665 		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
1666 		    IFF_BROADCAST)
1667 			continue;
1668 #endif
1669 		ifctx->ifp = ifp;
1670 		ifctx = ifctx->next;
1671 	}
1672 	IFNET_RUNLOCK();
1673 	CURVNET_RESTORE();
1674 
1675 	if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) {
1676 #ifdef BOOTP_WIRED_TO
1677 		panic("bootpc_init: Could not find interface specified "
1678 		      "by BOOTP_WIRED_TO: "
1679 		      __XSTRING(BOOTP_WIRED_TO));
1680 #else
1681 		panic("bootpc_init: no suitable interface");
1682 #endif
1683 	}
1684 
1685 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
1686 		bootpc_fakeup_interface(ifctx, gctx, td);
1687 
1688 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
1689 		bootpc_compose_query(ifctx, gctx, td);
1690 
1691 	error = bootpc_call(gctx, td);
1692 
1693 	if (error != 0) {
1694 #ifdef BOOTP_NFSROOT
1695 		panic("BOOTP call failed");
1696 #else
1697 		printf("BOOTP call failed\n");
1698 #endif
1699 	}
1700 
1701 	rootdevnames[0] = "nfs:";
1702 	mountopts(&nd->root_args, NULL);
1703 
1704 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
1705 		if (bootpc_ifctx_isresolved(ifctx) != 0)
1706 			bootpc_decode_reply(nd, ifctx, gctx);
1707 
1708 #ifdef BOOTP_NFSROOT
1709 	if (gctx->gotrootpath == 0)
1710 		panic("bootpc: No root path offered");
1711 #endif
1712 
1713 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
1714 		bootpc_adjust_interface(ifctx, gctx, td);
1715 
1716 		soclose(ifctx->so);
1717 	}
1718 
1719 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
1720 		if (ifctx->gotrootpath != 0)
1721 			break;
1722 	if (ifctx == NULL) {
1723 		for (ifctx = gctx->interfaces;
1724 		     ifctx != NULL;
1725 		     ifctx = ifctx->next)
1726 			if (bootpc_ifctx_isresolved(ifctx) != 0)
1727 				break;
1728 	}
1729 	if (ifctx == NULL)
1730 		goto out;
1731 
1732 	if (gctx->gotrootpath != 0) {
1733 
1734 		setenv("boot.netif.name", ifctx->ifp->if_xname);
1735 
1736 		error = md_mount(&nd->root_saddr, nd->root_hostnam,
1737 				 nd->root_fh, &nd->root_fhsize,
1738 				 &nd->root_args, td);
1739 		if (error != 0)
1740 			panic("nfs_boot: mountd root, error=%d", error);
1741 
1742 		nfs_diskless_valid = 3;
1743 	}
1744 
1745 	strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name);
1746 	bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr));
1747 	bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr));
1748 	((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
1749 		ifctx->myaddr.sin_addr.s_addr |
1750 		~ ifctx->netmask.sin_addr.s_addr;
1751 	bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
1752 
1753 out:
1754 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) {
1755 		nctx = ifctx->next;
1756 		free(ifctx, M_TEMP);
1757 	}
1758 	free(gctx, M_TEMP);
1759 }
1760 
1761 /*
1762  * RPC: mountd/mount
1763  * Given a server pathname, get an NFS file handle.
1764  * Also, sets sin->sin_port to the NFS service port.
1765  */
1766 static int
1767 md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
1768     struct nfs_args *args, struct thread *td)
1769 {
1770 	struct mbuf *m;
1771 	int error;
1772 	int authunixok;
1773 	int authcount;
1774 	int authver;
1775 
1776 #define	RPCPROG_MNT	100005
1777 #define	RPCMNT_VER1	1
1778 #define RPCMNT_VER3	3
1779 #define	RPCMNT_MOUNT	1
1780 #define	AUTH_SYS	1		/* unix style (uid, gids) */
1781 #define AUTH_UNIX	AUTH_SYS
1782 
1783 	/* XXX honor v2/v3 flags in args->flags? */
1784 #ifdef BOOTP_NFSV3
1785 	/* First try NFS v3 */
1786 	/* Get port number for MOUNTD. */
1787 	error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1788 			     &mdsin->sin_port, td);
1789 	if (error == 0) {
1790 		m = xdr_string_encode(path, strlen(path));
1791 
1792 		/* Do RPC to mountd. */
1793 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1794 				  RPCMNT_MOUNT, &m, NULL, td);
1795 	}
1796 	if (error == 0) {
1797 		args->flags |= NFSMNT_NFSV3;
1798 	} else {
1799 #endif
1800 		/* Fallback to NFS v2 */
1801 
1802 		/* Get port number for MOUNTD. */
1803 		error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1804 				     &mdsin->sin_port, td);
1805 		if (error != 0)
1806 			return error;
1807 
1808 		m = xdr_string_encode(path, strlen(path));
1809 
1810 		/* Do RPC to mountd. */
1811 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1812 				  RPCMNT_MOUNT, &m, NULL, td);
1813 		if (error != 0)
1814 			return error;	/* message already freed */
1815 
1816 #ifdef BOOTP_NFSV3
1817 	}
1818 #endif
1819 
1820 	if (xdr_int_decode(&m, &error) != 0 || error != 0)
1821 		goto bad;
1822 
1823 	if ((args->flags & NFSMNT_NFSV3) != 0) {
1824 		if (xdr_int_decode(&m, fhsizep) != 0 ||
1825 		    *fhsizep > NFSX_V3FHMAX ||
1826 		    *fhsizep <= 0)
1827 			goto bad;
1828 	} else
1829 		*fhsizep = NFSX_V2FH;
1830 
1831 	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
1832 		goto bad;
1833 
1834 	if (args->flags & NFSMNT_NFSV3) {
1835 		if (xdr_int_decode(&m, &authcount) != 0)
1836 			goto bad;
1837 		authunixok = 0;
1838 		if (authcount < 0 || authcount > 100)
1839 			goto bad;
1840 		while (authcount > 0) {
1841 			if (xdr_int_decode(&m, &authver) != 0)
1842 				goto bad;
1843 			if (authver == AUTH_UNIX)
1844 				authunixok = 1;
1845 			authcount--;
1846 		}
1847 		if (authunixok == 0)
1848 			goto bad;
1849 	}
1850 
1851 	/* Set port number for NFS use. */
1852 	error = krpc_portmap(mdsin, NFS_PROG,
1853 			     (args->flags &
1854 			      NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
1855 			     &mdsin->sin_port, td);
1856 
1857 	goto out;
1858 
1859 bad:
1860 	error = EBADRPC;
1861 
1862 out:
1863 	m_freem(m);
1864 	return error;
1865 }
1866 
1867 SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL);
1868