xref: /minix/lib/libc/rpc/xdr.c (revision 84d9c625)
1 /*	$NetBSD: xdr.c,v 1.33 2013/03/11 20:19:29 tron Exp $	*/
2 
3 /*
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 #if defined(LIBC_SCCS) && !defined(lint)
36 #if 0
37 static char *sccsid = "@(#)xdr.c 1.35 87/08/12";
38 static char *sccsid = "@(#)xdr.c	2.1 88/07/29 4.0 RPCSRC";
39 #else
40 __RCSID("$NetBSD: xdr.c,v 1.33 2013/03/11 20:19:29 tron Exp $");
41 #endif
42 #endif
43 
44 /*
45  * xdr.c, Generic XDR routines implementation.
46  *
47  * Copyright (C) 1986, Sun Microsystems, Inc.
48  *
49  * These are the "generic" xdr routines used to serialize and de-serialize
50  * most common data items.  See xdr.h for more info on the interface to
51  * xdr.
52  */
53 
54 #include "namespace.h"
55 
56 #include <assert.h>
57 #include <err.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 
62 #include <rpc/types.h>
63 #include <rpc/xdr.h>
64 
65 #ifdef __weak_alias
66 __weak_alias(xdr_bool,_xdr_bool)
67 __weak_alias(xdr_bytes,_xdr_bytes)
68 __weak_alias(xdr_char,_xdr_char)
69 __weak_alias(xdr_enum,_xdr_enum)
70 __weak_alias(xdr_free,_xdr_free)
71 __weak_alias(xdr_hyper,_xdr_hyper)
72 __weak_alias(xdr_int,_xdr_int)
73 __weak_alias(xdr_int16_t,_xdr_int16_t)
74 __weak_alias(xdr_int32_t,_xdr_int32_t)
75 __weak_alias(xdr_int64_t,_xdr_int64_t)
76 __weak_alias(xdr_long,_xdr_long)
77 __weak_alias(xdr_longlong_t,_xdr_longlong_t)
78 __weak_alias(xdr_netobj,_xdr_netobj)
79 __weak_alias(xdr_opaque,_xdr_opaque)
80 __weak_alias(xdr_short,_xdr_short)
81 __weak_alias(xdr_string,_xdr_string)
82 __weak_alias(xdr_u_char,_xdr_u_char)
83 __weak_alias(xdr_u_hyper,_xdr_u_hyper)
84 __weak_alias(xdr_u_int,_xdr_u_int)
85 __weak_alias(xdr_u_int16_t,_xdr_u_int16_t)
86 __weak_alias(xdr_u_int32_t,_xdr_u_int32_t)
87 __weak_alias(xdr_u_int64_t,_xdr_u_int64_t)
88 __weak_alias(xdr_u_long,_xdr_u_long)
89 __weak_alias(xdr_u_longlong_t,_xdr_u_longlong_t)
90 __weak_alias(xdr_u_short,_xdr_u_short)
91 __weak_alias(xdr_union,_xdr_union)
92 __weak_alias(xdr_void,_xdr_void)
93 __weak_alias(xdr_wrapstring,_xdr_wrapstring)
94 #endif
95 
96 /*
97  * constants specific to the xdr "protocol"
98  */
99 #define XDR_FALSE	((long) 0)
100 #define XDR_TRUE	((long) 1)
101 #define LASTUNSIGNED	((u_int) 0-1)
102 
103 /*
104  * for unit alignment
105  */
106 static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
107 
108 /*
109  * Free a data structure using XDR
110  * Not a filter, but a convenient utility nonetheless
111  */
112 void
xdr_free(xdrproc_t proc,char * objp)113 xdr_free(xdrproc_t proc, char *objp)
114 {
115 	XDR x;
116 
117 	x.x_op = XDR_FREE;
118 	(*proc)(&x, objp);
119 }
120 
121 /*
122  * XDR nothing
123  */
124 bool_t
xdr_void(void)125 xdr_void(void) {
126 
127 	return (TRUE);
128 }
129 
130 
131 /*
132  * XDR integers
133  */
134 bool_t
xdr_int(XDR * xdrs,int * ip)135 xdr_int(XDR *xdrs, int *ip)
136 {
137 	long l;
138 
139 	_DIAGASSERT(xdrs != NULL);
140 	_DIAGASSERT(ip != NULL);
141 
142 	switch (xdrs->x_op) {
143 
144 	case XDR_ENCODE:
145 		l = (long) *ip;
146 		return (XDR_PUTLONG(xdrs, &l));
147 
148 	case XDR_DECODE:
149 		if (!XDR_GETLONG(xdrs, &l)) {
150 			return (FALSE);
151 		}
152 		*ip = (int) l;
153 		return (TRUE);
154 
155 	case XDR_FREE:
156 		return (TRUE);
157 	}
158 	/* NOTREACHED */
159 	return (FALSE);
160 }
161 
162 /*
163  * XDR unsigned integers
164  */
165 bool_t
xdr_u_int(XDR * xdrs,u_int * up)166 xdr_u_int(XDR *xdrs, u_int *up)
167 {
168 	u_long l;
169 
170 	_DIAGASSERT(xdrs != NULL);
171 	_DIAGASSERT(up != NULL);
172 
173 	switch (xdrs->x_op) {
174 
175 	case XDR_ENCODE:
176 		l = (u_long) *up;
177 		return (XDR_PUTLONG(xdrs, (long *)&l));
178 
179 	case XDR_DECODE:
180 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
181 			return (FALSE);
182 		}
183 		*up = (u_int) l;
184 		return (TRUE);
185 
186 	case XDR_FREE:
187 		return (TRUE);
188 	}
189 	/* NOTREACHED */
190 	return (FALSE);
191 }
192 
193 
194 /*
195  * XDR long integers
196  * same as xdr_u_long - open coded to save a proc call!
197  */
198 bool_t
xdr_long(XDR * xdrs,long * lp)199 xdr_long(XDR *xdrs, long *lp)
200 {
201 
202 	_DIAGASSERT(xdrs != NULL);
203 	_DIAGASSERT(lp != NULL);
204 
205 	switch (xdrs->x_op) {
206 	case XDR_ENCODE:
207 		return (XDR_PUTLONG(xdrs, lp));
208 	case XDR_DECODE:
209 		return (XDR_GETLONG(xdrs, lp));
210 	case XDR_FREE:
211 		return (TRUE);
212 	}
213 	/* NOTREACHED */
214 	return (FALSE);
215 }
216 
217 /*
218  * XDR unsigned long integers
219  * same as xdr_long - open coded to save a proc call!
220  */
221 bool_t
xdr_u_long(XDR * xdrs,u_long * ulp)222 xdr_u_long(XDR *xdrs, u_long *ulp)
223 {
224 
225 	_DIAGASSERT(xdrs != NULL);
226 	_DIAGASSERT(ulp != NULL);
227 
228 	switch (xdrs->x_op) {
229 	case XDR_ENCODE:
230 		return (XDR_PUTLONG(xdrs, (long *)ulp));
231 	case XDR_DECODE:
232 		return (XDR_GETLONG(xdrs, (long *)ulp));
233 	case XDR_FREE:
234 		return (TRUE);
235 	}
236 	/* NOTREACHED */
237 	return (FALSE);
238 }
239 
240 
241 /*
242  * XDR 32-bit integers
243  * same as xdr_u_int32_t - open coded to save a proc call!
244  */
245 bool_t
xdr_int32_t(XDR * xdrs,int32_t * int32_p)246 xdr_int32_t(XDR *xdrs, int32_t *int32_p)
247 {
248 	long l;
249 
250 	_DIAGASSERT(xdrs != NULL);
251 	_DIAGASSERT(int32_p != NULL);
252 
253 	switch (xdrs->x_op) {
254 
255 	case XDR_ENCODE:
256 		l = (long) *int32_p;
257 		return (XDR_PUTLONG(xdrs, &l));
258 
259 	case XDR_DECODE:
260 		if (!XDR_GETLONG(xdrs, &l)) {
261 			return (FALSE);
262 		}
263 		*int32_p = (int32_t) l;
264 		return (TRUE);
265 
266 	case XDR_FREE:
267 		return (TRUE);
268 	}
269 	/* NOTREACHED */
270 	return (FALSE);
271 }
272 
273 /*
274  * XDR unsigned 32-bit integers
275  * same as xdr_int32_t - open coded to save a proc call!
276  */
277 bool_t
xdr_u_int32_t(XDR * xdrs,u_int32_t * u_int32_p)278 xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p)
279 {
280 	u_long l;
281 
282 	_DIAGASSERT(xdrs != NULL);
283 	_DIAGASSERT(u_int32_p != NULL);
284 
285 	switch (xdrs->x_op) {
286 
287 	case XDR_ENCODE:
288 		l = (u_long) *u_int32_p;
289 		return (XDR_PUTLONG(xdrs, (long *)&l));
290 
291 	case XDR_DECODE:
292 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
293 			return (FALSE);
294 		}
295 		*u_int32_p = (u_int32_t) l;
296 		return (TRUE);
297 
298 	case XDR_FREE:
299 		return (TRUE);
300 	}
301 	/* NOTREACHED */
302 	return (FALSE);
303 }
304 
305 
306 /*
307  * XDR short integers
308  */
309 bool_t
xdr_short(XDR * xdrs,short * sp)310 xdr_short(XDR *xdrs, short *sp)
311 {
312 	long l;
313 
314 	_DIAGASSERT(xdrs != NULL);
315 	_DIAGASSERT(sp != NULL);
316 
317 	switch (xdrs->x_op) {
318 
319 	case XDR_ENCODE:
320 		l = (long) *sp;
321 		return (XDR_PUTLONG(xdrs, &l));
322 
323 	case XDR_DECODE:
324 		if (!XDR_GETLONG(xdrs, &l)) {
325 			return (FALSE);
326 		}
327 		*sp = (short) l;
328 		return (TRUE);
329 
330 	case XDR_FREE:
331 		return (TRUE);
332 	}
333 	/* NOTREACHED */
334 	return (FALSE);
335 }
336 
337 /*
338  * XDR unsigned short integers
339  */
340 bool_t
xdr_u_short(XDR * xdrs,u_short * usp)341 xdr_u_short(XDR *xdrs, u_short *usp)
342 {
343 	u_long l;
344 
345 	_DIAGASSERT(xdrs != NULL);
346 	_DIAGASSERT(usp != NULL);
347 
348 	switch (xdrs->x_op) {
349 
350 	case XDR_ENCODE:
351 		l = (u_long) *usp;
352 		return (XDR_PUTLONG(xdrs, (long *)&l));
353 
354 	case XDR_DECODE:
355 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
356 			return (FALSE);
357 		}
358 		*usp = (u_short) l;
359 		return (TRUE);
360 
361 	case XDR_FREE:
362 		return (TRUE);
363 	}
364 	/* NOTREACHED */
365 	return (FALSE);
366 }
367 
368 
369 /*
370  * XDR 16-bit integers
371  */
372 bool_t
xdr_int16_t(XDR * xdrs,int16_t * int16_p)373 xdr_int16_t(XDR *xdrs, int16_t *int16_p)
374 {
375 	long l;
376 
377 	_DIAGASSERT(xdrs != NULL);
378 	_DIAGASSERT(int16_p != NULL);
379 
380 	switch (xdrs->x_op) {
381 
382 	case XDR_ENCODE:
383 		l = (long) *int16_p;
384 		return (XDR_PUTLONG(xdrs, &l));
385 
386 	case XDR_DECODE:
387 		if (!XDR_GETLONG(xdrs, &l)) {
388 			return (FALSE);
389 		}
390 		*int16_p = (int16_t) l;
391 		return (TRUE);
392 
393 	case XDR_FREE:
394 		return (TRUE);
395 	}
396 	/* NOTREACHED */
397 	return (FALSE);
398 }
399 
400 /*
401  * XDR unsigned 16-bit integers
402  */
403 bool_t
xdr_u_int16_t(XDR * xdrs,u_int16_t * u_int16_p)404 xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p)
405 {
406 	u_long l;
407 
408 	_DIAGASSERT(xdrs != NULL);
409 	_DIAGASSERT(u_int16_p != NULL);
410 
411 	switch (xdrs->x_op) {
412 
413 	case XDR_ENCODE:
414 		l = (u_long) *u_int16_p;
415 		return (XDR_PUTLONG(xdrs, (long *)&l));
416 
417 	case XDR_DECODE:
418 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
419 			return (FALSE);
420 		}
421 		*u_int16_p = (u_int16_t) l;
422 		return (TRUE);
423 
424 	case XDR_FREE:
425 		return (TRUE);
426 	}
427 	/* NOTREACHED */
428 	return (FALSE);
429 }
430 
431 
432 /*
433  * XDR a char
434  */
435 bool_t
xdr_char(XDR * xdrs,char * cp)436 xdr_char(XDR *xdrs, char *cp)
437 {
438 	int i;
439 
440 	_DIAGASSERT(xdrs != NULL);
441 	_DIAGASSERT(cp != NULL);
442 
443 	i = (*cp);
444 	if (!xdr_int(xdrs, &i)) {
445 		return (FALSE);
446 	}
447 	*cp = i;
448 	return (TRUE);
449 }
450 
451 /*
452  * XDR an unsigned char
453  */
454 bool_t
xdr_u_char(XDR * xdrs,u_char * cp)455 xdr_u_char(XDR *xdrs, u_char *cp)
456 {
457 	u_int u;
458 
459 	_DIAGASSERT(xdrs != NULL);
460 	_DIAGASSERT(cp != NULL);
461 
462 	u = (*cp);
463 	if (!xdr_u_int(xdrs, &u)) {
464 		return (FALSE);
465 	}
466 	*cp = u;
467 	return (TRUE);
468 }
469 
470 /*
471  * XDR booleans
472  */
473 bool_t
xdr_bool(XDR * xdrs,bool_t * bp)474 xdr_bool(XDR *xdrs, bool_t *bp)
475 {
476 	long lb;
477 
478 	_DIAGASSERT(xdrs != NULL);
479 	_DIAGASSERT(bp != NULL);
480 
481 	switch (xdrs->x_op) {
482 
483 	case XDR_ENCODE:
484 		lb = *bp ? XDR_TRUE : XDR_FALSE;
485 		return (XDR_PUTLONG(xdrs, &lb));
486 
487 	case XDR_DECODE:
488 		if (!XDR_GETLONG(xdrs, &lb)) {
489 			return (FALSE);
490 		}
491 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
492 		return (TRUE);
493 
494 	case XDR_FREE:
495 		return (TRUE);
496 	}
497 	/* NOTREACHED */
498 	return (FALSE);
499 }
500 
501 /*
502  * XDR enumerations
503  */
504 bool_t
xdr_enum(XDR * xdrs,enum_t * ep)505 xdr_enum(XDR *xdrs, enum_t *ep)
506 {
507 	long l;
508 
509 	_DIAGASSERT(xdrs != NULL);
510 	_DIAGASSERT(ep != NULL);
511 
512 	switch (xdrs->x_op) {
513 
514 	case XDR_ENCODE:
515 		l = (long) *ep;
516 		return (XDR_PUTLONG(xdrs, &l));
517 
518 	case XDR_DECODE:
519 		if (!XDR_GETLONG(xdrs, &l)) {
520 			return (FALSE);
521 		}
522 		*ep = (enum_t) l;
523 		return (TRUE);
524 
525 	case XDR_FREE:
526 		return (TRUE);
527 	}
528 	/* NOTREACHED */
529 	return (FALSE);
530 }
531 
532 /*
533  * XDR opaque data
534  * Allows the specification of a fixed size sequence of opaque bytes.
535  * cp points to the opaque object and cnt gives the byte length.
536  */
537 bool_t
xdr_opaque(XDR * xdrs,caddr_t cp,u_int cnt)538 xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
539 {
540 	u_int rndup;
541 	static int crud[BYTES_PER_XDR_UNIT];
542 
543 	_DIAGASSERT(xdrs != NULL);
544 		/*
545 		 * if no data we are done
546 		 */
547 	if (cnt == 0)
548 		return (TRUE);
549 	_DIAGASSERT(cp != NULL);
550 
551 	/*
552 	 * round byte count to full xdr units
553 	 */
554 	rndup = cnt % BYTES_PER_XDR_UNIT;
555 	if (rndup > 0)
556 		rndup = BYTES_PER_XDR_UNIT - rndup;
557 
558 	if (xdrs->x_op == XDR_DECODE) {
559 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
560 			return (FALSE);
561 		}
562 		if (rndup == 0)
563 			return (TRUE);
564 		return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
565 	}
566 
567 	if (xdrs->x_op == XDR_ENCODE) {
568 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
569 			return (FALSE);
570 		}
571 		if (rndup == 0)
572 			return (TRUE);
573 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
574 	}
575 
576 	if (xdrs->x_op == XDR_FREE) {
577 		return (TRUE);
578 	}
579 
580 	return (FALSE);
581 }
582 
583 /*
584  * XDR counted bytes
585  * *cpp is a pointer to the bytes, *sizep is the count.
586  * If *cpp is NULL maxsize bytes are allocated
587  */
588 bool_t
xdr_bytes(XDR * xdrs,char ** cpp,u_int * sizep,u_int maxsize)589 xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
590 {
591 	char *sp;  		/* sp is the actual string pointer */
592 	u_int nodesize;
593 
594 	_DIAGASSERT(xdrs != NULL);
595 	_DIAGASSERT(cpp != NULL);
596 	_DIAGASSERT(sizep != NULL);
597 
598 	sp = *cpp;
599 
600 	/*
601 	 * first deal with the length since xdr bytes are counted
602 	 */
603 	if (! xdr_u_int(xdrs, sizep)) {
604 		return (FALSE);
605 	}
606 	nodesize = *sizep;
607 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
608 		return (FALSE);
609 	}
610 
611 	/*
612 	 * now deal with the actual bytes
613 	 */
614 	switch (xdrs->x_op) {
615 
616 	case XDR_DECODE:
617 		if (nodesize == 0) {
618 			return (TRUE);
619 		}
620 		if (sp == NULL) {
621 			*cpp = sp = mem_alloc(nodesize);
622 		}
623 		if (sp == NULL) {
624 			warn("%s: out of memory", __func__);
625 			return (FALSE);
626 		}
627 		/* FALLTHROUGH */
628 
629 	case XDR_ENCODE:
630 		return (xdr_opaque(xdrs, sp, nodesize));
631 
632 	case XDR_FREE:
633 		if (sp != NULL) {
634 			mem_free(sp, nodesize);
635 			*cpp = NULL;
636 		}
637 		return (TRUE);
638 	}
639 	/* NOTREACHED */
640 	return (FALSE);
641 }
642 
643 /*
644  * Implemented here due to commonality of the object.
645  */
646 bool_t
xdr_netobj(XDR * xdrs,struct netobj * np)647 xdr_netobj(XDR *xdrs, struct netobj *np)
648 {
649 
650 	_DIAGASSERT(xdrs != NULL);
651 	_DIAGASSERT(np != NULL);
652 
653 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
654 }
655 
656 /*
657  * XDR a descriminated union
658  * Support routine for discriminated unions.
659  * You create an array of xdrdiscrim structures, terminated with
660  * an entry with a null procedure pointer.  The routine gets
661  * the discriminant value and then searches the array of xdrdiscrims
662  * looking for that value.  It calls the procedure given in the xdrdiscrim
663  * to handle the discriminant.  If there is no specific routine a default
664  * routine may be called.
665  * If there is no specific or default routine an error is returned.
666  */
667 bool_t
xdr_union(XDR * xdrs,enum_t * dscmp,char * unp,const struct xdr_discrim * choices,xdrproc_t dfault)668 xdr_union(
669 	XDR *xdrs,
670 	enum_t *dscmp,		/* enum to decide which arm to work on */
671 	char *unp,		/* the union itself */
672 	const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */
673 	xdrproc_t dfault	/* default xdr routine */
674 )
675 {
676 	enum_t dscm;
677 
678 	_DIAGASSERT(xdrs != NULL);
679 	_DIAGASSERT(dscmp != NULL);
680 	_DIAGASSERT(unp != NULL);
681 	_DIAGASSERT(choices != NULL);
682 	/* dfault may be NULL */
683 
684 	/*
685 	 * we deal with the discriminator;  it's an enum
686 	 */
687 	if (! xdr_enum(xdrs, dscmp)) {
688 		return (FALSE);
689 	}
690 	dscm = *dscmp;
691 
692 	/*
693 	 * search choices for a value that matches the discriminator.
694 	 * if we find one, execute the xdr routine for that value.
695 	 */
696 	for (; choices->proc != NULL_xdrproc_t; choices++) {
697 		if (choices->value == dscm)
698 			return ((*(choices->proc))(xdrs, unp));
699 	}
700 
701 	/*
702 	 * no match - execute the default xdr routine if there is one
703 	 */
704 	return ((dfault == NULL_xdrproc_t) ? FALSE :
705 	    (*dfault)(xdrs, unp));
706 }
707 
708 
709 /*
710  * Non-portable xdr primitives.
711  * Care should be taken when moving these routines to new architectures.
712  */
713 
714 
715 /*
716  * XDR null terminated ASCII strings
717  * xdr_string deals with "C strings" - arrays of bytes that are
718  * terminated by a NULL character.  The parameter cpp references a
719  * pointer to storage; If the pointer is null, then the necessary
720  * storage is allocated.  The last parameter is the max allowed length
721  * of the string as specified by a protocol.
722  */
723 bool_t
xdr_string(XDR * xdrs,char ** cpp,u_int maxsize)724 xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
725 {
726 	char *sp;  		/* sp is the actual string pointer */
727 	u_int size = 0;		/* XXX: GCC */
728 	u_int nodesize;
729 	size_t len;
730 
731 	_DIAGASSERT(xdrs != NULL);
732 	_DIAGASSERT(cpp != NULL);
733 
734 	sp = *cpp;
735 
736 	/*
737 	 * first deal with the length since xdr strings are counted-strings
738 	 */
739 	switch (xdrs->x_op) {
740 	case XDR_FREE:
741 		if (sp == NULL) {
742 			return(TRUE);	/* already free */
743 		}
744 		/* FALLTHROUGH */
745 	case XDR_ENCODE:
746 		len = strlen(sp);
747 		_DIAGASSERT(__type_fit(u_int, len));
748 		size = (u_int)len;
749 		break;
750 	case XDR_DECODE:
751 		break;
752 	}
753 	if (! xdr_u_int(xdrs, &size)) {
754 		return (FALSE);
755 	}
756 	if (size > maxsize) {
757 		return (FALSE);
758 	}
759 	nodesize = size + 1;
760 
761 	/*
762 	 * now deal with the actual bytes
763 	 */
764 	switch (xdrs->x_op) {
765 
766 	case XDR_DECODE:
767 		if (nodesize == 0) {
768 			return (TRUE);
769 		}
770 		if (sp == NULL)
771 			*cpp = sp = mem_alloc(nodesize);
772 		if (sp == NULL) {
773 			warn("%s: out of memory", __func__);
774 			return (FALSE);
775 		}
776 		sp[size] = 0;
777 		/* FALLTHROUGH */
778 
779 	case XDR_ENCODE:
780 		return (xdr_opaque(xdrs, sp, size));
781 
782 	case XDR_FREE:
783 		mem_free(sp, nodesize);
784 		*cpp = NULL;
785 		return (TRUE);
786 	}
787 	/* NOTREACHED */
788 	return (FALSE);
789 }
790 
791 /*
792  * Wrapper for xdr_string that can be called directly from
793  * routines like clnt_call
794  */
795 bool_t
xdr_wrapstring(XDR * xdrs,char ** cpp)796 xdr_wrapstring(XDR *xdrs, char **cpp)
797 {
798 
799 	_DIAGASSERT(xdrs != NULL);
800 	_DIAGASSERT(cpp != NULL);
801 
802 	return xdr_string(xdrs, cpp, LASTUNSIGNED);
803 }
804 
805 /*
806  * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
807  * are in the "non-portable" section because they require that a `long long'
808  * be a 64-bit type.
809  *
810  *	--thorpej@NetBSD.org, November 30, 1999
811  */
812 
813 /*
814  * XDR 64-bit integers
815  */
816 bool_t
xdr_int64_t(XDR * xdrs,int64_t * llp)817 xdr_int64_t(XDR *xdrs, int64_t *llp)
818 {
819 	u_long ul[2];
820 
821 	_DIAGASSERT(xdrs != NULL);
822 	_DIAGASSERT(llp != NULL);
823 
824 	switch (xdrs->x_op) {
825 	case XDR_ENCODE:
826 		ul[0] = (u_long)(((uint64_t)*llp >> 32) &
827 		    (uint64_t)0xffffffffULL);
828 		ul[1] = (u_long)(((uint64_t)*llp) &
829 		    (uint64_t)0xffffffffULL);
830 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
831 			return (FALSE);
832 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
833 	case XDR_DECODE:
834 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
835 			return (FALSE);
836 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
837 			return (FALSE);
838 		*llp = (int64_t)
839 		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
840 		return (TRUE);
841 	case XDR_FREE:
842 		return (TRUE);
843 	}
844 	/* NOTREACHED */
845 	return (FALSE);
846 }
847 
848 
849 /*
850  * XDR unsigned 64-bit integers
851  */
852 bool_t
xdr_u_int64_t(XDR * xdrs,u_int64_t * ullp)853 xdr_u_int64_t(XDR *xdrs, u_int64_t *ullp)
854 {
855 	u_long ul[2];
856 
857 	_DIAGASSERT(xdrs != NULL);
858 	_DIAGASSERT(ullp != NULL);
859 
860 	switch (xdrs->x_op) {
861 	case XDR_ENCODE:
862 		ul[0] = (u_long)(*ullp >> 32) & 0xffffffffUL;
863 		ul[1] = (u_long)(*ullp) & 0xffffffffUL;
864 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
865 			return (FALSE);
866 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
867 	case XDR_DECODE:
868 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
869 			return (FALSE);
870 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
871 			return (FALSE);
872 		*ullp = (u_int64_t)
873 		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
874 		return (TRUE);
875 	case XDR_FREE:
876 		return (TRUE);
877 	}
878 	/* NOTREACHED */
879 	return (FALSE);
880 }
881 
882 
883 /*
884  * XDR hypers
885  */
886 bool_t
xdr_hyper(XDR * xdrs,longlong_t * llp)887 xdr_hyper(XDR *xdrs, longlong_t *llp)
888 {
889 
890 	_DIAGASSERT(xdrs != NULL);
891 	_DIAGASSERT(llp != NULL);
892 
893 	/*
894 	 * Don't bother open-coding this; it's a fair amount of code.  Just
895 	 * call xdr_int64_t().
896 	 */
897 	return (xdr_int64_t(xdrs, (int64_t *)llp));
898 }
899 
900 
901 /*
902  * XDR unsigned hypers
903  */
904 bool_t
xdr_u_hyper(XDR * xdrs,u_longlong_t * ullp)905 xdr_u_hyper(XDR *xdrs, u_longlong_t *ullp)
906 {
907 
908 	_DIAGASSERT(xdrs != NULL);
909 	_DIAGASSERT(ullp != NULL);
910 
911 	/*
912 	 * Don't bother open-coding this; it's a fair amount of code.  Just
913 	 * call xdr_u_int64_t().
914 	 */
915 	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
916 }
917 
918 
919 /*
920  * XDR longlong_t's
921  */
922 bool_t
xdr_longlong_t(XDR * xdrs,longlong_t * llp)923 xdr_longlong_t(XDR *xdrs, longlong_t *llp)
924 {
925 
926 	_DIAGASSERT(xdrs != NULL);
927 	_DIAGASSERT(llp != NULL);
928 
929 	/*
930 	 * Don't bother open-coding this; it's a fair amount of code.  Just
931 	 * call xdr_int64_t().
932 	 */
933 	return (xdr_int64_t(xdrs, (int64_t *)llp));
934 }
935 
936 
937 /*
938  * XDR u_longlong_t's
939  */
940 bool_t
xdr_u_longlong_t(XDR * xdrs,u_longlong_t * ullp)941 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp)
942 {
943 
944 	_DIAGASSERT(xdrs != NULL);
945 	_DIAGASSERT(ullp != NULL);
946 
947 	/*
948 	 * Don't bother open-coding this; it's a fair amount of code.  Just
949 	 * call xdr_u_int64_t().
950 	 */
951 	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
952 }
953