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