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