diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2018-06-11 07:40:27 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2018-06-11 07:40:27 +0000 |
commit | 6fa871355586760f3c952e5e1839b3bae1135c9e (patch) | |
tree | 553fead65d9114fd3296c21ad7a96214abf9874b | |
parent | 7c4a9dc3c288181951922146adb913b5e09586a0 (diff) |
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 retrieve 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 visa@
-rw-r--r-- | sys/netinet/tcp_debug.c | 63 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 44 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_timer.c | 57 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 26 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 5 |
6 files changed, 107 insertions, 92 deletions
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c index 89f6b6567bd..8997019dabd 100644 --- a/sys/netinet/tcp_debug.c +++ b/sys/netinet/tcp_debug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_debug.c,v 1.26 2018/05/10 13:30:25 bluhm Exp $ */ +/* $OpenBSD: tcp_debug.c,v 1.27 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */ /* @@ -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, struct tcpcb *tp, caddr_t headers, 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, struct tcpcb *tp, caddr_t headers, 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, struct tcpcb *tp, caddr_t headers, 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, diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index a5fd6f7d7e4..25795a1155c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.355 2018/05/08 15:10:33 bluhm Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.356 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -366,12 +366,13 @@ tcp_input(struct mbuf **mp, int *offp, int proto, int af) 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; diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 3a18b29238f..7abcf26675e 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.124 2018/05/08 15:10:33 bluhm Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.125 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -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); /* diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 898c8e83304..f2e4a4a77b8 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_timer.c,v 1.66 2018/05/10 13:30:25 bluhm Exp $ */ +/* $OpenBSD: tcp_timer.c,v 1.67 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_timer.c,v 1.14 1996/02/13 23:44:09 christos Exp $ */ /* @@ -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(); } diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 6b1e036b574..304935cd569 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.168 2018/04/24 15:40:55 pirofti Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.169 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -127,7 +127,7 @@ tcp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, /* 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, struct mbuf *m, struct mbuf *nam, 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); } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 3c3af90e369..326ab952e93 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.132 2018/05/08 15:10:33 bluhm Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.133 2018/06/11 07:40:26 bluhm Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -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); |