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 #include "mt.h" 37 #include <stdlib.h> 38 #include <sys/param.h> 39 #include <rpc/rpc.h> 40 #include <syslog.h> 41 #include <sys/byteorder.h> 42 43 extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); 44 45 /* 46 * XDR a call message 47 */ 48 bool_t 49 xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) 50 { 51 rpc_inline_t *buf; 52 struct opaque_auth *oa; 53 54 if (xdrs->x_op == XDR_ENCODE) { 55 uint_t credrndup; 56 uint_t verfrndup; 57 58 if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) 59 return (FALSE); 60 if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) 61 return (FALSE); 62 credrndup = RNDUP(cmsg->rm_call.cb_cred.oa_length); 63 verfrndup = RNDUP(cmsg->rm_call.cb_verf.oa_length); 64 buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + 65 credrndup + 2 * BYTES_PER_XDR_UNIT + verfrndup); 66 if (buf != NULL) { 67 IXDR_PUT_INT32(buf, cmsg->rm_xid); 68 IXDR_PUT_ENUM(buf, cmsg->rm_direction); 69 if (cmsg->rm_direction != CALL) 70 return (FALSE); 71 IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers); 72 if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) 73 return (FALSE); 74 IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog); 75 IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers); 76 IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc); 77 oa = &cmsg->rm_call.cb_cred; 78 IXDR_PUT_ENUM(buf, oa->oa_flavor); 79 IXDR_PUT_INT32(buf, oa->oa_length); 80 if (oa->oa_length) { 81 (void) memcpy(buf, oa->oa_base, oa->oa_length); 82 buf += credrndup / BYTES_PER_XDR_UNIT; 83 if ((credrndup -= oa->oa_length) > 0) 84 (void) memset((char *)buf - credrndup, 85 0, credrndup); 86 } 87 oa = &cmsg->rm_call.cb_verf; 88 IXDR_PUT_ENUM(buf, oa->oa_flavor); 89 IXDR_PUT_INT32(buf, oa->oa_length); 90 if (oa->oa_length) { 91 (void) memcpy(buf, oa->oa_base, oa->oa_length); 92 buf += verfrndup / BYTES_PER_XDR_UNIT; 93 if ((verfrndup -= oa->oa_length) > 0) 94 (void) memset((char *)buf - verfrndup, 95 0, verfrndup); 96 } 97 return (TRUE); 98 } 99 } 100 if (xdrs->x_op == XDR_DECODE) { 101 buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); 102 if (buf != NULL) { 103 cmsg->rm_xid = IXDR_GET_INT32(buf); 104 cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); 105 if (cmsg->rm_direction != CALL) 106 return (FALSE); 107 cmsg->rm_call.cb_rpcvers = IXDR_GET_INT32(buf); 108 if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) 109 return (FALSE); 110 cmsg->rm_call.cb_prog = IXDR_GET_INT32(buf); 111 cmsg->rm_call.cb_vers = IXDR_GET_INT32(buf); 112 cmsg->rm_call.cb_proc = IXDR_GET_INT32(buf); 113 oa = &cmsg->rm_call.cb_cred; 114 oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); 115 oa->oa_length = IXDR_GET_INT32(buf); 116 if (oa->oa_length) { 117 if (oa->oa_length > MAX_AUTH_BYTES) 118 return (FALSE); 119 if (oa->oa_base == NULL) { 120 oa->oa_base = malloc(oa->oa_length); 121 if (oa->oa_base == NULL) { 122 syslog(LOG_ERR, "xdr_callmsg : " 123 "out of memory."); 124 return (FALSE); 125 } 126 } 127 buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); 128 if (buf == NULL) { 129 if (xdr_opaque(xdrs, oa->oa_base, 130 oa->oa_length) == FALSE) 131 return (FALSE); 132 } else { 133 (void) memcpy(oa->oa_base, 134 buf, (size_t)oa->oa_length); 135 /* 136 * no real need.... 137 * buf += RNDUP(oa->oa_length) / 138 * (int)sizeof (int32_t); 139 */ 140 } 141 } 142 oa = &cmsg->rm_call.cb_verf; 143 buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); 144 if (buf == NULL) { 145 if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || 146 xdr_u_int(xdrs, &oa->oa_length) == FALSE) 147 return (FALSE); 148 } else { 149 oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); 150 oa->oa_length = IXDR_GET_INT32(buf); 151 } 152 if (oa->oa_length) { 153 if (oa->oa_length > MAX_AUTH_BYTES) 154 return (FALSE); 155 if (oa->oa_base == NULL) { 156 oa->oa_base = malloc(oa->oa_length); 157 if (oa->oa_base == NULL) { 158 syslog(LOG_ERR, "xdr_callmsg : " 159 "out of memory."); 160 return (FALSE); 161 } 162 } 163 buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); 164 if (buf == NULL) { 165 if (xdr_opaque(xdrs, oa->oa_base, 166 oa->oa_length) == FALSE) 167 return (FALSE); 168 } else { 169 (void) memcpy(oa->oa_base, 170 buf, (size_t)oa->oa_length); 171 /* 172 * no real need... 173 * buf += RNDUP(oa->oa_length) / 174 * (int)sizeof (int32_t); 175 */ 176 } 177 } 178 return (TRUE); 179 } 180 } 181 if (xdr_u_int(xdrs, &(cmsg->rm_xid)) && 182 xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 183 (cmsg->rm_direction == CALL) && 184 xdr_u_int(xdrs, (uint_t *)&(cmsg->rm_call.cb_rpcvers)) && 185 (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && 186 xdr_u_int(xdrs, (uint_t *)&(cmsg->rm_call.cb_prog)) && 187 xdr_u_int(xdrs, (uint_t *)&(cmsg->rm_call.cb_vers)) && 188 xdr_u_int(xdrs, (uint_t *)&(cmsg->rm_call.cb_proc)) && 189 xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred))) { 190 return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); 191 } 192 return (FALSE); 193 } 194