xref: /netbsd-src/sys/lib/libsa/bootparam.c (revision 94ad267eb1d1735bdf16f6aebb5e9b4ed29887f9)
1*94ad267eSchristos /*	$NetBSD: bootparam.c,v 1.21 2019/04/02 22:25:10 christos Exp $	*/
2b4c3997cSgwr 
3b4c3997cSgwr /*
4b4c3997cSgwr  * Copyright (c) 1995 Gordon W. Ross
5b4c3997cSgwr  * All rights reserved.
6b4c3997cSgwr  *
7b4c3997cSgwr  * Redistribution and use in source and binary forms, with or without
8b4c3997cSgwr  * modification, are permitted provided that the following conditions
9b4c3997cSgwr  * are met:
10b4c3997cSgwr  * 1. Redistributions of source code must retain the above copyright
11b4c3997cSgwr  *    notice, this list of conditions and the following disclaimer.
12b4c3997cSgwr  * 2. Redistributions in binary form must reproduce the above copyright
13b4c3997cSgwr  *    notice, this list of conditions and the following disclaimer in the
14b4c3997cSgwr  *    documentation and/or other materials provided with the distribution.
15b4c3997cSgwr  *
16b4c3997cSgwr  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b4c3997cSgwr  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18b4c3997cSgwr  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19b4c3997cSgwr  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20b4c3997cSgwr  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21b4c3997cSgwr  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22b4c3997cSgwr  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23b4c3997cSgwr  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24b4c3997cSgwr  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25b4c3997cSgwr  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b4c3997cSgwr  */
27b4c3997cSgwr 
28b4c3997cSgwr /*
29b4c3997cSgwr  * RPC/bootparams
30b4c3997cSgwr  */
31b4c3997cSgwr 
32b4c3997cSgwr #include <sys/param.h>
33b4c3997cSgwr #include <sys/socket.h>
34b4c3997cSgwr 
35b4c3997cSgwr #include <net/if.h>
36b4c3997cSgwr 
37b4c3997cSgwr #include <netinet/in.h>
38b4c3997cSgwr #include <netinet/in_systm.h>
39b4c3997cSgwr 
4036ff5d93Sthorpej #ifdef _STANDALONE
4136ff5d93Sthorpej #include <lib/libkern/libkern.h>
4236ff5d93Sthorpej #else
4336ff5d93Sthorpej #include <string.h>
4436ff5d93Sthorpej #endif
4536ff5d93Sthorpej 
46056810edSgwr #include "rpcv2.h"
47056810edSgwr 
48b4c3997cSgwr #include "stand.h"
49b4c3997cSgwr #include "net.h"
50b4c3997cSgwr #include "rpc.h"
51b4c3997cSgwr #include "bootparam.h"
52b4c3997cSgwr 
532b33d9d5Schristos #ifdef DEBUG_RPC
54e44c1d1fSchristos #define RPC_PRINTF(a)	printf a
552b33d9d5Schristos #else
562b33d9d5Schristos #define RPC_PRINTF(a)
572b33d9d5Schristos #endif
582b33d9d5Schristos 
59d9124da4Spk struct in_addr	bp_server_addr;	/* net order */
60b4c3997cSgwr n_short		bp_server_port;	/* net order */
61b4c3997cSgwr 
6210497fd2Schristos uint32_t	hostnamelen;
633906113eSdrochner char		domainname[FNAME_SIZE]; /* our DNS domain */
64*94ad267eSchristos uint32_t	domainnamelen;
653906113eSdrochner 
66b4c3997cSgwr /*
67b4c3997cSgwr  * RPC definitions for bootparamd
68b4c3997cSgwr  */
69b4c3997cSgwr #define	BOOTPARAM_PROG		100026
70b4c3997cSgwr #define	BOOTPARAM_VERS		1
71b4c3997cSgwr #define BOOTPARAM_WHOAMI	1
72b4c3997cSgwr #define BOOTPARAM_GETFILE	2
73b4c3997cSgwr 
74b4c3997cSgwr /*
75b4c3997cSgwr  * Inet address in RPC messages
76b4c3997cSgwr  * (Note, really four ints, NOT chars.  Blech.)
77b4c3997cSgwr  */
78b4c3997cSgwr struct xdr_inaddr {
7910497fd2Schristos 	uint32_t  atype;
80b4c3997cSgwr 	int32_t	addr[4];
81b4c3997cSgwr };
82b4c3997cSgwr 
833f38114dStsutsui int xdr_inaddr_encode(char **, struct in_addr);
843f38114dStsutsui int xdr_inaddr_decode(char **, struct in_addr *);
85b4c3997cSgwr 
8610497fd2Schristos int xdr_string_encode(char **, char *, uint32_t);
8710497fd2Schristos int xdr_string_decode(char **, char *, uint32_t *);
88b4c3997cSgwr 
89b4c3997cSgwr 
90b4c3997cSgwr /*
91b4c3997cSgwr  * RPC: bootparam/whoami
92b4c3997cSgwr  * Given client IP address, get:
93b4c3997cSgwr  *	client name	(hostname)
94b4c3997cSgwr  *	domain name (domainname)
95b4c3997cSgwr  *	gateway address
96b4c3997cSgwr  *
97b4c3997cSgwr  * The hostname and domainname are set here for convenience.
98b4c3997cSgwr  *
99b4c3997cSgwr  * Note - bpsin is initialized to the broadcast address,
100b4c3997cSgwr  * and will be replaced with the bootparam server address
101b4c3997cSgwr  * after this call is complete.  Have to use PMAP_PROC_CALL
102b4c3997cSgwr  * to make sure we get responses only from a servers that
103b4c3997cSgwr  * know about us (don't want to broadcast a getport call).
104b4c3997cSgwr  */
105b4c3997cSgwr int
bp_whoami(int sockfd)1061c038e68Sisaki bp_whoami(int sockfd)
107b4c3997cSgwr {
108b4c3997cSgwr 	/* RPC structures for PMAPPROC_CALLIT */
109b4c3997cSgwr 	struct args {
11010497fd2Schristos 		uint32_t prog;
11110497fd2Schristos 		uint32_t vers;
11210497fd2Schristos 		uint32_t proc;
11310497fd2Schristos 		uint32_t arglen;
114b4c3997cSgwr 		struct xdr_inaddr xina;
115b4c3997cSgwr 	} *args;
116b4c3997cSgwr 	struct repl {
11710497fd2Schristos 		uint16_t _pad;
11810497fd2Schristos 		uint16_t port;
11910497fd2Schristos 		uint32_t encap_len;
120b4c3997cSgwr 		/* encapsulated data here */
121b4c3997cSgwr 		n_long  capsule[64];
122b4c3997cSgwr 	} *repl;
123b4c3997cSgwr 	struct {
124b4c3997cSgwr 		n_long	h[RPC_HEADER_WORDS];
125b4c3997cSgwr 		struct args d;
126b4c3997cSgwr 	} sdata;
127b4c3997cSgwr 	struct {
128b4c3997cSgwr 		n_long	h[RPC_HEADER_WORDS];
129b4c3997cSgwr 		struct repl d;
130b4c3997cSgwr 	} rdata;
1316f2a9404Sgwr 	char *send_tail, *recv_head;
132b4c3997cSgwr 	struct iodesc *d;
13310497fd2Schristos 	uint32_t x;
13410497fd2Schristos 	ssize_t len;
135b4c3997cSgwr 
13610497fd2Schristos 	RPC_PRINTF(("%s: myip=%s\n", __func__, inet_ntoa(myip)));
137b4c3997cSgwr 
138b4c3997cSgwr 	if (!(d = socktodesc(sockfd))) {
13910497fd2Schristos 		RPC_PRINTF(("%s: bad socket. %d\n", __func__, sockfd));
1401c038e68Sisaki 		return -1;
141b4c3997cSgwr 	}
142b4c3997cSgwr 	args = &sdata.d;
143b4c3997cSgwr 	repl = &rdata.d;
144b4c3997cSgwr 
145b4c3997cSgwr 	/*
146b4c3997cSgwr 	 * Build request args for PMAPPROC_CALLIT.
147b4c3997cSgwr 	 */
14810497fd2Schristos 	args->prog = htonl((uint32_t)BOOTPARAM_PROG);
14910497fd2Schristos 	args->vers = htonl((uint32_t)BOOTPARAM_VERS);
15010497fd2Schristos 	args->proc = htonl((uint32_t)BOOTPARAM_WHOAMI);
15110497fd2Schristos 	args->arglen = htonl((uint32_t)sizeof(struct xdr_inaddr));
1526f2a9404Sgwr 	send_tail = (char *)&args->xina;
153b4c3997cSgwr 
154b4c3997cSgwr 	/*
155b4c3997cSgwr 	 * append encapsulated data (client IP address)
156b4c3997cSgwr 	 */
157b4c3997cSgwr 	if (xdr_inaddr_encode(&send_tail, myip))
1581c038e68Sisaki 		return -1;
159b4c3997cSgwr 
160b4c3997cSgwr 	/* RPC: portmap/callit */
16110497fd2Schristos 	--rpc_port;
16210497fd2Schristos 	d->myport = (uint16_t)htons((uint16_t)rpc_port);
163d9124da4Spk 	d->destip.s_addr = INADDR_BROADCAST;	/* XXX: subnet bcast? */
164b4c3997cSgwr 	/* rpc_call will set d->destport */
165b4c3997cSgwr 
166b4c3997cSgwr 	len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
16710497fd2Schristos 				  args, (size_t)(send_tail - (char *)args),
168b4c3997cSgwr 				  repl, sizeof(*repl));
169b4c3997cSgwr 	if (len < 8) {
17010497fd2Schristos 		printf("%s: 'whoami' call failed\n", __func__);
1711c038e68Sisaki 		return -1;
172b4c3997cSgwr 	}
173b4c3997cSgwr 
174b4c3997cSgwr 	/* Save bootparam server address (from IP header). */
175b4c3997cSgwr 	rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
176b4c3997cSgwr 
177b4c3997cSgwr 	/*
178b4c3997cSgwr 	 * Note that bp_server_port is now 111 due to the
179b4c3997cSgwr 	 * indirect call (using PMAPPROC_CALLIT), so get the
180b4c3997cSgwr 	 * actual port number from the reply data.
181b4c3997cSgwr 	 */
182b4c3997cSgwr 	bp_server_port = repl->port;
183b4c3997cSgwr 
18410497fd2Schristos 	RPC_PRINTF(("%s: server at %s:%d\n", __func__,
18510497fd2Schristos 	    inet_ntoa(bp_server_addr), ntohs((uint16_t)bp_server_port)));
186b4c3997cSgwr 
187b4c3997cSgwr 	/* We have just done a portmap call, so cache the portnum. */
188b4c3997cSgwr 	rpc_pmap_putcache(bp_server_addr,
189b4c3997cSgwr 			  BOOTPARAM_PROG,
190b4c3997cSgwr 			  BOOTPARAM_VERS,
19110497fd2Schristos 			  (int)ntohs((uint16_t)bp_server_port));
192b4c3997cSgwr 
193b4c3997cSgwr 	/*
194b4c3997cSgwr 	 * Parse the encapsulated results from bootparam/whoami
195b4c3997cSgwr 	 */
19610497fd2Schristos 	x = ntohl((uint32_t)repl->encap_len);
197b4c3997cSgwr 	if (len < x) {
19810497fd2Schristos 		printf("%s: short reply, %zd < %d\n", __func__, len, x);
1991c038e68Sisaki 		return -1;
200b4c3997cSgwr 	}
2016f2a9404Sgwr 	recv_head = (char *)repl->capsule;
202b4c3997cSgwr 
203b4c3997cSgwr 	/* client name */
204b4c3997cSgwr 	hostnamelen = MAXHOSTNAMELEN-1;
205b4c3997cSgwr 	if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
20610497fd2Schristos 		RPC_PRINTF(("%s: bad hostname\n", __func__));
2071c038e68Sisaki 		return -1;
208b4c3997cSgwr 	}
209b4c3997cSgwr 
210b4c3997cSgwr 	/* domain name */
211b4c3997cSgwr 	domainnamelen = MAXHOSTNAMELEN-1;
212b4c3997cSgwr 	if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
21310497fd2Schristos 		RPC_PRINTF(("%s: bad domainname\n", __func__));
2141c038e68Sisaki 		return -1;
215b4c3997cSgwr 	}
216b4c3997cSgwr 
217b4c3997cSgwr 	/* gateway address */
218b4c3997cSgwr 	if (xdr_inaddr_decode(&recv_head, &gateip)) {
21910497fd2Schristos 		RPC_PRINTF(("%s: bad gateway\n", __func__));
2201c038e68Sisaki 		return -1;
221b4c3997cSgwr 	}
222b4c3997cSgwr 
223b4c3997cSgwr 	/* success */
2241c038e68Sisaki 	return 0;
225b4c3997cSgwr }
226b4c3997cSgwr 
227b4c3997cSgwr 
228b4c3997cSgwr /*
229b4c3997cSgwr  * RPC: bootparam/getfile
230b4c3997cSgwr  * Given client name and file "key", get:
231b4c3997cSgwr  *	server name
232b4c3997cSgwr  *	server IP address
233b4c3997cSgwr  *	server pathname
234b4c3997cSgwr  */
235b4c3997cSgwr int
bp_getfile(int sockfd,char * key,struct in_addr * serv_addr,char * pathname)2361c038e68Sisaki bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
237b4c3997cSgwr {
238b4c3997cSgwr 	struct {
239b4c3997cSgwr 		n_long	h[RPC_HEADER_WORDS];
240b4c3997cSgwr 		n_long  d[64];
241b4c3997cSgwr 	} sdata;
242b4c3997cSgwr 	struct {
243b4c3997cSgwr 		n_long	h[RPC_HEADER_WORDS];
244b4c3997cSgwr 		n_long  d[128];
245b4c3997cSgwr 	} rdata;
246b4c3997cSgwr 	char serv_name[FNAME_SIZE];
2476f2a9404Sgwr 	char *send_tail, *recv_head;
248b4c3997cSgwr 	/* misc... */
249b4c3997cSgwr 	struct iodesc *d;
250*94ad267eSchristos 	uint32_t sn_len, path_len;
25110497fd2Schristos 	ssize_t rlen;
252b4c3997cSgwr 
253b4c3997cSgwr 	if (!(d = socktodesc(sockfd))) {
25410497fd2Schristos 		RPC_PRINTF(("%s: bad socket. %d\n", __func__, sockfd));
2551c038e68Sisaki 		return -1;
256b4c3997cSgwr 	}
257b4c3997cSgwr 
2586f2a9404Sgwr 	send_tail = (char *)sdata.d;
2596f2a9404Sgwr 	recv_head = (char *)rdata.d;
260b4c3997cSgwr 
261b4c3997cSgwr 	/*
262b4c3997cSgwr 	 * Build request message.
263b4c3997cSgwr 	 */
264b4c3997cSgwr 
265b4c3997cSgwr 	/* client name (hostname) */
266b4c3997cSgwr 	if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
26710497fd2Schristos 		RPC_PRINTF(("%s: bad client\n", __func__));
2681c038e68Sisaki 		return -1;
269b4c3997cSgwr 	}
270b4c3997cSgwr 
271b4c3997cSgwr 	/* key name (root or swap) */
27210497fd2Schristos 	if (xdr_string_encode(&send_tail, key, (uint32_t)strlen(key))) {
27310497fd2Schristos 		RPC_PRINTF(("%s: bad key\n", __func__));
2741c038e68Sisaki 		return -1;
275b4c3997cSgwr 	}
276b4c3997cSgwr 
277b4c3997cSgwr 	/* RPC: bootparam/getfile */
27810497fd2Schristos 	--rpc_port;
27910497fd2Schristos 	d->myport = htons((uint16_t)rpc_port);
280b4c3997cSgwr 	d->destip = bp_server_addr;
281b4c3997cSgwr 	/* rpc_call will set d->destport */
282b4c3997cSgwr 
283b4c3997cSgwr 	rlen = rpc_call(d,
284b4c3997cSgwr 		BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
28510497fd2Schristos 		sdata.d, (size_t)(send_tail - (char *)sdata.d),
286b4c3997cSgwr 		rdata.d, sizeof(rdata.d));
287b4c3997cSgwr 	if (rlen < 4) {
28810497fd2Schristos 		RPC_PRINTF(("%s: short reply\n", __func__));
289d9124da4Spk 		errno = EBADRPC;
2901c038e68Sisaki 		return -1;
291b4c3997cSgwr 	}
2926f2a9404Sgwr 	recv_head = (char *)rdata.d;
293b4c3997cSgwr 
294b4c3997cSgwr 	/*
295b4c3997cSgwr 	 * Parse result message.
296b4c3997cSgwr 	 */
297b4c3997cSgwr 
298b4c3997cSgwr 	/* server name */
299b4c3997cSgwr 	sn_len = FNAME_SIZE - 1;
300b4c3997cSgwr 	if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
30110497fd2Schristos 		RPC_PRINTF(("%s: bad server name\n", __func__));
3021c038e68Sisaki 		return -1;
303b4c3997cSgwr 	}
304b4c3997cSgwr 
305b4c3997cSgwr 	/* server IP address (mountd/NFS) */
306b4c3997cSgwr 	if (xdr_inaddr_decode(&recv_head, serv_addr)) {
30710497fd2Schristos 		RPC_PRINTF(("%s: bad server addr\n", __func__));
3081c038e68Sisaki 		return -1;
309b4c3997cSgwr 	}
310b4c3997cSgwr 
311b4c3997cSgwr 	/* server pathname */
312b4c3997cSgwr 	path_len = MAXPATHLEN - 1;
313b4c3997cSgwr 	if (xdr_string_decode(&recv_head, pathname, &path_len)) {
31410497fd2Schristos 		RPC_PRINTF(("%s: bad server path\n", __func__));
3151c038e68Sisaki 		return -1;
316b4c3997cSgwr 	}
317b4c3997cSgwr 
318b4c3997cSgwr 	/* success */
3191c038e68Sisaki 	return 0;
320b4c3997cSgwr }
321b4c3997cSgwr 
322b4c3997cSgwr 
323b4c3997cSgwr /*
324b4c3997cSgwr  * eXternal Data Representation routines.
325b4c3997cSgwr  * (but with non-standard args...)
326b4c3997cSgwr  */
327b4c3997cSgwr 
328b4c3997cSgwr 
329b4c3997cSgwr int
xdr_string_encode(char ** pkt,char * str,uint32_t len)33010497fd2Schristos xdr_string_encode(char **pkt, char *str, uint32_t len)
331b4c3997cSgwr {
33210497fd2Schristos 	uint32_t *lenp;
333b4c3997cSgwr 	char *datap;
33410497fd2Schristos 	uint32_t padlen = (len + 3) & ~3U;	/* padded length */
335b4c3997cSgwr 
3366f2a9404Sgwr 	/* The data will be int aligned. */
33710497fd2Schristos 	lenp = (uint32_t *)*pkt;
3386f2a9404Sgwr 	*pkt += sizeof(*lenp);
339b4c3997cSgwr 	*lenp = htonl(len);
340b4c3997cSgwr 
341b4c3997cSgwr 	datap = *pkt;
3426f2a9404Sgwr 	*pkt += padlen;
343e1b834bdSchristos 	(void)memcpy(datap, str, len);
344b4c3997cSgwr 
3451c038e68Sisaki 	return 0;
346b4c3997cSgwr }
347b4c3997cSgwr 
3481c038e68Sisaki /* len_p: bufsize - 1 */
349b4c3997cSgwr int
xdr_string_decode(char ** pkt,char * str,uint32_t * len_p)35010497fd2Schristos xdr_string_decode(char **pkt, char *str, uint32_t *len_p)
351b4c3997cSgwr {
35210497fd2Schristos 	uint32_t *lenp;
353b4c3997cSgwr 	char *datap;
35410497fd2Schristos 	uint32_t slen;	/* string length */
35510497fd2Schristos 	uint32_t plen;	/* padded length */
356b4c3997cSgwr 
3576f2a9404Sgwr 	/* The data will be int aligned. */
35810497fd2Schristos 	lenp = (uint32_t *)*pkt;
3596f2a9404Sgwr 	*pkt += sizeof(*lenp);
360b4c3997cSgwr 	slen = ntohl(*lenp);
36110497fd2Schristos 	plen = (slen + 3) & ~3U;
362b4c3997cSgwr 
363b4c3997cSgwr 	if (slen > *len_p)
364b4c3997cSgwr 		slen = *len_p;
365b4c3997cSgwr 	datap = *pkt;
3666f2a9404Sgwr 	*pkt += plen;
367e1b834bdSchristos 	(void)memcpy(str, datap, slen);
368b4c3997cSgwr 
369b4c3997cSgwr 	str[slen] = '\0';
370b4c3997cSgwr 	*len_p = slen;
371b4c3997cSgwr 
3721c038e68Sisaki 	return 0;
373b4c3997cSgwr }
374b4c3997cSgwr 
375b4c3997cSgwr 
3761c038e68Sisaki /* ia: network order */
377b4c3997cSgwr int
xdr_inaddr_encode(char ** pkt,struct in_addr ia)3781c038e68Sisaki xdr_inaddr_encode(char **pkt, struct in_addr ia)
379b4c3997cSgwr {
380b4c3997cSgwr 	struct xdr_inaddr *xi;
381b4c3997cSgwr 	u_char *cp;
38210497fd2Schristos 	uint32_t *ip;
383b4c3997cSgwr 	union {
3846f2a9404Sgwr 		n_long l;	/* network order */
385b4c3997cSgwr 		u_char c[4];
386b4c3997cSgwr 	} uia;
387b4c3997cSgwr 
3886f2a9404Sgwr 	/* The data will be int aligned. */
3896f2a9404Sgwr 	xi = (struct xdr_inaddr *)*pkt;
3906f2a9404Sgwr 	*pkt += sizeof(*xi);
391b4c3997cSgwr 	xi->atype = htonl(1);
392d9124da4Spk 	uia.l = ia.s_addr;
393b4c3997cSgwr 	cp = uia.c;
394*94ad267eSchristos 	ip = (uint32_t *)xi->addr;
3956f2a9404Sgwr 	/*
3966f2a9404Sgwr 	 * Note: the htonl() calls below DO NOT
3976f2a9404Sgwr 	 * imply that uia.l is in host order.
3986f2a9404Sgwr 	 * In fact this needs it in net order.
3996f2a9404Sgwr 	 */
40010497fd2Schristos 	*ip++ = htonl((uint32_t)*cp++);
40110497fd2Schristos 	*ip++ = htonl((uint32_t)*cp++);
40210497fd2Schristos 	*ip++ = htonl((uint32_t)*cp++);
40310497fd2Schristos 	*ip++ = htonl((uint32_t)*cp++);
404b4c3997cSgwr 
4051c038e68Sisaki 	return 0;
406b4c3997cSgwr }
407b4c3997cSgwr 
4081c038e68Sisaki /* ia: network order */
409b4c3997cSgwr int
xdr_inaddr_decode(char ** pkt,struct in_addr * ia)4101c038e68Sisaki xdr_inaddr_decode(char **pkt, struct in_addr *ia)
411b4c3997cSgwr {
412b4c3997cSgwr 	struct xdr_inaddr *xi;
413b4c3997cSgwr 	u_char *cp;
41410497fd2Schristos 	uint32_t *ip;
415b4c3997cSgwr 	union {
4166f2a9404Sgwr 		n_long l;	/* network order */
417b4c3997cSgwr 		u_char c[4];
418b4c3997cSgwr 	} uia;
419b4c3997cSgwr 
4206f2a9404Sgwr 	/* The data will be int aligned. */
4216f2a9404Sgwr 	xi = (struct xdr_inaddr *)*pkt;
4226f2a9404Sgwr 	*pkt += sizeof(*xi);
42310497fd2Schristos 	if (xi->atype != htonl((uint32_t)1)) {
42410497fd2Schristos 		RPC_PRINTF(("%s: bad addrtype=%d\n", __func__,
42510497fd2Schristos 		    ntohl((uint32_t)nxi->atype)));
4261c038e68Sisaki 		return -1;
427b4c3997cSgwr 	}
428b4c3997cSgwr 
429b4c3997cSgwr 	cp = uia.c;
430*94ad267eSchristos 	ip = (uint32_t *)xi->addr;
4316f2a9404Sgwr 	/*
4326f2a9404Sgwr 	 * Note: the ntohl() calls below DO NOT
4336f2a9404Sgwr 	 * imply that uia.l is in host order.
4346f2a9404Sgwr 	 * In fact this needs it in net order.
4356f2a9404Sgwr 	 */
43610497fd2Schristos 	*cp++ = (u_char)ntohl(*ip++);
43710497fd2Schristos 	*cp++ = (u_char)ntohl(*ip++);
43810497fd2Schristos 	*cp++ = (u_char)ntohl(*ip++);
43910497fd2Schristos 	*cp++ = (u_char)ntohl(*ip++);
440d9124da4Spk 	ia->s_addr = uia.l;
441b4c3997cSgwr 
4421c038e68Sisaki 	return 0;
443b4c3997cSgwr }
444