Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/rust/src/dns/dns.rs
Line
Count
Source
1
/* Copyright (C) 2017-2022 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
use std;
19
use std::collections::HashMap;
20
use std::collections::VecDeque;
21
use std::ffi::CString;
22
use std::os::raw::c_void;
23
24
use crate::applayer::*;
25
use crate::core::{self, *};
26
use crate::direction::Direction;
27
use crate::direction::DIR_BOTH;
28
use crate::dns::parser;
29
use crate::flow::Flow;
30
use crate::frames::Frame;
31
32
use nom7::number::streaming::be_u16;
33
use nom7::{Err, IResult};
34
use suricata_sys::sys::{
35
    AppLayerParserState, AppProto, DetectEngineThreadCtx, SCAppLayerParserConfParserEnabled,
36
    SCAppLayerProtoDetectConfProtoDetectionEnabled,
37
};
38
39
/// DNS record types.
40
/// DNS error codes.
41
#[derive(Clone, Debug, EnumStringU16)]
42
pub enum DNSRecordType {
43
    A = 1,
44
    NS = 2,
45
    MD = 3, // Obsolete
46
    MF = 4, // Obsolete
47
    CNAME = 5,
48
    SOA = 6,
49
    MB = 7,    // Experimental
50
    MG = 8,    // Experimental
51
    MR = 9,    // Experimental
52
    NULL = 10, // Experimental
53
    WKS = 11,
54
    PTR = 12,
55
    HINFO = 13,
56
    MINFO = 14,
57
    MX = 15,
58
    TXT = 16,
59
    RP = 17,
60
    AFSDB = 18,
61
    X25 = 19,
62
    ISDN = 20,
63
    RT = 21,
64
    NSAP = 22,
65
    NSAPPTR = 23,
66
    SIG = 24,
67
    KEY = 25,
68
    PX = 26,
69
    GPOS = 27,
70
    AAAA = 28,
71
    LOC = 29,
72
    NXT = 30, // Obsolete
73
    SRV = 33,
74
    ATMA = 34,
75
    NAPTR = 35,
76
    KX = 36,
77
    CERT = 37,
78
    A6 = 38, // Obsolete
79
    DNAME = 39,
80
    OPT = 41,
81
    APL = 42,
82
    DS = 43,
83
    SSHFP = 44,
84
    IPSECKEY = 45,
85
    RRSIG = 46,
86
    NSEC = 47,
87
    DNSKEY = 48,
88
    DHCID = 49,
89
    NSEC3 = 50,
90
    NSEC3PARAM = 51,
91
    TLSA = 52,
92
    HIP = 55,
93
    CDS = 59,
94
    CDNSKEY = 60,
95
    HTTPS = 65,
96
    SPF = 99, // Obsolete
97
    TKEY = 249,
98
    TSIG = 250,
99
    MAILA = 254, // Obsolete
100
    ANY = 255,
101
    URI = 256,
102
}
103
104
/// DNS error codes.
105
#[derive(Clone, Debug, EnumStringU16)]
106
pub enum DNSRcode {
107
    NOERROR = 0,
108
    FORMERR = 1,
109
    SERVFAIL = 2,
110
    NXDOMAIN = 3,
111
    NOTIMP = 4,
112
    REFUSED = 5,
113
    YXDOMAIN = 6,
114
    YXRRSET = 7,
115
    NXRRSET = 8,
116
    NOTAUTH = 9,
117
    NOTZONE = 10,
118
    // Support for OPT RR from RFC6891 will be needed to
119
    // parse RCODE values over 15
120
    BADVERS = 16,
121
    //also pub const DNS_RCODE_BADSIG: u16 = 16;
122
    BADKEY = 17,
123
    BADTIME = 18,
124
    BADMODE = 19,
125
    BADNAME = 20,
126
    BADALG = 21,
127
    BADTRUNC = 22,
128
}
129
130
pub(super) static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
131
132
#[derive(AppLayerFrameType)]
133
pub(crate) enum DnsFrameType {
134
    /// DNS PDU frame. For UDP DNS this is the complete UDP payload, for TCP
135
    /// this is the DNS payload not including the leading length field allowing
136
    /// this frame to be used for UDP and TCP DNS.
137
    Pdu,
138
}
139
140
#[derive(Debug, PartialEq, Eq, AppLayerEvent)]
141
pub enum DNSEvent {
142
    MalformedData,
143
    NotRequest,
144
    NotResponse,
145
    ZFlagSet,
146
    InvalidOpcode,
147
    /// A DNS resource name was exessively long and was truncated.
148
    NameTooLong,
149
    /// An infinite loop was found while parsing a name.
150
    InfiniteLoop,
151
    /// Too many labels were found.
152
    TooManyLabels,
153
    InvalidAdditionals,
154
    InvalidAuthorities,
155
}
156
157
#[derive(Debug, PartialEq, Eq)]
158
#[repr(C)]
159
pub struct DNSHeader {
160
    pub tx_id: u16,
161
    pub flags: u16,
162
    pub questions: u16,
163
    pub answer_rr: u16,
164
    pub authority_rr: u16,
165
    pub additional_rr: u16,
166
}
167
168
#[derive(Debug)]
169
pub struct DNSQueryEntry {
170
    pub name: DNSName,
171
    pub rrtype: u16,
172
    pub rrclass: u16,
173
}
174
175
#[derive(Debug, PartialEq, Eq)]
176
pub struct DNSRDataOPT {
177
    /// Option Code
178
    pub code: u16,
179
    /// Option Data
180
    pub data: Vec<u8>,
181
}
182
183
#[derive(Debug, PartialEq, Eq)]
184
pub struct DNSRDataSOA {
185
    /// Primary name server for this zone
186
    pub mname: DNSName,
187
    /// Authority's mailbox
188
    pub rname: DNSName,
189
    /// Serial version number
190
    pub serial: u32,
191
    /// Refresh interval (seconds)
192
    pub refresh: u32,
193
    /// Retry interval (seconds)
194
    pub retry: u32,
195
    /// Upper time limit until zone is no longer authoritative (seconds)
196
    pub expire: u32,
197
    /// Minimum ttl for records in this zone (seconds)
198
    pub minimum: u32,
199
}
200
201
#[derive(Debug, PartialEq, Eq)]
202
pub struct DNSRDataSSHFP {
203
    /// Algorithm number
204
    pub algo: u8,
205
    /// Fingerprint type
206
    pub fp_type: u8,
207
    /// Fingerprint
208
    pub fingerprint: Vec<u8>,
209
}
210
211
#[derive(Debug, PartialEq, Eq)]
212
pub struct DNSRDataSRV {
213
    /// Priority
214
    pub priority: u16,
215
    /// Weight
216
    pub weight: u16,
217
    /// Port
218
    pub port: u16,
219
    /// Target
220
    pub target: DNSName,
221
}
222
223
bitflags! {
224
    #[derive(Default)]
225
    pub struct DNSNameFlags: u8 {
226
        const INFINITE_LOOP = 0b0000_0001;
227
        const TRUNCATED     = 0b0000_0010;
228
        const LABEL_LIMIT   = 0b0000_0100;
229
    }
230
}
231
232
#[derive(Debug, Clone, PartialEq, Eq)]
233
pub struct DNSName {
234
    pub value: Vec<u8>,
235
    pub flags: DNSNameFlags,
236
}
237
238
/// Represents RData of various formats
239
#[derive(Debug, PartialEq, Eq)]
240
pub enum DNSRData {
241
    // RData is an address
242
    A(Vec<u8>),
243
    AAAA(Vec<u8>),
244
    // RData is a domain name
245
    CNAME(DNSName),
246
    PTR(DNSName),
247
    MX(DNSName),
248
    NS(DNSName),
249
    // TXT records are an array of TXT entries
250
    TXT(Vec<Vec<u8>>),
251
    NULL(Vec<u8>),
252
    // RData has several fields
253
    SOA(DNSRDataSOA),
254
    SRV(DNSRDataSRV),
255
    SSHFP(DNSRDataSSHFP),
256
    OPT(Vec<DNSRDataOPT>),
257
    // RData for remaining types is sometimes ignored
258
    Unknown(Vec<u8>),
259
}
260
261
#[derive(Debug, PartialEq, Eq)]
262
pub struct DNSAnswerEntry {
263
    pub name: DNSName,
264
    pub rrtype: u16,
265
    pub rrclass: u16,
266
    pub ttl: u32,
267
    pub data: DNSRData,
268
}
269
270
#[derive(Debug)]
271
pub struct DNSMessage {
272
    pub header: DNSHeader,
273
    pub queries: Vec<DNSQueryEntry>,
274
    pub answers: Vec<DNSAnswerEntry>,
275
    pub authorities: Vec<DNSAnswerEntry>,
276
    pub invalid_authorities: bool,
277
    pub additionals: Vec<DNSAnswerEntry>,
278
    pub invalid_additionals: bool,
279
}
280
281
#[derive(Debug, Default)]
282
pub struct DNSTransaction {
283
    pub id: u64,
284
    pub request: Option<DNSMessage>,
285
    pub response: Option<DNSMessage>,
286
    pub tx_data: AppLayerTxData,
287
}
288
289
impl Transaction for DNSTransaction {
290
960k
    fn id(&self) -> u64 {
291
960k
        self.id
292
960k
    }
293
}
294
295
impl DNSTransaction {
296
924k
    pub(crate) fn new(direction: Direction) -> Self {
297
924k
        Self {
298
924k
            tx_data: AppLayerTxData::for_direction(direction),
299
924k
            ..Default::default()
300
924k
        }
301
924k
    }
302
303
    /// Get the DNS transactions ID (not the internal tracking ID).
304
772
    pub fn tx_id(&self) -> u16 {
305
772
        if let Some(request) = &self.request {
306
334
            return request.header.tx_id;
307
438
        }
308
438
        if let Some(response) = &self.response {
309
438
            return response.header.tx_id;
310
0
        }
311
312
        // Shouldn't happen.
313
0
        return 0;
314
772
    }
315
316
    /// Get the reply code of the transaction. Note that this will
317
    /// also return 0 if there is no reply.
318
0
    pub fn rcode(&self) -> u16 {
319
0
        if let Some(response) = &self.response {
320
0
            return response.header.flags & 0x000f;
321
0
        }
322
0
        return 0;
323
0
    }
324
325
    /// Set an event. The event is set on the most recent transaction.
326
2.98M
    pub fn set_event(&mut self, event: DNSEvent) {
327
2.98M
        self.tx_data.set_event(event as u8);
328
2.98M
    }
329
}
330
331
struct ConfigTracker {
332
    map: HashMap<u16, AppLayerTxConfig>,
333
    queue: VecDeque<u16>,
334
}
335
336
impl ConfigTracker {
337
0
    fn new() -> ConfigTracker {
338
0
        ConfigTracker {
339
0
            map: HashMap::new(),
340
0
            queue: VecDeque::new(),
341
0
        }
342
0
    }
343
344
0
    fn add(&mut self, id: u16, config: AppLayerTxConfig) {
345
        // If at size limit, remove the oldest entry.
346
0
        if self.queue.len() > 499 {
347
0
            if let Some(id) = self.queue.pop_front() {
348
0
                self.map.remove(&id);
349
0
            }
350
0
        }
351
352
0
        self.map.insert(id, config);
353
0
        self.queue.push_back(id);
354
0
    }
355
356
0
    fn remove(&mut self, id: &u16) -> Option<AppLayerTxConfig> {
357
0
        self.map.remove(id)
358
0
    }
359
}
360
361
pub(crate) enum DnsVariant {
362
    Dns,
363
    MulticastDns,
364
}
365
366
impl DnsVariant {
367
645k
    pub fn is_dns(&self) -> bool {
368
645k
        matches!(self, DnsVariant::Dns)
369
645k
    }
370
371
563k
    pub fn is_mdns(&self) -> bool {
372
563k
        matches!(self, DnsVariant::MulticastDns)
373
563k
    }
374
}
375
376
//#[derive(Default)]
377
pub struct DNSState {
378
    variant: DnsVariant,
379
    state_data: AppLayerStateData,
380
381
    // Internal transaction ID.
382
    tx_id: u64,
383
384
    // Transactions.
385
    transactions: VecDeque<DNSTransaction>,
386
387
    config: Option<ConfigTracker>,
388
389
    gap: bool,
390
}
391
392
impl State<DNSTransaction> for DNSState {
393
749k
    fn get_transaction_count(&self) -> usize {
394
749k
        self.transactions.len()
395
749k
    }
396
397
480k
    fn get_transaction_by_index(&self, index: usize) -> Option<&DNSTransaction> {
398
480k
        self.transactions.get(index)
399
480k
    }
400
}
401
402
1.16M
fn dns_validate_header(input: &[u8]) -> Option<(&[u8], DNSHeader)> {
403
1.16M
    if let Ok((body, header)) = parser::dns_parse_header(input) {
404
1.12M
        if probe_header_validity(&header, input.len()).0 {
405
1.04M
            return Some((body, header));
406
78.8k
        }
407
48.3k
    }
408
127k
    None
409
1.16M
}
410
411
#[derive(Debug, PartialEq, Eq)]
412
pub(crate) enum DNSParseError {
413
    HeaderValidation,
414
    NotRequest,
415
    Incomplete,
416
    OtherError,
417
}
418
419
775k
pub(crate) fn dns_parse_request(
420
775k
    input: &[u8], variant: &DnsVariant,
421
775k
) -> Result<DNSTransaction, DNSParseError> {
422
775k
    let (body, header) = if let Some((body, header)) = dns_validate_header(input) {
423
675k
        (body, header)
424
    } else {
425
100k
        return Err(DNSParseError::HeaderValidation);
426
    };
427
428
675k
    match parser::dns_parse_body(body, input, header) {
429
645k
        Ok((_, (request, parse_flags))) => {
430
645k
            if variant.is_dns() && request.header.flags & 0x8000 != 0 {
431
                SCLogDebug!("DNS message is not a request");
432
82.5k
                return Err(DNSParseError::NotRequest);
433
563k
            }
434
435
563k
            let z_flag = request.header.flags & 0x0040 != 0;
436
563k
            let opcode = ((request.header.flags >> 11) & 0xf) as u8;
437
438
563k
            let mut tx = DNSTransaction::new(Direction::ToServer);
439
563k
            if request.invalid_additionals {
440
464k
                tx.set_event(DNSEvent::InvalidAdditionals);
441
464k
            }
442
563k
            if request.invalid_authorities {
443
87.0k
                tx.set_event(DNSEvent::InvalidAuthorities);
444
476k
            }
445
446
563k
            if variant.is_mdns() && request.header.flags & 0x8000 != 0 {
447
179k
                tx.response = Some(request);
448
384k
            } else {
449
384k
                tx.request = Some(request);
450
384k
            }
451
452
563k
            if z_flag {
453
550k
                SCLogDebug!("Z-flag set on DNS request");
454
550k
                tx.set_event(DNSEvent::ZFlagSet);
455
550k
            }
456
457
563k
            if opcode >= 7 {
458
546k
                tx.set_event(DNSEvent::InvalidOpcode);
459
546k
            }
460
461
563k
            if parse_flags.contains(DNSNameFlags::TRUNCATED) {
462
1.32k
                tx.set_event(DNSEvent::NameTooLong);
463
561k
            }
464
465
563k
            if parse_flags.contains(DNSNameFlags::INFINITE_LOOP) {
466
694
                tx.set_event(DNSEvent::InfiniteLoop);
467
562k
            }
468
469
563k
            if parse_flags.contains(DNSNameFlags::LABEL_LIMIT) {
470
1.21k
                tx.set_event(DNSEvent::TooManyLabels);
471
561k
            }
472
473
563k
            return Ok(tx);
474
        }
475
        Err(Err::Incomplete(_)) => {
476
            // Insufficient data.
477
            SCLogDebug!("Insufficient data while parsing DNS request");
478
20.7k
            return Err(DNSParseError::Incomplete);
479
        }
480
        Err(_) => {
481
            // Error, probably malformed data.
482
            SCLogDebug!("An error occurred while parsing DNS request");
483
8.57k
            return Err(DNSParseError::OtherError);
484
        }
485
    }
486
775k
}
487
488
394k
pub(crate) fn dns_parse_response(input: &[u8]) -> Result<DNSTransaction, DNSParseError> {
489
394k
    let (body, header) = if let Some((body, header)) = dns_validate_header(input) {
490
367k
        (body, header)
491
    } else {
492
26.6k
        return Err(DNSParseError::HeaderValidation);
493
    };
494
495
367k
    match parser::dns_parse_body(body, input, header) {
496
361k
        Ok((_, (response, parse_flags))) => {
497
            SCLogDebug!("Response header flags: {}", response.header.flags);
498
361k
            let z_flag = response.header.flags & 0x0040 != 0;
499
361k
            let opcode = ((response.header.flags >> 11) & 0xf) as u8;
500
361k
            let flags = response.header.flags;
501
502
361k
            let mut tx = DNSTransaction::new(Direction::ToClient);
503
361k
            if response.invalid_additionals {
504
272k
                tx.set_event(DNSEvent::InvalidAdditionals);
505
272k
            }
506
361k
            if response.invalid_authorities {
507
77.6k
                tx.set_event(DNSEvent::InvalidAuthorities);
508
283k
            }
509
361k
            tx.response = Some(response);
510
511
361k
            if flags & 0x8000 == 0 {
512
277k
                SCLogDebug!("DNS message is not a response");
513
277k
                tx.set_event(DNSEvent::NotResponse);
514
277k
            }
515
516
361k
            if z_flag {
517
353k
                SCLogDebug!("Z-flag set on DNS response");
518
353k
                tx.set_event(DNSEvent::ZFlagSet);
519
353k
            }
520
521
361k
            if opcode >= 7 {
522
354k
                tx.set_event(DNSEvent::InvalidOpcode);
523
354k
            }
524
525
361k
            if parse_flags.contains(DNSNameFlags::TRUNCATED) {
526
632
                tx.set_event(DNSEvent::NameTooLong);
527
361k
            }
528
529
361k
            if parse_flags.contains(DNSNameFlags::INFINITE_LOOP) {
530
436
                tx.set_event(DNSEvent::InfiniteLoop);
531
361k
            }
532
533
361k
            if parse_flags.contains(DNSNameFlags::LABEL_LIMIT) {
534
600
                tx.set_event(DNSEvent::TooManyLabels);
535
361k
            }
536
537
361k
            return Ok(tx);
538
        }
539
        Err(Err::Incomplete(_)) => {
540
            // Insufficient data.
541
            SCLogDebug!("Insufficient data while parsing DNS request");
542
3.88k
            return Err(DNSParseError::Incomplete);
543
        }
544
        Err(_) => {
545
            // Error, probably malformed data.
546
            SCLogDebug!("An error occurred while parsing DNS request");
547
2.09k
            return Err(DNSParseError::OtherError);
548
        }
549
    }
550
394k
}
551
552
impl DNSState {
553
4.02k
    fn new() -> Self {
554
4.02k
        Self {
555
4.02k
            variant: DnsVariant::Dns,
556
4.02k
            state_data: AppLayerStateData::default(),
557
4.02k
            tx_id: 0,
558
4.02k
            transactions: VecDeque::default(),
559
4.02k
            config: None,
560
4.02k
            gap: false,
561
4.02k
        }
562
4.02k
    }
563
564
2.81k
    pub(crate) fn new_variant(variant: DnsVariant) -> Self {
565
2.81k
        Self {
566
2.81k
            variant,
567
2.81k
            state_data: AppLayerStateData::default(),
568
2.81k
            tx_id: 0,
569
2.81k
            transactions: VecDeque::default(),
570
2.81k
            config: None,
571
2.81k
            gap: false,
572
2.81k
        }
573
2.81k
    }
574
575
478k
    fn free_tx(&mut self, tx_id: u64) {
576
478k
        let len = self.transactions.len();
577
478k
        let mut found = false;
578
478k
        let mut index = 0;
579
478k
        for i in 0..len {
580
478k
            let tx = &self.transactions[i];
581
478k
            if tx.id == tx_id + 1 {
582
478k
                found = true;
583
478k
                index = i;
584
478k
                break;
585
0
            }
586
        }
587
478k
        if found {
588
478k
            self.transactions.remove(index);
589
478k
        }
590
478k
    }
591
592
0
    fn get_tx(&mut self, tx_id: u64) -> Option<&DNSTransaction> {
593
0
        return self.transactions.iter().find(|&tx| tx.id == tx_id + 1);
594
0
    }
595
596
    /// Set an event. The event is set on the most recent transaction.
597
117k
    fn set_event(&mut self, event: DNSEvent) {
598
117k
        let len = self.transactions.len();
599
117k
        if len == 0 {
600
117k
            return;
601
84
        }
602
603
84
        let tx = &mut self.transactions[len - 1];
604
84
        tx.tx_data.set_event(event as u8);
605
117k
    }
606
607
775k
    fn parse_request(
608
775k
        &mut self, input: &[u8], is_tcp: bool, frame: Option<Frame>, flow: *const Flow,
609
775k
    ) -> bool {
610
775k
        match dns_parse_request(input, &self.variant) {
611
563k
            Ok(mut tx) => {
612
563k
                self.tx_id += 1;
613
563k
                tx.id = self.tx_id;
614
563k
                if let Some(frame) = frame {
615
27
                    frame.set_tx(flow, tx.id);
616
563k
                }
617
563k
                self.transactions.push_back(tx);
618
563k
                return true;
619
            }
620
212k
            Err(e) => match e {
621
                DNSParseError::HeaderValidation => {
622
100k
                    return !is_tcp;
623
                }
624
                DNSParseError::NotRequest => {
625
82.5k
                    self.set_event(DNSEvent::NotRequest);
626
82.5k
                    return false;
627
                }
628
                DNSParseError::Incomplete => {
629
20.7k
                    self.set_event(DNSEvent::MalformedData);
630
20.7k
                    return false;
631
                }
632
                DNSParseError::OtherError => {
633
8.57k
                    self.set_event(DNSEvent::MalformedData);
634
8.57k
                    return false;
635
                }
636
            },
637
        }
638
775k
    }
639
640
407k
    pub(crate) fn parse_request_udp(
641
407k
        &mut self, flow: *const Flow, stream_slice: StreamSlice,
642
407k
    ) -> bool {
643
407k
        let input = stream_slice.as_slice();
644
407k
        let frame = Frame::new(
645
407k
            flow,
646
407k
            &stream_slice,
647
407k
            input,
648
407k
            input.len() as i64,
649
407k
            DnsFrameType::Pdu as u8,
650
407k
            None,
651
        );
652
407k
        self.parse_request(input, false, frame, flow)
653
407k
    }
654
655
120k
    fn parse_response_udp(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> bool {
656
120k
        let input = stream_slice.as_slice();
657
120k
        let frame = Frame::new(
658
120k
            flow,
659
120k
            &stream_slice,
660
120k
            input,
661
120k
            input.len() as i64,
662
120k
            DnsFrameType::Pdu as u8,
663
120k
            None,
664
        );
665
120k
        self.parse_response(input, false, frame, flow)
666
120k
    }
667
668
394k
    fn parse_response(
669
394k
        &mut self, input: &[u8], is_tcp: bool, frame: Option<Frame>, flow: *const Flow,
670
394k
    ) -> bool {
671
394k
        match dns_parse_response(input) {
672
361k
            Ok(mut tx) => {
673
361k
                self.tx_id += 1;
674
361k
                tx.id = self.tx_id;
675
361k
                if let Some(ref mut config) = &mut self.config {
676
0
                    if let Some(response) = &tx.response {
677
0
                        if let Some(config) = config.remove(&response.header.tx_id) {
678
0
                            tx.tx_data.config = config;
679
0
                        }
680
0
                    }
681
361k
                }
682
361k
                if let Some(frame) = frame {
683
15
                    frame.set_tx(flow, tx.id);
684
361k
                }
685
361k
                self.transactions.push_back(tx);
686
361k
                return true;
687
            }
688
32.6k
            Err(e) => match e {
689
                DNSParseError::HeaderValidation => {
690
26.6k
                    return !is_tcp;
691
                }
692
                _ => {
693
5.97k
                    self.set_event(DNSEvent::MalformedData);
694
5.97k
                    return false;
695
                }
696
            },
697
        }
698
394k
    }
699
700
    /// TCP variation of response request parser to handle the length
701
    /// prefix.
702
    ///
703
    /// Returns the number of messages parsed.
704
11.3k
    fn parse_request_tcp(
705
11.3k
        &mut self, flow: *mut Flow, stream_slice: StreamSlice,
706
11.3k
    ) -> AppLayerResult {
707
11.3k
        let input = stream_slice.as_slice();
708
11.3k
        if self.gap {
709
1.44k
            let (is_dns, _, is_incomplete) = probe_tcp(input);
710
1.44k
            if is_dns || is_incomplete {
711
22
                self.gap = false;
712
22
            } else {
713
1.42k
                return AppLayerResult::ok();
714
            }
715
9.94k
        }
716
717
9.96k
        let mut cur_i = input;
718
9.96k
        let mut consumed = 0;
719
2.86M
        while !cur_i.is_empty() {
720
2.86M
            if cur_i.len() == 1 {
721
1.70k
                return AppLayerResult::incomplete(consumed as u32, 2_u32);
722
2.86M
            }
723
2.86M
            let size = match be_u16(cur_i) as IResult<&[u8], u16> {
724
2.86M
                Ok((_, len)) => len,
725
0
                _ => 0,
726
            } as usize;
727
            SCLogDebug!(
728
                "[request] Have {} bytes, need {} to parse",
729
                cur_i.len(),
730
                size + 2
731
            );
732
2.86M
            if size > 0 && cur_i.len() >= size + 2 {
733
368k
                let msg = &cur_i[2..(size + 2)];
734
368k
                sc_app_layer_parser_trigger_raw_stream_inspection(flow, Direction::ToServer as i32);
735
368k
                let frame = Frame::new(
736
368k
                    flow,
737
368k
                    &stream_slice,
738
368k
                    msg,
739
368k
                    msg.len() as i64,
740
368k
                    DnsFrameType::Pdu as u8,
741
368k
                    None,
742
                );
743
368k
                if self.parse_request(msg, true, frame, flow) {
744
368k
                    cur_i = &cur_i[(size + 2)..];
745
368k
                    consumed += size + 2;
746
368k
                } else {
747
199
                    return AppLayerResult::err();
748
                }
749
2.49M
            } else if size == 0 {
750
2.48M
                cur_i = &cur_i[2..];
751
2.48M
                consumed += 2;
752
2.48M
            } else {
753
                SCLogDebug!(
754
                    "[request]Not enough DNS traffic to parse. Returning {}/{}",
755
                    consumed as u32,
756
                    (size + 2) as u32
757
                );
758
7.09k
                return AppLayerResult::incomplete(consumed as u32, (size + 2) as u32);
759
            }
760
        }
761
969
        AppLayerResult::ok()
762
11.3k
    }
763
764
    /// TCP variation of the response parser to handle the length
765
    /// prefix.
766
    ///
767
    /// Returns the number of messages parsed.
768
12.6k
    fn parse_response_tcp(
769
12.6k
        &mut self, flow: *mut Flow, stream_slice: StreamSlice,
770
12.6k
    ) -> AppLayerResult {
771
12.6k
        let input = stream_slice.as_slice();
772
12.6k
        if self.gap {
773
2.86k
            let (is_dns, _, is_incomplete) = probe_tcp(input);
774
2.86k
            if is_dns || is_incomplete {
775
5
                self.gap = false;
776
5
            } else {
777
2.85k
                return AppLayerResult::ok();
778
            }
779
9.77k
        }
780
781
9.77k
        let mut cur_i = input;
782
9.77k
        let mut consumed = 0;
783
2.47M
        while !cur_i.is_empty() {
784
2.46M
            if cur_i.len() == 1 {
785
1.71k
                return AppLayerResult::incomplete(consumed as u32, 2_u32);
786
2.46M
            }
787
2.46M
            let size = match be_u16(cur_i) as IResult<&[u8], u16> {
788
2.46M
                Ok((_, len)) => len,
789
0
                _ => 0,
790
            } as usize;
791
            SCLogDebug!(
792
                "[response] Have {} bytes, need {} to parse",
793
                cur_i.len(),
794
                size + 2
795
            );
796
2.46M
            if size > 0 && cur_i.len() >= size + 2 {
797
273k
                let msg = &cur_i[2..(size + 2)];
798
273k
                sc_app_layer_parser_trigger_raw_stream_inspection(flow, Direction::ToClient as i32);
799
273k
                let frame = Frame::new(
800
273k
                    flow,
801
273k
                    &stream_slice,
802
273k
                    msg,
803
273k
                    msg.len() as i64,
804
273k
                    DnsFrameType::Pdu as u8,
805
273k
                    None,
806
                );
807
273k
                if self.parse_response(msg, true, frame, flow) {
808
273k
                    cur_i = &cur_i[(size + 2)..];
809
273k
                    consumed += size + 2;
810
273k
                } else {
811
229
                    return AppLayerResult::err();
812
                }
813
2.19M
            } else if size == 0 {
814
2.18M
                cur_i = &cur_i[2..];
815
2.18M
                consumed += 2;
816
2.18M
            } else {
817
                SCLogDebug!(
818
                    "[response]Not enough DNS traffic to parse. Returning {}/{}",
819
                    consumed as u32,
820
                    (cur_i.len() - consumed) as u32
821
                );
822
6.97k
                return AppLayerResult::incomplete(consumed as u32, (size + 2) as u32);
823
            }
824
        }
825
859
        AppLayerResult::ok()
826
12.6k
    }
827
828
    /// A gap has been seen in the request direction. Set the gap flag.
829
23
    fn request_gap(&mut self, gap: u32) {
830
23
        if gap > 0 {
831
23
            self.gap = true;
832
23
        }
833
23
    }
834
835
    /// A gap has been seen in the response direction. Set the gap
836
    /// flag.
837
79
    fn response_gap(&mut self, gap: u32) {
838
79
        if gap > 0 {
839
79
            self.gap = true;
840
79
        }
841
79
    }
842
}
843
844
const DNS_HEADER_SIZE: usize = 12;
845
846
1.12M
pub(crate) fn probe_header_validity(header: &DNSHeader, rlen: usize) -> (bool, bool, bool) {
847
1.12M
    let nb_records = header.additional_rr as usize
848
1.12M
        + header.answer_rr as usize
849
1.12M
        + header.authority_rr as usize
850
1.12M
        + header.questions as usize;
851
852
1.12M
    let min_msg_size = 2 * nb_records;
853
1.12M
    if min_msg_size > rlen {
854
        // Not enough data for records defined in the header, or
855
        // impossibly large.
856
72.9k
        return (false, false, false);
857
1.05M
    }
858
859
1.05M
    if nb_records == 0 && rlen > DNS_HEADER_SIZE {
860
        // zero fields, data size should be just DNS_HEADER_SIZE
861
        // happens when DNS server returns format error
862
7.95k
        return (false, false, false);
863
1.04M
    }
864
865
1.04M
    let is_request = header.flags & 0x8000 == 0;
866
1.04M
    if is_request && header.questions == 0 {
867
3.38k
        return (false, false, false);
868
1.04M
    }
869
1.04M
    return (true, is_request, false);
870
1.12M
}
871
872
/// Probe input to see if it looks like DNS.
873
///
874
/// Returns a tuple of booleans: (is_dns, is_request, incomplete)
875
9.78k
fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
876
    // Trim input to dlen if larger.
877
9.78k
    let input = if input.len() <= dlen {
878
8.78k
        input
879
    } else {
880
992
        &input[..dlen]
881
    };
882
883
    // If input is less than dlen then we know we don't have enough data to
884
    // parse a complete message, so perform header validation only.
885
9.78k
    if input.len() < dlen {
886
7.09k
        if let Ok((_, header)) = parser::dns_parse_header(input) {
887
5.13k
            return probe_header_validity(&header, dlen);
888
        } else {
889
1.95k
            return (false, false, false);
890
        }
891
2.68k
    }
892
893
2.68k
    match parser::dns_parse_header(input) {
894
2.39k
        Ok((body, header)) => match parser::dns_parse_body(body, input, header) {
895
1.31k
            Ok((_, (request, _flags))) => probe_header_validity(&request.header, dlen),
896
633
            Err(Err::Incomplete(_)) => (false, false, true),
897
448
            Err(_) => (false, false, false),
898
        },
899
287
        Err(_) => (false, false, false),
900
    }
901
9.78k
}
902
903
/// Probe TCP input to see if it looks like DNS.
904
8.10k
fn probe_tcp(input: &[u8]) -> (bool, bool, bool) {
905
8.10k
    match be_u16(input) as IResult<&[u8], u16> {
906
8.08k
        Ok((rem, dlen)) => {
907
8.08k
            return probe(rem, dlen as usize);
908
        }
909
        Err(Err::Incomplete(_)) => {
910
16
            return (false, false, true);
911
        }
912
0
        _ => {}
913
    }
914
0
    return (false, false, false);
915
8.10k
}
916
917
/// Returns *mut DNSState
918
4.02k
pub(crate) extern "C" fn state_new(
919
4.02k
    _orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
920
4.02k
) -> *mut std::os::raw::c_void {
921
4.02k
    let state = DNSState::new();
922
4.02k
    let boxed = Box::new(state);
923
4.02k
    return Box::into_raw(boxed) as *mut _;
924
4.02k
}
925
926
/// Params:
927
/// - state: *mut DNSState as void pointer
928
6.84k
pub(crate) extern "C" fn state_free(state: *mut std::os::raw::c_void) {
929
    // Just unbox...
930
6.84k
    std::mem::drop(unsafe { Box::from_raw(state as *mut DNSState) });
931
6.84k
}
932
933
478k
pub(crate) unsafe extern "C" fn state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
934
478k
    let state = cast_pointer!(state, DNSState);
935
478k
    state.free_tx(tx_id);
936
478k
}
937
938
/// C binding parse a DNS request. Returns 1 on success, -1 on failure.
939
407k
pub(crate) unsafe extern "C" fn parse_request(
940
407k
    flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
941
407k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
942
407k
) -> AppLayerResult {
943
407k
    let state = cast_pointer!(state, DNSState);
944
407k
    state.parse_request_udp(flow, stream_slice);
945
407k
    AppLayerResult::ok()
946
407k
}
947
948
120k
unsafe extern "C" fn parse_response(
949
120k
    flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
950
120k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
951
120k
) -> AppLayerResult {
952
120k
    let state = cast_pointer!(state, DNSState);
953
120k
    state.parse_response_udp(flow, stream_slice);
954
120k
    AppLayerResult::ok()
955
120k
}
956
957
/// C binding parse a DNS request. Returns 1 on success, -1 on failure.
958
11.4k
unsafe extern "C" fn parse_request_tcp(
959
11.4k
    flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
960
11.4k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
961
11.4k
) -> AppLayerResult {
962
11.4k
    let state = cast_pointer!(state, DNSState);
963
11.4k
    if stream_slice.is_gap() {
964
23
        state.request_gap(stream_slice.gap_size());
965
11.3k
    } else if !stream_slice.is_empty() {
966
11.3k
        return state.parse_request_tcp(flow, stream_slice);
967
0
    }
968
23
    AppLayerResult::ok()
969
11.4k
}
970
971
12.7k
unsafe extern "C" fn parse_response_tcp(
972
12.7k
    flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
973
12.7k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
974
12.7k
) -> AppLayerResult {
975
12.7k
    let state = cast_pointer!(state, DNSState);
976
12.7k
    if stream_slice.is_gap() {
977
79
        state.response_gap(stream_slice.gap_size());
978
12.6k
    } else if !stream_slice.is_empty() {
979
12.6k
        return state.parse_response_tcp(flow, stream_slice);
980
0
    }
981
79
    AppLayerResult::ok()
982
12.7k
}
983
984
959k
pub(crate) extern "C" fn tx_get_alstate_progress(
985
959k
    _tx: *mut std::os::raw::c_void, _direction: u8,
986
959k
) -> std::os::raw::c_int {
987
    // This is a stateless parser, just the existence of a transaction
988
    // means its complete.
989
    SCLogDebug!("tx_get_alstate_progress");
990
959k
    return 1;
991
959k
}
992
993
1.66M
pub(crate) unsafe extern "C" fn state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
994
1.66M
    let state = cast_pointer!(state, DNSState);
995
    SCLogDebug!("state_get_tx_count: returning {}", state.tx_id);
996
1.66M
    return state.tx_id;
997
1.66M
}
998
999
0
pub(crate) unsafe extern "C" fn state_get_tx(
1000
0
    state: *mut std::os::raw::c_void, tx_id: u64,
1001
0
) -> *mut std::os::raw::c_void {
1002
0
    let state = cast_pointer!(state, DNSState);
1003
0
    match state.get_tx(tx_id) {
1004
0
        Some(tx) => {
1005
0
            return tx as *const _ as *mut _;
1006
        }
1007
        None => {
1008
0
            return std::ptr::null_mut();
1009
        }
1010
    }
1011
0
}
1012
1013
#[no_mangle]
1014
1.11k
pub extern "C" fn SCDnsTxIsRequest(tx: &mut DNSTransaction) -> bool {
1015
1.11k
    tx.request.is_some()
1016
1.11k
}
1017
1018
#[no_mangle]
1019
468
pub extern "C" fn SCDnsTxIsResponse(tx: &mut DNSTransaction) -> bool {
1020
468
    tx.response.is_some()
1021
468
}
1022
1023
480k
pub(crate) unsafe extern "C" fn state_get_tx_data(
1024
480k
    tx: *mut std::os::raw::c_void,
1025
480k
) -> *mut AppLayerTxData {
1026
480k
    let tx = cast_pointer!(tx, DNSTransaction);
1027
480k
    return &mut tx.tx_data;
1028
480k
}
1029
1030
877
pub(crate) unsafe extern "C" fn dns_get_state_data(
1031
877
    state: *mut std::os::raw::c_void,
1032
877
) -> *mut AppLayerStateData {
1033
877
    let state = cast_pointer!(state, DNSState);
1034
877
    return &mut state.state_data;
1035
877
}
1036
1037
/// Get the DNS query name at index i.
1038
#[no_mangle]
1039
0
pub unsafe extern "C" fn SCDnsTxGetQueryName(
1040
0
    _de: *mut DetectEngineThreadCtx, tx: *const c_void, flow_flags: u8, i: u32,
1041
0
    buf: *mut *const u8, len: *mut u32,
1042
0
) -> bool {
1043
0
    let tx = cast_pointer!(tx, DNSTransaction);
1044
0
    let queries = if (flow_flags & STREAM_TOSERVER) == 0 {
1045
0
        tx.response.as_ref().map(|response| &response.queries)
1046
    } else {
1047
0
        tx.request.as_ref().map(|request| &request.queries)
1048
    };
1049
0
    let index = i as usize;
1050
1051
0
    if let Some(queries) = queries {
1052
0
        if let Some(query) = queries.get(index) {
1053
0
            if !query.name.value.is_empty() {
1054
0
                *buf = query.name.value.as_ptr();
1055
0
                *len = query.name.value.len() as u32;
1056
0
                return true;
1057
0
            }
1058
0
        }
1059
0
    }
1060
1061
0
    false
1062
0
}
1063
1064
/// Get the DNS response answer name and index i.
1065
#[no_mangle]
1066
pub unsafe extern "C" fn SCDnsTxGetAnswerName(
1067
    _de: *mut DetectEngineThreadCtx, tx: *const c_void, flow_flags: u8, i: u32,
1068
    buf: *mut *const u8, len: *mut u32,
1069
) -> bool {
1070
    let tx = cast_pointer!(tx, DNSTransaction);
1071
    let answers = if (flow_flags & STREAM_TOSERVER) == 0 {
1072
        tx.response.as_ref().map(|response| &response.answers)
1073
    } else {
1074
        tx.request.as_ref().map(|request| &request.answers)
1075
    };
1076
    let index = i as usize;
1077
1078
    if let Some(answers) = answers {
1079
        if let Some(answer) = answers.get(index) {
1080
            if !answer.name.value.is_empty() {
1081
                *buf = answer.name.value.as_ptr();
1082
                *len = answer.name.value.len() as u32;
1083
                return true;
1084
            }
1085
        }
1086
    }
1087
1088
    false
1089
}
1090
1091
/// Get the DNS response authority name at index i.
1092
#[no_mangle]
1093
0
pub unsafe extern "C" fn SCDnsTxGetAuthorityName(
1094
0
    _de: *mut DetectEngineThreadCtx, tx: *const c_void, _flow_flags: u8, i: u32,
1095
0
    buf: *mut *const u8, len: *mut u32,
1096
0
) -> bool {
1097
0
    let tx = cast_pointer!(tx, DNSTransaction);
1098
0
    let index = i as usize;
1099
1100
0
    if let Some(response) = &tx.response {
1101
0
        if let Some(record) = response.authorities.get(index) {
1102
0
            if !record.name.value.is_empty() {
1103
0
                *buf = record.name.value.as_ptr();
1104
0
                *len = record.name.value.len() as u32;
1105
0
                return true;
1106
0
            }
1107
0
        }
1108
0
    }
1109
1110
0
    false
1111
0
}
1112
1113
/// Get the DNS response additional name at index i.
1114
#[no_mangle]
1115
0
pub unsafe extern "C" fn SCDnsTxGetAdditionalName(
1116
0
    _de: *mut DetectEngineThreadCtx, tx: *const c_void, _flow_flags: u8, i: u32,
1117
0
    buf: *mut *const u8, len: *mut u32,
1118
0
) -> bool {
1119
0
    let tx = cast_pointer!(tx, DNSTransaction);
1120
0
    let index = i as usize;
1121
1122
0
    if let Some(response) = &tx.response {
1123
0
        if let Some(record) = response.additionals.get(index) {
1124
0
            if !record.name.value.is_empty() {
1125
0
                *buf = record.name.value.as_ptr();
1126
0
                *len = record.name.value.len() as u32;
1127
0
                return true;
1128
0
            }
1129
0
        }
1130
0
    }
1131
1132
0
    false
1133
0
}
1134
1135
0
fn get_rdata_name(data: &DNSRData) -> Option<&DNSName> {
1136
0
    match data {
1137
0
        DNSRData::CNAME(name) | DNSRData::PTR(name) | DNSRData::MX(name) | DNSRData::NS(name) => {
1138
0
            Some(name)
1139
        }
1140
0
        DNSRData::SOA(soa) => Some(&soa.mname),
1141
0
        _ => None,
1142
    }
1143
0
}
1144
1145
/// Get the DNS response answer rdata at index i that could be a domain name.
1146
#[no_mangle]
1147
pub unsafe extern "C" fn SCDnsTxGetAnswerRdata(
1148
    tx: &mut DNSTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
1149
) -> bool {
1150
    let index = i as usize;
1151
1152
    if let Some(response) = &tx.response {
1153
        if let Some(record) = response.answers.get(index) {
1154
            if let Some(name) = get_rdata_name(&record.data) {
1155
                if !name.value.is_empty() {
1156
                    *buf = name.value.as_ptr();
1157
                    *len = name.value.len() as u32;
1158
                    return true;
1159
                }
1160
            }
1161
        }
1162
    }
1163
1164
    false
1165
}
1166
1167
/// Get the DNS response authority rdata at index i that could be a domain name.
1168
#[no_mangle]
1169
0
pub unsafe extern "C" fn SCDnsTxGetAuthorityRdata(
1170
0
    tx: &mut DNSTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
1171
0
) -> bool {
1172
0
    let index = i as usize;
1173
1174
0
    if let Some(response) = &tx.response {
1175
0
        if let Some(record) = response.authorities.get(index) {
1176
0
            if let Some(name) = get_rdata_name(&record.data) {
1177
0
                if !name.value.is_empty() {
1178
0
                    *buf = name.value.as_ptr();
1179
0
                    *len = name.value.len() as u32;
1180
0
                    return true;
1181
0
                }
1182
0
            }
1183
0
        }
1184
0
    }
1185
1186
0
    false
1187
0
}
1188
1189
/// Get the DNS response additional rdata at index i that could be a domain name.
1190
#[no_mangle]
1191
0
pub unsafe extern "C" fn SCDnsTxGetAdditionalRdata(
1192
0
    tx: &mut DNSTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
1193
0
) -> bool {
1194
0
    let index = i as usize;
1195
1196
0
    if let Some(response) = &tx.response {
1197
0
        if let Some(record) = response.additionals.get(index) {
1198
0
            if let Some(name) = get_rdata_name(&record.data) {
1199
0
                if !name.value.is_empty() {
1200
0
                    *buf = name.value.as_ptr();
1201
0
                    *len = name.value.len() as u32;
1202
0
                    return true;
1203
0
                }
1204
0
            }
1205
0
        }
1206
0
    }
1207
1208
0
    false
1209
0
}
1210
1211
/// Get the DNS response flags for a transaction.
1212
#[no_mangle]
1213
0
pub extern "C" fn SCDnsTxGetResponseFlags(tx: &mut DNSTransaction) -> u16 {
1214
0
    return tx.rcode();
1215
0
}
1216
1217
1.74k
pub(crate) unsafe extern "C" fn probe_udp(
1218
1.74k
    _flow: *const Flow, _dir: u8, input: *const u8, len: u32, rdir: *mut u8,
1219
1.74k
) -> AppProto {
1220
1.74k
    if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 {
1221
54
        return core::ALPROTO_UNKNOWN;
1222
1.69k
    }
1223
1.69k
    let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);
1224
1.69k
    let (is_dns, is_request, _) = probe(slice, slice.len());
1225
1.69k
    if is_dns {
1226
487
        let dir = if is_request {
1227
301
            Direction::ToServer
1228
        } else {
1229
186
            Direction::ToClient
1230
        };
1231
487
        *rdir = dir as u8;
1232
487
        return ALPROTO_DNS;
1233
1.20k
    }
1234
1.20k
    return 0;
1235
1.74k
}
1236
1237
31.3k
unsafe extern "C" fn c_probe_tcp(
1238
31.3k
    _flow: *const Flow, direction: u8, input: *const u8, len: u32, rdir: *mut u8,
1239
31.3k
) -> AppProto {
1240
31.3k
    if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
1241
27.5k
        return core::ALPROTO_UNKNOWN;
1242
3.79k
    }
1243
3.79k
    let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);
1244
    //is_incomplete is checked by caller
1245
3.79k
    let (is_dns, is_request, _) = probe_tcp(slice);
1246
3.79k
    if is_dns {
1247
537
        let dir = if is_request {
1248
410
            Direction::ToServer
1249
        } else {
1250
127
            Direction::ToClient
1251
        };
1252
537
        if (direction & DIR_BOTH) != u8::from(dir) {
1253
367
            *rdir = dir as u8;
1254
367
        }
1255
537
        return ALPROTO_DNS;
1256
3.26k
    }
1257
3.26k
    return 0;
1258
31.3k
}
1259
1260
0
unsafe extern "C" fn apply_tx_config(
1261
0
    _state: *mut std::os::raw::c_void, _tx: *mut std::os::raw::c_void, _mode: std::os::raw::c_int,
1262
0
    config: AppLayerTxConfig,
1263
0
) {
1264
0
    let tx = cast_pointer!(_tx, DNSTransaction);
1265
0
    let state = cast_pointer!(_state, DNSState);
1266
0
    if let Some(request) = &tx.request {
1267
0
        if state.config.is_none() {
1268
0
            state.config = Some(ConfigTracker::new());
1269
0
        }
1270
0
        if let Some(ref mut tracker) = &mut state.config {
1271
0
            tracker.add(request.header.tx_id, config);
1272
0
        }
1273
0
    }
1274
0
}
1275
1276
#[no_mangle]
1277
40
pub unsafe extern "C" fn SCRegisterDnsUdpParser() {
1278
40
    let default_port = std::ffi::CString::new("[53]").unwrap();
1279
40
    let parser = RustParser {
1280
40
        name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1281
40
        default_port: default_port.as_ptr(),
1282
40
        ipproto: IPPROTO_UDP,
1283
40
        probe_ts: Some(probe_udp),
1284
40
        probe_tc: Some(probe_udp),
1285
40
        min_depth: 0,
1286
40
        max_depth: std::mem::size_of::<DNSHeader>() as u16,
1287
40
        state_new,
1288
40
        state_free,
1289
40
        tx_free: state_tx_free,
1290
40
        parse_ts: parse_request,
1291
40
        parse_tc: parse_response,
1292
40
        get_tx_count: state_get_tx_count,
1293
40
        get_tx: state_get_tx,
1294
40
        tx_comp_st_ts: 1,
1295
40
        tx_comp_st_tc: 1,
1296
40
        tx_get_progress: tx_get_alstate_progress,
1297
40
        get_eventinfo: Some(DNSEvent::get_event_info),
1298
40
        get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id),
1299
40
        localstorage_new: None,
1300
40
        localstorage_free: None,
1301
40
        get_tx_files: None,
1302
40
        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
1303
40
        get_tx_data: state_get_tx_data,
1304
40
        get_state_data: dns_get_state_data,
1305
40
        apply_tx_config: Some(apply_tx_config),
1306
40
        flags: 0,
1307
40
        get_frame_id_by_name: Some(DnsFrameType::ffi_id_from_name),
1308
40
        get_frame_name_by_id: Some(DnsFrameType::ffi_name_from_id),
1309
40
        get_state_id_by_name: None,
1310
40
        get_state_name_by_id: None,
1311
40
    };
1312
1313
40
    let ip_proto_str = CString::new("udp").unwrap();
1314
40
    if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1315
40
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1316
40
        ALPROTO_DNS = alproto;
1317
40
        if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1318
40
            let _ = AppLayerRegisterParser(&parser, alproto);
1319
40
        }
1320
0
    }
1321
40
}
1322
1323
#[no_mangle]
1324
40
pub unsafe extern "C" fn SCRegisterDnsTcpParser() {
1325
40
    let default_port = std::ffi::CString::new("53").unwrap();
1326
40
    let parser = RustParser {
1327
40
        name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1328
40
        default_port: default_port.as_ptr(),
1329
40
        ipproto: IPPROTO_TCP,
1330
40
        probe_ts: Some(c_probe_tcp),
1331
40
        probe_tc: Some(c_probe_tcp),
1332
40
        min_depth: 0,
1333
40
        max_depth: std::mem::size_of::<DNSHeader>() as u16 + 2,
1334
40
        state_new,
1335
40
        state_free,
1336
40
        tx_free: state_tx_free,
1337
40
        parse_ts: parse_request_tcp,
1338
40
        parse_tc: parse_response_tcp,
1339
40
        get_tx_count: state_get_tx_count,
1340
40
        get_tx: state_get_tx,
1341
40
        tx_comp_st_ts: 1,
1342
40
        tx_comp_st_tc: 1,
1343
40
        tx_get_progress: tx_get_alstate_progress,
1344
40
        get_eventinfo: Some(DNSEvent::get_event_info),
1345
40
        get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id),
1346
40
        localstorage_new: None,
1347
40
        localstorage_free: None,
1348
40
        get_tx_files: None,
1349
40
        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
1350
40
        get_tx_data: state_get_tx_data,
1351
40
        get_state_data: dns_get_state_data,
1352
40
        apply_tx_config: Some(apply_tx_config),
1353
40
        flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
1354
40
        get_frame_id_by_name: Some(DnsFrameType::ffi_id_from_name),
1355
40
        get_frame_name_by_id: Some(DnsFrameType::ffi_name_from_id),
1356
40
        get_state_id_by_name: None,
1357
40
        get_state_name_by_id: None,
1358
40
    };
1359
1360
40
    let ip_proto_str = CString::new("tcp").unwrap();
1361
40
    if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1362
40
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1363
40
        ALPROTO_DNS = alproto;
1364
40
        if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1365
40
            let _ = AppLayerRegisterParser(&parser, alproto);
1366
40
        }
1367
0
    }
1368
40
}
1369
1370
#[cfg(test)]
1371
mod tests {
1372
1373
    use super::*;
1374
1375
    #[test]
1376
    fn test_dns_parse_request_tcp_valid() {
1377
        // A UDP DNS request with the DNS payload starting at byte 42.
1378
        // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1379
        #[rustfmt::skip]
1380
        let buf: &[u8] = &[
1381
            0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1382
            0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1383
            0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1384
            0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1385
            0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1386
            0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1387
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1388
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1389
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1390
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1391
            0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1392
            0x00, 0x00, 0x00                                /* ... */
