• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/rust/src/dns/lua.rs
1
/* Copyright (C) 2017 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::os::raw::c_int;
19

20
use crate::dns::dns::*;
21
use crate::dns::log::*;
22
use crate::lua::*;
23

24
#[no_mangle]
UNCOV
25
pub extern "C" fn SCDnsLuaGetTxId(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
26
    let lua = LuaState { lua: clua };
×
UNCOV
27

×
UNCOV
28
    lua.pushinteger(tx.tx_id() as i64);
×
UNCOV
29
    return 1;
×
UNCOV
30
}
×
31

32
#[no_mangle]
UNCOV
33
pub extern "C" fn SCDnsLuaGetRrname(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
34
    let lua = LuaState { lua: clua };
×
35

UNCOV
36
    if let Some(request) = &tx.request {
×
UNCOV
37
        if let Some(query) = request.queries.first() {
×
UNCOV
38
            lua.pushstring(&String::from_utf8_lossy(&query.name.value));
×
UNCOV
39
            return 1;
×
40
        }
×
UNCOV
41
    } else if let Some(response) = &tx.response {
×
UNCOV
42
        if let Some(query) = response.queries.first() {
×
UNCOV
43
            lua.pushstring(&String::from_utf8_lossy(&query.name.value));
×
UNCOV
44
            return 1;
×
45
        }
×
46
    }
×
47

48
    return 0;
×
UNCOV
49
}
×
50

51
#[no_mangle]
UNCOV
52
pub extern "C" fn SCDnsLuaGetRcode(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
53
    let lua = LuaState { lua: clua };
×
UNCOV
54
    lua.pushinteger(tx.rcode() as i64);
×
UNCOV
55
    return 1;
×
UNCOV
56
}
×
57

58
#[no_mangle]
UNCOV
59
pub extern "C" fn SCDnsLuaGetRcodeString(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
60
    let lua = LuaState { lua: clua };
×
UNCOV
61
    lua.pushstring(&dns_rcode_string(tx.rcode()));
×
UNCOV
62
    return 1;
×
UNCOV
63
}
×
64

65
#[no_mangle]
UNCOV
66
pub extern "C" fn SCDnsLuaGetQueryTable(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
67
    let lua = LuaState { lua: clua };
×
UNCOV
68

×
UNCOV
69
    let mut i: i64 = 0;
×
UNCOV
70

×
UNCOV
71
    // Create table now to be consistent with C that always returns
×
UNCOV
72
    // table even in the absence of any authorities.
×
UNCOV
73
    lua.newtable();
×
74

75
    // We first look in the request for queries. However, if there is
76
    // no request, check the response for queries.
UNCOV
77
    if let Some(request) = &tx.request {
×
UNCOV
78
        for query in &request.queries {
×
UNCOV
79
            lua.pushinteger(i);
×
UNCOV
80
            i += 1;
×
UNCOV
81

×
UNCOV
82
            lua.newtable();
×
UNCOV
83

×
UNCOV
84
            lua.pushstring("type");
×
UNCOV
85
            lua.pushstring(&dns_rrtype_string(query.rrtype));
×
UNCOV
86
            lua.settable(-3);
×
UNCOV
87

×
UNCOV
88
            lua.pushstring("rrname");
×
UNCOV
89
            lua.pushstring(&String::from_utf8_lossy(&query.name.value));
×
UNCOV
90
            lua.settable(-3);
×
UNCOV
91

×
UNCOV
92
            lua.settable(-3);
×
UNCOV
93
        }
×
UNCOV
94
    } else if let Some(response) = &tx.response {
×
UNCOV
95
        for query in &response.queries {
×
UNCOV
96
            lua.pushinteger(i);
×
UNCOV
97
            i += 1;
×
UNCOV
98

×
UNCOV
99
            lua.newtable();
×
UNCOV
100

×
UNCOV
101
            lua.pushstring("type");
×
UNCOV
102
            lua.pushstring(&dns_rrtype_string(query.rrtype));
×
UNCOV
103
            lua.settable(-3);
×
UNCOV
104

×
UNCOV
105
            lua.pushstring("rrname");
×
UNCOV
106
            lua.pushstring(&String::from_utf8_lossy(&query.name.value));
×
UNCOV
107
            lua.settable(-3);
×
UNCOV
108

×
UNCOV
109
            lua.settable(-3);
×
UNCOV
110
        }
×
111
    }
×
112

113
    // Again, always return 1 to be consistent with C, even if the
114
    // table is empty.
UNCOV
115
    return 1;
×
UNCOV
116
}
×
117

118
#[no_mangle]
UNCOV
119
pub extern "C" fn SCDnsLuaGetAnswerTable(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int {
×
UNCOV
120
    let lua = LuaState { lua: clua };
×
UNCOV
121

×
UNCOV
122
    let mut i: i64 = 0;
×
UNCOV
123

×
UNCOV
124
    // Create table now to be consistent with C that always returns
×
UNCOV
125
    // table even in the absence of any authorities.
×
UNCOV
126
    lua.newtable();
×
127

UNCOV
128
    if let Some(response) = &tx.response {
×
UNCOV
129
        for answer in &response.answers {
×
UNCOV
130
            lua.pushinteger(i);
×
UNCOV
131
            i += 1;
×
UNCOV
132

×
UNCOV
133
            lua.newtable();
×
UNCOV
134
            lua.pushstring("type");
×
UNCOV
135
            lua.pushstring(&dns_rrtype_string(answer.rrtype));
×
UNCOV
136
            lua.settable(-3);
×
UNCOV
137

×
UNCOV
138
            lua.pushstring("ttl");
×
UNCOV
139
            lua.pushinteger(answer.ttl as i64);
×
UNCOV
140
            lua.settable(-3);
×
UNCOV
141

×
UNCOV
142
            lua.pushstring("rrname");
×
UNCOV
143
            lua.pushstring(&String::from_utf8_lossy(&answer.name.value));
×
UNCOV
144
            lua.settable(-3);
×
UNCOV
145

×
UNCOV
146
            // All rdata types are pushed to "addr" for backwards compatibility
×
UNCOV
147
            match &answer.data {
×
UNCOV
148
                DNSRData::A(ref bytes) | DNSRData::AAAA(ref bytes) => {
×
UNCOV
149
                    if !bytes.is_empty() {
×
UNCOV
150
                        lua.pushstring("addr");
×
UNCOV
151
                        lua.pushstring(&dns_print_addr(bytes));
×
UNCOV
152
                        lua.settable(-3);
×
UNCOV
153
                    }
×
154
                }
UNCOV
155
                DNSRData::CNAME(name)
×
156
                | DNSRData::MX(name)
×
157
                | DNSRData::NS(name)
×
158
                | DNSRData::PTR(name) => {
×
UNCOV
159
                    if !name.value.is_empty() {
×
UNCOV
160
                        lua.pushstring("addr");
×
UNCOV
161
                        lua.pushstring(&String::from_utf8_lossy(&name.value));
×
UNCOV
162
                        lua.settable(-3);
×
UNCOV
163
                    }
×
164
                }
165
                DNSRData::TXT(ref txt) => {
×
166
                    if !txt.is_empty() {
×
167
                        lua.pushstring("addr");
×
168
                        let combined = txt
×
169
                            .iter()
×
170
                            .map(|s| String::from_utf8_lossy(s))
×
171
                            .collect::<Vec<_>>()
×
172
                            .join(" ");
×
173
                        lua.pushstring(&combined);
×
174
                        lua.settable(-3);
×
175
                    }
×
176
                }
177
                DNSRData::NULL(ref bytes)
×
178
                | DNSRData::Unknown(ref bytes) => {
×
179
                    if !bytes.is_empty() {
×
180
                        lua.pushstring("addr");
×
181
                        lua.pushstring(&String::from_utf8_lossy(bytes));
×
182
                        lua.settable(-3);
×
183
                    }
×
184
                }
185
                DNSRData::SOA(ref soa) => {
×
186
                    if !soa.mname.value.is_empty() {
×
187
                        lua.pushstring("addr");
×
188
                        lua.pushstring(&String::from_utf8_lossy(&soa.mname.value));
×
189
                        lua.settable(-3);
×
190
                    }
×
191
                }
192
                DNSRData::SSHFP(ref sshfp) => {
×
193
                    lua.pushstring("addr");
×
194
                    lua.pushstring(&String::from_utf8_lossy(&sshfp.fingerprint));
×
195
                    lua.settable(-3);
×
196
                }
×
197
                DNSRData::SRV(ref srv) => {
×
198
                    lua.pushstring("addr");
×
199
                    lua.pushstring(&String::from_utf8_lossy(&srv.target.value));
×
200
                    lua.settable(-3);
×
201
                }
×
202
                DNSRData::OPT(ref opt) => {
×
203
                    if !opt.is_empty() {
×
204
                        lua.pushstring("addr");
×
205
                        for option in opt.iter() {
×
206
                            lua.pushstring(&String::from_utf8_lossy(&option.code.to_be_bytes()));
×
207
                            lua.pushstring(&String::from_utf8_lossy(&option.data));
×
208
                        }
×
209
                        lua.settable(-3);
×
210
                    }
×
211
                }
212
            }
UNCOV
213
            lua.settable(-3);
×
214
        }
UNCOV
215
    }
×
216

217
    // Again, always return 1 to be consistent with C, even if the
218
    // table is empty.
UNCOV
219
    return 1;
×
UNCOV
220
}
×
221

222
#[no_mangle]
UNCOV
223
pub extern "C" fn SCDnsLuaGetAuthorityTable(
×
UNCOV
224
    clua: &mut CLuaState, tx: &mut DNSTransaction,
×
UNCOV
225
) -> c_int {
×
UNCOV
226
    let lua = LuaState { lua: clua };
×
UNCOV
227

×
UNCOV
228
    let mut i: i64 = 0;
×
UNCOV
229

×
UNCOV
230
    // Create table now to be consistent with C that always returns
×
UNCOV
231
    // table even in the absence of any authorities.
×
UNCOV
232
    lua.newtable();
×
233

UNCOV
234
    if let Some(response) = &tx.response {
×
UNCOV
235
        for answer in &response.authorities {
×
UNCOV
236
            lua.pushinteger(i);
×
UNCOV
237
            i += 1;
×
UNCOV
238

×
UNCOV
239
            lua.newtable();
×
UNCOV
240
            lua.pushstring("type");
×
UNCOV
241
            lua.pushstring(&dns_rrtype_string(answer.rrtype));
×
UNCOV
242
            lua.settable(-3);
×
UNCOV
243

×
UNCOV
244
            lua.pushstring("ttl");
×
UNCOV
245
            lua.pushinteger(answer.ttl as i64);
×
UNCOV
246
            lua.settable(-3);
×
UNCOV
247

×
UNCOV
248
            lua.pushstring("rrname");
×
UNCOV
249
            lua.pushstring(&String::from_utf8_lossy(&answer.name.value));
×
UNCOV
250
            lua.settable(-3);
×
UNCOV
251

×
UNCOV
252
            lua.settable(-3);
×
UNCOV
253
        }
×
UNCOV
254
    }
×
255

256
    // Again, always return 1 to be consistent with C, even if the
257
    // table is empty.
UNCOV
258
    return 1;
×
UNCOV
259
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc