diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-01-24 11:30:01 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-01-24 11:30:01 +0000 |
commit | 256367812d0f1e51f5c49db403ab280a663dcdab (patch) | |
tree | 877d1420a35191188259608be01e65471fe6e6e9 /sys/net/pf.c | |
parent | 73e37073b79fa338ba9c9831270f6a98fe1999ec (diff) |
Fix wscale support, the first version didn't really work right.
Interestingly, our own stack uses wscale 1 quite regularly, and I now
suspect that this is what caused most of the state failures I've seen.
They were quite rare, but with working wscale support, they are reduced
even more. ok henning@
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r-- | sys/net/pf.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 24c044c081f..9fe4ea62c83 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.307 2003/01/23 13:36:17 dhartmei Exp $ */ +/* $OpenBSD: pf.c,v 1.308 2003/01/24 11:30:00 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -2817,8 +2817,9 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, { struct pf_tree_node key; struct tcphdr *th = pd->hdr.tcp; - u_int32_t win = ntohs(th->th_win); + u_int16_t win = ntohs(th->th_win); u_int32_t ack, end, seq; + u_int8_t sws, dws; int ackskew; struct pf_state_peer *src, *dst; @@ -2839,6 +2840,12 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, dst = &(*state)->src; } + if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) { + sws = src->wscale & PF_WSCALE_MASK; + dws = dst->wscale & PF_WSCALE_MASK; + } else + sws = dws = 0; + /* * Sequence tracking algorithm from Guido van Rooij's paper: * http://www.madison-gurkha.com/publications/tcp_filtering/ @@ -2879,8 +2886,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, * after establishment) */ if (src->seqhi == 1 || - SEQ_GEQ(end + MAX(1, dst->max_win), src->seqhi)) - src->seqhi = end + MAX(1, dst->max_win); + SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi)) + src->seqhi = end + MAX(1, dst->max_win << dws); if (win > src->max_win) src->max_win = win; @@ -2899,9 +2906,6 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, end++; } - if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) - win <<= src->wscale & PF_WSCALE_MASK; - if ((th->th_flags & TH_ACK) == 0) { /* Let it pass through the ack skew check */ ack = dst->seqlo; @@ -2927,7 +2931,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, #define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */ if (SEQ_GEQ(src->seqhi, end) && /* Last octet inside other's window space */ - SEQ_GEQ(seq, src->seqlo - dst->max_win) && + SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) && /* Retrans: not more than one window back */ (ackskew >= -MAXACKWINDOW) && /* Acking not more than one window back */ @@ -2944,8 +2948,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, if (SEQ_GT(end, src->seqlo)) src->seqlo = end; /* slide the window of what the other end can send */ - if (SEQ_GEQ(ack + win, dst->seqhi)) - dst->seqhi = ack + MAX(win, 1); + if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) + dst->seqhi = ack + MAX((win << sws), 1); /* update states */ @@ -3034,8 +3038,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, if (SEQ_GT(end, src->seqlo)) src->seqlo = end; /* slide the window of what the other end can send */ - if (SEQ_GEQ(ack + win, dst->seqhi)) - dst->seqhi = ack + MAX(win, 1); + if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) + dst->seqhi = ack + MAX((win << sws), 1); /* * Cannot set dst->seqhi here since this could be a shotgunned @@ -3062,7 +3066,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, direction == (*state)->direction ? "fwd" : "rev"); printf("pf: State failure on: %c %c %c %c | %c %c\n", SEQ_GEQ(src->seqhi, end) ? ' ' : '1', - SEQ_GEQ(seq, src->seqlo - dst->max_win) ? ' ': '2', + SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ? + ' ': '2', (ackskew >= -MAXACKWINDOW) ? ' ' : '3', (ackskew <= MAXACKWINDOW) ? ' ' : '4', SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5', @@ -3379,6 +3384,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, u_int32_t seq; struct pf_tree_node key; struct pf_state_peer *src, *dst; + u_int8_t dws; /* * Only the first 8 bytes of the TCP header can be @@ -3409,6 +3415,11 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, dst = &(*state)->dst; } + if (src->wscale && dst->wscale && !(th.th_flags & TH_SYN)) + dws = dst->wscale & PF_WSCALE_MASK; + else + dws = 0; + /* Demodulate sequence number */ seq = ntohl(th.th_seq) - src->seqdiff; if (src->seqdiff) @@ -3416,7 +3427,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, htonl(seq), 0); if (!SEQ_GEQ(src->seqhi, seq) || - !SEQ_GEQ(seq, src->seqlo - dst->max_win)) { + !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws))) { if (pf_status.debug >= PF_DEBUG_MISC) { printf("pf: BAD ICMP state: "); pf_print_state(*state); |