1393
        ];
1394
1395
        // The DNS payload starts at offset 42.
1396
        let dns_payload = &buf[42..];
1397
1398
        // Make a TCP DNS request payload.
1399
        let mut request = Vec::new();
1400
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1401
        request.push(((dns_payload.len() as u16) & 0xff) as u8);
1402
        request.extend(dns_payload);
1403
1404
        let mut state = DNSState::new();
1405
        assert_eq!(
1406
            AppLayerResult::ok(),
1407
            state.parse_request_tcp(
1408
                std::ptr::null_mut(),
1409
                StreamSlice::from_slice(&request, STREAM_TOSERVER, 0)
1410
            )
1411
        );
1412
    }
1413
1414
    #[test]
1415
    fn test_dns_parse_request_tcp_short_payload() {
1416
        // A UDP DNS request with the DNS payload starting at byte 42.
1417
        // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1418
        #[rustfmt::skip]
1419
        let buf: &[u8] = &[
1420
            0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1421
            0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1422
            0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1423
            0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1424
            0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1425
            0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1426
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1427
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1428
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1429
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1430
            0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1431
            0x00, 0x00, 0x00                                /* ... */
1432
        ];
1433
1434
        // The DNS payload starts at offset 42.
1435
        let dns_payload = &buf[42..];
1436
1437
        // Make a TCP DNS request payload but with the length 1 larger
1438
        // than the available data.
1439
        let mut request = Vec::new();
1440
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1441
        request.push(((dns_payload.len() as u16) & 0xff) as u8 + 1);
1442
        request.extend(dns_payload);
1443
1444
        let mut state = DNSState::new();
1445
        assert_eq!(
1446
            AppLayerResult::incomplete(0, 52),
1447
            state.parse_request_tcp(
1448
                std::ptr::null_mut(),
1449
                StreamSlice::from_slice(&request, STREAM_TOSERVER, 0)
1450
            )
1451
        );
1452
    }
