Coverage Report

Created: 2026-02-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/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
23
use crate::applayer::*;
24
use crate::core::{self, *};
25
use crate::dns::parser;
26
use crate::frames::Frame;
27
28
use nom7::number::streaming::be_u16;
29
use nom7::{Err, IResult};
30
31
/// DNS record types.
32
pub const DNS_RECORD_TYPE_A: u16 = 1;
33
pub const DNS_RECORD_TYPE_NS: u16 = 2;
34
pub const DNS_RECORD_TYPE_MD: u16 = 3; // Obsolete
35
pub const DNS_RECORD_TYPE_MF: u16 = 4; // Obsolete
36
pub const DNS_RECORD_TYPE_CNAME: u16 = 5;
37
pub const DNS_RECORD_TYPE_SOA: u16 = 6;
38
pub const DNS_RECORD_TYPE_MB: u16 = 7; // Experimental
39
pub const DNS_RECORD_TYPE_MG: u16 = 8; // Experimental
40
pub const DNS_RECORD_TYPE_MR: u16 = 9; // Experimental
41
pub const DNS_RECORD_TYPE_NULL: u16 = 10; // Experimental
42
pub const DNS_RECORD_TYPE_WKS: u16 = 11;
43
pub const DNS_RECORD_TYPE_PTR: u16 = 12;
44
pub const DNS_RECORD_TYPE_HINFO: u16 = 13;
45
pub const DNS_RECORD_TYPE_MINFO: u16 = 14;
46
pub const DNS_RECORD_TYPE_MX: u16 = 15;
47
pub const DNS_RECORD_TYPE_TXT: u16 = 16;
48
pub const DNS_RECORD_TYPE_RP: u16 = 17;
49
pub const DNS_RECORD_TYPE_AFSDB: u16 = 18;
50
pub const DNS_RECORD_TYPE_X25: u16 = 19;
51
pub const DNS_RECORD_TYPE_ISDN: u16 = 20;
52
pub const DNS_RECORD_TYPE_RT: u16 = 21;
53
pub const DNS_RECORD_TYPE_NSAP: u16 = 22;
54
pub const DNS_RECORD_TYPE_NSAPPTR: u16 = 23;
55
pub const DNS_RECORD_TYPE_SIG: u16 = 24;
56
pub const DNS_RECORD_TYPE_KEY: u16 = 25;
57
pub const DNS_RECORD_TYPE_PX: u16 = 26;
58
pub const DNS_RECORD_TYPE_GPOS: u16 = 27;
59
pub const DNS_RECORD_TYPE_AAAA: u16 = 28;
60
pub const DNS_RECORD_TYPE_LOC: u16 = 29;
61
pub const DNS_RECORD_TYPE_NXT: u16 = 30; // Obsolete
62
pub const DNS_RECORD_TYPE_SRV: u16 = 33;
63
pub const DNS_RECORD_TYPE_ATMA: u16 = 34;
64
pub const DNS_RECORD_TYPE_NAPTR: u16 = 35;
65
pub const DNS_RECORD_TYPE_KX: u16 = 36;
66
pub const DNS_RECORD_TYPE_CERT: u16 = 37;
67
pub const DNS_RECORD_TYPE_A6: u16 = 38; // Obsolete
68
pub const DNS_RECORD_TYPE_DNAME: u16 = 39;
69
pub const DNS_RECORD_TYPE_OPT: u16 = 41;
70
pub const DNS_RECORD_TYPE_APL: u16 = 42;
71
pub const DNS_RECORD_TYPE_DS: u16 = 43;
72
pub const DNS_RECORD_TYPE_SSHFP: u16 = 44;
73
pub const DNS_RECORD_TYPE_IPSECKEY: u16 = 45;
74
pub const DNS_RECORD_TYPE_RRSIG: u16 = 46;
75
pub const DNS_RECORD_TYPE_NSEC: u16 = 47;
76
pub const DNS_RECORD_TYPE_DNSKEY: u16 = 48;
77
pub const DNS_RECORD_TYPE_DHCID: u16 = 49;
78
pub const DNS_RECORD_TYPE_NSEC3: u16 = 50;
79
pub const DNS_RECORD_TYPE_NSEC3PARAM: u16 = 51;
80
pub const DNS_RECORD_TYPE_TLSA: u16 = 52;
81
pub const DNS_RECORD_TYPE_HIP: u16 = 55;
82
pub const DNS_RECORD_TYPE_CDS: u16 = 59;
83
pub const DNS_RECORD_TYPE_CDNSKEY: u16 = 60;
84
pub const DNS_RECORD_TYPE_HTTPS: u16 = 65;
85
pub const DNS_RECORD_TYPE_SPF: u16 = 99; // Obsolete
86
pub const DNS_RECORD_TYPE_TKEY: u16 = 249;
87
pub const DNS_RECORD_TYPE_TSIG: u16 = 250;
88
pub const DNS_RECORD_TYPE_MAILA: u16 = 254; // Obsolete
89
pub const DNS_RECORD_TYPE_ANY: u16 = 255;
90
pub const DNS_RECORD_TYPE_URI: u16 = 256;
91
92
/// DNS error codes.
93
pub const DNS_RCODE_NOERROR: u16 = 0;
94
pub const DNS_RCODE_FORMERR: u16 = 1;
95
pub const DNS_RCODE_SERVFAIL: u16 = 2;
96
pub const DNS_RCODE_NXDOMAIN: u16 = 3;
97
pub const DNS_RCODE_NOTIMP: u16 = 4;
98
pub const DNS_RCODE_REFUSED: u16 = 5;
99
pub const DNS_RCODE_YXDOMAIN: u16 = 6;
100
pub const DNS_RCODE_YXRRSET: u16 = 7;
101
pub const DNS_RCODE_NXRRSET: u16 = 8;
102
pub const DNS_RCODE_NOTAUTH: u16 = 9;
103
pub const DNS_RCODE_NOTZONE: u16 = 10;
104
// Support for OPT RR from RFC6891 will be needed to
105
// parse RCODE values over 15
106
pub const DNS_RCODE_BADVERS: u16 = 16;
107
//also pub const DNS_RCODE_BADSIG: u16 = 16;
108
pub const DNS_RCODE_BADKEY: u16 = 17;
109
pub const DNS_RCODE_BADTIME: u16 = 18;
110
pub const DNS_RCODE_BADMODE: u16 = 19;
111
pub const DNS_RCODE_BADNAME: u16 = 20;
112
pub const DNS_RCODE_BADALG: u16 = 21;
113
pub const DNS_RCODE_BADTRUNC: u16 = 22;
114
115
static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
116
117
#[derive(AppLayerFrameType)]
118
pub enum DnsFrameType {
119
    /// DNS PDU frame. For UDP DNS this is the complete UDP payload, for TCP
120
    /// this is the DNS payload not including the leading length field allowing
121
    /// this frame to be used for UDP and TCP DNS.
122
    Pdu,
123
}
124
125
#[derive(Debug, PartialEq, Eq, AppLayerEvent)]
126
pub enum DNSEvent {
127
    MalformedData,
128
    NotRequest,
129
    NotResponse,
130
    ZFlagSet,
131
    InvalidOpcode,
132
    /// A DNS resource name was exessively long and was truncated.
133
    NameTooLong,
134
    /// An infinite loop was found while parsing a name.
135
    InfiniteLoop,
136
    /// Too many labels were found.
137
    TooManyLabels,
138
}
139
140
#[derive(Debug, PartialEq, Eq)]
141
#[repr(C)]
142
pub struct DNSHeader {
143
    pub tx_id: u16,
144
    pub flags: u16,
145
    pub questions: u16,
146
    pub answer_rr: u16,
147
    pub authority_rr: u16,
148
    pub additional_rr: u16,
149
}
150
151
#[derive(Debug)]
152
pub struct DNSQueryEntry {
153
    pub name: DNSName,
154
    pub rrtype: u16,
155
    pub rrclass: u16,
156
}
157
158
#[derive(Debug, PartialEq, Eq)]
159
pub struct DNSRDataSOA {
160
    /// Primary name server for this zone
161
    pub mname: DNSName,
162
    /// Authority's mailbox
163
    pub rname: DNSName,
164
    /// Serial version number
165
    pub serial: u32,
166
    /// Refresh interval (seconds)
167
    pub refresh: u32,
168
    /// Retry interval (seconds)
169
    pub retry: u32,
170
    /// Upper time limit until zone is no longer authoritative (seconds)
171
    pub expire: u32,
172
    /// Minimum ttl for records in this zone (seconds)
173
    pub minimum: u32,
174
}
175
176
#[derive(Debug, PartialEq, Eq)]
177
pub struct DNSRDataSSHFP {
178
    /// Algorithm number
179
    pub algo: u8,
180
    /// Fingerprint type
181
    pub fp_type: u8,
182
    /// Fingerprint
183
    pub fingerprint: Vec<u8>,
184
}
185
186
#[derive(Debug, PartialEq, Eq)]
187
pub struct DNSRDataSRV {
188
    /// Priority
189
    pub priority: u16,
190
    /// Weight
191
    pub weight: u16,
192
    /// Port
193
    pub port: u16,
194
    /// Target
195
    pub target: DNSName,
196
}
197
198
bitflags! {
199
    #[derive(Default)]
200
    pub struct DNSNameFlags: u8 {
201
        const INFINITE_LOOP = 0b0000_0001;
202
        const TRUNCATED     = 0b0000_0010;
203
        const LABEL_LIMIT   = 0b0000_0100;
204
    }
205
}
206
207
#[derive(Debug, Clone, PartialEq, Eq)]
208
pub struct DNSName {
209
    pub value: Vec<u8>,
210
    pub flags: DNSNameFlags,
211
}
212
213
/// Represents RData of various formats
214
#[derive(Debug, PartialEq, Eq)]
215
pub enum DNSRData {
216
    // RData is an address
217
    A(Vec<u8>),
218
    AAAA(Vec<u8>),
219
    // RData is a domain name
220
    CNAME(DNSName),
221
    PTR(DNSName),
222
    MX(DNSName),
223
    NS(DNSName),
224
    // RData is text
225
    TXT(Vec<u8>),
226
    NULL(Vec<u8>),
227
    // RData has several fields
228
    SOA(DNSRDataSOA),
229
    SRV(DNSRDataSRV),
230
    SSHFP(DNSRDataSSHFP),
231
    // RData for remaining types is sometimes ignored
232
    Unknown(Vec<u8>),
233
}
234
235
#[derive(Debug, PartialEq, Eq)]
236
pub struct DNSAnswerEntry {
237
    pub name: DNSName,
238
    pub rrtype: u16,
239
    pub rrclass: u16,
240
    pub ttl: u32,
241
    pub data: DNSRData,
242
}
243
244
#[derive(Debug)]
245
pub struct DNSRequest {
246
    pub header: DNSHeader,
247
    pub queries: Vec<DNSQueryEntry>,
248
}
249
250
#[derive(Debug)]
251
pub struct DNSResponse {
252
    pub header: DNSHeader,
253
    pub queries: Vec<DNSQueryEntry>,
254
    pub answers: Vec<DNSAnswerEntry>,
255
    pub authorities: Vec<DNSAnswerEntry>,
256
}
257
258
#[derive(Debug, Default)]
259
pub struct DNSTransaction {
260
    pub id: u64,
261
    pub request: Option<DNSRequest>,
262
    pub response: Option<DNSResponse>,
263
    pub tx_data: AppLayerTxData,
264
}
265
266
impl Transaction for DNSTransaction {
267
2.34M
    fn id(&self) -> u64 {
268
2.34M
        self.id
269
2.34M
    }
270
}
271
272
impl DNSTransaction {
273
2.90M
    pub fn new(direction: Direction) -> Self {
274
2.90M
  Self {
275
2.90M
      tx_data: AppLayerTxData::for_direction(direction),
276
2.90M
            ..Default::default()
277
2.90M
  }
278
2.90M
    }
279
280
    /// Get the DNS transactions ID (not the internal tracking ID).
281
0
    pub fn tx_id(&self) -> u16 {
282
0
        if let Some(request) = &self.request {
283
0
            return request.header.tx_id;
284
0
        }
285
0
        if let Some(response) = &self.response {
286
0
            return response.header.tx_id;
287
0
        }
288
289
        // Shouldn't happen.
290
0
        return 0;
291
0
    }
292
293
    /// Get the reply code of the transaction. Note that this will
294
    /// also return 0 if there is no reply.
295
0
    pub fn rcode(&self) -> u16 {
296
0
        if let Some(response) = &self.response {
297
0
            return response.header.flags & 0x000f;
298
0
        }
299
0
        return 0;
300
0
    }
301
}
302
303
struct ConfigTracker {
304
    map: HashMap<u16, AppLayerTxConfig>,
305
    queue: VecDeque<u16>,
306
}
307
308
impl ConfigTracker {
309
10
    fn new() -> ConfigTracker {
310
10
        ConfigTracker {
311
10
            map: HashMap::new(),
312
10
            queue: VecDeque::new(),
313
10
        }
314
10
    }
315
316
10
    fn add(&mut self, id: u16, config: AppLayerTxConfig) {
317
        // If at size limit, remove the oldest entry.
318
10
        if self.queue.len() > 499 {
319
0
            if let Some(id) = self.queue.pop_front() {
320
0
                self.map.remove(&id);
321
0
            }
322
10
        }
323
324
10
        self.map.insert(id, config);
325
10
        self.queue.push_back(id);
326
10
    }
327
328
17
    fn remove(&mut self, id: &u16) -> Option<AppLayerTxConfig> {
329
17
        self.map.remove(id)
330
17
    }
331
}
332
333
#[derive(Default)]
334
pub struct DNSState {
335
    state_data: AppLayerStateData,
336
337
    // Internal transaction ID.
338
    pub tx_id: u64,
339
340
    // Transactions.
341
    pub transactions: VecDeque<DNSTransaction>,
342
343
    config: Option<ConfigTracker>,
344
345
    gap: bool,
346
}
347
348
impl State<DNSTransaction> for DNSState {
349
1.36M
    fn get_transaction_count(&self) -> usize {
350
1.36M
        self.transactions.len()
351
1.36M
    }
352
353
1.17M
    fn get_transaction_by_index(&self, index: usize) -> Option<&DNSTransaction> {
354
1.17M
        self.transactions.get(index)
355
1.17M
    }
356
}
357
358
impl DNSState {
359
11.7k
    pub fn new() -> Self {
360
11.7k
        Default::default()
361
11.7k
    }
362
363
2.90M
    pub fn new_tx(&mut self, direction: Direction) -> DNSTransaction {
364
2.90M
        let mut tx = DNSTransaction::new(direction);
365
2.90M
        self.tx_id += 1;
366
2.90M
        tx.id = self.tx_id;
367
2.90M
        return tx;
368
2.90M
    }
369
370
1.01M
    pub fn free_tx(&mut self, tx_id: u64) {
371
1.01M
        let len = self.transactions.len();
372
1.01M
        let mut found = false;
373
1.01M
        let mut index = 0;
374
1.01M
        for i in 0..len {
375
1.01M
            let tx = &self.transactions[i];
376
1.01M
            if tx.id == tx_id + 1 {
377
1.01M
                found = true;
378
1.01M
                index = i;
379
1.01M
                break;
380
0
            }
381
        }
382
1.01M
        if found {
383
1.01M
            self.transactions.remove(index);
384
1.01M
        }
385
1.01M
    }
386
387
14.2k
    pub fn get_tx(&mut self, tx_id: u64) -> Option<&DNSTransaction> {
388
14.2k
        return self.transactions.iter().find(|&tx| tx.id == tx_id + 1);
389
14.2k
    }
390
391
    /// Set an event. The event is set on the most recent transaction.
392
5.14M
    pub fn set_event(&mut self, event: DNSEvent) {
393
5.14M
        let len = self.transactions.len();
394
5.14M
        if len == 0 {
395
80.9k
            return;
396
5.06M
        }
397
398
5.06M
        let tx = &mut self.transactions[len - 1];
399
5.06M
        tx.tx_data.set_event(event as u8);
400
5.14M
    }
401
402
3.06M
    fn validate_header<'a>(&self, input: &'a [u8]) -> Option<(&'a [u8], DNSHeader)> {
403
3.06M
        if let Ok((body, header)) = parser::dns_parse_header(input) {
404
3.02M
            if probe_header_validity(&header, input.len()).0 {
405
2.95M
                return Some((body, header));
406
65.8k
            }
407
38.0k
        }
408
103k
        None
409
3.06M
    }
410
411
1.42M
    fn parse_request(&mut self, input: &[u8], is_tcp: bool) -> bool {
412
1.42M
        let (body, header) = if let Some((body, header)) = self.validate_header(input) {
413
1.36M
            (body, header)
414
        } else {
415
55.0k
            return !is_tcp;
416
        };
417
418
1.36M
        match parser::dns_parse_request_body(body, input, header) {
419
1.35M
            Ok((_, (request, parse_flags))) => {
420
1.35M
                if request.header.flags & 0x8000 != 0 {
421
                    SCLogDebug!("DNS message is not a request");
422
1.94k
                    self.set_event(DNSEvent::NotRequest);
423
1.94k
                    return false;
424
1.35M
                }
425
426
1.35M
                let z_flag = request.header.flags & 0x0040 != 0;
427
1.35M
                let opcode = ((request.header.flags >> 11) & 0xf) as u8;
428
429
1.35M
                let mut tx = self.new_tx(Direction::ToServer);
430
1.35M
                tx.request = Some(request);
431
1.35M
                self.transactions.push_back(tx);
432
433
1.35M
                if z_flag {
434
557k
                    SCLogDebug!("Z-flag set on DNS response");
435
557k
                    self.set_event(DNSEvent::ZFlagSet);
436
796k
                }
437
438
1.35M
                if opcode >= 7 {
439
558k
                    self.set_event(DNSEvent::InvalidOpcode);
440
796k
                }
441
442
1.35M
                if parse_flags.contains(DNSNameFlags::TRUNCATED) {
443
823
                    self.set_event(DNSEvent::NameTooLong);
444
1.35M
                }
445
                
446
1.35M
                if parse_flags.contains(DNSNameFlags::INFINITE_LOOP) {
447
301
                    self.set_event(DNSEvent::InfiniteLoop);
448
1.35M
                }
449
                
450
1.35M
                if parse_flags.contains(DNSNameFlags::LABEL_LIMIT) {
451
591
                    self.set_event(DNSEvent::TooManyLabels);
452
1.35M
                }
453
454
1.35M
                return true;
455
            }
456
            Err(Err::Incomplete(_)) => {
457
                // Insufficient data.
458
                SCLogDebug!("Insufficient data while parsing DNS request");
459
3.45k
                self.set_event(DNSEvent::MalformedData);
460
3.45k
                return false;
461
            }
462
            Err(_) => {
463
                // Error, probably malformed data.
464
                SCLogDebug!("An error occurred while parsing DNS request");
465
7.46k
                self.set_event(DNSEvent::MalformedData);
466
7.46k
                return false;
467
            }
468
        }
469
1.42M
    }
