mirror of
https://github.com/mfontanini/libtins
synced 2026-01-22 18:25:57 +01:00
simplify tcp flag checks, fix stream_follower (#334)
* simplify tcp flag checks, fix stream_follower On various places was used simple comparison for checking state of flags. tcp.flags() == (TCP::SYN | TCP::ACK) This is not what you want usually, because this check is false in case that another flag is set also. Correct check for syn-ack packet should be: (tcp.flags() & (TCP::SYN | TCP::ACK)) == (TCP::SYN | TCP::ACK) To simplify this kind of check, add new has_flags method: bool TCP::has_flags(small_uint<12> check_flags) const * remove duplicate TCP::SYN flag check
This commit is contained in:
committed by
Matias Fontanini
parent
74e3d909e6
commit
22b4435c81
@@ -116,7 +116,7 @@ bool Scanner::callback(PDU& pdu) {
|
|||||||
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
|
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
|
||||||
}
|
}
|
||||||
// Is SYN flag on? Then port is open!
|
// Is SYN flag on? Then port is open!
|
||||||
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
else if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
|
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
const IP& ip = pdu.rfind_pdu<IP>();
|
const IP& ip = pdu.rfind_pdu<IP>();
|
||||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||||
// We'll only close a connection when seeing a SYN|ACK
|
// We'll only close a connection when seeing a SYN|ACK
|
||||||
if (tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
if (tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
// Create an ethernet header flipping the addresses
|
// Create an ethernet header flipping the addresses
|
||||||
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
||||||
// Do the same for IP
|
// Do the same for IP
|
||||||
|
|||||||
@@ -288,13 +288,29 @@ public:
|
|||||||
* \code
|
* \code
|
||||||
* TCP tcp = ...;
|
* TCP tcp = ...;
|
||||||
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||||
* // It's a SYN+ACK!
|
* // It's a SYN+ACK, but not SYN+ACK+ECN!
|
||||||
* }
|
* }
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* \return The value of the flags field.
|
* \return The value of the flags field.
|
||||||
*/
|
*/
|
||||||
small_uint<12> flags() const;
|
small_uint<12> flags() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check if the given flags are set.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* TCP tcp = ...;
|
||||||
|
* if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
|
* // It's a SYN+ACK, but it also possible that other flags are set!
|
||||||
|
* // it is equivalent to: (tpc.flags() & (TCP::SYN | TCP::ACK)) == (TCP::SYN | TCP::ACK)
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \param check_flags
|
||||||
|
* \return true if all check_flags are set
|
||||||
|
*/
|
||||||
|
bool has_flags(small_uint<12> check_flags) const;
|
||||||
|
|
||||||
/* Setters */
|
/* Setters */
|
||||||
|
|
||||||
|
|||||||
@@ -257,6 +257,10 @@ small_uint<12> TCP::flags() const {
|
|||||||
return (header_.res1 << 8) | header_.flags_8;
|
return (header_.res1 << 8) | header_.flags_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TCP::has_flags(small_uint<12> check_flags) const {
|
||||||
|
return (flags() & check_flags) == check_flags;
|
||||||
|
}
|
||||||
|
|
||||||
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
|
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
|
||||||
switch (tcp_flag) {
|
switch (tcp_flag) {
|
||||||
case FIN:
|
case FIN:
|
||||||
|
|||||||
@@ -127,19 +127,19 @@ void Flow::advance_sequence(uint32_t seq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Flow::update_state(const TCP& tcp) {
|
void Flow::update_state(const TCP& tcp) {
|
||||||
if ((tcp.flags() & TCP::FIN) != 0) {
|
if (tcp.has_flags(TCP::FIN)) {
|
||||||
state_ = FIN_SENT;
|
state_ = FIN_SENT;
|
||||||
}
|
}
|
||||||
else if ((tcp.flags() & TCP::RST) != 0) {
|
else if (tcp.has_flags(TCP::RST)) {
|
||||||
state_ = RST_SENT;
|
state_ = RST_SENT;
|
||||||
}
|
}
|
||||||
else if (state_ == SYN_SENT && (tcp.flags() & TCP::ACK) != 0) {
|
else if (state_ == SYN_SENT && tcp.has_flags(TCP::ACK)) {
|
||||||
#ifdef TINS_HAVE_ACK_TRACKER
|
#ifdef TINS_HAVE_ACK_TRACKER
|
||||||
ack_tracker_ = AckTracker(tcp.ack_seq());
|
ack_tracker_ = AckTracker(tcp.ack_seq());
|
||||||
#endif // TINS_HAVE_ACK_TRACKER
|
#endif // TINS_HAVE_ACK_TRACKER
|
||||||
state_ = ESTABLISHED;
|
state_ = ESTABLISHED;
|
||||||
}
|
}
|
||||||
else if (state_ == UNKNOWN && (tcp.flags() & TCP::SYN) != 0) {
|
else if (state_ == UNKNOWN && tcp.has_flags(TCP::SYN)) {
|
||||||
// This is the server's state, sending it's first SYN|ACK
|
// This is the server's state, sending it's first SYN|ACK
|
||||||
#ifdef TINS_HAVE_ACK_TRACKER
|
#ifdef TINS_HAVE_ACK_TRACKER
|
||||||
ack_tracker_ = AckTracker(tcp.ack_seq());
|
ack_tracker_ = AckTracker(tcp.ack_seq());
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Stream::Stream(PDU& packet, const timestamp_type& ts)
|
|||||||
}
|
}
|
||||||
const TCP& tcp = packet.rfind_pdu<TCP>();
|
const TCP& tcp = packet.rfind_pdu<TCP>();
|
||||||
// If this is not the first packet of a stream (SYN), then it's a partial stream
|
// If this is not the first packet of a stream (SYN), then it's a partial stream
|
||||||
is_partial_stream_ = tcp.flags() != TCP::SYN;
|
is_partial_stream_ = !tcp.has_flags(TCP::SYN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::process_packet(PDU& packet, const timestamp_type& ts) {
|
void Stream::process_packet(PDU& packet, const timestamp_type& ts) {
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
|
|||||||
if (iter == streams_.end()) {
|
if (iter == streams_.end()) {
|
||||||
// Start tracking if they're either SYNs or they contain data (attach
|
// Start tracking if they're either SYNs or they contain data (attach
|
||||||
// to an already running flow).
|
// to an already running flow).
|
||||||
if (tcp->flags() == TCP::SYN || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
|
const bool is_syn = tcp->has_flags(TCP::SYN);
|
||||||
|
if (is_syn || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
|
||||||
iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first;
|
iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first;
|
||||||
iter->second.setup_flows_callbacks();
|
iter->second.setup_flows_callbacks();
|
||||||
if (on_new_connection_) {
|
if (on_new_connection_) {
|
||||||
@@ -93,7 +94,7 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
|
|||||||
else {
|
else {
|
||||||
throw callback_not_set();
|
throw callback_not_set();
|
||||||
}
|
}
|
||||||
if (tcp->flags() != TCP::SYN) {
|
if (!is_syn) {
|
||||||
// assume the connection is established
|
// assume the connection is established
|
||||||
iter->second.client_flow().state(Flow::ESTABLISHED);
|
iter->second.client_flow().state(Flow::ESTABLISHED);
|
||||||
iter->second.server_flow().state(Flow::ESTABLISHED);
|
iter->second.server_flow().state(Flow::ESTABLISHED);
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ bool TCPStream::generic_process(uint32_t& my_seq,
|
|||||||
|
|
||||||
bool TCPStream::update(IP* ip, TCP* tcp) {
|
bool TCPStream::update(IP* ip, TCP* tcp) {
|
||||||
if (!syn_ack_sent_) {
|
if (!syn_ack_sent_) {
|
||||||
if (tcp->flags() == (TCP::SYN | TCP::ACK)) {
|
if (tcp->has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
server_seq_ = tcp->seq() + 1;
|
server_seq_ = tcp->seq() + 1;
|
||||||
client_seq_ = tcp->ack_seq();
|
client_seq_ = tcp->ack_seq();
|
||||||
syn_ack_sent_ = true;
|
syn_ack_sent_ = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user