1453
1454
    #[test]
1455
    fn test_dns_parse_response_tcp_valid() {
1456
        // A UDP DNS response with the DNS payload starting at byte 42.
1457
        // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1458
        #[rustfmt::skip]
1459
        let buf: &[u8] = &[
1460
            0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1461
            0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1462
            0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1463
            0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1464
            0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1465
            0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1466
            0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1467
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1468
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1469
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1470
            0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1471
            0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1472
            0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1473
            0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1474
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1475
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1476
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1477
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19              /* ....N. */
1478
        ];
1479
1480
        // The DNS payload starts at offset 42.
1481
        let dns_payload = &buf[42..];
1482
1483
        // Make a TCP DNS response payload.
1484
        let mut request = Vec::new();
1485
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1486
        request.push(((dns_payload.len() as u16) & 0xff) as u8);
1487
        request.extend(dns_payload);
1488
1489
        let mut state = DNSState::new();
1490
        assert_eq!(
1491
            AppLayerResult::ok(),
1492
            state.parse_response_tcp(
1493
                std::ptr::null_mut(),
1494
                StreamSlice::from_slice(&request, STREAM_TOCLIENT, 0)
1495
            )
1496
        );
1497
    }
1498
1499
    // Test that a TCP DNS payload won't be parsed if there is not
