From b7a22a87c635a1a9ad34dd9980afcfcc1a00b956 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 27 Jun 2025 14:02:31 +0200 Subject: [PATCH] ConnKey: Extend DoPopulateConnIdVal() with ctx This prepares the move where ConnKey implementations should fill out ctx rather than filling conn_id directly. The API continues to receive both, conn_id and ctx, as adding fields to `conn_id` is reasonable use-case even if it's just for logging purposes. --- src/Conn.cc | 5 ++-- src/ConnKey.h | 29 +++++++++++++++---- .../ip/conn_key/vlan_fivetuple/Factory.cc | 2 +- .../Baseline/plugins.connkey/conn.log.cut | 12 ++++---- testing/btest/Baseline/plugins.connkey/output | 4 +-- .../btest/plugins/connkey-plugin/src/Foo.cc | 11 +++++-- testing/btest/plugins/connkey.zeek | 7 +++-- 7 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/Conn.cc b/src/Conn.cc index 86c2c690ad..caac3ac561 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -230,9 +230,10 @@ const RecordValPtr& Connection::GetVal() { id_val->Assign(2, make_intrusive(resp_addr)); id_val->Assign(3, val_mgr->Port(ntohs(resp_port), prot_type)); id_val->Assign(4, KeyProto()); + auto* ctx = id_val->GetFieldAs(5); - // Allow customized ConnKeys to augment the conn_id: - key->PopulateConnIdVal(*id_val); + // Allow customized ConnKeys to augment conn_id and ctx. + key->PopulateConnIdVal(*id_val, *ctx); auto orig_endp = make_intrusive(id::endpoint); orig_endp->Assign(0, 0); diff --git a/src/ConnKey.h b/src/ConnKey.h index ec10104528..8670d8b9a9 100644 --- a/src/ConnKey.h +++ b/src/ConnKey.h @@ -29,16 +29,22 @@ public: void Init(const Packet& pkt) { DoInit(pkt); } /** - * When Zeek renders a connection into a script-layer record, it calls this - * method to populate custom conn_id fields unique to this ConnKey, such as - * VLAN fields. This only needs to populate in fields in addition to Zeek's - * five-tuple (i.e., complete the record, not populate all of it). + * Populates the conn_id and conn_id_ctx records. + * + * When Zeek renders a connection key into a script-layer record, it calls this + * method to populate the conn_id's and conn_id_ctx's fields that are unique to + * this ConnKey. + * + * Currently, \a conn_id and \a ctx will always have the script-layer types conn_id + * and conn_id_ctx. They could be of different types in the future for non-IP + * connections. * * The default implementation does nothing. * * @param conn_id The conn_id record to populate. + * @param ctx The conn_id's ctx record to populate. */ - void PopulateConnIdVal(RecordVal& conn_id) { DoPopulateConnIdVal(conn_id); }; + void PopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) { DoPopulateConnIdVal(conn_id, ctx); }; /** * Return a non-owning session::detail::Key instance for connection lookups. @@ -72,9 +78,20 @@ protected: /** * Hook method for ConnKey::PopulateConnIdVal. * + * When Zeek renders a connection key into a script-layer record, it calls this + * method to populate the conn_id's and conn_id_ctx's fields that are unique to + * this ConnKey. + * + * Currently, \a conn_id and \a ctx will always have the script-layer types conn_id + * and conn_id_ctx. They could be of different types in the future for non-IP + * connections. + * * The default implementation does nothing. + * + * @param conn_id The conn_id record to populate. + * @param ctx The conn_id's ctx record to populate. */ - virtual void DoPopulateConnIdVal(RecordVal& conn_id) {} + virtual void DoPopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) {} /** * Hook method for implementing ConnKey::SessionKey. diff --git a/src/packet_analysis/protocol/ip/conn_key/vlan_fivetuple/Factory.cc b/src/packet_analysis/protocol/ip/conn_key/vlan_fivetuple/Factory.cc index a9d5c32880..ce375bb30f 100644 --- a/src/packet_analysis/protocol/ip/conn_key/vlan_fivetuple/Factory.cc +++ b/src/packet_analysis/protocol/ip/conn_key/vlan_fivetuple/Factory.cc @@ -37,7 +37,7 @@ protected: return {reinterpret_cast(&key), sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE}; } - void DoPopulateConnIdVal(RecordVal& conn_id) override { + void DoPopulateConnIdVal(RecordVal& conn_id, RecordVal& ctx) override { if ( conn_id.NumFields() <= 5 ) return; diff --git a/testing/btest/Baseline/plugins.connkey/conn.log.cut b/testing/btest/Baseline/plugins.connkey/conn.log.cut index 93f6eb17ff..789c871e44 100644 --- a/testing/btest/Baseline/plugins.connkey/conn.log.cut +++ b/testing/btest/Baseline/plugins.connkey/conn.log.cut @@ -1,7 +1,7 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -ts uid id.orig_h id.orig_p id.resp_h id.resp_p id.inits proto service orig_pkts resp_pkts -XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 141.142.220.235 37604 199.233.217.249 56666 1 tcp ftp-data 4 4 -XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 141.142.220.235 59378 199.233.217.249 56667 22 tcp ftp-data 4 4 -XXXXXXXXXX.XXXXXX CtPZjS20MLrsMUOJi2 199.233.217.249 61920 141.142.220.235 33582 40 tcp ftp-data 5 3 -XXXXXXXXXX.XXXXXX CUM0KZ3MLUfNB0cl11 199.233.217.249 61918 141.142.220.235 37835 60 tcp ftp-data 5 3 -XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 0 tcp ftp 38 25 +ts uid id.orig_h id.orig_p id.resp_h id.resp_p id.ctx.inits id.inits proto service orig_pkts resp_pkts +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 141.142.220.235 37604 199.233.217.249 56666 1 1 tcp ftp-data 4 4 +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 141.142.220.235 59378 199.233.217.249 56667 22 22 tcp ftp-data 4 4 +XXXXXXXXXX.XXXXXX CtPZjS20MLrsMUOJi2 199.233.217.249 61920 141.142.220.235 33582 40 40 tcp ftp-data 5 3 +XXXXXXXXXX.XXXXXX CUM0KZ3MLUfNB0cl11 199.233.217.249 61918 141.142.220.235 37835 60 60 tcp ftp-data 5 3 +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 0 0 tcp ftp 38 25 diff --git a/testing/btest/Baseline/plugins.connkey/output b/testing/btest/Baseline/plugins.connkey/output index db292842a0..de1216c622 100644 --- a/testing/btest/Baseline/plugins.connkey/output +++ b/testing/btest/Baseline/plugins.connkey/output @@ -5,9 +5,9 @@ Demo::Foo - A Foo ConnKey factory (dynamic, version 1.0.0) === DoNewConnKey (0 key all_inits) DoNewConnKey (1 key all_inits) -DoConnKeyFromVal for [orig_h=141.142.220.235, orig_p=50003/tcp, resp_h=199.233.217.249, resp_p=21/tcp, proto=6, ctx=[], inits=0] +DoConnKeyFromVal for [orig_h=141.142.220.235, orig_p=50003/tcp, resp_h=199.233.217.249, resp_p=21/tcp, proto=6, ctx=[inits=0], inits=0] DoNewConnKey (2 key all_inits) -DoConnKeyFromVal for [orig_h=141.142.220.235, orig_p=50003/tcp, resp_h=199.233.217.249, resp_p=21/tcp, proto=6, ctx=[], inits=0] +DoConnKeyFromVal for [orig_h=141.142.220.235, orig_p=50003/tcp, resp_h=199.233.217.249, resp_p=21/tcp, proto=6, ctx=[inits=0], inits=0] DoNewConnKey (6 key all_inits) DoNewConnKey (22 key all_inits) DoNewConnKey (40 key all_inits) diff --git a/testing/btest/plugins/connkey-plugin/src/Foo.cc b/testing/btest/plugins/connkey-plugin/src/Foo.cc index 4ab9cfdaa6..58227cfd8f 100644 --- a/testing/btest/plugins/connkey-plugin/src/Foo.cc +++ b/testing/btest/plugins/connkey-plugin/src/Foo.cc @@ -23,9 +23,14 @@ public: void DoInit(const zeek::Packet& pkt) override { ++all_inits; } - void DoPopulateConnIdVal(zeek::RecordVal& rv) override { - static int offset = rv.GetType()->FieldOffset("inits"); - rv.Assign(offset, zeek::make_intrusive(inits)); + void DoPopulateConnIdVal(zeek::RecordVal& conn_id, zeek::RecordVal& ctx) override { + static int offset = conn_id.GetType()->FieldOffset("inits"); + static int offset_ctx = ctx.GetType()->FieldOffset("inits"); + + IPConnKey::DoPopulateConnIdVal(conn_id, ctx); + + conn_id.Assign(offset, zeek::make_intrusive(inits)); + ctx.Assign(offset_ctx, zeek::make_intrusive(std::to_string(inits))); } private: diff --git a/testing/btest/plugins/connkey.zeek b/testing/btest/plugins/connkey.zeek index eb643f8e88..0cabf432c8 100644 --- a/testing/btest/plugins/connkey.zeek +++ b/testing/btest/plugins/connkey.zeek @@ -4,13 +4,16 @@ # @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -NN Demo::Foo >>output # @TEST-EXEC: echo === >>output # @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -r $TRACES/ftp/ipv4.trace %INPUT >>output -# @TEST-EXEC: zeek-cut -m ts uid id.orig_h id.orig_p id.resp_h id.resp_p id.inits proto service orig_pkts resp_pkts < conn.log > conn.log.cut +# @TEST-EXEC: zeek-cut -m ts uid id.orig_h id.orig_p id.resp_h id.resp_p id.ctx.inits id.inits proto service orig_pkts resp_pkts < conn.log > conn.log.cut # @TEST-EXEC: btest-diff conn.log.cut # @TEST-EXEC: btest-diff output - redef ConnKey::factory = ConnKey::CONNKEY_FOO; redef record conn_id += { inits: int &log &default=-1; # Number of inits happened until the key was created. Not part of the hash, just metadata. }; + +redef record conn_id_ctx += { + inits: string &log &optional; +};