1 /* $NetBSD: rpc_prot.c,v 1.8 1998/02/13 05:52:32 lukem 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.8 1998/02/13 05:52:32 lukem 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)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 return (FALSE); 162 } 163 164 static struct xdr_discrim reply_dscrm[3] = { 165 { (int)MSG_ACCEPTED, xdr_accepted_reply }, 166 { (int)MSG_DENIED, xdr_rejected_reply }, 167 { __dontcare__, NULL_xdrproc_t } }; 168 169 /* 170 * XDR a reply message 171 */ 172 bool_t 173 xdr_replymsg(xdrs, rmsg) 174 XDR *xdrs; 175 struct rpc_msg *rmsg; 176 { 177 if ( 178 xdr_u_int32_t(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 */ 192 bool_t 193 xdr_callhdr(xdrs, cmsg) 194 XDR *xdrs; 195 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_int32_t(xdrs, &(cmsg->rm_xid)) && 203 xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 204 xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 205 xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) 206 return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); 207 return (FALSE); 208 } 209 210 /* ************************** Client utility routine ************* */ 211 212 static void 213 accepted(acpt_stat, error) 214 enum accept_stat acpt_stat; 215 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 error->re_lb.s1 = (long)MSG_ACCEPTED; 247 error->re_lb.s2 = (long)acpt_stat; 248 } 249 250 static void 251 rejected(rjct_stat, error) 252 enum reject_stat rjct_stat; 253 struct rpc_err *error; 254 { 255 256 switch (rjct_stat) { 257 case RPC_MISMATCH: 258 error->re_status = RPC_VERSMISMATCH; 259 return; 260 261 case AUTH_ERROR: 262 error->re_status = RPC_AUTHERROR; 263 return; 264 } 265 /* something's wrong, but we don't know what ... */ 266 error->re_status = RPC_FAILED; 267 error->re_lb.s1 = (long)MSG_DENIED; 268 error->re_lb.s2 = (long)rjct_stat; 269 } 270 271 /* 272 * given a reply message, fills in the error 273 */ 274 void 275 _seterr_reply(msg, error) 276 struct rpc_msg *msg; 277 struct rpc_err *error; 278 { 279 280 /* optimized for normal, SUCCESSful case */ 281 switch (msg->rm_reply.rp_stat) { 282 283 case MSG_ACCEPTED: 284 if (msg->acpted_rply.ar_stat == SUCCESS) { 285 error->re_status = RPC_SUCCESS; 286 return; 287 }; 288 accepted(msg->acpted_rply.ar_stat, error); 289 break; 290 291 case MSG_DENIED: 292 rejected(msg->rjcted_rply.rj_stat, error); 293 break; 294 295 default: 296 error->re_status = RPC_FAILED; 297 error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); 298 break; 299 } 300 switch (error->re_status) { 301 302 case RPC_VERSMISMATCH: 303 error->re_vers.low = msg->rjcted_rply.rj_vers.low; 304 error->re_vers.high = msg->rjcted_rply.rj_vers.high; 305 break; 306 307 case RPC_AUTHERROR: 308 error->re_why = msg->rjcted_rply.rj_why; 309 break; 310 311 case RPC_PROGVERSMISMATCH: 312 error->re_vers.low = msg->acpted_rply.ar_vers.low; 313 error->re_vers.high = msg->acpted_rply.ar_vers.high; 314 break; 315 316 case RPC_FAILED: 317 case RPC_SUCCESS: 318 case RPC_PROGNOTREGISTERED: 319 case RPC_PMAPFAILURE: 320 case RPC_UNKNOWNPROTO: 321 case RPC_UNKNOWNHOST: 322 case RPC_SYSTEMERROR: 323 case RPC_CANTDECODEARGS: 324 case RPC_PROCUNAVAIL: 325 case RPC_PROGUNAVAIL: 326 case RPC_TIMEDOUT: 327 case RPC_CANTRECV: 328 case RPC_CANTSEND: 329 case RPC_CANTDECODERES: 330 case RPC_CANTENCODEARGS: 331 break; 332 } 333 } 334