Conn: Move conn_id init and flip to IPBasedConnKey

This loosens the coupling of the script-layer conn_id record and
the code in Conn a bit, moving more into the IPBasedConnKey class.

I'm not quite sure whether moving the flipping logic is worth it,
but assuming Conn could become non-IP in the future, it might.
This commit is contained in:
Arne Welzel 2025-07-01 12:08:02 +02:00
parent 661fa91231
commit f8eab9e9cf
4 changed files with 94 additions and 31 deletions

View file

@ -3,6 +3,7 @@
#include "zeek/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h"
#include "zeek/Conn.h"
#include "zeek/Desc.h"
using namespace zeek;
using namespace zeek::packet_analysis::IP;
@ -28,3 +29,26 @@ void IPBasedConnKey::InitTuple(const IPAddr& src_addr, uint32_t src_port, const
tuple.proto = proto;
}
void IPBasedConnKey::DoPopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) {
if ( conn_id.GetType() != id::conn_id )
zeek::reporter->InternalError("unexpected conn_id type %s", obj_desc_short(conn_id.GetType()).c_str());
conn_id.Assign(0, make_intrusive<AddrVal>(SrcAddr()));
conn_id.Assign(1, val_mgr->Port(ntohs(SrcPort()), GetTransportProto()));
conn_id.Assign(2, make_intrusive<AddrVal>(DstAddr()));
conn_id.Assign(3, val_mgr->Port(ntohs(DstPort()), GetTransportProto()));
conn_id.Assign(4, Proto());
}
void IPBasedConnKey::DoFlipRoles(RecordVal& conn_id, RecordVal& ctx) {
if ( conn_id.GetType() != id::conn_id )
zeek::reporter->InternalError("unexpected conn_id type %s", obj_desc_short(conn_id.GetType()).c_str());
const auto& tmp_addr = conn_id.GetField<zeek::AddrVal>(0);
const auto& tmp_port = conn_id.GetField<zeek::PortVal>(1);
conn_id.Assign(0, conn_id.GetField<zeek::AddrVal>(2));
conn_id.Assign(1, conn_id.GetField<zeek::PortVal>(3));
conn_id.Assign(2, tmp_addr);
conn_id.Assign(3, tmp_port);
}

View file

@ -77,6 +77,28 @@ public:
}
}
/**
* Flips the role of source and destination fields in the packed tuple.
*/
void FlipRoles() { flipped = ! flipped; }
/**
* Flips the role of originator and responder.
*
* This overload will also flip fields of the conn_id and ctx record
* values. The DoFlipRoles hook can be overridden to customize this process,
* but that's usually not needed. The default implementation will flip
* the orig_h/resp_h and orig_p/resp_p pairs.
*
* @param conn_id The conn_id record to populate.
* @param ctx The conn_id's ctx record to populate.
*/
void FlipRoles(RecordVal& conn_id, RecordVal& ctx) {
FlipRoles();
DoFlipRoles(conn_id, ctx);
}
/**
* Return a modifiable reference to the embedded PackedConnTuple.
*
@ -98,6 +120,36 @@ public:
virtual const detail::PackedConnTuple& PackedTuple() const = 0;
protected:
/**
* Overridden from ConnKey.
*
* This implementation sets orig_h, resp_h, orig_p, resp_p and proto
* on the \a conn_id record value and leaves \a ctx untouched.
*
* When implementing subclasses of IPBasedConnKey, redef the script-layer
* record type conn_id_ctx with the fields specific to your ConnKey implementation,
* e.g. VLAN IDs. Then override this method to populate the fields of \a ctx based
* on data stored in your custom ConnKey instance. Ensure to call
* IPBasedConnKey::DoPopulateConnIdVal() to populate the common \a conn_id fields, too.
*
* @param conn_id The conn_id record to populate.
* @param ctx The conn_id's ctx record to populate.
*/
void DoPopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) override;
/**
* Hook for FlipRoles.
*
* The default implementation will flip the orig_h/resp_h and orig_p/resp_p pairs.
*
* @param conn_id The conn_id record to flip.
* @param ctx The conn_id's ctx record to flip.
*/
virtual void DoFlipRoles(RecordVal& conn_id, RecordVal& ctx);
/**
* Flag for tracking if src and dst addresses provided to InitTuple() were flipped.
*/
bool flipped = false;
};

View file

@ -39,6 +39,8 @@ protected:
}
void DoPopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) override {
IPBasedConnKey::DoPopulateConnIdVal(conn_id, ctx);
// Nothing to do if we have no VLAN tags at all.
if ( key.vlan == 0 && key.inner_vlan == 0 )
return;