1500
    // enough data.
1501
    #[test]
1502
    fn test_dns_parse_response_tcp_short_payload() {
1503
        // A UDP DNS response with the DNS payload starting at byte 42.
1504
        // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1505
        #[rustfmt::skip]
1506
        let buf: &[u8] = &[
1507
            0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1508
            0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1509
            0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1510
            0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1511
            0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1512
            0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1513
            0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1514
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1515
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1516
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1517
            0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1518
            0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1519
            0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1520
            0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1521
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1522
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1523
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1524
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19              /* ....N. */
1525
        ];
1526
1527
        // The DNS payload starts at offset 42.
1528
        let dns_payload = &buf[42..];
1529
1530
        // Make a TCP DNS response payload, but make the length 1 byte
1531
        // larger than the actual size.
1532
        let mut request = Vec::new();
1533
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1534
        request.push((((dns_payload.len() as u16) & 0xff) + 1) as u8);
1535
        request.extend(dns_payload);
1536
1537
        let mut state = DNSState::new();
1538
        assert_eq!(
1539
            AppLayerResult::incomplete(0, 103),
1540
            state.parse_response_tcp(
1541
                std::ptr::null_mut(),
1542
                StreamSlice::from_slice(&request, STREAM_TOCLIENT, 0)
1543
            )
1544
        );
1545
    }
