merge wnj changes plus lint
[unix-history] / usr / src / sys / netinet / tcp_usrreq.c
index 4b83833..229cbfc 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_usrreq.c    1.72    83/01/13        */
+/*     tcp_usrreq.c    1.78    83/05/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -6,9 +6,11 @@
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/protosw.h"
+#include "../h/errno.h"
 
 #include "../net/if.h"
 #include "../net/route.h"
 
 #include "../net/if.h"
 #include "../net/route.h"
+
 #include "../netinet/in.h"
 #include "../netinet/in_pcb.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/in.h"
 #include "../netinet/in_pcb.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/tcp_var.h"
 #include "../netinet/tcpip.h"
 #include "../netinet/tcp_debug.h"
 #include "../netinet/tcp_var.h"
 #include "../netinet/tcpip.h"
 #include "../netinet/tcp_debug.h"
-#include <errno.h>
 
 /*
  * TCP protocol interface to socket abstraction.
  */
 extern char *tcpstates[];
 struct tcpcb *tcp_newtcpcb();
 
 /*
  * TCP protocol interface to socket abstraction.
  */
 extern char *tcpstates[];
 struct tcpcb *tcp_newtcpcb();
+int    tcpsenderrors;
 
 /*
  * Process a TCP user request for TCP tb.  If this is a send request
 
 /*
  * Process a TCP user request for TCP tb.  If this is a send request
@@ -35,10 +37,10 @@ struct      tcpcb *tcp_newtcpcb();
  * (called from the software clock routine), then timertype tells which timer.
  */
 /*ARGSUSED*/
  * (called from the software clock routine), then timertype tells which timer.
  */
 /*ARGSUSED*/