470
471
168k
    fn parse_request_udp(&mut self, flow: *const core::Flow, stream_slice: StreamSlice) -> bool {
472
168k
        let input = stream_slice.as_slice();
473
168k
        let _pdu = Frame::new(
474
168k
            flow,
475
168k
            &stream_slice,
476
168k
            input,
477
168k
            input.len() as i64,
478
168k
            DnsFrameType::Pdu as u8,
479
        );
480
168k
        self.parse_request(input, false)
481
168k
    }
482
483
136k
    fn parse_response_udp(&mut self, flow: *const core::Flow, stream_slice: StreamSlice) -> bool {
484
136k
        let input = stream_slice.as_slice();
485
136k
        let _pdu = Frame::new(
486
136k
            flow,
487
136k
            &stream_slice,
488
136k
            input,
489
136k
            input.len() as i64,
490
136k
            DnsFrameType::Pdu as u8,
491
        );
492
136k
        self.parse_response(input, false)
493
136k
    }
494
495
1.63M
    pub fn parse_response(&mut self, input: &[u8], is_tcp: bool) -> bool {
496
1.63M
        let (body, header) = if let Some((body, header)) = self.validate_header(input) {
497
1.58M
            (body, header)
498
        } else {
499
48.7k
            return !is_tcp;
500
        };
501
502
1.58M
        match parser::dns_parse_response_body(body, input, header) {
503
1.55M
            Ok((_, (response, parse_flags))) => {
504
                SCLogDebug!("Response header flags: {}", response.header.flags);
505
506
1.55M
                if response.header.flags & 0x8000 == 0 {
507
1.52M
                    SCLogDebug!("DNS message is not a response");
508
1.52M
                    self.set_event(DNSEvent::NotResponse);
509
1.52M
                }
510
511
1.55M
                let z_flag = response.header.flags & 0x0040 != 0;
512
1.55M
                let opcode = ((response.header.flags >> 11) & 0xf) as u8;
513
514
1.55M
                let mut tx = self.new_tx(Direction::ToClient);
515
1.55M
                if let Some(ref mut config) = &mut self.config {
516
17
                    if let Some(config) = config.remove(&response.header.tx_id) {
517
5
                        tx.tx_data.config = config;
518
12
                    }
519
1.55M
                }
520
1.55M
                tx.response = Some(response);
521
1.55M
                self.transactions.push_back(tx);
522
523
1.55M
                if z_flag {
524
1.22M
                    SCLogDebug!("Z-flag set on DNS response");
525
1.22M
                    self.set_event(DNSEvent::ZFlagSet);
526
1.22M
                }
527
528
1.55M
                if opcode >= 7 {
529
1.22M
                    self.set_event(DNSEvent::InvalidOpcode);
530
1.22M
                }
531
532
1.55M
                if parse_flags.contains(DNSNameFlags::TRUNCATED) {
533
573
                    self.set_event(DNSEvent::NameTooLong);
534
1.54M
                }
535
                
536
1.55M
                if parse_flags.contains(DNSNameFlags::INFINITE_LOOP) {
537
310
                    self.set_event(DNSEvent::InfiniteLoop);
538
1.55M
                }
539
                
540
1.55M
                if parse_flags.contains(DNSNameFlags::LABEL_LIMIT) {
541
537
                    self.set_event(DNSEvent::TooManyLabels);
542
1.55M
                }
543
544
1.55M
                return true;
545
            }
546
            Err(Err::Incomplete(_)) => {
547
                // Insufficient data.
548
                SCLogDebug!("Insufficient data while parsing DNS response");
549
17.5k
                self.set_event(DNSEvent::MalformedData);
550
17.5k
                return false;
551
            }
552
            Err(_) => {
553
                // Error, probably malformed data.
554
                SCLogDebug!("An error occurred while parsing DNS response");
555
21.4k
                self.set_event(DNSEvent::MalformedData);
556
21.4k
                return false;
557
            }
558
        }
559
1.63M
    }