1546
1547
    // Port of the C RustDNSUDPParserTest02 unit test.
1548
    #[test]
1549
    fn test_dns_udp_parser_test_01() {
1550
        /* query: abcdefghijk.com
1551
         * TTL: 86400
1552
         * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
1553
         * ns, hostmaster */
1554
        #[rustfmt::skip]
1555
        let buf: &[u8] = &[
1556
            0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
1557
            0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
1558
            0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1559
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
1560
            0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
1561
            0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
1562
            0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
1563
            0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
1564
            0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
1565
            0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
1566
            0x80,
1567
        ];
1568
        let mut state = DNSState::new();
1569
        assert!(state.parse_response(buf, false, None, std::ptr::null()));
1570
    }
1571
1572
    // Port of the C RustDNSUDPParserTest02 unit test.
1573
    #[test]
1574
    fn test_dns_udp_parser_test_02() {
1575
        #[rustfmt::skip]
1576
        let buf: &[u8] = &[
1577
            0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
1578
            0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
1579
            0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
1580
            0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
1581
            0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
1582
            0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
1583
            0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
1584
            0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
1585
            0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
1586
            0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1587
        ];
1588
        let mut state = DNSState::new();
1589
        assert!(state.parse_response(buf, false, None, std::ptr::null()));
1590
    }
