1 /*	$NetBSD: rpcb_prot.c,v 1.11 2013/03/11 20:19:29 tron Exp $	*/
2 
3 /*
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
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.
19  *
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.
32  */
33 /*
34  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
35  */
36 
37 /* #ident	"@(#)rpcb_prot.c	1.13	94/04/24 SMI" */
38 
39 #include <sys/cdefs.h>
40 #if defined(LIBC_SCCS) && !defined(lint)
41 #if 0
42 static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
43 #else
44 __RCSID("$NetBSD: rpcb_prot.c,v 1.11 2013/03/11 20:19:29 tron Exp $");
45 #endif
46 #endif
47 
48 /*
49  * rpcb_prot.c
50  * XDR routines for the rpcbinder version 3.
51  *
52  * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
53  */
54 
55 #include "namespace.h"
56 
57 #include <rpc/rpc.h>
58 #include <rpc/types.h>
59 #include <rpc/xdr.h>
60 #include <rpc/rpcb_prot.h>
61 
62 #include <assert.h>
63 
64 #ifdef __weak_alias
__weak_alias(xdr_rpcb,_xdr_rpcb)65 __weak_alias(xdr_rpcb,_xdr_rpcb)
66 __weak_alias(xdr_rpcblist_ptr,_xdr_rpcblist_ptr)
67 __weak_alias(xdr_rpcblist,_xdr_rpcblist)
68 __weak_alias(xdr_rpcb_entry,_xdr_rpcb_entry)
69 __weak_alias(xdr_rpcb_entry_list_ptr,_xdr_rpcb_entry_list_ptr)
70 __weak_alias(xdr_rpcb_rmtcallargs,_xdr_rpcb_rmtcallargs)
71 __weak_alias(xdr_rpcb_rmtcallres,_xdr_rpcb_rmtcallres)
72 __weak_alias(xdr_netbuf,_xdr_netbuf)
73 #endif
74 
75 
76 bool_t
77 xdr_rpcb(XDR *xdrs, RPCB *objp)
78 {
79 
80 	_DIAGASSERT(objp != NULL);
81 
82 	if (!xdr_u_int32_t(xdrs, &objp->r_prog)) {
83 		return (FALSE);
84 	}
85 	if (!xdr_u_int32_t(xdrs, &objp->r_vers)) {
86 		return (FALSE);
87 	}
88 	if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) {
89 		return (FALSE);
90 	}
91 	if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) {
92 		return (FALSE);
93 	}
94 	if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) {
95 		return (FALSE);
96 	}
97 	return (TRUE);
98 }
99 
100 /*
101  * rpcblist_ptr implements a linked list.  The RPCL definition from
102  * rpcb_prot.x is:
103  *
104  * struct rpcblist {
105  * 	rpcb		rpcb_map;
106  *	struct rpcblist *rpcb_next;
107  * };
108  * typedef rpcblist *rpcblist_ptr;
109  *
110  * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
111  * there's any data behind the pointer, followed by the data (if any exists).
112  * The boolean can be interpreted as ``more data follows me''; if FALSE then
113  * nothing follows the boolean; if TRUE then the boolean is followed by an
114  * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
115  * rpcblist *").
116  *
117  * This could be implemented via the xdr_pointer type, though this would
118  * result in one recursive call per element in the list.  Rather than do that
119  * we can ``unwind'' the recursion into a while loop and use xdr_reference to
120  * serialize the rpcb elements.
121  */
122 
123 bool_t
xdr_rpcblist_ptr(XDR * xdrs,rpcblist_ptr * rp)124 xdr_rpcblist_ptr(XDR *xdrs, rpcblist_ptr *rp)
125 {
126 	/*
127 	 * more_elements is pre-computed in case the direction is
128 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
129 	 * xdr_bool when the direction is XDR_DECODE.
130 	 */
131 	bool_t more_elements;
132 	int freeing;
133 	rpcblist_ptr next;
134 	rpcblist_ptr next_copy;
135 
136 	_DIAGASSERT(xdrs != NULL);
137 	/* XXX: rp may be NULL ??? */
138 
139 	freeing = (xdrs->x_op == XDR_FREE);
140 	next = NULL;
141 
142 	for (;;) {
143 		more_elements = (bool_t)(*rp != NULL);
144 		if (! xdr_bool(xdrs, &more_elements)) {
145 			return (FALSE);
146 		}
147 		if (! more_elements) {
148 			return (TRUE);  /* we are done */
149 		}
150 		/*
151 		 * the unfortunate side effect of non-recursion is that in
152 		 * the case of freeing we must remember the next object
153 		 * before we free the current object ...
154 		 */
155 		if (freeing && *rp)
156 			next = (*rp)->rpcb_next;
157 		if (! xdr_reference(xdrs, (caddr_t *)rp,
158 		    (u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
159 			return (FALSE);
160 		}
161 		if (freeing) {
162 			next_copy = next;
163 			rp = &next_copy;
164 			/*
165 			 * Note that in the subsequent iteration, next_copy
166 			 * gets nulled out by the xdr_reference
167 			 * but next itself survives.
168 			 */
169 		} else if (*rp) {
170 			rp = &((*rp)->rpcb_next);
171 		}
172 	}
173 	/*NOTREACHED*/
174 }
175 
176 /*
177  * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
178  * functionality to xdr_rpcblist_ptr().
179  */
180 bool_t
xdr_rpcblist(XDR * xdrs,RPCBLIST ** rp)181 xdr_rpcblist(XDR *xdrs, RPCBLIST **rp)
182 {
183 	bool_t	dummy;
184 
185 	dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
186 	return (dummy);
187 }
188 
189 
190 bool_t
xdr_rpcb_entry(XDR * xdrs,rpcb_entry * objp)191 xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp)
192 {
193 
194 	_DIAGASSERT(objp != NULL);
195 
196 	if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) {
197 		return (FALSE);
198 	}
199 	if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) {
200 		return (FALSE);
201 	}
202 	if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
203 		return (FALSE);
204 	}
205 	if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) {
206 		return (FALSE);
207 	}
208 	if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) {
209 		return (FALSE);
210 	}
211 	return (TRUE);
212 }
213 
214 bool_t
xdr_rpcb_entry_list_ptr(XDR * xdrs,rpcb_entry_list_ptr * rp)215 xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)
216 {
217 	/*
218 	 * more_elements is pre-computed in case the direction is
219 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
220 	 * xdr_bool when the direction is XDR_DECODE.
221 	 */
222 	bool_t more_elements;
223 	int freeing;
224 	rpcb_entry_list_ptr next;
225 	rpcb_entry_list_ptr next_copy;
226 
227 	_DIAGASSERT(xdrs != NULL);
228 	/* XXX: rp is allowed to be NULL ??? */
229 
230 	freeing = (xdrs->x_op == XDR_FREE);
231 	next = NULL;
232 
233 	for (;;) {
234 		more_elements = (bool_t)(*rp != NULL);
235 		if (! xdr_bool(xdrs, &more_elements)) {
236 			return (FALSE);
237 		}
238 		if (! more_elements) {
239 			return (TRUE);  /* we are done */
240 		}
241 		/*
242 		 * the unfortunate side effect of non-recursion is that in
243 		 * the case of freeing we must remember the next object
244 		 * before we free the current object ...
245 		 */
246 		if (freeing && *rp)
247 			next = (*rp)->rpcb_entry_next;
248 		if (! xdr_reference(xdrs, (caddr_t *)rp,
249 		    (u_int)sizeof (rpcb_entry_list),
250 				    (xdrproc_t)xdr_rpcb_entry)) {
251 			return (FALSE);
252 		}
253 		if (freeing) {
254 			next_copy = next;
255 			rp = &next_copy;
256 			/*
257 			 * Note that in the subsequent iteration, next_copy
258 			 * gets nulled out by the xdr_reference
259 			 * but next itself survives.
260 			 */
261 		} else if (*rp) {
262 			rp = &((*rp)->rpcb_entry_next);
263 		}
264 	}
265 	/*NOTREACHED*/
266 }
267 
268 /*
269  * XDR remote call arguments
270  * written for XDR_ENCODE direction only
271  */
272 bool_t
xdr_rpcb_rmtcallargs(XDR * xdrs,struct rpcb_rmtcallargs * p)273 xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *p)
274 {
275 	struct r_rpcb_rmtcallargs *objp =
276 	    (struct r_rpcb_rmtcallargs *)(void *)p;
277 	u_int lenposition, argposition, position;
278 	int32_t *buf;
279 
280 	_DIAGASSERT(p != NULL);
281 
282 	buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
283 	if (buf == NULL) {
284 		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
285 			return (FALSE);
286 		}
287 		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
288 			return (FALSE);
289 		}
290 		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
291 			return (FALSE);
292 		}
293 	} else {
294 		IXDR_PUT_U_INT32(buf, objp->prog);
295 		IXDR_PUT_U_INT32(buf, objp->vers);
296 		IXDR_PUT_U_INT32(buf, objp->proc);
297 	}
298 
299 	/*
300 	 * All the jugglery for just getting the size of the arguments
301 	 */
302 	lenposition = XDR_GETPOS(xdrs);
303 	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
304 		return (FALSE);
305 	}
306 	argposition = XDR_GETPOS(xdrs);
307 	if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
308 		return (FALSE);
309 	}
310 	position = XDR_GETPOS(xdrs);
311 	objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
312 	XDR_SETPOS(xdrs, lenposition);
313 	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
314 		return (FALSE);
315 	}
316 	XDR_SETPOS(xdrs, position);
317 	return (TRUE);
318 }
319 
320 /*
321  * XDR remote call results
322  * written for XDR_DECODE direction only
323  */
324 bool_t
xdr_rpcb_rmtcallres(XDR * xdrs,struct rpcb_rmtcallres * p)325 xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *p)
326 {
327 	bool_t dummy;
328 	struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
329 
330 	_DIAGASSERT(p != NULL);
331 
332 	if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) {
333 		return (FALSE);
334 	}
335 	if (!xdr_u_int(xdrs, &objp->results.results_len)) {
336 		return (FALSE);
337 	}
338 	dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
339 	return (dummy);
340 }
341 
342 bool_t
xdr_netbuf(XDR * xdrs,struct netbuf * objp)343 xdr_netbuf(XDR *xdrs, struct netbuf *objp)
344 {
345 	bool_t dummy;
346 
347 	_DIAGASSERT(objp != NULL);
348 
349 	if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
350 		return (FALSE);
351 	}
352 	dummy = xdr_bytes(xdrs, (char **)(void *)&(objp->buf),
353 			(u_int *)&(objp->len), objp->maxlen);
354 	return (dummy);
355 }
356