FreeBSD/Linux Kernel Cross Reference
sys/rpc/svc_vc.c
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)
33 static char *sccsid2 = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
34 static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
35 #endif
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: src/sys/rpc/svc_vc.c,v 1.4 2008/11/03 10:38:00 dfr Exp $");
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 <sys/param.h>
48 #include <sys/lock.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #include <sys/mbuf.h>
52 #include <sys/mutex.h>
53 #include <sys/protosw.h>
54 #include <sys/queue.h>
55 #include <sys/socket.h>
56 #include <sys/socketvar.h>
57 #include <sys/sx.h>
58 #include <sys/systm.h>
59 #include <sys/uio.h>
60 #include <netinet/tcp.h>
61
62 #include <rpc/rpc.h>
63
64 #include <rpc/rpc_com.h>
65
66 static bool_t svc_vc_rendezvous_recv(SVCXPRT *, struct rpc_msg *,
67 struct sockaddr **, struct mbuf **);
68 static enum xprt_stat svc_vc_rendezvous_stat(SVCXPRT *);
69 static void svc_vc_rendezvous_destroy(SVCXPRT *);
70 static bool_t svc_vc_null(void);
71 static void svc_vc_destroy(SVCXPRT *);
72 static enum xprt_stat svc_vc_stat(SVCXPRT *);
73 static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *,
74 struct sockaddr **, struct mbuf **);
75 static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *,
76 struct sockaddr *, struct mbuf *);
77 static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
78 static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
79 void *in);
80 static SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so,
81 struct sockaddr *raddr);
82 static int svc_vc_accept(struct socket *head, struct socket **sop);
83 static void svc_vc_soupcall(struct socket *so, void *arg, int waitflag);
84
85 static struct xp_ops svc_vc_rendezvous_ops = {
86 .xp_recv = svc_vc_rendezvous_recv,
87 .xp_stat = svc_vc_rendezvous_stat,
88 .xp_reply = (bool_t (*)(SVCXPRT *, struct rpc_msg *,
89 struct sockaddr *, struct mbuf *))svc_vc_null,
90 .xp_destroy = svc_vc_rendezvous_destroy,
91 .xp_control = svc_vc_rendezvous_control
92 };
93
94 static struct xp_ops svc_vc_ops = {
95 .xp_recv = svc_vc_recv,
96 .xp_stat = svc_vc_stat,
97 .xp_reply = svc_vc_reply,
98 .xp_destroy = svc_vc_destroy,
99 .xp_control = svc_vc_control
100 };
101
102 struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
103 enum xprt_stat strm_stat;
104 struct mbuf *mpending; /* unparsed data read from the socket */
105 struct mbuf *mreq; /* current record being built from mpending */
106 uint32_t resid; /* number of bytes needed for fragment */
107 bool_t eor; /* reading last fragment of current record */
108 };
109
110 /*
111 * Usage:
112 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
113 *
114 * Creates, registers, and returns a (rpc) tcp based transporter.
115 * Once *xprt is initialized, it is registered as a transporter
116 * see (svc.h, xprt_register). This routine returns
117 * a NULL if a problem occurred.
118 *
119 * The filedescriptor passed in is expected to refer to a bound, but
120 * not yet connected socket.
121 *
122 * Since streams do buffered io similar to stdio, the caller can specify
123 * how big the send and receive buffers are via the second and third parms;
124 * 0 => use the system default.
125 */
126 SVCXPRT *
127 svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
128 size_t recvsize)
129 {
130 SVCXPRT *xprt;
131 struct sockaddr* sa;
132 int error;
133
134 if (so->so_state & SS_ISCONNECTED) {
135 error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
136 if (error)
137 return (NULL);
138 xprt = svc_vc_create_conn(pool, so, sa);
139 free(sa, M_SONAME);
140 return (xprt);
141 }
142
143 xprt = svc_xprt_alloc();
144 sx_init(&xprt->xp_lock, "xprt->xp_lock");
145 xprt->xp_pool = pool;
146 xprt->xp_socket = so;
147 xprt->xp_p1 = NULL;
148 xprt->xp_p2 = NULL;
149 xprt->xp_ops = &svc_vc_rendezvous_ops;
150
151 error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
152 if (error)
153 goto cleanup_svc_vc_create;
154
155 memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
156 free(sa, M_SONAME);
157
158 xprt_register(xprt);
159
160 solisten(so, SOMAXCONN, curthread);
161
162 SOCKBUF_LOCK(&so->so_rcv);
163 so->so_upcallarg = xprt;
164 so->so_upcall = svc_vc_soupcall;
165 so->so_rcv.sb_flags |= SB_UPCALL;
166 SOCKBUF_UNLOCK(&so->so_rcv);
167
168 return (xprt);
169 cleanup_svc_vc_create:
170 if (xprt)
171 svc_xprt_free(xprt);
172 return (NULL);
173 }
174
175 /*
176 * Create a new transport for a socket optained via soaccept().
177 */
178 SVCXPRT *
179 svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
180 {
181 SVCXPRT *xprt = NULL;
182 struct cf_conn *cd = NULL;
183 struct sockaddr* sa = NULL;
184 struct sockopt opt;
185 int one = 1;
186 int error;
187
188 bzero(&opt, sizeof(struct sockopt));
189 opt.sopt_dir = SOPT_SET;
190 opt.sopt_level = SOL_SOCKET;
191 opt.sopt_name = SO_KEEPALIVE;
192 opt.sopt_val = &one;
193 opt.sopt_valsize = sizeof(one);
194 error = sosetopt(so, &opt);
195 if (error)
196 return (NULL);
197
198 if (so->so_proto->pr_protocol == IPPROTO_TCP) {
199 bzero(&opt, sizeof(struct sockopt));
200 opt.sopt_dir = SOPT_SET;
201 opt.sopt_level = IPPROTO_TCP;
202 opt.sopt_name = TCP_NODELAY;
203 opt.sopt_val = &one;
204 opt.sopt_valsize = sizeof(one);
205 error = sosetopt(so, &opt);
206 if (error)
207 return (NULL);
208 }
209
210 cd = mem_alloc(sizeof(*cd));
211 cd->strm_stat = XPRT_IDLE;
212
213 xprt = svc_xprt_alloc();
214 sx_init(&xprt->xp_lock, "xprt->xp_lock");
215 xprt->xp_pool = pool;
216 xprt->xp_socket = so;
217 xprt->xp_p1 = cd;
218 xprt->xp_p2 = NULL;
219 xprt->xp_ops = &svc_vc_ops;
220
221 /*
222 * See http://www.connectathon.org/talks96/nfstcp.pdf - client
223 * has a 5 minute timer, server has a 6 minute timer.
224 */
225 xprt->xp_idletimeout = 6 * 60;
226
227 memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len);
228
229 error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
230 if (error)
231 goto cleanup_svc_vc_create;
232
233 memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
234 free(sa, M_SONAME);
235
236 xprt_register(xprt);
237
238 SOCKBUF_LOCK(&so->so_rcv);
239 so->so_upcallarg = xprt;
240 so->so_upcall = svc_vc_soupcall;
241 so->so_rcv.sb_flags |= SB_UPCALL;
242 SOCKBUF_UNLOCK(&so->so_rcv);
243
244 /*
245 * Throw the transport into the active list in case it already
246 * has some data buffered.
247 */
248 sx_xlock(&xprt->xp_lock);
249 xprt_active(xprt);
250 sx_xunlock(&xprt->xp_lock);
251
252 return (xprt);
253 cleanup_svc_vc_create:
254 if (xprt) {
255 mem_free(xprt, sizeof(*xprt));
256 }
257 if (cd)
258 mem_free(cd, sizeof(*cd));
259 return (NULL);
260 }
261
262 /*
263 * This does all of the accept except the final call to soaccept. The
264 * caller will call soaccept after dropping its locks (soaccept may
265 * call malloc).
266 */
267 int
268 svc_vc_accept(struct socket *head, struct socket **sop)
269 {
270 int error = 0;
271 struct socket *so;
272
273 if ((head->so_options & SO_ACCEPTCONN) == 0) {
274 error = EINVAL;
275 goto done;
276 }
277 #ifdef MAC
278 SOCK_LOCK(head);
279 error = mac_socket_check_accept(td->td_ucred, head);
280 SOCK_UNLOCK(head);
281 if (error != 0)
282 goto done;
283 #endif
284 ACCEPT_LOCK();
285 if (TAILQ_EMPTY(&head->so_comp)) {
286 ACCEPT_UNLOCK();
287 error = EWOULDBLOCK;
288 goto done;
289 }
290 so = TAILQ_FIRST(&head->so_comp);
291 KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP"));
292 KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP"));
293
294 /*
295 * Before changing the flags on the socket, we have to bump the
296 * reference count. Otherwise, if the protocol calls sofree(),
297 * the socket will be released due to a zero refcount.
298 * XXX might not need soref() since this is simpler than kern_accept.
299 */
300 SOCK_LOCK(so); /* soref() and so_state update */
301 soref(so); /* file descriptor reference */
302
303 TAILQ_REMOVE(&head->so_comp, so, so_list);
304 head->so_qlen--;
305 so->so_state |= (head->so_state & SS_NBIO);
306 so->so_qstate &= ~SQ_COMP;
307 so->so_head = NULL;
308
309 SOCK_UNLOCK(so);
310 ACCEPT_UNLOCK();
311
312 *sop = so;
313
314 /* connection has been removed from the listen queue */
315 KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
316 done:
317 return (error);
318 }
319
320 /*ARGSUSED*/
321 static bool_t
322 svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg,
323 struct sockaddr **addrp, struct mbuf **mp)
324 {
325 struct socket *so = NULL;
326 struct sockaddr *sa = NULL;
327 int error;
328
329 /*
330 * The socket upcall calls xprt_active() which will eventually
331 * cause the server to call us here. We attempt to accept a
332 * connection from the socket and turn it into a new
333 * transport. If the accept fails, we have drained all pending
334 * connections so we call xprt_inactive().
335 */
336 sx_xlock(&xprt->xp_lock);
337
338 error = svc_vc_accept(xprt->xp_socket, &so);
339
340 if (error == EWOULDBLOCK) {
341 /*
342 * We must re-test for new connections after taking
343 * the lock to protect us in the case where a new
344 * connection arrives after our call to accept fails
345 * with EWOULDBLOCK. The pool lock protects us from
346 * racing the upcall after our TAILQ_EMPTY() call
347 * returns false.
348 */
349 ACCEPT_LOCK();
350 mtx_lock(&xprt->xp_pool->sp_lock);
351 if (TAILQ_EMPTY(&xprt->xp_socket->so_comp))
352 xprt_inactive_locked(xprt);
353 mtx_unlock(&xprt->xp_pool->sp_lock);
354 ACCEPT_UNLOCK();
355 sx_xunlock(&xprt->xp_lock);
356 return (FALSE);
357 }
358
359 if (error) {
360 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
361 xprt->xp_socket->so_upcallarg = NULL;
362 xprt->xp_socket->so_upcall = NULL;
363 xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL;
364 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
365 xprt_inactive(xprt);
366 sx_xunlock(&xprt->xp_lock);
367 return (FALSE);
368 }
369
370 sx_xunlock(&xprt->xp_lock);
371
372 sa = 0;
373 error = soaccept(so, &sa);
374
375 if (error) {
376 /*
377 * XXX not sure if I need to call sofree or soclose here.
378 */
379 if (sa)
380 free(sa, M_SONAME);
381 return (FALSE);
382 }
383
384 /*
385 * svc_vc_create_conn will call xprt_register - we don't need
386 * to do anything with the new connection.
387 */
388 if (!svc_vc_create_conn(xprt->xp_pool, so, sa))
389 soclose(so);
390
391 free(sa, M_SONAME);
392
393 return (FALSE); /* there is never an rpc msg to be processed */
394 }
395
396 /*ARGSUSED*/
397 static enum xprt_stat
398 svc_vc_rendezvous_stat(SVCXPRT *xprt)
399 {
400
401 return (XPRT_IDLE);
402 }
403
404 static void
405 svc_vc_destroy_common(SVCXPRT *xprt)
406 {
407 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
408 xprt->xp_socket->so_upcallarg = NULL;
409 xprt->xp_socket->so_upcall = NULL;
410 xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL;
411 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
412
413 sx_destroy(&xprt->xp_lock);
414 if (xprt->xp_socket)
415 (void)soclose(xprt->xp_socket);
416
417 if (xprt->xp_netid)
418 (void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
419 svc_xprt_free(xprt);
420 }
421
422 static void
423 svc_vc_rendezvous_destroy(SVCXPRT *xprt)
424 {
425
426 svc_vc_destroy_common(xprt);
427 }
428
429 static void
430 svc_vc_destroy(SVCXPRT *xprt)
431 {
432 struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
433
434 svc_vc_destroy_common(xprt);
435
436 if (cd->mreq)
437 m_freem(cd->mreq);
438 if (cd->mpending)
439 m_freem(cd->mpending);
440 mem_free(cd, sizeof(*cd));
441 }
442
443 /*ARGSUSED*/
444 static bool_t
445 svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
446 {
447 return (FALSE);
448 }
449
450 static bool_t
451 svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
452 {
453
454 return (FALSE);
455 }
456
457 static enum xprt_stat
458 svc_vc_stat(SVCXPRT *xprt)
459 {
460 struct cf_conn *cd;
461 struct mbuf *m;
462 size_t n;
463
464 cd = (struct cf_conn *)(xprt->xp_p1);
465
466 if (cd->strm_stat == XPRT_DIED)
467 return (XPRT_DIED);
468
469 /*
470 * Return XPRT_MOREREQS if we have buffered data and we are
471 * mid-record or if we have enough data for a record
472 * marker. Since this is only a hint, we read mpending and
473 * resid outside the lock. We do need to take the lock if we
474 * have to traverse the mbuf chain.
475 */
476 if (cd->mpending) {
477 if (cd->resid)
478 return (XPRT_MOREREQS);
479 n = 0;
480 sx_xlock(&xprt->xp_lock);
481 m = cd->mpending;
482 while (m && n < sizeof(uint32_t)) {
483 n += m->m_len;
484 m = m->m_next;
485 }
486 sx_xunlock(&xprt->xp_lock);
487 if (n >= sizeof(uint32_t))
488 return (XPRT_MOREREQS);
489 }
490
491 if (soreadable(xprt->xp_socket))
492 return (XPRT_MOREREQS);
493
494 return (XPRT_IDLE);
495 }
496
497 static bool_t
498 svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
499 struct sockaddr **addrp, struct mbuf **mp)
500 {
501 struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
502 struct uio uio;
503 struct mbuf *m;
504 XDR xdrs;
505 int error, rcvflag;
506
507 /*
508 * Serialise access to the socket and our own record parsing
509 * state.
510 */
511 sx_xlock(&xprt->xp_lock);
512
513 for (;;) {
514 /*
515 * If we have an mbuf chain in cd->mpending, try to parse a
516 * record from it, leaving the result in cd->mreq. If we don't
517 * have a complete record, leave the partial result in
518 * cd->mreq and try to read more from the socket.
519 */
520 if (cd->mpending) {
521 /*
522 * If cd->resid is non-zero, we have part of the
523 * record already, otherwise we are expecting a record
524 * marker.
525 */
526 if (!cd->resid) {
527 /*
528 * See if there is enough data buffered to
529 * make up a record marker. Make sure we can
530 * handle the case where the record marker is
531 * split across more than one mbuf.
532 */
533 size_t n = 0;
534 uint32_t header;
535
536 m = cd->mpending;
537 while (n < sizeof(uint32_t) && m) {
538 n += m->m_len;
539 m = m->m_next;
540 }
541 if (n < sizeof(uint32_t))
542 goto readmore;
543 if (cd->mpending->m_len < sizeof(uint32_t))
544 cd->mpending = m_pullup(cd->mpending,
545 sizeof(uint32_t));
546 memcpy(&header, mtod(cd->mpending, uint32_t *),
547 sizeof(header));
548 header = ntohl(header);
549 cd->eor = (header & 0x80000000) != 0;
550 cd->resid = header & 0x7fffffff;
551 m_adj(cd->mpending, sizeof(uint32_t));
552 }
553
554 /*
555 * Start pulling off mbufs from cd->mpending
556 * until we either have a complete record or
557 * we run out of data. We use m_split to pull
558 * data - it will pull as much as possible and
559 * split the last mbuf if necessary.
560 */
561 while (cd->mpending && cd->resid) {
562 m = cd->mpending;
563 if (cd->mpending->m_next
564 || cd->mpending->m_len > cd->resid)
565 cd->mpending = m_split(cd->mpending,
566 cd->resid, M_WAIT);
567 else
568 cd->mpending = NULL;
569 if (cd->mreq)
570 m_last(cd->mreq)->m_next = m;
571 else
572 cd->mreq = m;
573 while (m) {
574 cd->resid -= m->m_len;
575 m = m->m_next;
576 }
577 }
578
579 /*
580 * If cd->resid is zero now, we have managed to
581 * receive a record fragment from the stream. Check
582 * for the end-of-record mark to see if we need more.
583 */
584 if (cd->resid == 0) {
585 if (!cd->eor)
586 continue;
587
588 /*
589 * Success - we have a complete record in
590 * cd->mreq.
591 */
592 xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
593 cd->mreq = NULL;
594 sx_xunlock(&xprt->xp_lock);
595
596 if (! xdr_callmsg(&xdrs, msg)) {
597 XDR_DESTROY(&xdrs);
598 return (FALSE);
599 }
600
601 *addrp = NULL;
602 *mp = xdrmbuf_getall(&xdrs);
603 XDR_DESTROY(&xdrs);
604
605 return (TRUE);
606 }
607 }
608
609 readmore:
610 /*
611 * The socket upcall calls xprt_active() which will eventually
612 * cause the server to call us here. We attempt to
613 * read as much as possible from the socket and put
614 * the result in cd->mpending. If the read fails,
615 * we have drained both cd->mpending and the socket so
616 * we can call xprt_inactive().
617 */
618 uio.uio_resid = 1000000000;
619 uio.uio_td = curthread;
620 m = NULL;
621 rcvflag = MSG_DONTWAIT;
622 error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL,
623 &rcvflag);
624
625 if (error == EWOULDBLOCK) {
626 /*
627 * We must re-test for readability after
628 * taking the lock to protect us in the case
629 * where a new packet arrives on the socket
630 * after our call to soreceive fails with
631 * EWOULDBLOCK. The pool lock protects us from
632 * racing the upcall after our soreadable()
633 * call returns false.
634 */
635 mtx_lock(&xprt->xp_pool->sp_lock);
636 if (!soreadable(xprt->xp_socket))
637 xprt_inactive_locked(xprt);
638 mtx_unlock(&xprt->xp_pool->sp_lock);
639 sx_xunlock(&xprt->xp_lock);
640 return (FALSE);
641 }
642
643 if (error) {
644 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
645 xprt->xp_socket->so_upcallarg = NULL;
646 xprt->xp_socket->so_upcall = NULL;
647 xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL;
648 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
649 xprt_inactive(xprt);
650 cd->strm_stat = XPRT_DIED;
651 sx_xunlock(&xprt->xp_lock);
652 return (FALSE);
653 }
654
655 if (!m) {
656 /*
657 * EOF - the other end has closed the socket.
658 */
659 xprt_inactive(xprt);
660 cd->strm_stat = XPRT_DIED;
661 sx_xunlock(&xprt->xp_lock);
662 return (FALSE);
663 }
664
665 if (cd->mpending)
666 m_last(cd->mpending)->m_next = m;
667 else
668 cd->mpending = m;
669 }
670 }
671
672 static bool_t
673 svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
674 struct sockaddr *addr, struct mbuf *m)
675 {
676 XDR xdrs;
677 struct mbuf *mrep;
678 bool_t stat = TRUE;
679 int error;
680
681 /*
682 * Leave space for record mark.
683 */
684 MGETHDR(mrep, M_WAIT, MT_DATA);
685 mrep->m_len = 0;
686 mrep->m_data += sizeof(uint32_t);
687
688 xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
689
690 if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
691 msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
692 if (!xdr_replymsg(&xdrs, msg))
693 stat = FALSE;
694 else
695 xdrmbuf_append(&xdrs, m);
696 } else {
697 stat = xdr_replymsg(&xdrs, msg);
698 }
699
700 if (stat) {
701 m_fixhdr(mrep);
702
703 /*
704 * Prepend a record marker containing the reply length.
705 */
706 M_PREPEND(mrep, sizeof(uint32_t), M_WAIT);
707 *mtod(mrep, uint32_t *) =
708 htonl(0x80000000 | (mrep->m_pkthdr.len
709 - sizeof(uint32_t)));
710 error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL,
711 0, curthread);
712 if (!error) {
713 stat = TRUE;
714 }
715 } else {
716 m_freem(mrep);
717 }
718
719 XDR_DESTROY(&xdrs);
720 xprt->xp_p2 = NULL;
721
722 return (stat);
723 }
724
725 static bool_t
726 svc_vc_null()
727 {
728
729 return (FALSE);
730 }
731
732 static void
733 svc_vc_soupcall(struct socket *so, void *arg, int waitflag)
734 {
735 SVCXPRT *xprt = (SVCXPRT *) arg;
736
737 xprt_active(xprt);
738 }
739
740 #if 0
741 /*
742 * Get the effective UID of the sending process. Used by rpcbind, keyserv
743 * and rpc.yppasswdd on AF_LOCAL.
744 */
745 int
746 __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
747 int sock, ret;
748 gid_t egid;
749 uid_t euid;
750 struct sockaddr *sa;
751
752 sock = transp->xp_fd;
753 sa = (struct sockaddr *)transp->xp_rtaddr;
754 if (sa->sa_family == AF_LOCAL) {
755 ret = getpeereid(sock, &euid, &egid);
756 if (ret == 0)
757 *uid = euid;
758 return (ret);
759 } else
760 return (-1);
761 }
762 #endif
763
|