1591
1592
    // Port of the C RustDNSUDPParserTest03 unit test.
1593
    #[test]
1594
    fn test_dns_udp_parser_test_03() {
1595
        #[rustfmt::skip]
1596
        let buf: &[u8] = &[
1597
            0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
1598
            0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
1599
            0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
1600
            0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
1601
            0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
1602
            0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
1603
            0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
1604
            0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
1605
            0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
1606
            0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1607
        ];
1608
        let mut state = DNSState::new();
1609
        assert!(state.parse_response(buf, false, None, std::ptr::null()));
1610
    }
1611
1612
    // Port of the C RustDNSUDPParserTest04 unit test.
1613
    //
1614
    // Test the TXT records in an answer.
1615
    #[test]
1616
    fn test_dns_udp_parser_test_04() {
1617
        #[rustfmt::skip]
1618
        let buf: &[u8] = &[
1619
            0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1620
            0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1621
            0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1622
            0x01,
1623
            /* answer record start */
1624
            0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1625
            /* txt record starts: */
1626
            0x20, /* <txt len 32 */  0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1627
            0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1628
            0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */   0xc0,0x1d,0x00,0x02,0x00,0x01,
1629
            0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1630
            0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1631
        ];
1632
        let mut state = DNSState::new();
1633
        assert!(state.parse_response(buf, false, None, std::ptr::null()));
1634
    }
