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