Add basic event for emitting DNS dynamic update data

This also changes the existing DU btest from checking to ensure a weird was
emitted to checking the output from the event.
This commit is contained in:
Tim Wojtulewicz 2025-09-09 15:14:10 -07:00
parent fa6eb6c928
commit d344f015e0
7 changed files with 42 additions and 21 deletions

View file

@ -2861,7 +2861,7 @@ global pkt_profile_file: file &redef;
## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
## dns_message dns_query_reply dns_rejected dns_request
## dns_message dns_query_reply dns_rejected dns_request dns_dynamic_update
type dns_msg: record {
id: count; ##< Transaction ID.
@ -2877,9 +2877,9 @@ type dns_msg: record {
AD: bool; ##< authentic data
CD: bool; ##< checking disabled
num_queries: count; ##< Number of query records.
num_answers: count; ##< Number of answer records.
num_auth: count; ##< Number of authoritative records.
num_queries: count; ##< Number of query records. For dynamic update messages, this is the number of zones.
num_answers: count; ##< Number of answer records. For dynamic update messages, this is the number of prerequisites.
num_auth: count; ##< Number of authoritative records. For dynamic update messages, this is the number of updates.
num_addl: count; ##< Number of additional records.
is_netbios: bool; ##< Whether this message came from NetBIOS.

View file

@ -136,6 +136,9 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) {
return;
}
StringValPtr zname = msg.query_name;
uint32_t zclass = msg.aclass;
if ( ! ParseAnswers(&msg, msg.an_pr_count, detail::DNS_PREREQUISITES, data, len, msg_start) ) {
EndMessage(&msg);
return;
@ -145,6 +148,12 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) {
EndMessage(&msg);
return;
}
// Send an event if the first three parts parsed correctly, since they're the
// actual update bits.
if ( dns_dynamic_update )
analyzer->EnqueueConnEvent(dns_dynamic_update, analyzer->ConnVal(), msg.BuildHdrVal(), zname,
val_mgr->Count(zclass));
}
else {
if ( ! ParseQuestions(&msg, data, len, msg_start) ) {

View file

@ -337,7 +337,7 @@ public:
StringValPtr query_name;
RR_Type atype = TYPE_ALL;
int aclass = 0; ///< normally = 1, inet
uint16_t aclass = 0; ///< normally = 1, inet
uint32_t ttl = 0;
DNS_AnswerType answer_type = DNS_QUESTION;

View file

@ -836,3 +836,16 @@ event dns_HTTPS%(c: connection, msg: dns_msg, ans: dns_answer, https: dns_svcb_r
## dns_rejected dns_request dns_max_queries dns_session_timeout
## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_end%(c: connection, msg: dns_msg%);
## Generated for DNS Dynamic Update messages. See `RFC for Dynamic Updates in the Domain Name System (DNS UPDATE) <https://datatracker.ietf.org/doc/html/rfc2136`__
## for more information about Dynamic Updates.
##
## c: The connection, which may be UDP or TCP depending on the type of the
## transport-layer session being analyzed.
##
## msg: The parsed DNS message header.
##
## zname: The name from the Zone section of the message.
##
## zclass: The class from the Zone section of the message.
event dns_dynamic_update%(c: connection, msg: dns_msg, zname: string, zclass: count%);

View file

@ -0,0 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
[id=47952, opcode=5, rcode=0, QR=F, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=1, is_netbios=F], stratolab.org, 1, C_INTERNET
[id=47952, opcode=5, rcode=5, QR=T, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=1, is_netbios=F], stratolab.org, 1, C_INTERNET
[id=61191, opcode=5, rcode=0, QR=F, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=0, is_netbios=F], stratolab.org, 1, C_INTERNET
[id=61191, opcode=5, rcode=0, QR=T, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=0, is_netbios=F], stratolab.org, 1, C_INTERNET

View file

@ -1,12 +0,0 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path weird
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
#types time string addr port addr port string string bool string string
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.106 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.105 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS
#close XXXX-XX-XX-XX-XX-XX

View file

@ -1,6 +1,12 @@
# @TEST-DOC: Tests that a DNS dynamic update packet doesn't error but reports an unknown opcode weird
# @TEST-EXEC: zeek -b -C -r $TRACES/dns/dynamic-update.pcap %INPUT
# @TEST-EXEC: btest-diff weird.log
# @TEST-DOC: Tests that a DNS dynamic update packet is processed.
# @TEST-EXEC: zeek -b -C -r $TRACES/dns/dynamic-update.pcap %INPUT >out 2>&1
# @TEST-EXEC: btest-diff out
# @TEST-EXEC: ! test -f weird.log
@load base/frameworks/notice/weird
@load base/protocols/dns
event dns_dynamic_update(c: connection, msg: dns_msg, zname: string, zclass: count)
{
print msg, zname, zclass, DNS::classes[zclass];
}