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