1 /* $NetBSD: rpc_prot.c,v 1.5 1997/07/21 14:08:36 jtc 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.5 1997/07/21 14:08:36 jtc 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 #include <sys/param.h> 57 #include <rpc/rpc.h> 58 59 #ifdef __weak_alias 60 __weak_alias(xdr_accepted_reply,_xdr_accepted_reply); 61 __weak_alias(xdr_callhdr,_xdr_callhdr); 62 __weak_alias(xdr_des_block,_xdr_des_block); 63 __weak_alias(xdr_opaque_auth,_xdr_opaque_auth); 64 __weak_alias(xdr_rejected_reply,_xdr_rejected_reply); 65 __weak_alias(xdr_replymsg,_xdr_replymsg); 66 #endif 67 68 static void accepted __P((enum accept_stat, struct rpc_err *)); 69 static void rejected __P((enum reject_stat, struct rpc_err *)); 70 71 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 72 73 struct opaque_auth _null_auth; 74 75 /* 76 * XDR an opaque authentication struct 77 * (see auth.h) 78 */ 79 bool_t 80 xdr_opaque_auth(xdrs, ap) 81 register XDR *xdrs; 82 register struct opaque_auth *ap; 83 { 84 85 if (xdr_enum(xdrs, &(ap->oa_flavor))) 86 return (xdr_bytes(xdrs, &ap->oa_base, 87 &ap->oa_length, MAX_AUTH_BYTES)); 88 return (FALSE); 89 } 90 91 /* 92 * XDR a DES block 93 */ 94 bool_t 95 xdr_des_block(xdrs, blkp) 96 register XDR *xdrs; 97 register des_block *blkp; 98 { 99 return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); 100 } 101 102 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 103 104 /* 105 * XDR the MSG_ACCEPTED part of a reply message union 106 */ 107 bool_t 108 xdr_accepted_reply(xdrs, ar) 109 register XDR *xdrs; 110 register struct accepted_reply *ar; 111 { 112 113 /* personalized union, rather than calling xdr_union */ 114 if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 115 return (FALSE); 116 if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) 117 return (FALSE); 118 switch (ar->ar_stat) { 119 120 case SUCCESS: 121 return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 122 123 case PROG_MISMATCH: 124 if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) 125 return (FALSE); 126 return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); 127 128 case GARBAGE_ARGS: 129 case SYSTEM_ERR: 130 case PROC_UNAVAIL: 131 case PROG_UNAVAIL: 132 break; 133 } 134 return (TRUE); /* TRUE => open ended set of problems */ 135 } 136 137 /* 138 * XDR the MSG_DENIED part of a reply message union 139 */ 140 bool_t 141 xdr_rejected_reply(xdrs, rr) 142 register XDR *xdrs; 143 register struct rejected_reply *rr; 144 { 145 146 /* personalized union, rather than calling xdr_union */ 147 if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) 148 return (FALSE); 149 switch (rr->rj_stat) { 150 151 case RPC_MISMATCH: 152 if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) 153 return (FALSE); 154 return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); 155 156 case AUTH_ERROR: 157 return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); 158 } 159 return (FALSE); 160 } 161 162 static struct xdr_discrim reply_dscrm[3] = { 163 { (int)MSG_ACCEPTED, xdr_accepted_reply }, 164 { (int)MSG_DENIED, xdr_rejected_reply }, 165 { __dontcare__, NULL_xdrproc_t } }; 166 167 /* 168 * XDR a reply message 169 */ 170 bool_t 171 xdr_replymsg(xdrs, rmsg) 172 register XDR *xdrs; 173 register struct rpc_msg *rmsg; 174 { 175 if ( 176 xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && 177 xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && 178 (rmsg->rm_direction == REPLY) ) 179 return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), 180 (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); 181 return (FALSE); 182 } 183 184 185 /* 186 * Serializes the "static part" of a call message header. 187 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 188 * The rm_xid is not really static, but the user can easily munge on the fly. 189 */ 190 bool_t 191 xdr_callhdr(xdrs, cmsg) 192 register XDR *xdrs; 193 register struct rpc_msg *cmsg; 194 { 195 196 cmsg->rm_direction = CALL; 197 cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 198 if ( 199 (xdrs->x_op == XDR_ENCODE) && 200 xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && 201 xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 202 xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 203 xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) 204 return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); 205 return (FALSE); 206 } 207 208 /* ************************** Client utility routine ************* */ 209 210 static void 211 accepted(acpt_stat, error) 212 register enum accept_stat acpt_stat; 213 register struct rpc_err *error; 214 { 215 216 switch (acpt_stat) { 217 218 case PROG_UNAVAIL: 219 error->re_status = RPC_PROGUNAVAIL; 220 return; 221 222 case PROG_MISMATCH: 223 error->re_status = RPC_PROGVERSMISMATCH; 224 return; 225 226 case PROC_UNAVAIL: 227 error->re_status = RPC_PROCUNAVAIL; 228 return; 229 230 case GARBAGE_ARGS: 231 error->re_status = RPC_CANTDECODEARGS; 232 return; 233 234 case SYSTEM_ERR: 235 error->re_status = RPC_SYSTEMERROR; 236 return; 237 238 case SUCCESS: 239 error->re_status = RPC_SUCCESS; 240 return; 241 } 242 /* something's wrong, but we don't know what ... */ 243 error->re_status = RPC_FAILED; 244 error->re_lb.s1 = (long)MSG_ACCEPTED; 245 error->re_lb.s2 = (long)acpt_stat; 246 } 247 248 static void 249 rejected(rjct_stat, error) 250 register enum reject_stat rjct_stat; 251 register struct rpc_err *error; 252 { 253 254 switch (rjct_stat) { 255 case RPC_MISMATCH: 256 error->re_status = RPC_VERSMISMATCH; 257 return; 258 259 case AUTH_ERROR: 260 error->re_status = RPC_AUTHERROR; 261 return; 262 } 263 /* something's wrong, but we don't know what ... */ 264 error->re_status = RPC_FAILED; 265 error->re_lb.s1 = (long)MSG_DENIED; 266 error->re_lb.s2 = (long)rjct_stat; 267 } 268 269 /* 270 * given a reply message, fills in the error 271 */ 272 void 273 _seterr_reply(msg, error) 274 register struct rpc_msg *msg; 275 register struct rpc_err *error; 276 { 277 278 /* optimized for normal, SUCCESSful case */ 279 switch (msg->rm_reply.rp_stat) { 280 281 case MSG_ACCEPTED: 282 if (msg->acpted_rply.ar_stat == SUCCESS) { 283 error->re_status = RPC_SUCCESS; 284 return; 285 }; 286 accepted(msg->acpted_rply.ar_stat, error); 287 break; 288 289 case MSG_DENIED: 290 rejected(msg->rjcted_rply.rj_stat, error); 291 break; 292 293 default: 294 error->re_status = RPC_FAILED; 295 error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); 296 break; 297 } 298 switch (error->re_status) { 299 300 case RPC_VERSMISMATCH: 301 error->re_vers.low = msg->rjcted_rply.rj_vers.low; 302 error->re_vers.high = msg->rjcted_rply.rj_vers.high; 303 break; 304 305 case RPC_AUTHERROR: 306 error->re_why = msg->rjcted_rply.rj_why; 307 break; 308 309 case RPC_PROGVERSMISMATCH: 310 error->re_vers.low = msg->acpted_rply.ar_vers.low; 311 error->re_vers.high = msg->acpted_rply.ar_vers.high; 312 break; 313 314 case RPC_FAILED: 315 case RPC_SUCCESS: 316 case RPC_PROGNOTREGISTERED: 317 case RPC_PMAPFAILURE: 318 case RPC_UNKNOWNPROTO: 319 case RPC_UNKNOWNHOST: 320 case RPC_SYSTEMERROR: 321 case RPC_CANTDECODEARGS: 322 case RPC_PROCUNAVAIL: 323 case RPC_PROGUNAVAIL: 324 case RPC_TIMEDOUT: 325 case RPC_CANTRECV: 326 case RPC_CANTSEND: 327 case RPC_CANTDECODERES: 328 case RPC_CANTENCODEARGS: 329 break; 330 } 331 } 332