From 85d7401520cf2baeb6d5b0a3182feabfdd36fd56 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Wed, 10 Feb 2016 21:24:15 -0800 Subject: [PATCH] Store MSS value on Flows --- examples/stream_dump.cpp | 1 - include/tins/tcp_ip/stream.h | 23 ++++++++++++++++++++--- src/tcp_ip/stream.cpp | 31 ++++++++++++++++++------------- tests/src/tcp_ip.cpp | 20 ++++++++++++++++++++ 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/examples/stream_dump.cpp b/examples/stream_dump.cpp index d76ee70..66353ae 100644 --- a/examples/stream_dump.cpp +++ b/examples/stream_dump.cpp @@ -99,7 +99,6 @@ void on_client_data(Stream& stream) { // Whenever there's new server data on the stream, this callback is executed. // This does the same thing as on_client_data void on_server_data(Stream& stream) { - std::cout << "server data\n"; string data(stream.server_payload().begin(), stream.server_payload().end()); cout << server_endpoint(stream) << " >> " << client_endpoint(stream) << ": " << endl << data << endl; diff --git a/include/tins/tcp_ip/stream.h b/include/tins/tcp_ip/stream.h index bdd9e4e..7495567 100644 --- a/include/tins/tcp_ip/stream.h +++ b/include/tins/tcp_ip/stream.h @@ -250,7 +250,24 @@ public: * followed to keep track of its state. */ void ignore_data_packets(); + + /** + * \brief Returns the MSS for this Flow. + * + * If the MSS option wasn't provided by the peer, -1 is returned + */ + int mss() const; private: + // Compress all flags into just one struct using bitfields + struct flags { + flags() : ignore_data_packets(0) { + + } + + uint32_t is_v6:1, + ignore_data_packets:1; + }; + void store_payload(uint32_t seq, payload_type payload); buffered_payload_type::iterator erase_iterator(buffered_payload_type::iterator iter); void update_state(const TCP& tcp); @@ -263,8 +280,8 @@ private: data_available_callback_type on_data_callback_; out_of_order_callback_type on_out_of_order_callback_; State state_; - bool is_v6_; - bool ignore_data_packets_; + int mss_; + flags flags_; }; /** @@ -310,7 +327,7 @@ public: /** * \brief Constructs a TCP stream using the provided packet. */ - Stream(const PDU& initial_packet); + Stream(PDU& initial_packet); /** * \brief Processes this packet. diff --git a/src/tcp_ip/stream.cpp b/src/tcp_ip/stream.cpp index abfd097..93c109f 100644 --- a/src/tcp_ip/stream.cpp +++ b/src/tcp_ip/stream.cpp @@ -78,18 +78,18 @@ int seq_compare(uint32_t seq1, uint32_t seq2) { Flow::Flow(const IPv4Address& dest_address, uint16_t dest_port, uint32_t sequence_number) -: seq_number_(sequence_number), dest_port_(dest_port), state_(UNKNOWN), - is_v6_(false), ignore_data_packets_(false) { +: seq_number_(sequence_number), dest_port_(dest_port), state_(UNKNOWN), mss_(-1) { OutputMemoryStream output(dest_address_.data(), dest_address_.size()); output.write(dest_address); + flags_.is_v6 = false; } Flow::Flow(const IPv6Address& dest_address, uint16_t dest_port, uint32_t sequence_number) -: seq_number_(sequence_number), dest_port_(dest_port), state_(UNKNOWN), - is_v6_(true), ignore_data_packets_(false) { +: seq_number_(sequence_number), dest_port_(dest_port), state_(UNKNOWN), mss_(-1) { OutputMemoryStream output(dest_address_.data(), dest_address_.size()); output.write(dest_address); + flags_.is_v6 = true; } void Flow::data_callback(const data_available_callback_type& callback) { @@ -107,7 +107,7 @@ void Flow::process_packet(PDU& pdu) { if (tcp) { update_state(*tcp); } - if (ignore_data_packets_) { + if (flags_.ignore_data_packets) { return; } if (!tcp || !raw) { @@ -218,11 +218,15 @@ void Flow::update_state(const TCP& tcp) { else if (state_ == UNKNOWN && (tcp.flags() & TCP::SYN) != 0) { state_ = SYN_SENT; seq_number_ = tcp.seq(); + const TCP::option* mss_option = tcp.search_option(TCP::MSS); + if (mss_option) { + mss_ = mss_option->to(); + } } } bool Flow::is_v6() const { - return is_v6_; + return flags_.is_v6; } bool Flow::is_finished() const { @@ -289,19 +293,20 @@ void Flow::state(State new_state) { } void Flow::ignore_data_packets() { - ignore_data_packets_ = true; + flags_.ignore_data_packets = true; +} + +int Flow::mss() const { + return mss_; } // Stream -Stream::Stream(const PDU& packet) +Stream::Stream(PDU& packet) : client_flow_(extract_client_flow(packet)), server_flow_(extract_server_flow(packet)), auto_cleanup_(true) { - const TCP& tcp = packet.rfind_pdu(); - // If it's a SYN, set the proper state - if (tcp.flags() == TCP::SYN) { - client_flow().state(Flow::SYN_SENT); - } + // Update client flow state + client_flow().process_packet(packet); const EthernetII* eth = packet.find_pdu(); if (eth) { client_hw_addr_ = eth->src_addr(); diff --git a/tests/src/tcp_ip.cpp b/tests/src/tcp_ip.cpp index 9163aa2..616649e 100644 --- a/tests/src/tcp_ip.cpp +++ b/tests/src/tcp_ip.cpp @@ -359,6 +359,26 @@ TEST_F(FlowTest, StreamFollower_ThreeWayHandshake) { EXPECT_EQ(61, stream.server_flow().sequence_number()); } +TEST_F(FlowTest, StreamFollower_MSS) { + using std::placeholders::_1; + + vector packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); + // Client's mss is 1220 + packets[0].rfind_pdu().mss(1220); + // Server's mss is 1460 + packets[1].rfind_pdu().mss(1460); + StreamFollower follower; + follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); + for (size_t i = 0; i < packets.size(); ++i) { + follower.process_packet(packets[i]); + } + Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, + IPv4Address("4.3.2.1"), 25); + EXPECT_EQ(1220, stream.client_flow().mss()); + EXPECT_EQ(1460, stream.server_flow().mss()); +} + + TEST_F(FlowTest, StreamFollower_RSTClosesStream) { using std::placeholders::_1;