summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2013-01-20 22:51:17 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2013-01-20 22:51:17 +0000
commitf8d2d1bc00a4e38b20e04a32364d436b07904801 (patch)
treee4d7903ff7bd517fe079f15eebdda8e8dce0f56f
parent79a60aa3a9cb8a9e44077937fb1ad6e876eac83a (diff)
Make pf TCP sequence number tracking less strict by one octet for
FIN packets. The data of a TCP packet must fit into the announced window, but this is not required for the sequence number of the FIN. A packet with the FIN bit set and containing data that fits exactly into the announced window was blocked. Our stack generates such packets when the receive buffer size is set to 1024. Now pf uses only the data lenght for window comparison. OK henning@
-rw-r--r--sys/net/pf.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index aa7a787b9d8..5a97987f748 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.817 2012/11/23 18:35:25 mikeb Exp $ */
+/* $OpenBSD: pf.c,v 1.818 2013/01/20 22:51:16 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -4013,7 +4013,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
{
struct tcphdr *th = pd->hdr.tcp;
u_int16_t win = ntohs(th->th_win);
- u_int32_t ack, end, seq, orig_seq;
+ u_int32_t ack, end, data_end, seq, orig_seq;
u_int8_t sws, dws;
int ackskew;
@@ -4076,6 +4076,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
}
}
}
+ data_end = end;
if (th->th_flags & TH_FIN)
end++;
@@ -4106,6 +4107,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
end = seq + pd->p_len;
if (th->th_flags & TH_SYN)
end++;
+ data_end = end;
if (th->th_flags & TH_FIN)
end++;
}
@@ -4152,7 +4154,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
#define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */
- if (SEQ_GEQ(src->seqhi, end) &&
+ if (SEQ_GEQ(src->seqhi, data_end) &&
/* Last octet inside other's window space */
SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
/* Retrans: not more than one window back */
@@ -4223,7 +4225,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
} else if ((dst->state < TCPS_SYN_SENT ||
dst->state >= TCPS_FIN_WAIT_2 ||
src->state >= TCPS_FIN_WAIT_2) &&
- SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
+ SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) &&
/* Within a window forward of the originating packet */
SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
/* Within a window backward of the originating packet */
@@ -4313,12 +4315,13 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
pd->dir == PF_IN ? "in" : "out",
pd->dir == (*state)->direction ? "fwd" : "rev");
addlog("pf: State failure on: %c %c %c %c | %c %c\n",
- SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
+ SEQ_GEQ(src->seqhi, data_end) ? ' ' : '1',
SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
' ': '2',
(ackskew >= -MAXACKWINDOW) ? ' ' : '3',
(ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
- SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
+ SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) ?
+ ' ' :'5',
SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
}
REASON_SET(reason, PFRES_BADSTATE);