📄 tcp_subr.c
字号:
int errno;{ struct socket *so = tp->t_inpcb->inp_socket; int s; if (smp_debug){ if (smp_owner(&so->lk_socket) == 0) panic("tcp_drop not lock owner"); } if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); TCPSTAT(tcps_drops++); } else{ TCPSTAT(tcps_conndrops++); } so->so_error = errno; return (tcp_close(tp));}/* * Close a TCP control block: * discard all space held by the tcp * discard internet protocol block * wake up any sleepers *//* SMP: Enter with a socket lock set. */struct tcpcb *tcp_close(tp) register struct tcpcb *tp;{ register struct tcpiphdr *t; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; register struct mbuf *m; int s; /* SMP */ struct socket *so_tmp = NULL; /* SMP */ int status = 0; /* SMP */ struct inpcb *inp_tmp = NULL; /* SMP */ struct socket *so_addr = NULL; /* SMP */ if (smp_debug){ if (smp_owner(&so->lk_socket) == 0) panic("tcp_close not lock owner"); } t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { t = (struct tcpiphdr *)t->ti_next; m = dtom(t->ti_prev); remque(t->ti_prev); m_freem(m); } if (tp->t_template) (void) m_free(dtom(tp->t_template)); /* Note that the manipulation with owner and the lk_tcb here * is due to the fact that when we are called from the timers, * lk_tcb is already set. */ if (smp){ if (smp_owner(&lk_tcb) == 1){#ifdef old (void) m_free(dtom(tp));#endif KM_FREE(tp, KM_PCB); inp->inp_ppcb = 0; soisdisconnected(so); in_pcbdetach(inp); TCPSTAT(tcps_closed++); return ((struct tcpcb *)0); } { int owner = 0; if (( so->so_head) && (smp_owner(&so->so_head->lk_socket)) == 1){ owner = 1; so->so_head->ref = 28; smp_unlock(&so->so_head->lk_socket); } so->ref = 10; smp_unlock(&so->lk_socket); smp_lock(&lk_tcb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; if (owner){ smp_lock(&so->so_head->lk_socket, LK_RETRY); so->so_head->ref = 0; owner = 0; } } } #ifdef old (void) m_free(dtom(tp));#endif KM_FREE(tp, KM_PCB); inp->inp_ppcb = 0; soisdisconnected(so); in_pcbdetach(inp); smp_unlock(&lk_tcb); TCPSTAT(tcps_closed++); return ((struct tcpcb *)0);}tcp_drain(){}/* * Notify a tcp user of an asynchronous error; * just wake up so that he can collect error status. */tcp_notify(inp) register struct inpcb *inp;{ /* Ensure that socket is locked before * doing wakeups because low level wakeup routines write * to the socket. */ /* Note that here, lk_tcb is already held so if we use * SO_LOCK, then SO_LOCK could find so->ref busy and spin * with lk_tcb held. This could result in a starvation * panic on lk_tcb. */ smp_lock(&inp->inp_socket->lk_socket, LK_RETRY); wakeup((caddr_t) &inp->inp_socket->so_timeo); sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); smp_unlock(&inp->inp_socket->lk_socket);}tcp_ctlinput(cmd, sa) int cmd; struct sockaddr *sa;{ extern u_char inetctlerrmap[]; struct sockaddr_in *sin; int tcp_quench(), in_rtchange(); int s; if ((unsigned) cmd > PRC_NCMDS) return; if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) return; sin = (struct sockaddr_in *)sa; if (sin->sin_addr.s_addr == INADDR_ANY) return; switch (cmd) { case PRC_QUENCH: s = splnet(); smp_lock(&lk_tcb, LK_RETRY); in_pcbnotify(&tcb, &sin->sin_addr, 0, tcp_quench); smp_unlock(&lk_tcb); splx(s); break; case PRC_ROUTEDEAD: case PRC_REDIRECT_NET: case PRC_REDIRECT_HOST: case PRC_REDIRECT_TOSNET: case PRC_REDIRECT_TOSHOST: s = splnet(); /* SMP */ smp_lock(&lk_tcb, LK_RETRY); in_pcbnotify(&tcb, &sin->sin_addr, 0, in_rtchange); smp_unlock(&lk_tcb); splx(s); break; default: if (inetctlerrmap[cmd] == 0) return; /* XXX */ s = splnet(); /* SMP */ smp_lock(&lk_tcb, LK_RETRY); in_pcbnotify(&tcb, &sin->sin_addr, (int)inetctlerrmap[cmd], tcp_notify); smp_unlock(&lk_tcb); splx(s); }}/* * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */tcp_quench(inp) struct inpcb *inp;{ struct tcpcb *tp = intotcpcb(inp); if(tp) tp->snd_cwnd = tp->t_maxseg;}#ifdef XTI/* * KEY * --- * so - socket pointer * inp - internet control block pointer * tp - tcp control block pointer * fd - file desciptor * * STATE MINIMUM MAPPING * ---------- ----------------------------- * T_UNINIT (getsock(fd) == 0)) * T_UNBND (getsock(fd) > 0) * T_IDLE (inp->inp_lport || inp->inp_fport) * T_OUTCON (so->so_state & SS_ISCONNECTING) * T_INCON (((so->so_options & SO_ACCEPTCONN) && so->so_qlen > 0) || * ((so->so_options & SO_ACCEPTCONN) && (so->so_state & SS_NBIO))) * * T_DATAXFER (so->so_state & SS_ISCONNECTED) * T_OUTREL ((so->so_state & SS_CANTSENDMORE) && * (tp->t_state >= TCPS_FIN_WAIT_1)) * T_INREL ((!(so->so_state & SS_CANTSENDMORE)) && * (tp->t_state >= TCPS_CLOSE_WAIT)) */tcp_to_xtistate(so) struct socket *so;{ int status; int default_state; struct inpcb *inp; struct tcpcb *tp; /* * determine what state we are in */ /* * we are already past T_UNINIT state, because * if we were a bogus descriptor or a non-socket descriptor we * would have been caught. */ default_state = T_UNBND; if (so) inp = (struct inpcb *) so->so_pcb; if (inp) tp = (struct tcpcb *) inp->inp_ppcb; if (inp) if (inp->inp_lport || inp->inp_fport) { default_state = T_IDLE; } else { return(default_state); } else return(default_state); if (so) { if (so->so_state & SS_ISCONNECTING) { default_state = T_OUTCON; } else if ((so->so_options & SO_ACCEPTCONN) && so->so_qlen != 0) { default_state = T_INCON; } else if ((so->so_options & SO_ACCEPTCONN) && (so->so_state & SS_NBIO)) { default_state = T_INCON; } else if (so->so_state & SS_ISCONNECTED) { default_state = T_DATAXFER; } } if (tp) { if ((so->so_state & SS_CANTSENDMORE) && (tp->t_state >= TCPS_FIN_WAIT_1)) { default_state = T_OUTREL; } else if ((!(so->so_state & SS_CANTSENDMORE)) && (tp->t_state >= TCPS_CLOSE_WAIT)) { default_state = T_INREL; } } return(default_state);}/* * Close a TCP control block: * discard all space held by the tcp * DONT discard internet protocol block * wake up any sleepers *//* SMP: Remove tp pointer only if no other routines are using it. * Enter with socket lock set. */struct tcpcb *tcp_closekeepinp(tp) register struct tcpcb *tp;{ register struct tcpiphdr *t; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; register struct mbuf *m; int s; if (smp_debug){ if (smp_owner(&so->lk_socket) == 0) panic("tcp_closekeepinp not lock owner"); } t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { t = (struct tcpiphdr *)t->ti_next; m = dtom(t->ti_prev); remque(t->ti_prev); m_freem(m); } if (tp->t_template) (void) m_free(dtom(tp->t_template)); KM_FREE(tp, KM_PCB); inp->inp_ppcb = 0; TCPSTAT(tcps_closed++); return ((struct tcpcb *)0);}/* * * cannot use bcmp because of padding * values may differ. */int cmp_xti_tcpopts(src, dst)struct tcp_options *src;struct tcp_options *dst;{ int trace = 0;#define CMPTCPOPT(member) \ if (src->member != dst->member) { \ return(trace); } \ trace++; CMPTCPOPT(precedence); CMPTCPOPT(timeout); CMPTCPOPT(max_seg_size); CMPTCPOPT(secopt.security); CMPTCPOPT(secopt.compartment); CMPTCPOPT(secopt.handling); CMPTCPOPT(secopt.tcc); return(0);}#endif XTI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -