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: #ifndef lint 30: static char sccsid[] = "@(#)rpc_prot.c 1.5 85/03/20 Copyr 1984 Sun Micro"; 31: #endif 32: 33: /* 34: * rpc_prot.c 35: * 36: * Copyright (C) 1984, Sun Microsystems, Inc. 37: * 38: * This set of routines implements the rpc message definition, 39: * its serializer and some common rpc utility routines. 40: * The routines are meant for various implementations of rpc - 41: * they are NOT for the rpc client or rpc service implementations! 42: * Because authentication stuff is easy and is part of rpc, the opaque 43: * routines are also in this program. 44: */ 45: 46: #include "types.h" 47: #include "xdr.h" 48: #include "auth.h" 49: #include "clnt.h" 50: #include "rpc_msg.h" 51: 52: /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 53: 54: struct opaque_auth _null_auth; 55: 56: /* 57: * XDR an opaque authentication struct 58: * (see auth.h) 59: */ 60: bool_t 61: xdr_opaque_auth(xdrs, ap) 62: register XDR *xdrs; 63: register struct opaque_auth *ap; 64: { 65: 66: if (xdr_enum(xdrs, &(ap->oa_flavor))) 67: return (xdr_bytes(xdrs, &ap->oa_base, 68: &ap->oa_length, MAX_AUTH_BYTES)); 69: return (FALSE); 70: } 71: 72: /* 73: * XDR a DES key. 74: */ 75: bool_t 76: xdr_deskey(xdrs, blkp) 77: register XDR *xdrs; 78: register union des_block *blkp; 79: { 80: 81: if (! xdr_u_long(xdrs, &(blkp->key.high))) 82: return (FALSE); 83: return (xdr_u_long(xdrs, &(blkp->key.low))); 84: } 85: 86: /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 87: 88: /* 89: * XDR the MSG_ACCEPTED part of a reply message union 90: */ 91: bool_t 92: xdr_accepted_reply(xdrs, ar) 93: register XDR *xdrs; 94: register struct accepted_reply *ar; 95: { 96: 97: /* personalized union, rather than calling xdr_union */ 98: if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 99: return (FALSE); 100: if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) 101: return (FALSE); 102: switch (ar->ar_stat) { 103: 104: case SUCCESS: 105: return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 106: 107: case PROG_MISMATCH: 108: if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) 109: return (FALSE); 110: return (xdr_u_long(xdrs, &(ar->ar_vers.high))); 111: } 112: return (TRUE); /* TRUE => open ended set of problems */ 113: } 114: 115: /* 116: * XDR the MSG_DENIED part of a reply message union 117: */ 118: bool_t 119: xdr_rejected_reply(xdrs, rr) 120: register XDR *xdrs; 121: register struct rejected_reply *rr; 122: { 123: 124: /* personalized union, rather than calling xdr_union */ 125: if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) 126: return (FALSE); 127: switch (rr->rj_stat) { 128: 129: case RPC_MISMATCH: 130: if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) 131: return (FALSE); 132: return (xdr_u_long(xdrs, &(rr->rj_vers.high))); 133: 134: case AUTH_ERROR: 135: return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); 136: } 137: return (FALSE); 138: } 139: 140: static struct xdr_discrim reply_dscrm[3] = { 141: { (int)MSG_ACCEPTED, xdr_accepted_reply }, 142: { (int)MSG_DENIED, xdr_rejected_reply }, 143: { __dontcare__, NULL_xdrproc_t } }; 144: 145: /* 146: * XDR a reply message 147: */ 148: bool_t 149: xdr_replymsg(xdrs, rmsg) 150: register XDR *xdrs; 151: register struct rpc_msg *rmsg; 152: { 153: 154: if ( 155: xdr_u_long(xdrs, &(rmsg->rm_xid)) && 156: xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && 157: (rmsg->rm_direction == REPLY) ) 158: return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), 159: (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); 160: return (FALSE); 161: } 162: 163: /* 164: * XDR a call message 165: */ 166: bool_t 167: xdr_callmsg(xdrs, cmsg) 168: register XDR *xdrs; 169: register struct rpc_msg *cmsg; 170: { 171: 172: if ( 173: xdr_u_long(xdrs, &(cmsg->rm_xid)) && 174: xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 175: (cmsg->rm_direction == CALL) && 176: xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 177: (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && 178: xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) && 179: xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) && 180: xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) && 181: xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) ) 182: return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); 183: return (FALSE); 184: } 185: 186: /* 187: * Serializes the "static part" of a call message header. 188: * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 189: * The rm_xid is not really static, but the user can easily munge on the fly. 190: */ 191: bool_t 192: xdr_callhdr(xdrs, cmsg) 193: register XDR *xdrs; 194: register struct rpc_msg *cmsg; 195: { 196: 197: cmsg->rm_direction = CALL; 198: cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 199: if ( 200: (xdrs->x_op == XDR_ENCODE) && 201: xdr_u_long(xdrs, &(cmsg->rm_xid)) && 202: xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 203: xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 204: xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) 205: return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); 206: return (FALSE); 207: } 208: 209: /* ************************** Client utility routine ************* */ 210: 211: static void 212: accepted(acpt_stat, error) 213: register enum accept_stat acpt_stat; 214: register struct rpc_err *error; 215: { 216: 217: switch (acpt_stat) { 218: 219: case PROG_UNAVAIL: 220: error->re_status = RPC_PROGUNAVAIL; 221: return; 222: 223: case PROG_MISMATCH: 224: error->re_status = RPC_PROGVERSMISMATCH; 225: return; 226: 227: case PROC_UNAVAIL: 228: error->re_status = RPC_PROCUNAVAIL; 229: return; 230: 231: case GARBAGE_ARGS: 232: error->re_status = RPC_CANTDECODEARGS; 233: return; 234: 235: case SYSTEM_ERR: 236: error->re_status = RPC_SYSTEMERROR; 237: return; 238: 239: case SUCCESS: 240: error->re_status = RPC_SUCCESS; 241: return; 242: } 243: /* something's wrong, but we don't know what ... */ 244: error->re_status = RPC_FAILED; 245: error->re_lb.s1 = (long)MSG_ACCEPTED; 246: error->re_lb.s2 = (long)acpt_stat; 247: } 248: 249: static void 250: rejected(rjct_stat, error) 251: register enum reject_stat rjct_stat; 252: register struct rpc_err *error; 253: { 254: 255: switch (rjct_stat) { 256: 257: case RPC_VERSMISMATCH: 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: register struct rpc_msg *msg; 277: register 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: }