00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2015-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018
00019 // tcp_state_none.cc author davis mcpherson <davmcphe@@cisco.com>
00020 // Created on: Jul 30, 2015
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025
00026 #include "tcp_state_none.h"
00027
00028 #include "tcp_normalizer.h"
00029 #include "tcp_session.h"
00030
00031 TcpStateNone::TcpStateNone(TcpStateMachine& tsm) :
00032 TcpStateHandler(TcpStreamTracker::TCP_STATE_NONE, tsm)
00033 {
00034 }
00035
00036
00037 bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00038 {
00039 Flow* flow = tsd.get_flow();
00040
00041 flow->ssn_state.direction = FROM_CLIENT;
00042
00043 flow->session_state |= STREAM_STATE_SYN;
00044 trk.init_on_syn_sent(tsd);
00045 trk.session->init_new_tcp_session(tsd);
00046
00047 return default_state_action(tsd, trk);
00048 }
00049
00050 bool TcpStateNone::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00051 {
00052 // FIXIT-H syn received on undefined client, figure this out and do the right thing
00053 return default_state_action(tsd, trk);
00054 }
00055
00056 bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00057 {
00058 Flow* flow = tsd.get_flow();
00059
00060 if ( !trk.session->config->require_3whs() || trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00061 {
00062 flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
00063 trk.init_on_synack_sent(tsd);
00064 trk.session->init_new_tcp_session(tsd);
00065 trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
00066 }
00067 else if ( trk.session->config->require_3whs() )
00068 {
00069 trk.session->generate_no_3whs_event();
00070 return false;
00071 }
00072
00073 return default_state_action(tsd, trk);
00074 }
00075
00076 bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00077 {
00078 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00079 {
00080 trk.init_on_synack_recv(tsd);
00081 trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
00082 if ( tsd.get_seg_len() > 0 )
00083 trk.session->handle_data_segment(tsd);
00084 }
00085 else if ( trk.session->config->require_3whs() )
00086 {
00087 trk.session->generate_no_3whs_event();
00088 return false;
00089 }
00090
00091 return default_state_action(tsd, trk);
00092 }
00093
00094 bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00095 {
00096 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
00097 ( tsd.get_seg_len() > 0 ) ) )
00098 {
00099 Flow* flow = tsd.get_flow();
00100
00101 // FIXIT-H do we need to verify the ACK field is >= the seq of the SYN-ACK?
00102 // 3-way Handshake complete, create TCP session
00103 flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
00104 STREAM_STATE_ESTABLISHED );
00105 trk.init_on_3whs_ack_sent(tsd);
00106 trk.session->init_new_tcp_session(tsd);
00107 trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
00108 }
00109 else if ( trk.session->config->require_3whs() )
00110 {
00111 trk.session->generate_no_3whs_event();
00112 return false;
00113 }
00114
00115 return default_state_action(tsd, trk);
00116 }
00117
00118 bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00119 {
00120 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
00121 ( tsd.get_seg_len() > 0 ) ) )
00122 {
00123 Flow* flow = tsd.get_flow();
00124
00125 if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
00126 {
00127 trk.init_on_3whs_ack_recv(tsd);
00128 trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
00129 }
00130 }
00131 else if ( trk.session->config->require_3whs() )
00132 {
00133 trk.session->generate_no_3whs_event();
00134 return false;
00135 }
00136
00137 return default_state_action(tsd, trk);
00138 }
00139
00140 bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00141 {
00142 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00143 {
00144 Flow* flow = tsd.get_flow();
00145
00146 flow->session_state |= STREAM_STATE_MIDSTREAM;
00147 flow->set_session_flags(SSNFLAG_MIDSTREAM);
00148
00149 trk.init_on_data_seg_sent(tsd);
00150 trk.session->init_new_tcp_session(tsd);
00151
00152 if ( flow->session_state & STREAM_STATE_ESTABLISHED )
00153 trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
00154 }
00155 else if ( trk.session->config->require_3whs() )
00156 {
00157 trk.session->generate_no_3whs_event();
00158 return false;
00159 }
00160
00161 return default_state_action(tsd, trk);
00162 }
00163
00164 bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00165 {
00166 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00167 {
00168 Flow* flow = tsd.get_flow();
00169
00170 flow->session_state |= STREAM_STATE_MIDSTREAM;
00171 flow->set_session_flags(SSNFLAG_MIDSTREAM);
00172
00173 trk.init_on_data_seg_recv(tsd);
00174 trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
00175 trk.session->handle_data_segment(tsd);
00176 }
00177 else if ( trk.session->config->require_3whs() )
00178 {
00179 trk.session->generate_no_3whs_event();
00180 return false;
00181 }
00182
00183 return default_state_action(tsd, trk);
00184 }
00185
00186 bool TcpStateNone::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00187 {
00188 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00189 {
00190 // FIXIT-H handle FIN on midstream
00191 }
00192 else if ( trk.session->config->require_3whs() )
00193 {
00194 trk.session->generate_no_3whs_event();
00195 return false;
00196 }
00197
00198 return default_state_action(tsd, trk);
00199 }
00200
00201 bool TcpStateNone::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00202 {
00203 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00204 {
00205 // FIXIT-H handle FIN on midstream
00206 }
00207 else if ( trk.session->config->require_3whs() )
00208 {
00209 trk.session->generate_no_3whs_event();
00210 return false;
00211 }
00212
00213 return default_state_action(tsd, trk);
00214 }
00215
00216 bool TcpStateNone::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00217 {
00218 if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
00219 {
00220 // FIXIT-H handle RST on midstream
00221 }
00222
00223 return default_state_action(tsd, trk);
00224 }
00225
00226 bool TcpStateNone::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
00227 {
00228 if ( trk.update_on_rst_recv(tsd) )
00229 {
00230 trk.session->update_session_on_rst(tsd, false);
00231 trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
00232 trk.session->set_pkt_action_flag(ACTION_RST);
00233 }
00234 else
00235 {
00236 trk.session->tel.set_tcp_event(EVENT_BAD_RST);
00237 }
00238
00239 return default_state_action(tsd, trk);
00240 }
00241
00242 #ifdef FOO // FIXIT-H UNIT_TEST need work
00243 #include "tcp_normalizers.h"
00244 #include "tcp_reassemblers.h"
00245
00246 TEST_CASE("TCP State None", "[tcp_none_state][stream_tcp]")
00247 {
00248 // initialization code here
00249 Flow* flow = new Flow;
00250 TcpStreamTracker* ctrk = new TcpStreamTracker(true);
00251 TcpStreamTracker* strk = new TcpStreamTracker(false);
00252 TcpEventLogger* tel = new TcpEventLogger;
00253 TcpSession* session = new TcpSession(flow);
00254 TcpStateMachine* tsm = new TcpStateMachine;
00255 TcpStateHandler* tsh = new TcpStateNone(*tsm, *session);
00256 ctrk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, ctrk, strk);
00257 strk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, strk, ctrk);
00258 ctrk->reassembler = TcpReassemblerFactory::create(session, ctrk, StreamPolicy::OS_LINUX,
00259 false);
00260 strk->reassembler = TcpReassemblerFactory::create(session, strk, StreamPolicy::OS_LINUX, true);
00261
00262 SECTION("syn_packet")
00263 {
00264 Packet* pkt = get_syn_packet(flow);
00265 REQUIRE( ( pkt != nullptr ) );
00266
00267 SECTION("syn_sent")
00268 {
00269 flow->ssn_state.direction = FROM_CLIENT;
00270 TcpSegmentDescriptor tsd(flow, pkt, tel);
00271 ctrk->set_tcp_event(tsd);
00272 ctrk->set_require_3whs(false);
00273 tsh->eval(tsd, *ctrk);
00274 CHECK(TcpStreamTracker::TCP_SYN_SENT_EVENT == ctrk->get_tcp_event() );
00275 //CHECK( ( ctrk->get_iss() == 9050 ) );
00276 //CHECK( ( ctrk->get_snd_una() == 9051 ) );
00277 //CHECK( ( ctrk->get_snd_nxt() == 9050 ) );
00278 //CHECK( ( ctrk->get_snd_wnd() == 8192 ) );
00279 }
00280
00281 SECTION("syn_recv")
00282 {
00283 flow->ssn_state.direction = FROM_SERVER;
00284 TcpSegmentDescriptor tsd(flow, pkt, tel);
00285 ctrk->set_tcp_event(tsd);
00286 tsh->eval(tsd, *ctrk);
00287 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00288 }
00289
00290 delete pkt;
00291 }
00292
00293 SECTION("syn_ack_packet")
00294 {
00295 Packet* pkt = get_syn_ack_packet(flow);
00296 REQUIRE( ( pkt != nullptr ) );
00297
00298 SECTION("syn_ack_sent")
00299 {
00300 flow->ssn_state.direction = FROM_CLIENT;
00301 TcpSegmentDescriptor tsd(flow, pkt, tel);
00302 ctrk->set_tcp_event(tsd);
00303 ctrk->set_require_3whs(false);
00304 tsh->eval(tsd, *ctrk);
00305 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00306 }
00307
00308 SECTION("syn_ack_recv")
00309 {
00310 flow->ssn_state.direction = FROM_SERVER;
00311 TcpSegmentDescriptor tsd(flow, pkt, tel);
00312 ctrk->set_tcp_event(tsd);
00313 ctrk->set_require_3whs(false);
00314 tsh->eval(tsd, *ctrk);
00315 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00316 }
00317
00318 delete pkt;
00319 }
00320
00321 SECTION("ack_packet")
00322 {
00323 Packet* pkt = get_ack_packet(flow);
00324 REQUIRE( ( pkt != nullptr ) );
00325
00326 SECTION("ack_sent")
00327 {
00328 flow->ssn_state.direction = FROM_CLIENT;
00329 TcpSegmentDescriptor tsd(flow, pkt, tel);
00330 ctrk->set_tcp_event(tsd);
00331 ctrk->set_require_3whs(false);
00332 tsh->eval(tsd, *ctrk);
00333 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00334 }
00335
00336 SECTION("ack_recv")
00337 {
00338 flow->ssn_state.direction = FROM_SERVER;
00339 TcpSegmentDescriptor tsd(flow, pkt, tel);
00340 ctrk->set_tcp_event(tsd);
00341 ctrk->set_require_3whs(false);
00342 tsh->eval(tsd, *ctrk);
00343 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00344 }
00345
00346 delete pkt;
00347 }
00348
00349 SECTION("data_seg_packet")
00350 {
00351 Packet* pkt = get_data_packet(flow);
00352 REQUIRE( ( pkt != nullptr ) );
00353
00354 SECTION("data_seg_sent")
00355 {
00356 flow->ssn_state.direction = FROM_CLIENT;
00357 TcpSegmentDescriptor tsd(flow, pkt, tel);
00358 ctrk->set_tcp_event(tsd);
00359 ctrk->set_require_3whs(false);
00360 tsh->eval(tsd, *ctrk);
00361 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00362 }
00363
00364 SECTION("data_seg_recv")
00365 {
00366 flow->ssn_state.direction = FROM_SERVER;
00367 TcpSegmentDescriptor tsd(flow, pkt, tel);
00368 ctrk->set_tcp_event(tsd);
00369 ctrk->set_require_3whs(false);
00370 tsh->eval(tsd, *ctrk);
00371 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00372 }
00373
00374 delete pkt;
00375 }
00376
00377 SECTION("fin_packet")
00378 {
00379 Packet* pkt = get_fin_packet(flow);
00380 REQUIRE( ( pkt != nullptr ) );
00381
00382 SECTION("fin_sent")
00383 {
00384 flow->ssn_state.direction = FROM_CLIENT;
00385 TcpSegmentDescriptor tsd(flow, pkt, tel);
00386 ctrk->set_tcp_event(tsd);
00387 ctrk->set_require_3whs(false);
00388 tsh->eval(tsd, *ctrk);
00389 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00390 }
00391
00392 SECTION("fin_recv")
00393 {
00394 flow->ssn_state.direction = FROM_SERVER;
00395 TcpSegmentDescriptor tsd(flow, pkt, tel);
00396 ctrk->set_tcp_event(tsd);
00397 ctrk->set_require_3whs(false);
00398 tsh->eval(tsd, *ctrk);
00399 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00400 }
00401
00402 delete pkt;
00403 }
00404
00405 SECTION("rst_packet")
00406 {
00407 Packet* pkt = get_rst_packet(flow);
00408 REQUIRE( ( pkt != nullptr ));
00409
00410 SECTION("rst_sent")
00411 {
00412 flow->ssn_state.direction = FROM_CLIENT;
00413 TcpSegmentDescriptor tsd(flow, pkt, tel);
00414 ctrk->set_tcp_event(tsd);
00415 ctrk->set_require_3whs(false);
00416 tsh->eval(tsd, *ctrk);
00417 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ));
00418 }
00419
00420 SECTION("rst_recv")
00421 {
00422 flow->ssn_state.direction = FROM_SERVER;
00423 TcpSegmentDescriptor tsd(flow, pkt, tel);
00424 ctrk->set_tcp_event(tsd);
00425 ctrk->set_require_3whs(false);
00426 tsh->eval(tsd, *ctrk);
00427 CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
00428 }
00429
00430 delete pkt;
00431 }
00432
00433 delete flow;
00434 delete tsh;
00435 delete ctrk;
00436 delete strk;
00437 }
00438
00439 #endif
00440
END OF CODE