560
561
    /// TCP variation of response request parser to handle the length
562
    /// prefix.
563
    ///
564
    /// Returns the number of messages parsed.
565
8.03k
    pub fn parse_request_tcp(
566
8.03k
        &mut self, flow: *const core::Flow, stream_slice: StreamSlice,
567
8.03k
    ) -> AppLayerResult {
568
8.03k
        let input = stream_slice.as_slice();
569
8.03k
        if self.gap {
570
46
            let (is_dns, _, is_incomplete) = probe_tcp(input);
571
46
            if is_dns || is_incomplete {
572
6
                self.gap = false;
573
40
            } else {
574
40
                AppLayerResult::ok();
575
40
            }
576
7.98k
        }
577
578
8.03k
        let mut cur_i = input;
579
8.03k
        let mut consumed = 0;
580
3.00M
        while !cur_i.is_empty() {
581
3.00M
            if cur_i.len() == 1 {
582
1.49k
                return AppLayerResult::incomplete(consumed as u32, 2_u32);
583
2.99M
            }
584
2.99M
            let size = match be_u16(cur_i) as IResult<&[u8], u16> {
585
2.99M
                Ok((_, len)) => len,
586
0
                _ => 0,
587
            } as usize;
588
            SCLogDebug!(
589
                "[request] Have {} bytes, need {} to parse",
590
                cur_i.len(),
591
                size + 2
592
            );
593
2.99M
            if size > 0 && cur_i.len() >= size + 2 {
594
1.25M
                let msg = &cur_i[2..(size + 2)];
595
1.25M
                sc_app_layer_parser_trigger_raw_stream_reassembly(flow, Direction::ToServer as i32);
596
1.25M
                let _pdu = Frame::new(
597
1.25M
                    flow,
598
1.25M
                    &stream_slice,
599
1.25M
                    msg,
600
1.25M
                    msg.len() as i64,
601
1.25M
                    DnsFrameType::Pdu as u8,
602
                );
603
1.25M
                if self.parse_request(msg, true) {
604
1.25M
                    cur_i = &cur_i[(size + 2)..];
605
1.25M
                    consumed += size + 2;
606
1.25M
                } else {
607
187
                    return AppLayerResult::err();
608
                }
609
1.74M
            } else if size == 0 {
610
1.74M
                cur_i = &cur_i[2..];
611
1.74M
                consumed += 2;
612
1.74M
            } else {
613
                SCLogDebug!(
614
                    "[request]Not enough DNS traffic to parse. Returning {}/{}",
615
                    consumed as u32,
616
                    (size + 2) as u32
617
                );
618
1.76k
                return AppLayerResult::incomplete(consumed as u32, (size + 2) as u32);
619
            }
620
        }
621
4.58k
        AppLayerResult::ok()
622
8.03k
    }
623
624
    /// TCP variation of the response parser to handle the length
625
    /// prefix.
626
    ///
627
    /// Returns the number of messages parsed.
628
11.6k
    pub fn parse_response_tcp(
629
11.6k
        &mut self, flow: *const core::Flow, stream_slice: StreamSlice,
630
11.6k
    ) -> AppLayerResult {
631
11.6k
        let input = stream_slice.as_slice();
632
11.6k
        if self.gap {
633
3.35k
            let (is_dns, _, is_incomplete) = probe_tcp(input);
634
3.35k
            if is_dns || is_incomplete {
635
35
                self.gap = false;
636
35
            } else {
637
3.31k
                return AppLayerResult::ok();
638
            }
639
8.32k
        }
640
641
8.35k
        let mut cur_i = input;
642
8.35k
        let mut consumed = 0;
643
3.44M
        while !cur_i.is_empty() {
644
3.44M
            if cur_i.len() == 1 {
645
1.63k
                return AppLayerResult::incomplete(consumed as u32, 2_u32);
646
3.44M
            }
647
3.44M
            let size = match be_u16(cur_i) as IResult<&[u8], u16> {
648
3.44M
                Ok((_, len)) => len,
649
0
                _ => 0,
650
            } as usize;
651
            SCLogDebug!(
652
                "[response] Have {} bytes, need {} to parse",
653
                cur_i.len(),
654
                size + 2
655
            );
656
3.44M
            if size > 0 && cur_i.len() >= size + 2 {
657
1.50M
                let msg = &cur_i[2..(size + 2)];
658
1.50M
                sc_app_layer_parser_trigger_raw_stream_reassembly(flow, Direction::ToClient as i32);
659
1.50M
                let _pdu = Frame::new(
660
1.50M
                    flow,
661
1.50M
                    &stream_slice,
662
1.50M
                    msg,
663
1.50M
                    msg.len() as i64,
664
1.50M
                    DnsFrameType::Pdu as u8,
665
                );
666
1.50M
                if self.parse_response(msg, true) {
667
1.50M
                    cur_i = &cur_i[(size + 2)..];
668
1.50M
                    consumed += size + 2;
669
1.50M
                } else {
670
181
                    return AppLayerResult::err();
671
                }
672
1.94M
            } else if size == 0 {
673
1.93M
                cur_i = &cur_i[2..];
674
1.93M
                consumed += 2;
675
1.93M
            } else {
676
                SCLogDebug!(
677
                    "[response]Not enough DNS traffic to parse. Returning {}/{}",
678
                    consumed as u32,
679
                    (cur_i.len() - consumed) as u32
680
                );
681
1.54k
                return AppLayerResult::incomplete(consumed as u32, (size + 2) as u32);
682
            }
683
        }
684
5.00k
        AppLayerResult::ok()
685
11.6k
    }
686
687
    /// A gap has been seen in the request direction. Set the gap flag.
688
27
    pub fn request_gap(&mut self, gap: u32) {
689
27
        if gap > 0 {
690
27
            self.gap = true;
691
27
        }
692
27
    }
693
694
    /// A gap has been seen in the response direction. Set the gap
695
    /// flag.
696
64
    pub fn response_gap(&mut self, gap: u32) {
697
64
        if gap > 0 {
698
64
            self.gap = true;
699
64
        }
700
64
    }
