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