1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.1 (the "License"). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24/* 25 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 26 * unrestricted use provided that this legend is included on all tape 27 * media and as a part of the software program in whole or part. Users 28 * may copy or modify Sun RPC without charge, but are not authorized 29 * to license or distribute it to anyone else except as part of a product or 30 * program developed by the user. 31 * 32 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 33 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 34 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 35 * 36 * Sun RPC is provided with no support and without any obligation on the 37 * part of Sun Microsystems, Inc. to assist in its use, correction, 38 * modification or enhancement. 39 * 40 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 41 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 42 * OR ANY PART THEREOF. 43 * 44 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 45 * or profits or other special, indirect and consequential damages, even if 46 * Sun has been advised of the possibility of such damages. 47 * 48 * Sun Microsystems, Inc. 49 * 2550 Garcia Avenue 50 * Mountain View, California 94043 51 */ 52 53#if defined(LIBC_SCCS) && !defined(lint) 54/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/ 55static char *rcsid = "$Id: rpc_prot.c,v 1.3 2003/06/23 17:24:59 majka Exp $"; 56#endif 57 58/* 59 * rpc_prot.c 60 * 61 * Copyright (C) 1984, Sun Microsystems, Inc. 62 * 63 * This set of routines implements the rpc message definition, 64 * its serializer and some common rpc utility routines. 65 * The routines are meant for various implementations of rpc - 66 * they are NOT for the rpc client or rpc service implementations! 67 * Because authentication stuff is easy and is part of rpc, the opaque 68 * routines are also in this program. 69 */ 70 71#include <sys/param.h> 72 73#include <rpc/rpc.h> 74 75/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 76 77#if defined(__APPLE__) 78extern 79#endif 80struct opaque_auth _null_auth; 81 82/* 83 * XDR an opaque authentication struct 84 * (see auth.h) 85 */ 86bool_t 87xdr_opaque_auth(xdrs, ap) 88 register XDR *xdrs; 89 register struct opaque_auth *ap; 90{ 91 92 if (xdr_enum(xdrs, &(ap->oa_flavor))) 93 return (xdr_bytes(xdrs, &ap->oa_base, 94 &ap->oa_length, MAX_AUTH_BYTES)); 95 return (FALSE); 96} 97 98/* 99 * XDR a DES block 100 */ 101bool_t 102xdr_des_block(xdrs, blkp) 103 register XDR *xdrs; 104 register des_block *blkp; 105{ 106 return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); 107} 108 109/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 110 111/* 112 * XDR the MSG_ACCEPTED part of a reply message union 113 */ 114bool_t 115xdr_accepted_reply(xdrs, ar) 116 register XDR *xdrs; 117 register struct accepted_reply *ar; 118{ 119 120 /* personalized union, rather than calling xdr_union */ 121 if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 122 return (FALSE); 123 if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) 124 return (FALSE); 125 switch (ar->ar_stat) { 126 127 case SUCCESS: 128 return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where, 0)); 129 130 case PROG_MISMATCH: 131 if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) 132 return (FALSE); 133 return (xdr_u_long(xdrs, &(ar->ar_vers.high))); 134 default: break; 135 } 136 return (TRUE); /* TRUE => open ended set of problems */ 137} 138 139/* 140 * XDR the MSG_DENIED part of a reply message union 141 */ 142bool_t 143xdr_rejected_reply(xdrs, rr) 144 register XDR *xdrs; 145 register struct rejected_reply *rr; 146{ 147 148 /* personalized union, rather than calling xdr_union */ 149 if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) 150 return (FALSE); 151 switch (rr->rj_stat) { 152 153 case RPC_MISMATCH: 154 if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) 155 return (FALSE); 156 return (xdr_u_long(xdrs, &(rr->rj_vers.high))); 157 158 case AUTH_ERROR: 159 return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); 160 } 161 return (FALSE); 162} 163 164static struct xdr_discrim reply_dscrm[3] = { 165 { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, 166 { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, 167 { __dontcare__, NULL_xdrproc_t } }; 168 169/* 170 * XDR a reply message 171 */ 172bool_t 173xdr_replymsg(xdrs, rmsg) 174 register XDR *xdrs; 175 register struct rpc_msg *rmsg; 176{ 177 if ( 178 xdr_u_long(xdrs, &(rmsg->rm_xid)) && 179 xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && 180 (rmsg->rm_direction == REPLY) ) 181 return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), 182 (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); 183 return (FALSE); 184} 185 186 187/* 188 * Serializes the "static part" of a call message header. 189 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 190 * The rm_xid is not really static, but the user can easily munge on the fly. 191 */ 192bool_t 193xdr_callhdr(xdrs, cmsg) 194 register XDR *xdrs; 195 register struct rpc_msg *cmsg; 196{ 197 198 cmsg->rm_direction = CALL; 199 cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 200 if ( 201 (xdrs->x_op == XDR_ENCODE) && 202 xdr_u_long(xdrs, &(cmsg->rm_xid)) && 203 xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 204 xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 205 xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) 206 return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); 207 return (FALSE); 208} 209 210/* ************************** Client utility routine ************* */ 211 212static void 213accepted(acpt_stat, error) 214 register enum accept_stat acpt_stat; 215 register struct rpc_err *error; 216{ 217 218 switch (acpt_stat) { 219 220 case PROG_UNAVAIL: 221 error->re_status = RPC_PROGUNAVAIL; 222 return; 223 224 case PROG_MISMATCH: 225 error->re_status = RPC_PROGVERSMISMATCH; 226 return; 227 228 case PROC_UNAVAIL: 229 error->re_status = RPC_PROCUNAVAIL; 230 return; 231 232 case GARBAGE_ARGS: 233 error->re_status = RPC_CANTDECODEARGS; 234 return; 235 236 case SYSTEM_ERR: 237 error->re_status = RPC_SYSTEMERROR; 238 return; 239 240 case SUCCESS: 241 error->re_status = RPC_SUCCESS; 242 return; 243 } 244 /* something's wrong, but we don't know what ... */ 245 error->re_status = RPC_FAILED; 246#ifdef __LP64__ 247 error->re_lb.s1 = (int)MSG_ACCEPTED; 248 error->re_lb.s2 = (int)acpt_stat; 249#else 250 error->re_lb.s1 = (long)MSG_ACCEPTED; 251 error->re_lb.s2 = (long)acpt_stat; 252#endif 253} 254 255static void 256rejected(rjct_stat, error) 257 register enum reject_stat rjct_stat; 258 register struct rpc_err *error; 259{ 260 261 switch (rjct_stat) { 262 263 case RPC_MISMATCH: 264 error->re_status = RPC_VERSMISMATCH; 265 return; 266 267 case AUTH_ERROR: 268 error->re_status = RPC_AUTHERROR; 269 return; 270 default: break; 271 } 272 /* something's wrong, but we don't know what ... */ 273 error->re_status = RPC_FAILED; 274#ifdef __LP64__ 275 error->re_lb.s1 = (int)MSG_DENIED; 276 error->re_lb.s2 = (int)rjct_stat; 277#else 278 error->re_lb.s1 = (long)MSG_DENIED; 279 error->re_lb.s2 = (long)rjct_stat; 280#endif 281} 282 283/* 284 * given a reply message, fills in the error 285 */ 286void 287_seterr_reply(msg, error) 288 register struct rpc_msg *msg; 289 register struct rpc_err *error; 290{ 291 292 /* optimized for normal, SUCCESSful case */ 293 switch (msg->rm_reply.rp_stat) { 294 295 case MSG_ACCEPTED: 296 if (msg->acpted_rply.ar_stat == SUCCESS) { 297 error->re_status = RPC_SUCCESS; 298 return; 299 }; 300 accepted(msg->acpted_rply.ar_stat, error); 301 break; 302 303 case MSG_DENIED: 304 rejected(msg->rjcted_rply.rj_stat, error); 305 break; 306 307 default: 308 error->re_status = RPC_FAILED; 309#ifdef __LP64__ 310 error->re_lb.s1 = (int)(msg->rm_reply.rp_stat); 311#else 312 error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); 313#endif 314 break; 315 } 316 switch (error->re_status) { 317 318 case RPC_VERSMISMATCH: 319 error->re_vers.low = msg->rjcted_rply.rj_vers.low; 320 error->re_vers.high = msg->rjcted_rply.rj_vers.high; 321 break; 322 323 case RPC_AUTHERROR: 324 error->re_why = msg->rjcted_rply.rj_why; 325 break; 326 327 case RPC_PROGVERSMISMATCH: 328 error->re_vers.low = msg->acpted_rply.ar_vers.low; 329 error->re_vers.high = msg->acpted_rply.ar_vers.high; 330 break; 331 332 default: break; 333 } 334} 335