1 //--------------------------------------------------------------------------
2 // Copyright (C) 2015-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // tcp_state_established.cc author davis mcpherson <davmcphe@cisco.com>
20 // Created on: Jul 30, 2015
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "tcp_state_established.h"
27 
28 #include "tcp_normalizers.h"
29 #include "tcp_session.h"
30 
TcpStateEstablished(TcpStateMachine & tsm)31 TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm) :
32     TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm)
33 { }
34 
syn_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)35 bool TcpStateEstablished::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
36 {
37     trk.session->check_for_repeated_syn(tsd);
38     return true;
39 }
40 
syn_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)41 bool TcpStateEstablished::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
42 {
43     trk.session->check_for_repeated_syn(tsd);
44     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
45     return true;
46 }
47 
syn_ack_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)48 bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
49 {
50     if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
51     {
52         // FIXIT-M there may be an issue when syn/ack from server is seen
53         // after ack from client which causes some tracker state variables to
54         // not be initialized... update_tracker_ack_sent may fix that but needs
55         // more testing
56         //trk.update_tracker_ack_sent( tsd );
57         trk.session->update_session_on_syn_ack();
58     }
59 
60     if ( trk.is_server_tracker() )
61         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
62 
63     return true;
64 }
65 
ack_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)66 bool TcpStateEstablished::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
67 {
68     trk.update_tracker_ack_sent(tsd);
69     return true;
70 }
71 
ack_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)72 bool TcpStateEstablished::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
73 {
74     trk.update_tracker_ack_recv(tsd);
75     return true;
76 }
77 
data_seg_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)78 bool TcpStateEstablished::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
79 {
80     trk.update_tracker_ack_sent(tsd);
81     if ( trk.session->no_ack_mode_enabled() )
82         trk.update_tracker_no_ack_recv(tsd);
83     return true;
84 }
85 
data_seg_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)86 bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
87 {
88     trk.update_tracker_ack_recv(tsd);
89     trk.session->handle_data_segment(tsd);
90     if ( trk.session->no_ack_mode_enabled() )
91         trk.update_tracker_no_ack_sent(tsd);
92     return true;
93 }
94 
fin_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)95 bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
96 {
97     trk.update_on_fin_sent(tsd);
98     trk.session->flow->call_handlers(tsd.get_pkt(), true);
99     trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
100     return true;
101 }
102 
fin_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)103 bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
104 {
105     trk.update_tracker_ack_recv(tsd);
106     trk.perform_fin_recv_flush(tsd);
107 
108     if ( trk.update_on_fin_recv(tsd) )
109     {
110         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
111         trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
112     }
113 
114     return true;
115 }
116 
rst_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)117 bool TcpStateEstablished::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
118 {
119     if ( trk.update_on_rst_recv(tsd) )
120     {
121         trk.session->update_session_on_rst(tsd, false);
122         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
123         trk.session->set_pkt_action_flag(ACTION_RST);
124     }
125 
126     // FIXIT-L might be good to create alert specific to RST with data
127     if ( tsd.is_data_segment() )
128         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
129 
130     return true;
131 }
132 
do_pre_sm_packet_actions(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)133 bool TcpStateEstablished::do_pre_sm_packet_actions(
134     TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
135 {
136     return trk.session->validate_packet_established_session(tsd);
137 }
138 
do_post_sm_packet_actions(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)139 bool TcpStateEstablished::do_post_sm_packet_actions(
140     TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
141 {
142     trk.session->update_paws_timestamps(tsd);
143     trk.session->check_for_window_slam(tsd);
144 
145     return true;
146 }
147 
148