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 /* 37 * Protocol for the local binder service, or pmap. 38 * All the pmap xdr routines here. 39 */ 40 41 #include "mt.h" 42 #include <rpc/types.h> 43 #include <rpc/xdr.h> 44 #include <rpc/pmap_prot.h> 45 #include <rpc/pmap_rmt.h> 46 47 bool_t 48 xdr_pmap(XDR *xdrs, struct pmap *objp) 49 { 50 rpc_inline_t *buf; 51 52 switch (xdrs->x_op) { 53 case XDR_ENCODE: 54 buf = XDR_INLINE(xdrs, 4 * BYTES_PER_XDR_UNIT); 55 if (buf == NULL) { 56 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->pm_prog)) 57 return (FALSE); 58 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->pm_vers)) 59 return (FALSE); 60 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->pm_prot)) 61 return (FALSE); 62 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->pm_port)) 63 return (FALSE); 64 } else { 65 IXDR_PUT_U_INT32(buf, objp->pm_prog); 66 IXDR_PUT_U_INT32(buf, objp->pm_vers); 67 IXDR_PUT_U_INT32(buf, objp->pm_prot); 68 IXDR_PUT_U_INT32(buf, objp->pm_port); 69 } 70 return (TRUE); 71 case XDR_DECODE: 72 buf = XDR_INLINE(xdrs, 4 * BYTES_PER_XDR_UNIT); 73 if (buf == NULL) { 74 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->pm_prog)) 75 return (FALSE); 76 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->pm_vers)) 77 return (FALSE); 78 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->pm_prot)) 79 return (FALSE); 80 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->pm_port)) 81 return (FALSE); 82 } else { 83 objp->pm_prog = IXDR_GET_U_INT32(buf); 84 objp->pm_vers = IXDR_GET_U_INT32(buf); 85 objp->pm_prot = IXDR_GET_U_INT32(buf); 86 objp->pm_port = IXDR_GET_U_INT32(buf); 87 } 88 return (TRUE); 89 case XDR_FREE: 90 return (TRUE); 91 } 92 return (FALSE); 93 } 94 95 /* 96 * pmaplist_ptr implements a linked list. The RPCL definition from 97 * pmap_prot.x is: 98 * 99 * struct pm__list { 100 * pmap pml_map; 101 * struct pm__list *pml_next; 102 * }; 103 * typedef pm__list *pmaplist_ptr; 104 * 105 * Recall that "pointers" in XDR are encoded as a boolean, indicating whether 106 * there's any data behind the pointer, followed by the data (if any exists). 107 * The boolean can be interpreted as ``more data follows me''; if FALSE then 108 * nothing follows the boolean; if TRUE then the boolean is followed by an 109 * actual struct pmap, and another pmaplist_ptr (declared in RPCL as "struct 110 * pmaplist *"). 111 * 112 * This could be implemented via the xdr_pointer type, though this would 113 * result in one recursive call per element in the list. Rather than do that 114 * we can ``unwind'' the recursion into a while loop and use xdr_reference to 115 * serialize the pmap elements. 116 */ 117 bool_t 118 xdr_pmaplist_ptr(XDR *xdrs, pmaplist_ptr *rp) 119 { 120 /* 121 * more_elements is pre-computed in case the direction is 122 * XDR_ENCODE or XDR_FREE. more_elements is overwritten by 123 * xdr_bool when the direction is XDR_DECODE. 124 */ 125 bool_t more_elements; 126 int freeing = (xdrs->x_op == XDR_FREE); 127 pmaplist_ptr next; 128 pmaplist_ptr next_copy; 129 130 for (;;) { 131 more_elements = (bool_t)(*rp != NULL); 132 if (!xdr_bool(xdrs, &more_elements)) 133 return (FALSE); 134 if (!more_elements) 135 return (TRUE); /* we are done */ 136 /* 137 * the unfortunate side effect of non-recursion is that in 138 * the case of freeing we must remember the next object 139 * before we free the current object ... 140 */ 141 if (freeing) 142 next = (*rp)->pml_next; 143 if (!xdr_reference(xdrs, (caddr_t *)rp, 144 (uint_t)sizeof (struct pmaplist), (xdrproc_t)xdr_pmap)) 145 return (FALSE); 146 if (freeing) { 147 next_copy = next; 148 rp = &next_copy; 149 /* 150 * Note that in the subsequent iteration, next_copy 151 * gets nulled out by the xdr_reference 152 * but next itself survives. 153 */ 154 } else { 155 rp = &((*rp)->pml_next); 156 } 157 } 158 /*NOTREACHED*/ 159 } 160 161 /* 162 * xdr_pmaplist() is specified to take a PMAPLIST **, but is identical in 163 * functionality to xdr_pmaplist_ptr(). 164 */ 165 bool_t 166 xdr_pmaplist(XDR *xdrs, PMAPLIST **rp) 167 { 168 return (xdr_pmaplist_ptr(xdrs, (pmaplist_ptr *)rp)); 169 } 170 171 172 /* 173 * XDR remote call arguments 174 * written for XDR_ENCODE direction only 175 */ 176 bool_t 177 xdr_rmtcallargs(XDR *xdrs, struct p_rmtcallargs *cap) 178 { 179 uint_t lenposition, argposition, position; 180 rpc_inline_t *buf; 181 182 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT); 183 if (buf == NULL) { 184 if (!xdr_u_int(xdrs, (uint_t *)&(cap->prog)) || 185 !xdr_u_int(xdrs, (uint_t *)&(cap->vers)) || 186 !xdr_u_int(xdrs, (uint_t *)&(cap->proc))) 187 return (FALSE); 188 } else { 189 IXDR_PUT_U_INT32(buf, cap->prog); 190 IXDR_PUT_U_INT32(buf, cap->vers); 191 IXDR_PUT_U_INT32(buf, cap->proc); 192 } 193 194 /* 195 * All the jugglery for just getting the size of the arguments 196 */ 197 lenposition = XDR_GETPOS(xdrs); 198 if (!xdr_u_int(xdrs, &(cap->args.args_len))) 199 return (FALSE); 200 argposition = XDR_GETPOS(xdrs); 201 if (!(*cap->xdr_args)(xdrs, cap->args.args_val)) 202 return (FALSE); 203 position = XDR_GETPOS(xdrs); 204 cap->args.args_len = position - argposition; 205 XDR_SETPOS(xdrs, lenposition); 206 if (!xdr_u_int(xdrs, &(cap->args.args_len))) 207 return (FALSE); 208 XDR_SETPOS(xdrs, position); 209 return (TRUE); 210 } 211 212 /* 213 * XDR remote call results 214 * written for XDR_DECODE direction only 215 */ 216 bool_t 217 xdr_rmtcallres(XDR *xdrs, struct p_rmtcallres *crp) 218 { 219 if (xdr_u_int(xdrs, (uint_t *)&crp->port) && 220 xdr_u_int(xdrs, &crp->res.res_len)) 221 return ((*(crp->xdr_res))(xdrs, crp->res.res_val)); 222 return (FALSE); 223 } 224