diff --git a/src/packet_analysis/protocol/ip/CMakeLists.txt b/src/packet_analysis/protocol/ip/CMakeLists.txt index 7e6d6ff8b4..fdefb433d0 100644 --- a/src/packet_analysis/protocol/ip/CMakeLists.txt +++ b/src/packet_analysis/protocol/ip/CMakeLists.txt @@ -1,3 +1,5 @@ zeek_add_plugin( PacketAnalyzer IP SOURCES IP.cc IPBasedAnalyzer.cc SessionAdapter.cc Plugin.cc) + +add_subdirectory(conn_key) diff --git a/src/packet_analysis/protocol/ip/conn_key/CMakeLists.txt b/src/packet_analysis/protocol/ip/conn_key/CMakeLists.txt new file mode 100644 index 0000000000..e3736f23ee --- /dev/null +++ b/src/packet_analysis/protocol/ip/conn_key/CMakeLists.txt @@ -0,0 +1 @@ +zeek_add_subdir_library(connkey-ip SOURCES IPBasedConnKey.cc) diff --git a/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.cc b/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.cc new file mode 100644 index 0000000000..ca4ac01e5e --- /dev/null +++ b/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.cc @@ -0,0 +1,3 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h" diff --git a/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h b/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h new file mode 100644 index 0000000000..4202b3420d --- /dev/null +++ b/src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h @@ -0,0 +1,123 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include + +#include "zeek/Conn.h" +#include "zeek/ConnKey.h" +#include "zeek/IPAddr.h" + +namespace zeek { + +namespace detail { + +/** + * Struct for embedding into an IPBasedConnKey. + */ +struct PackedConnTuple { + in6_addr ip1; + in6_addr ip2; + uint16_t port1 = 0; + uint16_t port2 = 0; + uint16_t proto = 0; +} __attribute__((packed, aligned)); + +} // namespace detail + +/** + * Abstract key class for IP-based connections. + * + * ConnKey instances for IP always hold a ConnTuple instance which is provided + * by the IPBasedAnalyzer. The InitConnTuple() method stores a normalized version + * in the tuple, losing the information about orig and responder. + */ +class IPBasedConnKey : public zeek::ConnKey { +public: + void InitTuple(const ConnTuple& ct) { InitPackedTuple(ct); } + + /** + * Return a modifiable reference to the embedded PackedConnTuple. + * + * This is virtual to give subclasses control over where + * to place the tuple within the key. + * + * @return A modifiable reference to the embedded PackedConnTuple. + */ + virtual detail::PackedConnTuple& PackedTuple() = 0; + + /** + * Return a non-modifiable reference to the embedded PackedConnTuple. + * + * This is virtual to give subclasses control over where + * to place the tuple within the key. + * + * @return A non-modifiable reference to the embedded PackedConnTuple. + */ + virtual const detail::PackedConnTuple& PackedTuple() const = 0; + +private: + /** + * Initialize a packed tuple from a ConnTuple instance. + */ + void InitPackedTuple(const ConnTuple& ct) { + auto& tuple = PackedTuple(); + + if ( ct.is_one_way || addr_port_canon_lt(ct.src_addr, ct.src_port, ct.dst_addr, ct.dst_port) ) { + ct.src_addr.CopyIPv6(&tuple.ip1); + ct.dst_addr.CopyIPv6(&tuple.ip2); + tuple.port1 = ct.src_port; + tuple.port2 = ct.dst_port; + } + else { + ct.dst_addr.CopyIPv6(&tuple.ip1); + ct.src_addr.CopyIPv6(&tuple.ip2); + tuple.port1 = ct.dst_port; + tuple.port2 = ct.src_port; + } + + tuple.proto = ct.proto; + } +}; + +using IPBasedConnKeyPtr = std::unique_ptr; + +/** + * The usual 5-tuple ConnKey, fully instantiable. + */ +class IPConnKey : public IPBasedConnKey { +public: + /** + * Constructor. + * + * Fill any holes in the key struct as we use the full tuple as a key. + */ + IPConnKey() { memset(static_cast(&key), 0, sizeof(key)); } + + /** + * @copydoc + */ + detail::PackedConnTuple& PackedTuple() override { return key.tuple; } + + /** + * @copydoc + */ + const detail::PackedConnTuple& PackedTuple() const override { return key.tuple; } + +protected: + /** + * @copydoc + */ + zeek::session::detail::Key DoSessionKey() const override { + return {reinterpret_cast(&key), sizeof(key), + // XXX: Not sure we need CONNECTION_KEY_TYPE? + session::detail::Key::CONNECTION_KEY_TYPE}; + } + +private: + struct { + struct detail::PackedConnTuple tuple; + } key; +}; + +} // namespace zeek