1 /*********************************************************************
2 * RPC for the Windows NT Operating System
3 * 1993 by Martin F. Gergeleit
4 * Users may use, copy or modify Sun RPC for the Windows NT Operating
5 * System according to the Sun copyright below.
6 *
7 * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO
8 * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE
9 * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
10 *********************************************************************/
11
12 /* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
13 /*
14 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
15 * unrestricted use provided that this legend is included on all tape
16 * media and as a part of the software program in whole or part. Users
17 * may copy or modify Sun RPC without charge, but are not authorized
18 * to license or distribute it to anyone else except as part of a product or
19 * program developed by the user.
20 *
21 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
22 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
24 *
25 * Sun RPC is provided with no support and without any obligation on the
26 * part of Sun Microsystems, Inc. to assist in its use, correction,
27 * modification or enhancement.
28 *
29 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
30 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
31 * OR ANY PART THEREOF.
32 *
33 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
34 * or profits or other special, indirect and consequential damages, even if
35 * Sun has been advised of the possibility of such damages.
36 *
37 * Sun Microsystems, Inc.
38 * 2550 Garcia Avenue
39 * Mountain View, California 94043
40 */
41 #if !defined(lint) && defined(SCCSIDS)
42 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
43 #endif
44
45 /*
46 * xdr.c, Generic XDR routines implementation.
47 *
48 * Copyright (C) 1986, Sun Microsystems, Inc.
49 *
50 * These are the "generic" xdr routines used to serialize and de-serialize
51 * most common data items. See xdr.h for more info on the interface to
52 * xdr.
53 */
54
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h> /* strlen */
58 #include <stdint.h>
59
60 #include <rpc/types.h>
61 #include <rpc/xdr.h>
62
63 /* R-specific */
64 void REprintf(char*, ...);
65 #define fprintf(a, b) REprintf(b)
66
67 #ifdef UNUSED
68 /*
69 * constants specific to the xdr "protocol"
70 */
71 #define XDR_FALSE ((int32_t) 0)
72 #define XDR_TRUE ((int32_t) 1)
73 #define LASTUNSIGNED ((u_int) 0-1)
74 #endif
75
76 /*
77 * for unit alignment
78 */
79 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
80
81 #ifdef UNUSED
82 /*
83 * Free a data structure using XDR
84 * Not a filter, but a convenient utility nonetheless
85 */
86 void
xdr_free(proc,objp)87 xdr_free(proc, objp)
88 xdrproc_t proc;
89 char *objp;
90 {
91 XDR x;
92
93 x.x_op = XDR_FREE;
94 (*proc)(&x, objp);
95 }
96 #endif
97
98 #ifdef UNUSED
99 /*
100 * XDR nothing
101 */
102 bool_t
xdr_void()103 xdr_void(/* xdrs, addr */)
104 /* XDR *xdrs; */
105 /* caddr_t addr; */
106 {
107
108 return (TRUE);
109 }
110 #endif
111
112 /*
113 * XDR integers: always 32-bit in R
114 */
115 bool_t
xdr_int(xdrs,ip)116 xdr_int(xdrs, ip)
117 XDR *xdrs;
118 int *ip;
119 {
120 // return (xdr_long(xdrs, (int32_t *)ip));
121
122 if (xdrs->x_op == XDR_DECODE)
123 return (XDR_GETLONG(xdrs, (int32_t *)ip));
124 if (xdrs->x_op == XDR_ENCODE)
125 return (XDR_PUTLONG(xdrs, (int32_t *)ip));
126 if (xdrs->x_op == XDR_FREE)
127 return (TRUE);
128 return (FALSE);
129 }
130
131 /*
132 * XDR unsigned integers: always 32-bit in R
133 */
134 bool_t
xdr_u_int(xdrs,up)135 xdr_u_int(xdrs, up)
136 XDR *xdrs;
137 u_int *up;
138 {
139 // return (xdr_u_long(xdrs, (uint32_t *)up));
140
141 if (xdrs->x_op == XDR_DECODE)
142 return (XDR_GETLONG(xdrs, (int32_t *)up));
143 if (xdrs->x_op == XDR_ENCODE)
144 return (XDR_PUTLONG(xdrs, (int32_t *)up));
145 if (xdrs->x_op == XDR_FREE)
146 return (TRUE);
147 return (FALSE);
148
149 }
150
151 #ifdef UNUSED
152 /*
153 * XDR long integers
154 * same as xdr_u_long - open coded to save a proc call!
155 */
156 bool_t
xdr_long(xdrs,lp)157 xdr_long(xdrs, lp)
158 register XDR *xdrs;
159 int32_t *lp;
160 {
161
162 if (xdrs->x_op == XDR_ENCODE)
163 return (XDR_PUTLONG(xdrs, lp));
164
165 if (xdrs->x_op == XDR_DECODE)
166 return (XDR_GETLONG(xdrs, lp));
167
168 if (xdrs->x_op == XDR_FREE)
169 return (TRUE);
170
171 return (FALSE);
172 }
173
174 /*
175 * XDR unsigned long integers
176 * same as xdr_long - open coded to save a proc call!
177 */
178 bool_t
xdr_u_long(xdrs,ulp)179 xdr_u_long(xdrs, ulp)
180 register XDR *xdrs;
181 uint32_t *ulp;
182 {
183
184 if (xdrs->x_op == XDR_DECODE)
185 return (XDR_GETLONG(xdrs, (int32_t *)ulp));
186 if (xdrs->x_op == XDR_ENCODE)
187 return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
188 if (xdrs->x_op == XDR_FREE)
189 return (TRUE);
190 return (FALSE);
191 }
192
193 /*
194 * XDR short integers
195 */
196 bool_t
xdr_short(xdrs,sp)197 xdr_short(xdrs, sp)
198 register XDR *xdrs;
199 short *sp;
200 {
201 int32_t l;
202
203 switch (xdrs->x_op) {
204
205 case XDR_ENCODE:
206 l = (int32_t) *sp;
207 return (XDR_PUTLONG(xdrs, &l));
208
209 case XDR_DECODE:
210 if (!XDR_GETLONG(xdrs, &l)) {
211 return (FALSE);
212 }
213 *sp = (short) l;
214 return (TRUE);
215
216 case XDR_FREE:
217 return (TRUE);
218 }
219 return (FALSE);
220 }
221
222 /*
223 * XDR unsigned short integers
224 */
225 bool_t
xdr_u_short(xdrs,usp)226 xdr_u_short(xdrs, usp)
227 register XDR *xdrs;
228 u_short *usp;
229 {
230 uint32_t l;
231
232 switch (xdrs->x_op) {
233
234 case XDR_ENCODE:
235 l = (uint32_t) *usp;
236 return (XDR_PUTLONG(xdrs, &l));
237
238 case XDR_DECODE:
239 if (!XDR_GETLONG(xdrs, &l)) {
240 return (FALSE);
241 }
242 *usp = (u_short) l;
243 return (TRUE);
244
245 case XDR_FREE:
246 return (TRUE);
247 }
248 return (FALSE);
249 }
250
251 /*
252 * XDR a char
253 */
254 bool_t
xdr_char(xdrs,cp)255 xdr_char(xdrs, cp)
256 XDR *xdrs;
257 char *cp;
258 {
259 int i;
260
261 i = (*cp);
262 if (!xdr_int(xdrs, &i)) {
263 return (FALSE);
264 }
265 *cp = i;
266 return (TRUE);
267 }
268
269 /*
270 * XDR an unsigned char
271 */
272 bool_t
xdr_u_char(xdrs,cp)273 xdr_u_char(xdrs, cp)
274 XDR *xdrs;
275 char *cp;
276 {
277 u_int u;
278
279 u = (*cp);
280 if (!xdr_u_int(xdrs, &u)) {
281 return (FALSE);
282 }
283 *cp = u;
284 return (TRUE);
285 }
286
287 /*
288 * XDR booleans
289 */
290 bool_t
xdr_bool(xdrs,bp)291 xdr_bool(xdrs, bp)
292 register XDR *xdrs;
293 bool_t *bp;
294 {
295 int32_t lb;
296
297 switch (xdrs->x_op) {
298
299 case XDR_ENCODE:
300 lb = *bp ? XDR_TRUE : XDR_FALSE;
301 return (XDR_PUTLONG(xdrs, &lb));
302
303 case XDR_DECODE:
304 if (!XDR_GETLONG(xdrs, &lb)) {
305 return (FALSE);
306 }
307 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
308 return (TRUE);
309
310 case XDR_FREE:
311 return (TRUE);
312 }
313 return (FALSE);
314 }
315
316 /*
317 * XDR enumerations
318 */
319 bool_t
xdr_enum(xdrs,ep)320 xdr_enum(xdrs, ep)
321 XDR *xdrs;
322 enum_t *ep;
323 {
324 #ifndef lint
325 enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
326
327 /*
328 * enums are treated as ints
329 */
330 if (sizeof (enum sizecheck) == sizeof (int32_t)) {
331 return (xdr_long(xdrs, (int32_t *)ep));
332 } else if (sizeof (enum sizecheck) == sizeof (short)) {
333 return (xdr_short(xdrs, (short *)ep));
334 } else {
335 return (FALSE);
336 }
337 #else
338 (void) (xdr_short(xdrs, (short *)ep));
339 return (xdr_long(xdrs, (int32_t *)ep));
340 #endif
341 }
342 #endif
343
344 /*
345 * XDR opaque data
346 * Allows the specification of a fixed size sequence of opaque bytes.
347 * cp points to the opaque object and cnt gives the byte length.
348 */
349 bool_t
xdr_opaque(xdrs,cp,cnt)350 xdr_opaque(xdrs, cp, cnt)
351 register XDR *xdrs;
352 caddr_t cp;
353 register u_int cnt;
354 {
355 register u_int rndup;
356 static int crud[BYTES_PER_XDR_UNIT];
357
358 /*
359 * if no data we are done
360 */
361 if (cnt == 0)
362 return (TRUE);
363
364 /*
365 * round byte count to full xdr units
366 */
367 rndup = cnt % BYTES_PER_XDR_UNIT;
368 if (rndup > 0)
369 rndup = BYTES_PER_XDR_UNIT - rndup;
370
371 if (xdrs->x_op == XDR_DECODE) {
372 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
373 return (FALSE);
374 }
375 if (rndup == 0)
376 return (TRUE);
377 return (XDR_GETBYTES(xdrs, crud, rndup));
378 }
379
380 if (xdrs->x_op == XDR_ENCODE) {
381 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
382 return (FALSE);
383 }
384 if (rndup == 0)
385 return (TRUE);
386 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
387 }
388
389 if (xdrs->x_op == XDR_FREE) {
390 return (TRUE);
391 }
392
393 return (FALSE);
394 }
395
396 /*
397 * XDR counted bytes
398 * *cpp is a pointer to the bytes, *sizep is the count.
399 * If *cpp is NULL maxsize bytes are allocated
400 */
401 bool_t
xdr_bytes(xdrs,cpp,sizep,maxsize)402 xdr_bytes(xdrs, cpp, sizep, maxsize)
403 register XDR *xdrs;
404 char **cpp;
405 register u_int *sizep;
406 u_int maxsize;
407 {
408 register char *sp = *cpp; /* sp is the actual string pointer */
409 register u_int nodesize;
410
411 /*
412 * first deal with the length since xdr bytes are counted
413 */
414 if (! xdr_u_int(xdrs, sizep)) {
415 return (FALSE);
416 }
417 nodesize = *sizep;
418 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
419 return (FALSE);
420 }
421
422 /*
423 * now deal with the actual bytes
424 */
425 switch (xdrs->x_op) {
426
427 case XDR_DECODE:
428 if (nodesize == 0) {
429 return (TRUE);
430 }
431 if (sp == NULL) {
432 *cpp = sp = (char *)mem_alloc(nodesize);
433 }
434 if (sp == NULL) {
435 (void) fprintf(stderr, "xdr_bytes: out of memory\n");
436 return (FALSE);
437 }
438 /* fall into ... */
439
440 case XDR_ENCODE:
441 return (xdr_opaque(xdrs, sp, nodesize));
442
443 case XDR_FREE:
444 if (sp != NULL) {
445 mem_free(sp, nodesize);
446 *cpp = NULL;
447 }
448 return (TRUE);
449 }
450 return (FALSE);
451 }
452
453 #ifdef UNUSED
454 /*
455 * Implemented here due to commonality of the object.
456 */
457 bool_t
xdr_netobj(xdrs,np)458 xdr_netobj(xdrs, np)
459 XDR *xdrs;
460 struct netobj *np;
461 {
462
463 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
464 }
465
466 /*
467 * XDR a descriminated union
468 * Support routine for discriminated unions.
469 * You create an array of xdrdiscrim structures, terminated with
470 * an entry with a null procedure pointer. The routine gets
471 * the discriminant value and then searches the array of xdrdiscrims
472 * looking for that value. It calls the procedure given in the xdrdiscrim
473 * to handle the discriminant. If there is no specific routine a default
474 * routine may be called.
475 * If there is no specific or default routine an error is returned.
476 */
477 bool_t
xdr_union(xdrs,dscmp,unp,choices,dfault)478 xdr_union(xdrs, dscmp, unp, choices, dfault)
479 register XDR *xdrs;
480 enum_t *dscmp; /* enum to decide which arm to work on */
481 char *unp; /* the union itself */
482 struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
483 xdrproc_t dfault; /* default xdr routine */
484 {
485 register enum_t dscm;
486
487 /*
488 * we deal with the discriminator; it's an enum
489 */
490 if (! xdr_enum(xdrs, dscmp)) {
491 return (FALSE);
492 }
493 dscm = *dscmp;
494
495 /*
496 * search choices for a value that matches the discriminator.
497 * if we find one, execute the xdr routine for that value.
498 */
499 for (; choices->proc != NULL_xdrproc_t; choices++) {
500 if (choices->value == dscm)
501 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
502 }
503
504 /*
505 * no match - execute the default xdr routine if there is one
506 */
507 return ((dfault == NULL_xdrproc_t) ? FALSE :
508 (*dfault)(xdrs, unp, LASTUNSIGNED));
509 }
510 #endif
511
512 /*
513 * Non-portable xdr primitives.
514 * Care should be taken when moving these routines to new architectures.
515 */
516
517
518 /*
519 * XDR null terminated ASCII strings
520 * xdr_string deals with "C strings" - arrays of bytes that are
521 * terminated by a NULL character. The parameter cpp references a
522 * pointer to storage; If the pointer is null, then the necessary
523 * storage is allocated. The last parameter is the max allowed length
524 * of the string as specified by a protocol.
525 */
526 bool_t
xdr_string(xdrs,cpp,maxsize)527 xdr_string(xdrs, cpp, maxsize)
528 register XDR *xdrs;
529 char **cpp;
530 u_int maxsize;
531 {
532 register char *sp = *cpp; /* sp is the actual string pointer */
533 u_int size;
534 u_int nodesize;
535
536 /*
537 * first deal with the length since xdr strings are counted-strings
538 */
539 switch (xdrs->x_op) {
540 case XDR_FREE:
541 if (sp == NULL) {
542 return(TRUE); /* already free */
543 }
544 /* fall through... */
545 case XDR_ENCODE:
546 size = strlen(sp);
547 break;
548 case XDR_DECODE:
549 /* size not used: just keep compilers happy */
550 break;
551 }
552 if (! xdr_u_int(xdrs, &size)) {
553 return (FALSE);
554 }
555 if (size > maxsize) {
556 return (FALSE);
557 }
558 nodesize = size + 1;
559
560 /*
561 * now deal with the actual bytes
562 */
563 switch (xdrs->x_op) {
564
565 case XDR_DECODE:
566 if (nodesize == 0) {
567 return (TRUE);
568 }
569 if (sp == NULL)
570 *cpp = sp = (char *)mem_alloc(nodesize);
571 if (sp == NULL) {
572 (void) fprintf(stderr, "xdr_string: out of memory\n");
573 return (FALSE);
574 }
575 sp[size] = 0;
576 /* fall into ... */
577
578 case XDR_ENCODE:
579 return (xdr_opaque(xdrs, sp, size));
580
581 case XDR_FREE:
582 mem_free(sp, nodesize);
583 *cpp = NULL;
584 return (TRUE);
585 }
586 return (FALSE);
587 }
588
589 #ifdef UNUSED
590 /*
591 * Wrapper for xdr_string that can be called directly from
592 * routines like clnt_call
593 */
594 bool_t
xdr_wrapstring(xdrs,cpp)595 xdr_wrapstring(xdrs, cpp)
596 XDR *xdrs;
597 char **cpp;
598 {
599 if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
600 return (TRUE);
601 }
602 return (FALSE);
603 }
604 #endif
605