listing
[unix-history] / usr / src / sys / netinet / tcp_usrreq.c
index d6871f7..abad774 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_usrreq.c 1.34 81/11/24 */
+/* tcp_usrreq.c 1.35 81/11/25 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -33,27 +33,24 @@ tcp_usrreq(so, req, m, addr)
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
        int s = splnet();
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
        int s = splnet();
-       register int nstate;
        int error = 0;
        int error = 0;
+       struct tcpiphdr ti;
 COUNT(TCP_USRREQ);
 
        /*
         * Make sure attached.  If not,
         * only PRU_ATTACH is valid.
         */
 COUNT(TCP_USRREQ);
 
        /*
         * Make sure attached.  If not,
         * only PRU_ATTACH is valid.
         */
-       if (inp == 0) {
-               if (req != PRU_ATTACH) {
-                       splx(s);
-                       return (EINVAL);
-               }
-       } else {
+       if (inp == 0 && req != PRU_ATTACH)
+               splx(s);
+               return (EINVAL);
+       }
+       if (inp) {
                tp = intotcpcb(inp);
                tp = intotcpcb(inp);
-               nstate = tp->t_state;
 #ifdef KPROF
 #ifdef KPROF
-               tcp_acounts[nstate][req]++;
+               tcp_acounts[tp->t_state][req]++;
 #endif
        }
 #endif
        }
-
        switch (req) {
 
        case PRU_ATTACH:
        switch (req) {
 
        case PRU_ATTACH:
@@ -62,20 +59,19 @@ COUNT(TCP_USRREQ);
                        break;
                }
                error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
                        break;
                }
                error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
-               if (error) {
-                       (void) m_free(dtom(tp));
+               if (error)
                        break;
                        break;
-               }
                inp = (struct inpcb *)so->so_pcb;
                if (so->so_options & SO_ACCEPTCONN) {
                        tp = tcp_newtcpcb(inp);
                        if (tp == 0) {
                inp = (struct inpcb *)so->so_pcb;
                if (so->so_options & SO_ACCEPTCONN) {
                        tp = tcp_newtcpcb(inp);
                        if (tp == 0) {
+                               in_pcbfree(inp);
                                error = ENOBUFS;
                                break;
                        }
                                error = ENOBUFS;
                                break;
                        }
-                       nstate = LISTEN;
+                       tp->t_state = TCPS_LISTEN;
                } else
                } else
-                       nstate = CLOSED;
+                       tp->t_state = TCPS_CLOSED;
                break;
 
        case PRU_DETACH:
                break;
 
        case PRU_DETACH:
@@ -93,9 +89,9 @@ COUNT(TCP_USRREQ);
                }
                tp->t_inpcb = inp;
                inp->inp_ppcb = (caddr_t)tp;
                }
                tp->t_inpcb = inp;
                inp->inp_ppcb = (caddr_t)tp;
-               (void) tcp_sndctl(tp);
-               nstate = SYN_SENT;
                soisconnecting(so);
                soisconnecting(so);
+               tp->t_state = TCPS_SYN_SENT;
+               tcp_output(tp);
                break;
 
        case PRU_ACCEPT:
                break;
 
        case PRU_ACCEPT:
@@ -103,72 +99,64 @@ COUNT(TCP_USRREQ);
                break;
 
        case PRU_DISCONNECT:
                break;
 
        case PRU_DISCONNECT:
-               if (nstate < ESTAB)
-                       tcp_disconnect(tp);
+               if (tp->t_state < TCPS_ESTABLISHED)
+                       tcp_close(tp);
                else {
                else {
-                       tp->tc_flags |= TC_SND_FIN;
-                       (void) tcp_sndctl(tp);
                        soisdisconnecting(so);
                        soisdisconnecting(so);
+                       tcp_output(tp);
                }
                break;
 
        case PRU_SHUTDOWN:
                }
                break;
 
        case PRU_SHUTDOWN:
-               switch (nstate) {
+               socantsndmore(so);
+               switch (tp->t_state) {
 
                case TCPS_LISTEN:
                case TCPS_SYN_SENT:
 
                case TCPS_LISTEN:
                case TCPS_SYN_SENT:
-                       nstate = TCPS_CLOSED;
+                       tp->t_state = TCPS_CLOSED;
                        break;
 
                case TCPS_SYN_RCVD:
                        break;
 
                case TCPS_SYN_RCVD:
-               case TCPS_ESTABLISHED:
-               case TCPS_CLOSE_WAIT:
-                       tp->tc_flags |= TC_SND_FIN;
-                       (void) tcp_sndctl(tp);
-                       nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
-                       break;
-                       
-               case TCPS_FIN_W1:
-               case TCPS_FIN_W2:
-               case TCPS_TIME_WAIT:
-               case TCPS_CLOSING:
-               case TCPS_LAST_ACK:
-               case TCPS_RCV_WAIT:
+               case TCPS_ESTAB:
+                       tp->t_state = TCPS_FIN_WAIT_1;
+                       tcp_output(tp);
                        break;
 
                        break;
 
-               default:
-                       goto bad;
+               case TCPS_CLOSE_WAIT:
+                       tp->t_state = TCPS_LAST_ACK;
+                       tcp_output(tp);
+                       break;
                }
                break;
 
        case PRU_RCVD:
                }
                break;
 
        case PRU_RCVD:
-               if (nstate < TCPS_ESTAB)
-                       goto bad;
-               tcp_sndwin(tp);
-               if (nstate == TCPS_RCV_WAIT && rcv_empty(tp))
-                       nstate = TCPS_CLOSED;
+               if (tp->t_state < TCPS_ESTABLISHED) {
+                       error = ENOTCONN;
+                       break;
+               }
+               tcp_output(tp);
                break;
 
        case PRU_SEND:
                break;
 
        case PRU_SEND:
-               switch (nstate) {
-
-               case ESTAB:
-               case CLOSE_WAIT:
-                       tcp_usrsend(tp, m);
+               if (tp->t_state < TCPS_ESTABLISHED) {
+                       error = ENOTCONN;
                        break;
                        break;
-               
-               default:
-                       if (nstate < ESTAB)
-                               goto bad;
+               }
+               if (tp->t_state > TCPS_CLOSE_WAIT) {
+                       error = EISDISCONN;
                        m_freem(m);
                        m_freem(m);
-                       error = ENOTCONN;
                        break;
                }
                        break;
                }
+               sbappend(&so->so_snd, m);
+               if (tp->t_options & TO_EOL)
+                       tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
+               if (tp->t_options & TO_URG)
+                       tp->snd_urp = tp->snd_una + so->so_snd.sb_cc + 1;
+               tcp_output(tp);
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
-               tcp_abort(tp);
-               nstate = CLOSED;
+               tcp_drop(tp, ECONNABORTED);
                break;
 
        case PRU_CONTROL:
                break;
 
        case PRU_CONTROL:
@@ -176,183 +164,12 @@ COUNT(TCP_USRREQ);
                break;
 
        case PRU_SLOWTIMO:
                break;
 
        case PRU_SLOWTIMO:
-               switch (nstate) {
-
-               case 0:
-               case CLOSED:
-               case LISTEN:
-                       goto bad;
-
-               default:
-                       nstate = tcp_timers(tp, (int)addr);
-               }
+               tcp_timers(tp, (int)addr);
                break;
 
        default:
                panic("tcp_usrreq");
                break;
 
        default:
                panic("tcp_usrreq");
-       bad:
-               printf("tcp: bad state: tcb=%x state=%d input=%d\n",
-                   tp, tp->t_state, req);
-               nstate = EFAILEC;
-               break;
-       }
-       switch (nstate) {
-
-       case CLOSED:
-       case SAME:
-               break;
-
-       case EFAILEC:
-               if (m)
-                       m_freem(dtom(m));
-               break;
-
-       default:
-               tp->t_state = nstate;
-               break;
        }
        splx(s);
        return (error);
 }
        }
        splx(s);
        return (error);
 }
