xref: /csrg-svn/lib/librpc/rpc/xdr.c (revision 45095)
1*45095Smckusick /* @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC */
2*45095Smckusick /*
3*45095Smckusick  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4*45095Smckusick  * unrestricted use provided that this legend is included on all tape
5*45095Smckusick  * media and as a part of the software program in whole or part.  Users
6*45095Smckusick  * may copy or modify Sun RPC without charge, but are not authorized
7*45095Smckusick  * to license or distribute it to anyone else except as part of a product or
8*45095Smckusick  * program developed by the user.
9*45095Smckusick  *
10*45095Smckusick  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11*45095Smckusick  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12*45095Smckusick  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13*45095Smckusick  *
14*45095Smckusick  * Sun RPC is provided with no support and without any obligation on the
15*45095Smckusick  * part of Sun Microsystems, Inc. to assist in its use, correction,
16*45095Smckusick  * modification or enhancement.
17*45095Smckusick  *
18*45095Smckusick  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19*45095Smckusick  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20*45095Smckusick  * OR ANY PART THEREOF.
21*45095Smckusick  *
22*45095Smckusick  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23*45095Smckusick  * or profits or other special, indirect and consequential damages, even if
24*45095Smckusick  * Sun has been advised of the possibility of such damages.
25*45095Smckusick  *
26*45095Smckusick  * Sun Microsystems, Inc.
27*45095Smckusick  * 2550 Garcia Avenue
28*45095Smckusick  * Mountain View, California  94043
29*45095Smckusick  */
30*45095Smckusick #if !defined(lint) && defined(SCCSIDS)
31*45095Smckusick static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
32*45095Smckusick #endif
33*45095Smckusick 
34*45095Smckusick /*
35*45095Smckusick  * xdr.c, Generic XDR routines implementation.
36*45095Smckusick  *
37*45095Smckusick  * Copyright (C) 1986, Sun Microsystems, Inc.
38*45095Smckusick  *
39*45095Smckusick  * These are the "generic" xdr routines used to serialize and de-serialize
40*45095Smckusick  * most common data items.  See xdr.h for more info on the interface to
41*45095Smckusick  * xdr.
42*45095Smckusick  */
43*45095Smckusick 
44*45095Smckusick #include <stdio.h>
45*45095Smckusick char *malloc();
46*45095Smckusick 
47*45095Smckusick #include <rpc/types.h>
48*45095Smckusick #include <rpc/xdr.h>
49*45095Smckusick 
50*45095Smckusick /*
51*45095Smckusick  * constants specific to the xdr "protocol"
52*45095Smckusick  */
53*45095Smckusick #define XDR_FALSE	((long) 0)
54*45095Smckusick #define XDR_TRUE	((long) 1)
55*45095Smckusick #define LASTUNSIGNED	((u_int) 0-1)
56*45095Smckusick 
57*45095Smckusick /*
58*45095Smckusick  * for unit alignment
59*45095Smckusick  */
60*45095Smckusick static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
61*45095Smckusick 
62*45095Smckusick /*
63*45095Smckusick  * Free a data structure using XDR
64*45095Smckusick  * Not a filter, but a convenient utility nonetheless
65*45095Smckusick  */
66*45095Smckusick void
67*45095Smckusick xdr_free(proc, objp)
68*45095Smckusick 	xdrproc_t proc;
69*45095Smckusick 	char *objp;
70*45095Smckusick {
71*45095Smckusick 	XDR x;
72*45095Smckusick 
73*45095Smckusick 	x.x_op = XDR_FREE;
74*45095Smckusick 	(*proc)(&x, objp);
75*45095Smckusick }
76*45095Smckusick 
77*45095Smckusick /*
78*45095Smckusick  * XDR nothing
79*45095Smckusick  */
80*45095Smckusick bool_t
81*45095Smckusick xdr_void(/* xdrs, addr */)
82*45095Smckusick 	/* XDR *xdrs; */
83*45095Smckusick 	/* caddr_t addr; */
84*45095Smckusick {
85*45095Smckusick 
86*45095Smckusick 	return (TRUE);
87*45095Smckusick }
88*45095Smckusick 
89*45095Smckusick /*
90*45095Smckusick  * XDR integers
91*45095Smckusick  */
92*45095Smckusick bool_t
93*45095Smckusick xdr_int(xdrs, ip)
94*45095Smckusick 	XDR *xdrs;
95*45095Smckusick 	int *ip;
96*45095Smckusick {
97*45095Smckusick 
98*45095Smckusick #ifdef lint
99*45095Smckusick 	(void) (xdr_short(xdrs, (short *)ip));
100*45095Smckusick 	return (xdr_long(xdrs, (long *)ip));
101*45095Smckusick #else
102*45095Smckusick 	if (sizeof (int) == sizeof (long)) {
103*45095Smckusick 		return (xdr_long(xdrs, (long *)ip));
104*45095Smckusick 	} else {
105*45095Smckusick 		return (xdr_short(xdrs, (short *)ip));
106*45095Smckusick 	}
107*45095Smckusick #endif
108*45095Smckusick }
109*45095Smckusick 
110*45095Smckusick /*
111*45095Smckusick  * XDR unsigned integers
112*45095Smckusick  */
113*45095Smckusick bool_t
114*45095Smckusick xdr_u_int(xdrs, up)
115*45095Smckusick 	XDR *xdrs;
116*45095Smckusick 	u_int *up;
117*45095Smckusick {
118*45095Smckusick 
119*45095Smckusick #ifdef lint
120*45095Smckusick 	(void) (xdr_short(xdrs, (short *)up));
121*45095Smckusick 	return (xdr_u_long(xdrs, (u_long *)up));
122*45095Smckusick #else
123*45095Smckusick 	if (sizeof (u_int) == sizeof (u_long)) {
124*45095Smckusick 		return (xdr_u_long(xdrs, (u_long *)up));
125*45095Smckusick 	} else {
126*45095Smckusick 		return (xdr_short(xdrs, (short *)up));
127*45095Smckusick 	}
128*45095Smckusick #endif
129*45095Smckusick }
130*45095Smckusick 
131*45095Smckusick /*
132*45095Smckusick  * XDR long integers
133*45095Smckusick  * same as xdr_u_long - open coded to save a proc call!
134*45095Smckusick  */
135*45095Smckusick bool_t
136*45095Smckusick xdr_long(xdrs, lp)
137*45095Smckusick 	register XDR *xdrs;
138*45095Smckusick 	long *lp;
139*45095Smckusick {
140*45095Smckusick 
141*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE)
142*45095Smckusick 		return (XDR_PUTLONG(xdrs, lp));
143*45095Smckusick 
144*45095Smckusick 	if (xdrs->x_op == XDR_DECODE)
145*45095Smckusick 		return (XDR_GETLONG(xdrs, lp));
146*45095Smckusick 
147*45095Smckusick 	if (xdrs->x_op == XDR_FREE)
148*45095Smckusick 		return (TRUE);
149*45095Smckusick 
150*45095Smckusick 	return (FALSE);
151*45095Smckusick }
152*45095Smckusick 
153*45095Smckusick /*
154*45095Smckusick  * XDR unsigned long integers
155*45095Smckusick  * same as xdr_long - open coded to save a proc call!
156*45095Smckusick  */
157*45095Smckusick bool_t
158*45095Smckusick xdr_u_long(xdrs, ulp)
159*45095Smckusick 	register XDR *xdrs;
160*45095Smckusick 	u_long *ulp;
161*45095Smckusick {
162*45095Smckusick 
163*45095Smckusick 	if (xdrs->x_op == XDR_DECODE)
164*45095Smckusick 		return (XDR_GETLONG(xdrs, (long *)ulp));
165*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE)
166*45095Smckusick 		return (XDR_PUTLONG(xdrs, (long *)ulp));
167*45095Smckusick 	if (xdrs->x_op == XDR_FREE)
168*45095Smckusick 		return (TRUE);
169*45095Smckusick 	return (FALSE);
170*45095Smckusick }
171*45095Smckusick 
172*45095Smckusick /*
173*45095Smckusick  * XDR short integers
174*45095Smckusick  */
175*45095Smckusick bool_t
176*45095Smckusick xdr_short(xdrs, sp)
177*45095Smckusick 	register XDR *xdrs;
178*45095Smckusick 	short *sp;
179*45095Smckusick {
180*45095Smckusick 	long l;
181*45095Smckusick 
182*45095Smckusick 	switch (xdrs->x_op) {
183*45095Smckusick 
184*45095Smckusick 	case XDR_ENCODE:
185*45095Smckusick 		l = (long) *sp;
186*45095Smckusick 		return (XDR_PUTLONG(xdrs, &l));
187*45095Smckusick 
188*45095Smckusick 	case XDR_DECODE:
189*45095Smckusick 		if (!XDR_GETLONG(xdrs, &l)) {
190*45095Smckusick 			return (FALSE);
191*45095Smckusick 		}
192*45095Smckusick 		*sp = (short) l;
193*45095Smckusick 		return (TRUE);
194*45095Smckusick 
195*45095Smckusick 	case XDR_FREE:
196*45095Smckusick 		return (TRUE);
197*45095Smckusick 	}
198*45095Smckusick 	return (FALSE);
199*45095Smckusick }
200*45095Smckusick 
201*45095Smckusick /*
202*45095Smckusick  * XDR unsigned short integers
203*45095Smckusick  */
204*45095Smckusick bool_t
205*45095Smckusick xdr_u_short(xdrs, usp)
206*45095Smckusick 	register XDR *xdrs;
207*45095Smckusick 	u_short *usp;
208*45095Smckusick {
209*45095Smckusick 	u_long l;
210*45095Smckusick 
211*45095Smckusick 	switch (xdrs->x_op) {
212*45095Smckusick 
213*45095Smckusick 	case XDR_ENCODE:
214*45095Smckusick 		l = (u_long) *usp;
215*45095Smckusick 		return (XDR_PUTLONG(xdrs, &l));
216*45095Smckusick 
217*45095Smckusick 	case XDR_DECODE:
218*45095Smckusick 		if (!XDR_GETLONG(xdrs, &l)) {
219*45095Smckusick 			return (FALSE);
220*45095Smckusick 		}
221*45095Smckusick 		*usp = (u_short) l;
222*45095Smckusick 		return (TRUE);
223*45095Smckusick 
224*45095Smckusick 	case XDR_FREE:
225*45095Smckusick 		return (TRUE);
226*45095Smckusick 	}
227*45095Smckusick 	return (FALSE);
228*45095Smckusick }
229*45095Smckusick 
230*45095Smckusick 
231*45095Smckusick /*
232*45095Smckusick  * XDR a char
233*45095Smckusick  */
234*45095Smckusick bool_t
235*45095Smckusick xdr_char(xdrs, cp)
236*45095Smckusick 	XDR *xdrs;
237*45095Smckusick 	char *cp;
238*45095Smckusick {
239*45095Smckusick 	int i;
240*45095Smckusick 
241*45095Smckusick 	i = (*cp);
242*45095Smckusick 	if (!xdr_int(xdrs, &i)) {
243*45095Smckusick 		return (FALSE);
244*45095Smckusick 	}
245*45095Smckusick 	*cp = i;
246*45095Smckusick 	return (TRUE);
247*45095Smckusick }
248*45095Smckusick 
249*45095Smckusick /*
250*45095Smckusick  * XDR an unsigned char
251*45095Smckusick  */
252*45095Smckusick bool_t
253*45095Smckusick xdr_u_char(xdrs, cp)
254*45095Smckusick 	XDR *xdrs;
255*45095Smckusick 	char *cp;
256*45095Smckusick {
257*45095Smckusick 	u_int u;
258*45095Smckusick 
259*45095Smckusick 	u = (*cp);
260*45095Smckusick 	if (!xdr_u_int(xdrs, &u)) {
261*45095Smckusick 		return (FALSE);
262*45095Smckusick 	}
263*45095Smckusick 	*cp = u;
264*45095Smckusick 	return (TRUE);
265*45095Smckusick }
266*45095Smckusick 
267*45095Smckusick /*
268*45095Smckusick  * XDR booleans
269*45095Smckusick  */
270*45095Smckusick bool_t
271*45095Smckusick xdr_bool(xdrs, bp)
272*45095Smckusick 	register XDR *xdrs;
273*45095Smckusick 	bool_t *bp;
274*45095Smckusick {
275*45095Smckusick 	long lb;
276*45095Smckusick 
277*45095Smckusick 	switch (xdrs->x_op) {
278*45095Smckusick 
279*45095Smckusick 	case XDR_ENCODE:
280*45095Smckusick 		lb = *bp ? XDR_TRUE : XDR_FALSE;
281*45095Smckusick 		return (XDR_PUTLONG(xdrs, &lb));
282*45095Smckusick 
283*45095Smckusick 	case XDR_DECODE:
284*45095Smckusick 		if (!XDR_GETLONG(xdrs, &lb)) {
285*45095Smckusick 			return (FALSE);
286*45095Smckusick 		}
287*45095Smckusick 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
288*45095Smckusick 		return (TRUE);
289*45095Smckusick 
290*45095Smckusick 	case XDR_FREE:
291*45095Smckusick 		return (TRUE);
292*45095Smckusick 	}
293*45095Smckusick 	return (FALSE);
294*45095Smckusick }
295*45095Smckusick 
296*45095Smckusick /*
297*45095Smckusick  * XDR enumerations
298*45095Smckusick  */
299*45095Smckusick bool_t
300*45095Smckusick xdr_enum(xdrs, ep)
301*45095Smckusick 	XDR *xdrs;
302*45095Smckusick 	enum_t *ep;
303*45095Smckusick {
304*45095Smckusick #ifndef lint
305*45095Smckusick 	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
306*45095Smckusick 
307*45095Smckusick 	/*
308*45095Smckusick 	 * enums are treated as ints
309*45095Smckusick 	 */
310*45095Smckusick 	if (sizeof (enum sizecheck) == sizeof (long)) {
311*45095Smckusick 		return (xdr_long(xdrs, (long *)ep));
312*45095Smckusick 	} else if (sizeof (enum sizecheck) == sizeof (short)) {
313*45095Smckusick 		return (xdr_short(xdrs, (short *)ep));
314*45095Smckusick 	} else {
315*45095Smckusick 		return (FALSE);
316*45095Smckusick 	}
317*45095Smckusick #else
318*45095Smckusick 	(void) (xdr_short(xdrs, (short *)ep));
319*45095Smckusick 	return (xdr_long(xdrs, (long *)ep));
320*45095Smckusick #endif
321*45095Smckusick }
322*45095Smckusick 
323*45095Smckusick /*
324*45095Smckusick  * XDR opaque data
325*45095Smckusick  * Allows the specification of a fixed size sequence of opaque bytes.
326*45095Smckusick  * cp points to the opaque object and cnt gives the byte length.
327*45095Smckusick  */
328*45095Smckusick bool_t
329*45095Smckusick xdr_opaque(xdrs, cp, cnt)
330*45095Smckusick 	register XDR *xdrs;
331*45095Smckusick 	caddr_t cp;
332*45095Smckusick 	register u_int cnt;
333*45095Smckusick {
334*45095Smckusick 	register u_int rndup;
335*45095Smckusick 	static crud[BYTES_PER_XDR_UNIT];
336*45095Smckusick 
337*45095Smckusick 	/*
338*45095Smckusick 	 * if no data we are done
339*45095Smckusick 	 */
340*45095Smckusick 	if (cnt == 0)
341*45095Smckusick 		return (TRUE);
342*45095Smckusick 
343*45095Smckusick 	/*
344*45095Smckusick 	 * round byte count to full xdr units
345*45095Smckusick 	 */
346*45095Smckusick 	rndup = cnt % BYTES_PER_XDR_UNIT;
347*45095Smckusick 	if (rndup > 0)
348*45095Smckusick 		rndup = BYTES_PER_XDR_UNIT - rndup;
349*45095Smckusick 
350*45095Smckusick 	if (xdrs->x_op == XDR_DECODE) {
351*45095Smckusick 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
352*45095Smckusick 			return (FALSE);
353*45095Smckusick 		}
354*45095Smckusick 		if (rndup == 0)
355*45095Smckusick 			return (TRUE);
356*45095Smckusick 		return (XDR_GETBYTES(xdrs, crud, rndup));
357*45095Smckusick 	}
358*45095Smckusick 
359*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE) {
360*45095Smckusick 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
361*45095Smckusick 			return (FALSE);
362*45095Smckusick 		}
363*45095Smckusick 		if (rndup == 0)
364*45095Smckusick 			return (TRUE);
365*45095Smckusick 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
366*45095Smckusick 	}
367*45095Smckusick 
368*45095Smckusick 	if (xdrs->x_op == XDR_FREE) {
369*45095Smckusick 		return (TRUE);
370*45095Smckusick 	}
371*45095Smckusick 
372*45095Smckusick 	return (FALSE);
373*45095Smckusick }
374*45095Smckusick 
375*45095Smckusick /*
376*45095Smckusick  * XDR counted bytes
377*45095Smckusick  * *cpp is a pointer to the bytes, *sizep is the count.
378*45095Smckusick  * If *cpp is NULL maxsize bytes are allocated
379*45095Smckusick  */
380*45095Smckusick bool_t
381*45095Smckusick xdr_bytes(xdrs, cpp, sizep, maxsize)
382*45095Smckusick 	register XDR *xdrs;
383*45095Smckusick 	char **cpp;
384*45095Smckusick 	register u_int *sizep;
385*45095Smckusick 	u_int maxsize;
386*45095Smckusick {
387*45095Smckusick 	register char *sp = *cpp;  /* sp is the actual string pointer */
388*45095Smckusick 	register u_int nodesize;
389*45095Smckusick 
390*45095Smckusick 	/*
391*45095Smckusick 	 * first deal with the length since xdr bytes are counted
392*45095Smckusick 	 */
393*45095Smckusick 	if (! xdr_u_int(xdrs, sizep)) {
394*45095Smckusick 		return (FALSE);
395*45095Smckusick 	}
396*45095Smckusick 	nodesize = *sizep;
397*45095Smckusick 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
398*45095Smckusick 		return (FALSE);
399*45095Smckusick 	}
400*45095Smckusick 
401*45095Smckusick 	/*
402*45095Smckusick 	 * now deal with the actual bytes
403*45095Smckusick 	 */
404*45095Smckusick 	switch (xdrs->x_op) {
405*45095Smckusick 
406*45095Smckusick 	case XDR_DECODE:
407*45095Smckusick 		if (nodesize == 0) {
408*45095Smckusick 			return (TRUE);
409*45095Smckusick 		}
410*45095Smckusick 		if (sp == NULL) {
411*45095Smckusick 			*cpp = sp = (char *)mem_alloc(nodesize);
412*45095Smckusick 		}
413*45095Smckusick 		if (sp == NULL) {
414*45095Smckusick 			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
415*45095Smckusick 			return (FALSE);
416*45095Smckusick 		}
417*45095Smckusick 		/* fall into ... */
418*45095Smckusick 
419*45095Smckusick 	case XDR_ENCODE:
420*45095Smckusick 		return (xdr_opaque(xdrs, sp, nodesize));
421*45095Smckusick 
422*45095Smckusick 	case XDR_FREE:
423*45095Smckusick 		if (sp != NULL) {
424*45095Smckusick 			mem_free(sp, nodesize);
425*45095Smckusick 			*cpp = NULL;
426*45095Smckusick 		}
427*45095Smckusick 		return (TRUE);
428*45095Smckusick 	}
429*45095Smckusick 	return (FALSE);
430*45095Smckusick }
431*45095Smckusick 
432*45095Smckusick /*
433*45095Smckusick  * Implemented here due to commonality of the object.
434*45095Smckusick  */
435*45095Smckusick bool_t
436*45095Smckusick xdr_netobj(xdrs, np)
437*45095Smckusick 	XDR *xdrs;
438*45095Smckusick 	struct netobj *np;
439*45095Smckusick {
440*45095Smckusick 
441*45095Smckusick 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
442*45095Smckusick }
443*45095Smckusick 
444*45095Smckusick /*
445*45095Smckusick  * XDR a descriminated union
446*45095Smckusick  * Support routine for discriminated unions.
447*45095Smckusick  * You create an array of xdrdiscrim structures, terminated with
448*45095Smckusick  * an entry with a null procedure pointer.  The routine gets
449*45095Smckusick  * the discriminant value and then searches the array of xdrdiscrims
450*45095Smckusick  * looking for that value.  It calls the procedure given in the xdrdiscrim
451*45095Smckusick  * to handle the discriminant.  If there is no specific routine a default
452*45095Smckusick  * routine may be called.
453*45095Smckusick  * If there is no specific or default routine an error is returned.
454*45095Smckusick  */
455*45095Smckusick bool_t
456*45095Smckusick xdr_union(xdrs, dscmp, unp, choices, dfault)
457*45095Smckusick 	register XDR *xdrs;
458*45095Smckusick 	enum_t *dscmp;		/* enum to decide which arm to work on */
459*45095Smckusick 	char *unp;		/* the union itself */
460*45095Smckusick 	struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
461*45095Smckusick 	xdrproc_t dfault;	/* default xdr routine */
462*45095Smckusick {
463*45095Smckusick 	register enum_t dscm;
464*45095Smckusick 
465*45095Smckusick 	/*
466*45095Smckusick 	 * we deal with the discriminator;  it's an enum
467*45095Smckusick 	 */
468*45095Smckusick 	if (! xdr_enum(xdrs, dscmp)) {
469*45095Smckusick 		return (FALSE);
470*45095Smckusick 	}
471*45095Smckusick 	dscm = *dscmp;
472*45095Smckusick 
473*45095Smckusick 	/*
474*45095Smckusick 	 * search choices for a value that matches the discriminator.
475*45095Smckusick 	 * if we find one, execute the xdr routine for that value.
476*45095Smckusick 	 */
477*45095Smckusick 	for (; choices->proc != NULL_xdrproc_t; choices++) {
478*45095Smckusick 		if (choices->value == dscm)
479*45095Smckusick 			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
480*45095Smckusick 	}
481*45095Smckusick 
482*45095Smckusick 	/*
483*45095Smckusick 	 * no match - execute the default xdr routine if there is one
484*45095Smckusick 	 */
485*45095Smckusick 	return ((dfault == NULL_xdrproc_t) ? FALSE :
486*45095Smckusick 	    (*dfault)(xdrs, unp, LASTUNSIGNED));
487*45095Smckusick }
488*45095Smckusick 
489*45095Smckusick 
490*45095Smckusick /*
491*45095Smckusick  * Non-portable xdr primitives.
492*45095Smckusick  * Care should be taken when moving these routines to new architectures.
493*45095Smckusick  */
494*45095Smckusick 
495*45095Smckusick 
496*45095Smckusick /*
497*45095Smckusick  * XDR null terminated ASCII strings
498*45095Smckusick  * xdr_string deals with "C strings" - arrays of bytes that are
499*45095Smckusick  * terminated by a NULL character.  The parameter cpp references a
500*45095Smckusick  * pointer to storage; If the pointer is null, then the necessary
501*45095Smckusick  * storage is allocated.  The last parameter is the max allowed length
502*45095Smckusick  * of the string as specified by a protocol.
503*45095Smckusick  */
504*45095Smckusick bool_t
505*45095Smckusick xdr_string(xdrs, cpp, maxsize)
506*45095Smckusick 	register XDR *xdrs;
507*45095Smckusick 	char **cpp;
508*45095Smckusick 	u_int maxsize;
509*45095Smckusick {
510*45095Smckusick 	register char *sp = *cpp;  /* sp is the actual string pointer */
511*45095Smckusick 	u_int size;
512*45095Smckusick 	u_int nodesize;
513*45095Smckusick 
514*45095Smckusick 	/*
515*45095Smckusick 	 * first deal with the length since xdr strings are counted-strings
516*45095Smckusick 	 */
517*45095Smckusick 	switch (xdrs->x_op) {
518*45095Smckusick 	case XDR_FREE:
519*45095Smckusick 		if (sp == NULL) {
520*45095Smckusick 			return(TRUE);	/* already free */
521*45095Smckusick 		}
522*45095Smckusick 		/* fall through... */
523*45095Smckusick 	case XDR_ENCODE:
524*45095Smckusick 		size = strlen(sp);
525*45095Smckusick 		break;
526*45095Smckusick 	}
527*45095Smckusick 	if (! xdr_u_int(xdrs, &size)) {
528*45095Smckusick 		return (FALSE);
529*45095Smckusick 	}
530*45095Smckusick 	if (size > maxsize) {
531*45095Smckusick 		return (FALSE);
532*45095Smckusick 	}
533*45095Smckusick 	nodesize = size + 1;
534*45095Smckusick 
535*45095Smckusick 	/*
536*45095Smckusick 	 * now deal with the actual bytes
537*45095Smckusick 	 */
538*45095Smckusick 	switch (xdrs->x_op) {
539*45095Smckusick 
540*45095Smckusick 	case XDR_DECODE:
541*45095Smckusick 		if (nodesize == 0) {
542*45095Smckusick 			return (TRUE);
543*45095Smckusick 		}
544*45095Smckusick 		if (sp == NULL)
545*45095Smckusick 			*cpp = sp = (char *)mem_alloc(nodesize);
546*45095Smckusick 		if (sp == NULL) {
547*45095Smckusick 			(void) fprintf(stderr, "xdr_string: out of memory\n");
548*45095Smckusick 			return (FALSE);
549*45095Smckusick 		}
550*45095Smckusick 		sp[size] = 0;
551*45095Smckusick 		/* fall into ... */
552*45095Smckusick 
553*45095Smckusick 	case XDR_ENCODE:
554*45095Smckusick 		return (xdr_opaque(xdrs, sp, size));
555*45095Smckusick 
556*45095Smckusick 	case XDR_FREE:
557*45095Smckusick 		mem_free(sp, nodesize);
558*45095Smckusick 		*cpp = NULL;
559*45095Smckusick 		return (TRUE);
560*45095Smckusick 	}
561*45095Smckusick 	return (FALSE);
562*45095Smckusick }
563*45095Smckusick 
564*45095Smckusick /*
565*45095Smckusick  * Wrapper for xdr_string that can be called directly from
566*45095Smckusick  * routines like clnt_call
567*45095Smckusick  */
568*45095Smckusick bool_t
569*45095Smckusick xdr_wrapstring(xdrs, cpp)
570*45095Smckusick 	XDR *xdrs;
571*45095Smckusick 	char **cpp;
572*45095Smckusick {
573*45095Smckusick 	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
574*45095Smckusick 		return (TRUE);
575*45095Smckusick 	}
576*45095Smckusick 	return (FALSE);
577*45095Smckusick }
578