summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMike Frantzen <frantzen@cvs.openbsd.org>2004-05-05 23:16:04 +0000
committerMike Frantzen <frantzen@cvs.openbsd.org>2004-05-05 23:16:04 +0000
commit03fe38624159eac6e41dc6a190b5b866f9b76748 (patch)
tree5b58d58675b482a463883b257b61556403829b2a /sys
parent8f6a4f2e535871b3eafb365b6ebe1de3a4e5bc57 (diff)
Use RFC1323 PAWS timestamps as a logical extension to the conventional TCP
sequence numbers by taking advantage of the maximum 1KHz clock as an upperbound on the timestamp. Typically gains 10 to 18 bits of additional security against blind data insertion attacks. More if the TS Echo wasn't optional :-( Enabled with: scrub on !lo0 all reassemble tcp ok dhartmei@. documentation help from jmc@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf.c28
-rw-r--r--sys/net/pf_ioctl.c3
-rw-r--r--sys/net/pf_norm.c325
-rw-r--r--sys/net/pfvar.h28
4 files changed, 348 insertions, 36 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 6bbdcb2e4fb..13b373924e8 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.445 2004/04/28 02:51:58 cedric Exp $ */
+/* $OpenBSD: pf.c,v 1.446 2004/05/05 23:16:03 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -111,8 +111,6 @@ struct pool pf_src_tree_pl, pf_rule_pl;
struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
-void pf_print_state(struct pf_state *);
-void pf_print_flags(u_int8_t);
u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
u_int8_t);
@@ -2760,8 +2758,11 @@ cleanup:
return (PF_DROP);
}
if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
- pf_normalize_tcp_stateful(m, off, pd, &reason, th, &s->src,
- &s->dst, &rewrite)) {
+ pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
+ &s->src, &s->dst, &rewrite)) {
+ /* This really shouldn't happen!!! */
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_normalize_tcp_stateful failed on first pkt"));
pf_normalize_tcp_cleanup(s);
pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
@@ -3926,6 +3927,12 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(pd->flags & PFDESC_IP_REAS) == 0)) {
/* Require an exact sequence match on resets when possible */
+ if (dst->scrub || src->scrub) {
+ if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
+ *state, src, dst, &copyback))
+ return (PF_DROP);
+ }
+
/* update max window */
if (src->max_win < win)
src->max_win = win;
@@ -4010,6 +4017,12 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(*state)->packets[0], (*state)->packets[1]);
}
+ if (dst->scrub || src->scrub) {
+ if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
+ *state, src, dst, &copyback))
+ return (PF_DROP);
+ }
+
/* update max window */
if (src->max_win < win)
src->max_win = win;
@@ -4075,11 +4088,6 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
return (PF_DROP);
}
- if (dst->scrub || src->scrub) {
- if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
- src, dst, &copyback))
- return (PF_DROP);
- }
/* Any packets which have gotten here are to be passed */
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index e554039d3c9..56f7c2cd6ec 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.118 2004/05/03 07:51:59 kjc Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.119 2004/05/05 23:16:03 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -178,6 +178,7 @@ pfattach(int num)
timeout[PFTM_FRAG] = 30; /* Fragment expire */
timeout[PFTM_INTERVAL] = 10; /* Expire interval */
timeout[PFTM_SRC_NODE] = 0; /* Source tracking */
+ timeout[PFTM_TS_DIFF] = 30; /* Allowed TS diff */
timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz);
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index fd306c6d978..f95c57f9682 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.84 2004/04/28 02:43:09 pb Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.85 2004/05/05 23:16:03 frantzen Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -118,8 +118,12 @@ u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t);
int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
struct tcphdr *, int);
-#define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \
- { printf("%s: ", __func__); printf x ;}
+#define DPFPRINTF(x) do { \
+ if (pf_status.debug >= PF_DEBUG_MISC) { \
+ printf("%s: ", __func__); \
+ printf x ; \
+ } \
+} while(0)
/* Globals */
struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
@@ -1310,6 +1314,7 @@ int
pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
{
+ u_int32_t tsval, tsecr;
u_int8_t hdr[60];
u_int8_t *opt;
@@ -1365,6 +1370,16 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
PFSS_TIMESTAMP;
src->scrub->pfss_ts_mod =
htonl(arc4random());
+
+ /* note PFSS_PAWS not set yet */
+ memcpy(&tsval, &opt[2],
+ sizeof(u_int32_t));
+ memcpy(&tsecr, &opt[6],
+ sizeof(u_int32_t));
+ src->scrub->pfss_tsval0 = ntohl(tsval);
+ src->scrub->pfss_tsval = ntohl(tsval);
+ src->scrub->pfss_tsecr = ntohl(tsecr);
+ src->scrub->pfss_last = mono_time;
}
/* FALLTHROUGH */
default:
@@ -1391,12 +1406,15 @@ pf_normalize_tcp_cleanup(struct pf_state *state)
int
pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
- u_short *reason, struct tcphdr *th, struct pf_state_peer *src,
- struct pf_state_peer *dst, int *writeback)
+ u_short *reason, struct tcphdr *th, struct pf_state *state,
+ struct pf_state_peer *src, struct pf_state_peer *dst, int *writeback)
{
+ u_int32_t tsval, tsecr;
+ u_int tsval_from_last;
u_int8_t hdr[60];
u_int8_t *opt;
int copyback = 0;
+ int got_ts = 0;
KASSERT(src->scrub || dst->scrub);
@@ -1450,32 +1468,46 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
* NAT detection, OS uptime determination or
* reboot detection.
*/
+
+ if (got_ts) {
+ /* Huh? Multiple timestamps!? */
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("multiple TS??"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
if (opt[1] >= TCPOLEN_TIMESTAMP) {
- u_int32_t ts_value;
- if (src->scrub &&
+ memcpy(&tsval, &opt[2],
+ sizeof(u_int32_t));
+ if (tsval && src->scrub &&
(src->scrub->pfss_flags &
PFSS_TIMESTAMP)) {
- memcpy(&ts_value, &opt[2],
- sizeof(u_int32_t));
- ts_value = htonl(ntohl(ts_value)
- + src->scrub->pfss_ts_mod);
+ tsval = ntohl(tsval);
pf_change_a(&opt[2],
- &th->th_sum, ts_value, 0);
+ &th->th_sum,
+ htonl(tsval +
+ src->scrub->pfss_ts_mod),
+ 0);
copyback = 1;
}
/* Modulate TS reply iff valid (!0) */
- memcpy(&ts_value, &opt[6],
+ memcpy(&tsecr, &opt[6],
sizeof(u_int32_t));
- if (ts_value && dst->scrub &&
+ if (tsecr && dst->scrub &&
(dst->scrub->pfss_flags &
PFSS_TIMESTAMP)) {
- ts_value = htonl(ntohl(ts_value)
- - dst->scrub->pfss_ts_mod);
+ tsecr = ntohl(tsecr)
+ - dst->scrub->pfss_ts_mod;
pf_change_a(&opt[6],
- &th->th_sum, ts_value, 0);
+ &th->th_sum, htonl(tsecr),
+ 0);
copyback = 1;
}
+ got_ts = 1;
}
/* FALLTHROUGH */
default:
@@ -1494,9 +1526,268 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
}
+ /*
+ * Must invalidate PAWS checks on connections idle for too long.
+ * The fastest allowed timestamp clock is 1ms. That turns out to
+ * be about 24 days before it wraps. XXX Right now our lowerbound
+ * TS echo check only works for the first 12 days of a connection
+ * when the TS has exhausted half its 32bit space
+ */
+#define TS_MAX_IDLE (24*24*60*60)
+#define TS_MAX_CONN (12*24*60*60) /* XXX remove when better tsecr check */
+ if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (mono_time.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
+ time.tv_sec - state->creation > TS_MAX_CONN)) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("src idled out of PAWS\n"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ src->scrub->pfss_flags = (src->scrub->pfss_flags & ~PFSS_PAWS)
+ | PFSS_PAWS_IDLED;
+ }
+ if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
+ mono_time.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("dst idled out of PAWS\n"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ dst->scrub->pfss_flags = (dst->scrub->pfss_flags & ~PFSS_PAWS)
+ | PFSS_PAWS_IDLED;
+ }
+
+ if (got_ts && src->scrub && dst->scrub &&
+ (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (dst->scrub->pfss_flags & PFSS_PAWS)) {
+ /* Validate that the timestamps are "in-window".
+ * RFC1323 describes TCP Timestamp options that allow
+ * measurement of RTT (round trip time) and PAWS
+ * (protection against wrapped sequence numbers). PAWS
+ * gives us a set of rules for rejecting packets on
+ * long fat pipes (packets that were somehow delayed
+ * in transit longer than the time it took to send the
+ * full TCP sequence space of 4Gb). We can use these
+ * rules and infer a few others that will let us treat
+ * the 32bit timestamp and the 32bit echoed timestamp
+ * as sequence numbers to prevent a blind attacker from
+ * inserting packets into a connection.
+ *
+ * RFC1323 tells us:
+ * - The timestamp on this packet must be greater than
+ * or equal to the last value echoed by the other
+ * endpoint. The RFC says those will be discarded
+ * since it is a dup that has already been acked.
+ * This gives us a lowerbound on the timestamp.
+ * timestamp >= other last echoed timestamp
+ * - The timestamp will be less than or equal to
+ * the last timestamp plus the time between the
+ * last packet and now. The RFC defines the max
+ * clock rate as 1ms. We will allow clocks to be
+ * up to 10% fast and will allow a total difference
+ * or 30 seconds due to a route change. And this
+ * gives us an upperbound on the timestamp.
+ * timestamp <= last timestamp + max ticks
+ * We have to be careful here. Windows will send an
+ * initial timestamp of zero and then initialize it
+ * to a random value after the 3whs; presumably to
+ * avoid a DoS by having to call an expensive RNG
+ * during a SYN flood. Proof MS has at least one
+ * good security geek.
+ *
+ * - The TCP timestamp option must also echo the other
+ * endpoints timestamp. The timestamp echoed is the
+ * one carried on the earliest unacknowledged segment
+ * on the left edge of the sequence window. The RFC
+ * states that the host will reject any echoed
+ * timestamps that were larger than any ever sent.
+ * This gives us an upperbound on the TS echo.
+ * tescr <= largest_tsval
+ * - The lowerbound on the TS echo is a little more
+ * tricky to determine. The other endpoint's echoed
+ * values will not decrease. But there may be
+ * network conditions that re-order packets and
+ * cause our view of them to decrease. For now the
+ * only lowerbound we can safely determine is that
+ * the TS echo will never be less than the orginal
+ * TS. XXX There is probably a better lowerbound.
+ * Remove TS_MAX_CONN with better lowerbound check.
+ * tescr >= other original TS
+ *
+ * It is also important to note that the fastest
+ * timestamp clock of 1ms will wrap its 32bit space in
+ * 24 days. So we just disable TS checking after 24
+ * days of idle time. We actually must use a 12d
+ * connection limit until we can come up with a better
+ * lowerbound to the TS echo check.
+ */
+ struct timeval delta_ts;
+ int ts_fudge;
+
+
+ /*
+ * PFTM_TS_DIFF is how many seconds of leeway to allow
+ * a host's timestamp. This can happen if the previous
+ * packet got delayed in transit for much longer than
+ * this packet.
+ */
+ if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
+ ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
+
+
+ /* Calculate max ticks since the last timestamp */
+#define TS_MAXFREQ 1100 /* RFC max TS freq of 1Khz + 10% skew */
+#define TS_MICROSECS 1000000 /* microseconds per second */
+ timersub(&mono_time, &src->scrub->pfss_last, &delta_ts);
+ tsval_from_last = (delta_ts.tv_sec + ts_fudge) * TS_MAXFREQ;
+ tsval_from_last += delta_ts.tv_usec / (TS_MICROSECS/TS_MAXFREQ);
+
+
+ if ((src->state >= TCPS_ESTABLISHED &&
+ dst->state >= TCPS_ESTABLISHED) &&
+ (SEQ_LT(tsval, dst->scrub->pfss_tsecr) ||
+ SEQ_GT(tsval, src->scrub->pfss_tsval + tsval_from_last) ||
+ (tsecr && (SEQ_GT(tsecr, dst->scrub->pfss_tsval) ||
+ SEQ_LT(tsecr, dst->scrub->pfss_tsval0))))) {
+ /* Bad RFC1323 implementation or an insertion attack.
+ *
+ * - Solaris 2.6 and 2.7 are known to send another ACK
+ * after the FIN,FIN|ACK,ACK closing that carries
+ * an old timestamp.
+ */
+
+ DPFPRINTF(("Timestamp failed %c%c%c%c\n",
+ SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ',
+ SEQ_GT(tsval, src->scrub->pfss_tsval +
+ tsval_from_last) ? '1' : ' ',
+ SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ',
+ SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '));
+ DPFPRINTF((" tsval: %lu tsecr: %lu +ticks: %lu idle: %lus %lums\n",
+ tsval, tsecr, tsval_from_last, delta_ts.tv_sec,
+ delta_ts.tv_usec / 1000));
+ DPFPRINTF((" src->tsval: %lu tsecr: %lu\n",
+ src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
+ DPFPRINTF((" dst->tsval: %lu tsecr: %lu tsval0: %lu\n",
+ dst->scrub->pfss_tsval, dst->scrub->pfss_tsecr,
+ dst->scrub->pfss_tsval0));
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
+
+ /* XXX I'd really like to require tsecr but it's optional */
+
+ } else if (!got_ts && (th->th_flags & TH_RST) == 0 &&
+ ((src->state == TCPS_ESTABLISHED && dst->state == TCPS_ESTABLISHED)
+ || pd->p_len > 0 || (th->th_flags & TH_SYN)) &&
+ src->scrub && dst->scrub &&
+ (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (dst->scrub->pfss_flags & PFSS_PAWS)) {
+ /* Didn't send a timestamp. Timestamps aren't really useful
+ * when:
+ * - connection opening or closing (often not even sent).
+ * but we must not let an attacker to put a FIN on a
+ * data packet to sneak it through our ESTABLISHED check.
+ * - on a TCP reset. RFC suggests not even looking at TS.
+ * - on an empty ACK. The TS will not be echoed so it will
+ * probably not help keep the RTT calculation in sync and
+ * there isn't as much danger when the sequence numbers
+ * got wrapped. So some stacks don't include TS on empty
+ * ACKs :-(
+ *
+ * To minimize the disruption to mostly RFC1323 conformant
+ * stacks, we will only require timestamps on data packets.
+ *
+ * And what do ya know, we cannot require timestamps on data
+ * packets. There appear to be devices that do legitimate
+ * TCP connection hijacking. There are HTTP devices that allow
+ * a 3whs (with timestamps) and then buffer the HTTP request.
+ * If the intermediate device has the HTTP response cache, it
+ * will spoof the response but not bother timestamping its
+ * packets. So we can look for the presence of a timestamp in
+ * the first data packet and if there, require it in all future
+ * packets.
+ */
+
+ if (pd->p_len > 0 && (src->scrub->pfss_flags & PFSS_DATA_TS)) {
+ /*
+ * Hey! Someone tried to sneak a packet in. Or the
+ * stack changed its RFC1323 behavior?!?!
+ */
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("Did not receive expected RFC1323 timestamp\n"));
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
+ }
+
+
+ /*
+ * We will note if a host sends his data packets with or without
+ * timestamps. And require all data packets to contain a timestamp
+ * if the first does. PAWS implicitly requires that all data packets be
+ * timestamped. But I think there are middle-man devices that hijack
+ * TCP streams immedietly after the 3whs and don't timestamp their
+ * packets (seen in a WWW accelerator or cache).
+ */
+ if (pd->p_len > 0 && (src->scrub->pfss_flags &
+ (PFSS_TIMESTAMP|PFSS_DATA_TS|PFSS_DATA_NOTS)) == PFSS_TIMESTAMP) {
+ if (got_ts)
+ src->scrub->pfss_flags |= PFSS_DATA_TS;
+ else {
+ src->scrub->pfss_flags |= PFSS_DATA_NOTS;
+ if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
+ (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
+ /* Don't warn if other host rejected RFC1323 */
+ DPFPRINTF(("Broken RFC1323 stack did not timestamp data packet. Disabled PAWS security.\n"));
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ }
+ }
+
+
+ /*
+ * Update PAWS values
+ */
+ if (got_ts && src->scrub && PFSS_TIMESTAMP == (src->scrub->pfss_flags &
+ (PFSS_PAWS_IDLED|PFSS_TIMESTAMP))) {
+ src->scrub->pfss_last = mono_time;
+ if (SEQ_GEQ(tsval, src->scrub->pfss_tsval) ||
+ (src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_tsval = tsval;
+
+ if (tsecr) {
+ if (SEQ_GEQ(tsecr, src->scrub->pfss_tsecr) ||
+ (src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_tsecr = tsecr;
+
+ if ((src->scrub->pfss_flags & PFSS_PAWS) == 0 &&
+ (SEQ_LT(tsval, src->scrub->pfss_tsval0) ||
+ src->scrub->pfss_tsval0 == 0)) {
+ /* tsval0 MUST be the lowest timestamp */
+ src->scrub->pfss_tsval0 = tsval;
+ }
+
+ /* Only fully initialized after a TS gets echoed */
+ if ((src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_flags |= PFSS_PAWS;
+ }
+ }
+
/* I have a dream.... TCP segment reassembly.... */
return (0);
}
+
int
pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
int off)
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 07224e79591..8f69e7a0d96 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.192 2004/04/28 02:51:58 cedric Exp $ */
+/* $OpenBSD: pfvar.h,v 1.193 2004/05/05 23:16:03 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -69,7 +69,7 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE,
PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL,
PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE,
- PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
+ PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, PF_LIMIT_MAX };
#define PF_POOL_IDMASK 0x0f
@@ -569,11 +569,19 @@ struct pf_src_node {
#define PFSNODE_HIWAT 10000 /* default source node table size */
struct pf_state_scrub {
+ struct timeval pfss_last; /* time received last packet */
+ u_int32_t pfss_tsecr; /* last echoed timestamp */
+ u_int32_t pfss_tsval; /* largest timestamp */
+ u_int32_t pfss_tsval0; /* original timestamp */
u_int16_t pfss_flags;
-#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */
- u_int8_t pfss_ttl; /* stashed TTL */
+#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */
+#define PFSS_PAWS 0x0010 /* stricter PAWS checks */
+#define PFSS_PAWS_IDLED 0x0020 /* was idle too long. no PAWS */
+#define PFSS_DATA_TS 0x0040 /* timestamp on data packets */
+#define PFSS_DATA_NOTS 0x0080 /* no timestamp on data packets */
+ u_int8_t pfss_ttl; /* stashed TTL */
u_int8_t pad;
- u_int32_t pfss_ts_mod; /* timestamp modulation */
+ u_int32_t pfss_ts_mod; /* timestamp modulation */
};
struct pf_state_host {
@@ -870,7 +878,8 @@ struct pf_pdesc {
#define PFRES_SHORT 3 /* Dropping short packet */
#define PFRES_NORM 4 /* Dropping by normalizer */
#define PFRES_MEMORY 5 /* Dropped due to lacking mem */
-#define PFRES_MAX 6 /* total+1 */
+#define PFRES_TS 6 /* Bad TCP Timestamp (RFC1323) */
+#define PFRES_MAX 7 /* total+1 */
#define PFRES_NAMES { \
"match", \
@@ -879,6 +888,7 @@ struct pf_pdesc {
"short", \
"normalize", \
"memory", \
+ "bad-timestamp", \
NULL \
}
@@ -1326,6 +1336,8 @@ void pf_src_tree_remove_state(struct pf_state *);
extern struct pf_state *pf_find_state_byid(struct pf_state *);
extern struct pf_state *pf_find_state_all(struct pf_state *key,
u_int8_t tree, int *more);
+extern void pf_print_state(struct pf_state *);
+extern void pf_print_flags(u_int8_t);
extern struct pf_anchor *pf_find_anchor(const char *);
extern struct pf_ruleset *pf_find_ruleset(char *, char *);
extern struct pf_ruleset *pf_find_or_create_ruleset(
@@ -1377,8 +1389,8 @@ void pf_normalize_tcp_cleanup(struct pf_state *);
int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
struct tcphdr *, struct pf_state_peer *, struct pf_state_peer *);
int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
- u_short *, struct tcphdr *, struct pf_state_peer *,
- struct pf_state_peer *, int *);
+ u_short *, struct tcphdr *, struct pf_state *,
+ struct pf_state_peer *, struct pf_state_peer *, int *);
u_int32_t
pf_state_expires(const struct pf_state *);
void pf_purge_expired_fragments(void);