Hi,

The output from tcp debug sockets was incomplete.  After detach tp
was NULL and nothing was traced.  So save the old tcpcb and use
that to retreive some information.  Note that otb may be freed and
must not be dereferenced.  Use a heuristic for cases where the
address family is in the IP header but not provided in the PCB.

ok?

bluhm

Index: netinet/tcp_debug.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_debug.c,v
retrieving revision 1.26
diff -u -p -r1.26 tcp_debug.c
--- netinet/tcp_debug.c 10 May 2018 13:30:25 -0000      1.26
+++ netinet/tcp_debug.c 6 Jun 2018 22:12:59 -0000
@@ -110,18 +110,19 @@ int       tcp_debx;
  * Tcp debug routines
  */
 void
-tcp_trace(short act, short ostate, struct tcpcb *tp, caddr_t headers,
-   int req, int len)
+tcp_trace(short act, short ostate, struct tcpcb *tp, struct tcpcb *otp,
+    caddr_t headers, int req, int len)
 {
 #ifdef TCPDEBUG
        tcp_seq seq, ack;
        int flags;
 #endif
+       int pf = PF_UNSPEC;
        struct tcp_debug *td = &tcp_debug[tcp_debx++];
        struct tcpiphdr *ti = (struct tcpiphdr *)headers;
        struct tcphdr *th;
 #ifdef INET6
-       struct tcpipv6hdr *ti6 = (struct tcpipv6hdr *)ti;
+       struct tcpipv6hdr *ti6 = (struct tcpipv6hdr *)headers;
 #endif
 
        if (tcp_debx == TCP_NDEBUG)
@@ -129,40 +130,54 @@ tcp_trace(short act, short ostate, struc
        td->td_time = iptime();
        td->td_act = act;
        td->td_ostate = ostate;
-       td->td_tcb = (caddr_t)tp;
-       if (tp)
+       td->td_tcb = (caddr_t)otp;
+       if (tp) {
+               pf = tp->pf;
                td->td_cb = *tp;
-       else
+       } else
                bzero((caddr_t)&td->td_cb, sizeof (*tp));
-       switch (tp->pf) {
+
+       bzero(&td->td_ti6, sizeof(struct tcpipv6hdr));
+       bzero(&td->td_ti, sizeof(struct tcpiphdr));
+       if (headers) {
+               /* The address family may be in tcpcb or ip header. */
+               if (pf == PF_UNSPEC) {
+                       switch (ti6->ti6_i.ip6_vfc & IPV6_VERSION_MASK) {
 #ifdef INET6
-       case PF_INET6:
-               if (ti6) {
+                       case IPV6_VERSION:
+                               pf = PF_INET6;
+                               break;
+#endif /* INET6 */
+                       case IPVERSION:
+                               pf = PF_INET;
+                               break;
+                       }
+               }
+               switch (pf) {
+#ifdef INET6
+               case PF_INET6:
                        th = &ti6->ti6_t;
                        td->td_ti6 = *ti6;
                        td->td_ti6.ti6_plen = len;
-               } else
-                       bzero(&td->td_ti6, sizeof(struct tcpipv6hdr));
-               break;
+                       break;
 #endif /* INET6 */
-       case PF_INET:
-               if (ti) {
+               case PF_INET:
                        th = &ti->ti_t;
                        td->td_ti = *ti;
                        td->td_ti.ti_len = len;
-               } else
-                       bzero(&td->td_ti, sizeof(struct tcpiphdr));
-               break;
-       default:
-               return;
+                       break;
+               default:
+                       headers = NULL;
+                       break;
+               }
        }
 
        td->td_req = req;
 #ifdef TCPDEBUG
        if (tcpconsdebug == 0)
                return;
-       if (tp)
-               printf("%p %s:", tp, tcpstates[ostate]);
+       if (otp)
+               printf("%p %s:", otp, tcpstates[ostate]);
        else
                printf("???????? ");
        printf("%s ", tanames[act]);
@@ -171,7 +186,7 @@ tcp_trace(short act, short ostate, struc
        case TA_INPUT:
        case TA_OUTPUT:
        case TA_DROP:
-               if (ti == 0)
+               if (headers == NULL)
                        break;
                seq = th->th_seq;
                ack = th->th_ack;
@@ -205,7 +220,7 @@ tcp_trace(short act, short ostate, struc
                printf(" -> %s", tcpstates[tp->t_state]);
        /* print out internal state of tp !?! */
        printf("\n");
-       if (tp == 0)
+       if (tp == NULL)
                return;
        printf("\trcv_(nxt,wnd,up) (%x,%lx,%x) snd_(una,nxt,max) (%x,%x,%x)\n",
            tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt,
Index: netinet/tcp_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.355
diff -u -p -r1.355 tcp_input.c
--- netinet/tcp_input.c 8 May 2018 15:10:33 -0000       1.355
+++ netinet/tcp_input.c 6 Jun 2018 20:57:26 -0000
@@ -366,12 +366,13 @@ tcp_input(struct mbuf **mp, int *offp, i
        u_int8_t *optp = NULL;
        int optlen = 0;
        int tlen, off;
-       struct tcpcb *tp = NULL;
+       struct tcpcb *otp = NULL, *tp = NULL;
        int tiflags;
        struct socket *so = NULL;
        int todrop, acked, ourfinisacked;
        int hdroptlen = 0;
-       short ostate = 0;
+       short ostate;
+       caddr_t saveti;
        tcp_seq iss, *reuse = NULL;
        u_long tiwin;
        struct tcp_opt_info opti;
@@ -635,20 +636,21 @@ findpcb:
                        dst.sin6.sin6_port = th->th_dport;
                        break;
 #endif /* INET6 */
-               default:
-                       goto badsyn;    /*sanity*/
                }
 
                if (so->so_options & SO_DEBUG) {
+                       otp = tp;
                        ostate = tp->t_state;
                        switch (af) {
 #ifdef INET6
                        case AF_INET6:
+                               saveti = (caddr_t) &tcp_saveti6;
                                memcpy(&tcp_saveti6.ti6_i, ip6, sizeof(*ip6));
                                memcpy(&tcp_saveti6.ti6_t, th, sizeof(*th));
                                break;
 #endif
                        case AF_INET:
+                               saveti = (caddr_t) &tcp_saveti;
                                memcpy(&tcp_saveti.ti_i, ip, sizeof(*ip));
                                memcpy(&tcp_saveti.ti_t, th, sizeof(*th));
                                break;
@@ -2001,20 +2003,8 @@ dodata:                                                  
/* XXX */
                        break;
                }
        }
-       if (so->so_options & SO_DEBUG) {
-               switch (tp->pf) {
-#ifdef INET6
-               case PF_INET6:
-                       tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6,
-                           0, tlen);
-                       break;
-#endif /* INET6 */
-               case PF_INET:
-                       tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti,
-                           0, tlen);
-                       break;
-               }
-       }
+       if (otp)
+               tcp_trace(TA_INPUT, ostate, tp, otp, saveti, 0, tlen);
 
        /*
         * Return any desired output.
@@ -2089,20 +2079,8 @@ drop:
        /*
         * Drop space held by incoming segment and return.
         */
-       if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
-               switch (tp->pf) {
-#ifdef INET6
-               case PF_INET6:
-                       tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6,
-                           0, tlen);
-                       break;
-#endif /* INET6 */
-               case PF_INET:
-                       tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti,
-                           0, tlen);
-                       break;
-               }
-       }
+       if (otp)
+               tcp_trace(TA_DROP, ostate, tp, otp, saveti, 0, tlen);
 
        m_freem(m);
        return IPPROTO_DONE;
Index: netinet/tcp_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.124
diff -u -p -r1.124 tcp_output.c
--- netinet/tcp_output.c        8 May 2018 15:10:33 -0000       1.124
+++ netinet/tcp_output.c        6 Jun 2018 20:59:19 -0000
@@ -983,7 +983,7 @@ send:
         * Trace.
         */
        if (so->so_options & SO_DEBUG)
-               tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0,
+               tcp_trace(TA_OUTPUT, tp->t_state, tp, tp, mtod(m, caddr_t), 0,
                        len);
 
        /*
Index: netinet/tcp_timer.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.66
diff -u -p -r1.66 tcp_timer.c
--- netinet/tcp_timer.c 10 May 2018 13:30:25 -0000      1.66
+++ netinet/tcp_timer.c 6 Jun 2018 21:09:49 -0000
@@ -109,7 +109,7 @@ tcp_timer_init(void)
 void
 tcp_timer_delack(void *arg)
 {
-       struct tcpcb *tp = arg;
+       struct tcpcb *otp = NULL, *tp = arg;
        short ostate;
 
        /*
@@ -124,11 +124,14 @@ tcp_timer_delack(void *arg)
                goto out;
        CLR((tp)->t_flags, TF_TMR_DELACK);
 
-       ostate = tp->t_state;
+       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
        tp->t_flags |= TF_ACKNOW;
        (void) tcp_output(tp);
-       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
-               tcp_trace(TA_TIMER, ostate, tp, (caddr_t)0, TCPT_DELACK, 0);
+       if (otp)
+               tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_DELACK, 0);
  out:
        NET_UNLOCK();
 }
@@ -192,7 +195,7 @@ tcp_timer_freesack(struct tcpcb *tp)
 void
 tcp_timer_rexmt(void *arg)
 {
-       struct tcpcb *tp = arg;
+       struct tcpcb *otp = NULL, *tp = arg;
        uint32_t rto;
        short ostate;
 
@@ -239,7 +242,10 @@ tcp_timer_rexmt(void *arg)
                    tp->t_softerror : ETIMEDOUT);
                goto out;
        }
-       ostate = tp->t_state;
+       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
        tcpstat_inc(tcps_rexmttimeo);
        rto = TCP_REXMTVAL(tp);
        if (rto < tp->t_rttmin)
@@ -374,8 +380,8 @@ tcp_timer_rexmt(void *arg)
 #endif
        }
        (void) tcp_output(tp);
-       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
-               tcp_trace(TA_TIMER, ostate, tp, (caddr_t)0, TCPT_REXMT, 0);
+       if (otp)
+               tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_REXMT, 0);
  out:
        NET_UNLOCK();
 }
@@ -383,7 +389,7 @@ tcp_timer_rexmt(void *arg)
 void
 tcp_timer_persist(void *arg)
 {
-       struct tcpcb *tp = arg;
+       struct tcpcb *otp = NULL, *tp = arg;
        uint32_t rto;
        short ostate;
 
@@ -397,7 +403,10 @@ tcp_timer_persist(void *arg)
        if (TCP_TIMER_ISARMED(tp, TCPT_REXMT))
                goto out;
 
-       ostate = tp->t_state;
+       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
        tcpstat_inc(tcps_persisttimeo);
        /*
         * Hack: if the peer is dead/unreachable, we do not
@@ -420,8 +429,8 @@ tcp_timer_persist(void *arg)
        tp->t_force = 1;
        (void) tcp_output(tp);
        tp->t_force = 0;
-       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
-               tcp_trace(TA_TIMER, ostate, tp, (caddr_t)0, TCPT_PERSIST, 0);
+       if (otp)
+               tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_PERSIST, 0);
  out:
        NET_UNLOCK();
 }
@@ -429,7 +438,7 @@ tcp_timer_persist(void *arg)
 void
 tcp_timer_keep(void *arg)
 {
-       struct tcpcb *tp = arg;
+       struct tcpcb *otp = NULL, *tp = arg;
        short ostate;
 
        NET_LOCK();
@@ -439,7 +448,10 @@ tcp_timer_keep(void *arg)
                goto out;
        CLR((tp)->t_flags, TF_TMR_KEEP);
 
-       ostate = tp->t_state;
+       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
        tcpstat_inc(tcps_keeptimeo);
        if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
                goto dropit;
@@ -467,8 +479,8 @@ tcp_timer_keep(void *arg)
                TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepintvl);
        } else
                TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle);
-       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
-               tcp_trace(TA_TIMER, ostate, tp, (caddr_t)0, TCPT_KEEP, 0);
+       if (otp)
+               tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_KEEP, 0);
  out:
        NET_UNLOCK();
        return;
@@ -482,7 +494,7 @@ tcp_timer_keep(void *arg)
 void
 tcp_timer_2msl(void *arg)
 {
-       struct tcpcb *tp = arg;
+       struct tcpcb *otp = NULL, *tp = arg;
        short ostate;
 
        NET_LOCK();
@@ -492,7 +504,10 @@ tcp_timer_2msl(void *arg)
                goto out;
        CLR((tp)->t_flags, TF_TMR_2MSL);
 
-       ostate = tp->t_state;
+       if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
        tcp_timer_freesack(tp);
 
        if (tp->t_state != TCPS_TIME_WAIT &&
@@ -500,8 +515,8 @@ tcp_timer_2msl(void *arg)
                TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_keepintvl);
        else
                tp = tcp_close(tp);
-       if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
-               tcp_trace(TA_TIMER, ostate, tp, (caddr_t)0, TCPT_2MSL, 0);
+       if (otp)
+               tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_2MSL, 0);
  out:
        NET_UNLOCK();
 }
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.168
diff -u -p -r1.168 tcp_usrreq.c
--- netinet/tcp_usrreq.c        24 Apr 2018 15:40:55 -0000      1.168
+++ netinet/tcp_usrreq.c        6 Jun 2018 20:44:20 -0000
@@ -127,7 +127,7 @@ tcp_usrreq(struct socket *so, int req, s
     struct mbuf *control, struct proc *p)
 {
        struct inpcb *inp;
-       struct tcpcb *tp = NULL;
+       struct tcpcb *otp = NULL, *tp = NULL;
        int error = 0;
        short ostate;
 
@@ -172,7 +172,10 @@ tcp_usrreq(struct socket *so, int req, s
        /* tp might get 0 when using socket splicing */
        if (tp == NULL)
                return (0);
-       ostate = tp->t_state;
+       if (so->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
 
        switch (req) {
 
@@ -399,8 +402,8 @@ tcp_usrreq(struct socket *so, int req, s
        default:
                panic("tcp_usrreq");
        }
-       if (tp && (so->so_options & SO_DEBUG))
-               tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);
+       if (otp)
+               tcp_trace(TA_USER, ostate, tp, otp, NULL, req, 0);
        return (error);
 }
 
@@ -599,7 +602,7 @@ tcp_attach(struct socket *so, int proto)
                so->so_linger = TCP_LINGERTIME;
 
        if (so->so_options & SO_DEBUG)
-               tcp_trace(TA_USER, TCPS_CLOSED, tp, (caddr_t)0, PRU_ATTACH, 0);
+               tcp_trace(TA_USER, TCPS_CLOSED, tp, tp, NULL, PRU_ATTACH, 0);
        return (0);
 }
 
@@ -607,7 +610,7 @@ int
 tcp_detach(struct socket *so)
 {
        struct inpcb *inp;
-       struct tcpcb *tp = NULL;
+       struct tcpcb *otp = NULL, *tp = NULL;
        int error = 0;
        short ostate;
 
@@ -629,7 +632,10 @@ tcp_detach(struct socket *so)
        /* tp might get 0 when using socket splicing */
        if (tp == NULL)
                return (0);
-       ostate = tp->t_state;
+       if (so->so_options & SO_DEBUG) {
+               otp = tp;
+               ostate = tp->t_state;
+       }
 
        /*
         * Detach the TCP protocol from the socket.
@@ -640,8 +646,8 @@ tcp_detach(struct socket *so)
         */
        tp = tcp_disconnect(tp);
 
-       if (tp && (so->so_options & SO_DEBUG))
-               tcp_trace(TA_USER, ostate, tp, (caddr_t)0, PRU_DETACH, 0);
+       if (otp)
+               tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_DETACH, 0);
        return (error);
 }
 
Index: netinet/tcp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.132
diff -u -p -r1.132 tcp_var.h
--- netinet/tcp_var.h   8 May 2018 15:10:33 -0000       1.132
+++ netinet/tcp_var.h   6 Jun 2018 20:39:16 -0000
@@ -721,7 +721,8 @@ void         tcp_update_rcvspace(struct tcpcb *
 void    tcp_slowtimo(void);
 struct mbuf *
         tcp_template(struct tcpcb *);
-void    tcp_trace(short, short, struct tcpcb *, caddr_t, int, int);
+void    tcp_trace(short, short, struct tcpcb *, struct tcpcb *, caddr_t,
+               int, int);
 struct tcpcb *
         tcp_usrclosed(struct tcpcb *);
 int     tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t);

Reply via email to