📄 clnt_kudp.c
字号:
/* * Set timeout then wait for input, timeout * or interrupt. */#ifdef RPCDEBUG rpc_debug(3, "callit: waiting %d\n", timohz);#endif timeout(ckuwakeup, (caddr_t)p, timohz); so->so_rcv.sb_flags |= SB_WAIT;#if defined(ASYNCHIO) && defined(LWP) if (!runthreads) {#endif /* ASYNCHIO && LWP */ smask = pp->p_sigmask; pp->p_sigmask |= ~(sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM));#if defined(ASYNCHIO) && defined(LWP) }#endif /* ASYNCHIO && LWP */ /* * Hideous hack here for sunview locking bug * Please remove this when they fix their code */ pp->p_flag |= SRPC; interrupted = sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1 | PCATCH); pp->p_flag &= ~SRPC;#if defined(ASYNCHIO) && defined(LWP) if (!runthreads)#endif /* ASYNCHIO && LWP */ pp->p_sigmask = smask; untimeout(ckuwakeup, (caddr_t)p); if (interrupted) { (void) splx(s); p->cku_err.re_status = RPC_INTR; p->cku_err.re_errno = EINTR; goto done; } if (p->cku_flags & CKU_TIMEDOUT) { p->cku_flags &= ~CKU_TIMEDOUT; (void) splx(s); p->cku_err.re_status = RPC_TIMEDOUT; p->cku_err.re_errno = ETIMEDOUT; rcstat.rctimeouts++; goto done; } } if (so->so_error) { so->so_error = 0; (void) splx(s); continue; } { /* * Declare this variable here to have smaller * demand for stack space in this procedure. */ struct sockaddr_in from; p->cku_inmbuf = ku_recvfrom(so, &from); if (sin) { *sin = from; } } (void) splx(s); if (p->cku_inmbuf == NULL) { continue; } p->cku_inbuf = mtod(p->cku_inmbuf, char *); if (p->cku_inmbuf->m_len < sizeof (u_long)) { m_freem(p->cku_inmbuf); continue; } /* * If reply transaction id matches id sent * we have a good packet. */ if (*((u_long *)(p->cku_inbuf)) != *((u_long *)(p->cku_outbuf))) { rcstat.rcbadxids++; m_freem(p->cku_inmbuf); continue; } break; } if (rtries == 0) { p->cku_err.re_status = RPC_CANTRECV; p->cku_err.re_errno = EIO; goto done; } round_trip = time_in_hz - round_trip; /* * Van Jacobson timer algorithm here, only if NOT a retransmission. */ if (p->cku_timers != (struct rpc_timers *)0 && (stries == p->cku_retrys) && !ignorebad) { register int rt; rt = round_trip; rt -= (p->cku_timers->rt_srtt >> 3); p->cku_timers->rt_srtt += rt; if (rt < 0) rt = - rt; rt -= (p->cku_timers->rt_deviate >> 2); p->cku_timers->rt_deviate += rt; p->cku_timers->rt_rtxcur = ((p->cku_timers->rt_srtt >> 2) + p->cku_timers->rt_deviate) >> 1; rt = round_trip; rt -= (p->cku_timeall->rt_srtt >> 3); p->cku_timeall->rt_srtt += rt; if (rt < 0) rt = - rt; rt -= (p->cku_timeall->rt_deviate >> 2); p->cku_timeall->rt_deviate += rt; p->cku_timeall->rt_rtxcur = ((p->cku_timeall->rt_srtt >> 2) + p->cku_timeall->rt_deviate) >> 1; if (p->cku_feedback != (void (*)()) 0) (*p->cku_feedback)(FEEDBACK_OK, procnum, p->cku_feedarg); } /* * Process reply */ xdrs = &(p->cku_inxdr); xdrmbuf_init(xdrs, p->cku_inmbuf, XDR_DECODE); { /* * Declare this variable here to have smaller * demand for stack space in this procedure. */ struct rpc_msg reply_msg; reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xdr_results; /* * Decode and validate the response. */ if (xdr_replymsg(xdrs, &reply_msg)) { _seterr_reply(&reply_msg, &(p->cku_err)); if (p->cku_err.re_status == RPC_SUCCESS) { /* * Reply is good, check auth. */ if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { p->cku_err.re_status = RPC_AUTHERROR; p->cku_err.re_why = AUTH_INVALIDRESP; rcstat.rcbadverfs++; } if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { /* free auth handle */ xdrs->x_op = XDR_FREE; (void) xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); } } else { p->cku_err.re_errno = EIO; /* * Maybe our credential needs refreshed */ if (refreshes > 0 && AUTH_REFRESH(h->cl_auth)) { refreshes--; rcstat.rcnewcreds++; rempos = 0; } } } else { p->cku_err.re_status = RPC_CANTDECODERES; p->cku_err.re_errno = EIO; } } m_freem(p->cku_inmbuf);#ifdef RPCDEBUG rpc_debug(4, "cku_callit done\n");#endifdone: /* * Weed out remote rpc error replies. */ if (ignorebad && ((p->cku_err.re_status == RPC_VERSMISMATCH) || (p->cku_err.re_status == RPC_AUTHERROR) || (p->cku_err.re_status == RPC_PROGUNAVAIL) || (p->cku_err.re_status == RPC_PROGVERSMISMATCH) || (p->cku_err.re_status == RPC_PROCUNAVAIL) || (p->cku_err.re_status == RPC_CANTDECODEARGS) || (p->cku_err.re_status == RPC_SYSTEMERROR))) goto recv_again; /* * Flush the rest of the stuff on the input queue * for the socket. */ s = splnet(); sbflush(&so->so_rcv); (void) splx(s); if ((p->cku_err.re_status != RPC_SUCCESS) && (p->cku_err.re_status != RPC_INTR) && (p->cku_err.re_status != RPC_CANTENCODEARGS)) { if (p->cku_feedback != (void (*)()) 0 && stries == p->cku_retrys) (*p->cku_feedback)(FEEDBACK_REXMIT1, procnum, p->cku_feedarg); timohz = backoff(timohz); if (p->cku_timeall != (struct rpc_timers *)0) p->cku_timeall->rt_rtxcur = timohz; if (p->cku_err.re_status == RPC_SYSTEMERROR || p->cku_err.re_status == RPC_CANTSEND) { /* * Errors due to lack o resources, wait a bit * and try again. */ (void) sleep((caddr_t)&lbolt, PZERO-4); } if (--stries > 0) { rcstat.rcretrans++; goto call_again; } } u.u_cred = tmpcred; /* * Insure that buffer is not busy prior to releasing client handle. */ s = splimp(); while (p->cku_flags & CKU_BUFBUSY) { p->cku_flags |= CKU_BUFWANTED; timeout(wakeup, (caddr_t)&p->cku_outbuf, hz); (void) sleep((caddr_t)&p->cku_outbuf, PZERO-3); if (!(p->cku_flags & CKU_BUFBUSY)) { /* probably woke up from buffree */ untimeout(wakeup, (caddr_t)&p->cku_outbuf); } sbflush(&so->so_rcv); } (void) splx(s); p->cku_flags &= ~CKU_BUSY; if (p->cku_flags & CKU_WANTED) { p->cku_flags &= ~CKU_WANTED; wakeup((caddr_t)h); } if (p->cku_err.re_status != RPC_SUCCESS) { rcstat.rcbadcalls++; } return (p->cku_err.re_status);}enum clnt_statclntkudp_callit(h, procnum, xdr_args, argsp, xdr_results, resultsp, wait) register CLIENT *h; u_long procnum; xdrproc_t xdr_args; caddr_t argsp; xdrproc_t xdr_results; caddr_t resultsp; struct timeval wait;{ return (clntkudp_callit_addr(h, procnum, xdr_args, argsp, xdr_results, resultsp, wait, (struct sockaddr_in *)0, 0));}/* * Wake up client waiting for a reply. */ckuwakeup(p) register struct cku_private *p;{ register struct socket *so = p->cku_sock;#ifdef RPCDEBUG rpc_debug(4, "cku_timeout\n");#endif p->cku_flags |= CKU_TIMEDOUT; sbwakeup(so, &so->so_rcv);}/* * Return error info on this handle. */voidclntkudp_error(h, err) CLIENT *h; struct rpc_err *err;{ register struct cku_private *p = htop(h); *err = p->cku_err;}static bool_tclntkudp_freeres(cl, xdr_res, res_ptr) CLIENT *cl; xdrproc_t xdr_res; caddr_t res_ptr;{ register struct cku_private *p = (struct cku_private *)cl->cl_private; register XDR *xdrs = &(p->cku_outxdr); xdrs->x_op = XDR_FREE; return ((*xdr_res)(xdrs, res_ptr));}voidclntkudp_abort(){}bool_tclntkudp_control(){ return (FALSE);}/* * Destroy rpc handle. * Frees the space used for output buffer, private data, and handle * structure, and closes the socket for this handle. */voidclntkudp_destroy(h) CLIENT *h;{ register struct cku_private *p = htop(h);#ifdef RPCDEBUG rpc_debug(4, "cku_destroy %x\n", h);#endif (void) soclose(p->cku_sock); kmem_free((caddr_t)p->cku_outbuf, (u_int)UDPMSGSIZE); kmem_free((caddr_t)p, sizeof (*p));}/* * try to bind to a reserved port */bindresvport(so) struct socket *so;{ struct sockaddr_in *sin; struct mbuf *m; u_short i; int error; struct ucred *tmpcred; struct ucred *savecred;# define MAX_PRIV (IPPORT_RESERVED-1)# define MIN_PRIV (IPPORT_RESERVED/2) m = m_get(M_WAIT, MT_SONAME); if (m == NULL) { printf("bindresvport: couldn't alloc mbuf"); return (ENOBUFS); } sin = mtod(m, struct sockaddr_in *); sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; m->m_len = sizeof (struct sockaddr_in); /* * Only root can bind to a privileged port number, so * temporarily change the uid to 0 to do the bind. */ tmpcred = crdup(u.u_cred); savecred = u.u_cred; u.u_cred = tmpcred; u.u_uid = 0; error = EADDRINUSE; for (i = MAX_PRIV; error == EADDRINUSE && i >= MIN_PRIV; i--) { sin->sin_port = htons(i); error = sobind(so, m); } (void) m_freem(m); u.u_cred = savecred; crfree(tmpcred); return (error);}#endif KERNEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -