xref: /illumos-gate/usr/src/stand/lib/fs/nfs/bootparams.c (revision b531f6d1)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * This file contains routines responsible for getting the system's
297c478bd9Sstevel@tonic-gate  * name and boot params. Most of it comes from the SVR4 diskless boot
307c478bd9Sstevel@tonic-gate  * code (dlboot_inet), modified to work in a non socket environment.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <rpc/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/errno.h>
367c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
377c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
387c478bd9Sstevel@tonic-gate #include <rpc/rpc_msg.h>
397c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
407c478bd9Sstevel@tonic-gate #include "clnt.h"
417c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
427c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
437c478bd9Sstevel@tonic-gate #include <netinet/in.h>
447c478bd9Sstevel@tonic-gate #include <sys/socket.h>
457c478bd9Sstevel@tonic-gate #include <net/if.h>
467c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h>
477c478bd9Sstevel@tonic-gate #include <netinet/in.h>
487c478bd9Sstevel@tonic-gate #include <sys/promif.h>
497c478bd9Sstevel@tonic-gate #include <rpcsvc/bootparam.h>
507c478bd9Sstevel@tonic-gate #include "pmap.h"
517c478bd9Sstevel@tonic-gate #include "brpc.h"
527c478bd9Sstevel@tonic-gate #include "socket_inet.h"
537c478bd9Sstevel@tonic-gate #include "ipv4.h"
547c478bd9Sstevel@tonic-gate #include <sys/salib.h>
557c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate extern int errno;
587c478bd9Sstevel@tonic-gate static struct bp_whoami_res	bp;
597c478bd9Sstevel@tonic-gate static char			bp_hostname[SYS_NMLN+1];
607c478bd9Sstevel@tonic-gate static char			bp_domainname[SYS_NMLN+1];
617c478bd9Sstevel@tonic-gate static struct in_addr		responder; /* network order */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static const char *noserver =
647c478bd9Sstevel@tonic-gate 	"No bootparam (%s) server responding; still trying...\n";
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define	GETFILE_BTIMEO		1
677c478bd9Sstevel@tonic-gate #define	GETFILE_BRETRIES	2
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	dprintf	if (boothowto & RB_DEBUG) printf
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * Returns TRUE if it has set the global structure 'bp' to our boot
737c478bd9Sstevel@tonic-gate  * parameters, FALSE if some failure occurred.
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate bool_t
whoami(void)767c478bd9Sstevel@tonic-gate whoami(void)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	struct bp_whoami_arg	arg;
797c478bd9Sstevel@tonic-gate 	struct sockaddr_in	to, from;
807c478bd9Sstevel@tonic-gate 	struct in_addr		ipaddr;
817c478bd9Sstevel@tonic-gate 	enum clnt_stat		stat;
827c478bd9Sstevel@tonic-gate 	bool_t			retval = TRUE;
837c478bd9Sstevel@tonic-gate 	int			rexmit;		/* retransmission interval */
847c478bd9Sstevel@tonic-gate 	int			resp_wait;	/* secs to wait for resp */
857c478bd9Sstevel@tonic-gate 	int			namelen;
867c478bd9Sstevel@tonic-gate 	int			printed_waiting_msg;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	/*
897c478bd9Sstevel@tonic-gate 	 * Set our destination IP address to the limited broadcast address
907c478bd9Sstevel@tonic-gate 	 * (INADDR_BROADCAST).
917c478bd9Sstevel@tonic-gate 	 */
927c478bd9Sstevel@tonic-gate 	to.sin_family = AF_INET;
937c478bd9Sstevel@tonic-gate 	to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
947c478bd9Sstevel@tonic-gate 	to.sin_port = htons(0);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	/*
977c478bd9Sstevel@tonic-gate 	 * Set up the arguments expected by bootparamd.
987c478bd9Sstevel@tonic-gate 	 */
997c478bd9Sstevel@tonic-gate 	arg.client_address.address_type = IP_ADDR_TYPE;
1007c478bd9Sstevel@tonic-gate 	ipv4_getipaddr(&ipaddr);
1017c478bd9Sstevel@tonic-gate 	ipaddr.s_addr = htonl(ipaddr.s_addr);
1027c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ipaddr,
1037c478bd9Sstevel@tonic-gate 		(caddr_t)&arg.client_address.bp_address_u.ip_addr,
1047c478bd9Sstevel@tonic-gate 		sizeof (ipaddr));
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/*
1077c478bd9Sstevel@tonic-gate 	 * Retransmit/wait for up to resp_wait secs.
1087c478bd9Sstevel@tonic-gate 	 */
1097c478bd9Sstevel@tonic-gate 	rexmit = 0;	/* start at default retransmission interval. */
1107c478bd9Sstevel@tonic-gate 	resp_wait = 16;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	bp.client_name = &bp_hostname[0];
1137c478bd9Sstevel@tonic-gate 	bp.domain_name = &bp_domainname[0];
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/*
1167c478bd9Sstevel@tonic-gate 	 * Do a broadcast call to find a bootparam daemon that
1177c478bd9Sstevel@tonic-gate 	 * will tell us our hostname, domainname and any
1187c478bd9Sstevel@tonic-gate 	 * router that we have to use to talk to our NFS server.
1197c478bd9Sstevel@tonic-gate 	 */
1207c478bd9Sstevel@tonic-gate 	printed_waiting_msg = 0;
1217c478bd9Sstevel@tonic-gate 	do {
1227c478bd9Sstevel@tonic-gate 		/*
1237c478bd9Sstevel@tonic-gate 		 * First try the SunOS portmapper and if no reply is
1247c478bd9Sstevel@tonic-gate 		 * received will then try the SVR4 rpcbind.
1257c478bd9Sstevel@tonic-gate 		 * Either way, `bootpaddr' will be set to the
1267c478bd9Sstevel@tonic-gate 		 * correct address for the bootparamd that responds.
1277c478bd9Sstevel@tonic-gate 		 */
1287c478bd9Sstevel@tonic-gate 		stat = bpmap_rmtcall((rpcprog_t)BOOTPARAMPROG,
1297c478bd9Sstevel@tonic-gate 		    (rpcvers_t)BOOTPARAMVERS, (rpcproc_t)BOOTPARAMPROC_WHOAMI,
1307c478bd9Sstevel@tonic-gate 		    xdr_bp_whoami_arg, (caddr_t)&arg,
1317c478bd9Sstevel@tonic-gate 		    xdr_bp_whoami_res, (caddr_t)&bp, rexmit, resp_wait,
1327c478bd9Sstevel@tonic-gate 			&to, &from, AUTH_NONE);
1337c478bd9Sstevel@tonic-gate 		if (stat == RPC_TIMEDOUT && !printed_waiting_msg) {
1347c478bd9Sstevel@tonic-gate 			dprintf(noserver, "whoami");
1357c478bd9Sstevel@tonic-gate 			printed_waiting_msg = 1;
1367c478bd9Sstevel@tonic-gate 		}
1377c478bd9Sstevel@tonic-gate 		/*
1387c478bd9Sstevel@tonic-gate 		 * Retransmission interval for second and subsequent tries.
1397c478bd9Sstevel@tonic-gate 		 * We expect first bpmap_rmtcall to retransmit and backoff to
1407c478bd9Sstevel@tonic-gate 		 * at least this value.
1417c478bd9Sstevel@tonic-gate 		 */
1427c478bd9Sstevel@tonic-gate 		rexmit = resp_wait;
1437c478bd9Sstevel@tonic-gate 		resp_wait = 0;		/* go to default wait now. */
1447c478bd9Sstevel@tonic-gate 	} while (stat == RPC_TIMEDOUT);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (stat != RPC_SUCCESS) {
1477c478bd9Sstevel@tonic-gate 		dprintf("whoami RPC call failed with rpc status: %d\n", stat);
1487c478bd9Sstevel@tonic-gate 		retval = FALSE;
1497c478bd9Sstevel@tonic-gate 		goto done;
1507c478bd9Sstevel@tonic-gate 	} else {
1517c478bd9Sstevel@tonic-gate 		if (printed_waiting_msg && (boothowto & RB_VERBOSE))
1527c478bd9Sstevel@tonic-gate 			printf("Bootparam response received\n");
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		/* Cache responder... We'll send our getfile here... */
1557c478bd9Sstevel@tonic-gate 		responder.s_addr = from.sin_addr.s_addr;
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	namelen = strlen(bp.client_name);
1597c478bd9Sstevel@tonic-gate 	if (namelen > SYS_NMLN) {
1607c478bd9Sstevel@tonic-gate 		dprintf("whoami: hostname too long");
1617c478bd9Sstevel@tonic-gate 		retval = FALSE;
1627c478bd9Sstevel@tonic-gate 		goto done;
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 	if (namelen > 0) {
1657c478bd9Sstevel@tonic-gate 		if (boothowto & RB_VERBOSE)
1667c478bd9Sstevel@tonic-gate 			printf("hostname: %s\n", bp.client_name);
167*b531f6d1SToomas Soome 		(void) sethostname(bp.client_name, namelen);
1687c478bd9Sstevel@tonic-gate 	} else {
1697c478bd9Sstevel@tonic-gate 		dprintf("whoami: no host name\n");
1707c478bd9Sstevel@tonic-gate 		retval = FALSE;
1717c478bd9Sstevel@tonic-gate 		goto done;
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	namelen = strlen(bp.domain_name);
1757c478bd9Sstevel@tonic-gate 	if (namelen > SYS_NMLN) {
1767c478bd9Sstevel@tonic-gate 		dprintf("whoami: domainname too long");
1777c478bd9Sstevel@tonic-gate 		retval = FALSE;
1787c478bd9Sstevel@tonic-gate 		goto done;
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 	if (namelen > 0)
1817c478bd9Sstevel@tonic-gate 		if (boothowto & RB_VERBOSE)
1827c478bd9Sstevel@tonic-gate 			printf("domainname: %s\n", bp.domain_name);
1837c478bd9Sstevel@tonic-gate 	else
1847c478bd9Sstevel@tonic-gate 		dprintf("whoami: no domain name\n");
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	if (bp.router_address.address_type == IP_ADDR_TYPE) {
1877c478bd9Sstevel@tonic-gate 		bcopy((caddr_t)&bp.router_address.bp_address_u.ip_addr,
1887c478bd9Sstevel@tonic-gate 		    (caddr_t)&ipaddr, sizeof (ipaddr));
1897c478bd9Sstevel@tonic-gate 		if (ntohl(ipaddr.s_addr) != INADDR_ANY) {
1907c478bd9Sstevel@tonic-gate 			dprintf("whoami: Router ip is: %s\n",
1917c478bd9Sstevel@tonic-gate 			    inet_ntoa(ipaddr));
1927c478bd9Sstevel@tonic-gate 			/* ipv4_route expects IP addresses in network order */
1937c478bd9Sstevel@tonic-gate 			(void) ipv4_route(IPV4_ADD_ROUTE, RT_DEFAULT, NULL,
1947c478bd9Sstevel@tonic-gate 			    &ipaddr);
1957c478bd9Sstevel@tonic-gate 		}
1967c478bd9Sstevel@tonic-gate 	} else
1977c478bd9Sstevel@tonic-gate 		dprintf("whoami: unknown gateway addr family %d\n",
1987c478bd9Sstevel@tonic-gate 		    bp.router_address.address_type);
1997c478bd9Sstevel@tonic-gate done:
2007c478bd9Sstevel@tonic-gate 	return (retval);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * Returns:
2057c478bd9Sstevel@tonic-gate  *	1) The ascii form of our root servers name in `server_name'.
2067c478bd9Sstevel@tonic-gate  *	2) Pathname of our root on the server in `server_path'.
2077c478bd9Sstevel@tonic-gate  *
2087c478bd9Sstevel@tonic-gate  * NOTE: it's ok for getfile() to do dynamic allocation - it's only
2097c478bd9Sstevel@tonic-gate  * used locally, then freed. If the server address returned from the
2107c478bd9Sstevel@tonic-gate  * getfile call is different from our current destination address,
2117c478bd9Sstevel@tonic-gate  * reset destination IP address to the new value.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate bool_t
getfile(char * fileid,char * server_name,struct in_addr * server_ip,char * server_path)2147c478bd9Sstevel@tonic-gate getfile(char *fileid, char *server_name, struct in_addr *server_ip,
2157c478bd9Sstevel@tonic-gate     char *server_path)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	struct bp_getfile_arg	arg;
2187c478bd9Sstevel@tonic-gate 	struct bp_getfile_res	res;
2197c478bd9Sstevel@tonic-gate 	enum clnt_stat		stat;
2207c478bd9Sstevel@tonic-gate 	struct sockaddr_in	to, from;
2217c478bd9Sstevel@tonic-gate 	int			rexmit;
2227c478bd9Sstevel@tonic-gate 	int			wait;
2237c478bd9Sstevel@tonic-gate 	uint_t			max_retries = 0xFFFFFFFF;
2247c478bd9Sstevel@tonic-gate 	int			def_rexmit = 0;
2257c478bd9Sstevel@tonic-gate 	int			def_wait = 32;
2267c478bd9Sstevel@tonic-gate 	int			printed_waiting_msg;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/*
2297c478bd9Sstevel@tonic-gate 	 * For non-root requests, set a smaller timeout
2307c478bd9Sstevel@tonic-gate 	 */
2317c478bd9Sstevel@tonic-gate 	if (strcmp(fileid, "root") != 0) {
2327c478bd9Sstevel@tonic-gate 		/*
2337c478bd9Sstevel@tonic-gate 		 * Only send one request per call
2347c478bd9Sstevel@tonic-gate 		 */
2357c478bd9Sstevel@tonic-gate 		def_wait = GETFILE_BTIMEO;
2367c478bd9Sstevel@tonic-gate 		def_rexmit = GETFILE_BTIMEO;
2377c478bd9Sstevel@tonic-gate 		max_retries = GETFILE_BRETRIES;
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	arg.client_name = bp.client_name;
2417c478bd9Sstevel@tonic-gate 	arg.file_id = fileid;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	res.server_name = (bp_machine_name_t)bkmem_zalloc(SYS_NMLN + 1);
2447c478bd9Sstevel@tonic-gate 	res.server_path = (bp_path_t)bkmem_zalloc(SYS_NMLN + 1);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if (res.server_name == NULL || res.server_path == NULL) {
2477c478bd9Sstevel@tonic-gate 		dprintf("getfile: rpc_call failed: No memory\n");
2487c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
2497c478bd9Sstevel@tonic-gate 		if (res.server_name != NULL)
2507c478bd9Sstevel@tonic-gate 			bkmem_free(res.server_name, SYS_NMLN + 1);
2517c478bd9Sstevel@tonic-gate 		if (res.server_path != NULL)
2527c478bd9Sstevel@tonic-gate 			bkmem_free(res.server_path, SYS_NMLN + 1);
2537c478bd9Sstevel@tonic-gate 		return (FALSE);
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	to.sin_family = AF_INET;
2577c478bd9Sstevel@tonic-gate 	to.sin_addr.s_addr = responder.s_addr;
2587c478bd9Sstevel@tonic-gate 	to.sin_port = htons(0);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	/*
2617c478bd9Sstevel@tonic-gate 	 * Our addressing information was filled in by the call to
2627c478bd9Sstevel@tonic-gate 	 * whoami(), so now send an rpc message to the
2637c478bd9Sstevel@tonic-gate 	 * bootparam daemon requesting our server information.
2647c478bd9Sstevel@tonic-gate 	 *
2657c478bd9Sstevel@tonic-gate 	 * Wait only 32 secs for rpc_call to succeed.
2667c478bd9Sstevel@tonic-gate 	 */
2677c478bd9Sstevel@tonic-gate 	rexmit = def_rexmit;
2687c478bd9Sstevel@tonic-gate 	wait = def_wait;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	stat = brpc_call((rpcprog_t)BOOTPARAMPROG, (rpcvers_t)BOOTPARAMVERS,
2717c478bd9Sstevel@tonic-gate 	    (rpcproc_t)BOOTPARAMPROC_GETFILE, xdr_bp_getfile_arg, (caddr_t)&arg,
2727c478bd9Sstevel@tonic-gate 	    xdr_bp_getfile_res, (caddr_t)&res, rexmit, wait,
2737c478bd9Sstevel@tonic-gate 				&to, &from, AUTH_NONE);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (stat == RPC_TIMEDOUT) {
2767c478bd9Sstevel@tonic-gate 		/*
2777c478bd9Sstevel@tonic-gate 		 * The server that answered the whoami doesn't
2787c478bd9Sstevel@tonic-gate 		 * answer our getfile. Broadcast the call to all. Keep
2797c478bd9Sstevel@tonic-gate 		 * trying forever. Set up for limited broadcast.
2807c478bd9Sstevel@tonic-gate 		 */
2817c478bd9Sstevel@tonic-gate 		to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
2827c478bd9Sstevel@tonic-gate 		to.sin_port = htons(0);
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 		rexmit = def_rexmit;	/* use default rexmit interval */
2857c478bd9Sstevel@tonic-gate 		wait = def_wait;
2867c478bd9Sstevel@tonic-gate 		printed_waiting_msg = 0;
2877c478bd9Sstevel@tonic-gate 		do {
2887c478bd9Sstevel@tonic-gate 			/*
2897c478bd9Sstevel@tonic-gate 			 * Limit the number of retries
2907c478bd9Sstevel@tonic-gate 			 */
2917c478bd9Sstevel@tonic-gate 			if (max_retries-- == 0)
2927c478bd9Sstevel@tonic-gate 				break;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 			stat = bpmap_rmtcall((rpcprog_t)BOOTPARAMPROG,
2957c478bd9Sstevel@tonic-gate 			    (rpcvers_t)BOOTPARAMVERS,
2967c478bd9Sstevel@tonic-gate 			    (rpcproc_t)BOOTPARAMPROC_GETFILE,
2977c478bd9Sstevel@tonic-gate 			    xdr_bp_getfile_arg, (caddr_t)&arg,
2987c478bd9Sstevel@tonic-gate 			    xdr_bp_getfile_res, (caddr_t)&res, rexmit,
2997c478bd9Sstevel@tonic-gate 			    wait, &to, &from, AUTH_NONE);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 			if (stat == RPC_SUCCESS) {
3027c478bd9Sstevel@tonic-gate 				/*
3037c478bd9Sstevel@tonic-gate 				 * set our destination addresses to
3047c478bd9Sstevel@tonic-gate 				 * those of the server that responded.
3057c478bd9Sstevel@tonic-gate 				 * It's probably our server, and we
3067c478bd9Sstevel@tonic-gate 				 * can thus save arping for no reason later.
3077c478bd9Sstevel@tonic-gate 				 */
3087c478bd9Sstevel@tonic-gate 				responder.s_addr = from.sin_addr.s_addr;
3097c478bd9Sstevel@tonic-gate 				if (printed_waiting_msg &&
3107c478bd9Sstevel@tonic-gate 				    (boothowto & RB_VERBOSE)) {
3117c478bd9Sstevel@tonic-gate 					printf(
3127c478bd9Sstevel@tonic-gate 					    "Bootparam response received.\n");
3137c478bd9Sstevel@tonic-gate 				}
3147c478bd9Sstevel@tonic-gate 				break;
3157c478bd9Sstevel@tonic-gate 			}
3167c478bd9Sstevel@tonic-gate 			if (stat == RPC_TIMEDOUT && !printed_waiting_msg) {
3177c478bd9Sstevel@tonic-gate 				dprintf(noserver, "getfile");
3187c478bd9Sstevel@tonic-gate 				printed_waiting_msg = 1;
3197c478bd9Sstevel@tonic-gate 			}
3207c478bd9Sstevel@tonic-gate 			/*
3217c478bd9Sstevel@tonic-gate 			 * Retransmission interval for second and
3227c478bd9Sstevel@tonic-gate 			 * subsequent tries. We expect first bpmap_rmtcall
3237c478bd9Sstevel@tonic-gate 			 * to retransmit and backoff to at least this
3247c478bd9Sstevel@tonic-gate 			 * value.
3257c478bd9Sstevel@tonic-gate 			 */
3267c478bd9Sstevel@tonic-gate 			rexmit = wait;
3277c478bd9Sstevel@tonic-gate 			wait = def_wait;
3287c478bd9Sstevel@tonic-gate 		} while (stat == RPC_TIMEDOUT);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (stat == RPC_SUCCESS) {
3327c478bd9Sstevel@tonic-gate 		/* got the goods */
3337c478bd9Sstevel@tonic-gate 		bcopy(res.server_name, server_name, strlen(res.server_name));
3347c478bd9Sstevel@tonic-gate 		bcopy(res.server_path, server_path, strlen(res.server_path));
3357c478bd9Sstevel@tonic-gate 		switch (res.server_address.address_type) {
3367c478bd9Sstevel@tonic-gate 		case IP_ADDR_TYPE:
3377c478bd9Sstevel@tonic-gate 			/*
3387c478bd9Sstevel@tonic-gate 			 * server_address is where we will get our root
3397c478bd9Sstevel@tonic-gate 			 * from. Replace destination entries in address if
3407c478bd9Sstevel@tonic-gate 			 * necessary.
3417c478bd9Sstevel@tonic-gate 			 */
3427c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)&res.server_address.bp_address_u.ip_addr,
3437c478bd9Sstevel@tonic-gate 			    (caddr_t)server_ip, sizeof (struct in_addr));
3447c478bd9Sstevel@tonic-gate 			break;
3457c478bd9Sstevel@tonic-gate 		default:
3467c478bd9Sstevel@tonic-gate 			dprintf("getfile: unknown address type %d\n",
3477c478bd9Sstevel@tonic-gate 				res.server_address.address_type);
3487c478bd9Sstevel@tonic-gate 			server_ip->s_addr = htonl(INADDR_ANY);
3497c478bd9Sstevel@tonic-gate 			bkmem_free(res.server_name, SYS_NMLN + 1);
3507c478bd9Sstevel@tonic-gate 			bkmem_free(res.server_path, SYS_NMLN + 1);
3517c478bd9Sstevel@tonic-gate 			return (FALSE);
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 	} else {
3547c478bd9Sstevel@tonic-gate 		dprintf("getfile: rpc_call failed.\n");
3557c478bd9Sstevel@tonic-gate 		bkmem_free(res.server_name, SYS_NMLN + 1);
3567c478bd9Sstevel@tonic-gate 		bkmem_free(res.server_path, SYS_NMLN + 1);
3577c478bd9Sstevel@tonic-gate 		return (FALSE);
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	bkmem_free(res.server_name, SYS_NMLN + 1);
3617c478bd9Sstevel@tonic-gate 	bkmem_free(res.server_path, SYS_NMLN + 1);
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	return (TRUE);
3647c478bd9Sstevel@tonic-gate }
365