1/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */
| 1/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */
|
2/* $FreeBSD: head/lib/libc/rpc/svc_vc.c 74536 2001-03-20 20:28:09Z alfred $ */
| 2/* $FreeBSD: head/lib/libc/rpc/svc_vc.c 74627 2001-03-22 04:31:30Z alfred $ */
|
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));
| 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 __msgread_withcred(int, void *, size_t, struct cmessage *);
|
88static int __msgwrite(int, void *, size_t);
| 89static 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
| 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 415 do { 416 pollfd.fd = sock; 417 pollfd.events = POLLIN; 418 pollfd.revents = 0; 419 switch (_poll(&pollfd, 1, milliseconds)) { 420 case -1: 421 if (errno == EINTR) 422 continue; 423 /*FALLTHROUGH*/
| 103/* 104 * Usage: 105 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 106 * 107 * Creates, registers, and returns a (rpc) tcp based transporter. 108 * Once *xprt is initialized, it is registered as a transporter 109 * see (svc.h, xprt_register). This routine returns 110 * a NULL if a problem occurred. 111 * 112 * The filedescriptor passed in is expected to refer to a bound, but 113 * not yet connected socket. 114 * 115 * Since streams do buffered io similar to stdio, the caller can specify 116 * how big the send and receive buffers are via the second and third parms; 117 * 0 => use the system default. 118 */ 119SVCXPRT * 120svc_vc_create(fd, sendsize, recvsize) 121 int fd; 122 u_int sendsize; 123 u_int recvsize; 124{ 125 SVCXPRT *xprt; 126 struct cf_rendezvous *r = NULL; 127 struct __rpc_sockinfo si; 128 struct sockaddr_storage sslocal; 129 socklen_t slen; 130 int one = 1; 131 132 r = mem_alloc(sizeof(*r)); 133 if (r == NULL) { 134 warnx("svc_vc_create: out of memory"); 135 goto cleanup_svc_vc_create; 136 } 137 if (!__rpc_fd2sockinfo(fd, &si)) 138 return NULL; 139 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 140 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 141 xprt = mem_alloc(sizeof(SVCXPRT)); 142 if (xprt == NULL) { 143 warnx("svc_vc_create: out of memory"); 144 goto cleanup_svc_vc_create; 145 } 146 xprt->xp_tp = NULL; 147 xprt->xp_p1 = (caddr_t)(void *)r; 148 xprt->xp_p2 = NULL; 149 xprt->xp_p3 = NULL; 150 xprt->xp_verf = _null_auth; 151 svc_vc_rendezvous_ops(xprt); 152 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 153 xprt->xp_fd = fd; 154 155 slen = sizeof (struct sockaddr_storage); 156 if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 157 warnx("svc_vc_create: could not retrieve local addr"); 158 goto cleanup_svc_vc_create; 159 } 160 161 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 162 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 163 if (xprt->xp_ltaddr.buf == NULL) { 164 warnx("svc_vc_create: no mem for local addr"); 165 goto cleanup_svc_vc_create; 166 } 167 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 168 169 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 170 xprt_register(xprt); 171 return (xprt); 172cleanup_svc_vc_create: 173 if (r != NULL) 174 mem_free(r, sizeof(*r)); 175 return (NULL); 176} 177 178/* 179 * Like svtcp_create(), except the routine takes any *open* UNIX file 180 * descriptor as its first input. 181 */ 182SVCXPRT * 183svc_fd_create(fd, sendsize, recvsize) 184 int fd; 185 u_int sendsize; 186 u_int recvsize; 187{ 188 struct sockaddr_storage ss; 189 socklen_t slen; 190 SVCXPRT *ret; 191 192 assert(fd != -1); 193 194 ret = makefd_xprt(fd, sendsize, recvsize); 195 if (ret == NULL) 196 return NULL; 197 198 slen = sizeof (struct sockaddr_storage); 199 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 200 warnx("svc_fd_create: could not retrieve local addr"); 201 goto freedata; 202 } 203 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 204 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 205 if (ret->xp_ltaddr.buf == NULL) { 206 warnx("svc_fd_create: no mem for local addr"); 207 goto freedata; 208 } 209 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 210 211 slen = sizeof (struct sockaddr_storage); 212 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 213 warnx("svc_fd_create: could not retrieve remote addr"); 214 goto freedata; 215 } 216 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 217 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 218 if (ret->xp_rtaddr.buf == NULL) { 219 warnx("svc_fd_create: no mem for local addr"); 220 goto freedata; 221 } 222 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 223#ifdef PORTMAP 224 if (ss.ss_family == AF_INET) { 225 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 226 ret->xp_addrlen = sizeof (struct sockaddr_in); 227 } 228#endif /* PORTMAP */ 229 230 return ret; 231 232freedata: 233 if (ret->xp_ltaddr.buf != NULL) 234 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 235 236 return NULL; 237} 238 239static SVCXPRT * 240makefd_xprt(fd, sendsize, recvsize) 241 int fd; 242 u_int sendsize; 243 u_int recvsize; 244{ 245 SVCXPRT *xprt; 246 struct cf_conn *cd; 247 const char *netid; 248 struct __rpc_sockinfo si; 249 250 assert(fd != -1); 251 252 xprt = mem_alloc(sizeof(SVCXPRT)); 253 if (xprt == NULL) { 254 warnx("svc_vc: makefd_xprt: out of memory"); 255 goto done; 256 } 257 memset(xprt, 0, sizeof *xprt); 258 cd = mem_alloc(sizeof(struct cf_conn)); 259 if (cd == NULL) { 260 warnx("svc_tcp: makefd_xprt: out of memory"); 261 mem_free(xprt, sizeof(SVCXPRT)); 262 xprt = NULL; 263 goto done; 264 } 265 cd->strm_stat = XPRT_IDLE; 266 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 267 (caddr_t)(void *)xprt, read_vc, write_vc); 268 xprt->xp_p1 = (caddr_t)(void *)cd; 269 xprt->xp_verf.oa_base = cd->verf_body; 270 svc_vc_ops(xprt); /* truely deals with calls */ 271 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 272 xprt->xp_fd = fd; 273 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 274 xprt->xp_netid = strdup(netid); 275 276 xprt_register(xprt); 277done: 278 return (xprt); 279} 280 281/*ARGSUSED*/ 282static bool_t 283rendezvous_request(xprt, msg) 284 SVCXPRT *xprt; 285 struct rpc_msg *msg; 286{ 287 int sock; 288 struct cf_rendezvous *r; 289 struct sockaddr_storage addr; 290 socklen_t len; 291 struct __rpc_sockinfo si; 292 293 assert(xprt != NULL); 294 assert(msg != NULL); 295 296 r = (struct cf_rendezvous *)xprt->xp_p1; 297again: 298 len = sizeof addr; 299 if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 300 &len)) < 0) { 301 if (errno == EINTR) 302 goto again; 303 return (FALSE); 304 } 305 /* 306 * make a new transporter (re-uses xprt) 307 */ 308 xprt = makefd_xprt(sock, r->sendsize, r->recvsize); 309 xprt->xp_rtaddr.buf = mem_alloc(len); 310 if (xprt->xp_rtaddr.buf == NULL) 311 return (FALSE); 312 memcpy(xprt->xp_rtaddr.buf, &addr, len); 313 xprt->xp_rtaddr.len = len; 314#ifdef PORTMAP 315 if (addr.ss_family == AF_INET) { 316 xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf; 317 xprt->xp_addrlen = sizeof (struct sockaddr_in); 318 } 319#endif /* PORTMAP */ 320 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 321 len = 1; 322 /* XXX fvdl - is this useful? */ 323 _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 324 } 325 return (FALSE); /* there is never an rpc msg to be processed */ 326} 327 328/*ARGSUSED*/ 329static enum xprt_stat 330rendezvous_stat(xprt) 331 SVCXPRT *xprt; 332{ 333 334 return (XPRT_IDLE); 335} 336 337static void 338svc_vc_destroy(xprt) 339 SVCXPRT *xprt; 340{ 341 struct cf_conn *cd; 342 struct cf_rendezvous *r; 343 344 assert(xprt != NULL); 345 346 cd = (struct cf_conn *)xprt->xp_p1; 347 348 xprt_unregister(xprt); 349 if (xprt->xp_fd != RPC_ANYFD) 350 (void)_close(xprt->xp_fd); 351 if (xprt->xp_port != 0) { 352 /* a rendezvouser socket */ 353 r = (struct cf_rendezvous *)xprt->xp_p1; 354 mem_free(r, sizeof (struct cf_rendezvous)); 355 xprt->xp_port = 0; 356 } else { 357 /* an actual connection socket */ 358 XDR_DESTROY(&(cd->xdrs)); 359 mem_free(cd, sizeof(struct cf_conn)); 360 } 361 if (xprt->xp_rtaddr.buf) 362 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 363 if (xprt->xp_ltaddr.buf) 364 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 365 if (xprt->xp_tp) 366 free(xprt->xp_tp); 367 if (xprt->xp_netid) 368 free(xprt->xp_netid); 369 mem_free(xprt, sizeof(SVCXPRT)); 370} 371 372/*ARGSUSED*/ 373static bool_t 374svc_vc_control(xprt, rq, in) 375 SVCXPRT *xprt; 376 const u_int rq; 377 void *in; 378{ 379 return (FALSE); 380} 381 382/* 383 * reads data from the tcp or uip connection. 384 * any error is fatal and the connection is closed. 385 * (And a read of zero bytes is a half closed stream => error.) 386 * All read operations timeout after 35 seconds. A timeout is 387 * fatal for the connection. 388 */ 389static int 390read_vc(xprtp, buf, len) 391 caddr_t xprtp; 392 caddr_t buf; 393 int len; 394{ 395 SVCXPRT *xprt; 396 int sock; 397 int milliseconds = 35 * 1000; 398 struct pollfd pollfd; 399 struct sockaddr *sa; 400 struct cmessage *cm; 401 struct cmsghdr *cmp; 402 struct sockcred *sc; 403 404 xprt = (SVCXPRT *)(void *)xprtp; 405 assert(xprt != NULL); 406 407 sock = xprt->xp_fd; 408 409 do { 410 pollfd.fd = sock; 411 pollfd.events = POLLIN; 412 pollfd.revents = 0; 413 switch (_poll(&pollfd, 1, milliseconds)) { 414 case -1: 415 if (errno == EINTR) 416 continue; 417 /*FALLTHROUGH*/
|
424 case 0: 425 goto fatal_err; 426 default: 427 break;
| 418 case 0: 419 goto fatal_err; 420 421 default: 422 break;
|
428 } 429 } while ((pollfd.revents & POLLIN) == 0); 430 431 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 432 if (sa->sa_family == AF_LOCAL) {
| 423 } 424 } while ((pollfd.revents & POLLIN) == 0); 425 426 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 427 if (sa->sa_family == AF_LOCAL) {
|
433 if ((len = __msgread(sock, buf, len)) > 0) { 434 cm = (struct cmessage *)xprt->xp_verf.oa_base;
| 428 cm = (struct cmessage *)xprt->xp_verf.oa_base; 429 if ((len = __msgread_withcred(sock, buf, len, cm)) > 0) {
|
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
| 430 cmp = &cm->cmsg; 431 sc = (struct sockcred *)(void *)CMSG_DATA(cmp); 432 xprt->xp_p2 = sc; 433 return (len); 434 } 435 } else { 436 if ((len = _read(sock, buf, (size_t)len)) > 0) 437 return (len); 438 } 439 440fatal_err: 441 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 442 return (-1); 443} 444 445/* 446 * writes data to the tcp connection. 447 * Any error is fatal and the connection is closed. 448 */ 449static int 450write_vc(xprtp, buf, len) 451 caddr_t xprtp; 452 caddr_t buf; 453 int len; 454{ 455 SVCXPRT *xprt; 456 int i, cnt; 457 struct sockaddr *sa; 458 459 xprt = (SVCXPRT *)(void *)xprtp; 460 assert(xprt != NULL); 461 462 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 463 if (sa->sa_family == AF_LOCAL) { 464 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 465 if ((i = __msgwrite(xprt->xp_fd, buf, 466 (size_t)cnt)) < 0) { 467 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 468 XPRT_DIED; 469 return (-1); 470 } 471 } 472 } else { 473 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 474 if ((i = _write(xprt->xp_fd, buf, 475 (size_t)cnt)) < 0) { 476 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 477 XPRT_DIED; 478 return (-1); 479 } 480 } 481 } 482 483 return (len); 484} 485 486static enum xprt_stat 487svc_vc_stat(xprt) 488 SVCXPRT *xprt; 489{ 490 struct cf_conn *cd; 491 492 assert(xprt != NULL); 493 494 cd = (struct cf_conn *)(xprt->xp_p1); 495 496 if (cd->strm_stat == XPRT_DIED) 497 return (XPRT_DIED); 498 if (! xdrrec_eof(&(cd->xdrs))) 499 return (XPRT_MOREREQS); 500 return (XPRT_IDLE); 501} 502 503static bool_t 504svc_vc_recv(xprt, msg) 505 SVCXPRT *xprt; 506 struct rpc_msg *msg; 507{ 508 struct cf_conn *cd; 509 XDR *xdrs; 510 511 assert(xprt != NULL); 512 assert(msg != NULL); 513 514 cd = (struct cf_conn *)(xprt->xp_p1); 515 xdrs = &(cd->xdrs); 516 517 xdrs->x_op = XDR_DECODE; 518 (void)xdrrec_skiprecord(xdrs); 519 if (xdr_callmsg(xdrs, msg)) { 520 cd->x_id = msg->rm_xid; 521 return (TRUE); 522 } 523 cd->strm_stat = XPRT_DIED; 524 return (FALSE); 525} 526 527static bool_t 528svc_vc_getargs(xprt, xdr_args, args_ptr) 529 SVCXPRT *xprt; 530 xdrproc_t xdr_args; 531 caddr_t args_ptr; 532{ 533 534 assert(xprt != NULL); 535 /* args_ptr may be NULL */ 536 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 537 args_ptr)); 538} 539 540static bool_t 541svc_vc_freeargs(xprt, xdr_args, args_ptr) 542 SVCXPRT *xprt; 543 xdrproc_t xdr_args; 544 caddr_t args_ptr; 545{ 546 XDR *xdrs; 547 548 assert(xprt != NULL); 549 /* args_ptr may be NULL */ 550 551 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 552 553 xdrs->x_op = XDR_FREE; 554 return ((*xdr_args)(xdrs, args_ptr)); 555} 556 557static bool_t 558svc_vc_reply(xprt, msg) 559 SVCXPRT *xprt; 560 struct rpc_msg *msg; 561{ 562 struct cf_conn *cd; 563 XDR *xdrs; 564 bool_t stat; 565 566 assert(xprt != NULL); 567 assert(msg != NULL); 568 569 cd = (struct cf_conn *)(xprt->xp_p1); 570 xdrs = &(cd->xdrs); 571 572 xdrs->x_op = XDR_ENCODE; 573 msg->rm_xid = cd->x_id; 574 stat = xdr_replymsg(xdrs, msg); 575 (void)xdrrec_endofrecord(xdrs, TRUE); 576 return (stat); 577} 578 579static void 580svc_vc_ops(xprt) 581 SVCXPRT *xprt; 582{ 583 static struct xp_ops ops; 584 static struct xp_ops2 ops2; 585 extern mutex_t ops_lock; 586 587/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 588 589 mutex_lock(&ops_lock); 590 if (ops.xp_recv == NULL) { 591 ops.xp_recv = svc_vc_recv; 592 ops.xp_stat = svc_vc_stat; 593 ops.xp_getargs = svc_vc_getargs; 594 ops.xp_reply = svc_vc_reply; 595 ops.xp_freeargs = svc_vc_freeargs; 596 ops.xp_destroy = svc_vc_destroy; 597 ops2.xp_control = svc_vc_control; 598 } 599 xprt->xp_ops = &ops; 600 xprt->xp_ops2 = &ops2; 601 mutex_unlock(&ops_lock); 602} 603 604static void 605svc_vc_rendezvous_ops(xprt) 606 SVCXPRT *xprt; 607{ 608 static struct xp_ops ops; 609 static struct xp_ops2 ops2; 610 extern mutex_t ops_lock; 611 612 mutex_lock(&ops_lock); 613 if (ops.xp_recv == NULL) { 614 ops.xp_recv = rendezvous_request; 615 ops.xp_stat = rendezvous_stat; 616 ops.xp_getargs = 617 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort; 618 ops.xp_reply = 619 (bool_t (*) __P((SVCXPRT *, struct rpc_msg *)))abort; 620 ops.xp_freeargs = 621 (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort, 622 ops.xp_destroy = svc_vc_destroy; 623 ops2.xp_control = svc_vc_control; 624 } 625 xprt->xp_ops = &ops; 626 xprt->xp_ops2 = &ops2; 627 mutex_unlock(&ops_lock); 628} 629
|
635static int 636__msgread(sock, buf, cnt)
| 630int 631__msgread_withcred(sock, buf, cnt, cmp)
|
637 int sock; 638 void *buf; 639 size_t cnt;
| 632 int sock; 633 void *buf; 634 size_t cnt;
|
| 635 struct cmessage *cmp;
|
640{ 641 struct iovec iov[1]; 642 struct msghdr msg;
| 636{ 637 struct iovec iov[1]; 638 struct msghdr msg;
|
643 struct cmessage cm;
| |
644
| 639
|
645 bzero((char *)&cm, sizeof(cm));
| 640 bzero(cmp, sizeof(*cmp));
|
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;
| 641 iov[0].iov_base = buf; 642 iov[0].iov_len = cnt; 643 644 msg.msg_iov = iov; 645 msg.msg_iovlen = 1; 646 msg.msg_name = NULL; 647 msg.msg_namelen = 0;
|
653 msg.msg_control = (caddr_t)&cm;
| 648 msg.msg_control = cmp;
|
654 msg.msg_controllen = sizeof(struct cmessage); 655 msg.msg_flags = 0; 656 657 return(_recvmsg(sock, &msg, 0)); 658}
| 649 msg.msg_controllen = sizeof(struct cmessage); 650 msg.msg_flags = 0; 651 652 return(_recvmsg(sock, &msg, 0)); 653}
|
659
| 654
|
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}
| 655static int 656__msgwrite(sock, buf, cnt) 657 int sock; 658 void *buf; 659 size_t cnt; 660{ 661 struct iovec iov[1]; 662 struct msghdr msg; 663 struct cmessage cm; 664 665 bzero((char *)&cm, sizeof(cm)); 666 iov[0].iov_base = buf; 667 iov[0].iov_len = cnt; 668 669 cm.cmsg.cmsg_type = SCM_CREDS; 670 cm.cmsg.cmsg_level = SOL_SOCKET; 671 cm.cmsg.cmsg_len = sizeof(struct cmessage); 672 673 msg.msg_iov = iov; 674 msg.msg_iovlen = 1; 675 msg.msg_name = NULL; 676 msg.msg_namelen = 0; 677 msg.msg_control = (caddr_t)&cm; 678 msg.msg_controllen = sizeof(struct cmessage); 679 msg.msg_flags = 0; 680 681 return(_sendmsg(sock, &msg, 0)); 682}
|
| 683 684/* 685 * Get the effective UID of the sending process. Used by rpcbind and keyserv 686 * (AF_LOCAL). 687 */ 688int 689__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) 690{ 691 struct cmsgcred *cmcred; 692 693 cmcred = __svc_getcallercreds(transp); 694 if (cmcred == NULL) 695 return(-1); 696 *uid = cmcred->cmcred_euid; 697 return(0); 698}
|
| |