summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2003-06-09 07:40:26 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2003-06-09 07:40:26 +0000
commit8d1676992f6c6f897fde850e52a016d4c3cfc1fe (patch)
treeb9eca6af623fc55075d32e2b5733943ab20e7ee5 /sys
parentbc786f06fee201918acb3f6ca1e5864d8c58e2bf (diff)
backout following:
>use m_pulldown not m_pullup2. fix some bugs in IPv6 tcp_trace(). PR 3283 fixed (confirmed)
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/tcp_debug.c26
-rw-r--r--sys/netinet/tcp_input.c226
-rw-r--r--sys/netinet/tcp_output.c19
-rw-r--r--sys/netinet/tcp_usrreq.c4
-rw-r--r--sys/netinet/tcp_var.h4
5 files changed, 154 insertions, 125 deletions
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c
index 81a8b0fc837..b18e0715b52 100644
--- a/sys/netinet/tcp_debug.c
+++ b/sys/netinet/tcp_debug.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_debug.c,v 1.16 2003/06/02 23:28:14 millert Exp $ */
+/* $OpenBSD: tcp_debug.c,v 1.17 2003/06/09 07:40:25 itojun Exp $ */
/* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */
/*
@@ -109,16 +109,16 @@ int tcpconsdebug = 0;
#endif
struct tcp_debug tcp_debug[TCP_NDEBUG];
-int tcp_debx = 0;
+int tcp_debx;
/*
* Tcp debug routines
*/
void
-tcp_trace(act, ostate, tp, m, req, len)
+tcp_trace(act, ostate, tp, headers, req, len)
short act, ostate;
struct tcpcb *tp;
- struct mbuf *m;
+ caddr_t headers;
int req;
int len;
{
@@ -126,27 +126,15 @@ tcp_trace(act, ostate, tp, m, req, len)
tcp_seq seq, ack;
int flags;
#endif
- caddr_t headers;
- struct tcp_debug *td;
- struct tcpiphdr *ti;
+ 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;
#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;
@@ -158,7 +146,7 @@ tcp_trace(act, ostate, tp, m, req, len)
switch (tp->pf) {
#ifdef INET6
case PF_INET6:
- if (ti6) {
+ if (ti) {
th = &ti6->ti6_t;
td->td_ti6 = *ti6;
} else
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index ae06e434ce7..02866771153 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.130 2003/06/02 23:28:14 millert Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.131 2003/06/09 07:40:25 itojun Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -97,6 +97,9 @@
#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))
@@ -104,6 +107,7 @@
#endif /* INET6 */
int tcprexmtthresh = 3;
+struct tcpiphdr tcp_saveti;
int tcptv_keep_init = TCPTV_KEEP_INIT;
extern u_long sb_max;
@@ -409,7 +413,7 @@ tcp_input(struct mbuf *m, ...)
u_long tiwin;
u_int32_t ts_val, ts_ecr;
int ts_present = 0;
- int iphlen, toff;
+ int iphlen;
va_list ap;
struct tcphdr *th;
#ifdef INET6
@@ -423,13 +427,12 @@ 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);
- toff = va_arg(ap, int);
+ iphlen = va_arg(ap, int);
va_end(ap);
tcpstat.tcps_rcvtotal++;
@@ -459,68 +462,38 @@ tcp_input(struct mbuf *m, ...)
switch (af) {
case AF_INET:
#ifdef DIAGNOSTIC
- if (toff < sizeof(struct ip)) {
+ if (iphlen < sizeof(struct ip)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
- 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++;
+ if (iphlen > sizeof(struct ip)) {
+#if 0 /*XXX*/
+ ip_stripoptions(m, (struct mbuf *)0);
+ iphlen = sizeof(struct ip);
+#else
+ m_freem(m);
return;
- }
- len = m->m_pkthdr.len;
- tlen = len - toff;
-#ifdef TCP_ECN
- /* save ip_tos before clearing it for checksum */
- iptos = ip->ip_tos;
#endif
+ }
break;
#ifdef INET6
case AF_INET6:
#ifdef DIAGNOSTIC
- if (toff < sizeof(struct ip6_hdr)) {
+ if (iphlen < sizeof(struct ip6_hdr)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
- ip6 = mtod(m, struct ip6_hdr *);
- iphlen = sizeof(*ip6);
- IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
- sizeof(struct tcphdr));
- if (th == NULL) {
- tcpstat.tcps_rcvshort++;
+ if (iphlen > sizeof(struct ip6_hdr)) {
+#if 0 /*XXX*/
+ ipv6_stripoptions(m, iphlen);
+ iphlen = sizeof(struct ip6_hdr);
+#else
+ m_freem(m);
return;
- }
- len = m->m_pkthdr.len;
- tlen = len - toff;
-#ifdef TCP_ECN
- iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
#endif
-
- /* Be proactive about malicious use of IPv4 mapped address */
- if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
- IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
- /* XXX stat */
- goto drop;
}
-
- /*
- * Be proactive about unspecified IPv6 address in source.
- * As we use all-zero to indicate unbounded/unconnected pcb,
- * unspecified IPv6 address can be used to confuse us.
- *
- * Note that packets with unspecified IPv6 destination is
- * already dropped in ip6_input.
- */
- if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
- /* XXX stat */
- goto drop;
- }
-
break;
#endif
default:
@@ -528,19 +501,49 @@ tcp_input(struct mbuf *m, ...)
return;
}
+ if (m->m_len < iphlen + sizeof(struct tcphdr)) {
+ m = m_pullup2(m, iphlen + sizeof(struct tcphdr));
+ if (m == 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 *);
+
+#ifdef TCP_ECN
+ /* save ip_tos before clearing it for checksum */
+ iptos = ip->ip_tos;
+#endif
/*
* Checksum extended TCP header and data.
*/
- HTONS(ip->ip_len);
+ 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 (in4_cksum(m, IPPROTO_TCP, toff, tlen) != 0) {
+ if ((ti->ti_sum = in_cksum(m, len)) != 0) {
tcpstat.tcps_rcvbadsum++;
goto drop;
}
@@ -549,8 +552,35 @@ tcp_input(struct mbuf *m, ...)
tcpstat.tcps_inhwcsum++;
}
break;
+ }
#ifdef INET6
case AF_INET6:
+ ip6 = mtod(m, struct ip6_hdr *);
+ tlen = m->m_pkthdr.len - iphlen;
+#ifdef TCP_ECN
+ iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+#endif
+
+ /* Be proactive about malicious use of IPv4 mapped address */
+ if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
+ IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
+ /* XXX stat */
+ goto drop;
+ }
+
+ /*
+ * Be proactive about unspecified IPv6 address in source.
+ * As we use all-zero to indicate unbounded/unconnected pcb,
+ * unspecified IPv6 address can be used to confuse us.
+ *
+ * Note that packets with unspecified IPv6 destination is
+ * already dropped in ip6_input.
+ */
+ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
+ /* XXX stat */
+ goto drop;
+ }
+
/*
* Checksum extended TCP header and data.
*/
@@ -563,6 +593,8 @@ 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
@@ -574,13 +606,25 @@ tcp_input(struct mbuf *m, ...)
}
tlen -= off;
if (off > sizeof(struct tcphdr)) {
- IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, off);
- if (th == NULL) {
- tcpstat.tcps_rcvshort++;
- return;
+ 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);
}
optlen = off - sizeof(struct tcphdr);
- optp = mtod(m, u_int8_t *) + toff + sizeof(struct tcphdr);
+ optp = mtod(m, u_int8_t *) + iphlen + sizeof(struct tcphdr);
/*
* Do quick retrieval of timestamp options ("options
* prediction?"). If timestamp is the only option and it's
@@ -668,28 +712,16 @@ findpcb:
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
if (so->so_options & SO_DEBUG) {
ostate = tp->t_state;
- 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;
- }
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *));
+ break;
#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;
- }
+ case AF_INET:
+ tcp_saveti = *(mtod(m, struct tcpiphdr *));
+ break;
}
- 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;
@@ -847,7 +879,7 @@ findpcb:
tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
} else
tdb = NULL;
- ipsp_spd_lookup(m, af, toff, &error, IPSP_DIRECTION_IN,
+ ipsp_spd_lookup(m, af, iphlen, &error, IPSP_DIRECTION_IN,
tdb, inp);
if (error) {
splx(s);
@@ -1044,7 +1076,7 @@ findpcb:
if (so->so_state & SS_CANTRCVMORE)
m_freem(m);
else {
- m_adj(m, toff + off);
+ m_adj(m, iphlen + off);
sbappendstream(&so->so_rcv, m);
}
sorwakeup(so);
@@ -1058,7 +1090,7 @@ findpcb:
/*
* Compute mbuf offset to TCP data segment.
*/
- hdroptlen = toff + off;
+ hdroptlen = iphlen + off;
/*
* Calculate amount of space in receive window,
@@ -2206,8 +2238,20 @@ dodata: /* XXX */
break;
}
}
- if (so->so_options & SO_DEBUG)
- tcp_trace(TA_INPUT, ostate, tp, tcp_saveti, 0, tlen);
+ 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;
+ }
+ }
/*
* Return any desired output.
@@ -2215,7 +2259,6 @@ dodata: /* XXX */
if (needoutput || (tp->t_flags & TF_ACKNOW)) {
(void) tcp_output(tp);
}
- m_freem(tcp_saveti);
return;
dropafterack:
@@ -2228,7 +2271,6 @@ dropafterack:
m_freem(m);
tp->t_flags |= TF_ACKNOW;
(void) tcp_output(tp);
- m_freem(tcp_saveti);
return;
dropwithreset_ratelim:
@@ -2278,17 +2320,27 @@ 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))
- tcp_trace(TA_DROP, ostate, tp, tcp_saveti, 0, tlen);
+ 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;
+ }
+ }
- m_freem(tcp_saveti);
m_freem(m);
/* destroy temporarily created socket */
if (dropsocket)
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index facb432fbfd..80c927bc06a 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.56 2003/06/02 23:28:14 millert Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.57 2003/06/09 07:40:25 itojun Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -1067,20 +1067,9 @@ send:
/*
* Trace.
*/
- 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);
- }
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0,
+ len);
/*
* Fill in IP length and desired time to live and
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 26f2f659623..501efc21a7b 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.70 2003/06/02 23:28:15 millert Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.71 2003/06/09 07:40:25 itojun Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -484,7 +484,7 @@ tcp_usrreq(so, req, m, nam, control)
panic("tcp_usrreq");
}
if (tp && (so->so_options & SO_DEBUG))
- tcp_trace(TA_USER, ostate, tp, NULL, req, 0);
+ tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);
splx(s);
return (error);
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 264f1df2be7..3acccd04282 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.50 2003/06/02 23:28:15 millert Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.51 2003/06/09 07:40:25 itojun Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -420,7 +420,7 @@ void tcp_setpersist(struct tcpcb *);
void tcp_slowtimo(void);
struct mbuf *
tcp_template(struct tcpcb *);
-void tcp_trace(int, int, struct tcpcb *, struct mbuf *, int, int);
+void tcp_trace(int, int, struct tcpcb *, caddr_t, int, int);
struct tcpcb *
tcp_usrclosed(struct tcpcb *);
int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t);