1 | /* |
2 | * xdr.c, Generic XDR routines implementation. |
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 | * These are the "generic" xdr routines used to serialize and de-serialize |
34 | * most common data items. See xdr.h for more info on the interface to |
35 | * xdr. |
36 | */ |
37 | |
38 | #include <stdio.h> |
39 | #include <limits.h> |
40 | #include <string.h> |
41 | #include <libintl.h> |
42 | #include <wchar.h> |
43 | #include <stdint.h> |
44 | |
45 | #include <rpc/types.h> |
46 | #include <rpc/xdr.h> |
47 | #include <shlib-compat.h> |
48 | |
49 | |
50 | /* |
51 | * constants specific to the xdr "protocol" |
52 | */ |
53 | #define XDR_FALSE ((long) 0) |
54 | #define XDR_TRUE ((long) 1) |
55 | #define LASTUNSIGNED ((u_int) 0-1) |
56 | |
57 | /* |
58 | * for unit alignment |
59 | */ |
60 | static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; |
61 | |
62 | /* |
63 | * Free a data structure using XDR |
64 | * Not a filter, but a convenient utility nonetheless |
65 | */ |
66 | void |
67 | xdr_free (xdrproc_t proc, char *objp) |
68 | { |
69 | XDR x; |
70 | |
71 | x.x_op = XDR_FREE; |
72 | (*proc) (&x, objp); |
73 | } |
74 | #ifdef EXPORT_RPC_SYMBOLS |
75 | libc_hidden_def (xdr_free) |
76 | #else |
77 | libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0) |
78 | #endif |
79 | |
80 | /* |
81 | * XDR nothing |
82 | */ |
83 | bool_t |
84 | xdr_void (void) |
85 | { |
86 | return TRUE; |
87 | } |
88 | #ifdef EXPORT_RPC_SYMBOLS |
89 | libc_hidden_def (xdr_void) |
90 | #else |
91 | libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0) |
92 | #endif |
93 | |
94 | /* |
95 | * XDR integers |
96 | */ |
97 | bool_t |
98 | xdr_int (XDR *xdrs, int *ip) |
99 | { |
100 | |
101 | #if INT_MAX < LONG_MAX |
102 | long l; |
103 | |
104 | switch (xdrs->x_op) |
105 | { |
106 | case XDR_ENCODE: |
107 | l = (long) *ip; |
108 | return XDR_PUTLONG (xdrs, &l); |
109 | |
110 | case XDR_DECODE: |
111 | if (!XDR_GETLONG (xdrs, &l)) |
112 | { |
113 | return FALSE; |
114 | } |
115 | *ip = (int) l; |
116 | case XDR_FREE: |
117 | return TRUE; |
118 | } |
119 | return FALSE; |
120 | #elif INT_MAX == LONG_MAX |
121 | return xdr_long (xdrs, (long *) ip); |
122 | #elif INT_MAX == SHRT_MAX |
123 | return xdr_short (xdrs, (short *) ip); |
124 | #else |
125 | #error unexpected integer sizes in_xdr_int() |
126 | #endif |
127 | } |
128 | #ifdef EXPORT_RPC_SYMBOLS |
129 | libc_hidden_def (xdr_int) |
130 | #else |
131 | libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0) |
132 | #endif |
133 | |
134 | /* |
135 | * XDR unsigned integers |
136 | */ |
137 | bool_t |
138 | xdr_u_int (XDR *xdrs, u_int *up) |
139 | { |
140 | #if UINT_MAX < ULONG_MAX |
141 | long l; |
142 | |
143 | switch (xdrs->x_op) |
144 | { |
145 | case XDR_ENCODE: |
146 | l = (u_long) * up; |
147 | return XDR_PUTLONG (xdrs, &l); |
148 | |
149 | case XDR_DECODE: |
150 | if (!XDR_GETLONG (xdrs, &l)) |
151 | { |
152 | return FALSE; |
153 | } |
154 | *up = (u_int) (u_long) l; |
155 | case XDR_FREE: |
156 | return TRUE; |
157 | } |
158 | return FALSE; |
159 | #elif UINT_MAX == ULONG_MAX |
160 | return xdr_u_long (xdrs, (u_long *) up); |
161 | #elif UINT_MAX == USHRT_MAX |
162 | return xdr_short (xdrs, (short *) up); |
163 | #else |
164 | #error unexpected integer sizes in_xdr_u_int() |
165 | #endif |
166 | } |
167 | #ifdef EXPORT_RPC_SYMBOLS |
168 | libc_hidden_def (xdr_u_int) |
169 | #else |
170 | libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0) |
171 | #endif |
172 | |
173 | /* |
174 | * XDR long integers |
175 | * The definition of xdr_long() is kept for backward |
176 | * compatibility. Instead xdr_int() should be used. |
177 | */ |
178 | bool_t |
179 | xdr_long (XDR *xdrs, long *lp) |
180 | { |
181 | |
182 | if (xdrs->x_op == XDR_ENCODE |
183 | && (sizeof (int32_t) == sizeof (long) |
184 | || (int32_t) *lp == *lp)) |
185 | return XDR_PUTLONG (xdrs, lp); |
186 | |
187 | if (xdrs->x_op == XDR_DECODE) |
188 | return XDR_GETLONG (xdrs, lp); |
189 | |
190 | if (xdrs->x_op == XDR_FREE) |
191 | return TRUE; |
192 | |
193 | return FALSE; |
194 | } |
195 | #ifdef EXPORT_RPC_SYMBOLS |
196 | libc_hidden_def (xdr_long) |
197 | #else |
198 | libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0) |
199 | #endif |
200 | |
201 | /* |
202 | * XDR unsigned long integers |
203 | * The definition of xdr_u_long() is kept for backward |
204 | * compatibility. Instead xdr_u_int() should be used. |
205 | */ |
206 | bool_t |
207 | xdr_u_long (XDR *xdrs, u_long *ulp) |
208 | { |
209 | switch (xdrs->x_op) |
210 | { |
211 | case XDR_DECODE: |
212 | { |
213 | long int tmp; |
214 | |
215 | if (XDR_GETLONG (xdrs, &tmp) == FALSE) |
216 | return FALSE; |
217 | |
218 | *ulp = (uint32_t) tmp; |
219 | return TRUE; |
220 | } |
221 | |
222 | case XDR_ENCODE: |
223 | if (sizeof (uint32_t) != sizeof (u_long) |
224 | && (uint32_t) *ulp != *ulp) |
225 | return FALSE; |
226 | |
227 | return XDR_PUTLONG (xdrs, (long *) ulp); |
228 | |
229 | case XDR_FREE: |
230 | return TRUE; |
231 | } |
232 | return FALSE; |
233 | } |
234 | #ifdef EXPORT_RPC_SYMBOLS |
235 | libc_hidden_def (xdr_u_long) |
236 | #else |
237 | libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0) |
238 | #endif |
239 | |
240 | /* |
241 | * XDR hyper integers |
242 | * same as xdr_u_hyper - open coded to save a proc call! |
243 | */ |
244 | bool_t |
245 | xdr_hyper (XDR *xdrs, quad_t *llp) |
246 | { |
247 | long int t1, t2; |
248 | |
249 | if (xdrs->x_op == XDR_ENCODE) |
250 | { |
251 | t1 = (long) ((*llp) >> 32); |
252 | t2 = (long) (*llp); |
253 | return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); |
254 | } |
255 | |
256 | if (xdrs->x_op == XDR_DECODE) |
257 | { |
258 | if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) |
259 | return FALSE; |
260 | *llp = ((quad_t) t1) << 32; |
261 | *llp |= (uint32_t) t2; |
262 | return TRUE; |
263 | } |
264 | |
265 | if (xdrs->x_op == XDR_FREE) |
266 | return TRUE; |
267 | |
268 | return FALSE; |
269 | } |
270 | #ifdef EXPORT_RPC_SYMBOLS |
271 | libc_hidden_def (xdr_hyper) |
272 | #else |
273 | libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1) |
274 | #endif |
275 | |
276 | /* |
277 | * XDR hyper integers |
278 | * same as xdr_hyper - open coded to save a proc call! |
279 | */ |
280 | bool_t |
281 | xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) |
282 | { |
283 | long int t1, t2; |
284 | |
285 | if (xdrs->x_op == XDR_ENCODE) |
286 | { |
287 | t1 = (unsigned long) ((*ullp) >> 32); |
288 | t2 = (unsigned long) (*ullp); |
289 | return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); |
290 | } |
291 | |
292 | if (xdrs->x_op == XDR_DECODE) |
293 | { |
294 | if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) |
295 | return FALSE; |
296 | *ullp = ((u_quad_t) t1) << 32; |
297 | *ullp |= (uint32_t) t2; |
298 | return TRUE; |
299 | } |
300 | |
301 | if (xdrs->x_op == XDR_FREE) |
302 | return TRUE; |
303 | |
304 | return FALSE; |
305 | } |
306 | #ifdef EXPORT_RPC_SYMBOLS |
307 | libc_hidden_def (xdr_u_hyper) |
308 | #else |
309 | libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1) |
310 | #endif |
311 | |
312 | bool_t |
313 | xdr_longlong_t (XDR *xdrs, quad_t *llp) |
314 | { |
315 | return xdr_hyper (xdrs, llp); |
316 | } |
317 | #ifdef EXPORT_RPC_SYMBOLS |
318 | libc_hidden_def (xdr_longlong_t) |
319 | #else |
320 | libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1) |
321 | #endif |
322 | |
323 | bool_t |
324 | xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) |
325 | { |
326 | return xdr_u_hyper (xdrs, ullp); |
327 | } |
328 | #ifdef EXPORT_RPC_SYMBOLS |
329 | libc_hidden_def (xdr_u_longlong_t) |
330 | #else |
331 | libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1) |
332 | #endif |
333 | |
334 | /* |
335 | * XDR short integers |
336 | */ |
337 | bool_t |
338 | xdr_short (XDR *xdrs, short *sp) |
339 | { |
340 | long l; |
341 | |
342 | switch (xdrs->x_op) |
343 | { |
344 | case XDR_ENCODE: |
345 | l = (long) *sp; |
346 | return XDR_PUTLONG (xdrs, &l); |
347 | |
348 | case XDR_DECODE: |
349 | if (!XDR_GETLONG (xdrs, &l)) |
350 | { |
351 | return FALSE; |
352 | } |
353 | *sp = (short) l; |
354 | return TRUE; |
355 | |
356 | case XDR_FREE: |
357 | return TRUE; |
358 | } |
359 | return FALSE; |
360 | } |
361 | #ifdef EXPORT_RPC_SYMBOLS |
362 | libc_hidden_def (xdr_short) |
363 | #else |
364 | libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0) |
365 | #endif |
366 | |
367 | /* |
368 | * XDR unsigned short integers |
369 | */ |
370 | bool_t |
371 | xdr_u_short (XDR *xdrs, u_short *usp) |
372 | { |
373 | long l; |
374 | |
375 | switch (xdrs->x_op) |
376 | { |
377 | case XDR_ENCODE: |
378 | l = (u_long) * usp; |
379 | return XDR_PUTLONG (xdrs, &l); |
380 | |
381 | case XDR_DECODE: |
382 | if (!XDR_GETLONG (xdrs, &l)) |
383 | { |
384 | return FALSE; |
385 | } |
386 | *usp = (u_short) (u_long) l; |
387 | return TRUE; |
388 | |
389 | case XDR_FREE: |
390 | return TRUE; |
391 | } |
392 | return FALSE; |
393 | } |
394 | #ifdef EXPORT_RPC_SYMBOLS |
395 | libc_hidden_def (xdr_u_short) |
396 | #else |
397 | libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0) |
398 | #endif |
399 | |
400 | |
401 | /* |
402 | * XDR a char |
403 | */ |
404 | bool_t |
405 | xdr_char (XDR *xdrs, char *cp) |
406 | { |
407 | int i; |
408 | |
409 | i = (*cp); |
410 | if (!xdr_int (xdrs, &i)) |
411 | { |
412 | return FALSE; |
413 | } |
414 | *cp = i; |
415 | return TRUE; |
416 | } |
417 | #ifdef EXPORT_RPC_SYMBOLS |
418 | libc_hidden_def (xdr_char) |
419 | #else |
420 | libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0) |
421 | #endif |
422 | |
423 | /* |
424 | * XDR an unsigned char |
425 | */ |
426 | bool_t |
427 | xdr_u_char (XDR *xdrs, u_char *cp) |
428 | { |
429 | u_int u; |
430 | |
431 | u = (*cp); |
432 | if (!xdr_u_int (xdrs, &u)) |
433 | { |
434 | return FALSE; |
435 | } |
436 | *cp = u; |
437 | return TRUE; |
438 | } |
439 | #ifdef EXPORT_RPC_SYMBOLS |
440 | libc_hidden_def (xdr_u_char) |
441 | #else |
442 | libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0) |
443 | #endif |
444 | |
445 | /* |
446 | * XDR booleans |
447 | */ |
448 | bool_t |
449 | xdr_bool (XDR *xdrs, bool_t *bp) |
450 | { |
451 | long lb; |
452 | |
453 | switch (xdrs->x_op) |
454 | { |
455 | case XDR_ENCODE: |
456 | lb = *bp ? XDR_TRUE : XDR_FALSE; |
457 | return XDR_PUTLONG (xdrs, &lb); |
458 | |
459 | case XDR_DECODE: |
460 | if (!XDR_GETLONG (xdrs, &lb)) |
461 | { |
462 | return FALSE; |
463 | } |
464 | *bp = (lb == XDR_FALSE) ? FALSE : TRUE; |
465 | return TRUE; |
466 | |
467 | case XDR_FREE: |
468 | return TRUE; |
469 | } |
470 | return FALSE; |
471 | } |
472 | #ifdef EXPORT_RPC_SYMBOLS |
473 | libc_hidden_def (xdr_bool) |
474 | #else |
475 | libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0) |
476 | #endif |
477 | |
478 | /* |
479 | * XDR enumerations |
480 | */ |
481 | bool_t |
482 | xdr_enum (XDR *xdrs, enum_t *ep) |
483 | { |
484 | enum sizecheck |
485 | { |
486 | SIZEVAL |
487 | }; /* used to find the size of an enum */ |
488 | |
489 | /* |
490 | * enums are treated as ints |
491 | */ |
492 | if (sizeof (enum sizecheck) == 4) |
493 | { |
494 | #if INT_MAX < LONG_MAX |
495 | long l; |
496 | |
497 | switch (xdrs->x_op) |
498 | { |
499 | case XDR_ENCODE: |
500 | l = *ep; |
501 | return XDR_PUTLONG (xdrs, &l); |
502 | |
503 | case XDR_DECODE: |
504 | if (!XDR_GETLONG (xdrs, &l)) |
505 | { |
506 | return FALSE; |
507 | } |
508 | *ep = l; |
509 | case XDR_FREE: |
510 | return TRUE; |
511 | |
512 | } |
513 | return FALSE; |
514 | #else |
515 | return xdr_long (xdrs, (long *) ep); |
516 | #endif |
517 | } |
518 | else if (sizeof (enum sizecheck) == sizeof (short)) |
519 | { |
520 | return xdr_short (xdrs, (short *) ep); |
521 | } |
522 | else |
523 | { |
524 | return FALSE; |
525 | } |
526 | } |
527 | #ifdef EXPORT_RPC_SYMBOLS |
528 | libc_hidden_def (xdr_enum) |
529 | #else |
530 | libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0) |
531 | #endif |
532 | |
533 | /* |
534 | * XDR opaque data |
535 | * Allows the specification of a fixed size sequence of opaque bytes. |
536 | * cp points to the opaque object and cnt gives the byte length. |
537 | */ |
538 | bool_t |
539 | xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) |
540 | { |
541 | u_int rndup; |
542 | static char crud[BYTES_PER_XDR_UNIT]; |
543 | |
544 | /* |
545 | * if no data we are done |
546 | */ |
547 | if (cnt == 0) |
548 | return TRUE; |
549 | |
550 | /* |
551 | * round byte count to full xdr units |
552 | */ |
553 | rndup = cnt % BYTES_PER_XDR_UNIT; |
554 | if (rndup > 0) |
555 | rndup = BYTES_PER_XDR_UNIT - rndup; |
556 | |
557 | switch (xdrs->x_op) |
558 | { |
559 | case XDR_DECODE: |
560 | if (!XDR_GETBYTES (xdrs, cp, cnt)) |
561 | { |
562 | return FALSE; |
563 | } |
564 | if (rndup == 0) |
565 | return TRUE; |
566 | return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup); |
567 | |
568 | case XDR_ENCODE: |
569 | if (!XDR_PUTBYTES (xdrs, cp, cnt)) |
570 | { |
571 | return FALSE; |
572 | } |
573 | if (rndup == 0) |
574 | return TRUE; |
575 | return XDR_PUTBYTES (xdrs, xdr_zero, rndup); |
576 | |
577 | case XDR_FREE: |
578 | return TRUE; |
579 | } |
580 | return FALSE; |
581 | } |
582 | #ifdef EXPORT_RPC_SYMBOLS |
583 | libc_hidden_def (xdr_opaque) |
584 | #else |
585 | libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0) |
586 | #endif |
587 | |
588 | /* |
589 | * XDR counted bytes |
590 | * *cpp is a pointer to the bytes, *sizep is the count. |
591 | * If *cpp is NULL maxsize bytes are allocated |
592 | */ |
593 | bool_t |
594 | xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) |
595 | { |
596 | char *sp = *cpp; /* sp is the actual string pointer */ |
597 | u_int nodesize; |
598 | |
599 | /* |
600 | * first deal with the length since xdr bytes are counted |
601 | */ |
602 | if (!xdr_u_int (xdrs, sizep)) |
603 | { |
604 | return FALSE; |
605 | } |
606 | nodesize = *sizep; |
607 | if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) |
608 | { |
609 | return FALSE; |
610 | } |
611 | |
612 | /* |
613 | * now deal with the actual bytes |
614 | */ |
615 | switch (xdrs->x_op) |
616 | { |
617 | case XDR_DECODE: |
618 | if (nodesize == 0) |
619 | { |
620 | return TRUE; |
621 | } |
622 | if (sp == NULL) |
623 | { |
624 | *cpp = sp = (char *) mem_alloc (nodesize); |
625 | } |
626 | if (sp == NULL) |
627 | { |
628 | (void) __fxprintf (NULL, "%s: %s" , __func__, _("out of memory\n" )); |
629 | return FALSE; |
630 | } |
631 | /* fall into ... */ |
632 | |
633 | case XDR_ENCODE: |
634 | return xdr_opaque (xdrs, sp, nodesize); |
635 | |
636 | case XDR_FREE: |
637 | if (sp != NULL) |
638 | { |
639 | mem_free (sp, nodesize); |
640 | *cpp = NULL; |
641 | } |
642 | return TRUE; |
643 | } |
644 | return FALSE; |
645 | } |
646 | #ifdef EXPORT_RPC_SYMBOLS |
647 | libc_hidden_def (xdr_bytes) |
648 | #else |
649 | libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0) |
650 | #endif |
651 | |
652 | /* |
653 | * Implemented here due to commonality of the object. |
654 | */ |
655 | bool_t |
656 | xdr_netobj (XDR *xdrs, struct netobj *np) |
657 | { |
658 | |
659 | return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); |
660 | } |
661 | #ifdef EXPORT_RPC_SYMBOLS |
662 | libc_hidden_def (xdr_netobj) |
663 | #else |
664 | libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0) |
665 | #endif |
666 | |
667 | /* |
668 | * XDR a discriminated union |
669 | * Support routine for discriminated unions. |
670 | * You create an array of xdrdiscrim structures, terminated with |
671 | * an entry with a null procedure pointer. The routine gets |
672 | * the discriminant value and then searches the array of xdrdiscrims |
673 | * looking for that value. It calls the procedure given in the xdrdiscrim |
674 | * to handle the discriminant. If there is no specific routine a default |
675 | * routine may be called. |
676 | * If there is no specific or default routine an error is returned. |
677 | */ |
678 | bool_t |
679 | xdr_union (XDR *xdrs, |
680 | /* enum to decide which arm to work on */ |
681 | enum_t *dscmp, |
682 | /* the union itself */ |
683 | char *unp, |
684 | /* [value, xdr proc] for each arm */ |
685 | const struct xdr_discrim *choices, |
686 | /* default xdr routine */ |
687 | xdrproc_t dfault) |
688 | { |
689 | enum_t dscm; |
690 | |
691 | /* |
692 | * we deal with the discriminator; it's an enum |
693 | */ |
694 | if (!xdr_enum (xdrs, dscmp)) |
695 | { |
696 | return FALSE; |
697 | } |
698 | dscm = *dscmp; |
699 | |
700 | /* |
701 | * search choices for a value that matches the discriminator. |
702 | * if we find one, execute the xdr routine for that value. |
703 | */ |
704 | for (; choices->proc != NULL_xdrproc_t; choices++) |
705 | { |
706 | if (choices->value == dscm) |
707 | return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED); |
708 | } |
709 | |
710 | /* |
711 | * no match - execute the default xdr routine if there is one |
712 | */ |
713 | return ((dfault == NULL_xdrproc_t) ? FALSE : |
714 | (*dfault) (xdrs, unp, LASTUNSIGNED)); |
715 | } |
716 | libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0) |
717 | |
718 | |
719 | /* |
720 | * Non-portable xdr primitives. |
721 | * Care should be taken when moving these routines to new architectures. |
722 | */ |
723 | |
724 | |
725 | /* |
726 | * XDR null terminated ASCII strings |
727 | * xdr_string deals with "C strings" - arrays of bytes that are |
728 | * terminated by a NULL character. The parameter cpp references a |
729 | * pointer to storage; If the pointer is null, then the necessary |
730 | * storage is allocated. The last parameter is the max allowed length |
731 | * of the string as specified by a protocol. |
732 | */ |
733 | bool_t |
734 | xdr_string (XDR *xdrs, char **cpp, u_int maxsize) |
735 | { |
736 | char *sp = *cpp; /* sp is the actual string pointer */ |
737 | /* Initialize to silence the compiler. It is not really needed because SIZE |
738 | never actually gets used without being initialized. */ |
739 | u_int size = 0; |
740 | u_int nodesize; |
741 | |
742 | /* |
743 | * first deal with the length since xdr strings are counted-strings |
744 | */ |
745 | switch (xdrs->x_op) |
746 | { |
747 | case XDR_FREE: |
748 | if (sp == NULL) |
749 | { |
750 | return TRUE; /* already free */ |
751 | } |
752 | /* fall through... */ |
753 | case XDR_ENCODE: |
754 | if (sp == NULL) |
755 | return FALSE; |
756 | size = strlen (sp); |
757 | break; |
758 | case XDR_DECODE: |
759 | break; |
760 | } |
761 | if (!xdr_u_int (xdrs, &size)) |
762 | { |
763 | return FALSE; |
764 | } |
765 | if (size > maxsize) |
766 | { |
767 | return FALSE; |
768 | } |
769 | nodesize = size + 1; |
770 | if (nodesize == 0) |
771 | { |
772 | /* This means an overflow. It a bug in the caller which |
773 | provided a too large maxsize but nevertheless catch it |
774 | here. */ |
775 | return FALSE; |
776 | } |
777 | |
778 | /* |
779 | * now deal with the actual bytes |
780 | */ |
781 | switch (xdrs->x_op) |
782 | { |
783 | case XDR_DECODE: |
784 | if (sp == NULL) |
785 | *cpp = sp = (char *) mem_alloc (nodesize); |
786 | if (sp == NULL) |
787 | { |
788 | (void) __fxprintf (NULL, "%s: %s" , __func__, _("out of memory\n" )); |
789 | return FALSE; |
790 | } |
791 | sp[size] = 0; |
792 | /* fall into ... */ |
793 | |
794 | case XDR_ENCODE: |
795 | return xdr_opaque (xdrs, sp, size); |
796 | |
797 | case XDR_FREE: |
798 | mem_free (sp, nodesize); |
799 | *cpp = NULL; |
800 | return TRUE; |
801 | } |
802 | return FALSE; |
803 | } |
804 | #ifdef EXPORT_RPC_SYMBOLS |
805 | libc_hidden_def (xdr_string) |
806 | #else |
807 | libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0) |
808 | #endif |
809 | |
810 | /* |
811 | * Wrapper for xdr_string that can be called directly from |
812 | * routines like clnt_call |
813 | */ |
814 | bool_t |
815 | xdr_wrapstring (XDR *xdrs, char **cpp) |
816 | { |
817 | if (xdr_string (xdrs, cpp, LASTUNSIGNED)) |
818 | { |
819 | return TRUE; |
820 | } |
821 | return FALSE; |
822 | } |
823 | #ifdef EXPORT_RPC_SYMBOLS |
824 | libc_hidden_def (xdr_wrapstring) |
825 | #else |
826 | libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0) |
827 | #endif |
828 | |