-
-struct tcpcb *
-tcp_newtcpcb(inp)
-       struct inpcb *inp;
-{
-       struct mbuf *m = m_getclr(0);
-       register struct tcpcb *tp;
-COUNT(TCP_NEWTCPCB);
-
-       if (m == 0)
-               return (0);
-       tp = mtod(m, struct tcpcb *);
-
-       /*
-        * Make empty reassembly queue.
-        */
-       tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
-
-       /*
-        * Initialize sequence numbers and round trip retransmit timer.
-        */
-       tp->t_xmtime = T_REXMT;
-       tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
-           tp->iss = tcp_iss;
-       tp->snd_off = tp->iss + 1;
-       tcp_iss += (ISSINCR >> 1) + 1;
-
-       /*
-        * Hook to inpcb.
-        */
-       tp->t_inpcb = inp;
-       inp->inp_ppcb = (caddr_t)tp;
-       return (tp);
-}
-
-tcp_disconnect(tp)
-       register struct tcpcb *tp;
-{
-       register struct tcpiphdr *t;
-
-COUNT(TCP_DISCONNECT);
-       tcp_tcancel(tp);
-       t = tp->seg_next;
-       for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next)
-               m_freem(dtom(t));
-       tcp_drainunack(tp);
-       if (tp->t_template) {
-               (void) m_free(dtom(tp->t_template));
-               tp->t_template = 0;
-       }
-       in_pcbfree(tp->t_inpcb);
-       (void) m_free(dtom(tp));
-}
-
-tcp_abort(tp)
-       register struct tcpcb *tp;
-{
-
-COUNT(TCP_ABORT);
-       switch (tp->t_state) {
-
-       case SYN_RCVD:
-       case ESTAB:
-       case FIN_W1:
-       case FIN_W2:
-       case CLOSE_WAIT:
-               tp->tc_flags |= TC_SND_RST;
-               tcp_sndnull(tp);
-       }
-       soisdisconnected(tp->t_inpcb->inp_socket);
-       tcp_disconnect(tp);
-}
-
-/*
- * Send data queue headed by m0 into the protocol.
- */
-tcp_usrsend(tp, m0)
-       register struct tcpcb *tp;
-       struct mbuf *m0;
-{
-       register struct socket *so = tp->t_inpcb->inp_socket;
-COUNT(TCP_USRSEND);
-
-       sbappend(&so->so_snd, m0);
-       if (tp->t_options & TO_EOL)
-               tp->snd_end = tp->snd_off + so->so_snd.sb_cc;
-       if (tp->t_options & TO_URG) {
-               tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1;
-               tp->tc_flags |= TC_SND_URG;
-       }
-       (void) tcp_send(tp);
-}
-
-/*ARGSUSED*/
-tcp_sense(m)
-       struct mbuf *m;
-{
-
-COUNT(TCP_SENSE);
-       return (EOPNOTSUPP);
-}
-
-tcp_drop(tp, errno)
-       struct tcpcb *tp;
-       int errno;
-{
-       struct socket *so = tp->t_inpcb->inp_socket;
-
-COUNT(TCP_ERROR);
-       so->so_error = errno;
-       sorwakeup(so);
-       sowwakeup(so);
-       tcp_disconnect(tp);
-}
-
-tcp_drain()
-{
-       register struct inpcb *ip;
-
-COUNT(TCP_DRAIN);
-       for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next)
-               tcp_drainunack(intotcpcb(ip));
-}
-
-tcp_drainunack(tp)
-       register struct tcpcb *tp;
-{
-       register struct mbuf *m;
-
-COUNT(TCP_DRAINUNACK);
-       for (m = tp->seg_unack; m; m = m->m_act)
-               m_freem(m);
-       tp->seg_unack = 0;
-}
-       
-tcp_ctlinput(m)
-       struct mbuf *m;
-{
-
-COUNT(TCP_CTLINPUT);
-       m_freem(m);
-}