diff --git a/sys/net/npf/npf_state_tcp.c b/sys/net/npf/npf_state_tcp.c index 1012c0479a06..5c39ffba3ad4 100644 --- a/sys/net/npf/npf_state_tcp.c +++ b/sys/net/npf/npf_state_tcp.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $ */ +/* $NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $ */ /*- * Copyright (c) 2010-2011 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $"); #include #include @@ -79,7 +79,7 @@ void npf_state_sample(npf_state_t *); /* * TCP connection timeout table (in seconds). */ -static const u_int npf_tcp_timeouts[] __read_mostly = { +static u_int npf_tcp_timeouts[] __read_mostly = { /* Closed, timeout nearly immediately. */ [NPF_TCPS_CLOSED] = 10, /* Unsynchronised states. */ @@ -99,71 +99,92 @@ static const u_int npf_tcp_timeouts[] __read_mostly = { #define NPF_TCP_MAXACKWIN 66000 -#define TH_STATE_MASK (TH_SYN | TH_ACK | TH_FIN) -#define TH_SYNACK (TH_SYN | TH_ACK) -#define TH_FINACK (TH_FIN | TH_ACK) +/* + * List of TCP flag cases and conversion of flags to a case (index). + */ + +#define TCPFC_INVALID 0 +#define TCPFC_SYN 1 +#define TCPFC_SYNACK 2 +#define TCPFC_ACK 3 +#define TCPFC_FIN 4 +#define TCPFC_COUNT 5 + +static inline u_int +npf_tcpfl2case(const int tcpfl) +{ + u_int i, c; + + /* + * Magic value maps flag combinations to TCPFC case numbers. + * Other cases are zero. Note: FIN-ACK is mapped to FIN. + */ + i = (tcpfl & (TH_SYN | TH_FIN)) | ((tcpfl & TH_ACK) >> 2); + c = (0x2430140 >> (i << 2)) & 7; + + KASSERT(c < TCPFC_COUNT); + return c; +} /* * NPF transition table of a tracked TCP connection. * * There is a single state, which is changed in the following way: * - * new_state = npf_tcp_fsm[old_state][direction][tcp_flags & TH_STATE_MASK]; + * new_state = npf_tcp_fsm[old_state][direction][npf_tcpfl2case(tcp_flags)]; * * Note that this state is different from the state in each end (host). */ -static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1] - __read_mostly = { +static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TCPFC_COUNT] = { [NPF_TCPS_CLOSED] = { [NPF_FLOW_FORW] = { /* Handshake (1): initial SYN. */ - [TH_SYN] = NPF_TCPS_SYN_SENT, + [TCPFC_SYN] = NPF_TCPS_SYN_SENT, }, }, [NPF_TCPS_SYN_SENT] = { [NPF_FLOW_FORW] = { /* SYN may be retransmitted. */ - [TH_SYN] = NPF_TCPS_OK, + [TCPFC_SYN] = NPF_TCPS_OK, }, [NPF_FLOW_BACK] = { /* Handshake (2): SYN-ACK is expected. */ - [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, + [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED, /* Simultaneous initiation - SYN. */ - [TH_SYN] = NPF_TCPS_SIMSYN_SENT, + [TCPFC_SYN] = NPF_TCPS_SIMSYN_SENT, }, }, [NPF_TCPS_SIMSYN_SENT] = { [NPF_FLOW_FORW] = { /* Original SYN re-transmission. */ - [TH_SYN] = NPF_TCPS_OK, + [TCPFC_SYN] = NPF_TCPS_OK, /* SYN-ACK response to simultaneous SYN. */ - [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, + [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED, }, [NPF_FLOW_BACK] = { /* Simultaneous SYN re-transmission.*/ - [TH_SYN] = NPF_TCPS_OK, + [TCPFC_SYN] = NPF_TCPS_OK, /* SYN-ACK response to original SYN. */ - [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, - /* FIN may be sent at this point. */ - [TH_FIN] = NPF_TCPS_FIN_SEEN, - [TH_FINACK] = NPF_TCPS_FIN_SEEN, + [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED, + /* FIN may be sent early. */ + [TCPFC_FIN] = NPF_TCPS_FIN_SEEN, }, }, [NPF_TCPS_SYN_RECEIVED] = { [NPF_FLOW_FORW] = { /* Handshake (3): ACK is expected. */ - [TH_ACK] = NPF_TCPS_ESTABLISHED, - [TH_FIN] = NPF_TCPS_CLOSING, - [TH_FINACK] = NPF_TCPS_CLOSING, + [TCPFC_ACK] = NPF_TCPS_ESTABLISHED, + /* FIN may be sent early. */ + [TCPFC_FIN] = NPF_TCPS_FIN_SEEN, }, [NPF_FLOW_BACK] = { /* SYN-ACK may be retransmitted. */ - [TH_SYNACK] = NPF_TCPS_OK, + [TCPFC_SYNACK] = NPF_TCPS_OK, /* XXX: ACK of late SYN in simultaneous case? */ - [TH_ACK] = NPF_TCPS_OK, - /* XXX: Can this happen? - [TH_FIN] = NPF_TCPS_CLOSING, */ + [TCPFC_ACK] = NPF_TCPS_OK, + /* FIN may be sent early. */ + [TCPFC_FIN] = NPF_TCPS_FIN_SEEN, }, }, [NPF_TCPS_ESTABLISHED] = { @@ -172,16 +193,14 @@ static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1] * FIN packets may have ACK set. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_OK, + [TCPFC_ACK] = NPF_TCPS_OK, /* FIN by the sender. */ - [TH_FIN] = NPF_TCPS_FIN_SEEN, - [TH_FINACK] = NPF_TCPS_FIN_SEEN, + [TCPFC_FIN] = NPF_TCPS_FIN_SEEN, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_OK, + [TCPFC_ACK] = NPF_TCPS_OK, /* FIN by the receiver. */ - [TH_FIN] = NPF_TCPS_FIN_SEEN, - [TH_FINACK] = NPF_TCPS_FIN_SEEN, + [TCPFC_FIN] = NPF_TCPS_FIN_SEEN, }, }, [NPF_TCPS_FIN_SEEN] = { @@ -192,64 +211,58 @@ static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1] * case we are closing immediately. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_CLOSE_WAIT, - [TH_FIN] = NPF_TCPS_CLOSING, - [TH_FINACK] = NPF_TCPS_CLOSING, + [TCPFC_ACK] = NPF_TCPS_CLOSE_WAIT, + [TCPFC_FIN] = NPF_TCPS_CLOSING, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_FIN_WAIT, - [TH_FIN] = NPF_TCPS_CLOSING, - [TH_FINACK] = NPF_TCPS_CLOSING, + [TCPFC_ACK] = NPF_TCPS_FIN_WAIT, + [TCPFC_FIN] = NPF_TCPS_CLOSING, }, }, [NPF_TCPS_CLOSE_WAIT] = { /* Sender has sent the FIN and closed its end. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_OK, - [TH_FIN] = NPF_TCPS_LAST_ACK, - [TH_FINACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_OK, + [TCPFC_FIN] = NPF_TCPS_LAST_ACK, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_OK, - [TH_FIN] = NPF_TCPS_LAST_ACK, - [TH_FINACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_OK, + [TCPFC_FIN] = NPF_TCPS_LAST_ACK, }, }, [NPF_TCPS_FIN_WAIT] = { /* Receiver has closed its end. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_OK, - [TH_FIN] = NPF_TCPS_LAST_ACK, - [TH_FINACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_OK, + [TCPFC_FIN] = NPF_TCPS_LAST_ACK, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_OK, - [TH_FIN] = NPF_TCPS_LAST_ACK, - [TH_FINACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_OK, + [TCPFC_FIN] = NPF_TCPS_LAST_ACK, }, }, [NPF_TCPS_CLOSING] = { /* Race of FINs - expecting ACK. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_LAST_ACK, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_LAST_ACK, + [TCPFC_ACK] = NPF_TCPS_LAST_ACK, }, }, [NPF_TCPS_LAST_ACK] = { /* FINs exchanged - expecting last ACK. */ [NPF_FLOW_FORW] = { - [TH_ACK] = NPF_TCPS_TIME_WAIT, + [TCPFC_ACK] = NPF_TCPS_TIME_WAIT, }, [NPF_FLOW_BACK] = { - [TH_ACK] = NPF_TCPS_TIME_WAIT, + [TCPFC_ACK] = NPF_TCPS_TIME_WAIT, }, }, [NPF_TCPS_TIME_WAIT] = { /* May re-open the connection as per RFC 1122. */ [NPF_FLOW_FORW] = { - [TH_SYN] = NPF_TCPS_SYN_SENT, + [TCPFC_SYN] = NPF_TCPS_SYN_SENT, }, }, }; @@ -280,7 +293,7 @@ npf_tcp_inwindow(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, * * There four boundaries are defined as following: * I) SEQ + LEN <= MAX { SND.ACK + MAX(SND.WIN, 1) } - * II) SEQ >= MAX { SND.SEQ + SND.LEN } + * II) SEQ >= MAX { SND.SEQ + SND.LEN - MAX(RCV.WIN, 1) } * III) ACK <= MAX { RCV.SEQ + RCV.LEN } * IV) ACK >= MAX { RCV.SEQ + RCV.LEN } - MAXACKWIN * @@ -427,7 +440,8 @@ npf_state_tcp(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, int di) /* Look for a transition to a new state. */ if (__predict_true((tcpfl & TH_RST) == 0)) { - nstate = npf_tcp_fsm[state][di][tcpfl & TH_STATE_MASK]; + const int flagcase = npf_tcpfl2case(tcpfl); + nstate = npf_tcp_fsm[state][di][flagcase]; } else if (state == NPF_TCPS_TIME_WAIT) { /* Prevent TIME-WAIT assassination (RFC 1337). */ nstate = NPF_TCPS_OK;