📄 tp_usrreq.c
字号:
struct mbuf *m, *nam, *controlp;{ register struct tp_pcb *tpcb = sototpcb(so); int s = splnet(); int error = 0; int flags, *outflags = &flags; u_long eotsdu = 0; struct tp_event E; IFDEBUG(D_REQUEST) printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); if (so->so_error) printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); ENDDEBUG IFTRACE(D_REQUEST) tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, tpcb?tpcb->tp_state:0); ENDTRACE if ((u_int)tpcb == 0 && req != PRU_ATTACH) { IFTRACE(D_REQUEST) tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); ENDTRACE splx(s); return ENOTCONN; } switch (req) { case PRU_ATTACH: if (tpcb) { error = EISCONN; } else if ((error = tp_attach(so, (int)nam)) == 0) tpcb = sototpcb(so); break; case PRU_ABORT: /* called from close() */ /* called for each incoming connect queued on the * parent (accepting) socket */ if (tpcb->tp_state == TP_OPEN || tpcb->tp_state == TP_CONFIRMING) { E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; error = DoEvent(T_DISC_req); /* pretend it was a close() */ break; } /* else DROP THROUGH */ case PRU_DETACH: /* called from close() */ /* called only after disconnect was called */ error = DoEvent(T_DETACH); if (tpcb->tp_state == TP_CLOSED) { if (tpcb->tp_notdetached) { IFDEBUG(D_CONN) printf("PRU_DETACH: not detached\n"); ENDDEBUG tp_detach(tpcb); } free((caddr_t)tpcb, M_PCB); tpcb = 0; } break; case PRU_SHUTDOWN: /* recv end may have been released; local credit might be zero */ case PRU_DISCONNECT: E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; error = DoEvent(T_DISC_req); break; case PRU_BIND: error = tp_pcbbind(tpcb, nam); break; case PRU_LISTEN: if (tpcb->tp_state != TP_CLOSED || tpcb->tp_lsuffixlen == 0 || tpcb->tp_next == 0) error = EINVAL; else { register struct tp_pcb **tt; remque(tpcb); tpcb->tp_next = tpcb->tp_prev = tpcb; for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) if ((*tt)->tp_lsuffixlen) break; tpcb->tp_nextlisten = *tt; *tt = tpcb; error = DoEvent(T_LISTEN_req); } break; case PRU_CONNECT2: error = EOPNOTSUPP; /* for unix domain sockets */ break; case PRU_CONNECT: IFTRACE(D_CONN) tptraceTPCB(TPPTmisc, "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, tpcb->tp_class); ENDTRACE IFDEBUG(D_CONN) printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, tpcb->tp_class); ENDDEBUG if (tpcb->tp_lsuffixlen == 0) { if (error = tp_pcbbind(tpcb, MNULL)) { IFDEBUG(D_CONN) printf("pcbbind returns error 0x%x\n", error); ENDDEBUG break; } } IFDEBUG(D_CONN) printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); dump_buf(tpcb->tp_npcb, 16); ENDDEBUG if (error = tp_route_to(nam, tpcb, /* channel */0)) break; IFDEBUG(D_CONN) printf( "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); dump_buf(tpcb->tp_npcb, 16); ENDDEBUG if (tpcb->tp_fsuffixlen == 0) { /* didn't set peer extended suffix */ (tpcb->tp_nlproto->nlp_getsufx)(tpcb->tp_npcb, &tpcb->tp_fsuffixlen, tpcb->tp_fsuffix, TP_FOREIGN); } if (tpcb->tp_state == TP_CLOSED) { soisconnecting(so); error = DoEvent(T_CONN_req); } else { (tpcb->tp_nlproto->nlp_pcbdisc)(tpcb->tp_npcb); error = EISCONN; } IFPERF(tpcb) u_int lsufx, fsufx; lsufx = *(u_short *)(tpcb->tp_lsuffix); fsufx = *(u_short *)(tpcb->tp_fsuffix); tpmeas(tpcb->tp_lref, TPtime_open | (tpcb->tp_xtd_format << 4), &time, lsufx, fsufx, tpcb->tp_fref); ENDPERF break; case PRU_ACCEPT: (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN); IFDEBUG(D_REQUEST) printf("ACCEPT PEERADDDR:"); dump_buf(mtod(nam, char *), nam->m_len); ENDDEBUG IFPERF(tpcb) u_int lsufx, fsufx; lsufx = *(u_short *)(tpcb->tp_lsuffix); fsufx = *(u_short *)(tpcb->tp_fsuffix); tpmeas(tpcb->tp_lref, TPtime_open, &time, lsufx, fsufx, tpcb->tp_fref); ENDPERF break; case PRU_RCVD: if (so->so_state & SS_ISCONFIRMING) { if (tpcb->tp_state == TP_CONFIRMING) error = tp_confirm(tpcb); break; } IFTRACE(D_DATA) tptraceTPCB(TPPTmisc, "RCVD BF: lcredit sent_lcdt cc hiwat \n", tpcb->tp_lcredit, tpcb->tp_sent_lcdt, so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); LOCAL_CREDIT(tpcb); tptraceTPCB(TPPTmisc, "PRU_RCVD AF sbspace lcredit hiwat cc", sbspace(&so->so_rcv), tpcb->tp_lcredit, so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); ENDTRACE IFDEBUG(D_REQUEST) printf("RCVD: cc %d space %d hiwat %d\n", so->so_rcv.sb_cc, sbspace(&so->so_rcv), so->so_rcv.sb_hiwat); ENDDEBUG if (((int)nam) & MSG_OOB) error = DoEvent(T_USR_Xrcvd); else error = DoEvent(T_USR_rcvd); break; case PRU_RCVOOB: if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; break; } if (! tpcb->tp_xpd_service) { error = EOPNOTSUPP; break; } /* kludge - nam is really flags here */ error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); break; case PRU_SEND: case PRU_SENDOOB: if (controlp) { error = tp_snd_control(controlp, so, &m); controlp = NULL; if (error) break; } if ((so->so_state & SS_ISCONFIRMING) && (tpcb->tp_state == TP_CONFIRMING) && (error = tp_confirm(tpcb))) break; if (req == PRU_SENDOOB) { error = (tpcb->tp_xpd_service == 0) ? EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags); break; } if (m == 0) break; if (m->m_flags & M_EOR) { eotsdu = 1; m->m_flags &= ~M_EOR; } if (eotsdu == 0 && m->m_pkthdr.len == 0) break; if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) { error = ENOTCONN; break; } /* * The protocol machine copies mbuf chains, * prepends headers, assigns seq numbers, and * puts the packets on the device. * When they are acked they are removed from the socket buf. * * sosend calls this up until sbspace goes negative. * Sbspace may be made negative by appending this mbuf chain, * possibly by a whole cluster. */ { /* * Could have eotsdu and no data.(presently MUST have * an mbuf though, even if its length == 0) */ int totlen = m->m_pkthdr.len; struct sockbuf *sb = &so->so_snd; IFPERF(tpcb) PStat(tpcb, Nb_from_sess) += totlen; tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, PStat(tpcb, Nb_from_sess), totlen); ENDPERF IFDEBUG(D_SYSCALL) printf( "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", eotsdu, m, totlen, sb); dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); dump_mbuf(m, "m : to be added"); ENDDEBUG tp_packetize(tpcb, m, eotsdu); IFDEBUG(D_SYSCALL) printf("PRU_SEND: eot %d after sbappend 0x%x\n", eotsdu, m); dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); ENDDEBUG if (tpcb->tp_state == TP_OPEN) error = DoEvent(T_DATA_req); IFDEBUG(D_SYSCALL) printf("PRU_SEND: after driver error 0x%x \n",error); printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", sb, sb->sb_cc, sb->sb_mbcnt); dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); ENDDEBUG } break; case PRU_SOCKADDR: (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_LOCAL); break; case PRU_PEERADDR: (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN); break; case PRU_CONTROL: error = EOPNOTSUPP; break; case PRU_PROTOSEND: case PRU_PROTORCV: case PRU_SENSE: case PRU_SLOWTIMO: case PRU_FASTTIMO: error = EOPNOTSUPP; break; default:#ifdef ARGO_DEBUG printf("tp_usrreq UNKNOWN PRU %d\n", req);#endif /* ARGO_DEBUG */ error = EOPNOTSUPP; } IFDEBUG(D_REQUEST) printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", "returning from tp_usrreq", so, tpcb, error, tpcb ? tpcb->tp_state : 0); ENDDEBUG IFTRACE(D_REQUEST) tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, tpcb ? tpcb->tp_state : 0); ENDTRACE if (controlp) { m_freem(controlp); printf("control data unexpectedly retained in tp_usrreq()"); } splx(s); return error;}tp_ltrace(so, uio)struct socket *so;struct uio *uio;{ IFTRACE(D_DATA) register struct tp_pcb *tpcb = sototpcb(so); if (tpcb) { tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, uio->uio_resid, uio->uio_iovcnt, 0); } ENDTRACE}tp_confirm(tpcb)register struct tp_pcb *tpcb;{ struct tp_event E; if (tpcb->tp_state == TP_CONFIRMING) return DoEvent(T_ACPT_req); printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", tpcb, tpcb->tp_state); return 0;}/* * Process control data sent with sendmsg() */tp_snd_control(m, so, data) struct mbuf *m; struct socket *so; register struct mbuf **data;{ register struct cmsghdr *ch; int error = 0; if (m && m->m_len) { ch = mtod(m, struct cmsghdr *); m->m_len -= sizeof (*ch); m->m_data += sizeof (*ch); error = tp_ctloutput(PRCO_SETOPT, so, ch->cmsg_level, ch->cmsg_type, &m); if (ch->cmsg_type == TPOPT_DISC_DATA) { if (data && *data) { m_freem(*data); *data = 0; } error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, (caddr_t)0, (struct mbuf *)0); } } if (m) m_freem(m); return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -