1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

use m_pulldown not m_pullup2. fix some bugs in IPv6 tcp_trace().

This commit is contained in:
itojun 2003-05-29 00:35:18 +00:00
parent 3a42e73970
commit 24773939e6
5 changed files with 132 additions and 161 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_debug.c,v 1.14 2003/05/14 01:12:27 jason Exp $ */
/* $OpenBSD: tcp_debug.c,v 1.15 2003/05/29 00:35:18 itojun Exp $ */
/* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */
/*
@ -113,16 +113,16 @@ int tcpconsdebug = 0;
#endif
struct tcp_debug tcp_debug[TCP_NDEBUG];
int tcp_debx;
int tcp_debx = 0;
/*
* Tcp debug routines
*/
void
tcp_trace(act, ostate, tp, headers, req, len)
tcp_trace(act, ostate, tp, m, req, len)
short act, ostate;
struct tcpcb *tp;
caddr_t headers;
struct mbuf *m;
int req;
int len;
{
@ -130,15 +130,27 @@ tcp_trace(act, ostate, tp, headers, req, len)
tcp_seq seq, ack;
int flags;
#endif
struct tcp_debug *td = &tcp_debug[tcp_debx++];
struct tcpiphdr *ti = (struct tcpiphdr *)headers;
caddr_t headers;
struct tcp_debug *td;
struct tcpiphdr *ti;
struct tcphdr *th;
#ifdef INET6
struct tcpipv6hdr *ti6 = (struct tcpipv6hdr *)ti;
#endif
td = &tcp_debug[tcp_debx++];
if (tcp_debx == TCP_NDEBUG)
tcp_debx = 0;
if (m)
headers = mtod(m, caddr_t);
else
headers = NULL;
ti = (struct tcpiphdr *)headers;
#ifdef INET6
ti6 = (struct tcpipv6hdr *)headers;
#endif
td->td_time = iptime();
td->td_act = act;
td->td_ostate = ostate;
@ -150,7 +162,7 @@ tcp_trace(act, ostate, tp, headers, req, len)
switch (tp->pf) {
#ifdef INET6
case PF_INET6:
if (ti) {
if (ti6) {
th = &ti6->ti6_t;
td->td_ti6 = *ti6;
} else

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_input.c,v 1.127 2003/05/19 02:03:28 dhartmei Exp $ */
/* $OpenBSD: tcp_input.c,v 1.128 2003/05/29 00:35:18 itojun Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@ -101,9 +101,6 @@
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
struct tcpiphdr tcp_saveti;
struct tcpipv6hdr tcp_saveti6;
/* for the packet header length in the mbuf */
#define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len)
#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr))
@ -111,7 +108,6 @@ struct tcpipv6hdr tcp_saveti6;
#endif /* INET6 */
int tcprexmtthresh = 3;
struct tcpiphdr tcp_saveti;
int tcptv_keep_init = TCPTV_KEEP_INIT;
extern u_long sb_max;
@ -417,7 +413,7 @@ tcp_input(struct mbuf *m, ...)
u_long tiwin;
u_int32_t ts_val, ts_ecr;
int ts_present = 0;
int iphlen;
int iphlen, toff;
va_list ap;
struct tcphdr *th;
#ifdef INET6
@ -431,12 +427,13 @@ tcp_input(struct mbuf *m, ...)
int error, s;
#endif /* IPSEC */
int af;
struct mbuf *tcp_saveti = NULL;
#ifdef TCP_ECN
u_char iptos;
#endif
va_start(ap, m);
iphlen = va_arg(ap, int);
toff = va_arg(ap, int);
va_end(ap);
tcpstat.tcps_rcvtotal++;
@ -466,101 +463,44 @@ tcp_input(struct mbuf *m, ...)
switch (af) {
case AF_INET:
#ifdef DIAGNOSTIC
if (iphlen < sizeof(struct ip)) {
if (toff < sizeof(struct ip)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
if (iphlen > sizeof(struct ip)) {
#if 0 /*XXX*/
ip_stripoptions(m, (struct mbuf *)0);
iphlen = sizeof(struct ip);
#else
m_freem(m);
return;
#endif
}
break;
#ifdef INET6
case AF_INET6:
#ifdef DIAGNOSTIC
if (iphlen < sizeof(struct ip6_hdr)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
if (iphlen > sizeof(struct ip6_hdr)) {
#if 0 /*XXX*/
ipv6_stripoptions(m, iphlen);
iphlen = sizeof(struct ip6_hdr);
#else
m_freem(m);
return;
#endif
}
break;
#endif
default:
m_freem(m);
return;
}
if (m->m_len < iphlen + sizeof(struct tcphdr)) {
m = m_pullup2(m, iphlen + sizeof(struct tcphdr));
if (m == NULL) {
ip = mtod(m, struct ip *);
iphlen = sizeof(*ip);
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
sizeof(struct tcphdr));
if (th == NULL) {
tcpstat.tcps_rcvshort++;
return;
}
}
ip = NULL;
#ifdef INET6
ip6 = NULL;
#endif
switch (af) {
case AF_INET:
{
struct tcpiphdr *ti;
ip = mtod(m, struct ip *);
#if 1
tlen = m->m_pkthdr.len - iphlen;
#else
tlen = ((struct ip *)ti)->ip_len;
#endif
ti = mtod(m, struct tcpiphdr *);
len = m->m_pkthdr.len;
tlen = len - toff;
#ifdef TCP_ECN
/* save ip_tos before clearing it for checksum */
iptos = ip->ip_tos;
#endif
/*
* Checksum extended TCP header and data.
*/
len = sizeof(struct ip) + tlen;
bzero(ti->ti_x1, sizeof ti->ti_x1);
ti->ti_len = (u_int16_t)tlen;
HTONS(ti->ti_len);
if ((m->m_pkthdr.csum & M_TCP_CSUM_IN_OK) == 0) {
if (m->m_pkthdr.csum & M_TCP_CSUM_IN_BAD) {
tcpstat.tcps_inhwcsum++;
tcpstat.tcps_rcvbadsum++;
goto drop;
}
if ((ti->ti_sum = in_cksum(m, len)) != 0) {
tcpstat.tcps_rcvbadsum++;
goto drop;
}
} else {
m->m_pkthdr.csum &= ~M_TCP_CSUM_IN_OK;
tcpstat.tcps_inhwcsum++;
}
break;
}
#ifdef INET6
case AF_INET6:
#ifdef DIAGNOSTIC
if (toff < sizeof(struct ip6_hdr)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
ip6 = mtod(m, struct ip6_hdr *);
tlen = m->m_pkthdr.len - iphlen;
iphlen = sizeof(*ip6);
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
sizeof(struct tcphdr));
if (th == NULL) {
tcpstat.tcps_rcvshort++;
return;
}
len = m->m_pkthdr.len;
tlen = len - toff;
#ifdef TCP_ECN
iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
#endif
@ -585,6 +525,36 @@ tcp_input(struct mbuf *m, ...)
goto drop;
}
break;
#endif
default:
m_freem(m);
return;
}
switch (af) {
case AF_INET:
/*
* Checksum extended TCP header and data.
*/
HTONS(ip->ip_len);
if ((m->m_pkthdr.csum & M_TCP_CSUM_IN_OK) == 0) {
if (m->m_pkthdr.csum & M_TCP_CSUM_IN_BAD) {
tcpstat.tcps_inhwcsum++;
tcpstat.tcps_rcvbadsum++;
goto drop;
}
if (in4_cksum(m, IPPROTO_TCP, toff, tlen) != 0) {
tcpstat.tcps_rcvbadsum++;
goto drop;
}
} else {
m->m_pkthdr.csum &= ~M_TCP_CSUM_IN_OK;
tcpstat.tcps_inhwcsum++;
}
break;
#ifdef INET6
case AF_INET6:
/*
* Checksum extended TCP header and data.
*/
@ -597,8 +567,6 @@ tcp_input(struct mbuf *m, ...)
}
#endif /* TUBA_INCLUDE */
th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen);
/*
* Check that TCP offset makes sense,
* pull out TCP options and adjust length. XXX
@ -610,25 +578,13 @@ tcp_input(struct mbuf *m, ...)
}
tlen -= off;
if (off > sizeof(struct tcphdr)) {
if (m->m_len < iphlen + off) {
if ((m = m_pullup2(m, iphlen + off)) == NULL) {
tcpstat.tcps_rcvshort++;
return;
}
switch (af) {
case AF_INET:
ip = mtod(m, struct ip *);
break;
#ifdef INET6
case AF_INET6:
ip6 = mtod(m, struct ip6_hdr *);
break;
#endif
}
th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen);
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, off);
if (th == NULL) {
tcpstat.tcps_rcvshort++;
return;
}
optlen = off - sizeof(struct tcphdr);
optp = mtod(m, u_int8_t *) + iphlen + sizeof(struct tcphdr);
optp = mtod(m, u_int8_t *) + toff + sizeof(struct tcphdr);
/*
* Do quick retrieval of timestamp options ("options
* prediction?"). If timestamp is the only option and it's
@ -716,16 +672,28 @@ findpcb:
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
if (so->so_options & SO_DEBUG) {
ostate = tp->t_state;
switch (af) {
#ifdef INET6
case AF_INET6:
tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *));
break;
#endif
case AF_INET:
tcp_saveti = *(mtod(m, struct tcpiphdr *));
break;
tcp_saveti = NULL;
MGETHDR(tcp_saveti, M_DONTWAIT, MT_HEADER);
if (!tcp_saveti)
goto nosave;
#ifdef DIAGNOSTIC
if (iphlen + sizeof(struct tcphdr) > MCLBYTES) {
printf("cannot save to tcp_saveti\n");
goto nosave;
}
#endif
if (iphlen + sizeof(struct tcphdr) > MHLEN) {
MCLGET(tcp_saveti, M_DONTWAIT);
if ((tcp_saveti->m_flags & M_EXT) == 0) {
m_freem(tcp_saveti);
tcp_saveti = NULL;
goto nosave;
}
}
m_copydata(m, 0, iphlen, mtod(tcp_saveti, caddr_t));
m_copydata(m, toff, sizeof(struct tcphdr),
mtod(tcp_saveti, caddr_t) + iphlen);
nosave:;
}
if (so->so_options & SO_ACCEPTCONN) {
struct socket *so1;
@ -883,7 +851,7 @@ findpcb:
tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
} else
tdb = NULL;
ipsp_spd_lookup(m, af, iphlen, &error, IPSP_DIRECTION_IN,
ipsp_spd_lookup(m, af, toff, &error, IPSP_DIRECTION_IN,
tdb, inp);
if (error) {
splx(s);
@ -1080,7 +1048,7 @@ findpcb:
if (so->so_state & SS_CANTRCVMORE)
m_freem(m);
else {
m_adj(m, iphlen + off);
m_adj(m, toff + off);
sbappendstream(&so->so_rcv, m);
}
sorwakeup(so);
@ -1094,7 +1062,7 @@ findpcb:
/*
* Compute mbuf offset to TCP data segment.
*/
hdroptlen = iphlen + off;
hdroptlen = toff + off;
/*
* Calculate amount of space in receive window,
@ -2242,20 +2210,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 (so->so_options & SO_DEBUG)
tcp_trace(TA_INPUT, ostate, tp, tcp_saveti, 0, tlen);
/*
* Return any desired output.
@ -2263,6 +2219,7 @@ dodata: /* XXX */
if (needoutput || (tp->t_flags & TF_ACKNOW)) {
(void) tcp_output(tp);
}
m_freem(tcp_saveti);
return;
dropafterack:
@ -2275,6 +2232,7 @@ dropafterack:
m_freem(m);
tp->t_flags |= TF_ACKNOW;
(void) tcp_output(tp);
m_freem(tcp_saveti);
return;
dropwithreset_ratelim:
@ -2324,27 +2282,17 @@ dropwithreset:
/* destroy temporarily created socket */
if (dropsocket)
(void) soabort(so);
m_freem(tcp_saveti);
return;
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 (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
tcp_trace(TA_DROP, ostate, tp, tcp_saveti, 0, tlen);
m_freem(tcp_saveti);
m_freem(m);
/* destroy temporarily created socket */
if (dropsocket)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_output.c,v 1.54 2003/01/25 15:27:29 markus Exp $ */
/* $OpenBSD: tcp_output.c,v 1.55 2003/05/29 00:35:18 itojun Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@ -1071,9 +1071,20 @@ send:
/*
* Trace.
*/
if (so->so_options & SO_DEBUG)
tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0,
len);
if (so->so_options & SO_DEBUG) {
/* TCP template does not fill ip version, so fill it in here */
struct ip *sip;
sip = mtod(m, struct ip *);
switch (tp->pf) {
case AF_INET:
sip->ip_v = 4;
break;
case AF_INET6:
sip->ip_v = 6;
break;
}
tcp_trace(TA_OUTPUT, tp->t_state, tp, m, 0, len);
}
/*
* Fill in IP length and desired time to live and

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_usrreq.c,v 1.68 2003/02/12 14:41:08 jason Exp $ */
/* $OpenBSD: tcp_usrreq.c,v 1.69 2003/05/29 00:35:18 itojun Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@ -488,7 +488,7 @@ tcp_usrreq(so, req, m, nam, control)
panic("tcp_usrreq");
}
if (tp && (so->so_options & SO_DEBUG))
tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);
tcp_trace(TA_USER, ostate, tp, NULL, req, 0);
splx(s);
return (error);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_var.h,v 1.48 2003/05/26 05:01:55 itojun Exp $ */
/* $OpenBSD: tcp_var.h,v 1.49 2003/05/29 00:35:18 itojun Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@ -424,7 +424,7 @@ void tcp_setpersist(struct tcpcb *);
void tcp_slowtimo(void);
struct mbuf *
tcp_template(struct tcpcb *);
void tcp_trace(int, int, struct tcpcb *, caddr_t, int, int);
void tcp_trace(int, int, struct tcpcb *, struct mbuf *, int, int);
struct tcpcb *
tcp_usrclosed(struct tcpcb *);
int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t);