xref: /freebsd/sys/rpc/rpcb_prot.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
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 __FBSDID("$FreeBSD$");
43 
44 /*
45  * rpcb_prot.c
46  * XDR routines for the rpcbinder version 3.
47  *
48  * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 
56 #include <rpc/rpc.h>
57 #include <rpc/rpc_com.h>
58 #include <rpc/rpcb_prot.h>
59 
60 bool_t
61 xdr_portmap(XDR *xdrs, struct portmap *regs)
62 {
63 
64 	if (xdr_u_long(xdrs, &regs->pm_prog) &&
65 		xdr_u_long(xdrs, &regs->pm_vers) &&
66 		xdr_u_long(xdrs, &regs->pm_prot))
67 		return (xdr_u_long(xdrs, &regs->pm_port));
68 	return (FALSE);
69 }
70 
71 bool_t
72 xdr_rpcb(XDR *xdrs, RPCB *objp)
73 {
74 	if (!xdr_uint32_t(xdrs, &objp->r_prog)) {
75 		return (FALSE);
76 	}
77 	if (!xdr_uint32_t(xdrs, &objp->r_vers)) {
78 		return (FALSE);
79 	}
80 	if (!xdr_string(xdrs, &objp->r_netid, RPC_MAXDATASIZE)) {
81 		return (FALSE);
82 	}
83 	if (!xdr_string(xdrs, &objp->r_addr, RPC_MAXDATASIZE)) {
84 		return (FALSE);
85 	}
86 	if (!xdr_string(xdrs, &objp->r_owner, RPC_MAXDATASIZE)) {
87 		return (FALSE);
88 	}
89 	return (TRUE);
90 }
91 
92 /*
93  * rpcblist_ptr implements a linked list.  The RPCL definition from
94  * rpcb_prot.x is:
95  *
96  * struct rpcblist {
97  * 	rpcb		rpcb_map;
98  *	struct rpcblist *rpcb_next;
99  * };
100  * typedef rpcblist *rpcblist_ptr;
101  *
102  * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
103  * there's any data behind the pointer, followed by the data (if any exists).
104  * The boolean can be interpreted as ``more data follows me''; if FALSE then
105  * nothing follows the boolean; if TRUE then the boolean is followed by an
106  * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
107  * rpcblist *").
108  *
109  * This could be implemented via the xdr_pointer type, though this would
110  * result in one recursive call per element in the list.  Rather than do that
111  * we can ``unwind'' the recursion into a while loop and use xdr_reference to
112  * serialize the rpcb elements.
113  */
114 
115 bool_t
116 xdr_rpcblist_ptr(XDR *xdrs, rpcblist_ptr *rp)
117 {
118 	/*
119 	 * more_elements is pre-computed in case the direction is
120 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
121 	 * xdr_bool when the direction is XDR_DECODE.
122 	 */
123 	bool_t more_elements;
124 	int freeing = (xdrs->x_op == XDR_FREE);
125 	rpcblist_ptr next;
126 	rpcblist_ptr next_copy;
127 
128 	next = NULL;
129 	for (;;) {
130 		more_elements = (bool_t)(*rp != NULL);
131 		if (! xdr_bool(xdrs, &more_elements)) {
132 			return (FALSE);
133 		}
134 		if (! more_elements) {
135 			return (TRUE);  /* we are done */
136 		}
137 		/*
138 		 * the unfortunate side effect of non-recursion is that in
139 		 * the case of freeing we must remember the next object
140 		 * before we free the current object ...
141 		 */
142 		if (freeing && *rp)
143 			next = (*rp)->rpcb_next;
144 		if (! xdr_reference(xdrs, (caddr_t *)rp,
145 		    (u_int)sizeof (RPCBLIST), (xdrproc_t)xdr_rpcb)) {
146 			return (FALSE);
147 		}
148 		if (freeing) {
149 			next_copy = next;
150 			rp = &next_copy;
151 			/*
152 			 * Note that in the subsequent iteration, next_copy
153 			 * gets nulled out by the xdr_reference
154 			 * but next itself survives.
155 			 */
156 		} else if (*rp) {
157 			rp = &((*rp)->rpcb_next);
158 		}
159 	}
160 	/*NOTREACHED*/
161 }
162 
163 #if 0
164 /*
165  * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
166  * functionality to xdr_rpcblist_ptr().
167  */
168 bool_t
169 xdr_rpcblist(XDR *xdrs, RPCBLIST **rp)
170 {
171 	bool_t	dummy;
172 
173 	dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
174 	return (dummy);
175 }
176 #endif
177 
178 bool_t
179 xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp)
180 {
181 	if (!xdr_string(xdrs, &objp->r_maddr, RPC_MAXDATASIZE)) {
182 		return (FALSE);
183 	}
184 	if (!xdr_string(xdrs, &objp->r_nc_netid, RPC_MAXDATASIZE)) {
185 		return (FALSE);
186 	}
187 	if (!xdr_uint32_t(xdrs, &objp->r_nc_semantics)) {
188 		return (FALSE);
189 	}
190 	if (!xdr_string(xdrs, &objp->r_nc_protofmly, RPC_MAXDATASIZE)) {
191 		return (FALSE);
192 	}
193 	if (!xdr_string(xdrs, &objp->r_nc_proto, RPC_MAXDATASIZE)) {
194 		return (FALSE);
195 	}
196 	return (TRUE);
197 }
198 
199 bool_t
200 xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)
201 {
202 	/*
203 	 * more_elements is pre-computed in case the direction is
204 	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
205 	 * xdr_bool when the direction is XDR_DECODE.
206 	 */
207 	bool_t more_elements;
208 	int freeing = (xdrs->x_op == XDR_FREE);
209 	rpcb_entry_list_ptr next;
210 	rpcb_entry_list_ptr next_copy;
211 
212 	next = NULL;
213 	for (;;) {
214 		more_elements = (bool_t)(*rp != NULL);
215 		if (! xdr_bool(xdrs, &more_elements)) {
216 			return (FALSE);
217 		}
218 		if (! more_elements) {
219 			return (TRUE);  /* we are done */
220 		}
221 		/*
222 		 * the unfortunate side effect of non-recursion is that in
223 		 * the case of freeing we must remember the next object
224 		 * before we free the current object ...
225 		 */
226 		if (freeing)
227 			next = (*rp)->rpcb_entry_next;
228 		if (! xdr_reference(xdrs, (caddr_t *)rp,
229 		    (u_int)sizeof (rpcb_entry_list),
230 				    (xdrproc_t)xdr_rpcb_entry)) {
231 			return (FALSE);
232 		}
233 		if (freeing && *rp) {
234 			next_copy = next;
235 			rp = &next_copy;
236 			/*
237 			 * Note that in the subsequent iteration, next_copy
238 			 * gets nulled out by the xdr_reference
239 			 * but next itself survives.
240 			 */
241 		} else if (*rp) {
242 			rp = &((*rp)->rpcb_entry_next);
243 		}
244 	}
245 	/*NOTREACHED*/
246 }
247