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