xref: /freebsd/lib/libc/rpc/rpcb_prot.c (revision 6ef644f5889afbd0f681b08ed1a2f369524af83e)
1 /*	$NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (c) 2009, Sun Microsystems, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  * - Redistributions of source code must retain the above copyright notice,
12  *   this list of conditions and the following disclaimer.
13  * - Redistributions in binary form must reproduce the above copyright notice,
14  *   this list of conditions and the following disclaimer in the documentation
15  *   and/or other materials provided with the distribution.
16  * - Neither the name of Sun Microsystems, 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 "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
34  */
35 
36 /* #ident	"@(#)rpcb_prot.c	1.13	94/04/24 SMI" */
37 
38 #if defined(LIBC_SCCS) && !defined(lint)
39 static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
40 #endif
41 #include <sys/cdefs.h>
42 /*
43  * rpcb_prot.c
44  * XDR routines for the rpcbinder version 3.
45  *
46  * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
47  */
48 
49 #include "namespace.h"
50 #include <rpc/rpc.h>
51 #include <rpc/types.h>
52 #include <rpc/xdr.h>
53 #include <rpc/rpcb_prot.h>
54 #include <rpc/rpc_com.h>
55 #include "un-namespace.h"
56 
57 bool_t
58 xdr_rpcb(XDR *xdrs, RPCB *objp)
59 {
60 	if (!xdr_rpcprog(xdrs, &objp->r_prog)) {
61 		return (FALSE);
62 	}
63 	if (!xdr_rpcvers(xdrs, &objp->r_vers)) {
64 		return (FALSE);
65 	}
66 	if (!xdr_string(xdrs, &objp->r_netid, RPC_MAXDATASIZE)) {
67 		return (FALSE);
68 	}
69 	if (!xdr_string(xdrs, &objp->r_addr, RPC_MAXDATASIZE)) {
70 		return (FALSE);
71 	}
72 	if (!xdr_string(xdrs, &objp->r_owner, RPC_MAXDATASIZE)) {
73 		return (FALSE);
74 	}
75 	return (TRUE);
76 }
77 
78 /*
79  * rpcblist_ptr implements a linked list.  The RPCL definition from
80  * rpcb_prot.x is:
81  *
82  * struct rpcblist {
83  * 	rpcb		rpcb_map;
84  *	struct rpcblist *rpcb_next;
85  * };
86  * typedef rpcblist *rpcblist_ptr;
87  *
88  * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
89  * there's any data behind the pointer, followed by the data (if any exists).
90  * The boolean can be interpreted as ``more data follows me''; if FALSE then
91  * nothing follows the boolean; if TRUE then the boolean is followed by an
92  * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
93  * rpcblist *").
94  *
95  * This could be implemented via the xdr_pointer type, though this would
96  * result in one recursive call per element in the list.  Rather than do that
97  * we can ``unwind'' the recursion into a while loop and use xdr_reference to
98  * serialize the rpcb elements.
99  */
100 
101 bool_t
102 xdr_rpcblist_ptr(XDR *xdrs, rpcblist_ptr *rp)
103 {
104 	/*
105 	 * more_elements is pre-computed in case the direction is
106 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
107 	 * xdr_bool when the direction is XDR_DECODE.
108 	 */
109 	bool_t more_elements;
110 	int freeing = (xdrs->x_op == XDR_FREE);
111 	rpcblist_ptr next;
112 	rpcblist_ptr next_copy;
113 
114 	next = NULL;
115 	for (;;) {
116 		more_elements = (bool_t)(*rp != NULL);
117 		if (! xdr_bool(xdrs, &more_elements)) {
118 			return (FALSE);
119 		}
120 		if (! more_elements) {
121 			return (TRUE);  /* we are done */
122 		}
123 		/*
124 		 * the unfortunate side effect of non-recursion is that in
125 		 * the case of freeing we must remember the next object
126 		 * before we free the current object ...
127 		 */
128 		if (freeing && *rp)
129 			next = (*rp)->rpcb_next;
130 		if (! xdr_reference(xdrs, (caddr_t *)rp,
131 		    (u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
132 			return (FALSE);
133 		}
134 		if (freeing) {
135 			next_copy = next;
136 			rp = &next_copy;
137 			/*
138 			 * Note that in the subsequent iteration, next_copy
139 			 * gets nulled out by the xdr_reference
140 			 * but next itself survives.
141 			 */
142 		} else if (*rp) {
143 			rp = &((*rp)->rpcb_next);
144 		}
145 	}
146 	/*NOTREACHED*/
147 }
148 
149 /*
150  * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
151  * functionality to xdr_rpcblist_ptr().
152  */
153 bool_t
154 xdr_rpcblist(XDR *xdrs, RPCBLIST **rp)
155 {
156 	bool_t	dummy;
157 
158 	dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
159 	return (dummy);
160 }
161 
162 
163 bool_t
164 xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp)
165 {
166 	if (!xdr_string(xdrs, &objp->r_maddr, RPC_MAXDATASIZE)) {
167 		return (FALSE);
168 	}
169 	if (!xdr_string(xdrs, &objp->r_nc_netid, RPC_MAXDATASIZE)) {
170 		return (FALSE);
171 	}
172 	if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
173 		return (FALSE);
174 	}
175 	if (!xdr_string(xdrs, &objp->r_nc_protofmly, RPC_MAXDATASIZE)) {
176 		return (FALSE);
177 	}
178 	if (!xdr_string(xdrs, &objp->r_nc_proto, RPC_MAXDATASIZE)) {
179 		return (FALSE);
180 	}
181 	return (TRUE);
182 }
183 
184 bool_t
185 xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)
186 {
187 	/*
188 	 * more_elements is pre-computed in case the direction is
189 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
190 	 * xdr_bool when the direction is XDR_DECODE.
191 	 */
192 	bool_t more_elements;
193 	int freeing = (xdrs->x_op == XDR_FREE);
194 	rpcb_entry_list_ptr next;
195 	rpcb_entry_list_ptr next_copy;
196 
197 	next = NULL;
198 	for (;;) {
199 		more_elements = (bool_t)(*rp != NULL);
200 		if (! xdr_bool(xdrs, &more_elements)) {
201 			return (FALSE);
202 		}
203 		if (! more_elements) {
204 			return (TRUE);  /* we are done */
205 		}
206 		/*
207 		 * the unfortunate side effect of non-recursion is that in
208 		 * the case of freeing we must remember the next object
209 		 * before we free the current object ...
210 		 */
211 		if (freeing && *rp)
212 			next = (*rp)->rpcb_entry_next;
213 		if (! xdr_reference(xdrs, (caddr_t *)rp,
214 		    (u_int)sizeof (rpcb_entry_list),
215 				    (xdrproc_t)xdr_rpcb_entry)) {
216 			return (FALSE);
217 		}
218 		if (freeing) {
219 			next_copy = next;
220 			rp = &next_copy;
221 			/*
222 			 * Note that in the subsequent iteration, next_copy
223 			 * gets nulled out by the xdr_reference
224 			 * but next itself survives.
225 			 */
226 		} else if (*rp) {
227 			rp = &((*rp)->rpcb_entry_next);
228 		}
229 	}
230 	/*NOTREACHED*/
231 }
232 
233 /*
234  * XDR remote call arguments
235  * written for XDR_ENCODE direction only
236  */
237 bool_t
238 xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *p)
239 {
240 	struct r_rpcb_rmtcallargs *objp =
241 	    (struct r_rpcb_rmtcallargs *)(void *)p;
242 	u_int lenposition, argposition, position;
243 	int32_t *buf;
244 
245 	buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
246 	if (buf == NULL) {
247 		if (!xdr_rpcprog(xdrs, &objp->prog)) {
248 			return (FALSE);
249 		}
250 		if (!xdr_rpcvers(xdrs, &objp->vers)) {
251 			return (FALSE);
252 		}
253 		if (!xdr_rpcproc(xdrs, &objp->proc)) {
254 			return (FALSE);
255 		}
256 	} else {
257 		IXDR_PUT_U_INT32(buf, objp->prog);
258 		IXDR_PUT_U_INT32(buf, objp->vers);
259 		IXDR_PUT_U_INT32(buf, objp->proc);
260 	}
261 
262 	/*
263 	 * All the jugglery for just getting the size of the arguments
264 	 */
265 	lenposition = XDR_GETPOS(xdrs);
266 	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
267 		return (FALSE);
268 	}
269 	argposition = XDR_GETPOS(xdrs);
270 	if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
271 		return (FALSE);
272 	}
273 	position = XDR_GETPOS(xdrs);
274 	objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
275 	XDR_SETPOS(xdrs, lenposition);
276 	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
277 		return (FALSE);
278 	}
279 	XDR_SETPOS(xdrs, position);
280 	return (TRUE);
281 }
282 
283 /*
284  * XDR remote call results
285  * written for XDR_DECODE direction only
286  */
287 bool_t
288 xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *p)
289 {
290 	bool_t dummy;
291 	struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
292 
293 	if (!xdr_string(xdrs, &objp->addr, RPC_MAXDATASIZE)) {
294 		return (FALSE);
295 	}
296 	if (!xdr_u_int(xdrs, &objp->results.results_len)) {
297 		return (FALSE);
298 	}
299 	dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
300 	return (dummy);
301 }
302 
303 bool_t
304 xdr_netbuf(XDR *xdrs, struct netbuf *objp)
305 {
306 	bool_t dummy;
307 	void **pp;
308 
309 	if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
310 		return (FALSE);
311 	}
312 	pp = &objp->buf;
313 	dummy = xdr_bytes(xdrs, (char **) pp,
314 			(u_int *)&(objp->len), objp->maxlen);
315 	return (dummy);
316 }
317