]>
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> | |
47 | ||
51028f34 | 48 | |
28f540f4 RM |
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 | */ | |
a1129917 | 59 | static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; |
28f540f4 RM |
60 | |
61 | /* | |
62 | * Free a data structure using XDR | |
63 | * Not a filter, but a convenient utility nonetheless | |
64 | */ | |
65 | void | |
a1129917 | 66 | xdr_free (xdrproc_t proc, char *objp) |
28f540f4 | 67 | { |
e7fd8a39 | 68 | XDR x; |
be64fe6d | 69 | |
e7fd8a39 UD |
70 | x.x_op = XDR_FREE; |
71 | (*proc) (&x, objp); | |
28f540f4 | 72 | } |
7b57bfe5 UD |
73 | #ifdef EXPORT_RPC_SYMBOLS |
74 | libc_hidden_def (xdr_free) | |
75 | #else | |
021db4be | 76 | libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0) |
7b57bfe5 | 77 | #endif |
28f540f4 RM |
78 | |
79 | /* | |
80 | * XDR nothing | |
81 | */ | |
82 | bool_t | |
e7fd8a39 | 83 | xdr_void (void) |
28f540f4 | 84 | { |
e7fd8a39 | 85 | return TRUE; |
28f540f4 | 86 | } |
7b57bfe5 UD |
87 | #ifdef EXPORT_RPC_SYMBOLS |
88 | libc_hidden_def (xdr_void) | |
89 | #else | |
021db4be | 90 | libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0) |
7b57bfe5 | 91 | #endif |
28f540f4 RM |
92 | |
93 | /* | |
94 | * XDR integers | |
95 | */ | |
96 | bool_t | |
a1129917 | 97 | xdr_int (XDR *xdrs, int *ip) |
28f540f4 RM |
98 | { |
99 | ||
e7fd8a39 UD |
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; | |
28f540f4 | 113 | } |
e7fd8a39 UD |
114 | *ip = (int) l; |
115 | case XDR_FREE: | |
116 | return TRUE; | |
117 | } | |
118 | return FALSE; | |
119 | #elif INT_MAX == LONG_MAX | |
7b57bfe5 | 120 | return xdr_long (xdrs, (long *) ip); |
e7fd8a39 | 121 | #elif INT_MAX == SHRT_MAX |
7b57bfe5 | 122 | return xdr_short (xdrs, (short *) ip); |
e7fd8a39 UD |
123 | #else |
124 | #error unexpected integer sizes in_xdr_int() | |
125 | #endif | |
28f540f4 | 126 | } |
7b57bfe5 UD |
127 | #ifdef EXPORT_RPC_SYMBOLS |
128 | libc_hidden_def (xdr_int) | |
129 | #else | |
021db4be | 130 | libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0) |
7b57bfe5 | 131 | #endif |
28f540f4 RM |
132 | |
133 | /* | |
134 | * XDR unsigned integers | |
135 | */ | |
136 | bool_t | |
a1129917 | 137 | xdr_u_int (XDR *xdrs, u_int *up) |
28f540f4 | 138 | { |
e7fd8a39 | 139 | #if UINT_MAX < ULONG_MAX |
b34cbd14 | 140 | long l; |
e7fd8a39 UD |
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; | |
28f540f4 | 152 | } |
b34cbd14 | 153 | *up = (u_int) (u_long) l; |
e7fd8a39 UD |
154 | case XDR_FREE: |
155 | return TRUE; | |
156 | } | |
157 | return FALSE; | |
158 | #elif UINT_MAX == ULONG_MAX | |
7b57bfe5 | 159 | return xdr_u_long (xdrs, (u_long *) up); |
e7fd8a39 | 160 | #elif UINT_MAX == USHRT_MAX |
7b57bfe5 | 161 | return xdr_short (xdrs, (short *) up); |
e7fd8a39 UD |
162 | #else |
163 | #error unexpected integer sizes in_xdr_u_int() | |
164 | #endif | |
28f540f4 | 165 | } |
7b57bfe5 UD |
166 | #ifdef EXPORT_RPC_SYMBOLS |
167 | libc_hidden_def (xdr_u_int) | |
168 | #else | |
021db4be | 169 | libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0) |
7b57bfe5 | 170 | #endif |
28f540f4 RM |
171 | |
172 | /* | |
173 | * XDR long integers | |
b1c15739 UD |
174 | * The definition of xdr_long() is kept for backward |
175 | * compatibility. Instead xdr_int() should be used. | |
28f540f4 RM |
176 | */ |
177 | bool_t | |
a1129917 | 178 | xdr_long (XDR *xdrs, long *lp) |
28f540f4 RM |
179 | { |
180 | ||
b1c15739 UD |
181 | if (xdrs->x_op == XDR_ENCODE |
182 | && (sizeof (int32_t) == sizeof (long) | |
183 | || (int32_t) *lp == *lp)) | |
e7fd8a39 | 184 | return XDR_PUTLONG (xdrs, lp); |
28f540f4 | 185 | |
e7fd8a39 UD |
186 | if (xdrs->x_op == XDR_DECODE) |
187 | return XDR_GETLONG (xdrs, lp); | |
28f540f4 | 188 | |
e7fd8a39 UD |
189 | if (xdrs->x_op == XDR_FREE) |
190 | return TRUE; | |
28f540f4 | 191 | |
e7fd8a39 | 192 | return FALSE; |
28f540f4 | 193 | } |
7b57bfe5 UD |
194 | #ifdef EXPORT_RPC_SYMBOLS |
195 | libc_hidden_def (xdr_long) | |
196 | #else | |
021db4be | 197 | libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0) |
7b57bfe5 | 198 | #endif |
28f540f4 RM |
199 | |
200 | /* | |
201 | * XDR unsigned long integers | |
b1c15739 UD |
202 | * The definition of xdr_u_long() is kept for backward |
203 | * compatibility. Instead xdr_u_int() should be used. | |
28f540f4 RM |
204 | */ |
205 | bool_t | |
a1129917 | 206 | xdr_u_long (XDR *xdrs, u_long *ulp) |
28f540f4 | 207 | { |
e7fd8a39 UD |
208 | switch (xdrs->x_op) |
209 | { | |
210 | case XDR_DECODE: | |
f218b5f5 UD |
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 | } | |
e7fd8a39 UD |
220 | |
221 | case XDR_ENCODE: | |
b1c15739 UD |
222 | if (sizeof (uint32_t) != sizeof (u_long) |
223 | && (uint32_t) *ulp != *ulp) | |
224 | return FALSE; | |
225 | ||
e7fd8a39 UD |
226 | return XDR_PUTLONG (xdrs, (long *) ulp); |
227 | ||
228 | case XDR_FREE: | |
229 | return TRUE; | |
230 | } | |
231 | return FALSE; | |
28f540f4 | 232 | } |
7b57bfe5 UD |
233 | #ifdef EXPORT_RPC_SYMBOLS |
234 | libc_hidden_def (xdr_u_long) | |
235 | #else | |
021db4be | 236 | libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0) |
7b57bfe5 | 237 | #endif |
28f540f4 | 238 | |
50f301a8 AS |
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 | { | |
9cfe5381 | 246 | long int t1, t2; |
50f301a8 AS |
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; | |
bb6e8ca3 | 260 | *llp |= (uint32_t) t2; |
50f301a8 AS |
261 | return TRUE; |
262 | } | |
263 | ||
264 | if (xdrs->x_op == XDR_FREE) | |
265 | return TRUE; | |
266 | ||
267 | return FALSE; | |
268 | } | |
7b57bfe5 UD |
269 | #ifdef EXPORT_RPC_SYMBOLS |
270 | libc_hidden_def (xdr_hyper) | |
271 | #else | |
021db4be | 272 | libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1) |
7b57bfe5 | 273 | #endif |
50f301a8 AS |
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 | { | |
9cfe5381 | 282 | long int t1, t2; |
50f301a8 AS |
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; | |
bb6e8ca3 | 296 | *ullp |= (uint32_t) t2; |
50f301a8 AS |
297 | return TRUE; |
298 | } | |
299 | ||
300 | if (xdrs->x_op == XDR_FREE) | |
301 | return TRUE; | |
302 | ||
303 | return FALSE; | |
304 | } | |
7b57bfe5 UD |
305 | #ifdef EXPORT_RPC_SYMBOLS |
306 | libc_hidden_def (xdr_u_hyper) | |
307 | #else | |
021db4be | 308 | libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1) |
7b57bfe5 | 309 | #endif |
50f301a8 AS |
310 | |
311 | bool_t | |
312 | xdr_longlong_t (XDR *xdrs, quad_t *llp) | |
313 | { | |
7b57bfe5 | 314 | return xdr_hyper (xdrs, llp); |
50f301a8 | 315 | } |
7b57bfe5 UD |
316 | #ifdef EXPORT_RPC_SYMBOLS |
317 | libc_hidden_def (xdr_longlong_t) | |
318 | #else | |
021db4be | 319 | libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1) |
7b57bfe5 | 320 | #endif |
50f301a8 AS |
321 | |
322 | bool_t | |
323 | xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) | |
324 | { | |
7b57bfe5 | 325 | return xdr_u_hyper (xdrs, ullp); |
50f301a8 | 326 | } |
7b57bfe5 UD |
327 | #ifdef EXPORT_RPC_SYMBOLS |
328 | libc_hidden_def (xdr_u_longlong_t) | |
329 | #else | |
021db4be | 330 | libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1) |
7b57bfe5 | 331 | #endif |
50f301a8 | 332 | |
28f540f4 RM |
333 | /* |
334 | * XDR short integers | |
335 | */ | |
336 | bool_t | |
50f301a8 | 337 | xdr_short (XDR *xdrs, short *sp) |
28f540f4 | 338 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 351 | } |
e7fd8a39 UD |
352 | *sp = (short) l; |
353 | return TRUE; | |
354 | ||
355 | case XDR_FREE: | |
356 | return TRUE; | |
357 | } | |
358 | return FALSE; | |
28f540f4 | 359 | } |
7b57bfe5 UD |
360 | #ifdef EXPORT_RPC_SYMBOLS |
361 | libc_hidden_def (xdr_short) | |
362 | #else | |
021db4be | 363 | libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0) |
7b57bfe5 | 364 | #endif |
28f540f4 RM |
365 | |
366 | /* | |
367 | * XDR unsigned short integers | |
368 | */ | |
369 | bool_t | |
50f301a8 | 370 | xdr_u_short (XDR *xdrs, u_short *usp) |
28f540f4 | 371 | { |
9cfe5381 | 372 | long l; |
e7fd8a39 UD |
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; | |
28f540f4 | 384 | } |
9cfe5381 | 385 | *usp = (u_short) (u_long) l; |
e7fd8a39 UD |
386 | return TRUE; |
387 | ||
388 | case XDR_FREE: | |
389 | return TRUE; | |
390 | } | |
391 | return FALSE; | |
28f540f4 | 392 | } |
7b57bfe5 UD |
393 | #ifdef EXPORT_RPC_SYMBOLS |
394 | libc_hidden_def (xdr_u_short) | |
395 | #else | |
021db4be | 396 | libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0) |
7b57bfe5 | 397 | #endif |
28f540f4 RM |
398 | |
399 | ||
400 | /* | |
401 | * XDR a char | |
402 | */ | |
403 | bool_t | |
50f301a8 | 404 | xdr_char (XDR *xdrs, char *cp) |
28f540f4 | 405 | { |
e7fd8a39 UD |
406 | int i; |
407 | ||
408 | i = (*cp); | |
7b57bfe5 | 409 | if (!xdr_int (xdrs, &i)) |
e7fd8a39 UD |
410 | { |
411 | return FALSE; | |
412 | } | |
413 | *cp = i; | |
414 | return TRUE; | |
28f540f4 | 415 | } |
7b57bfe5 UD |
416 | #ifdef EXPORT_RPC_SYMBOLS |
417 | libc_hidden_def (xdr_char) | |
418 | #else | |
021db4be | 419 | libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0) |
7b57bfe5 | 420 | #endif |
28f540f4 RM |
421 | |
422 | /* | |
423 | * XDR an unsigned char | |
424 | */ | |
425 | bool_t | |
50f301a8 | 426 | xdr_u_char (XDR *xdrs, u_char *cp) |
28f540f4 | 427 | { |
e7fd8a39 UD |
428 | u_int u; |
429 | ||
430 | u = (*cp); | |
7b57bfe5 | 431 | if (!xdr_u_int (xdrs, &u)) |
e7fd8a39 UD |
432 | { |
433 | return FALSE; | |
434 | } | |
435 | *cp = u; | |
436 | return TRUE; | |
28f540f4 | 437 | } |
7b57bfe5 UD |
438 | #ifdef EXPORT_RPC_SYMBOLS |
439 | libc_hidden_def (xdr_u_char) | |
440 | #else | |
021db4be | 441 | libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0) |
7b57bfe5 | 442 | #endif |
28f540f4 RM |
443 | |
444 | /* | |
445 | * XDR booleans | |
446 | */ | |
447 | bool_t | |
50f301a8 | 448 | xdr_bool (XDR *xdrs, bool_t *bp) |
28f540f4 | 449 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 462 | } |
e7fd8a39 UD |
463 | *bp = (lb == XDR_FALSE) ? FALSE : TRUE; |
464 | return TRUE; | |
465 | ||
466 | case XDR_FREE: | |
467 | return TRUE; | |
468 | } | |
469 | return FALSE; | |
28f540f4 | 470 | } |
7b57bfe5 UD |
471 | #ifdef EXPORT_RPC_SYMBOLS |
472 | libc_hidden_def (xdr_bool) | |
473 | #else | |
021db4be | 474 | libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0) |
7b57bfe5 | 475 | #endif |
28f540f4 RM |
476 | |
477 | /* | |
478 | * XDR enumerations | |
479 | */ | |
480 | bool_t | |
50f301a8 | 481 | xdr_enum (XDR *xdrs, enum_t *ep) |
28f540f4 | 482 | { |
e7fd8a39 UD |
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 | ||
28f540f4 | 511 | } |
e7fd8a39 UD |
512 | return FALSE; |
513 | #else | |
7b57bfe5 | 514 | return xdr_long (xdrs, (long *) ep); |
e7fd8a39 UD |
515 | #endif |
516 | } | |
517 | else if (sizeof (enum sizecheck) == sizeof (short)) | |
518 | { | |
7b57bfe5 | 519 | return xdr_short (xdrs, (short *) ep); |
e7fd8a39 UD |
520 | } |
521 | else | |
522 | { | |
523 | return FALSE; | |
524 | } | |
28f540f4 | 525 | } |
7b57bfe5 UD |
526 | #ifdef EXPORT_RPC_SYMBOLS |
527 | libc_hidden_def (xdr_enum) | |
528 | #else | |
021db4be | 529 | libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0) |
7b57bfe5 | 530 | #endif |
28f540f4 RM |
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 | |
50f301a8 | 538 | xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) |
28f540f4 | 539 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 562 | } |
e7fd8a39 UD |
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; | |
28f540f4 | 580 | } |
7b57bfe5 UD |
581 | #ifdef EXPORT_RPC_SYMBOLS |
582 | libc_hidden_def (xdr_opaque) | |
583 | #else | |
021db4be | 584 | libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0) |
7b57bfe5 | 585 | #endif |
28f540f4 RM |
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 | |
9d46370c | 593 | xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) |
28f540f4 | 594 | { |
e7fd8a39 UD |
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 | */ | |
7b57bfe5 | 601 | if (!xdr_u_int (xdrs, sizep)) |
e7fd8a39 UD |
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); | |
28f540f4 | 624 | } |
e7fd8a39 UD |
625 | if (sp == NULL) |
626 | { | |
1d20f7f8 | 627 | (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); |
e7fd8a39 | 628 | return FALSE; |
28f540f4 | 629 | } |
e7fd8a39 | 630 | /* fall into ... */ |
28f540f4 | 631 | |
e7fd8a39 | 632 | case XDR_ENCODE: |
7b57bfe5 | 633 | return xdr_opaque (xdrs, sp, nodesize); |
e7fd8a39 UD |
634 | |
635 | case XDR_FREE: | |
636 | if (sp != NULL) | |
637 | { | |
638 | mem_free (sp, nodesize); | |
639 | *cpp = NULL; | |
28f540f4 | 640 | } |
e7fd8a39 UD |
641 | return TRUE; |
642 | } | |
643 | return FALSE; | |
28f540f4 | 644 | } |
7b57bfe5 UD |
645 | #ifdef EXPORT_RPC_SYMBOLS |
646 | libc_hidden_def (xdr_bytes) | |
647 | #else | |
021db4be | 648 | libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0) |
7b57bfe5 | 649 | #endif |
28f540f4 RM |
650 | |
651 | /* | |
652 | * Implemented here due to commonality of the object. | |
653 | */ | |
654 | bool_t | |
9d46370c | 655 | xdr_netobj (XDR *xdrs, struct netobj *np) |
28f540f4 RM |
656 | { |
657 | ||
7b57bfe5 | 658 | return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); |
28f540f4 | 659 | } |
7b57bfe5 UD |
660 | #ifdef EXPORT_RPC_SYMBOLS |
661 | libc_hidden_def (xdr_netobj) | |
662 | #else | |
021db4be | 663 | libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0) |
7b57bfe5 | 664 | #endif |
28f540f4 RM |
665 | |
666 | /* | |
6d52618b | 667 | * XDR a discriminated union |
28f540f4 RM |
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 | |
e7fd8a39 UD |
678 | xdr_union (xdrs, dscmp, unp, choices, dfault) |
679 | XDR *xdrs; | |
680 | enum_t *dscmp; /* enum to decide which arm to work on */ | |
681 | char *unp; /* the union itself */ | |
682 | const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ | |
683 | xdrproc_t dfault; /* default xdr routine */ | |
28f540f4 | 684 | { |
e7fd8a39 UD |
685 | enum_t dscm; |
686 | ||
687 | /* | |
688 | * we deal with the discriminator; it's an enum | |
689 | */ | |
7b57bfe5 | 690 | if (!xdr_enum (xdrs, dscmp)) |
e7fd8a39 UD |
691 | { |
692 | return FALSE; | |
693 | } | |
694 | dscm = *dscmp; | |
695 | ||
696 | /* | |
697 | * search choices for a value that matches the discriminator. | |
698 | * if we find one, execute the xdr routine for that value. | |
699 | */ | |
700 | for (; choices->proc != NULL_xdrproc_t; choices++) | |
701 | { | |
702 | if (choices->value == dscm) | |
703 | return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED); | |
704 | } | |
705 | ||
706 | /* | |
707 | * no match - execute the default xdr routine if there is one | |
708 | */ | |
709 | return ((dfault == NULL_xdrproc_t) ? FALSE : | |
710 | (*dfault) (xdrs, unp, LASTUNSIGNED)); | |
28f540f4 | 711 | } |
021db4be | 712 | libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0) |
28f540f4 RM |
713 | |
714 | ||
715 | /* | |
716 | * Non-portable xdr primitives. | |
717 | * Care should be taken when moving these routines to new architectures. | |
718 | */ | |
719 | ||
720 | ||
721 | /* | |
722 | * XDR null terminated ASCII strings | |
723 | * xdr_string deals with "C strings" - arrays of bytes that are | |
724 | * terminated by a NULL character. The parameter cpp references a | |
725 | * pointer to storage; If the pointer is null, then the necessary | |
726 | * storage is allocated. The last parameter is the max allowed length | |
727 | * of the string as specified by a protocol. | |
728 | */ | |
729 | bool_t | |
9d46370c | 730 | xdr_string (XDR *xdrs, char **cpp, u_int maxsize) |
28f540f4 | 731 | { |
e7fd8a39 | 732 | char *sp = *cpp; /* sp is the actual string pointer */ |
d69b7f5a SP |
733 | /* Initialize to silence the compiler. It is not really needed because SIZE |
734 | never actually gets used without being initialized. */ | |
6ee3eab4 | 735 | u_int size = 0; |
e7fd8a39 UD |
736 | u_int nodesize; |
737 | ||
738 | /* | |
739 | * first deal with the length since xdr strings are counted-strings | |
740 | */ | |
741 | switch (xdrs->x_op) | |
742 | { | |
743 | case XDR_FREE: | |
744 | if (sp == NULL) | |
745 | { | |
746 | return TRUE; /* already free */ | |
28f540f4 | 747 | } |
e7fd8a39 UD |
748 | /* fall through... */ |
749 | case XDR_ENCODE: | |
750 | if (sp == NULL) | |
751 | return FALSE; | |
752 | size = strlen (sp); | |
753 | break; | |
754 | case XDR_DECODE: | |
755 | break; | |
756 | } | |
7b57bfe5 | 757 | if (!xdr_u_int (xdrs, &size)) |
e7fd8a39 UD |
758 | { |
759 | return FALSE; | |
760 | } | |
761 | if (size > maxsize) | |
762 | { | |
763 | return FALSE; | |
764 | } | |
765 | nodesize = size + 1; | |
a9f17952 UD |
766 | if (nodesize == 0) |
767 | { | |
768 | /* This means an overflow. It a bug in the caller which | |
769 | provided a too large maxsize but nevertheless catch it | |
770 | here. */ | |
771 | return FALSE; | |
772 | } | |
e7fd8a39 UD |
773 | |
774 | /* | |
775 | * now deal with the actual bytes | |
776 | */ | |
777 | switch (xdrs->x_op) | |
778 | { | |
779 | case XDR_DECODE: | |
e7fd8a39 UD |
780 | if (sp == NULL) |
781 | *cpp = sp = (char *) mem_alloc (nodesize); | |
782 | if (sp == NULL) | |
783 | { | |
1d20f7f8 | 784 | (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); |
e7fd8a39 | 785 | return FALSE; |
28f540f4 | 786 | } |
e7fd8a39 UD |
787 | sp[size] = 0; |
788 | /* fall into ... */ | |
789 | ||
790 | case XDR_ENCODE: | |
7b57bfe5 | 791 | return xdr_opaque (xdrs, sp, size); |
e7fd8a39 UD |
792 | |
793 | case XDR_FREE: | |
794 | mem_free (sp, nodesize); | |
795 | *cpp = NULL; | |
796 | return TRUE; | |
797 | } | |
798 | return FALSE; | |
28f540f4 | 799 | } |
7b57bfe5 UD |
800 | #ifdef EXPORT_RPC_SYMBOLS |
801 | libc_hidden_def (xdr_string) | |
802 | #else | |
021db4be | 803 | libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0) |
7b57bfe5 | 804 | #endif |
28f540f4 | 805 | |
be64fe6d RM |
806 | /* |
807 | * Wrapper for xdr_string that can be called directly from | |
28f540f4 RM |
808 | * routines like clnt_call |
809 | */ | |
810 | bool_t | |
9d46370c | 811 | xdr_wrapstring (XDR *xdrs, char **cpp) |
28f540f4 | 812 | { |
7b57bfe5 | 813 | if (xdr_string (xdrs, cpp, LASTUNSIGNED)) |
e7fd8a39 UD |
814 | { |
815 | return TRUE; | |
816 | } | |
817 | return FALSE; | |
28f540f4 | 818 | } |
7b57bfe5 UD |
819 | #ifdef EXPORT_RPC_SYMBOLS |
820 | libc_hidden_def (xdr_wrapstring) | |
821 | #else | |
021db4be | 822 | libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0) |
7b57bfe5 | 823 | #endif |