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