xref: /freebsd/crypto/krb5/src/lib/rpc/xdr_sizeof.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /*
2  * Copyright (c) 2010, Oracle America, Inc.
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *
17  *     * Neither the name of the "Oracle America, Inc." nor the names of
18  *       its contributors may be used to endorse or promote products
19  *       derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * xdr_sizeof.c
35  *
36  * General purpose routine to see how much space something will use
37  * when serialized using XDR.
38  */
39 
40 #include <gssrpc/types.h>
41 #include <gssrpc/xdr.h>
42 #include <sys/types.h>
43 
44 /* ARGSUSED */
45 static bool_t
x_putlong(XDR * xdrs,long * longp)46 x_putlong(XDR *xdrs, long *longp)
47 {
48 	xdrs->x_handy += BYTES_PER_XDR_UNIT;
49 	return (TRUE);
50 }
51 
52 /* ARGSUSED */
53 static bool_t
x_putbytes(XDR * xdrs,char * bp,u_int len)54 x_putbytes(XDR *xdrs, char *bp, u_int len)
55 {
56 	xdrs->x_handy += len;
57 
58 	return (TRUE);
59 }
60 
61 static u_int
x_getpostn(XDR * xdrs)62 x_getpostn(XDR *xdrs)
63 {
64 	return (xdrs->x_handy);
65 }
66 
67 /* ARGSUSED */
68 static bool_t
x_setpostn(XDR * xdrs,u_int pos)69 x_setpostn(XDR *xdrs, u_int pos)
70 {
71 	/* This is not allowed */
72 	return (FALSE);
73 }
74 
75 static rpc_inline_t *
x_inline(XDR * xdrs,int len)76 x_inline(XDR *xdrs, int len)
77 {
78 	if (len == 0) {
79 		return (NULL);
80 	}
81 	if (xdrs->x_op != XDR_ENCODE) {
82 		return (NULL);
83 	}
84 	if (len < (int) ((caddr_t) xdrs->x_private - xdrs->x_base)) {
85 		/* x_private was already allocated */
86 		xdrs->x_handy += len;
87 		return ((rpc_inline_t *) xdrs->x_private);
88 	} else {
89 		/* Free the earlier space and allocate new area */
90 		if (xdrs->x_base)
91 			free(xdrs->x_base);
92 		if ((xdrs->x_base = (caddr_t) malloc(len)) == NULL) {
93 			xdrs->x_private = NULL;
94 			return (NULL);
95 		}
96 		xdrs->x_private = xdrs->x_base + len;
97 		xdrs->x_handy += len;
98 		return ((rpc_inline_t *) (void *) xdrs->x_base);
99 	}
100 }
101 
102 static int
harmless(void)103 harmless(void)
104 {
105 	/* Always return FALSE/NULL, as the case may be */
106 	return (0);
107 }
108 
109 static void
x_destroy(XDR * xdrs)110 x_destroy(XDR *xdrs)
111 {
112 	xdrs->x_handy = 0;
113 	xdrs->x_private = NULL;
114 	if (xdrs->x_base) {
115 		free(xdrs->x_base);
116 		xdrs->x_base = NULL;
117 	}
118 	return;
119 }
120 
121 unsigned long
xdr_sizeof(xdrproc_t func,void * data)122 xdr_sizeof(xdrproc_t func, void *data)
123 {
124 	XDR x;
125 	struct xdr_ops ops;
126 	bool_t stat;
127 	/* to stop ANSI-C compiler from complaining */
128 	typedef  bool_t (* dummyfunc1)(XDR *, long *);
129 	typedef  bool_t (* dummyfunc2)(XDR *, caddr_t, u_int);
130 
131 	ops.x_putlong = x_putlong;
132 	ops.x_putbytes = x_putbytes;
133 	ops.x_inline = x_inline;
134 	ops.x_getpostn = x_getpostn;
135 	ops.x_setpostn = x_setpostn;
136 	ops.x_destroy = x_destroy;
137 
138 	/* the other harmless ones */
139 	ops.x_getlong =  (dummyfunc1) harmless;
140 	ops.x_getbytes = (dummyfunc2) harmless;
141 
142 	x.x_op = XDR_ENCODE;
143 	x.x_ops = &ops;
144 	x.x_handy = 0;
145 	x.x_private = (caddr_t) NULL;
146 	x.x_base = (caddr_t) 0;
147 
148 	stat = func(&x, data);
149 	if (x.x_base)
150 		free(x.x_base);
151 	return (stat == TRUE ? (unsigned) x.x_handy: 0);
152 }
153