/* // Copyright (c) 2017 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #ifndef __INCLUDE_RTE_CT_TCP_H__ #define __INCLUDE_RTE_CT_TCP_H__ #include #include #include #include #include #include #include #include #include #include #include #include "rte_cnxn_tracking.h" /* AN INNER, PRIVATE INTERFACE FOR RTE_CNXN_TRACKING */ /* constants for TCP options */ #define RTE_CT_TCPOPT_EOL 0 /* End of options */ #define RTE_CT_TCPOPT_NOP 1 /* Padding */ #define RTE_CT_TCPOPT_MSS 2 /* Segment size negotiating */ #define RTE_CT_TCPOPT_WINDOW 3 /* Window scaling */ #define RTE_CT_TCPOPT_SACK_PERM 4 /* SACK Permitted */ #define RTE_CT_TCPOPT_SACK 5 /* SACK Block */ #define RTE_CT_TCPOPT_TIMESTAMP 8 /* RTT estimations */ #define RTE_CT_TCPOLEN_MSS 4 #define RTE_CT_TCPOLEN_WINDOW 3 #define RTE_CT_TCPOLEN_SACK_PERM 2 #define RTE_CT_TCPOLEN_TIMESTAMP 10 #define RTE_CT_TCPOLEN_PER_SACK_ENTRY 8 #define RTE_CT_TCPOLEN_MSS_ALIGNED 4 #define RTE_CT_TCPOLEN_WINDOW_ALIGNED 4 #define RTE_CT_TCPOLEN_SACK_PERM_ALIGNED 4 #define RTE_CT_TCPOLEN_TIMESTAMP_ALIGNED 12 #define RTE_CT_MAX_TCP_WINDOW_SCALE 14 #define RTE_SP_OPTIONS_MSS 1 #define RTE_SP_OPTIONS_WINDOW_SCALE 2 #define RTE_SP_OPTIONS_TIMESTAMP 4 #define RTE_SP_OPTIONS_SACK_PERM 8 enum rte_ct_packet_action { RTE_CT_OPEN_CONNECTION, RTE_CT_DROP_PACKET, RTE_CT_FORWARD_PACKET, RTE_CT_DESTROY_CNXN_AND_FORWARD_PACKET, RTE_CT_REOPEN_CNXN_AND_FORWARD_PACKET, RTE_CT_SEND_CLIENT_SYNACK, RTE_CT_SEND_SERVER_SYN, RTE_CT_SEND_SERVER_ACK, RTE_CT_HIJACK }; enum rte_ct_connstatus { RTE_INIT_CONN, RTE_SEEN_REPLY_CONN, RTE_ASSURED_CONN }; /* TCP tracking. */ static const char *const rte_ct_tcp_names[] = { "NONE", "SYN_SENT", "SYN_RECV", "ESTABLISHED", "FIN_WAIT", "CLOSE_WAIT", "LAST_ACK", "TIME_WAIT", "CLOSE", "SYN_SENT2", "RETRANS", "UNACK", "IGNORE" }; static const char *const rte_ct_udp_names[] = { "NONE_UDP", "UNREPLIED", "REPLIED" }; /* Fixme: what about big packets? */ #define RTE_MAX_ACKWIN_CONST 66000 /* Window scaling is advertised by the sender */ #define RTE_CT_TCP_FLAG_WINDOW_SCALE 0x01 /* SACK is permitted by the sender */ #define RTE_CT_TCP_FLAG_SACK_PERM 0x02 /* This sender sent FIN first */ #define RTE_CT_TCP_FLAG_CLOSE_INIT 0x04 /* Be liberal in window checking */ #define RTE_CT_TCP_FLAG_BE_LIBERAL 0x08 /* Has unacknowledged data */ #define RTE_CT_TCP_FLAG_DATA_UNACKNOWLEDGED 0x10 /* The field td_maxack has been set */ #define RTE_CT_TCP_FLAG_MAXACK_SET 0x20 /* Marks possibility for expected RFC5961 challenge ACK */ #define RTE_CT_EXP_CHALLENGE_ACK 0x40 /* TCP header flags of interest */ #define RTE_CT_TCPHDR_FIN 0x01 #define RTE_CT_TCPHDR_SYN 0x02 #define RTE_CT_TCPHDR_RST 0x04 #define RTE_CT_TCPHDR_ACK 0x10 #define RTE_CT_TCPHDR_RST_ACK (RTE_CT_TCPHDR_RST | RTE_CT_TCPHDR_ACK) /* state machine values. Note that order is important as relative checks made */ enum rte_ct_tcp_states { RTE_CT_TCP_NONE, RTE_CT_TCP_SYN_SENT, RTE_CT_TCP_SYN_RECV, RTE_CT_TCP_ESTABLISHED, RTE_CT_TCP_FIN_WAIT, RTE_CT_TCP_CLOSE_WAIT, RTE_CT_TCP_LAST_ACK, RTE_CT_TCP_TIME_WAIT, RTE_CT_TCP_CLOSE, RTE_CT_TCP_SYN_SENT_2, RTE_CT_TCP_RETRANS, RTE_CT_TCP_UNACK, RTE_CT_TCP_IGNORE }; enum rte_ct_udp_states { RTE_CT_UDP_NONE, RTE_CT_UDP_UNREPLIED, RTE_CT_UDP_REPLIED, RTE_CT_UDP_MAX }; #define RTE_CT_TCP_MAX RTE_CT_TCP_UNACK enum rte_ct_pkt_direction { RTE_CT_DIR_ORIGINAL, RTE_CT_DIR_REPLY }; struct rte_ct_tcp_state { uint32_t end; /* max of seq + len */ uint32_t maxend; /* max of ack + max(win, 1) */ uint32_t maxwin; /* max(win) */ uint32_t maxack; /* max of ack */ uint8_t scale; /* window scale factor */ uint8_t flags; /* per direction options */ }; struct rte_synproxy_options { uint8_t options; uint8_t window_scale; uint16_t mss; uint32_t ts_val; uint32_t ts_echo_reply; uint16_t initial_window; }; struct ct_sp_cnxn_data { /* buffer client pkt while waiting on server setup, * store in reverse order */ struct rte_mbuf *buffered_pkt_list; uint32_t original_spoofed_seq; /* difference between spoofed and real seq from server */ uint32_t seq_diff; struct rte_synproxy_options cnxn_options; /* non-zero if this connection created using synproxy */ uint8_t synproxied; bool half_established; /* non-zero after both half-connections established */ bool cnxn_established; }; struct rte_ct_tcp { struct rte_ct_tcp_state seen[2]; /* connection parms per direction */ uint8_t state; uint8_t last_dir; /* Direction of the last packet * (TODO: enum ip_conntrack_dir) */ uint8_t retrans; /* Number of retransmitted packets */ uint8_t last_index; /* Index of the last packet */ uint32_t last_seq; /* Last seq number seen in dir */ uint32_t last_ack; /* Last seq number seen opposite dir */ uint32_t last_end; /* Last seq + len */ uint16_t last_win; /* Last window seen in dir */ /* For SYN packets while we may be out-of-sync */ uint8_t last_wscale; /* Last window scaling factor seen */ uint8_t last_flags; /* Last flags set */ }; /* * rte_ct_cnxn_counters holds all the connection-specicif counters. * TODO: Make available in public interface */ struct rte_ct_cnxn_counters { uint64_t packets_received;//Added for CT-NAT uint64_t packets_forwarded; uint64_t packets_dropped; }; struct rte_ct_proto { struct rte_ct_tcp tcp_ct_data; /* TCP specific data fields*/ struct ct_sp_cnxn_data synproxy_data; }; /* * rte_ct_cnxn_data contains all the data for a TCP connection. This include * state data as necessary for verifying the validity of TCP packets. In * addition, it holds data necessary for implementing the TCP timers. */ struct rte_ct_cnxn_data { /* The timer will be kept as part of the cnxn_data. When it fires, the * pointer to the timer can be cast as the pointer to the cnxn_data */ struct rte_timer timer; /* !!!!! IMPORTANT: Keep as first field !!!!! */ struct rte_ct_cnxn_counters counters; /* full key stored here to allow the timer to remove the connection */ /* TODO: Consider storing key signature as well to speed up deletions.*/ uint32_t key[10]; struct rte_ct_proto ct_protocol; /* the 100 ms timing step that a packet was seen for connection */ uint64_t expected_timeout; /* Abstract states also used for timer values, e.g. RTE_CT_TCP_UNACK*/ uint8_t state_used_for_timer; /* used to compute the "direction" of the packet */ uint8_t key_is_client_order; uint8_t connstatus; uint8_t protocol; /* used to store the type of packet ipv4 or ipv6 */ uint8_t type; //#ifdef FTP_ALG // Bypass flag to indicate that ALG checking is no more needed; uint8_t alg_bypass_flag; // Can we use key_is_client_order for direction checking uint8_t server_direction; int16_t tcpSeqdiff; // PORT = 0, PASV = 1 uint8_t ftp_session_type; uint32_t tcp_payload_size; int16_t seq_client; int16_t ack_client; int16_t seq_server; int16_t ack_server; //#endif } __rte_cache_aligned; #define RTE_CT_TCP_MAX_RETRANS 3 struct rte_ct_tcptimeout { /* a table of timeouts for each state of TCP */ uint64_t tcp_timeouts[RTE_CT_TCP_MAX + 1]; }; struct rte_ct_misc_options { uint8_t synproxy_enabled; uint32_t tcp_loose; uint32_t tcp_be_liberal; uint32_t tcp_max_retrans; }; struct rte_ct_udptimeout { uint64_t udp_timeouts[RTE_CT_UDP_MAX + 1]; }; struct rte_ct_timeout { struct rte_ct_tcptimeout tcptimeout; struct rte_ct_udptimeout udptimeout; }; struct rte_ct_cnxn_tracker { struct rte_hash *rhash; /* * Data for bulk hash lookup. Use this memory as temporary space. * Too big for stack (64*16 bytes) */ uint32_t hash_keys[RTE_HASH_LOOKUP_BULK_MAX][10]; /* table of pointers to above, for bulk hash lookup */ void *hash_key_ptrs[RTE_HASH_LOOKUP_BULK_MAX]; #ifdef CT_CGNAT uint32_t positions[RTE_HASH_LOOKUP_BULK_MAX];/*added for ALG*/ #endif /* hash table and timer storage */ uint32_t num_cnxn_entries; /* * pointer to data space used for hash table, "num_cnxn_entries" long. * Memory allocated during initialization. */ struct rte_ct_cnxn_data *hash_table_entries; struct rte_CT_counter_block *counters; uint64_t hertz; uint64_t timing_cycles_per_timing_step; uint64_t timing_100ms_steps; uint64_t timing_100ms_steps_previous; uint64_t timing_last_time; struct rte_ct_timeout ct_timeout; struct rte_ct_misc_options misc_options; char name[16]; struct rte_ct_cnxn_data *new_connections[64]; struct rte_mbuf *buffered_pkt_list; int latest_connection; /* offset into mbuf where synnproxy can store a pointer */ uint16_t pointer_offset; } __rte_cache_aligned; /* * Returns a value stating if this is a valid TCP open connection attempt. * If valid, updates cnxn with any data fields it need to save. */ enum rte_ct_packet_action rte_ct_tcp_new_connection( struct rte_ct_cnxn_tracker *inst, struct rte_ct_cnxn_data *cnxn, struct rte_mbuf *pkt, int use_synproxy, uint8_t ip_hdr_size); /* * Returns a value stating if this is a valid TCP packet for the give connection. * If valid, updates cnxn with any data fields it need to save. */ enum rte_ct_packet_action rte_ct_verify_tcp_packet( struct rte_ct_cnxn_tracker *inst, struct rte_ct_cnxn_data *cnxn, struct rte_mbuf *pkt, uint8_t key_was_flipped, uint8_t ip_hdr_size); /* * Returns a value stating if this is a valid UDP open connection attempt. * If valid, updates cnxn with any data fields it need to save. */ uint8_t rte_ct_udp_new_connection( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd, struct rte_mbuf *pkt); /* * Returns a value stating if this is a valid UDP packet for the give connection. * If valid, updates cnxn with any data fields it need to save. */ enum rte_ct_packet_action rte_ct_udp_packet( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd, struct rte_mbuf *pkt, uint8_t key_was_flipped); /* * For the given connection, set a timeout based on the given state. If the * timer is already set, this call will reset the timer with a new value. */ void rte_ct_set_cnxn_timer_for_tcp( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd, uint8_t tcp_state); void rte_ct_set_cnxn_timer_for_udp( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd, uint8_t tcp_state); /* Cancel timer associated with the connection. Safe to call if no timer set.*/ void rte_ct_cancel_cnxn_timer(struct rte_ct_cnxn_data *cd); /* * SYNPROXY related routines. Detailed comments are available in * rte_ct_synproxy.c where they are implemented. */ /* these 3 routines convert a received packet to a different one */ void rte_sp_cvt_to_spoofed_client_synack(struct rte_ct_cnxn_data *cd, struct rte_mbuf *old_pkt); void rte_sp_cvt_to_spoofed_server_syn(struct rte_ct_cnxn_data *cd, struct rte_mbuf *old_pkt); void rte_sp_cvt_to_spoofed_server_ack(struct rte_ct_cnxn_data *cd, struct rte_mbuf *old_pkt); /* These two routines adjust seq or ack numbers, * as part of the proxy mechanism */ void rte_sp_adjust_client_ack_before_window_check( struct rte_ct_cnxn_data *cd, void *i_hdr, struct tcp_hdr *thdr, enum rte_ct_pkt_direction dir); void rte_sp_adjust_server_seq_after_window_check( struct rte_ct_cnxn_data *cd, void *i_hdr, struct tcp_hdr *thdr, enum rte_ct_pkt_direction dir); /* parse tcp options and save in t_opts */ void rte_sp_parse_options(struct rte_mbuf *pkt, struct rte_ct_cnxn_data *cd); /* these two routines deal with packet buffering */ void rte_ct_buffer_packet( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd, struct rte_mbuf *pkt); void rte_ct_release_buffered_packets( struct rte_ct_cnxn_tracker *ct, struct rte_ct_cnxn_data *cd); #endif /* TCPCONNTRACK_H */