1635
1636
    // Port of the C RustDNSUDPParserTest05 unit test.
1637
    //
1638
    // Test TXT records in answer with a bad length.
1639
    #[test]
1640
    fn test_dns_udp_parser_test_05() {
1641
        #[rustfmt::skip]
1642
        let buf: &[u8] = &[
1643
            0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1644
            0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1645
            0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1646
            0x01,
1647
            /* answer record start */
1648
            0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1649
            /* txt record starts: */
1650
            0x40, /* <txt len 64 */  0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1651
            0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1652
            0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */   0xc0,0x1d,0x00,0x02,0x00,0x01,
1653
            0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1654
            0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1655
        ];
1656
        let mut state = DNSState::new();
1657
        assert!(!state.parse_response(buf, false, None, std::ptr::null()));
1658
    }
1659
1660
    // Port of the C RustDNSTCPParserTestMultiRecord unit test.
1661
    #[test]
1662
    fn test_dns_tcp_parser_multi_record() {
1663
        #[rustfmt::skip]
1664
        let buf: &[u8] = &[
1665
            0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
1666
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
1667
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1668
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1669
            0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
1670
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
1671
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1672
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1673
            0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
1674
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
1675
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1676
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1677
            0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
1678
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
1679
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1680
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1681
            0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
1682
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
1683
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1684
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1685
            0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
1686
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
1687
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1688
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1689
            0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
1690
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
1691
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1692
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1693
            0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
1694
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
1695
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1696
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1697
            0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
1698
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
1699
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1700
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1701
            0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
1702
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
1703
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1704
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1705
            0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
1706
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1707
            0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1708
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1709
            0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
1710
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1711
            0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1712
            0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1713
            0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
1714
            0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1715
            0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
1716
            0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
1717
            0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
1718
            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1719
            0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
1720
            0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
1721
            0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
1722
            0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1723
            0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
1724
            0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
1725
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
1726
            0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1727
            0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
1728
            0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1729
            0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
1730
            0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
1731
            0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
1732
            0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
1733
            0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
1734
            0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
1735
            0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
1736
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1737
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1738
            0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
1739
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1740
            0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1741
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1742
            0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
1743
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1744
            0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1745
            0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1746
            0x00, 0x01
1747
        ];
1748
1749
        // A NULL flow.
1750
        let flow = std::ptr::null_mut();
1751
1752
        let mut state = DNSState::new();
1753
        assert_eq!(
1754
            AppLayerResult::ok(),
1755
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf, STREAM_TOSERVER, 0))
1756
        );
