3 4/* 5 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 6 * unrestricted use provided that this legend is included on all tape 7 * media and as a part of the software program in whole or part. Users 8 * may copy or modify Sun RPC without charge, but are not authorized 9 * to license or distribute it to anyone else except as part of a product or 10 * program developed by the user. 11 * 12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15 * 16 * Sun RPC is provided with no support and without any obligation on the 17 * part of Sun Microsystems, Inc. to assist in its use, correction, 18 * modification or enhancement. 19 * 20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22 * OR ANY PART THEREOF. 23 * 24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25 * or profits or other special, indirect and consequential damages, even if 26 * Sun has been advised of the possibility of such damages. 27 * 28 * Sun Microsystems, Inc. 29 * 2550 Garcia Avenue 30 * Mountain View, California 94043 31 */ 32 33#include <sys/cdefs.h> 34#if defined(LIBC_SCCS) && !defined(lint) 35static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 36static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 37#endif 38 39/* 40 * svc_vc.c, Server side for Connection Oriented based RPC. 41 * 42 * Actually implements two flavors of transporter - 43 * a tcp rendezvouser (a listner and connection establisher) 44 * and a record/tcp stream. 45 */ 46 47#include "reentrant.h" 48#include "namespace.h" 49#include <sys/types.h> 50#include <sys/param.h> 51#include <sys/poll.h> 52#include <sys/socket.h> 53#include <sys/un.h> 54#include <sys/uio.h> 55#include <netinet/in.h> 56#include <netinet/tcp.h> 57 58#include <assert.h> 59#include <err.h> 60#include <errno.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <unistd.h> 65 66#include <rpc/rpc.h> 67 68#include "rpc_com.h" 69#include "un-namespace.h" 70 71#define SOCKCREDSIZE(ngrps) \ 72 (sizeof(struct cmsgcred) + (sizeof(gid_t) * ((ngrps) - 1))) 73 74static SVCXPRT *makefd_xprt __P((int, u_int, u_int)); 75static bool_t rendezvous_request __P((SVCXPRT *, struct rpc_msg *)); 76static enum xprt_stat rendezvous_stat __P((SVCXPRT *)); 77static void svc_vc_destroy __P((SVCXPRT *)); 78static int read_vc __P((caddr_t, caddr_t, int)); 79static int write_vc __P((caddr_t, caddr_t, int)); 80static enum xprt_stat svc_vc_stat __P((SVCXPRT *)); 81static bool_t svc_vc_recv __P((SVCXPRT *, struct rpc_msg *)); 82static bool_t svc_vc_getargs __P((SVCXPRT *, xdrproc_t, caddr_t)); 83static bool_t svc_vc_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t)); 84static bool_t svc_vc_reply __P((SVCXPRT *, struct rpc_msg *)); 85static void svc_vc_rendezvous_ops __P((SVCXPRT *)); 86static void svc_vc_ops __P((SVCXPRT *)); 87static bool_t svc_vc_control __P((SVCXPRT *xprt, const u_int rq, void *in)); 88static int __msgwrite(int, void *, size_t); 89static int __msgread(int, void *, size_t); 90 91struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 92 u_int sendsize; 93 u_int recvsize; 94}; 95 96struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 97 enum xprt_stat strm_stat; 98 u_int32_t x_id; 99 XDR xdrs; 100 char verf_body[MAX_AUTH_BYTES]; 101}; 102 103struct cmessage { 104 struct cmsghdr cmsg; 105 struct cmsgcred cmcred; 106}; 107 108 109/* 110 * Usage: 111 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 112 * 113 * Creates, registers, and returns a (rpc) tcp based transporter. 114 * Once *xprt is initialized, it is registered as a transporter 115 * see (svc.h, xprt_register). This routine returns 116 * a NULL if a problem occurred. 117 * 118 * The filedescriptor passed in is expected to refer to a bound, but 119 * not yet connected socket. 120 * 121 * Since streams do buffered io similar to stdio, the caller can specify 122 * how big the send and receive buffers are via the second and third parms; 123 * 0 => use the system default. 124 */ 125SVCXPRT * 126svc_vc_create(fd, sendsize, recvsize) 127 int fd; 128 u_int sendsize; 129 u_int recvsize; 130{ 131 SVCXPRT *xprt; 132 struct cf_rendezvous *r = NULL; 133 struct __rpc_sockinfo si; 134 struct sockaddr_storage sslocal; 135 socklen_t slen; 136 int one = 1; 137 138 r = mem_alloc(sizeof(*r)); 139 if (r == NULL) { 140 warnx("svc_vc_create: out of memory"); 141 goto cleanup_svc_vc_create; 142 } 143 if (!__rpc_fd2sockinfo(fd, &si)) 144 return NULL; 145 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 146 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 147 xprt = mem_alloc(sizeof(SVCXPRT)); 148 if (xprt == NULL) { 149 warnx("svc_vc_create: out of memory"); 150 goto cleanup_svc_vc_create; 151 } 152 xprt->xp_tp = NULL; 153 xprt->xp_p1 = (caddr_t)(void *)r; 154 xprt->xp_p2 = NULL; 155 xprt->xp_p3 = NULL; 156 xprt->xp_verf = _null_auth; 157 svc_vc_rendezvous_ops(xprt); 158 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 159 xprt->xp_fd = fd; 160 161 slen = sizeof (struct sockaddr_storage); 162 if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 163 warnx("svc_vc_create: could not retrieve local addr"); 164 goto cleanup_svc_vc_create; 165 } 166 167 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 168 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 169 if (xprt->xp_ltaddr.buf == NULL) { 170 warnx("svc_vc_create: no mem for local addr"); 171 goto cleanup_svc_vc_create; 172 } 173 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 174 175 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 176 xprt_register(xprt); 177 return (xprt); 178cleanup_svc_vc_create: 179 if (r != NULL) 180 mem_free(r, sizeof(*r)); 181 return (NULL); 182} 183 184/* 185 * Like svtcp_create(), except the routine takes any *open* UNIX file 186 * descriptor as its first input. 187 */ 188SVCXPRT * 189svc_fd_create(fd, sendsize, recvsize) 190 int fd; 191 u_int sendsize; 192 u_int recvsize; 193{ 194 struct sockaddr_storage ss; 195 socklen_t slen; 196 SVCXPRT *ret; 197 198 assert(fd != -1); 199 200 ret = makefd_xprt(fd, sendsize, recvsize); 201 if (ret == NULL) 202 return NULL; 203 204 slen = sizeof (struct sockaddr_storage); 205 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 206 warnx("svc_fd_create: could not retrieve local addr"); 207 goto freedata; 208 } 209 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 210 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 211 if (ret->xp_ltaddr.buf == NULL) { 212 warnx("svc_fd_create: no mem for local addr"); 213 goto freedata; 214 } 215 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 216 217 slen = sizeof (struct sockaddr_storage); 218 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 219 warnx("svc_fd_create: could not retrieve remote addr"); 220 goto freedata; 221 } 222 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 223 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 224 if (ret->xp_rtaddr.buf == NULL) { 225 warnx("svc_fd_create: no mem for local addr"); 226 goto freedata; 227 } 228 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 229#ifdef PORTMAP 230 if (ss.ss_family == AF_INET) { 231 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 232 ret->xp_addrlen = sizeof (struct sockaddr_in); 233 } 234#endif /* PORTMAP */ 235 236 return ret; 237 238freedata: 239 if (ret->xp_ltaddr.buf != NULL) 240 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 241 242 return NULL; 243} 244 245static SVCXPRT * 246makefd_xprt(fd, sendsize, recvsize) 247 int fd; 248 u_int sendsize; 249 u_int recvsize; 250{ 251 SVCXPRT *xprt; 252 struct cf_conn *cd; 253 const char *netid; 254 struct __rpc_sockinfo si; 255 256 assert(fd != -1); 257 258 xprt = mem_alloc(sizeof(SVCXPRT)); 259 if (xprt == NULL) { 260 warnx("svc_vc: makefd_xprt: out of memory"); 261 goto done; 262 } 263 memset(xprt, 0, sizeof *xprt); 264 cd = mem_alloc(sizeof(struct cf_conn)); 265 if (cd == NULL) { 266 warnx("svc_tcp: makefd_xprt: out of memory"); 267 mem_free(xprt, sizeof(SVCXPRT)); 268 xprt = NULL; 269 goto done; 270 } 271 cd->strm_stat = XPRT_IDLE; 272 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 273 (caddr_t)(void *)xprt, read_vc, write_vc); 274 xprt->xp_p1 = (caddr_t)(void *)cd; 275 xprt->xp_verf.oa_base = cd->verf_body; 276 svc_vc_ops(xprt); /* truely deals with calls */ 277 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 278 xprt->xp_fd = fd; 279 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 280 xprt->xp_netid = strdup(netid); 281 282 xprt_register(xprt); 283done: 284 return (xprt); 285} 286 287/*ARGSUSED*/ 288static bool_t 289rendezvous_request(xprt, msg) 290 SVCXPRT *xprt; 291 struct rpc_msg *msg; 292{ 293 int sock; 294 struct cf_rendezvous *r; 295 struct sockaddr_storage addr; 296 socklen_t len; 297 struct __rpc_sockinfo si; 298 299 assert(xprt != NULL); 300 assert(msg != NULL); 301 302 r = (struct cf_rendezvous *)xprt->xp_p1; 303again: 304 len = sizeof addr; 305 if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 306 &len)) < 0) { 307 if (errno == EINTR) 308 goto again; 309 return (FALSE); 310 } 311 /* 312 * make a new transporter (re-uses xprt) 313 */ 314 xprt = makefd_xprt(sock, r->sendsize, r->recvsize); 315 xprt->xp_rtaddr.buf = mem_alloc(len); 316 if (xprt->xp_rtaddr.buf == NULL) 317 return (FALSE); 318 memcpy(xprt->xp_rtaddr.buf, &addr, len); 319 xprt->xp_rtaddr.len = len; 320#ifdef PORTMAP 321 if (addr.ss_family == AF_INET) { 322 xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf; 323 xprt->xp_addrlen = sizeof (struct sockaddr_in); 324 } 325#endif /* PORTMAP */ 326 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 327 len = 1; 328 /* XXX fvdl - is this useful? */ 329 _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 330 } 331 return (FALSE); /* there is never an rpc msg to be processed */ 332} 333 334/*ARGSUSED*/ 335static enum xprt_stat 336rendezvous_stat(xprt) 337 SVCXPRT *xprt; 338{ 339 340 return (XPRT_IDLE); 341} 342 343static void 344svc_vc_destroy(xprt) 345 SVCXPRT *xprt; 346{ 347 struct cf_conn *cd; 348 struct cf_rendezvous *r; 349 350 assert(xprt != NULL); 351 352 cd = (struct cf_conn *)xprt->xp_p1; 353 354 xprt_unregister(xprt); 355 if (xprt->xp_fd != RPC_ANYFD) 356 (void)_close(xprt->xp_fd); 357 if (xprt->xp_port != 0) { 358 /* a rendezvouser socket */ 359 r = (struct cf_rendezvous *)xprt->xp_p1; 360 mem_free(r, sizeof (struct cf_rendezvous)); 361 xprt->xp_port = 0; 362 } else { 363 /* an actual connection socket */ 364 XDR_DESTROY(&(cd->xdrs)); 365 mem_free(cd, sizeof(struct cf_conn)); 366 } 367 if (xprt->xp_rtaddr.buf) 368 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 369 if (xprt->xp_ltaddr.buf) 370 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 371 if (xprt->xp_tp) 372 free(xprt->xp_tp); 373 if (xprt->xp_netid) 374 free(xprt->xp_netid); 375 mem_free(xprt, sizeof(SVCXPRT)); 376} 377 378/*ARGSUSED*/ 379static bool_t 380svc_vc_control(xprt, rq, in) 381 SVCXPRT *xprt; 382 const u_int rq; 383 void *in; 384{ 385 return (FALSE); 386} 387 388/* 389 * reads data from the tcp or uip connection. 390 * any error is fatal and the connection is closed. 391 * (And a read of zero bytes is a half closed stream => error.) 392 * All read operations timeout after 35 seconds. A timeout is 393 * fatal for the connection. 394 */ 395static int 396read_vc(xprtp, buf, len) 397 caddr_t xprtp; 398 caddr_t buf; 399 int len; 400{ 401 SVCXPRT *xprt; 402 int sock; 403 int milliseconds = 35 * 1000; 404 struct pollfd pollfd; 405 struct sockaddr *sa; 406 struct cmessage *cm; 407 struct cmsghdr *cmp; 408 struct sockcred *sc; 409 410 xprt = (SVCXPRT *)(void *)xprtp; 411 assert(xprt != NULL); 412 413 sock = xprt->xp_fd; 414
| 3 4/* 5 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 6 * unrestricted use provided that this legend is included on all tape 7 * media and as a part of the software program in whole or part. Users 8 * may copy or modify Sun RPC without charge, but are not authorized 9 * to license or distribute it to anyone else except as part of a product or 10 * program developed by the user. 11 * 12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15 * 16 * Sun RPC is provided with no support and without any obligation on the 17 * part of Sun Microsystems, Inc. to assist in its use, correction, 18 * modification or enhancement. 19 * 20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22 * OR ANY PART THEREOF. 23 * 24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25 * or profits or other special, indirect and consequential damages, even if 26 * Sun has been advised of the possibility of such damages. 27 * 28 * Sun Microsystems, Inc. 29 * 2550 Garcia Avenue 30 * Mountain View, California 94043 31 */ 32 33#include <sys/cdefs.h> 34#if defined(LIBC_SCCS) && !defined(lint) 35static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 36static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 37#endif 38 39/* 40 * svc_vc.c, Server side for Connection Oriented based RPC. 41 * 42 * Actually implements two flavors of transporter - 43 * a tcp rendezvouser (a listner and connection establisher) 44 * and a record/tcp stream. 45 */ 46 47#include "reentrant.h" 48#include "namespace.h" 49#include <sys/types.h> 50#include <sys/param.h> 51#include <sys/poll.h> 52#include <sys/socket.h> 53#include <sys/un.h> 54#include <sys/uio.h> 55#include <netinet/in.h> 56#include <netinet/tcp.h> 57 58#include <assert.h> 59#include <err.h> 60#include <errno.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <unistd.h> 65 66#include <rpc/rpc.h> 67 68#include "rpc_com.h" 69#include "un-namespace.h" 70 71#define SOCKCREDSIZE(ngrps) \ 72 (sizeof(struct cmsgcred) + (sizeof(gid_t) * ((ngrps) - 1))) 73 74static SVCXPRT *makefd_xprt __P((int, u_int, u_int)); 75static bool_t rendezvous_request __P((SVCXPRT *, struct rpc_msg *)); 76static enum xprt_stat rendezvous_stat __P((SVCXPRT *)); 77static void svc_vc_destroy __P((SVCXPRT *)); 78static int read_vc __P((caddr_t, caddr_t, int)); 79static int write_vc __P((caddr_t, caddr_t, int)); 80static enum xprt_stat svc_vc_stat __P((SVCXPRT *)); 81static bool_t svc_vc_recv __P((SVCXPRT *, struct rpc_msg *)); 82static bool_t svc_vc_getargs __P((SVCXPRT *, xdrproc_t, caddr_t)); 83static bool_t svc_vc_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t)); 84static bool_t svc_vc_reply __P((SVCXPRT *, struct rpc_msg *)); 85static void svc_vc_rendezvous_ops __P((SVCXPRT *)); 86static void svc_vc_ops __P((SVCXPRT *)); 87static bool_t svc_vc_control __P((SVCXPRT *xprt, const u_int rq, void *in)); 88static int __msgwrite(int, void *, size_t); 89static int __msgread(int, void *, size_t); 90 91struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 92 u_int sendsize; 93 u_int recvsize; 94}; 95 96struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 97 enum xprt_stat strm_stat; 98 u_int32_t x_id; 99 XDR xdrs; 100 char verf_body[MAX_AUTH_BYTES]; 101}; 102 103struct cmessage { 104 struct cmsghdr cmsg; 105 struct cmsgcred cmcred; 106}; 107 108 109/* 110 * Usage: 111 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 112 * 113 * Creates, registers, and returns a (rpc) tcp based transporter. 114 * Once *xprt is initialized, it is registered as a transporter 115 * see (svc.h, xprt_register). This routine returns 116 * a NULL if a problem occurred. 117 * 118 * The filedescriptor passed in is expected to refer to a bound, but 119 * not yet connected socket. 120 * 121 * Since streams do buffered io similar to stdio, the caller can specify 122 * how big the send and receive buffers are via the second and third parms; 123 * 0 => use the system default. 124 */ 125SVCXPRT * 126svc_vc_create(fd, sendsize, recvsize) 127 int fd; 128 u_int sendsize; 129 u_int recvsize; 130{ 131 SVCXPRT *xprt; 132 struct cf_rendezvous *r = NULL; 133 struct __rpc_sockinfo si; 134 struct sockaddr_storage sslocal; 135 socklen_t slen; 136 int one = 1; 137 138 r = mem_alloc(sizeof(*r)); 139 if (r == NULL) { 140 warnx("svc_vc_create: out of memory"); 141 goto cleanup_svc_vc_create; 142 } 143 if (!__rpc_fd2sockinfo(fd, &si)) 144 return NULL; 145 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 146 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 147 xprt = mem_alloc(sizeof(SVCXPRT)); 148 if (xprt == NULL) { 149 warnx("svc_vc_create: out of memory"); 150 goto cleanup_svc_vc_create; 151 } 152 xprt->xp_tp = NULL; 153 xprt->xp_p1 = (caddr_t)(void *)r; 154 xprt->xp_p2 = NULL; 155 xprt->xp_p3 = NULL; 156 xprt->xp_verf = _null_auth; 157 svc_vc_rendezvous_ops(xprt); 158 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 159 xprt->xp_fd = fd; 160 161 slen = sizeof (struct sockaddr_storage); 162 if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 163 warnx("svc_vc_create: could not retrieve local addr"); 164 goto cleanup_svc_vc_create; 165 } 166 167 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 168 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 169 if (xprt->xp_ltaddr.buf == NULL) { 170 warnx("svc_vc_create: no mem for local addr"); 171 goto cleanup_svc_vc_create; 172 } 173 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 174 175 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 176 xprt_register(xprt); 177 return (xprt); 178cleanup_svc_vc_create: 179 if (r != NULL) 180 mem_free(r, sizeof(*r)); 181 return (NULL); 182} 183 184/* 185 * Like svtcp_create(), except the routine takes any *open* UNIX file 186 * descriptor as its first input. 187 */ 188SVCXPRT * 189svc_fd_create(fd, sendsize, recvsize) 190 int fd; 191 u_int sendsize; 192 u_int recvsize; 193{ 194 struct sockaddr_storage ss; 195 socklen_t slen; 196 SVCXPRT *ret; 197 198 assert(fd != -1); 199 200 ret = makefd_xprt(fd, sendsize, recvsize); 201 if (ret == NULL) 202 return NULL; 203 204 slen = sizeof (struct sockaddr_storage); 205 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 206 warnx("svc_fd_create: could not retrieve local addr"); 207 goto freedata; 208 } 209 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 210 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 211 if (ret->xp_ltaddr.buf == NULL) { 212 warnx("svc_fd_create: no mem for local addr"); 213 goto freedata; 214 } 215 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 216 217 slen = sizeof (struct sockaddr_storage); 218 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 219 warnx("svc_fd_create: could not retrieve remote addr"); 220 goto freedata; 221 } 222 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 223 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 224 if (ret->xp_rtaddr.buf == NULL) { 225 warnx("svc_fd_create: no mem for local addr"); 226 goto freedata; 227 } 228 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 229#ifdef PORTMAP 230 if (ss.ss_family == AF_INET) { 231 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 232 ret->xp_addrlen = sizeof (struct sockaddr_in); 233 } 234#endif /* PORTMAP */ 235 236 return ret; 237 238freedata: 239 if (ret->xp_ltaddr.buf != NULL) 240 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 241 242 return NULL; 243} 244 245static SVCXPRT * 246makefd_xprt(fd, sendsize, recvsize) 247 int fd; 248 u_int sendsize; 249 u_int recvsize; 250{ 251 SVCXPRT *xprt; 252 struct cf_conn *cd; 253 const char *netid; 254 struct __rpc_sockinfo si; 255 256 assert(fd != -1); 257 258 xprt = mem_alloc(sizeof(SVCXPRT)); 259 if (xprt == NULL) { 260 warnx("svc_vc: makefd_xprt: out of memory"); 261 goto done; 262 } 263 memset(xprt, 0, sizeof *xprt); 264 cd = mem_alloc(sizeof(struct cf_conn)); 265 if (cd == NULL) { 266 warnx("svc_tcp: makefd_xprt: out of memory"); 267 mem_free(xprt, sizeof(SVCXPRT)); 268 xprt = NULL; 269 goto done; 270 } 271 cd->strm_stat = XPRT_IDLE; 272 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 273 (caddr_t)(void *)xprt, read_vc, write_vc); 274 xprt->xp_p1 = (caddr_t)(void *)cd; 275 xprt->xp_verf.oa_base = cd->verf_body; 276 svc_vc_ops(xprt); /* truely deals with calls */ 277 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 278 xprt->xp_fd = fd; 279 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 280 xprt->xp_netid = strdup(netid); 281 282 xprt_register(xprt); 283done: 284 return (xprt); 285} 286 287/*ARGSUSED*/ 288static bool_t 289rendezvous_request(xprt, msg) 290 SVCXPRT *xprt; 291 struct rpc_msg *msg; 292{ 293 int sock; 294 struct cf_rendezvous *r; 295 struct sockaddr_storage addr; 296 socklen_t len; 297 struct __rpc_sockinfo si; 298 299 assert(xprt != NULL); 300 assert(msg != NULL); 301 302 r = (struct cf_rendezvous *)xprt->xp_p1; 303again: 304 len = sizeof addr; 305 if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 306 &len)) < 0) { 307 if (errno == EINTR) 308 goto again; 309 return (FALSE); 310 } 311 /* 312 * make a new transporter (re-uses xprt) 313 */ 314 xprt = makefd_xprt(sock, r->sendsize, r->recvsize); 315 xprt->xp_rtaddr.buf = mem_alloc(len); 316 if (xprt->xp_rtaddr.buf == NULL) 317 return (FALSE); 318 memcpy(xprt->xp_rtaddr.buf, &addr, len); 319 xprt->xp_rtaddr.len = len; 320#ifdef PORTMAP 321 if (addr.ss_family == AF_INET) { 322 xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf; 323 xprt->xp_addrlen = sizeof (struct sockaddr_in); 324 } 325#endif /* PORTMAP */ 326 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 327 len = 1; 328 /* XXX fvdl - is this useful? */ 329 _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 330 } 331 return (FALSE); /* there is never an rpc msg to be processed */ 332} 333 334/*ARGSUSED*/ 335static enum xprt_stat 336rendezvous_stat(xprt) 337 SVCXPRT *xprt; 338{ 339 340 return (XPRT_IDLE); 341} 342 343static void 344svc_vc_destroy(xprt) 345 SVCXPRT *xprt; 346{ 347 struct cf_conn *cd; 348 struct cf_rendezvous *r; 349 350 assert(xprt != NULL); 351 352 cd = (struct cf_conn *)xprt->xp_p1; 353 354 xprt_unregister(xprt); 355 if (xprt->xp_fd != RPC_ANYFD) 356 (void)_close(xprt->xp_fd); 357 if (xprt->xp_port != 0) { 358 /* a rendezvouser socket */ 359 r = (struct cf_rendezvous *)xprt->xp_p1; 360 mem_free(r, sizeof (struct cf_rendezvous)); 361 xprt->xp_port = 0; 362 } else { 363 /* an actual connection socket */ 364 XDR_DESTROY(&(cd->xdrs)); 365 mem_free(cd, sizeof(struct cf_conn)); 366 } 367 if (xprt->xp_rtaddr.buf) 368 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 369 if (xprt->xp_ltaddr.buf) 370 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 371 if (xprt->xp_tp) 372 free(xprt->xp_tp); 373 if (xprt->xp_netid) 374 free(xprt->xp_netid); 375 mem_free(xprt, sizeof(SVCXPRT)); 376} 377 378/*ARGSUSED*/ 379static bool_t 380svc_vc_control(xprt, rq, in) 381 SVCXPRT *xprt; 382 const u_int rq; 383 void *in; 384{ 385 return (FALSE); 386} 387 388/* 389 * reads data from the tcp or uip connection. 390 * any error is fatal and the connection is closed. 391 * (And a read of zero bytes is a half closed stream => error.) 392 * All read operations timeout after 35 seconds. A timeout is 393 * fatal for the connection. 394 */ 395static int 396read_vc(xprtp, buf, len) 397 caddr_t xprtp; 398 caddr_t buf; 399 int len; 400{ 401 SVCXPRT *xprt; 402 int sock; 403 int milliseconds = 35 * 1000; 404 struct pollfd pollfd; 405 struct sockaddr *sa; 406 struct cmessage *cm; 407 struct cmsghdr *cmp; 408 struct sockcred *sc; 409 410 xprt = (SVCXPRT *)(void *)xprtp; 411 assert(xprt != NULL); 412 413 sock = xprt->xp_fd; 414
|
432 433 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 434 if (sa->sa_family == AF_LOCAL) { 435 if ((len = __msgread(sock, buf, len)) > 0) { 436 cm = (struct cmessage *)xprt->xp_verf.oa_base; 437 cmp = &cm->cmsg; 438 sc = (struct sockcred *)(void *)CMSG_DATA(cmp); 439 xprt->xp_p2 = sc; 440 return (len); 441 } 442 } else { 443 if ((len = _read(sock, buf, (size_t)len)) > 0) 444 return (len); 445 } 446 447fatal_err: 448 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 449 return (-1); 450} 451 452/* 453 * writes data to the tcp connection. 454 * Any error is fatal and the connection is closed. 455 */ 456static int 457write_vc(xprtp, buf, len) 458 caddr_t xprtp; 459 caddr_t buf; 460 int len; 461{ 462 SVCXPRT *xprt; 463 int i, cnt; 464 struct sockaddr *sa; 465 466 xprt = (SVCXPRT *)(void *)xprtp; 467 assert(xprt != NULL); 468 469 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 470 if (sa->sa_family == AF_LOCAL) { 471 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 472 if ((i = __msgwrite(xprt->xp_fd, buf, 473 (size_t)cnt)) < 0) { 474 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 475 XPRT_DIED; 476 return (-1); 477 } 478 } 479 } else { 480 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 481 if ((i = _write(xprt->xp_fd, buf, 482 (size_t)cnt)) < 0) { 483 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 484 XPRT_DIED; 485 return (-1); 486 } 487 } 488 } 489 490 return (len); 491} 492 493static enum xprt_stat 494svc_vc_stat(xprt) 495 SVCXPRT *xprt; 496{ 497 struct cf_conn *cd; 498 499 assert(xprt != NULL); 500 501 cd = (struct cf_conn *)(xprt->xp_p1); 502 503 if (cd->strm_stat == XPRT_DIED) 504 return (XPRT_DIED); 505 if (! xdrrec_eof(&(cd->xdrs))) 506 return (XPRT_MOREREQS); 507 return (XPRT_IDLE); 508} 509 510static bool_t 511svc_vc_recv(xprt, msg) 512 SVCXPRT *xprt; 513 struct rpc_msg *msg; 514{ 515 struct cf_conn *cd; 516 XDR *xdrs; 517 518 assert(xprt != NULL); 519 assert(msg != NULL); 520 521 cd = (struct cf_conn *)(xprt->xp_p1); 522 xdrs = &(cd->xdrs); 523 524 xdrs->x_op = XDR_DECODE; 525 (void)xdrrec_skiprecord(xdrs); 526 if (xdr_callmsg(xdrs, msg)) { 527 cd->x_id = msg->rm_xid; 528 return (TRUE); 529 } 530 cd->strm_stat = XPRT_DIED; 531 return (FALSE); 532} 533 534static bool_t 535svc_vc_getargs(xprt, xdr_args, args_ptr) 536 SVCXPRT *xprt; 537 xdrproc_t xdr_args; 538 caddr_t args_ptr; 539{ 540 541 assert(xprt != NULL); 542 /* args_ptr may be NULL */ 543 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 544 args_ptr)); 545} 546 547static bool_t 548svc_vc_freeargs(xprt, xdr_args, args_ptr) 549 SVCXPRT *xprt; 550 xdrproc_t xdr_args; 551 caddr_t args_ptr; 552{ 553 XDR *xdrs; 554 555 assert(xprt != NULL); 556 /* args_ptr may be NULL */ 557 558 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 559 560 xdrs->x_op = XDR_FREE; 561 return ((*xdr_args)(xdrs, args_ptr)); 562} 563 564static bool_t 565svc_vc_reply(xprt, msg) 566 SVCXPRT *xprt; 567 struct rpc_msg *msg; 568{ 569 struct cf_conn *cd; 570 XDR *xdrs; 571 bool_t stat; 572 573 assert(xprt != NULL); 574 assert(msg != NULL); 575 576 cd = (struct cf_conn *)(xprt->xp_p1); 577 xdrs = &(cd->xdrs); 578 579 xdrs->x_op = XDR_ENCODE; 580 msg->rm_xid = cd->x_id; 581 stat = xdr_replymsg(xdrs, msg); 582 (void)xdrrec_endofrecord(xdrs, TRUE); 583 return (stat); 584} 585 586static void 587svc_vc_ops(xprt) 588 SVCXPRT *xprt; 589{ 590 static struct xp_ops ops; 591 static struct xp_ops2 ops2; 592 extern mutex_t ops_lock; 593 594/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 595 596 mutex_lock(&ops_lock); 597 if (ops.xp_recv == NULL) { 598 ops.xp_recv = svc_vc_recv; 599 ops.xp_stat = svc_vc_stat; 600 ops.xp_getargs = svc_vc_getargs; 601 ops.xp_reply = svc_vc_reply; 602 ops.xp_freeargs = svc_vc_freeargs; 603 ops.xp_destroy = svc_vc_destroy; 604 ops2.xp_control = svc_vc_control; 605 } 606 xprt->xp_ops = &ops; 607 xprt->xp_ops2 = &ops2; 608 mutex_unlock(&ops_lock); 609} 610 611static void 612svc_vc_rendezvous_ops(xprt) 613 SVCXPRT *xprt; 614{ 615 static struct xp_ops ops; 616 static struct xp_ops2 ops2; 617 extern mutex_t ops_lock; 618 619 mutex_lock(&ops_lock); 620 if (ops.xp_recv == NULL) { 621 ops.xp_recv = rendezvous_request; 622 ops.xp_stat = rendezvous_stat; 623 ops.xp_getargs = 624 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort; 625 ops.xp_reply = 626 (bool_t (*) __P((SVCXPRT *, struct rpc_msg *)))abort; 627 ops.xp_freeargs = 628 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort, 629 ops.xp_destroy = svc_vc_destroy; 630 ops2.xp_control = svc_vc_control; 631 } 632 xprt->xp_ops = &ops; 633 xprt->xp_ops2 = &ops2; 634 mutex_unlock(&ops_lock); 635} 636 637static int 638__msgread(sock, buf, cnt) 639 int sock; 640 void *buf; 641 size_t cnt; 642{ 643 struct iovec iov[1]; 644 struct msghdr msg; 645 struct cmessage cm; 646 647 bzero((char *)&cm, sizeof(cm)); 648 iov[0].iov_base = buf; 649 iov[0].iov_len = cnt; 650 651 msg.msg_iov = iov; 652 msg.msg_iovlen = 1; 653 msg.msg_name = NULL; 654 msg.msg_namelen = 0; 655 msg.msg_control = (caddr_t)&cm; 656 msg.msg_controllen = sizeof(struct cmessage); 657 msg.msg_flags = 0; 658 659 return(_recvmsg(sock, &msg, 0)); 660} 661 662static int 663__msgwrite(sock, buf, cnt) 664 int sock; 665 void *buf; 666 size_t cnt; 667{ 668 struct iovec iov[1]; 669 struct msghdr msg; 670 struct cmessage cm; 671 672 bzero((char *)&cm, sizeof(cm)); 673 iov[0].iov_base = buf; 674 iov[0].iov_len = cnt; 675 676 cm.cmsg.cmsg_type = SCM_CREDS; 677 cm.cmsg.cmsg_level = SOL_SOCKET; 678 cm.cmsg.cmsg_len = sizeof(struct cmessage); 679 680 msg.msg_iov = iov; 681 msg.msg_iovlen = 1; 682 msg.msg_name = NULL; 683 msg.msg_namelen = 0; 684 msg.msg_control = (caddr_t)&cm; 685 msg.msg_controllen = sizeof(struct cmessage); 686 msg.msg_flags = 0; 687 688 return(_sendmsg(sock, &msg, 0)); 689}
| 430 431 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 432 if (sa->sa_family == AF_LOCAL) { 433 if ((len = __msgread(sock, buf, len)) > 0) { 434 cm = (struct cmessage *)xprt->xp_verf.oa_base; 435 cmp = &cm->cmsg; 436 sc = (struct sockcred *)(void *)CMSG_DATA(cmp); 437 xprt->xp_p2 = sc; 438 return (len); 439 } 440 } else { 441 if ((len = _read(sock, buf, (size_t)len)) > 0) 442 return (len); 443 } 444 445fatal_err: 446 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 447 return (-1); 448} 449 450/* 451 * writes data to the tcp connection. 452 * Any error is fatal and the connection is closed. 453 */ 454static int 455write_vc(xprtp, buf, len) 456 caddr_t xprtp; 457 caddr_t buf; 458 int len; 459{ 460 SVCXPRT *xprt; 461 int i, cnt; 462 struct sockaddr *sa; 463 464 xprt = (SVCXPRT *)(void *)xprtp; 465 assert(xprt != NULL); 466 467 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 468 if (sa->sa_family == AF_LOCAL) { 469 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 470 if ((i = __msgwrite(xprt->xp_fd, buf, 471 (size_t)cnt)) < 0) { 472 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 473 XPRT_DIED; 474 return (-1); 475 } 476 } 477 } else { 478 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 479 if ((i = _write(xprt->xp_fd, buf, 480 (size_t)cnt)) < 0) { 481 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 482 XPRT_DIED; 483 return (-1); 484 } 485 } 486 } 487 488 return (len); 489} 490 491static enum xprt_stat 492svc_vc_stat(xprt) 493 SVCXPRT *xprt; 494{ 495 struct cf_conn *cd; 496 497 assert(xprt != NULL); 498 499 cd = (struct cf_conn *)(xprt->xp_p1); 500 501 if (cd->strm_stat == XPRT_DIED) 502 return (XPRT_DIED); 503 if (! xdrrec_eof(&(cd->xdrs))) 504 return (XPRT_MOREREQS); 505 return (XPRT_IDLE); 506} 507 508static bool_t 509svc_vc_recv(xprt, msg) 510 SVCXPRT *xprt; 511 struct rpc_msg *msg; 512{ 513 struct cf_conn *cd; 514 XDR *xdrs; 515 516 assert(xprt != NULL); 517 assert(msg != NULL); 518 519 cd = (struct cf_conn *)(xprt->xp_p1); 520 xdrs = &(cd->xdrs); 521 522 xdrs->x_op = XDR_DECODE; 523 (void)xdrrec_skiprecord(xdrs); 524 if (xdr_callmsg(xdrs, msg)) { 525 cd->x_id = msg->rm_xid; 526 return (TRUE); 527 } 528 cd->strm_stat = XPRT_DIED; 529 return (FALSE); 530} 531 532static bool_t 533svc_vc_getargs(xprt, xdr_args, args_ptr) 534 SVCXPRT *xprt; 535 xdrproc_t xdr_args; 536 caddr_t args_ptr; 537{ 538 539 assert(xprt != NULL); 540 /* args_ptr may be NULL */ 541 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 542 args_ptr)); 543} 544 545static bool_t 546svc_vc_freeargs(xprt, xdr_args, args_ptr) 547 SVCXPRT *xprt; 548 xdrproc_t xdr_args; 549 caddr_t args_ptr; 550{ 551 XDR *xdrs; 552 553 assert(xprt != NULL); 554 /* args_ptr may be NULL */ 555 556 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 557 558 xdrs->x_op = XDR_FREE; 559 return ((*xdr_args)(xdrs, args_ptr)); 560} 561 562static bool_t 563svc_vc_reply(xprt, msg) 564 SVCXPRT *xprt; 565 struct rpc_msg *msg; 566{ 567 struct cf_conn *cd; 568 XDR *xdrs; 569 bool_t stat; 570 571 assert(xprt != NULL); 572 assert(msg != NULL); 573 574 cd = (struct cf_conn *)(xprt->xp_p1); 575 xdrs = &(cd->xdrs); 576 577 xdrs->x_op = XDR_ENCODE; 578 msg->rm_xid = cd->x_id; 579 stat = xdr_replymsg(xdrs, msg); 580 (void)xdrrec_endofrecord(xdrs, TRUE); 581 return (stat); 582} 583 584static void 585svc_vc_ops(xprt) 586 SVCXPRT *xprt; 587{ 588 static struct xp_ops ops; 589 static struct xp_ops2 ops2; 590 extern mutex_t ops_lock; 591 592/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 593 594 mutex_lock(&ops_lock); 595 if (ops.xp_recv == NULL) { 596 ops.xp_recv = svc_vc_recv; 597 ops.xp_stat = svc_vc_stat; 598 ops.xp_getargs = svc_vc_getargs; 599 ops.xp_reply = svc_vc_reply; 600 ops.xp_freeargs = svc_vc_freeargs; 601 ops.xp_destroy = svc_vc_destroy; 602 ops2.xp_control = svc_vc_control; 603 } 604 xprt->xp_ops = &ops; 605 xprt->xp_ops2 = &ops2; 606 mutex_unlock(&ops_lock); 607} 608 609static void 610svc_vc_rendezvous_ops(xprt) 611 SVCXPRT *xprt; 612{ 613 static struct xp_ops ops; 614 static struct xp_ops2 ops2; 615 extern mutex_t ops_lock; 616 617 mutex_lock(&ops_lock); 618 if (ops.xp_recv == NULL) { 619 ops.xp_recv = rendezvous_request; 620 ops.xp_stat = rendezvous_stat; 621 ops.xp_getargs = 622 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort; 623 ops.xp_reply = 624 (bool_t (*) __P((SVCXPRT *, struct rpc_msg *)))abort; 625 ops.xp_freeargs = 626 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort, 627 ops.xp_destroy = svc_vc_destroy; 628 ops2.xp_control = svc_vc_control; 629 } 630 xprt->xp_ops = &ops; 631 xprt->xp_ops2 = &ops2; 632 mutex_unlock(&ops_lock); 633} 634 635static int 636__msgread(sock, buf, cnt) 637 int sock; 638 void *buf; 639 size_t cnt; 640{ 641 struct iovec iov[1]; 642 struct msghdr msg; 643 struct cmessage cm; 644 645 bzero((char *)&cm, sizeof(cm)); 646 iov[0].iov_base = buf; 647 iov[0].iov_len = cnt; 648 649 msg.msg_iov = iov; 650 msg.msg_iovlen = 1; 651 msg.msg_name = NULL; 652 msg.msg_namelen = 0; 653 msg.msg_control = (caddr_t)&cm; 654 msg.msg_controllen = sizeof(struct cmessage); 655 msg.msg_flags = 0; 656 657 return(_recvmsg(sock, &msg, 0)); 658} 659 660static int 661__msgwrite(sock, buf, cnt) 662 int sock; 663 void *buf; 664 size_t cnt; 665{ 666 struct iovec iov[1]; 667 struct msghdr msg; 668 struct cmessage cm; 669 670 bzero((char *)&cm, sizeof(cm)); 671 iov[0].iov_base = buf; 672 iov[0].iov_len = cnt; 673 674 cm.cmsg.cmsg_type = SCM_CREDS; 675 cm.cmsg.cmsg_level = SOL_SOCKET; 676 cm.cmsg.cmsg_len = sizeof(struct cmessage); 677 678 msg.msg_iov = iov; 679 msg.msg_iovlen = 1; 680 msg.msg_name = NULL; 681 msg.msg_namelen = 0; 682 msg.msg_control = (caddr_t)&cm; 683 msg.msg_controllen = sizeof(struct cmessage); 684 msg.msg_flags = 0; 685 686 return(_sendmsg(sock, &msg, 0)); 687}
|