]>
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 UD |
115 | *ip = (int) l; |
116 | case XDR_FREE: | |
117 | return TRUE; | |
118 | } | |
119 | return FALSE; | |
120 | #elif INT_MAX == LONG_MAX | |
7b57bfe5 | 121 | return xdr_long (xdrs, (long *) ip); |
e7fd8a39 | 122 | #elif INT_MAX == SHRT_MAX |
7b57bfe5 | 123 | return xdr_short (xdrs, (short *) ip); |
e7fd8a39 UD |
124 | #else |
125 | #error unexpected integer sizes in_xdr_int() | |
126 | #endif | |
28f540f4 | 127 | } |
7b57bfe5 UD |
128 | #ifdef EXPORT_RPC_SYMBOLS |
129 | libc_hidden_def (xdr_int) | |
130 | #else | |
021db4be | 131 | libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0) |
7b57bfe5 | 132 | #endif |
28f540f4 RM |
133 | |
134 | /* | |
135 | * XDR unsigned integers | |
136 | */ | |
137 | bool_t | |
a1129917 | 138 | xdr_u_int (XDR *xdrs, u_int *up) |
28f540f4 | 139 | { |
e7fd8a39 | 140 | #if UINT_MAX < ULONG_MAX |
b34cbd14 | 141 | long l; |
e7fd8a39 UD |
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; | |
28f540f4 | 153 | } |
b34cbd14 | 154 | *up = (u_int) (u_long) l; |
e7fd8a39 UD |
155 | case XDR_FREE: |
156 | return TRUE; | |
157 | } | |
158 | return FALSE; | |
159 | #elif UINT_MAX == ULONG_MAX | |
7b57bfe5 | 160 | return xdr_u_long (xdrs, (u_long *) up); |
e7fd8a39 | 161 | #elif UINT_MAX == USHRT_MAX |
7b57bfe5 | 162 | return xdr_short (xdrs, (short *) up); |
e7fd8a39 UD |
163 | #else |
164 | #error unexpected integer sizes in_xdr_u_int() | |
165 | #endif | |
28f540f4 | 166 | } |
7b57bfe5 UD |
167 | #ifdef EXPORT_RPC_SYMBOLS |
168 | libc_hidden_def (xdr_u_int) | |
169 | #else | |
021db4be | 170 | libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0) |
7b57bfe5 | 171 | #endif |
28f540f4 RM |
172 | |
173 | /* | |
174 | * XDR long integers | |
b1c15739 UD |
175 | * The definition of xdr_long() is kept for backward |
176 | * compatibility. Instead xdr_int() should be used. | |
28f540f4 RM |
177 | */ |
178 | bool_t | |
a1129917 | 179 | xdr_long (XDR *xdrs, long *lp) |
28f540f4 RM |
180 | { |
181 | ||
b1c15739 UD |
182 | if (xdrs->x_op == XDR_ENCODE |
183 | && (sizeof (int32_t) == sizeof (long) | |
184 | || (int32_t) *lp == *lp)) | |
e7fd8a39 | 185 | return XDR_PUTLONG (xdrs, lp); |
28f540f4 | 186 | |
e7fd8a39 UD |
187 | if (xdrs->x_op == XDR_DECODE) |
188 | return XDR_GETLONG (xdrs, lp); | |
28f540f4 | 189 | |
e7fd8a39 UD |
190 | if (xdrs->x_op == XDR_FREE) |
191 | return TRUE; | |
28f540f4 | 192 | |
e7fd8a39 | 193 | return FALSE; |
28f540f4 | 194 | } |
7b57bfe5 UD |
195 | #ifdef EXPORT_RPC_SYMBOLS |
196 | libc_hidden_def (xdr_long) | |
197 | #else | |
021db4be | 198 | libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0) |
7b57bfe5 | 199 | #endif |
28f540f4 RM |
200 | |
201 | /* | |
202 | * XDR unsigned long integers | |
b1c15739 UD |
203 | * The definition of xdr_u_long() is kept for backward |
204 | * compatibility. Instead xdr_u_int() should be used. | |
28f540f4 RM |
205 | */ |
206 | bool_t | |
a1129917 | 207 | xdr_u_long (XDR *xdrs, u_long *ulp) |
28f540f4 | 208 | { |
e7fd8a39 UD |
209 | switch (xdrs->x_op) |
210 | { | |
211 | case XDR_DECODE: | |
f218b5f5 UD |
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 | } | |
e7fd8a39 UD |
221 | |
222 | case XDR_ENCODE: | |
b1c15739 UD |
223 | if (sizeof (uint32_t) != sizeof (u_long) |
224 | && (uint32_t) *ulp != *ulp) | |
225 | return FALSE; | |
226 | ||
e7fd8a39 UD |
227 | return XDR_PUTLONG (xdrs, (long *) ulp); |
228 | ||
229 | case XDR_FREE: | |
230 | return TRUE; | |
231 | } | |
232 | return FALSE; | |
28f540f4 | 233 | } |
7b57bfe5 UD |
234 | #ifdef EXPORT_RPC_SYMBOLS |
235 | libc_hidden_def (xdr_u_long) | |
236 | #else | |
021db4be | 237 | libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0) |
7b57bfe5 | 238 | #endif |
28f540f4 | 239 | |
50f301a8 AS |
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 | { | |
9cfe5381 | 247 | long int t1, t2; |
50f301a8 AS |
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; | |
bb6e8ca3 | 261 | *llp |= (uint32_t) t2; |
50f301a8 AS |
262 | return TRUE; |
263 | } | |
264 | ||
265 | if (xdrs->x_op == XDR_FREE) | |
266 | return TRUE; | |
267 | ||
268 | return FALSE; | |
269 | } | |
7b57bfe5 UD |
270 | #ifdef EXPORT_RPC_SYMBOLS |
271 | libc_hidden_def (xdr_hyper) | |
272 | #else | |
021db4be | 273 | libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1) |
7b57bfe5 | 274 | #endif |
50f301a8 AS |
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 | { | |
9cfe5381 | 283 | long int t1, t2; |
50f301a8 AS |
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; | |
bb6e8ca3 | 297 | *ullp |= (uint32_t) t2; |
50f301a8 AS |
298 | return TRUE; |
299 | } | |
300 | ||
301 | if (xdrs->x_op == XDR_FREE) | |
302 | return TRUE; | |
303 | ||
304 | return FALSE; | |
305 | } | |
7b57bfe5 UD |
306 | #ifdef EXPORT_RPC_SYMBOLS |
307 | libc_hidden_def (xdr_u_hyper) | |
308 | #else | |
021db4be | 309 | libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1) |
7b57bfe5 | 310 | #endif |
50f301a8 AS |
311 | |
312 | bool_t | |
313 | xdr_longlong_t (XDR *xdrs, quad_t *llp) | |
314 | { | |
7b57bfe5 | 315 | return xdr_hyper (xdrs, llp); |
50f301a8 | 316 | } |
7b57bfe5 UD |
317 | #ifdef EXPORT_RPC_SYMBOLS |
318 | libc_hidden_def (xdr_longlong_t) | |
319 | #else | |
021db4be | 320 | libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1) |
7b57bfe5 | 321 | #endif |
50f301a8 AS |
322 | |
323 | bool_t | |
324 | xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) | |
325 | { | |
7b57bfe5 | 326 | return xdr_u_hyper (xdrs, ullp); |
50f301a8 | 327 | } |
7b57bfe5 UD |
328 | #ifdef EXPORT_RPC_SYMBOLS |
329 | libc_hidden_def (xdr_u_longlong_t) | |
330 | #else | |
021db4be | 331 | libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1) |
7b57bfe5 | 332 | #endif |
50f301a8 | 333 | |
28f540f4 RM |
334 | /* |
335 | * XDR short integers | |
336 | */ | |
337 | bool_t | |
50f301a8 | 338 | xdr_short (XDR *xdrs, short *sp) |
28f540f4 | 339 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 352 | } |
e7fd8a39 UD |
353 | *sp = (short) l; |
354 | return TRUE; | |
355 | ||
356 | case XDR_FREE: | |
357 | return TRUE; | |
358 | } | |
359 | return FALSE; | |
28f540f4 | 360 | } |
7b57bfe5 UD |
361 | #ifdef EXPORT_RPC_SYMBOLS |
362 | libc_hidden_def (xdr_short) | |
363 | #else | |
021db4be | 364 | libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0) |
7b57bfe5 | 365 | #endif |
28f540f4 RM |
366 | |
367 | /* | |
368 | * XDR unsigned short integers | |
369 | */ | |
370 | bool_t | |
50f301a8 | 371 | xdr_u_short (XDR *xdrs, u_short *usp) |
28f540f4 | 372 | { |
9cfe5381 | 373 | long l; |
e7fd8a39 UD |
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; | |
28f540f4 | 385 | } |
9cfe5381 | 386 | *usp = (u_short) (u_long) l; |
e7fd8a39 UD |
387 | return TRUE; |
388 | ||
389 | case XDR_FREE: | |
390 | return TRUE; | |
391 | } | |
392 | return FALSE; | |
28f540f4 | 393 | } |
7b57bfe5 UD |
394 | #ifdef EXPORT_RPC_SYMBOLS |
395 | libc_hidden_def (xdr_u_short) | |
396 | #else | |
021db4be | 397 | libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0) |
7b57bfe5 | 398 | #endif |
28f540f4 RM |
399 | |
400 | ||
401 | /* | |
402 | * XDR a char | |
403 | */ | |
404 | bool_t | |
50f301a8 | 405 | xdr_char (XDR *xdrs, char *cp) |
28f540f4 | 406 | { |
e7fd8a39 UD |
407 | int i; |
408 | ||
409 | i = (*cp); | |
7b57bfe5 | 410 | if (!xdr_int (xdrs, &i)) |
e7fd8a39 UD |
411 | { |
412 | return FALSE; | |
413 | } | |
414 | *cp = i; | |
415 | return TRUE; | |
28f540f4 | 416 | } |
7b57bfe5 UD |
417 | #ifdef EXPORT_RPC_SYMBOLS |
418 | libc_hidden_def (xdr_char) | |
419 | #else | |
021db4be | 420 | libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0) |
7b57bfe5 | 421 | #endif |
28f540f4 RM |
422 | |
423 | /* | |
424 | * XDR an unsigned char | |
425 | */ | |
426 | bool_t | |
50f301a8 | 427 | xdr_u_char (XDR *xdrs, u_char *cp) |
28f540f4 | 428 | { |
e7fd8a39 UD |
429 | u_int u; |
430 | ||
431 | u = (*cp); | |
7b57bfe5 | 432 | if (!xdr_u_int (xdrs, &u)) |
e7fd8a39 UD |
433 | { |
434 | return FALSE; | |
435 | } | |
436 | *cp = u; | |
437 | return TRUE; | |
28f540f4 | 438 | } |
7b57bfe5 UD |
439 | #ifdef EXPORT_RPC_SYMBOLS |
440 | libc_hidden_def (xdr_u_char) | |
441 | #else | |
021db4be | 442 | libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0) |
7b57bfe5 | 443 | #endif |
28f540f4 RM |
444 | |
445 | /* | |
446 | * XDR booleans | |
447 | */ | |
448 | bool_t | |
50f301a8 | 449 | xdr_bool (XDR *xdrs, bool_t *bp) |
28f540f4 | 450 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 463 | } |
e7fd8a39 UD |
464 | *bp = (lb == XDR_FALSE) ? FALSE : TRUE; |
465 | return TRUE; | |
466 | ||
467 | case XDR_FREE: | |
468 | return TRUE; | |
469 | } | |
470 | return FALSE; | |
28f540f4 | 471 | } |
7b57bfe5 UD |
472 | #ifdef EXPORT_RPC_SYMBOLS |
473 | libc_hidden_def (xdr_bool) | |
474 | #else | |
021db4be | 475 | libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0) |
7b57bfe5 | 476 | #endif |
28f540f4 RM |
477 | |
478 | /* | |
479 | * XDR enumerations | |
480 | */ | |
481 | bool_t | |
50f301a8 | 482 | xdr_enum (XDR *xdrs, enum_t *ep) |
28f540f4 | 483 | { |
e7fd8a39 UD |
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 | ||
28f540f4 | 512 | } |
e7fd8a39 UD |
513 | return FALSE; |
514 | #else | |
7b57bfe5 | 515 | return xdr_long (xdrs, (long *) ep); |
e7fd8a39 UD |
516 | #endif |
517 | } | |
518 | else if (sizeof (enum sizecheck) == sizeof (short)) | |
519 | { | |
7b57bfe5 | 520 | return xdr_short (xdrs, (short *) ep); |
e7fd8a39 UD |
521 | } |
522 | else | |
523 | { | |
524 | return FALSE; | |
525 | } | |
28f540f4 | 526 | } |
7b57bfe5 UD |
527 | #ifdef EXPORT_RPC_SYMBOLS |
528 | libc_hidden_def (xdr_enum) | |
529 | #else | |
021db4be | 530 | libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0) |
7b57bfe5 | 531 | #endif |
28f540f4 RM |
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 | |
50f301a8 | 539 | xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) |
28f540f4 | 540 | { |
e7fd8a39 UD |
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; | |
28f540f4 | 563 | } |
e7fd8a39 UD |
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; | |
28f540f4 | 581 | } |
7b57bfe5 UD |
582 | #ifdef EXPORT_RPC_SYMBOLS |
583 | libc_hidden_def (xdr_opaque) | |
584 | #else | |
021db4be | 585 | libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0) |
7b57bfe5 | 586 | #endif |
28f540f4 RM |
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 | |
9d46370c | 594 | xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) |
28f540f4 | 595 | { |
e7fd8a39 UD |
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 | */ | |
7b57bfe5 | 602 | if (!xdr_u_int (xdrs, sizep)) |
e7fd8a39 UD |
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); | |
28f540f4 | 625 | } |
e7fd8a39 UD |
626 | if (sp == NULL) |
627 | { | |
1d20f7f8 | 628 | (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); |
e7fd8a39 | 629 | return FALSE; |
28f540f4 | 630 | } |
e7fd8a39 | 631 | /* fall into ... */ |
28f540f4 | 632 | |
e7fd8a39 | 633 | case XDR_ENCODE: |
7b57bfe5 | 634 | return xdr_opaque (xdrs, sp, nodesize); |
e7fd8a39 UD |
635 | |
636 | case XDR_FREE: | |
637 | if (sp != NULL) | |
638 | { | |
639 | mem_free (sp, nodesize); | |
640 | *cpp = NULL; | |
28f540f4 | 641 | } |
e7fd8a39 UD |
642 | return TRUE; |
643 | } | |
644 | return FALSE; | |
28f540f4 | 645 | } |
7b57bfe5 UD |
646 | #ifdef EXPORT_RPC_SYMBOLS |
647 | libc_hidden_def (xdr_bytes) | |
648 | #else | |
021db4be | 649 | libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0) |
7b57bfe5 | 650 | #endif |
28f540f4 RM |
651 | |
652 | /* | |
653 | * Implemented here due to commonality of the object. | |
654 | */ | |
655 | bool_t | |
9d46370c | 656 | xdr_netobj (XDR *xdrs, struct netobj *np) |
28f540f4 RM |
657 | { |
658 | ||
7b57bfe5 | 659 | return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); |
28f540f4 | 660 | } |
7b57bfe5 UD |
661 | #ifdef EXPORT_RPC_SYMBOLS |
662 | libc_hidden_def (xdr_netobj) | |
663 | #else | |
021db4be | 664 | libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0) |
7b57bfe5 | 665 | #endif |
28f540f4 RM |
666 | |
667 | /* | |
6d52618b | 668 | * XDR a discriminated union |
28f540f4 RM |
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 | |
80d9be81 JM |
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) | |
28f540f4 | 688 | { |
e7fd8a39 UD |
689 | enum_t dscm; |
690 | ||
691 | /* | |
692 | * we deal with the discriminator; it's an enum | |
693 | */ | |
7b57bfe5 | 694 | if (!xdr_enum (xdrs, dscmp)) |
e7fd8a39 UD |
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)); | |
28f540f4 | 715 | } |
021db4be | 716 | libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0) |
28f540f4 RM |
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 | |
9d46370c | 734 | xdr_string (XDR *xdrs, char **cpp, u_int maxsize) |
28f540f4 | 735 | { |
e7fd8a39 | 736 | char *sp = *cpp; /* sp is the actual string pointer */ |
d69b7f5a SP |
737 | /* Initialize to silence the compiler. It is not really needed because SIZE |
738 | never actually gets used without being initialized. */ | |
6ee3eab4 | 739 | u_int size = 0; |
e7fd8a39 UD |
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 */ | |
28f540f4 | 751 | } |
e7fd8a39 UD |
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 | } | |
7b57bfe5 | 761 | if (!xdr_u_int (xdrs, &size)) |
e7fd8a39 UD |
762 | { |
763 | return FALSE; | |
764 | } | |
765 | if (size > maxsize) | |
766 | { | |
767 | return FALSE; | |
768 | } | |
769 | nodesize = size + 1; | |
a9f17952 UD |
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 | } | |
e7fd8a39 UD |
777 | |
778 | /* | |
779 | * now deal with the actual bytes | |
780 | */ | |
781 | switch (xdrs->x_op) | |
782 | { | |
783 | case XDR_DECODE: | |
e7fd8a39 UD |
784 | if (sp == NULL) |
785 | *cpp = sp = (char *) mem_alloc (nodesize); | |
786 | if (sp == NULL) | |
787 | { | |
1d20f7f8 | 788 | (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); |
e7fd8a39 | 789 | return FALSE; |
28f540f4 | 790 | } |
e7fd8a39 UD |
791 | sp[size] = 0; |
792 | /* fall into ... */ | |
793 | ||
794 | case XDR_ENCODE: | |
7b57bfe5 | 795 | return xdr_opaque (xdrs, sp, size); |
e7fd8a39 UD |
796 | |
797 | case XDR_FREE: | |
798 | mem_free (sp, nodesize); | |
799 | *cpp = NULL; | |
800 | return TRUE; | |
801 | } | |
802 | return FALSE; | |
28f540f4 | 803 | } |
7b57bfe5 UD |
804 | #ifdef EXPORT_RPC_SYMBOLS |
805 | libc_hidden_def (xdr_string) | |
806 | #else | |
021db4be | 807 | libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0) |
7b57bfe5 | 808 | #endif |
28f540f4 | 809 | |
be64fe6d RM |
810 | /* |
811 | * Wrapper for xdr_string that can be called directly from | |
28f540f4 RM |
812 | * routines like clnt_call |
813 | */ | |
814 | bool_t | |
9d46370c | 815 | xdr_wrapstring (XDR *xdrs, char **cpp) |
28f540f4 | 816 | { |
7b57bfe5 | 817 | if (xdr_string (xdrs, cpp, LASTUNSIGNED)) |
e7fd8a39 UD |
818 | { |
819 | return TRUE; | |
820 | } | |
821 | return FALSE; | |
28f540f4 | 822 | } |
7b57bfe5 UD |
823 | #ifdef EXPORT_RPC_SYMBOLS |
824 | libc_hidden_def (xdr_wrapstring) | |
825 | #else | |
021db4be | 826 | libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0) |
7b57bfe5 | 827 | #endif |