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