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[] = "@(#)svc_udp.c 1.4 85/03/14 Copyr 1984 Sun Micro"; 31: #endif 32: 33: /* 34: * svc_udp.c, 35: * Server side for UDP/IP based RPC. (Does some caching in the hopes of 36: * achieving execute-at-most-once semantics.) 37: * 38: * Copyright (C) 1984, Sun Microsystems, Inc. 39: */ 40: 41: #include <stdio.h> 42: #include "types.h" 43: #include <netinet/in.h> 44: #include <sys/socket.h> 45: #include <errno.h> 46: #include "xdr.h" 47: #include "auth.h" 48: #include "clnt.h" 49: #include "rpc_msg.h" 50: #include "svc.h" 51: 52: char *mem_alloc(); 53: 54: #define rpc_buffer(xprt) ((xprt)->xp_p1) 55: 56: static bool_t svcudp_recv(); 57: static bool_t svcudp_reply(); 58: static enum xprt_stat svcudp_stat(); 59: static bool_t svcudp_getargs(); 60: static bool_t svcudp_freeargs(); 61: static void svcudp_destroy(); 62: 63: static struct xp_ops svcudp_op = { 64: svcudp_recv, 65: svcudp_stat, 66: svcudp_getargs, 67: svcudp_reply, 68: svcudp_freeargs, 69: svcudp_destroy 70: }; 71: 72: extern int errno; 73: 74: /* 75: * kept in xprt->xp_p2 76: */ 77: struct svcudp_data { 78: u_long su_xid; /* transaction id */ 79: XDR su_xdrs; /* XDR handle */ 80: char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ 81: }; 82: #define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) 83: 84: /* 85: * Usage: 86: * xprt = svcudp_create(sock); 87: * 88: * If sock<0 then a socket is created, else sock is used. 89: * If the socket, sock is not bound to a port then svcudp_create 90: * binds it to an arbitrary port. In any (successful) case, 91: * xprt->xp_sock is the registered socket number and xprt->xp_port is the 92: * associated port number. 93: * Once *xprt is initialized, it is registered as a transporter; 94: * see (svc.h, xprt_register). 95: * The routines returns NULL if a problem occurred. 96: */ 97: SVCXPRT * 98: svcudp_create(sock) 99: register int sock; 100: { 101: bool_t madesock = FALSE; 102: register SVCXPRT *xprt; 103: register struct svcudp_data *su; 104: struct sockaddr_in addr; 105: int len = sizeof(struct sockaddr_in); 106: 107: if (sock == RPC_ANYSOCK) { 108: if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 109: perror("svcudp_create: socket creation problem"); 110: return ((SVCXPRT *)NULL); 111: } 112: madesock = TRUE; 113: } 114: addr.sin_addr.s_addr = 0; 115: addr.sin_family = AF_INET; 116: addr.sin_port = 0; 117: (void)bind(sock, (struct sockaddr *)&addr, len); 118: if (getsockname(sock, (caddr_t)&addr, &len) != 0) { 119: perror("svcudp_create - cannot getsockname"); 120: if (madesock) 121: (void)close(sock); 122: return ((SVCXPRT *)NULL); 123: } 124: xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); 125: if (xprt == NULL) { 126: fprintf(stderr, "svcudp_create: out of memory\n"); 127: return (NULL); 128: } 129: if ((rpc_buffer(xprt) = mem_alloc(UDPMSGSIZE)) == NULL) { 130: fprintf(stderr, "svcudp_create: out of memory\n"); 131: return (NULL); 132: } 133: su = (struct svcudp_data *)mem_alloc(sizeof(*su)); 134: if (su == NULL) { 135: fprintf(stderr, "svcudp_create: out of memory\n"); 136: return (NULL); 137: } 138: xdrmem_create( 139: &(su->su_xdrs), rpc_buffer(xprt), UDPMSGSIZE, XDR_DECODE); 140: xprt->xp_p2 = (caddr_t)su; 141: xprt->xp_verf.oa_base = su->su_verfbody; 142: xprt->xp_ops = &svcudp_op; 143: xprt->xp_port = ntohs(addr.sin_port); 144: xprt->xp_sock = sock; 145: xprt_register(xprt); 146: return (xprt); 147: } 148: 149: static enum xprt_stat 150: svcudp_stat(xprt) 151: SVCXPRT *xprt; 152: { 153: 154: return (XPRT_IDLE); 155: } 156: 157: static bool_t 158: svcudp_recv(xprt, msg) 159: register SVCXPRT *xprt; 160: struct rpc_msg *msg; 161: { 162: register struct svcudp_data *su = su_data(xprt); 163: register XDR *xdrs = &(su->su_xdrs); 164: register int rlen; 165: 166: again: 167: xprt->xp_addrlen = sizeof(struct sockaddr_in); 168: rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), UDPMSGSIZE, 169: 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); 170: if (rlen == -1 && errno == EINTR) 171: goto again; 172: if (rlen < 4*sizeof(u_long)) 173: return (FALSE); 174: xdrs->x_op = XDR_DECODE; 175: XDR_SETPOS(xdrs, 0); 176: if (! xdr_callmsg(xdrs, msg)) 177: return (FALSE); 178: su->su_xid = msg->rm_xid; 179: return (TRUE); 180: } 181: 182: static bool_t 183: svcudp_reply(xprt, msg) 184: register SVCXPRT *xprt; 185: struct rpc_msg *msg; 186: { 187: register struct svcudp_data *su = su_data(xprt); 188: register XDR *xdrs = &(su->su_xdrs); 189: register int slen; 190: register bool_t stat = FALSE; 191: 192: xdrs->x_op = XDR_ENCODE; 193: XDR_SETPOS(xdrs, 0); 194: msg->rm_xid = su->su_xid; 195: if (xdr_replymsg(xdrs, msg)) { 196: slen = (int)XDR_GETPOS(xdrs); 197: if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0, 198: (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen) 199: == slen) 200: stat = TRUE; 201: } 202: return (stat); 203: } 204: 205: static bool_t 206: svcudp_getargs(xprt, xdr_args, args_ptr) 207: SVCXPRT *xprt; 208: xdrproc_t xdr_args; 209: caddr_t args_ptr; 210: { 211: 212: return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); 213: } 214: 215: static bool_t 216: svcudp_freeargs(xprt, xdr_args, args_ptr) 217: SVCXPRT *xprt; 218: xdrproc_t xdr_args; 219: caddr_t args_ptr; 220: { 221: register XDR *xdrs = &(su_data(xprt)->su_xdrs); 222: 223: xdrs->x_op = XDR_FREE; 224: return ((*xdr_args)(xdrs, args_ptr)); 225: } 226: 227: static void 228: svcudp_destroy(xprt) 229: register SVCXPRT *xprt; 230: { 231: register struct svcudp_data *su = su_data(xprt); 232: 233: xprt_unregister(xprt); 234: (void)close(xprt->xp_sock); 235: XDR_DESTROY(&(su->su_xdrs)); 236: mem_free((caddr_t)su, sizeof(struct svcudp_data)); 237: mem_free(rpc_buffer(xprt), UDPMSGSIZE); 238: mem_free((caddr_t)xprt, sizeof(SVCXPRT)); 239: }