-tcp_usrreq(so, req, m, nam)
+tcp_usrreq(so, req, m, nam, rights)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m, *nam;
+       struct mbuf *m, *nam, *rights;
 {
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
 {
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
@@ -46,6 +48,10 @@ tcp_usrreq(so, req, m, nam)
        int error = 0;
        int ostate;
 
        int error = 0;
        int ostate;
 
+       if (rights && rights->m_len) {
+               splx(s);
+               return (EINVAL);
+       }
        /*
         * When a TCP is attached to a socket, then there will be
         * a (struct inpcb) pointed at by the socket, and this
        /*
         * When a TCP is attached to a socket, then there will be
         * a (struct inpcb) pointed at by the socket, and this
@@ -78,7 +84,7 @@ tcp_usrreq(so, req, m, nam)
                error = tcp_attach(so);
                if (error)
                        break;
                error = tcp_attach(so);
                if (error)
                        break;
-               if (so->so_options & SO_LINGER && so->so_linger == 0)
+               if ((so->so_options & SO_LINGER) && so->so_linger == 0)
                        so->so_linger = TCP_LINGERTIME;
                tp = sototcpcb(so);
                break;
                        so->so_linger = TCP_LINGERTIME;
                tp = sototcpcb(so);
                break;
@@ -92,11 +98,9 @@ tcp_usrreq(so, req, m, nam)
         */
        case PRU_DETACH:
                if (tp->t_state > TCPS_LISTEN)
         */
        case PRU_DETACH:
                if (tp->t_state > TCPS_LISTEN)
-                       tcp_disconnect(tp);
-               else {
-                       tcp_close(tp);
-                       tp = 0;
-               }
+                       tp = tcp_disconnect(tp);
+               else
+                       tp = tcp_close(tp);
                break;
 
        /*
                break;
 
        /*
@@ -160,7 +164,7 @@ tcp_usrreq(so, req, m, nam)
         * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
         */
        case PRU_DISCONNECT:
         * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
         */
        case PRU_DISCONNECT:
-               tcp_disconnect(tp);
+               tp = tcp_disconnect(tp);
                break;
 
        /*
                break;
 
        /*
@@ -183,8 +187,9 @@ tcp_usrreq(so, req, m, nam)
         */
        case PRU_SHUTDOWN:
                socantsendmore(so);
         */
        case PRU_SHUTDOWN:
                socantsendmore(so);
-               tcp_usrclosed(tp);
-               error = tcp_output(tp);
+               tp = tcp_usrclosed(tp);
+               if (tp)
+                       error = tcp_output(tp);
                break;
 
        /*
                break;
 
        /*
@@ -205,13 +210,18 @@ tcp_usrreq(so, req, m, nam)
                        tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
 #endif
                error = tcp_output(tp);
                        tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
 #endif
                error = tcp_output(tp);
+               if (error) {            /* XXX fix to use other path */
+                       if (error == ENOBUFS)           /* XXX */
+                               error = 0;              /* XXX */
+                       tcpsenderrors++;
+               }
                break;
 
        /*
         * Abort the TCP.
         */
        case PRU_ABORT:
                break;
 
        /*
         * Abort the TCP.
         */
        case PRU_ABORT:
-               tcp_drop(tp, ECONNABORTED);
+               tp = tcp_drop(tp, ECONNABORTED);
                break;
 
 /* SOME AS YET UNIMPLEMENTED HOOKS */
                break;
 
 /* SOME AS YET UNIMPLEMENTED HOOKS */
@@ -240,6 +250,7 @@ tcp_usrreq(so, req, m, nam)
 
        case PRU_SENDOOB:
                if (sbspace(&so->so_snd) < -512) {
 
        case PRU_SENDOOB:
                if (sbspace(&so->so_snd) < -512) {
+                       m_freem(m);
                        error = ENOBUFS;
                        break;
                }
                        error = ENOBUFS;
                        break;
                }
@@ -259,7 +270,7 @@ tcp_usrreq(so, req, m, nam)
         * routine for tracing's sake.
         */
        case PRU_SLOWTIMO:
         * routine for tracing's sake.
         */
        case PRU_SLOWTIMO:
-               tcp_timers(tp, (int)nam);
+               tp = tcp_timers(tp, (int)nam);
                req |= (int)nam << 8;           /* for debug's sake */
                break;
 
                req |= (int)nam << 8;           /* for debug's sake */
                break;
 
@@ -314,21 +325,24 @@ bad:
  * current input data; switch states based on user close, and
  * send segment to peer (with FIN).
  */
  * current input data; switch states based on user close, and
  * send segment to peer (with FIN).
  */
+struct tcpcb *
 tcp_disconnect(tp)
 tcp_disconnect(tp)
-       struct tcpcb *tp;
+       register struct tcpcb *tp;
 {
        struct socket *so = tp->t_inpcb->inp_socket;
 
        if (tp->t_state < TCPS_ESTABLISHED)
 {
        struct socket *so = tp->t_inpcb->inp_socket;
 
        if (tp->t_state < TCPS_ESTABLISHED)
-               tcp_close(tp);
+               tp = tcp_close(tp);
        else if (so->so_linger == 0)
        else if (so->so_linger == 0)
-               tcp_drop(tp, 0);
+               tp = tcp_drop(tp, 0);
        else {
                soisdisconnecting(so);
                sbflush(&so->so_rcv);
        else {
                soisdisconnecting(so);
                sbflush(&so->so_rcv);
-               tcp_usrclosed(tp);
-               (void) tcp_output(tp);
+               tp = tcp_usrclosed(tp);
+               if (tp)
+                       (void) tcp_output(tp);
        }
        }
+       return (tp);
 }
 
 /*
 }
 
 /*
@@ -341,16 +355,18 @@ tcp_disconnect(tp)
  * for peer to send FIN or not respond to keep-alives, etc.
  * We can let the user exit from the close as soon as the FIN is acked.
  */
  * for peer to send FIN or not respond to keep-alives, etc.
  * We can let the user exit from the close as soon as the FIN is acked.
  */
+struct tcpcb *
 tcp_usrclosed(tp)
 tcp_usrclosed(tp)
-       struct tcpcb *tp;
+       register struct tcpcb *tp;
 {
 
        switch (tp->t_state) {
 
 {
 
        switch (tp->t_state) {
 
+       case TCPS_CLOSED:
        case TCPS_LISTEN:
        case TCPS_SYN_SENT:
                tp->t_state = TCPS_CLOSED;
        case TCPS_LISTEN:
        case TCPS_SYN_SENT:
                tp->t_state = TCPS_CLOSED;
-               tcp_close(tp);
+               tp = tcp_close(tp);
                break;
 
        case TCPS_SYN_RECEIVED:
                break;
 
        case TCPS_SYN_RECEIVED:
@@ -362,6 +378,7 @@ tcp_usrclosed(tp)
                tp->t_state = TCPS_LAST_ACK;
                break;
        }
                tp->t_state = TCPS_LAST_ACK;
                break;
        }
-       if (tp->t_state >= TCPS_FIN_WAIT_2)
+       if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
                soisdisconnected(tp->t_inpcb->inp_socket);
                soisdisconnected(tp->t_inpcb->inp_socket);
+       return (tp);
 }
 }