1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Store MSS value on Flows

This commit is contained in:
Matias Fontanini
2016-02-10 21:24:15 -08:00
parent 3b848060aa
commit 85d7401520
4 changed files with 58 additions and 17 deletions

View File

@@ -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;

View File

@@ -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.

View File

@@ -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<uint16_t>();
}
}
}
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<TCP>();
// 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<EthernetII>();
if (eth) {
client_hw_addr_ = eth->src_addr();

View File

@@ -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<EthernetII> 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<TCP>().mss(1220);
// Server's mss is 1460
packets[1].rfind_pdu<TCP>().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;