701
}
702
703
const DNS_HEADER_SIZE: usize = 12;
704
705
3.05M
fn probe_header_validity(header: &DNSHeader, rlen: usize) -> (bool, bool, bool) {
706
3.05M
    let min_msg_size = 2
707
3.05M
        * (header.additional_rr as usize
708
3.05M
            + header.answer_rr as usize
709
3.05M
            + header.authority_rr as usize
710
3.05M
            + header.questions as usize)
711
3.05M
        + DNS_HEADER_SIZE;
712
713
3.05M
    if min_msg_size > rlen {
714
        // Not enough data for records defined in the header, or
715
        // impossibly large.
716
67.4k
        return (false, false, false);
717
2.98M
    }
718
719
2.98M
    let is_request = header.flags & 0x8000 == 0;
720
2.98M
    return (true, is_request, false);
721
3.05M
}
722
723
/// Probe input to see if it looks like DNS.
724
///
725
/// Returns a tuple of booleans: (is_dns, is_request, incomplete)
726
31.5k
fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
727
    // Trim input to dlen if larger.
728
31.5k
    let input = if input.len() <= dlen {
729
20.0k
        input
730
    } else {
731
11.5k
        &input[..dlen]
732
    };
733
734
    // If input is less than dlen then we know we don't have enough data to
735
    // parse a complete message, so perform header validation only.
736
31.5k
    if input.len() < dlen {
737
8.01k
        if let Ok((_, header)) = parser::dns_parse_header(input) {
738
5.47k
            return probe_header_validity(&header, dlen);
739
        } else {
740
2.53k
            return (false, false, false);
741
        }
742
23.5k
    }
743
744
23.5k
    match parser::dns_parse_request(input) {
745
13.5k
        Ok((_, (request, _))) => {
746
13.5k
            return probe_header_validity(&request.header, dlen);
747
        }
748
9.22k
        Err(Err::Incomplete(_)) => match parser::dns_parse_header(input) {
749
8.52k
            Ok((_, header)) => {
750
8.52k
                return probe_header_validity(&header, dlen);
751
            }
752
696
            Err(Err::Incomplete(_)) => (false, false, true),
753
0
            Err(_) => (false, false, false),
754
        },
755
759
        Err(_) => (false, false, false),
756
    }
757
31.5k
}
758
759
/// Probe TCP input to see if it looks like DNS.
760
19.8k
pub fn probe_tcp(input: &[u8]) -> (bool, bool, bool) {
761
19.8k
    match be_u16(input) as IResult<&[u8], u16> {
762
19.8k
        Ok((rem, dlen)) => {
763
19.8k
            return probe(rem, dlen as usize);
764
        }
765
        Err(Err::Incomplete(_)) => {
766
5
            return (false, false, true);
767
        }
768
0
        _ => {}
769
    }
770
0
    return (false, false, false);
771
19.8k
}
772
773
/// Returns *mut DNSState
774
#[no_mangle]
775
11.7k
pub extern "C" fn rs_dns_state_new(
776
11.7k
    _orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
777
11.7k
) -> *mut std::os::raw::c_void {
778
11.7k
    let state = DNSState::new();
779
11.7k
    let boxed = Box::new(state);
780
11.7k
    return Box::into_raw(boxed) as *mut _;
781
11.7k
}
782
783
/// Returns *mut DNSState
784
#[no_mangle]
785
0
pub extern "C" fn rs_dns_state_tcp_new() -> *mut std::os::raw::c_void {
786
0
    let state = DNSState::new();
787
0
    let boxed = Box::new(state);
788
0
    return Box::into_raw(boxed) as *mut _;
789
0
}
790
791
/// Params:
792
/// - state: *mut DNSState as void pointer
793
#[no_mangle]
794
11.7k
pub extern "C" fn rs_dns_state_free(state: *mut std::os::raw::c_void) {
795
    // Just unbox...
796
11.7k
    std::mem::drop(unsafe { Box::from_raw(state as *mut DNSState) });
797
11.7k
}
798
799
#[no_mangle]
800
1.01M
pub unsafe extern "C" fn rs_dns_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
801
1.01M
    let state = cast_pointer!(state, DNSState);
802
1.01M
    state.free_tx(tx_id);
803
1.01M
}
804
805
/// C binding parse a DNS request. Returns 1 on success, -1 on failure.
806
#[no_mangle]
807
168k
pub unsafe extern "C" fn rs_dns_parse_request(
808
168k
    flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
809
168k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
810
168k
) -> AppLayerResult {
811
168k
    let state = cast_pointer!(state, DNSState);
812
168k
    state.parse_request_udp(flow, stream_slice);
813
168k
    AppLayerResult::ok()
814
168k
}
815
816
#[no_mangle]
817
136k
pub unsafe extern "C" fn rs_dns_parse_response(
818
136k
    flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
819
136k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
820
136k
) -> AppLayerResult {
821
136k
    let state = cast_pointer!(state, DNSState);
822
136k
    state.parse_response_udp(flow, stream_slice);
823
136k
    AppLayerResult::ok()
824
136k
}
825
826
/// C binding parse a DNS request. Returns 1 on success, -1 on failure.
827
#[no_mangle]
828
8.06k
pub unsafe extern "C" fn rs_dns_parse_request_tcp(
829
8.06k
    flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
830
8.06k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
831
8.06k
) -> AppLayerResult {
832
8.06k
    let state = cast_pointer!(state, DNSState);
833
8.06k
    if stream_slice.is_gap() {
834
27
        state.request_gap(stream_slice.gap_size());
835
8.03k
    } else if !stream_slice.is_empty() {
836
8.03k
        return state.parse_request_tcp(flow, stream_slice);
837
3
    }
838
30
    AppLayerResult::ok()
839
8.06k
}
840
841
#[no_mangle]
842
11.7k
pub unsafe extern "C" fn rs_dns_parse_response_tcp(
843
11.7k
    flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
844
11.7k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
845
11.7k
) -> AppLayerResult {
846
11.7k
    let state = cast_pointer!(state, DNSState);
847
11.7k
    if stream_slice.is_gap() {
848
64
        state.response_gap(stream_slice.gap_size());
849
11.6k
    } else if !stream_slice.is_empty() {
850
11.6k
        return state.parse_response_tcp(flow, stream_slice);
851
6
    }
852
70
    AppLayerResult::ok()
853
11.7k
}
854
855
#[no_mangle]
856
2.26M
pub extern "C" fn rs_dns_tx_get_alstate_progress(
857
2.26M
    _tx: *mut std::os::raw::c_void, _direction: u8,
858
2.26M
) -> std::os::raw::c_int {
859
    // This is a stateless parser, just the existence of a transaction
860
    // means its complete.
861
    SCLogDebug!("rs_dns_tx_get_alstate_progress");
862
2.26M
    return 1;
863
2.26M
}
864
865
#[no_mangle]
866
1.13M
pub unsafe extern "C" fn rs_dns_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
867
1.13M
    let state = cast_pointer!(state, DNSState);
868
    SCLogDebug!("rs_dns_state_get_tx_count: returning {}", state.tx_id);
869
1.13M
    return state.tx_id;
