]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / sys / cddl / contrib / opensolaris / uts / common / rpc / opensolaris_xdr.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
27 /*        All Rights Reserved   */
28
29 /*
30  * Portions of this source code were derived from Berkeley 4.3 BSD
31  * under license from the Regents of the University of California.
32  */
33
34 /*
35  * xdr.c, generic XDR routines implementation.
36  * These are the "generic" xdr routines used to serialize and de-serialize
37  * most common data items.  See xdr.h for more info on the interface to
38  * xdr.
39  */
40
41 #include <sys/param.h>
42 #include <sys/cmn_err.h>
43 #include <sys/types.h>
44 #include <sys/systm.h>
45
46 #include <rpc/types.h>
47 #include <rpc/xdr.h>
48
49 #pragma weak xdr_int32_t = xdr_int
50 #pragma weak xdr_uint32_t = xdr_u_int
51 #pragma weak xdr_int64_t = xdr_longlong_t
52 #pragma weak xdr_uint64_t = xdr_u_longlong_t
53
54 #if defined(sun)
55 #if !defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
56 #error "Exactly one of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined"
57 #elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
58 #error "Only one of _BIG_ENDIAN or _LITTLE_ENDIAN may be defined"
59 #endif
60 #endif
61
62 /*
63  * constants specific to the xdr "protocol"
64  */
65 #define XDR_FALSE       ((int32_t)0)
66 #define XDR_TRUE        ((int32_t)1)
67 #define LASTUNSIGNED    ((uint_t)0-1)
68
69 /*
70  * for unit alignment
71  */
72 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
73
74 /*
75  * Free a data structure using XDR
76  * Not a filter, but a convenient utility nonetheless
77  */
78 void
79 xdr_free(xdrproc_t proc, char *objp)
80 {
81         XDR x;
82
83         x.x_op = XDR_FREE;
84         (*proc)(&x, objp);
85 }
86
87 /*
88  * XDR nothing
89  */
90 bool_t
91 xdr_void(void)
92 {
93         return (TRUE);
94 }
95
96 /*
97  * XDR integers
98  *
99  * PSARC 2003/523 Contract Private Interface
100  * xdr_int
101  * Changes must be reviewed by Solaris File Sharing
102  * Changes must be communicated to contract-2003-523@sun.com
103  */
104 bool_t
105 xdr_int(XDR *xdrs, int *ip)
106 {
107         if (xdrs->x_op == XDR_ENCODE)
108                 return (XDR_PUTINT32(xdrs, ip));
109
110         if (xdrs->x_op == XDR_DECODE)
111                 return (XDR_GETINT32(xdrs, ip));
112
113         if (xdrs->x_op == XDR_FREE)
114                 return (TRUE);
115
116         return (FALSE);
117 }
118
119 /*
120  * XDR unsigned integers
121  *
122  * PSARC 2003/523 Contract Private Interface
123  * xdr_u_int
124  * Changes must be reviewed by Solaris File Sharing
125  * Changes must be communicated to contract-2003-523@sun.com
126  */
127 bool_t
128 xdr_u_int(XDR *xdrs, uint_t *up)
129 {
130         if (xdrs->x_op == XDR_ENCODE)
131                 return (XDR_PUTINT32(xdrs, (int32_t *)up));
132
133         if (xdrs->x_op == XDR_DECODE)
134                 return (XDR_GETINT32(xdrs, (int32_t *)up));
135
136         if (xdrs->x_op == XDR_FREE)
137                 return (TRUE);
138
139         return (FALSE);
140 }
141
142
143 #if defined(_ILP32)
144 /*
145  * xdr_long and xdr_u_long for binary compatability on ILP32 kernels.
146  *
147  * No prototypes since new code should not be using these interfaces.
148  */
149 bool_t
150 xdr_long(XDR *xdrs, long *ip)
151 {
152         return (xdr_int(xdrs, (int *)ip));
153 }
154
155 bool_t
156 xdr_u_long(XDR *xdrs, unsigned long *up)
157 {
158         return (xdr_u_int(xdrs, (uint_t *)up));
159 }
160 #endif /* _ILP32 */
161
162
163 /*
164  * XDR long long integers
165  */
166 bool_t
167 xdr_longlong_t(XDR *xdrs, longlong_t *hp)
168 {
169         if (xdrs->x_op == XDR_ENCODE) {
170 #if BYTE_ORDER == _LITTLE_ENDIAN
171                 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
172                     BYTES_PER_XDR_UNIT)) == TRUE) {
173                         return (XDR_PUTINT32(xdrs, (int32_t *)hp));
174                 }
175 #else
176                 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
177                         return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
178                             BYTES_PER_XDR_UNIT)));
179                 }
180 #endif
181                 return (FALSE);
182
183         }
184         if (xdrs->x_op == XDR_DECODE) {
185 #if BYTE_ORDER == _LITTLE_ENDIAN
186                 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
187                     BYTES_PER_XDR_UNIT)) == TRUE) {
188                         return (XDR_GETINT32(xdrs, (int32_t *)hp));
189                 }
190 #else
191                 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
192                         return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
193                             BYTES_PER_XDR_UNIT)));
194                 }
195 #endif
196                 return (FALSE);
197         }
198         return (TRUE);
199 }
200
201 /*
202  * XDR unsigned long long integers
203  */
204 bool_t
205 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
206 {
207
208         if (xdrs->x_op == XDR_ENCODE) {
209 #if BYTE_ORDER == _LITTLE_ENDIAN
210                 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
211                     BYTES_PER_XDR_UNIT)) == TRUE) {
212                         return (XDR_PUTINT32(xdrs, (int32_t *)hp));
213                 }
214 #else
215                 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
216                         return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
217                             BYTES_PER_XDR_UNIT)));
218                 }
219 #endif
220                 return (FALSE);
221
222         }
223         if (xdrs->x_op == XDR_DECODE) {
224 #if BYTE_ORDER == _LITTLE_ENDIAN
225                 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
226                     BYTES_PER_XDR_UNIT)) == TRUE) {
227                         return (XDR_GETINT32(xdrs, (int32_t *)hp));
228                 }
229 #else
230                 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
231                         return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
232                             BYTES_PER_XDR_UNIT)));
233                 }
234 #endif
235                 return (FALSE);
236         }
237         return (TRUE);
238 }
239
240 /*
241  * XDR short integers
242  */
243 bool_t
244 xdr_short(XDR *xdrs, short *sp)
245 {
246         int32_t l;
247
248         switch (xdrs->x_op) {
249
250         case XDR_ENCODE:
251                 l = (int32_t)*sp;
252                 return (XDR_PUTINT32(xdrs, &l));
253
254         case XDR_DECODE:
255                 if (!XDR_GETINT32(xdrs, &l))
256                         return (FALSE);
257                 *sp = (short)l;
258                 return (TRUE);
259
260         case XDR_FREE:
261                 return (TRUE);
262         }
263         return (FALSE);
264 }
265
266 /*
267  * XDR unsigned short integers
268  */
269 bool_t
270 xdr_u_short(XDR *xdrs, ushort_t *usp)
271 {
272         uint32_t l;
273
274         switch (xdrs->x_op) {
275
276         case XDR_ENCODE:
277                 l = (uint32_t)*usp;
278                 return (XDR_PUTINT32(xdrs, (int32_t *)&l));
279
280         case XDR_DECODE:
281                 if (!XDR_GETINT32(xdrs, (int32_t *)&l)) {
282                         return (FALSE);
283                 }
284                 *usp = (ushort_t)l;
285                 return (TRUE);
286
287         case XDR_FREE:
288                 return (TRUE);
289         }
290         return (FALSE);
291 }
292
293
294 /*
295  * XDR a char
296  */
297 bool_t
298 xdr_char(XDR *xdrs, char *cp)
299 {
300         int i;
301
302         i = (*cp);
303         if (!xdr_int(xdrs, &i)) {
304                 return (FALSE);
305         }
306         *cp = (char)i;
307         return (TRUE);
308 }
309
310 /*
311  * XDR booleans
312  *
313  * PSARC 2003/523 Contract Private Interface
314  * xdr_bool
315  * Changes must be reviewed by Solaris File Sharing
316  * Changes must be communicated to contract-2003-523@sun.com
317  */
318 bool_t
319 xdr_bool(XDR *xdrs, bool_t *bp)
320 {
321         int32_t i32b;
322
323         switch (xdrs->x_op) {
324
325         case XDR_ENCODE:
326                 i32b = *bp ? XDR_TRUE : XDR_FALSE;
327                 return (XDR_PUTINT32(xdrs, &i32b));
328
329         case XDR_DECODE:
330                 if (!XDR_GETINT32(xdrs, &i32b)) {
331                         return (FALSE);
332                 }
333                 *bp = (i32b == XDR_FALSE) ? FALSE : TRUE;
334                 return (TRUE);
335
336         case XDR_FREE:
337                 return (TRUE);
338         }
339         return (FALSE);
340 }
341
342 /*
343  * XDR enumerations
344  *
345  * PSARC 2003/523 Contract Private Interface
346  * xdr_enum
347  * Changes must be reviewed by Solaris File Sharing
348  * Changes must be communicated to contract-2003-523@sun.com
349  */
350 #ifndef lint
351 enum sizecheck { SIZEVAL } sizecheckvar;        /* used to find the size of */
352                                                 /* an enum */
353 #endif
354 bool_t
355 xdr_enum(XDR *xdrs, enum_t *ep)
356 {
357 #ifndef lint
358         /*
359          * enums are treated as ints
360          */
361         if (sizeof (sizecheckvar) == sizeof (int32_t)) {
362                 return (xdr_int(xdrs, (int32_t *)ep));
363         } else if (sizeof (sizecheckvar) == sizeof (short)) {
364                 return (xdr_short(xdrs, (short *)ep));
365         } else {
366                 return (FALSE);
367         }
368 #else
369         (void) (xdr_short(xdrs, (short *)ep));
370         return (xdr_int(xdrs, (int32_t *)ep));
371 #endif
372 }
373
374 /*
375  * XDR opaque data
376  * Allows the specification of a fixed size sequence of opaque bytes.
377  * cp points to the opaque object and cnt gives the byte length.
378  *
379  * PSARC 2003/523 Contract Private Interface
380  * xdr_opaque
381  * Changes must be reviewed by Solaris File Sharing
382  * Changes must be communicated to contract-2003-523@sun.com
383  */
384 bool_t
385 xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
386 {
387         uint_t rndup;
388         static char crud[BYTES_PER_XDR_UNIT];
389
390         /*
391          * if no data we are done
392          */
393         if (cnt == 0)
394                 return (TRUE);
395
396         /*
397          * round byte count to full xdr units
398          */
399         rndup = cnt % BYTES_PER_XDR_UNIT;
400         if (rndup != 0)
401                 rndup = BYTES_PER_XDR_UNIT - rndup;
402
403         if (xdrs->x_op == XDR_DECODE) {
404                 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
405                         return (FALSE);
406                 }
407                 if (rndup == 0)
408                         return (TRUE);
409                 return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
410         }
411
412         if (xdrs->x_op == XDR_ENCODE) {
413                 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
414                         return (FALSE);
415                 }
416                 if (rndup == 0)
417                         return (TRUE);
418                 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
419         }
420
421         if (xdrs->x_op == XDR_FREE)
422                 return (TRUE);
423
424         return (FALSE);
425 }
426
427 /*
428  * XDR counted bytes
429  * *cpp is a pointer to the bytes, *sizep is the count.
430  * If *cpp is NULL maxsize bytes are allocated
431  *
432  * PSARC 2003/523 Contract Private Interface
433  * xdr_bytes
434  * Changes must be reviewed by Solaris File Sharing
435  * Changes must be communicated to contract-2003-523@sun.com
436  */
437 bool_t
438 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
439 {
440         char *sp = *cpp;  /* sp is the actual string pointer */
441         uint_t nodesize;
442
443         /*
444          * first deal with the length since xdr bytes are counted
445          */
446         if (!xdr_u_int(xdrs, sizep)) {
447                 return (FALSE);
448         }
449         nodesize = *sizep;
450         if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
451                 return (FALSE);
452         }
453
454         /*
455          * now deal with the actual bytes
456          */
457         switch (xdrs->x_op) {
458         case XDR_DECODE:
459                 if (nodesize == 0)
460                         return (TRUE);
461                 if (sp == NULL)
462                         *cpp = sp = (char *)mem_alloc(nodesize);
463                 /* FALLTHROUGH */
464
465         case XDR_ENCODE:
466                 return (xdr_opaque(xdrs, sp, nodesize));
467
468         case XDR_FREE:
469                 if (sp != NULL) {
470                         mem_free(sp, nodesize);
471                         *cpp = NULL;
472                 }
473                 return (TRUE);
474         }
475         return (FALSE);
476 }
477
478 /*
479  * Implemented here due to commonality of the object.
480  */
481 bool_t
482 xdr_netobj(XDR *xdrs, struct netobj *np)
483 {
484         return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
485 }
486
487 /*
488  * XDR a descriminated union
489  * Support routine for discriminated unions.
490  * You create an array of xdrdiscrim structures, terminated with
491  * an entry with a null procedure pointer.  The routine gets
492  * the discriminant value and then searches the array of xdrdiscrims
493  * looking for that value.  It calls the procedure given in the xdrdiscrim
494  * to handle the discriminant.  If there is no specific routine a default
495  * routine may be called.
496  * If there is no specific or default routine an error is returned.
497  */
498 bool_t
499 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
500         const struct xdr_discrim *choices, const xdrproc_t dfault)
501 {
502         enum_t dscm;
503
504         /*
505          * we deal with the discriminator;  it's an enum
506          */
507         if (!xdr_enum(xdrs, dscmp)) {
508                 return (FALSE);
509         }
510         dscm = *dscmp;
511
512         /*
513          * search choices for a value that matches the discriminator.
514          * if we find one, execute the xdr routine for that value.
515          */
516         for (; choices->proc != NULL_xdrproc_t; choices++) {
517                 if (choices->value == dscm)
518                         return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
519         }
520
521         /*
522          * no match - execute the default xdr routine if there is one
523          */
524         return ((dfault == NULL_xdrproc_t) ? FALSE :
525             (*dfault)(xdrs, unp, LASTUNSIGNED));
526 }
527
528
529 /*
530  * Non-portable xdr primitives.
531  * Care should be taken when moving these routines to new architectures.
532  */
533
534
535 /*
536  * XDR null terminated ASCII strings
537  * xdr_string deals with "C strings" - arrays of bytes that are
538  * terminated by a NULL character.  The parameter cpp references a
539  * pointer to storage; If the pointer is null, then the necessary
540  * storage is allocated.  The last parameter is the max allowed length
541  * of the string as specified by a protocol.
542  */
543 bool_t
544 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
545 {
546         char *sp = *cpp;  /* sp is the actual string pointer */
547         uint_t size;
548         uint_t nodesize;
549
550         /*
551          * first deal with the length since xdr strings are counted-strings
552          */
553         switch (xdrs->x_op) {
554         case XDR_FREE:
555                 if (sp == NULL)
556                         return (TRUE);  /* already free */
557                 /* FALLTHROUGH */
558         case XDR_ENCODE:
559                 size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
560                 break;
561         case XDR_DECODE:
562                 break;
563         }
564         if (!xdr_u_int(xdrs, &size)) {
565                 return (FALSE);
566         }
567         if (size > maxsize) {
568                 return (FALSE);
569         }
570         nodesize = size + 1;
571
572         /*
573          * now deal with the actual bytes
574          */
575         switch (xdrs->x_op) {
576         case XDR_DECODE:
577                 if (nodesize == 0)
578                         return (TRUE);
579                 if (sp == NULL)
580                         sp = (char *)mem_alloc(nodesize);
581                 sp[size] = 0;
582                 if (!xdr_opaque(xdrs, sp, size)) {
583                         /*
584                          * free up memory if allocated here
585                          */
586                         if (*cpp == NULL) {
587                                 mem_free(sp, nodesize);
588                         }
589                         return (FALSE);
590                 }
591                 if (strlen(sp) != size) {
592                         if (*cpp == NULL) {
593                                 mem_free(sp, nodesize);
594                         }
595                         return (FALSE);
596                 }
597                 *cpp = sp;
598                 return (TRUE);
599
600         case XDR_ENCODE:
601                 return (xdr_opaque(xdrs, sp, size));
602
603         case XDR_FREE:
604                 mem_free(sp, nodesize);
605                 *cpp = NULL;
606                 return (TRUE);
607         }
608         return (FALSE);
609 }
610
611 /*
612  * Wrapper for xdr_string that can be called directly from
613  * routines like clnt_call
614  */
615 bool_t
616 xdr_wrapstring(XDR *xdrs, char **cpp)
617 {
618         if (xdr_string(xdrs, cpp, LASTUNSIGNED))
619                 return (TRUE);
620         return (FALSE);
621 }