xref: /minix3/sys/lib/libsa/bootparam.c (revision 58a2b0008e28f606a7f7f5faaeaba4faac57a1ea)
1*58a2b000SEvgeniy Ivanov /*	$NetBSD: bootparam.c,v 1.19 2009/10/21 23:12:10 snj Exp $	*/
2*58a2b000SEvgeniy Ivanov 
3*58a2b000SEvgeniy Ivanov /*
4*58a2b000SEvgeniy Ivanov  * Copyright (c) 1995 Gordon W. Ross
5*58a2b000SEvgeniy Ivanov  * All rights reserved.
6*58a2b000SEvgeniy Ivanov  *
7*58a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
8*58a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
9*58a2b000SEvgeniy Ivanov  * are met:
10*58a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
11*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
12*58a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
13*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
14*58a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
15*58a2b000SEvgeniy Ivanov  *
16*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*58a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*58a2b000SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*58a2b000SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*58a2b000SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*58a2b000SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*58a2b000SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*58a2b000SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*58a2b000SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*58a2b000SEvgeniy Ivanov  */
27*58a2b000SEvgeniy Ivanov 
28*58a2b000SEvgeniy Ivanov /*
29*58a2b000SEvgeniy Ivanov  * RPC/bootparams
30*58a2b000SEvgeniy Ivanov  */
31*58a2b000SEvgeniy Ivanov 
32*58a2b000SEvgeniy Ivanov #include <sys/param.h>
33*58a2b000SEvgeniy Ivanov #include <sys/socket.h>
34*58a2b000SEvgeniy Ivanov 
35*58a2b000SEvgeniy Ivanov #include <net/if.h>
36*58a2b000SEvgeniy Ivanov 
37*58a2b000SEvgeniy Ivanov #include <netinet/in.h>
38*58a2b000SEvgeniy Ivanov #include <netinet/in_systm.h>
39*58a2b000SEvgeniy Ivanov 
40*58a2b000SEvgeniy Ivanov #ifdef _STANDALONE
41*58a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h>
42*58a2b000SEvgeniy Ivanov #else
43*58a2b000SEvgeniy Ivanov #include <string.h>
44*58a2b000SEvgeniy Ivanov #endif
45*58a2b000SEvgeniy Ivanov 
46*58a2b000SEvgeniy Ivanov #include "rpcv2.h"
47*58a2b000SEvgeniy Ivanov 
48*58a2b000SEvgeniy Ivanov #include "stand.h"
49*58a2b000SEvgeniy Ivanov #include "net.h"
50*58a2b000SEvgeniy Ivanov #include "rpc.h"
51*58a2b000SEvgeniy Ivanov #include "bootparam.h"
52*58a2b000SEvgeniy Ivanov 
53*58a2b000SEvgeniy Ivanov #ifdef DEBUG_RPC
54*58a2b000SEvgeniy Ivanov #define RPC_PRINTF(a)	printf a
55*58a2b000SEvgeniy Ivanov #else
56*58a2b000SEvgeniy Ivanov #define RPC_PRINTF(a)
57*58a2b000SEvgeniy Ivanov #endif
58*58a2b000SEvgeniy Ivanov 
59*58a2b000SEvgeniy Ivanov struct in_addr	bp_server_addr;	/* net order */
60*58a2b000SEvgeniy Ivanov n_short		bp_server_port;	/* net order */
61*58a2b000SEvgeniy Ivanov 
62*58a2b000SEvgeniy Ivanov int		hostnamelen;
63*58a2b000SEvgeniy Ivanov char		domainname[FNAME_SIZE]; /* our DNS domain */
64*58a2b000SEvgeniy Ivanov int		domainnamelen;
65*58a2b000SEvgeniy Ivanov 
66*58a2b000SEvgeniy Ivanov /*
67*58a2b000SEvgeniy Ivanov  * RPC definitions for bootparamd
68*58a2b000SEvgeniy Ivanov  */
69*58a2b000SEvgeniy Ivanov #define	BOOTPARAM_PROG		100026
70*58a2b000SEvgeniy Ivanov #define	BOOTPARAM_VERS		1
71*58a2b000SEvgeniy Ivanov #define BOOTPARAM_WHOAMI	1
72*58a2b000SEvgeniy Ivanov #define BOOTPARAM_GETFILE	2
73*58a2b000SEvgeniy Ivanov 
74*58a2b000SEvgeniy Ivanov /*
75*58a2b000SEvgeniy Ivanov  * Inet address in RPC messages
76*58a2b000SEvgeniy Ivanov  * (Note, really four ints, NOT chars.  Blech.)
77*58a2b000SEvgeniy Ivanov  */
78*58a2b000SEvgeniy Ivanov struct xdr_inaddr {
79*58a2b000SEvgeniy Ivanov 	u_int32_t  atype;
80*58a2b000SEvgeniy Ivanov 	int32_t	addr[4];
81*58a2b000SEvgeniy Ivanov };
82*58a2b000SEvgeniy Ivanov 
83*58a2b000SEvgeniy Ivanov int xdr_inaddr_encode(char **, struct in_addr);
84*58a2b000SEvgeniy Ivanov int xdr_inaddr_decode(char **, struct in_addr *);
85*58a2b000SEvgeniy Ivanov 
86*58a2b000SEvgeniy Ivanov int xdr_string_encode(char **, char *, int);
87*58a2b000SEvgeniy Ivanov int xdr_string_decode(char **, char *, int *);
88*58a2b000SEvgeniy Ivanov 
89*58a2b000SEvgeniy Ivanov 
90*58a2b000SEvgeniy Ivanov /*
91*58a2b000SEvgeniy Ivanov  * RPC: bootparam/whoami
92*58a2b000SEvgeniy Ivanov  * Given client IP address, get:
93*58a2b000SEvgeniy Ivanov  *	client name	(hostname)
94*58a2b000SEvgeniy Ivanov  *	domain name (domainname)
95*58a2b000SEvgeniy Ivanov  *	gateway address
96*58a2b000SEvgeniy Ivanov  *
97*58a2b000SEvgeniy Ivanov  * The hostname and domainname are set here for convenience.
98*58a2b000SEvgeniy Ivanov  *
99*58a2b000SEvgeniy Ivanov  * Note - bpsin is initialized to the broadcast address,
100*58a2b000SEvgeniy Ivanov  * and will be replaced with the bootparam server address
101*58a2b000SEvgeniy Ivanov  * after this call is complete.  Have to use PMAP_PROC_CALL
102*58a2b000SEvgeniy Ivanov  * to make sure we get responses only from a servers that
103*58a2b000SEvgeniy Ivanov  * know about us (don't want to broadcast a getport call).
104*58a2b000SEvgeniy Ivanov  */
105*58a2b000SEvgeniy Ivanov int
bp_whoami(int sockfd)106*58a2b000SEvgeniy Ivanov bp_whoami(int sockfd)
107*58a2b000SEvgeniy Ivanov {
108*58a2b000SEvgeniy Ivanov 	/* RPC structures for PMAPPROC_CALLIT */
109*58a2b000SEvgeniy Ivanov 	struct args {
110*58a2b000SEvgeniy Ivanov 		u_int32_t prog;
111*58a2b000SEvgeniy Ivanov 		u_int32_t vers;
112*58a2b000SEvgeniy Ivanov 		u_int32_t proc;
113*58a2b000SEvgeniy Ivanov 		u_int32_t arglen;
114*58a2b000SEvgeniy Ivanov 		struct xdr_inaddr xina;
115*58a2b000SEvgeniy Ivanov 	} *args;
116*58a2b000SEvgeniy Ivanov 	struct repl {
117*58a2b000SEvgeniy Ivanov 		u_int16_t _pad;
118*58a2b000SEvgeniy Ivanov 		u_int16_t port;
119*58a2b000SEvgeniy Ivanov 		u_int32_t encap_len;
120*58a2b000SEvgeniy Ivanov 		/* encapsulated data here */
121*58a2b000SEvgeniy Ivanov 		n_long  capsule[64];
122*58a2b000SEvgeniy Ivanov 	} *repl;
123*58a2b000SEvgeniy Ivanov 	struct {
124*58a2b000SEvgeniy Ivanov 		n_long	h[RPC_HEADER_WORDS];
125*58a2b000SEvgeniy Ivanov 		struct args d;
126*58a2b000SEvgeniy Ivanov 	} sdata;
127*58a2b000SEvgeniy Ivanov 	struct {
128*58a2b000SEvgeniy Ivanov 		n_long	h[RPC_HEADER_WORDS];
129*58a2b000SEvgeniy Ivanov 		struct repl d;
130*58a2b000SEvgeniy Ivanov 	} rdata;
131*58a2b000SEvgeniy Ivanov 	char *send_tail, *recv_head;
132*58a2b000SEvgeniy Ivanov 	struct iodesc *d;
133*58a2b000SEvgeniy Ivanov 	int len, x;
134*58a2b000SEvgeniy Ivanov 
135*58a2b000SEvgeniy Ivanov 	RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
136*58a2b000SEvgeniy Ivanov 
137*58a2b000SEvgeniy Ivanov 	if (!(d = socktodesc(sockfd))) {
138*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
139*58a2b000SEvgeniy Ivanov 		return -1;
140*58a2b000SEvgeniy Ivanov 	}
141*58a2b000SEvgeniy Ivanov 	args = &sdata.d;
142*58a2b000SEvgeniy Ivanov 	repl = &rdata.d;
143*58a2b000SEvgeniy Ivanov 
144*58a2b000SEvgeniy Ivanov 	/*
145*58a2b000SEvgeniy Ivanov 	 * Build request args for PMAPPROC_CALLIT.
146*58a2b000SEvgeniy Ivanov 	 */
147*58a2b000SEvgeniy Ivanov 	args->prog = htonl(BOOTPARAM_PROG);
148*58a2b000SEvgeniy Ivanov 	args->vers = htonl(BOOTPARAM_VERS);
149*58a2b000SEvgeniy Ivanov 	args->proc = htonl(BOOTPARAM_WHOAMI);
150*58a2b000SEvgeniy Ivanov 	args->arglen = htonl(sizeof(struct xdr_inaddr));
151*58a2b000SEvgeniy Ivanov 	send_tail = (char *)&args->xina;
152*58a2b000SEvgeniy Ivanov 
153*58a2b000SEvgeniy Ivanov 	/*
154*58a2b000SEvgeniy Ivanov 	 * append encapsulated data (client IP address)
155*58a2b000SEvgeniy Ivanov 	 */
156*58a2b000SEvgeniy Ivanov 	if (xdr_inaddr_encode(&send_tail, myip))
157*58a2b000SEvgeniy Ivanov 		return -1;
158*58a2b000SEvgeniy Ivanov 
159*58a2b000SEvgeniy Ivanov 	/* RPC: portmap/callit */
160*58a2b000SEvgeniy Ivanov 	d->myport = htons(--rpc_port);
161*58a2b000SEvgeniy Ivanov 	d->destip.s_addr = INADDR_BROADCAST;	/* XXX: subnet bcast? */
162*58a2b000SEvgeniy Ivanov 	/* rpc_call will set d->destport */
163*58a2b000SEvgeniy Ivanov 
164*58a2b000SEvgeniy Ivanov 	len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
165*58a2b000SEvgeniy Ivanov 				  args, send_tail - (char *)args,
166*58a2b000SEvgeniy Ivanov 				  repl, sizeof(*repl));
167*58a2b000SEvgeniy Ivanov 	if (len < 8) {
168*58a2b000SEvgeniy Ivanov 		printf("bootparamd: 'whoami' call failed\n");
169*58a2b000SEvgeniy Ivanov 		return -1;
170*58a2b000SEvgeniy Ivanov 	}
171*58a2b000SEvgeniy Ivanov 
172*58a2b000SEvgeniy Ivanov 	/* Save bootparam server address (from IP header). */
173*58a2b000SEvgeniy Ivanov 	rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
174*58a2b000SEvgeniy Ivanov 
175*58a2b000SEvgeniy Ivanov 	/*
176*58a2b000SEvgeniy Ivanov 	 * Note that bp_server_port is now 111 due to the
177*58a2b000SEvgeniy Ivanov 	 * indirect call (using PMAPPROC_CALLIT), so get the
178*58a2b000SEvgeniy Ivanov 	 * actual port number from the reply data.
179*58a2b000SEvgeniy Ivanov 	 */
180*58a2b000SEvgeniy Ivanov 	bp_server_port = repl->port;
181*58a2b000SEvgeniy Ivanov 
182*58a2b000SEvgeniy Ivanov 	RPC_PRINTF(("bp_whoami: server at %s:%d\n",
183*58a2b000SEvgeniy Ivanov 	    inet_ntoa(bp_server_addr), ntohs(bp_server_port)));
184*58a2b000SEvgeniy Ivanov 
185*58a2b000SEvgeniy Ivanov 	/* We have just done a portmap call, so cache the portnum. */
186*58a2b000SEvgeniy Ivanov 	rpc_pmap_putcache(bp_server_addr,
187*58a2b000SEvgeniy Ivanov 			  BOOTPARAM_PROG,
188*58a2b000SEvgeniy Ivanov 			  BOOTPARAM_VERS,
189*58a2b000SEvgeniy Ivanov 			  (int)ntohs(bp_server_port));
190*58a2b000SEvgeniy Ivanov 
191*58a2b000SEvgeniy Ivanov 	/*
192*58a2b000SEvgeniy Ivanov 	 * Parse the encapsulated results from bootparam/whoami
193*58a2b000SEvgeniy Ivanov 	 */
194*58a2b000SEvgeniy Ivanov 	x = ntohl(repl->encap_len);
195*58a2b000SEvgeniy Ivanov 	if (len < x) {
196*58a2b000SEvgeniy Ivanov 		printf("bp_whoami: short reply, %d < %d\n", len, x);
197*58a2b000SEvgeniy Ivanov 		return -1;
198*58a2b000SEvgeniy Ivanov 	}
199*58a2b000SEvgeniy Ivanov 	recv_head = (char *)repl->capsule;
200*58a2b000SEvgeniy Ivanov 
201*58a2b000SEvgeniy Ivanov 	/* client name */
202*58a2b000SEvgeniy Ivanov 	hostnamelen = MAXHOSTNAMELEN-1;
203*58a2b000SEvgeniy Ivanov 	if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
204*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_whoami: bad hostname\n"));
205*58a2b000SEvgeniy Ivanov 		return -1;
206*58a2b000SEvgeniy Ivanov 	}
207*58a2b000SEvgeniy Ivanov 
208*58a2b000SEvgeniy Ivanov 	/* domain name */
209*58a2b000SEvgeniy Ivanov 	domainnamelen = MAXHOSTNAMELEN-1;
210*58a2b000SEvgeniy Ivanov 	if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
211*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_whoami: bad domainname\n"));
212*58a2b000SEvgeniy Ivanov 		return -1;
213*58a2b000SEvgeniy Ivanov 	}
214*58a2b000SEvgeniy Ivanov 
215*58a2b000SEvgeniy Ivanov 	/* gateway address */
216*58a2b000SEvgeniy Ivanov 	if (xdr_inaddr_decode(&recv_head, &gateip)) {
217*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_whoami: bad gateway\n"));
218*58a2b000SEvgeniy Ivanov 		return -1;
219*58a2b000SEvgeniy Ivanov 	}
220*58a2b000SEvgeniy Ivanov 
221*58a2b000SEvgeniy Ivanov 	/* success */
222*58a2b000SEvgeniy Ivanov 	return 0;
223*58a2b000SEvgeniy Ivanov }
224*58a2b000SEvgeniy Ivanov 
225*58a2b000SEvgeniy Ivanov 
226*58a2b000SEvgeniy Ivanov /*
227*58a2b000SEvgeniy Ivanov  * RPC: bootparam/getfile
228*58a2b000SEvgeniy Ivanov  * Given client name and file "key", get:
229*58a2b000SEvgeniy Ivanov  *	server name
230*58a2b000SEvgeniy Ivanov  *	server IP address
231*58a2b000SEvgeniy Ivanov  *	server pathname
232*58a2b000SEvgeniy Ivanov  */
233*58a2b000SEvgeniy Ivanov int
bp_getfile(int sockfd,char * key,struct in_addr * serv_addr,char * pathname)234*58a2b000SEvgeniy Ivanov bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
235*58a2b000SEvgeniy Ivanov {
236*58a2b000SEvgeniy Ivanov 	struct {
237*58a2b000SEvgeniy Ivanov 		n_long	h[RPC_HEADER_WORDS];
238*58a2b000SEvgeniy Ivanov 		n_long  d[64];
239*58a2b000SEvgeniy Ivanov 	} sdata;
240*58a2b000SEvgeniy Ivanov 	struct {
241*58a2b000SEvgeniy Ivanov 		n_long	h[RPC_HEADER_WORDS];
242*58a2b000SEvgeniy Ivanov 		n_long  d[128];
243*58a2b000SEvgeniy Ivanov 	} rdata;
244*58a2b000SEvgeniy Ivanov 	char serv_name[FNAME_SIZE];
245*58a2b000SEvgeniy Ivanov 	char *send_tail, *recv_head;
246*58a2b000SEvgeniy Ivanov 	/* misc... */
247*58a2b000SEvgeniy Ivanov 	struct iodesc *d;
248*58a2b000SEvgeniy Ivanov 	int sn_len, path_len, rlen;
249*58a2b000SEvgeniy Ivanov 
250*58a2b000SEvgeniy Ivanov 	if (!(d = socktodesc(sockfd))) {
251*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
252*58a2b000SEvgeniy Ivanov 		return -1;
253*58a2b000SEvgeniy Ivanov 	}
254*58a2b000SEvgeniy Ivanov 
255*58a2b000SEvgeniy Ivanov 	send_tail = (char *)sdata.d;
256*58a2b000SEvgeniy Ivanov 	recv_head = (char *)rdata.d;
257*58a2b000SEvgeniy Ivanov 
258*58a2b000SEvgeniy Ivanov 	/*
259*58a2b000SEvgeniy Ivanov 	 * Build request message.
260*58a2b000SEvgeniy Ivanov 	 */
261*58a2b000SEvgeniy Ivanov 
262*58a2b000SEvgeniy Ivanov 	/* client name (hostname) */
263*58a2b000SEvgeniy Ivanov 	if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
264*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad client\n"));
265*58a2b000SEvgeniy Ivanov 		return -1;
266*58a2b000SEvgeniy Ivanov 	}
267*58a2b000SEvgeniy Ivanov 
268*58a2b000SEvgeniy Ivanov 	/* key name (root or swap) */
269*58a2b000SEvgeniy Ivanov 	if (xdr_string_encode(&send_tail, key, strlen(key))) {
270*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad key\n"));
271*58a2b000SEvgeniy Ivanov 		return -1;
272*58a2b000SEvgeniy Ivanov 	}
273*58a2b000SEvgeniy Ivanov 
274*58a2b000SEvgeniy Ivanov 	/* RPC: bootparam/getfile */
275*58a2b000SEvgeniy Ivanov 	d->myport = htons(--rpc_port);
276*58a2b000SEvgeniy Ivanov 	d->destip = bp_server_addr;
277*58a2b000SEvgeniy Ivanov 	/* rpc_call will set d->destport */
278*58a2b000SEvgeniy Ivanov 
279*58a2b000SEvgeniy Ivanov 	rlen = rpc_call(d,
280*58a2b000SEvgeniy Ivanov 		BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
281*58a2b000SEvgeniy Ivanov 		sdata.d, send_tail - (char *)sdata.d,
282*58a2b000SEvgeniy Ivanov 		rdata.d, sizeof(rdata.d));
283*58a2b000SEvgeniy Ivanov 	if (rlen < 4) {
284*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: short reply\n"));
285*58a2b000SEvgeniy Ivanov 		errno = EBADRPC;
286*58a2b000SEvgeniy Ivanov 		return -1;
287*58a2b000SEvgeniy Ivanov 	}
288*58a2b000SEvgeniy Ivanov 	recv_head = (char *)rdata.d;
289*58a2b000SEvgeniy Ivanov 
290*58a2b000SEvgeniy Ivanov 	/*
291*58a2b000SEvgeniy Ivanov 	 * Parse result message.
292*58a2b000SEvgeniy Ivanov 	 */
293*58a2b000SEvgeniy Ivanov 
294*58a2b000SEvgeniy Ivanov 	/* server name */
295*58a2b000SEvgeniy Ivanov 	sn_len = FNAME_SIZE-1;
296*58a2b000SEvgeniy Ivanov 	if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
297*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad server name\n"));
298*58a2b000SEvgeniy Ivanov 		return -1;
299*58a2b000SEvgeniy Ivanov 	}
300*58a2b000SEvgeniy Ivanov 
301*58a2b000SEvgeniy Ivanov 	/* server IP address (mountd/NFS) */
302*58a2b000SEvgeniy Ivanov 	if (xdr_inaddr_decode(&recv_head, serv_addr)) {
303*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad server addr\n"));
304*58a2b000SEvgeniy Ivanov 		return -1;
305*58a2b000SEvgeniy Ivanov 	}
306*58a2b000SEvgeniy Ivanov 
307*58a2b000SEvgeniy Ivanov 	/* server pathname */
308*58a2b000SEvgeniy Ivanov 	path_len = MAXPATHLEN - 1;
309*58a2b000SEvgeniy Ivanov 	if (xdr_string_decode(&recv_head, pathname, &path_len)) {
310*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("bp_getfile: bad server path\n"));
311*58a2b000SEvgeniy Ivanov 		return -1;
312*58a2b000SEvgeniy Ivanov 	}
313*58a2b000SEvgeniy Ivanov 
314*58a2b000SEvgeniy Ivanov 	/* success */
315*58a2b000SEvgeniy Ivanov 	return 0;
316*58a2b000SEvgeniy Ivanov }
317*58a2b000SEvgeniy Ivanov 
318*58a2b000SEvgeniy Ivanov 
319*58a2b000SEvgeniy Ivanov /*
320*58a2b000SEvgeniy Ivanov  * eXternal Data Representation routines.
321*58a2b000SEvgeniy Ivanov  * (but with non-standard args...)
322*58a2b000SEvgeniy Ivanov  */
323*58a2b000SEvgeniy Ivanov 
324*58a2b000SEvgeniy Ivanov 
325*58a2b000SEvgeniy Ivanov int
xdr_string_encode(char ** pkt,char * str,int len)326*58a2b000SEvgeniy Ivanov xdr_string_encode(char **pkt, char *str, int len)
327*58a2b000SEvgeniy Ivanov {
328*58a2b000SEvgeniy Ivanov 	u_int32_t *lenp;
329*58a2b000SEvgeniy Ivanov 	char *datap;
330*58a2b000SEvgeniy Ivanov 	int padlen = (len + 3) & ~3;	/* padded length */
331*58a2b000SEvgeniy Ivanov 
332*58a2b000SEvgeniy Ivanov 	/* The data will be int aligned. */
333*58a2b000SEvgeniy Ivanov 	lenp = (u_int32_t *)*pkt;
334*58a2b000SEvgeniy Ivanov 	*pkt += sizeof(*lenp);
335*58a2b000SEvgeniy Ivanov 	*lenp = htonl(len);
336*58a2b000SEvgeniy Ivanov 
337*58a2b000SEvgeniy Ivanov 	datap = *pkt;
338*58a2b000SEvgeniy Ivanov 	*pkt += padlen;
339*58a2b000SEvgeniy Ivanov 	(void)memcpy(datap, str, len);
340*58a2b000SEvgeniy Ivanov 
341*58a2b000SEvgeniy Ivanov 	return 0;
342*58a2b000SEvgeniy Ivanov }
343*58a2b000SEvgeniy Ivanov 
344*58a2b000SEvgeniy Ivanov /* len_p: bufsize - 1 */
345*58a2b000SEvgeniy Ivanov int
xdr_string_decode(char ** pkt,char * str,int * len_p)346*58a2b000SEvgeniy Ivanov xdr_string_decode(char **pkt, char *str, int *len_p)
347*58a2b000SEvgeniy Ivanov {
348*58a2b000SEvgeniy Ivanov 	u_int32_t *lenp;
349*58a2b000SEvgeniy Ivanov 	char *datap;
350*58a2b000SEvgeniy Ivanov 	int slen;	/* string length */
351*58a2b000SEvgeniy Ivanov 	int plen;	/* padded length */
352*58a2b000SEvgeniy Ivanov 
353*58a2b000SEvgeniy Ivanov 	/* The data will be int aligned. */
354*58a2b000SEvgeniy Ivanov 	lenp = (u_int32_t *)*pkt;
355*58a2b000SEvgeniy Ivanov 	*pkt += sizeof(*lenp);
356*58a2b000SEvgeniy Ivanov 	slen = ntohl(*lenp);
357*58a2b000SEvgeniy Ivanov 	plen = (slen + 3) & ~3;
358*58a2b000SEvgeniy Ivanov 
359*58a2b000SEvgeniy Ivanov 	if (slen > *len_p)
360*58a2b000SEvgeniy Ivanov 		slen = *len_p;
361*58a2b000SEvgeniy Ivanov 	datap = *pkt;
362*58a2b000SEvgeniy Ivanov 	*pkt += plen;
363*58a2b000SEvgeniy Ivanov 	(void)memcpy(str, datap, slen);
364*58a2b000SEvgeniy Ivanov 
365*58a2b000SEvgeniy Ivanov 	str[slen] = '\0';
366*58a2b000SEvgeniy Ivanov 	*len_p = slen;
367*58a2b000SEvgeniy Ivanov 
368*58a2b000SEvgeniy Ivanov 	return 0;
369*58a2b000SEvgeniy Ivanov }
370*58a2b000SEvgeniy Ivanov 
371*58a2b000SEvgeniy Ivanov 
372*58a2b000SEvgeniy Ivanov /* ia: network order */
373*58a2b000SEvgeniy Ivanov int
xdr_inaddr_encode(char ** pkt,struct in_addr ia)374*58a2b000SEvgeniy Ivanov xdr_inaddr_encode(char **pkt, struct in_addr ia)
375*58a2b000SEvgeniy Ivanov {
376*58a2b000SEvgeniy Ivanov 	struct xdr_inaddr *xi;
377*58a2b000SEvgeniy Ivanov 	u_char *cp;
378*58a2b000SEvgeniy Ivanov 	int32_t *ip;
379*58a2b000SEvgeniy Ivanov 	union {
380*58a2b000SEvgeniy Ivanov 		n_long l;	/* network order */
381*58a2b000SEvgeniy Ivanov 		u_char c[4];
382*58a2b000SEvgeniy Ivanov 	} uia;
383*58a2b000SEvgeniy Ivanov 
384*58a2b000SEvgeniy Ivanov 	/* The data will be int aligned. */
385*58a2b000SEvgeniy Ivanov 	xi = (struct xdr_inaddr *)*pkt;
386*58a2b000SEvgeniy Ivanov 	*pkt += sizeof(*xi);
387*58a2b000SEvgeniy Ivanov 	xi->atype = htonl(1);
388*58a2b000SEvgeniy Ivanov 	uia.l = ia.s_addr;
389*58a2b000SEvgeniy Ivanov 	cp = uia.c;
390*58a2b000SEvgeniy Ivanov 	ip = xi->addr;
391*58a2b000SEvgeniy Ivanov 	/*
392*58a2b000SEvgeniy Ivanov 	 * Note: the htonl() calls below DO NOT
393*58a2b000SEvgeniy Ivanov 	 * imply that uia.l is in host order.
394*58a2b000SEvgeniy Ivanov 	 * In fact this needs it in net order.
395*58a2b000SEvgeniy Ivanov 	 */
396*58a2b000SEvgeniy Ivanov 	*ip++ = htonl((unsigned int)*cp++);
397*58a2b000SEvgeniy Ivanov 	*ip++ = htonl((unsigned int)*cp++);
398*58a2b000SEvgeniy Ivanov 	*ip++ = htonl((unsigned int)*cp++);
399*58a2b000SEvgeniy Ivanov 	*ip++ = htonl((unsigned int)*cp++);
400*58a2b000SEvgeniy Ivanov 
401*58a2b000SEvgeniy Ivanov 	return 0;
402*58a2b000SEvgeniy Ivanov }
403*58a2b000SEvgeniy Ivanov 
404*58a2b000SEvgeniy Ivanov /* ia: network order */
405*58a2b000SEvgeniy Ivanov int
xdr_inaddr_decode(char ** pkt,struct in_addr * ia)406*58a2b000SEvgeniy Ivanov xdr_inaddr_decode(char **pkt, struct in_addr *ia)
407*58a2b000SEvgeniy Ivanov {
408*58a2b000SEvgeniy Ivanov 	struct xdr_inaddr *xi;
409*58a2b000SEvgeniy Ivanov 	u_char *cp;
410*58a2b000SEvgeniy Ivanov 	int32_t *ip;
411*58a2b000SEvgeniy Ivanov 	union {
412*58a2b000SEvgeniy Ivanov 		n_long l;	/* network order */
413*58a2b000SEvgeniy Ivanov 		u_char c[4];
414*58a2b000SEvgeniy Ivanov 	} uia;
415*58a2b000SEvgeniy Ivanov 
416*58a2b000SEvgeniy Ivanov 	/* The data will be int aligned. */
417*58a2b000SEvgeniy Ivanov 	xi = (struct xdr_inaddr *)*pkt;
418*58a2b000SEvgeniy Ivanov 	*pkt += sizeof(*xi);
419*58a2b000SEvgeniy Ivanov 	if (xi->atype != htonl(1)) {
420*58a2b000SEvgeniy Ivanov 		RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n",
421*58a2b000SEvgeniy Ivanov 		    ntohl(xi->atype)));
422*58a2b000SEvgeniy Ivanov 		return -1;
423*58a2b000SEvgeniy Ivanov 	}
424*58a2b000SEvgeniy Ivanov 
425*58a2b000SEvgeniy Ivanov 	cp = uia.c;
426*58a2b000SEvgeniy Ivanov 	ip = xi->addr;
427*58a2b000SEvgeniy Ivanov 	/*
428*58a2b000SEvgeniy Ivanov 	 * Note: the ntohl() calls below DO NOT
429*58a2b000SEvgeniy Ivanov 	 * imply that uia.l is in host order.
430*58a2b000SEvgeniy Ivanov 	 * In fact this needs it in net order.
431*58a2b000SEvgeniy Ivanov 	 */
432*58a2b000SEvgeniy Ivanov 	*cp++ = ntohl(*ip++);
433*58a2b000SEvgeniy Ivanov 	*cp++ = ntohl(*ip++);
434*58a2b000SEvgeniy Ivanov 	*cp++ = ntohl(*ip++);
435*58a2b000SEvgeniy Ivanov 	*cp++ = ntohl(*ip++);
436*58a2b000SEvgeniy Ivanov 	ia->s_addr = uia.l;
437*58a2b000SEvgeniy Ivanov 
438*58a2b000SEvgeniy Ivanov 	return 0;
439*58a2b000SEvgeniy Ivanov }
440