870
1.13M
}
871
872
#[no_mangle]
873
14.2k
pub unsafe extern "C" fn rs_dns_state_get_tx(
874
14.2k
    state: *mut std::os::raw::c_void, tx_id: u64,
875
14.2k
) -> *mut std::os::raw::c_void {
876
14.2k
    let state = cast_pointer!(state, DNSState);
877
14.2k
    match state.get_tx(tx_id) {
878
14.1k
        Some(tx) => {
879
14.1k
            return tx as *const _ as *mut _;
880
        }
881
        None => {
882
86
            return std::ptr::null_mut();
883
        }
884
    }
885
14.2k
}
886
887
#[no_mangle]
888
82.1k
pub extern "C" fn rs_dns_tx_is_request(tx: &mut DNSTransaction) -> bool {
889
82.1k
    tx.request.is_some()
890
82.1k
}
891
892
#[no_mangle]
893
23.0k
pub extern "C" fn rs_dns_tx_is_response(tx: &mut DNSTransaction) -> bool {
894
23.0k
    tx.response.is_some()
895
23.0k
}
896
897
1.24M
pub unsafe extern "C" fn rs_dns_state_get_tx_data(
898
1.24M
    tx: *mut std::os::raw::c_void,
899
1.24M
) -> *mut AppLayerTxData {
900
1.24M
    let tx = cast_pointer!(tx, DNSTransaction);
901
1.24M
    return &mut tx.tx_data;
902
1.24M
}
903
904
export_state_data_get!(rs_dns_get_state_data, DNSState);
905
906
#[no_mangle]
907
1.97k
pub unsafe extern "C" fn rs_dns_tx_get_query_name(
908
1.97k
    tx: &mut DNSTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
909
1.97k
) -> u8 {
910
1.97k
    if let Some(request) = &tx.request {
911
1.97k
        if (i as usize) < request.queries.len() {
912
1.02k
            let query = &request.queries[i as usize];
913
1.02k
            if !query.name.value.is_empty() {
914
1.00k
                *len = query.name.value.len() as u32;
915
1.00k
                *buf = query.name.value.as_ptr();
916
1.00k
                return 1;
917
15
            }
918
953
        }
919
0
    }
920
968
    return 0;
921
1.97k
}
922
923
/// Get the DNS transaction ID of a transaction.
924
//
925
/// extern uint16_t rs_dns_tx_get_tx_id(RSDNSTransaction *);
926
#[no_mangle]
927
0
pub extern "C" fn rs_dns_tx_get_tx_id(tx: &mut DNSTransaction) -> u16 {
928
0
    return tx.tx_id();
929
0
}
930
931
/// Get the DNS response flags for a transaction.
932
///
933
/// extern uint16_t rs_dns_tx_get_response_flags(RSDNSTransaction *);
934
#[no_mangle]
935
0
pub extern "C" fn rs_dns_tx_get_response_flags(tx: &mut DNSTransaction) -> u16 {
936
0
    return tx.rcode();
937
0
}
938
939
#[no_mangle]
940
0
pub unsafe extern "C" fn rs_dns_tx_get_query_rrtype(
941
0
    tx: &mut DNSTransaction, i: u16, rrtype: *mut u16,
942
0
) -> u8 {
943
0
    if let Some(request) = &tx.request {
944
0
        if (i as usize) < request.queries.len() {
945
0
            let query = &request.queries[i as usize];
946
0
            if !query.name.value.is_empty() {
947
0
                *rrtype = query.rrtype;
948
0
                return 1;
949
0
            }
950
0
        }
951
0
    }
952
0
    return 0;
953
0
}
954
955
#[no_mangle]
956
11.7k
pub unsafe extern "C" fn rs_dns_probe(
957
11.7k
    _flow: *const core::Flow, _dir: u8, input: *const u8, len: u32, rdir: *mut u8,
958
11.7k
) -> AppProto {
959
11.7k
    if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 {
960
29
        return core::ALPROTO_UNKNOWN;
961
11.7k
    }
962
11.7k
    let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);
963
11.7k
    let (is_dns, is_request, _) = probe(slice, slice.len());
964
11.7k
    if is_dns {
965
10.8k
        let dir = if is_request {
966
6.98k
            Direction::ToServer
967
        } else {
968
3.83k
            Direction::ToClient
969
        };
970
10.8k
        *rdir = dir as u8;
971
10.8k
        return ALPROTO_DNS;
972
943
    }
973
943
    return 0;
974
11.7k
}
975
976
#[no_mangle]
977
21.1k
pub unsafe extern "C" fn rs_dns_probe_tcp(
978
21.1k
    _flow: *const core::Flow, direction: u8, input: *const u8, len: u32, rdir: *mut u8,
979
21.1k
) -> AppProto {
980
21.1k
    if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
981
4.77k
        return core::ALPROTO_UNKNOWN;
982
16.4k
    }
983
16.4k
    let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);
984
    //is_incomplete is checked by caller
985
16.4k
    let (is_dns, is_request, _) = probe_tcp(slice);
986
16.4k
    if is_dns {
987
15.1k
        let dir = if is_request {
988
12.6k
            Direction::ToServer
989
        } else {
990
2.51k
            Direction::ToClient
991
        };
992
15.1k
        if (direction & DIR_BOTH) != dir.into() {
993
9.81k
            *rdir = dir as u8;
994
9.81k
        }
995
15.1k
        return ALPROTO_DNS;
996
1.24k
    }
997
1.24k
    return 0;
998
21.1k
}
999
1000
#[no_mangle]
1001
22
pub unsafe extern "C" fn rs_dns_apply_tx_config(
1002
22
    _state: *mut std::os::raw::c_void, _tx: *mut std::os::raw::c_void, _mode: std::os::raw::c_int,
1003
22
    config: AppLayerTxConfig,
1004
22
) {
1005
22
    let tx = cast_pointer!(_tx, DNSTransaction);
1006
22
    let state = cast_pointer!(_state, DNSState);
1007
22
    if let Some(request) = &tx.request {
1008
10
        if state.config.is_none() {
1009
10
            state.config = Some(ConfigTracker::new());
1010
10
        }
1011
10
        if let Some(ref mut tracker) = &mut state.config {
1012
10
            tracker.add(request.header.tx_id, config);
1013
10
        }
1014
12
    }
1015
22
}
1016
1017
#[no_mangle]
1018
34
pub unsafe extern "C" fn rs_dns_udp_register_parser() {
1019
34
    let default_port = std::ffi::CString::new("[53]").unwrap();
1020
34
    let parser = RustParser {
1021
34
        name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1022
34
        default_port: default_port.as_ptr(),
1023
34
        ipproto: IPPROTO_UDP,
1024
34
        probe_ts: Some(rs_dns_probe),
1025
34
        probe_tc: Some(rs_dns_probe),
1026
34
        min_depth: 0,
1027
34
        max_depth: std::mem::size_of::<DNSHeader>() as u16,
1028
34
        state_new: rs_dns_state_new,
1029
34
        state_free: rs_dns_state_free,
1030
34
        tx_free: rs_dns_state_tx_free,
1031
34
        parse_ts: rs_dns_parse_request,
1032
34
        parse_tc: rs_dns_parse_response,
1033
34
        get_tx_count: rs_dns_state_get_tx_count,
1034
34
        get_tx: rs_dns_state_get_tx,
1035
34
        tx_comp_st_ts: 1,
1036
34
        tx_comp_st_tc: 1,
1037
34
        tx_get_progress: rs_dns_tx_get_alstate_progress,
1038
34
        get_eventinfo: Some(DNSEvent::get_event_info),
1039
34
        get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id),
1040
34
        localstorage_new: None,
1041
34
        localstorage_free: None,
1042
34
        get_tx_files: None,
1043
34
        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
1044
34
        get_tx_data: rs_dns_state_get_tx_data,
1045
34
        get_state_data: rs_dns_get_state_data,
1046
34
        apply_tx_config: Some(rs_dns_apply_tx_config),
1047
34
        flags: 0,
1048
34
        truncate: None,
1049
34
        get_frame_id_by_name: Some(DnsFrameType::ffi_id_from_name),
1050
34
        get_frame_name_by_id: Some(DnsFrameType::ffi_name_from_id),
1051
34
    };
1052
1053
34
    let ip_proto_str = CString::new("udp").unwrap();
