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