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