1054
34
    if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1055
34
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1056
34
        ALPROTO_DNS = alproto;
1057
34
        if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1058
34
            let _ = AppLayerRegisterParser(&parser, alproto);
1059
34
        }
1060
0
    }
1061
34
}
1062
1063
#[no_mangle]
1064
34
pub unsafe extern "C" fn rs_dns_tcp_register_parser() {
1065
34
    let default_port = std::ffi::CString::new("53").unwrap();
1066
34
    let parser = RustParser {
1067
34
        name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1068
34
        default_port: default_port.as_ptr(),
1069
34
        ipproto: IPPROTO_TCP,
1070
34
        probe_ts: Some(rs_dns_probe_tcp),
1071
34
        probe_tc: Some(rs_dns_probe_tcp),
1072
34
        min_depth: 0,
1073
34
        max_depth: std::mem::size_of::<DNSHeader>() as u16 + 2,
1074
34
        state_new: rs_dns_state_new,
1075
34
        state_free: rs_dns_state_free,
1076
34
        tx_free: rs_dns_state_tx_free,
1077
34
        parse_ts: rs_dns_parse_request_tcp,
1078
34
        parse_tc: rs_dns_parse_response_tcp,
1079
34
        get_tx_count: rs_dns_state_get_tx_count,
1080
34
        get_tx: rs_dns_state_get_tx,
1081
34
        tx_comp_st_ts: 1,
1082
34
        tx_comp_st_tc: 1,
1083
34
        tx_get_progress: rs_dns_tx_get_alstate_progress,
1084
34
        get_eventinfo: Some(DNSEvent::get_event_info),
1085
34
        get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id),
1086
34
        localstorage_new: None,
1087
34
        localstorage_free: None,
1088
34
        get_tx_files: None,
1089
34
        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
1090
34
        get_tx_data: rs_dns_state_get_tx_data,
1091
34
        get_state_data: rs_dns_get_state_data,
1092
34
        apply_tx_config: Some(rs_dns_apply_tx_config),
1093
34
        flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
1094
34
        truncate: None,
1095
34
        get_frame_id_by_name: Some(DnsFrameType::ffi_id_from_name),
1096
34
        get_frame_name_by_id: Some(DnsFrameType::ffi_name_from_id),
1097
34
    };
1098
1099
34
    let ip_proto_str = CString::new("tcp").unwrap();
1100
34
    if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1101
34
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1102
34
        ALPROTO_DNS = alproto;
1103
34
        if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1104
34
            let _ = AppLayerRegisterParser(&parser, alproto);
1105
34
        }
1106
0
    }