1757
    }
1758
1759
    #[test]
1760
    fn test_dns_tcp_parser_split_payload() {
1761
        // A NULL flow.
1762
        let flow = std::ptr::null_mut();
1763
1764
        /* incomplete payload */
1765
        #[rustfmt::skip]
1766
        let buf1: &[u8] = &[
1767
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1768
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1769
        ];
1770
        /* complete payload plus the start of a new payload */
1771
        #[rustfmt::skip]
1772
        let buf2: &[u8] = &[
1773
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1774
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1775
            0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1776
            0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1777
1778
            // next.
1779
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1780
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1781
        ];
1782
1783
        /* and the complete payload again with no trailing data. */
1784
        #[rustfmt::skip]
1785
        let buf3: &[u8] = &[
1786
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1787
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1788
            0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1789
            0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1790
        ];
1791
1792
        let mut state = DNSState::new();
1793
        assert_eq!(
1794
            AppLayerResult::incomplete(0, 30),
1795
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf1, STREAM_TOSERVER, 0))
1796
        );
1797
        assert_eq!(
1798
            AppLayerResult::incomplete(30, 30),
1799
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf2, STREAM_TOSERVER, 0))
1800
        );
1801
        assert_eq!(
1802
            AppLayerResult::ok(),
1803
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf3, STREAM_TOSERVER, 0))
1804
        );
1805
    }
1806
1807
    #[test]
1808
    fn test_dns_event_from_id() {
1809
        assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData));
1810
        assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet));
1811
        assert_eq!(DNSEvent::from_id(99), None);
1812
    }
1813
1814
    #[test]
1815
    fn test_dns_event_to_cstring() {
1816
        assert_eq!(DNSEvent::MalformedData.to_cstring(), "malformed_data\0");
1817
    }
1818
1819
    #[test]
1820
    fn test_dns_event_from_string() {
1821
        let name = "malformed_data";
1822
        let event = DNSEvent::from_string(name).unwrap();
1823
        assert_eq!(event, DNSEvent::MalformedData);
1824
        assert_eq!(event.to_cstring(), format!("{}\0", name));
1825
    }
1826
}