diff --git a/examples/portscan.cpp b/examples/portscan.cpp index 63affe3..df37711 100644 --- a/examples/portscan.cpp +++ b/examples/portscan.cpp @@ -116,7 +116,7 @@ bool Scanner::callback(PDU& pdu) { cout << "Port: " << setw(5) << tcp.sport() << " closed\n"; } // 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"; } } diff --git a/examples/tcp_connection_close.cpp b/examples/tcp_connection_close.cpp index 1298fdf..b1694cc 100644 --- a/examples/tcp_connection_close.cpp +++ b/examples/tcp_connection_close.cpp @@ -68,7 +68,7 @@ private: const IP& ip = pdu.rfind_pdu(); const TCP& tcp = pdu.rfind_pdu(); // 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 EthernetII packet(eth.src_addr(), eth.dst_addr()); // Do the same for IP diff --git a/include/tins/tcp.h b/include/tins/tcp.h index 879da45..7e906c5 100644 --- a/include/tins/tcp.h +++ b/include/tins/tcp.h @@ -288,13 +288,29 @@ public: * \code * TCP tcp = ...; * if(tcp.flags() == (TCP::SYN | TCP::ACK)) { - * // It's a SYN+ACK! + * // It's a SYN+ACK, but not SYN+ACK+ECN! * } * \endcode * * \return The value of the flags field. */ 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 */ diff --git a/src/tcp.cpp b/src/tcp.cpp index fb31884..81507f0 100644 --- a/src/tcp.cpp +++ b/src/tcp.cpp @@ -257,6 +257,10 @@ small_uint<12> TCP::flags() const { 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) { switch (tcp_flag) { case FIN: diff --git a/src/tcp_ip/flow.cpp b/src/tcp_ip/flow.cpp index de4fdba..573474f 100644 --- a/src/tcp_ip/flow.cpp +++ b/src/tcp_ip/flow.cpp @@ -127,19 +127,19 @@ void Flow::advance_sequence(uint32_t seq) { } void Flow::update_state(const TCP& tcp) { - if ((tcp.flags() & TCP::FIN) != 0) { + if (tcp.has_flags(TCP::FIN)) { state_ = FIN_SENT; } - else if ((tcp.flags() & TCP::RST) != 0) { + else if (tcp.has_flags(TCP::RST)) { 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 ack_tracker_ = AckTracker(tcp.ack_seq()); #endif // TINS_HAVE_ACK_TRACKER 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 #ifdef TINS_HAVE_ACK_TRACKER ack_tracker_ = AckTracker(tcp.ack_seq()); diff --git a/src/tcp_ip/stream.cpp b/src/tcp_ip/stream.cpp index 48e7cfc..1274b80 100644 --- a/src/tcp_ip/stream.cpp +++ b/src/tcp_ip/stream.cpp @@ -61,7 +61,7 @@ Stream::Stream(PDU& packet, const timestamp_type& ts) } const TCP& tcp = packet.rfind_pdu(); // 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) { diff --git a/src/tcp_ip/stream_follower.cpp b/src/tcp_ip/stream_follower.cpp index b683219..8165f1c 100644 --- a/src/tcp_ip/stream_follower.cpp +++ b/src/tcp_ip/stream_follower.cpp @@ -84,7 +84,8 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) { if (iter == streams_.end()) { // Start tracking if they're either SYNs or they contain data (attach // to an already running flow). - if (tcp->flags() == TCP::SYN || (attach_to_flows_ && tcp->find_pdu() != 0)) { + const bool is_syn = tcp->has_flags(TCP::SYN); + if (is_syn || (attach_to_flows_ && tcp->find_pdu() != 0)) { iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first; iter->second.setup_flows_callbacks(); if (on_new_connection_) { @@ -93,7 +94,7 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) { else { throw callback_not_set(); } - if (tcp->flags() != TCP::SYN) { + if (!is_syn) { // assume the connection is established iter->second.client_flow().state(Flow::ESTABLISHED); iter->second.server_flow().state(Flow::ESTABLISHED); diff --git a/src/tcp_stream.cpp b/src/tcp_stream.cpp index ec5905f..5018962 100644 --- a/src/tcp_stream.cpp +++ b/src/tcp_stream.cpp @@ -230,7 +230,7 @@ bool TCPStream::generic_process(uint32_t& my_seq, bool TCPStream::update(IP* ip, TCP* tcp) { if (!syn_ack_sent_) { - if (tcp->flags() == (TCP::SYN | TCP::ACK)) { + if (tcp->has_flags(TCP::SYN | TCP::ACK)) { server_seq_ = tcp->seq() + 1; client_seq_ = tcp->ack_seq(); syn_ack_sent_ = true;