1107
34
}
1108
1109
#[cfg(test)]
1110
mod tests {
1111
1112
    use super::*;
1113
1114
    #[test]
1115
    fn test_dns_parse_request_tcp_valid() {
1116
        // A UDP DNS request with the DNS payload starting at byte 42.
1117
        // 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
1118
        #[rustfmt::skip]
1119
        let buf: &[u8] = &[
1120
            0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1121
            0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1122
            0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1123
            0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1124
            0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1125
            0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1126
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1127
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1128
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1129
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1130
            0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1131
            0x00, 0x00, 0x00                                /* ... */
1132
        ];
1133
1134
        // The DNS payload starts at offset 42.
1135
        let dns_payload = &buf[42..];
1136
1137
        // Make a TCP DNS request payload.
1138
        let mut request = Vec::new();
1139
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1140
        request.push(((dns_payload.len() as u16) & 0xff) as u8);
1141
        request.extend(dns_payload);
1142
1143
        let mut state = DNSState::new();
1144
        assert_eq!(
1145
            AppLayerResult::ok(),
1146
            state.parse_request_tcp(
1147
                std::ptr::null(),
1148
                StreamSlice::from_slice(&request, STREAM_TOSERVER, 0)
1149
            )
1150
        );
1151
    }
1152
1153
    #[test]
1154
    fn test_dns_parse_request_tcp_short_payload() {
1155
        // A UDP DNS request with the DNS payload starting at byte 42.
1156
        // 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
1157
        #[rustfmt::skip]
1158
        let buf: &[u8] = &[
1159
            0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1160
            0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1161
            0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1162
            0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1163
            0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1164
            0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1165
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1166
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1167
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1168
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1169
            0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1170
            0x00, 0x00, 0x00                                /* ... */
1171
        ];
1172
1173
        // The DNS payload starts at offset 42.
1174
        let dns_payload = &buf[42..];
1175
1176
        // Make a TCP DNS request payload but with the length 1 larger
1177
        // than the available data.
1178
        let mut request = Vec::new();
1179
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1180
        request.push(((dns_payload.len() as u16) & 0xff) as u8 + 1);
1181
        request.extend(dns_payload);
1182
1183
        let mut state = DNSState::new();
1184
        assert_eq!(
1185
            AppLayerResult::incomplete(0, 52),
1186
            state.parse_request_tcp(
1187
                std::ptr::null(),
1188
                StreamSlice::from_slice(&request, STREAM_TOSERVER, 0)
1189
            )
1190
        );
1191
    }
1192
1193
    #[test]
1194
    fn test_dns_parse_response_tcp_valid() {
1195
        // A UDP DNS response with the DNS payload starting at byte 42.
1196
        // 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
1197
        #[rustfmt::skip]
1198
        let buf: &[u8] = &[
1199
            0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1200
            0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1201
            0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1202
            0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1203
            0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1204
            0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1205
            0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1206
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1207
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1208
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1209
            0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1210
            0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1211
            0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1212
            0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1213
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1214
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1215
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1216
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19              /* ....N. */
1217
        ];
1218
1219
        // The DNS payload starts at offset 42.
1220
        let dns_payload = &buf[42..];
1221
1222
        // Make a TCP DNS response payload.
1223
        let mut request = Vec::new();
1224
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1225
        request.push(((dns_payload.len() as u16) & 0xff) as u8);
1226
        request.extend(dns_payload);
1227
1228
        let mut state = DNSState::new();
1229
        assert_eq!(
1230
            AppLayerResult::ok(),
1231
            state.parse_response_tcp(
1232
                std::ptr::null(),
1233
                StreamSlice::from_slice(&request, STREAM_TOCLIENT, 0)
1234
            )
1235
        );
1236
    }
1237
1238
    // Test that a TCP DNS payload won't be parsed if there is not
1239
    // enough data.
1240
    #[test]
1241
    fn test_dns_parse_response_tcp_short_payload() {
1242
        // A UDP DNS response with the DNS payload starting at byte 42.
1243
        // 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
1244
        #[rustfmt::skip]
1245
        let buf: &[u8] = &[
1246
            0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1247
            0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1248
            0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1249
            0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1250
            0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1251
            0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1252
            0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1253
            0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1254
            0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1255
            0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1256
            0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1257
            0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1258
            0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1259
            0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1260
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1261
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1262
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1263
            0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19              /* ....N. */
1264
        ];
1265
1266
        // The DNS payload starts at offset 42.
1267
        let dns_payload = &buf[42..];
1268
1269
        // Make a TCP DNS response payload, but make the length 1 byte
1270
        // larger than the actual size.
1271
        let mut request = Vec::new();
1272
        request.push(((dns_payload.len() as u16) >> 8) as u8);
1273
        request.push((((dns_payload.len() as u16) & 0xff) + 1) as u8);
1274
        request.extend(dns_payload);
1275
1276
        let mut state = DNSState::new();
1277
        assert_eq!(
1278
            AppLayerResult::incomplete(0, 103),
1279
            state.parse_response_tcp(
1280
                std::ptr::null(),
1281
                StreamSlice::from_slice(&request, STREAM_TOCLIENT, 0)
1282
            )
1283
        );
1284
    }
1285
1286
    // Port of the C RustDNSUDPParserTest02 unit test.
1287
    #[test]
1288
    fn test_dns_udp_parser_test_01() {
1289
        /* query: abcdefghijk.com
1290
         * TTL: 86400
1291
         * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
1292
         * ns, hostmaster */
1293
        #[rustfmt::skip]
1294
        let buf: &[u8] = &[
1295
            0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
1296
            0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
1297
            0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1298
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
1299
            0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
1300
            0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
1301
            0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
1302
            0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
1303
            0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
1304
            0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
1305
            0x80,
1306
        ];
1307
        let mut state = DNSState::new();
1308
        assert!(state.parse_response(buf, false));
1309
    }
1310
1311
    // Port of the C RustDNSUDPParserTest02 unit test.
1312
    #[test]
1313
    fn test_dns_udp_parser_test_02() {
1314
        #[rustfmt::skip]
1315
        let buf: &[u8] = &[
1316
            0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
1317
            0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
1318
            0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
1319
            0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
1320
            0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
1321
            0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
1322
            0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
1323
            0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
1324
            0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
1325
            0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1326
        ];
1327
        let mut state = DNSState::new();
1328
        assert!(state.parse_response(buf, false));
1329
    }
1330
1331
    // Port of the C RustDNSUDPParserTest03 unit test.
1332
    #[test]
1333
    fn test_dns_udp_parser_test_03() {
1334
        #[rustfmt::skip]
1335
        let buf: &[u8] = &[
1336
            0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
1337
            0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
1338
            0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
1339
            0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
1340
            0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
1341
            0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
1342
            0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
1343
            0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
1344
            0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
1345
            0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1346
        ];
1347
        let mut state = DNSState::new();
1348
        assert!(state.parse_response(buf, false));
1349
    }
1350
1351
    // Port of the C RustDNSUDPParserTest04 unit test.
1352
    //
1353
    // Test the TXT records in an answer.
1354
    #[test]
1355
    fn test_dns_udp_parser_test_04() {
1356
        #[rustfmt::skip]
1357
        let buf: &[u8] = &[
1358
            0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1359
            0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1360
            0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1361
            0x01,
1362
            /* answer record start */
1363
            0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1364
            /* txt record starts: */
1365
            0x20, /* <txt len 32 */  0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1366
            0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1367
            0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */   0xc0,0x1d,0x00,0x02,0x00,0x01,
1368
            0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1369
            0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1370
        ];
1371
        let mut state = DNSState::new();
1372
        assert!(state.parse_response(buf, false));
1373
    }
1374
1375
    // Port of the C RustDNSUDPParserTest05 unit test.
1376
    //
1377
    // Test TXT records in answer with a bad length.
1378
    #[test]
1379
    fn test_dns_udp_parser_test_05() {
1380
        #[rustfmt::skip]
1381
        let buf: &[u8] = &[
1382
            0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1383
            0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1384
            0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1385
            0x01,
1386
            /* answer record start */
1387
            0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1388
            /* txt record starts: */
1389
            0x40, /* <txt len 64 */  0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1390
            0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1391
            0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */   0xc0,0x1d,0x00,0x02,0x00,0x01,
1392
            0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1393
            0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1394
        ];
1395
        let mut state = DNSState::new();
1396
        assert!(!state.parse_response(buf, false));
1397
    }
1398
1399
    // Port of the C RustDNSTCPParserTestMultiRecord unit test.
1400
    #[test]
1401
    fn test_dns_tcp_parser_multi_record() {
1402
        #[rustfmt::skip]
1403
        let buf: &[u8] = &[
1404
            0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
1405
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
1406
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1407
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1408
            0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
1409
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
1410
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1411
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1412
            0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
1413
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
1414
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1415
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1416
            0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
1417
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
1418
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1419
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1420
            0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
1421
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
1422
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1423
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1424
            0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
1425
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
1426
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1427
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1428
            0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
1429
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
1430
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1431
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1432
            0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
1433
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
1434
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1435
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1436
            0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
1437
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
1438
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1439
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1440
            0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
1441
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
1442
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1443
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1444
            0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
1445
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1446
            0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1447
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1448
            0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
1449
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1450
            0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1451
            0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1452
            0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
1453
            0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454
            0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
1455
            0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
1456
            0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
1457
            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1458
            0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
1459
            0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
1460
            0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
1461
            0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1462
            0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
1463
            0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
1464
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
1465
            0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1466
            0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
1467
            0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1468
            0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
1469
            0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
1470
            0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
1471
            0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
1472
            0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
1473
            0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
1474
            0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
1475
            0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1476
            0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1477
            0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
1478
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1479
            0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1480
            0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1481
            0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
1482
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1483
            0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1484
            0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1485
            0x00, 0x01
1486
        ];
1487
1488
        // A NULL flow.
1489
        let flow = std::ptr::null();
1490
1491
        let mut state = DNSState::new();
1492
        assert_eq!(
1493
            AppLayerResult::ok(),
1494
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf, STREAM_TOSERVER, 0))
1495
        );
1496
    }
1497
1498
    #[test]
1499
    fn test_dns_tcp_parser_split_payload() {
1500
        // A NULL flow.
1501
        let flow = std::ptr::null();
1502
1503
        /* incomplete payload */
1504
        #[rustfmt::skip]
1505
        let buf1: &[u8] = &[
1506
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1507
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1508
        ];
1509
        /* complete payload plus the start of a new payload */
1510
        #[rustfmt::skip]
1511
        let buf2: &[u8] = &[
1512
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1513
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1514
            0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1515
            0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1516
1517
            // next.
1518
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1519
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1520
        ];
1521
1522
        /* and the complete payload again with no trailing data. */
1523
        #[rustfmt::skip]
1524
        let buf3: &[u8] = &[
1525
            0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1526
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1527
            0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1528
            0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1529
        ];
1530
1531
        let mut state = DNSState::new();
1532
        assert_eq!(
1533
            AppLayerResult::incomplete(0, 30),
1534
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf1, STREAM_TOSERVER, 0))
1535
        );
1536
        assert_eq!(
1537
            AppLayerResult::incomplete(30, 30),
1538
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf2, STREAM_TOSERVER, 0))
1539
        );
1540
        assert_eq!(
1541
            AppLayerResult::ok(),
1542
            state.parse_request_tcp(flow, StreamSlice::from_slice(buf3, STREAM_TOSERVER, 0))
1543
        );
1544
    }
1545
1546
    #[test]
1547
    fn test_dns_event_from_id() {
1548
        assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData));
1549
        assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet));
1550
        assert_eq!(DNSEvent::from_id(9), None);
1551
    }
1552
1553
    #[test]
1554
    fn test_dns_event_to_cstring() {
1555
        assert_eq!(DNSEvent::MalformedData.to_cstring(), "malformed_data\0");
1556
    }
1557
1558
    #[test]
1559
    fn test_dns_event_from_string() {
1560
        let name = "malformed_data";
1561
        let event = DNSEvent::from_string(name).unwrap();
1562
        assert_eq!(event, DNSEvent::MalformedData);
1563
        assert_eq!(event.to_cstring(), format!("{}\0", name));
1564
    }
1565
}