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