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