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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30 /*
31 * Portions of this source code were derived from Berkeley
32 * 4.3 BSD under license from the Regents of the University of
33 * California.
34 */
35
36 #pragma ident "%Z%%M% %I% %E% SMI"
37
38 /*
39 * XDR routines for the rpcbinder version 3.
40 */
41
42 #include "mt.h"
43 #include <rpc/rpc.h>
44 #include <rpc/types.h>
45 #include <rpc/xdr.h>
46 #include <rpc/rpcb_prot.h>
47
48
49 bool_t
xdr_rpcb(XDR * xdrs,RPCB * objp)50 xdr_rpcb(XDR *xdrs, RPCB *objp)
51 {
52 if (!xdr_u_int(xdrs, (uint_t *)&objp->r_prog))
53 return (FALSE);
54 if (!xdr_u_int(xdrs, (uint_t *)&objp->r_vers))
55 return (FALSE);
56 if (!xdr_string(xdrs, &objp->r_netid, ~0))
57 return (FALSE);
58 if (!xdr_string(xdrs, &objp->r_addr, ~0))
59 return (FALSE);
60 return (xdr_string(xdrs, &objp->r_owner, ~0));
61 }
62
63 /*
64 * rpcblist_ptr implements a linked list. The RPCL definition from
65 * rpcb_prot.x is:
66 *
67 * struct rpcblist {
68 * rpcb rpcb_map;
69 * struct rpcblist *rpcb_next;
70 * };
71 * typedef rpcblist *rpcblist_ptr;
72 *
73 * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
74 * there's any data behind the pointer, followed by the data (if any exists).
75 * The boolean can be interpreted as ``more data follows me''; if FALSE then
76 * nothing follows the boolean; if TRUE then the boolean is followed by an
77 * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
78 * rpcblist *").
79 *
80 * This could be implemented via the xdr_pointer type, though this would
81 * result in one recursive call per element in the list. Rather than do that
82 * we can ``unwind'' the recursion into a while loop and use xdr_reference to
83 * serialize the rpcb elements.
84 */
85
86 bool_t
xdr_rpcblist_ptr(XDR * xdrs,rpcblist_ptr * rp)87 xdr_rpcblist_ptr(XDR *xdrs, rpcblist_ptr *rp)
88 {
89 /*
90 * more_elements is pre-computed in case the direction is
91 * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
92 * xdr_bool when the direction is XDR_DECODE.
93 */
94 bool_t more_elements;
95 int freeing = (xdrs->x_op == XDR_FREE);
96 rpcblist_ptr next;
97 rpcblist_ptr next_copy;
98
99 for (;;) {
100 more_elements = (bool_t)(*rp != NULL);
101 if (!xdr_bool(xdrs, &more_elements))
102 return (FALSE);
103 if (!more_elements)
104 return (TRUE); /* we are done */
105 /*
106 * the unfortunate side effect of non-recursion is that in
107 * the case of freeing we must remember the next object
108 * before we free the current object ...
109 */
110 if (freeing)
111 next = (*rp)->rpcb_next;
112 if (!xdr_reference(xdrs, (caddr_t *)rp,
113 (uint_t)sizeof (rpcblist), (xdrproc_t)xdr_rpcb))
114 return (FALSE);
115 if (freeing) {
116 next_copy = next;
117 rp = &next_copy;
118 /*
119 * Note that in the subsequent iteration, next_copy
120 * gets nulled out by the xdr_reference
121 * but next itself survives.
122 */
123 } else {
124 rp = &((*rp)->rpcb_next);
125 }
126 }
127 /*NOTREACHED*/
128 }
129
130 /*
131 * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
132 * functionality to xdr_rpcblist_ptr().
133 */
134 bool_t
xdr_rpcblist(XDR * xdrs,RPCBLIST ** rp)135 xdr_rpcblist(XDR *xdrs, RPCBLIST **rp)
136 {
137 return (xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp));
138 }
139
140
141 bool_t
xdr_rpcb_entry(XDR * xdrs,rpcb_entry * objp)142 xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp)
143 {
144 if (!xdr_string(xdrs, &objp->r_maddr, ~0))
145 return (FALSE);
146 if (!xdr_string(xdrs, &objp->r_nc_netid, ~0))
147 return (FALSE);
148 if (!xdr_u_int(xdrs, &objp->r_nc_semantics))
149 return (FALSE);
150 if (!xdr_string(xdrs, &objp->r_nc_protofmly, ~0))
151 return (FALSE);
152 return (xdr_string(xdrs, &objp->r_nc_proto, ~0));
153 }
154
155 bool_t
xdr_rpcb_entry_list_ptr(XDR * xdrs,rpcb_entry_list_ptr * rp)156 xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)
157 {
158 /*
159 * more_elements is pre-computed in case the direction is
160 * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
161 * xdr_bool when the direction is XDR_DECODE.
162 */
163 bool_t more_elements;
164 int freeing = (xdrs->x_op == XDR_FREE);
165 rpcb_entry_list_ptr next;
166 rpcb_entry_list_ptr next_copy;
167
168 for (;;) {
169 more_elements = (bool_t)(*rp != NULL);
170 if (!xdr_bool(xdrs, &more_elements))
171 return (FALSE);
172 if (!more_elements)
173 return (TRUE); /* we are done */
174 /*
175 * the unfortunate side effect of non-recursion is that in
176 * the case of freeing we must remember the next object
177 * before we free the current object ...
178 */
179 if (freeing)
180 next = (*rp)->rpcb_entry_next;
181 if (!xdr_reference(xdrs, (caddr_t *)rp,
182 (uint_t)sizeof (rpcb_entry_list),
183 (xdrproc_t)xdr_rpcb_entry))
184 return (FALSE);
185 if (freeing) {
186 next_copy = next;
187 rp = &next_copy;
188 /*
189 * Note that in the subsequent iteration, next_copy
190 * gets nulled out by the xdr_reference
191 * but next itself survives.
192 */
193 } else {
194 rp = &((*rp)->rpcb_entry_next);
195 }
196 }
197 /*NOTREACHED*/
198 }
199
200 /*
201 * XDR remote call arguments
202 * written for XDR_ENCODE direction only
203 */
204 bool_t
xdr_rpcb_rmtcallargs(XDR * xdrs,struct r_rpcb_rmtcallargs * objp)205 xdr_rpcb_rmtcallargs(XDR *xdrs, struct r_rpcb_rmtcallargs *objp)
206 {
207 uint_t lenposition, argposition, position;
208 rpc_inline_t *buf;
209
210 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
211 if (buf == NULL) {
212 if (!xdr_u_int(xdrs, (uint_t *)&objp->prog))
213 return (FALSE);
214 if (!xdr_u_int(xdrs, (uint_t *)&objp->vers))
215 return (FALSE);
216 if (!xdr_u_int(xdrs, (uint_t *)&objp->proc))
217 return (FALSE);
218 } else {
219 IXDR_PUT_U_INT32(buf, objp->prog);
220 IXDR_PUT_U_INT32(buf, objp->vers);
221 IXDR_PUT_U_INT32(buf, objp->proc);
222 }
223
224 /*
225 * All the jugglery for just getting the size of the arguments
226 */
227 lenposition = XDR_GETPOS(xdrs);
228 if (!xdr_u_int(xdrs, &(objp->args.args_len)))
229 return (FALSE);
230 argposition = XDR_GETPOS(xdrs);
231 if (!(*objp->xdr_args)(xdrs, objp->args.args_val))
232 return (FALSE);
233 position = XDR_GETPOS(xdrs);
234 objp->args.args_len = (uint_t)position - (uint_t)argposition;
235 XDR_SETPOS(xdrs, lenposition);
236 if (!xdr_u_int(xdrs, &(objp->args.args_len)))
237 return (FALSE);
238 XDR_SETPOS(xdrs, position);
239 return (TRUE);
240 }
241
242 /*
243 * XDR remote call results
244 * written for XDR_DECODE direction only
245 */
246 bool_t
xdr_rpcb_rmtcallres(XDR * xdrs,struct r_rpcb_rmtcallres * objp)247 xdr_rpcb_rmtcallres(XDR *xdrs, struct r_rpcb_rmtcallres *objp)
248 {
249 if (!xdr_string(xdrs, &objp->addr, ~0))
250 return (FALSE);
251 if (!xdr_u_int(xdrs, &objp->results.results_len))
252 return (FALSE);
253 return ((*(objp->xdr_res))(xdrs, objp->results.results_val));
254 }
255
256 bool_t
xdr_netbuf(XDR * xdrs,struct netbuf * objp)257 xdr_netbuf(XDR *xdrs, struct netbuf *objp)
258 {
259 if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen))
260 return (FALSE);
261 return (xdr_bytes(xdrs, (char **)&(objp->buf),
262 (uint_t *)&(objp->len), objp->maxlen));
263 }
264