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