1/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32#if defined(LIBC_SCCS) && !defined(lint) 33static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 34static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 35#endif 36#include <sys/cdefs.h>
| 1/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32#if defined(LIBC_SCCS) && !defined(lint) 33static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 34static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 35#endif 36#include <sys/cdefs.h>
|
37__FBSDID("$FreeBSD: head/lib/libc/rpc/svc_vc.c 115394 2003-05-29 22:06:06Z mbr $");
| 37__FBSDID("$FreeBSD: head/lib/libc/rpc/svc_vc.c 116391 2003-06-15 10:32:01Z mbr $");
|
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 "namespace.h" 48#include "reentrant.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/time.h> 55#include <sys/uio.h> 56#include <netinet/in.h> 57#include <netinet/tcp.h> 58 59#include <assert.h> 60#include <err.h> 61#include <errno.h> 62#include <fcntl.h> 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <unistd.h> 67 68#include <rpc/rpc.h> 69 70#include "rpc_com.h" 71#include "un-namespace.h" 72
| 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 "namespace.h" 48#include "reentrant.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/time.h> 55#include <sys/uio.h> 56#include <netinet/in.h> 57#include <netinet/tcp.h> 58 59#include <assert.h> 60#include <err.h> 61#include <errno.h> 62#include <fcntl.h> 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <unistd.h> 67 68#include <rpc/rpc.h> 69 70#include "rpc_com.h" 71#include "un-namespace.h" 72
|
73struct cmessage { 74 struct cmsghdr cmsg; 75 struct cmsgcred cmcred; 76}; 77
| |
78extern rwlock_t svc_fd_lock; 79 80static SVCXPRT *makefd_xprt(int, u_int, u_int); 81static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); 82static enum xprt_stat rendezvous_stat(SVCXPRT *); 83static void svc_vc_destroy(SVCXPRT *); 84static void __svc_vc_dodestroy (SVCXPRT *); 85static int read_vc(void *, void *, int); 86static int write_vc(void *, void *, int); 87static enum xprt_stat svc_vc_stat(SVCXPRT *); 88static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); 89static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *); 90static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *); 91static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); 92static void svc_vc_rendezvous_ops(SVCXPRT *); 93static void svc_vc_ops(SVCXPRT *); 94static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); 95static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq, 96 void *in);
| 73extern rwlock_t svc_fd_lock; 74 75static SVCXPRT *makefd_xprt(int, u_int, u_int); 76static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); 77static enum xprt_stat rendezvous_stat(SVCXPRT *); 78static void svc_vc_destroy(SVCXPRT *); 79static void __svc_vc_dodestroy (SVCXPRT *); 80static int read_vc(void *, void *, int); 81static int write_vc(void *, void *, int); 82static enum xprt_stat svc_vc_stat(SVCXPRT *); 83static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); 84static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *); 85static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *); 86static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); 87static void svc_vc_rendezvous_ops(SVCXPRT *); 88static void svc_vc_ops(SVCXPRT *); 89static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); 90static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq, 91 void *in);
|
97static int __msgread_withcred(int, void *, size_t, struct cmessage *);
| |
98static int __msgwrite(int, void *, size_t); 99 100struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 101 u_int sendsize; 102 u_int recvsize; 103 int maxrec; 104}; 105 106struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 107 enum xprt_stat strm_stat; 108 u_int32_t x_id; 109 XDR xdrs; 110 char verf_body[MAX_AUTH_BYTES]; 111 u_int sendsize; 112 u_int recvsize; 113 int maxrec; 114 bool_t nonblock; 115 struct timeval last_recv_time; 116}; 117 118/* 119 * Usage: 120 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 121 * 122 * Creates, registers, and returns a (rpc) tcp based transporter. 123 * Once *xprt is initialized, it is registered as a transporter 124 * see (svc.h, xprt_register). This routine returns 125 * a NULL if a problem occurred. 126 * 127 * The filedescriptor passed in is expected to refer to a bound, but 128 * not yet connected socket. 129 * 130 * Since streams do buffered io similar to stdio, the caller can specify 131 * how big the send and receive buffers are via the second and third parms; 132 * 0 => use the system default. 133 */ 134SVCXPRT * 135svc_vc_create(fd, sendsize, recvsize) 136 int fd; 137 u_int sendsize; 138 u_int recvsize; 139{ 140 SVCXPRT *xprt; 141 struct cf_rendezvous *r = NULL; 142 struct __rpc_sockinfo si; 143 struct sockaddr_storage sslocal; 144 socklen_t slen; 145 146 r = mem_alloc(sizeof(*r)); 147 if (r == NULL) { 148 warnx("svc_vc_create: out of memory"); 149 goto cleanup_svc_vc_create; 150 } 151 if (!__rpc_fd2sockinfo(fd, &si)) 152 return NULL; 153 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 154 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 155 r->maxrec = __svc_maxrec; 156 xprt = mem_alloc(sizeof(SVCXPRT)); 157 if (xprt == NULL) { 158 warnx("svc_vc_create: out of memory"); 159 goto cleanup_svc_vc_create; 160 } 161 xprt->xp_tp = NULL; 162 xprt->xp_p1 = r; 163 xprt->xp_p2 = NULL; 164 xprt->xp_p3 = NULL; 165 xprt->xp_verf = _null_auth; 166 svc_vc_rendezvous_ops(xprt); 167 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 168 xprt->xp_fd = fd; 169 170 slen = sizeof (struct sockaddr_storage); 171 if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 172 warnx("svc_vc_create: could not retrieve local addr"); 173 goto cleanup_svc_vc_create; 174 } 175 176 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 177 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 178 if (xprt->xp_ltaddr.buf == NULL) { 179 warnx("svc_vc_create: no mem for local addr"); 180 goto cleanup_svc_vc_create; 181 } 182 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 183 184 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 185 xprt_register(xprt); 186 return (xprt); 187cleanup_svc_vc_create: 188 if (r != NULL) 189 mem_free(r, sizeof(*r)); 190 return (NULL); 191} 192 193/* 194 * Like svtcp_create(), except the routine takes any *open* UNIX file 195 * descriptor as its first input. 196 */ 197SVCXPRT * 198svc_fd_create(fd, sendsize, recvsize) 199 int fd; 200 u_int sendsize; 201 u_int recvsize; 202{ 203 struct sockaddr_storage ss; 204 socklen_t slen; 205 SVCXPRT *ret; 206 207 assert(fd != -1); 208 209 ret = makefd_xprt(fd, sendsize, recvsize); 210 if (ret == NULL) 211 return NULL; 212 213 slen = sizeof (struct sockaddr_storage); 214 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 215 warnx("svc_fd_create: could not retrieve local addr"); 216 goto freedata; 217 } 218 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 219 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 220 if (ret->xp_ltaddr.buf == NULL) { 221 warnx("svc_fd_create: no mem for local addr"); 222 goto freedata; 223 } 224 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 225 226 slen = sizeof (struct sockaddr_storage); 227 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 228 warnx("svc_fd_create: could not retrieve remote addr"); 229 goto freedata; 230 } 231 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 232 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 233 if (ret->xp_rtaddr.buf == NULL) { 234 warnx("svc_fd_create: no mem for local addr"); 235 goto freedata; 236 } 237 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 238#ifdef PORTMAP 239 if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) { 240 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 241 ret->xp_addrlen = sizeof (struct sockaddr_in); 242 } 243#endif /* PORTMAP */ 244 245 return ret; 246 247freedata: 248 if (ret->xp_ltaddr.buf != NULL) 249 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 250 251 return NULL; 252} 253 254static SVCXPRT * 255makefd_xprt(fd, sendsize, recvsize) 256 int fd; 257 u_int sendsize; 258 u_int recvsize; 259{ 260 SVCXPRT *xprt; 261 struct cf_conn *cd; 262 const char *netid; 263 struct __rpc_sockinfo si; 264 265 assert(fd != -1); 266 267 xprt = mem_alloc(sizeof(SVCXPRT)); 268 if (xprt == NULL) { 269 warnx("svc_vc: makefd_xprt: out of memory"); 270 goto done; 271 } 272 memset(xprt, 0, sizeof *xprt); 273 cd = mem_alloc(sizeof(struct cf_conn)); 274 if (cd == NULL) { 275 warnx("svc_tcp: makefd_xprt: out of memory"); 276 mem_free(xprt, sizeof(SVCXPRT)); 277 xprt = NULL; 278 goto done; 279 } 280 cd->strm_stat = XPRT_IDLE; 281 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 282 xprt, read_vc, write_vc); 283 xprt->xp_p1 = cd; 284 xprt->xp_verf.oa_base = cd->verf_body; 285 svc_vc_ops(xprt); /* truely deals with calls */ 286 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 287 xprt->xp_fd = fd; 288 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 289 xprt->xp_netid = strdup(netid); 290 291 xprt_register(xprt); 292done: 293 return (xprt); 294} 295 296/*ARGSUSED*/ 297static bool_t 298rendezvous_request(xprt, msg) 299 SVCXPRT *xprt; 300 struct rpc_msg *msg; 301{ 302 int sock, flags; 303 struct cf_rendezvous *r; 304 struct cf_conn *cd; 305 struct sockaddr_storage addr; 306 socklen_t len; 307 struct __rpc_sockinfo si; 308 SVCXPRT *newxprt; 309 fd_set cleanfds; 310 311 assert(xprt != NULL); 312 assert(msg != NULL); 313 314 r = (struct cf_rendezvous *)xprt->xp_p1; 315again: 316 len = sizeof addr; 317 if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 318 &len)) < 0) { 319 if (errno == EINTR) 320 goto again; 321 /* 322 * Clean out the most idle file descriptor when we're 323 * running out. 324 */ 325 if (errno == EMFILE || errno == ENFILE) { 326 cleanfds = svc_fdset; 327 __svc_clean_idle(&cleanfds, 0, FALSE); 328 goto again; 329 } 330 return (FALSE); 331 } 332 /* 333 * make a new transporter (re-uses xprt) 334 */ 335 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); 336 newxprt->xp_rtaddr.buf = mem_alloc(len); 337 if (newxprt->xp_rtaddr.buf == NULL) 338 return (FALSE); 339 memcpy(newxprt->xp_rtaddr.buf, &addr, len); 340 newxprt->xp_rtaddr.len = len; 341#ifdef PORTMAP 342 if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) { 343 newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf; 344 newxprt->xp_addrlen = sizeof (struct sockaddr_in); 345 } 346#endif /* PORTMAP */ 347 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 348 len = 1; 349 /* XXX fvdl - is this useful? */ 350 _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 351 } 352 353 cd = (struct cf_conn *)newxprt->xp_p1; 354 355 cd->recvsize = r->recvsize; 356 cd->sendsize = r->sendsize; 357 cd->maxrec = r->maxrec; 358 359 if (cd->maxrec != 0) { 360 flags = _fcntl(sock, F_GETFL, 0); 361 if (flags == -1) 362 return (FALSE); 363 if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) 364 return (FALSE); 365 if (cd->recvsize > cd->maxrec) 366 cd->recvsize = cd->maxrec; 367 cd->nonblock = TRUE; 368 __xdrrec_setnonblock(&cd->xdrs, cd->maxrec); 369 } else 370 cd->nonblock = FALSE; 371 372 gettimeofday(&cd->last_recv_time, NULL); 373 374 return (FALSE); /* there is never an rpc msg to be processed */ 375} 376 377/*ARGSUSED*/ 378static enum xprt_stat 379rendezvous_stat(xprt) 380 SVCXPRT *xprt; 381{ 382 383 return (XPRT_IDLE); 384} 385 386static void 387svc_vc_destroy(xprt) 388 SVCXPRT *xprt; 389{ 390 assert(xprt != NULL); 391 392 xprt_unregister(xprt); 393 __svc_vc_dodestroy(xprt); 394} 395 396static void 397__svc_vc_dodestroy(xprt) 398 SVCXPRT *xprt; 399{ 400 struct cf_conn *cd; 401 struct cf_rendezvous *r; 402 403 cd = (struct cf_conn *)xprt->xp_p1; 404 405 if (xprt->xp_fd != RPC_ANYFD) 406 (void)_close(xprt->xp_fd); 407 if (xprt->xp_port != 0) { 408 /* a rendezvouser socket */ 409 r = (struct cf_rendezvous *)xprt->xp_p1; 410 mem_free(r, sizeof (struct cf_rendezvous)); 411 xprt->xp_port = 0; 412 } else { 413 /* an actual connection socket */ 414 XDR_DESTROY(&(cd->xdrs)); 415 mem_free(cd, sizeof(struct cf_conn)); 416 } 417 if (xprt->xp_rtaddr.buf) 418 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 419 if (xprt->xp_ltaddr.buf) 420 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 421 if (xprt->xp_tp) 422 free(xprt->xp_tp); 423 if (xprt->xp_netid) 424 free(xprt->xp_netid); 425 mem_free(xprt, sizeof(SVCXPRT)); 426} 427 428/*ARGSUSED*/ 429static bool_t 430svc_vc_control(xprt, rq, in) 431 SVCXPRT *xprt; 432 const u_int rq; 433 void *in; 434{ 435 return (FALSE); 436} 437 438static bool_t 439svc_vc_rendezvous_control(xprt, rq, in) 440 SVCXPRT *xprt; 441 const u_int rq; 442 void *in; 443{ 444 struct cf_rendezvous *cfp; 445 446 cfp = (struct cf_rendezvous *)xprt->xp_p1; 447 if (cfp == NULL) 448 return (FALSE); 449 switch (rq) { 450 case SVCGET_CONNMAXREC: 451 *(int *)in = cfp->maxrec; 452 break; 453 case SVCSET_CONNMAXREC: 454 cfp->maxrec = *(int *)in; 455 break; 456 default: 457 return (FALSE); 458 } 459 return (TRUE); 460} 461 462/* 463 * reads data from the tcp or uip connection. 464 * any error is fatal and the connection is closed. 465 * (And a read of zero bytes is a half closed stream => error.) 466 * All read operations timeout after 35 seconds. A timeout is 467 * fatal for the connection. 468 */ 469static int 470read_vc(xprtp, buf, len) 471 void *xprtp; 472 void *buf; 473 int len; 474{ 475 SVCXPRT *xprt; 476 int sock; 477 int milliseconds = 35 * 1000; 478 struct pollfd pollfd;
| 92static int __msgwrite(int, void *, size_t); 93 94struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 95 u_int sendsize; 96 u_int recvsize; 97 int maxrec; 98}; 99 100struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 101 enum xprt_stat strm_stat; 102 u_int32_t x_id; 103 XDR xdrs; 104 char verf_body[MAX_AUTH_BYTES]; 105 u_int sendsize; 106 u_int recvsize; 107 int maxrec; 108 bool_t nonblock; 109 struct timeval last_recv_time; 110}; 111 112/* 113 * Usage: 114 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 115 * 116 * Creates, registers, and returns a (rpc) tcp based transporter. 117 * Once *xprt is initialized, it is registered as a transporter 118 * see (svc.h, xprt_register). This routine returns 119 * a NULL if a problem occurred. 120 * 121 * The filedescriptor passed in is expected to refer to a bound, but 122 * not yet connected socket. 123 * 124 * Since streams do buffered io similar to stdio, the caller can specify 125 * how big the send and receive buffers are via the second and third parms; 126 * 0 => use the system default. 127 */ 128SVCXPRT * 129svc_vc_create(fd, sendsize, recvsize) 130 int fd; 131 u_int sendsize; 132 u_int recvsize; 133{ 134 SVCXPRT *xprt; 135 struct cf_rendezvous *r = NULL; 136 struct __rpc_sockinfo si; 137 struct sockaddr_storage sslocal; 138 socklen_t slen; 139 140 r = mem_alloc(sizeof(*r)); 141 if (r == NULL) { 142 warnx("svc_vc_create: out of memory"); 143 goto cleanup_svc_vc_create; 144 } 145 if (!__rpc_fd2sockinfo(fd, &si)) 146 return NULL; 147 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 148 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 149 r->maxrec = __svc_maxrec; 150 xprt = mem_alloc(sizeof(SVCXPRT)); 151 if (xprt == NULL) { 152 warnx("svc_vc_create: out of memory"); 153 goto cleanup_svc_vc_create; 154 } 155 xprt->xp_tp = NULL; 156 xprt->xp_p1 = r; 157 xprt->xp_p2 = NULL; 158 xprt->xp_p3 = NULL; 159 xprt->xp_verf = _null_auth; 160 svc_vc_rendezvous_ops(xprt); 161 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 162 xprt->xp_fd = fd; 163 164 slen = sizeof (struct sockaddr_storage); 165 if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 166 warnx("svc_vc_create: could not retrieve local addr"); 167 goto cleanup_svc_vc_create; 168 } 169 170 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 171 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 172 if (xprt->xp_ltaddr.buf == NULL) { 173 warnx("svc_vc_create: no mem for local addr"); 174 goto cleanup_svc_vc_create; 175 } 176 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 177 178 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 179 xprt_register(xprt); 180 return (xprt); 181cleanup_svc_vc_create: 182 if (r != NULL) 183 mem_free(r, sizeof(*r)); 184 return (NULL); 185} 186 187/* 188 * Like svtcp_create(), except the routine takes any *open* UNIX file 189 * descriptor as its first input. 190 */ 191SVCXPRT * 192svc_fd_create(fd, sendsize, recvsize) 193 int fd; 194 u_int sendsize; 195 u_int recvsize; 196{ 197 struct sockaddr_storage ss; 198 socklen_t slen; 199 SVCXPRT *ret; 200 201 assert(fd != -1); 202 203 ret = makefd_xprt(fd, sendsize, recvsize); 204 if (ret == NULL) 205 return NULL; 206 207 slen = sizeof (struct sockaddr_storage); 208 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 209 warnx("svc_fd_create: could not retrieve local addr"); 210 goto freedata; 211 } 212 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 213 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 214 if (ret->xp_ltaddr.buf == NULL) { 215 warnx("svc_fd_create: no mem for local addr"); 216 goto freedata; 217 } 218 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 219 220 slen = sizeof (struct sockaddr_storage); 221 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 222 warnx("svc_fd_create: could not retrieve remote addr"); 223 goto freedata; 224 } 225 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 226 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 227 if (ret->xp_rtaddr.buf == NULL) { 228 warnx("svc_fd_create: no mem for local addr"); 229 goto freedata; 230 } 231 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 232#ifdef PORTMAP 233 if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) { 234 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 235 ret->xp_addrlen = sizeof (struct sockaddr_in); 236 } 237#endif /* PORTMAP */ 238 239 return ret; 240 241freedata: 242 if (ret->xp_ltaddr.buf != NULL) 243 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 244 245 return NULL; 246} 247 248static SVCXPRT * 249makefd_xprt(fd, sendsize, recvsize) 250 int fd; 251 u_int sendsize; 252 u_int recvsize; 253{ 254 SVCXPRT *xprt; 255 struct cf_conn *cd; 256 const char *netid; 257 struct __rpc_sockinfo si; 258 259 assert(fd != -1); 260 261 xprt = mem_alloc(sizeof(SVCXPRT)); 262 if (xprt == NULL) { 263 warnx("svc_vc: makefd_xprt: out of memory"); 264 goto done; 265 } 266 memset(xprt, 0, sizeof *xprt); 267 cd = mem_alloc(sizeof(struct cf_conn)); 268 if (cd == NULL) { 269 warnx("svc_tcp: makefd_xprt: out of memory"); 270 mem_free(xprt, sizeof(SVCXPRT)); 271 xprt = NULL; 272 goto done; 273 } 274 cd->strm_stat = XPRT_IDLE; 275 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 276 xprt, read_vc, write_vc); 277 xprt->xp_p1 = cd; 278 xprt->xp_verf.oa_base = cd->verf_body; 279 svc_vc_ops(xprt); /* truely deals with calls */ 280 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 281 xprt->xp_fd = fd; 282 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 283 xprt->xp_netid = strdup(netid); 284 285 xprt_register(xprt); 286done: 287 return (xprt); 288} 289 290/*ARGSUSED*/ 291static bool_t 292rendezvous_request(xprt, msg) 293 SVCXPRT *xprt; 294 struct rpc_msg *msg; 295{ 296 int sock, flags; 297 struct cf_rendezvous *r; 298 struct cf_conn *cd; 299 struct sockaddr_storage addr; 300 socklen_t len; 301 struct __rpc_sockinfo si; 302 SVCXPRT *newxprt; 303 fd_set cleanfds; 304 305 assert(xprt != NULL); 306 assert(msg != NULL); 307 308 r = (struct cf_rendezvous *)xprt->xp_p1; 309again: 310 len = sizeof addr; 311 if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 312 &len)) < 0) { 313 if (errno == EINTR) 314 goto again; 315 /* 316 * Clean out the most idle file descriptor when we're 317 * running out. 318 */ 319 if (errno == EMFILE || errno == ENFILE) { 320 cleanfds = svc_fdset; 321 __svc_clean_idle(&cleanfds, 0, FALSE); 322 goto again; 323 } 324 return (FALSE); 325 } 326 /* 327 * make a new transporter (re-uses xprt) 328 */ 329 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); 330 newxprt->xp_rtaddr.buf = mem_alloc(len); 331 if (newxprt->xp_rtaddr.buf == NULL) 332 return (FALSE); 333 memcpy(newxprt->xp_rtaddr.buf, &addr, len); 334 newxprt->xp_rtaddr.len = len; 335#ifdef PORTMAP 336 if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) { 337 newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf; 338 newxprt->xp_addrlen = sizeof (struct sockaddr_in); 339 } 340#endif /* PORTMAP */ 341 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 342 len = 1; 343 /* XXX fvdl - is this useful? */ 344 _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 345 } 346 347 cd = (struct cf_conn *)newxprt->xp_p1; 348 349 cd->recvsize = r->recvsize; 350 cd->sendsize = r->sendsize; 351 cd->maxrec = r->maxrec; 352 353 if (cd->maxrec != 0) { 354 flags = _fcntl(sock, F_GETFL, 0); 355 if (flags == -1) 356 return (FALSE); 357 if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) 358 return (FALSE); 359 if (cd->recvsize > cd->maxrec) 360 cd->recvsize = cd->maxrec; 361 cd->nonblock = TRUE; 362 __xdrrec_setnonblock(&cd->xdrs, cd->maxrec); 363 } else 364 cd->nonblock = FALSE; 365 366 gettimeofday(&cd->last_recv_time, NULL); 367 368 return (FALSE); /* there is never an rpc msg to be processed */ 369} 370 371/*ARGSUSED*/ 372static enum xprt_stat 373rendezvous_stat(xprt) 374 SVCXPRT *xprt; 375{ 376 377 return (XPRT_IDLE); 378} 379 380static void 381svc_vc_destroy(xprt) 382 SVCXPRT *xprt; 383{ 384 assert(xprt != NULL); 385 386 xprt_unregister(xprt); 387 __svc_vc_dodestroy(xprt); 388} 389 390static void 391__svc_vc_dodestroy(xprt) 392 SVCXPRT *xprt; 393{ 394 struct cf_conn *cd; 395 struct cf_rendezvous *r; 396 397 cd = (struct cf_conn *)xprt->xp_p1; 398 399 if (xprt->xp_fd != RPC_ANYFD) 400 (void)_close(xprt->xp_fd); 401 if (xprt->xp_port != 0) { 402 /* a rendezvouser socket */ 403 r = (struct cf_rendezvous *)xprt->xp_p1; 404 mem_free(r, sizeof (struct cf_rendezvous)); 405 xprt->xp_port = 0; 406 } else { 407 /* an actual connection socket */ 408 XDR_DESTROY(&(cd->xdrs)); 409 mem_free(cd, sizeof(struct cf_conn)); 410 } 411 if (xprt->xp_rtaddr.buf) 412 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 413 if (xprt->xp_ltaddr.buf) 414 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 415 if (xprt->xp_tp) 416 free(xprt->xp_tp); 417 if (xprt->xp_netid) 418 free(xprt->xp_netid); 419 mem_free(xprt, sizeof(SVCXPRT)); 420} 421 422/*ARGSUSED*/ 423static bool_t 424svc_vc_control(xprt, rq, in) 425 SVCXPRT *xprt; 426 const u_int rq; 427 void *in; 428{ 429 return (FALSE); 430} 431 432static bool_t 433svc_vc_rendezvous_control(xprt, rq, in) 434 SVCXPRT *xprt; 435 const u_int rq; 436 void *in; 437{ 438 struct cf_rendezvous *cfp; 439 440 cfp = (struct cf_rendezvous *)xprt->xp_p1; 441 if (cfp == NULL) 442 return (FALSE); 443 switch (rq) { 444 case SVCGET_CONNMAXREC: 445 *(int *)in = cfp->maxrec; 446 break; 447 case SVCSET_CONNMAXREC: 448 cfp->maxrec = *(int *)in; 449 break; 450 default: 451 return (FALSE); 452 } 453 return (TRUE); 454} 455 456/* 457 * reads data from the tcp or uip connection. 458 * any error is fatal and the connection is closed. 459 * (And a read of zero bytes is a half closed stream => error.) 460 * All read operations timeout after 35 seconds. A timeout is 461 * fatal for the connection. 462 */ 463static int 464read_vc(xprtp, buf, len) 465 void *xprtp; 466 void *buf; 467 int len; 468{ 469 SVCXPRT *xprt; 470 int sock; 471 int milliseconds = 35 * 1000; 472 struct pollfd pollfd;
|
479 struct sockaddr *sa; 480 struct cmessage *cm;
| |
481 struct cf_conn *cfp; 482 483 xprt = (SVCXPRT *)xprtp; 484 assert(xprt != NULL); 485 486 sock = xprt->xp_fd; 487 488 cfp = (struct cf_conn *)xprt->xp_p1; 489
| 473 struct cf_conn *cfp; 474 475 xprt = (SVCXPRT *)xprtp; 476 assert(xprt != NULL); 477 478 sock = xprt->xp_fd; 479 480 cfp = (struct cf_conn *)xprt->xp_p1; 481
|
490 cm = NULL; 491 sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
| |
492 if (cfp->nonblock) {
| 482 if (cfp->nonblock) {
|
493 if (sa->sa_family == AF_LOCAL) { 494 cm = (struct cmessage *)xprt->xp_verf.oa_base; 495 if ((len = __msgread_withcred(sock, buf, len, cm)) > 0) 496 xprt->xp_p2 = &cm->cmcred; 497 } else 498 len = _read(sock, buf, (size_t)len);
| 483 len = _read(sock, buf, (size_t)len);
|
499 if (len < 0) { 500 if (errno == EAGAIN) 501 len = 0; 502 else 503 goto fatal_err; 504 } 505 if (len != 0) 506 gettimeofday(&cfp->last_recv_time, NULL); 507 return len; 508 } 509 510 do { 511 pollfd.fd = sock; 512 pollfd.events = POLLIN; 513 pollfd.revents = 0; 514 switch (_poll(&pollfd, 1, milliseconds)) { 515 case -1: 516 if (errno == EINTR) 517 continue; 518 /*FALLTHROUGH*/ 519 case 0: 520 goto fatal_err; 521 522 default: 523 break; 524 } 525 } while ((pollfd.revents & POLLIN) == 0); 526
| 484 if (len < 0) { 485 if (errno == EAGAIN) 486 len = 0; 487 else 488 goto fatal_err; 489 } 490 if (len != 0) 491 gettimeofday(&cfp->last_recv_time, NULL); 492 return len; 493 } 494 495 do { 496 pollfd.fd = sock; 497 pollfd.events = POLLIN; 498 pollfd.revents = 0; 499 switch (_poll(&pollfd, 1, milliseconds)) { 500 case -1: 501 if (errno == EINTR) 502 continue; 503 /*FALLTHROUGH*/ 504 case 0: 505 goto fatal_err; 506 507 default: 508 break; 509 } 510 } while ((pollfd.revents & POLLIN) == 0); 511
|
527 if (sa->sa_family == AF_LOCAL) { 528 cm = (struct cmessage *)xprt->xp_verf.oa_base; 529 if ((len = __msgread_withcred(sock, buf, len, cm)) > 0) { 530 xprt->xp_p2 = &cm->cmcred; 531 return (len); 532 } else 533 goto fatal_err; 534 } else { 535 if ((len = _read(sock, buf, (size_t)len)) > 0) { 536 gettimeofday(&cfp->last_recv_time, NULL); 537 return (len); 538 }
| 512 if ((len = _read(sock, buf, (size_t)len)) > 0) { 513 gettimeofday(&cfp->last_recv_time, NULL); 514 return (len);
|
539 } 540 541fatal_err: 542 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 543 return (-1); 544} 545 546/* 547 * writes data to the tcp connection. 548 * Any error is fatal and the connection is closed. 549 */ 550static int 551write_vc(xprtp, buf, len) 552 void *xprtp; 553 void *buf; 554 int len; 555{ 556 SVCXPRT *xprt; 557 int i, cnt;
| 515 } 516 517fatal_err: 518 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 519 return (-1); 520} 521 522/* 523 * writes data to the tcp connection. 524 * Any error is fatal and the connection is closed. 525 */ 526static int 527write_vc(xprtp, buf, len) 528 void *xprtp; 529 void *buf; 530 int len; 531{ 532 SVCXPRT *xprt; 533 int i, cnt;
|
558 struct sockaddr *sa;
| |
559 struct cf_conn *cd; 560 struct timeval tv0, tv1; 561 562 xprt = (SVCXPRT *)xprtp; 563 assert(xprt != NULL); 564 565 cd = (struct cf_conn *)xprt->xp_p1; 566 567 if (cd->nonblock) 568 gettimeofday(&tv0, NULL); 569
| 534 struct cf_conn *cd; 535 struct timeval tv0, tv1; 536 537 xprt = (SVCXPRT *)xprtp; 538 assert(xprt != NULL); 539 540 cd = (struct cf_conn *)xprt->xp_p1; 541 542 if (cd->nonblock) 543 gettimeofday(&tv0, NULL); 544
|
570 sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
| |
571 for (cnt = len; cnt > 0; cnt -= i, buf += i) {
| 545 for (cnt = len; cnt > 0; cnt -= i, buf += i) {
|
572 if (sa->sa_family == AF_LOCAL) 573 i = __msgwrite(xprt->xp_fd, buf, (size_t)cnt); 574 else 575 i = _write(xprt->xp_fd, buf, (size_t)cnt);
| 546 i = _write(xprt->xp_fd, buf, (size_t)cnt);
|
576 if (i < 0) { 577 if (errno != EAGAIN || !cd->nonblock) { 578 cd->strm_stat = XPRT_DIED; 579 return (-1); 580 } 581 if (cd->nonblock && i != cnt) { 582 /* 583 * For non-blocking connections, do not 584 * take more than 2 seconds writing the 585 * data out. 586 * 587 * XXX 2 is an arbitrary amount. 588 */ 589 gettimeofday(&tv1, NULL); 590 if (tv1.tv_sec - tv0.tv_sec >= 2) { 591 cd->strm_stat = XPRT_DIED; 592 return (-1); 593 } 594 } 595 } 596 } 597 598 return (len); 599} 600 601static enum xprt_stat 602svc_vc_stat(xprt) 603 SVCXPRT *xprt; 604{ 605 struct cf_conn *cd; 606 607 assert(xprt != NULL); 608 609 cd = (struct cf_conn *)(xprt->xp_p1); 610 611 if (cd->strm_stat == XPRT_DIED) 612 return (XPRT_DIED); 613 if (! xdrrec_eof(&(cd->xdrs))) 614 return (XPRT_MOREREQS); 615 return (XPRT_IDLE); 616} 617 618static bool_t 619svc_vc_recv(xprt, msg) 620 SVCXPRT *xprt; 621 struct rpc_msg *msg; 622{ 623 struct cf_conn *cd; 624 XDR *xdrs; 625 626 assert(xprt != NULL); 627 assert(msg != NULL); 628 629 cd = (struct cf_conn *)(xprt->xp_p1); 630 xdrs = &(cd->xdrs); 631 632 if (cd->nonblock) { 633 if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE)) 634 return FALSE; 635 } 636 637 xdrs->x_op = XDR_DECODE; 638 (void)xdrrec_skiprecord(xdrs); 639 if (xdr_callmsg(xdrs, msg)) { 640 cd->x_id = msg->rm_xid; 641 return (TRUE); 642 } 643 cd->strm_stat = XPRT_DIED; 644 return (FALSE); 645} 646 647static bool_t 648svc_vc_getargs(xprt, xdr_args, args_ptr) 649 SVCXPRT *xprt; 650 xdrproc_t xdr_args; 651 void *args_ptr; 652{ 653 654 assert(xprt != NULL); 655 /* args_ptr may be NULL */ 656 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 657 args_ptr)); 658} 659 660static bool_t 661svc_vc_freeargs(xprt, xdr_args, args_ptr) 662 SVCXPRT *xprt; 663 xdrproc_t xdr_args; 664 void *args_ptr; 665{ 666 XDR *xdrs; 667 668 assert(xprt != NULL); 669 /* args_ptr may be NULL */ 670 671 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 672 673 xdrs->x_op = XDR_FREE; 674 return ((*xdr_args)(xdrs, args_ptr)); 675} 676 677static bool_t 678svc_vc_reply(xprt, msg) 679 SVCXPRT *xprt; 680 struct rpc_msg *msg; 681{ 682 struct cf_conn *cd; 683 XDR *xdrs; 684 bool_t rstat; 685 686 assert(xprt != NULL); 687 assert(msg != NULL); 688 689 cd = (struct cf_conn *)(xprt->xp_p1); 690 xdrs = &(cd->xdrs); 691 692 xdrs->x_op = XDR_ENCODE; 693 msg->rm_xid = cd->x_id; 694 rstat = xdr_replymsg(xdrs, msg); 695 (void)xdrrec_endofrecord(xdrs, TRUE); 696 return (rstat); 697} 698 699static void 700svc_vc_ops(xprt) 701 SVCXPRT *xprt; 702{ 703 static struct xp_ops ops; 704 static struct xp_ops2 ops2; 705 extern mutex_t ops_lock; 706 707/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 708 709 mutex_lock(&ops_lock); 710 if (ops.xp_recv == NULL) { 711 ops.xp_recv = svc_vc_recv; 712 ops.xp_stat = svc_vc_stat; 713 ops.xp_getargs = svc_vc_getargs; 714 ops.xp_reply = svc_vc_reply; 715 ops.xp_freeargs = svc_vc_freeargs; 716 ops.xp_destroy = svc_vc_destroy; 717 ops2.xp_control = svc_vc_control; 718 } 719 xprt->xp_ops = &ops; 720 xprt->xp_ops2 = &ops2; 721 mutex_unlock(&ops_lock); 722} 723 724static void 725svc_vc_rendezvous_ops(xprt) 726 SVCXPRT *xprt; 727{ 728 static struct xp_ops ops; 729 static struct xp_ops2 ops2; 730 extern mutex_t ops_lock; 731 732 mutex_lock(&ops_lock); 733 if (ops.xp_recv == NULL) { 734 ops.xp_recv = rendezvous_request; 735 ops.xp_stat = rendezvous_stat; 736 ops.xp_getargs = 737 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort; 738 ops.xp_reply = 739 (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort; 740 ops.xp_freeargs = 741 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort, 742 ops.xp_destroy = svc_vc_destroy; 743 ops2.xp_control = svc_vc_rendezvous_control; 744 } 745 xprt->xp_ops = &ops; 746 xprt->xp_ops2 = &ops2; 747 mutex_unlock(&ops_lock); 748} 749
| 547 if (i < 0) { 548 if (errno != EAGAIN || !cd->nonblock) { 549 cd->strm_stat = XPRT_DIED; 550 return (-1); 551 } 552 if (cd->nonblock && i != cnt) { 553 /* 554 * For non-blocking connections, do not 555 * take more than 2 seconds writing the 556 * data out. 557 * 558 * XXX 2 is an arbitrary amount. 559 */ 560 gettimeofday(&tv1, NULL); 561 if (tv1.tv_sec - tv0.tv_sec >= 2) { 562 cd->strm_stat = XPRT_DIED; 563 return (-1); 564 } 565 } 566 } 567 } 568 569 return (len); 570} 571 572static enum xprt_stat 573svc_vc_stat(xprt) 574 SVCXPRT *xprt; 575{ 576 struct cf_conn *cd; 577 578 assert(xprt != NULL); 579 580 cd = (struct cf_conn *)(xprt->xp_p1); 581 582 if (cd->strm_stat == XPRT_DIED) 583 return (XPRT_DIED); 584 if (! xdrrec_eof(&(cd->xdrs))) 585 return (XPRT_MOREREQS); 586 return (XPRT_IDLE); 587} 588 589static bool_t 590svc_vc_recv(xprt, msg) 591 SVCXPRT *xprt; 592 struct rpc_msg *msg; 593{ 594 struct cf_conn *cd; 595 XDR *xdrs; 596 597 assert(xprt != NULL); 598 assert(msg != NULL); 599 600 cd = (struct cf_conn *)(xprt->xp_p1); 601 xdrs = &(cd->xdrs); 602 603 if (cd->nonblock) { 604 if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE)) 605 return FALSE; 606 } 607 608 xdrs->x_op = XDR_DECODE; 609 (void)xdrrec_skiprecord(xdrs); 610 if (xdr_callmsg(xdrs, msg)) { 611 cd->x_id = msg->rm_xid; 612 return (TRUE); 613 } 614 cd->strm_stat = XPRT_DIED; 615 return (FALSE); 616} 617 618static bool_t 619svc_vc_getargs(xprt, xdr_args, args_ptr) 620 SVCXPRT *xprt; 621 xdrproc_t xdr_args; 622 void *args_ptr; 623{ 624 625 assert(xprt != NULL); 626 /* args_ptr may be NULL */ 627 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 628 args_ptr)); 629} 630 631static bool_t 632svc_vc_freeargs(xprt, xdr_args, args_ptr) 633 SVCXPRT *xprt; 634 xdrproc_t xdr_args; 635 void *args_ptr; 636{ 637 XDR *xdrs; 638 639 assert(xprt != NULL); 640 /* args_ptr may be NULL */ 641 642 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 643 644 xdrs->x_op = XDR_FREE; 645 return ((*xdr_args)(xdrs, args_ptr)); 646} 647 648static bool_t 649svc_vc_reply(xprt, msg) 650 SVCXPRT *xprt; 651 struct rpc_msg *msg; 652{ 653 struct cf_conn *cd; 654 XDR *xdrs; 655 bool_t rstat; 656 657 assert(xprt != NULL); 658 assert(msg != NULL); 659 660 cd = (struct cf_conn *)(xprt->xp_p1); 661 xdrs = &(cd->xdrs); 662 663 xdrs->x_op = XDR_ENCODE; 664 msg->rm_xid = cd->x_id; 665 rstat = xdr_replymsg(xdrs, msg); 666 (void)xdrrec_endofrecord(xdrs, TRUE); 667 return (rstat); 668} 669 670static void 671svc_vc_ops(xprt) 672 SVCXPRT *xprt; 673{ 674 static struct xp_ops ops; 675 static struct xp_ops2 ops2; 676 extern mutex_t ops_lock; 677 678/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 679 680 mutex_lock(&ops_lock); 681 if (ops.xp_recv == NULL) { 682 ops.xp_recv = svc_vc_recv; 683 ops.xp_stat = svc_vc_stat; 684 ops.xp_getargs = svc_vc_getargs; 685 ops.xp_reply = svc_vc_reply; 686 ops.xp_freeargs = svc_vc_freeargs; 687 ops.xp_destroy = svc_vc_destroy; 688 ops2.xp_control = svc_vc_control; 689 } 690 xprt->xp_ops = &ops; 691 xprt->xp_ops2 = &ops2; 692 mutex_unlock(&ops_lock); 693} 694 695static void 696svc_vc_rendezvous_ops(xprt) 697 SVCXPRT *xprt; 698{ 699 static struct xp_ops ops; 700 static struct xp_ops2 ops2; 701 extern mutex_t ops_lock; 702 703 mutex_lock(&ops_lock); 704 if (ops.xp_recv == NULL) { 705 ops.xp_recv = rendezvous_request; 706 ops.xp_stat = rendezvous_stat; 707 ops.xp_getargs = 708 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort; 709 ops.xp_reply = 710 (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort; 711 ops.xp_freeargs = 712 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort, 713 ops.xp_destroy = svc_vc_destroy; 714 ops2.xp_control = svc_vc_rendezvous_control; 715 } 716 xprt->xp_ops = &ops; 717 xprt->xp_ops2 = &ops2; 718 mutex_unlock(&ops_lock); 719} 720
|
750int 751__msgread_withcred(sock, buf, cnt, cmp) 752 int sock; 753 void *buf; 754 size_t cnt; 755 struct cmessage *cmp; 756{ 757 struct iovec iov[1]; 758 struct msghdr msg; 759 union { 760 struct cmsghdr cmsg; 761 char control[CMSG_SPACE(sizeof(struct cmsgcred))]; 762 } cm; 763 int ret; 764 765 766 bzero(&cm, sizeof(cm)); 767 iov[0].iov_base = buf; 768 iov[0].iov_len = cnt; 769 770 msg.msg_iov = iov; 771 msg.msg_iovlen = 1; 772 msg.msg_name = NULL; 773 msg.msg_namelen = 0; 774 msg.msg_control = &cm; 775 msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred)); 776 msg.msg_flags = 0; 777 778 ret = _recvmsg(sock, &msg, 0); 779 bcopy(&cm.cmsg, &cmp->cmsg, sizeof(cmp->cmsg)); 780 bcopy(CMSG_DATA(&cm), &cmp->cmcred, sizeof(cmp->cmcred)); 781 782 if ((msg.msg_flags & MSG_CTRUNC) != 0) 783 return (-1); 784 785 return (ret); 786} 787 788static int 789__msgwrite(sock, buf, cnt) 790 int sock; 791 void *buf; 792 size_t cnt; 793{ 794 struct iovec iov[1]; 795 struct msghdr msg; 796 struct cmessage cm; 797 798 bzero((char *)&cm, sizeof(cm)); 799 iov[0].iov_base = buf; 800 iov[0].iov_len = cnt; 801 802 cm.cmsg.cmsg_type = SCM_CREDS; 803 cm.cmsg.cmsg_level = SOL_SOCKET; 804 cm.cmsg.cmsg_len = sizeof(struct cmessage); 805 806 msg.msg_iov = iov; 807 msg.msg_iovlen = 1; 808 msg.msg_name = NULL; 809 msg.msg_namelen = 0; 810 msg.msg_control = &cm; 811 msg.msg_controllen = sizeof(struct cmessage); 812 msg.msg_flags = 0; 813 814 return(_sendmsg(sock, &msg, 0)); 815} 816
| |
817/*
| 721/*
|
818 * Get the effective UID of the sending process. Used by rpcbind and keyserv 819 * (AF_LOCAL).
| 722 * Get the effective UID of the sending process. Used by rpcbind, keyserv 723 * and rpc.yppasswdd on AF_LOCAL.
|
820 */ 821int
| 724 */ 725int
|
822__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) 823{ 824 struct cmsgcred *cmcred; 825 struct cmessage *cm; 826 struct cmsghdr *cmp; 827 828 cm = (struct cmessage *)transp->xp_verf.oa_base; 829 830 if (cm == NULL)
| 726__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) { 727 int sock, ret; 728 gid_t egid; 729 uid_t euid; 730 struct sockaddr *sa; 731 732 sock = transp->xp_fd; 733 sa = (struct sockaddr *)transp->xp_rtaddr.buf; 734 if (sa->sa_family == AF_LOCAL) { 735 ret = getpeereid(sock, &euid, &egid); 736 if (ret == 0) 737 *uid = euid; 738 return (ret); 739 } else
|
831 return (-1);
| 740 return (-1);
|
832 cmp = &cm->cmsg; 833 if (cmp == NULL || cmp->cmsg_level != SOL_SOCKET || 834 cmp->cmsg_type != SCM_CREDS) 835 return (-1); 836 837 cmcred = __svc_getcallercreds(transp); 838 if (cmcred == NULL) 839 return (-1); 840 *uid = cmcred->cmcred_euid; 841 return (0);
| |
842} 843 844/* 845 * Destroy xprts that have not have had any activity in 'timeout' seconds. 846 * If 'cleanblock' is true, blocking connections (the default) are also 847 * cleaned. If timeout is 0, the least active connection is picked. 848 */ 849bool_t 850__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) 851{ 852 int i, ncleaned; 853 SVCXPRT *xprt, *least_active; 854 struct timeval tv, tdiff, tmax; 855 struct cf_conn *cd; 856 857 gettimeofday(&tv, NULL); 858 tmax.tv_sec = tmax.tv_usec = 0; 859 least_active = NULL; 860 rwlock_wrlock(&svc_fd_lock); 861 for (i = ncleaned = 0; i <= svc_maxfd; i++) { 862 if (FD_ISSET(i, fds)) { 863 xprt = __svc_xports[i]; 864 if (xprt == NULL || xprt->xp_ops == NULL || 865 xprt->xp_ops->xp_recv != svc_vc_recv) 866 continue; 867 cd = (struct cf_conn *)xprt->xp_p1; 868 if (!cleanblock && !cd->nonblock) 869 continue; 870 if (timeout == 0) { 871 timersub(&tv, &cd->last_recv_time, &tdiff); 872 if (timercmp(&tdiff, &tmax, >)) { 873 tmax = tdiff; 874 least_active = xprt; 875 } 876 continue; 877 } 878 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { 879 __xprt_unregister_unlocked(xprt); 880 __svc_vc_dodestroy(xprt); 881 ncleaned++; 882 } 883 } 884 } 885 if (timeout == 0 && least_active != NULL) { 886 __xprt_unregister_unlocked(least_active); 887 __svc_vc_dodestroy(least_active); 888 ncleaned++; 889 } 890 rwlock_unlock(&svc_fd_lock); 891 return ncleaned > 0 ? TRUE : FALSE; 892}
| 741} 742 743/* 744 * Destroy xprts that have not have had any activity in 'timeout' seconds. 745 * If 'cleanblock' is true, blocking connections (the default) are also 746 * cleaned. If timeout is 0, the least active connection is picked. 747 */ 748bool_t 749__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) 750{ 751 int i, ncleaned; 752 SVCXPRT *xprt, *least_active; 753 struct timeval tv, tdiff, tmax; 754 struct cf_conn *cd; 755 756 gettimeofday(&tv, NULL); 757 tmax.tv_sec = tmax.tv_usec = 0; 758 least_active = NULL; 759 rwlock_wrlock(&svc_fd_lock); 760 for (i = ncleaned = 0; i <= svc_maxfd; i++) { 761 if (FD_ISSET(i, fds)) { 762 xprt = __svc_xports[i]; 763 if (xprt == NULL || xprt->xp_ops == NULL || 764 xprt->xp_ops->xp_recv != svc_vc_recv) 765 continue; 766 cd = (struct cf_conn *)xprt->xp_p1; 767 if (!cleanblock && !cd->nonblock) 768 continue; 769 if (timeout == 0) { 770 timersub(&tv, &cd->last_recv_time, &tdiff); 771 if (timercmp(&tdiff, &tmax, >)) { 772 tmax = tdiff; 773 least_active = xprt; 774 } 775 continue; 776 } 777 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { 778 __xprt_unregister_unlocked(xprt); 779 __svc_vc_dodestroy(xprt); 780 ncleaned++; 781 } 782 } 783 } 784 if (timeout == 0 && least_active != NULL) { 785 __xprt_unregister_unlocked(least_active); 786 __svc_vc_dodestroy(least_active); 787 ncleaned++; 788 } 789 rwlock_unlock(&svc_fd_lock); 790 return ncleaned > 0 ? TRUE : FALSE; 791}
|