summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1998-08-24 07:47:39 +0000
committerdfr <dfr@FreeBSD.org>1998-08-24 07:47:39 +0000
commitb9492066e97d868408f504260ae6be723843e4e8 (patch)
tree39418968d5099f5b89b07632470056fe32935ec1 /sys/netinet/tcp_input.c
parent91d93c9726bff72d58cdc4eab23a032d9f461681 (diff)
downloadFreeBSD-src-b9492066e97d868408f504260ae6be723843e4e8.zip
FreeBSD-src-b9492066e97d868408f504260ae6be723843e4e8.tar.gz
Re-implement tcp and ip fragment reassembly to not store pointers in the
ip header which can't work on alpha since pointers are too big. Reviewed by: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 75aef2a..16eb79b 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
- * $Id: tcp_input.c,v 1.78 1998/05/31 18:42:49 peter Exp $
+ * $Id: tcp_input.c,v 1.79 1998/07/06 03:20:19 julian Exp $
*/
#include "opt_ipfw.h" /* for ipfw_fwd */
@@ -110,7 +110,7 @@ static void tcp_xmit_timer __P((struct tcpcb *, int));
*/
#define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->seg_next == (struct tcpiphdr *)(tp) && \
+ (tp)->t_segq == NULL && \
(tp)->t_state == TCPS_ESTABLISHED) { \
if (tcp_delack_enabled) \
tp->t_flags |= TF_DELACK; \
@@ -134,10 +134,14 @@ tcp_reass(tp, ti, m)
register struct tcpiphdr *ti;
struct mbuf *m;
{
- register struct tcpiphdr *q;
+ struct mbuf *q;
+ struct mbuf *p;
+ struct mbuf *nq;
struct socket *so = tp->t_inpcb->inp_socket;
int flags;
+#define GETTCP(m) ((struct tcpiphdr *)m->m_pkthdr.header)
+
/*
* Call with ti==0 after become established to
* force pre-ESTABLISHED data up to user socket.
@@ -145,12 +149,13 @@ tcp_reass(tp, ti, m)
if (ti == 0)
goto present;
+ m->m_pkthdr.header = ti;
+
/*
* Find a segment which begins after this one does.
*/
- for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
- q = (struct tcpiphdr *)q->ti_next)
- if (SEQ_GT(q->ti_seq, ti->ti_seq))
+ for (q = tp->t_segq, p = NULL; q; p = q, q = q->m_nextpkt)
+ if (SEQ_GT(GETTCP(q)->ti_seq, ti->ti_seq))
break;
/*
@@ -158,11 +163,10 @@ tcp_reass(tp, ti, m)
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
+ if (p != NULL) {
register int i;
- q = (struct tcpiphdr *)q->ti_prev;
/* conversion to int (in i) handles seq wraparound */
- i = q->ti_seq + q->ti_len - ti->ti_seq;
+ i = GETTCP(p)->ti_seq + GETTCP(p)->ti_len - ti->ti_seq;
if (i > 0) {
if (i >= ti->ti_len) {
tcpstat.tcps_rcvduppack++;
@@ -180,36 +184,41 @@ tcp_reass(tp, ti, m)
ti->ti_len -= i;
ti->ti_seq += i;
}
- q = (struct tcpiphdr *)(q->ti_next);
}
tcpstat.tcps_rcvoopack++;
tcpstat.tcps_rcvoobyte += ti->ti_len;
- REASS_MBUF(ti) = m; /* XXX */
/*
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (q != (struct tcpiphdr *)tp) {
- register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
+ while (q) {
+ register int i = (ti->ti_seq + ti->ti_len) - GETTCP(q)->ti_seq;
if (i <= 0)
break;
- if (i < q->ti_len) {
- q->ti_seq += i;
- q->ti_len -= i;
- m_adj(REASS_MBUF(q), i);
+ if (i < GETTCP(q)->ti_len) {
+ GETTCP(q)->ti_seq += i;
+ GETTCP(q)->ti_len -= i;
+ m_adj(q, i);
break;
}
- q = (struct tcpiphdr *)q->ti_next;
- m = REASS_MBUF((struct tcpiphdr *)q->ti_prev);
- remque(q->ti_prev);
- m_freem(m);
+
+ nq = q->m_nextpkt;
+ if (p)
+ p->m_nextpkt = nq;
+ else
+ tp->t_segq = nq;
+ m_freem(q);
+ q = nq;
}
- /*
- * Stick new segment in its place.
- */
- insque(ti, q->ti_prev);
+ if (p == NULL) {
+ m->m_nextpkt = tp->t_segq;
+ tp->t_segq = m;
+ } else {
+ m->m_nextpkt = p->m_nextpkt;
+ p->m_nextpkt = m;
+ }
present:
/*
@@ -218,22 +227,25 @@ present:
*/
if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0);
- ti = tp->seg_next;
- if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+ q = tp->t_segq;
+ if (!q || GETTCP(q)->ti_seq != tp->rcv_nxt)
return (0);
do {
- tp->rcv_nxt += ti->ti_len;
- flags = ti->ti_flags & TH_FIN;
- remque(ti);
- m = REASS_MBUF(ti);
- ti = (struct tcpiphdr *)ti->ti_next;
+ tp->rcv_nxt += GETTCP(q)->ti_len;
+ flags = GETTCP(q)->ti_flags & TH_FIN;
+ nq = q->m_nextpkt;
+ tp->t_segq = nq;
+ q->m_nextpkt = NULL;
if (so->so_state & SS_CANTRCVMORE)
- m_freem(m);
+ m_freem(q);
else
- sbappend(&so->so_rcv, m);
- } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
+ sbappend(&so->so_rcv, q);
+ q = nq;
+ } while (q && GETTCP(q)->ti_seq == tp->rcv_nxt);
sorwakeup(so);
return (flags);
+
+#undef GETTCP
}
/*
@@ -288,8 +300,7 @@ tcp_input(m, iphlen)
*/
tlen = ((struct ip *)ti)->ip_len;
len = sizeof (struct ip) + tlen;
- ti->ti_next = ti->ti_prev = 0;
- ti->ti_x1 = 0;
+ bzero(ti->ti_x1, sizeof(ti->ti_x1));
ti->ti_len = (u_short)tlen;
HTONS(ti->ti_len);
ti->ti_sum = in_cksum(m, len);
@@ -572,7 +583,7 @@ findpcb:
return;
}
} else if (ti->ti_ack == tp->snd_una &&
- tp->seg_next == (struct tcpiphdr *)tp &&
+ tp->t_segq == NULL &&
ti->ti_len <= sbspace(&so->so_rcv)) {
/*
* this is a pure, in-sequence data packet
OpenPOWER on IntegriCloud