diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/src/dns/lua.rs | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/src/dns/lua.rs')
-rw-r--r-- | rust/src/dns/lua.rs | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/rust/src/dns/lua.rs b/rust/src/dns/lua.rs new file mode 100644 index 0000000..b9935f8 --- /dev/null +++ b/rust/src/dns/lua.rs @@ -0,0 +1,234 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use std::os::raw::c_int; + +use crate::dns::dns::*; +use crate::dns::log::*; +use crate::lua::*; + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_tx_id(clua: &mut CLuaState, tx: &mut DNSTransaction) { + let lua = LuaState { lua: clua }; + + lua.pushinteger(tx.tx_id() as i64); +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_rrname(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int { + let lua = LuaState { lua: clua }; + + if let Some(request) = &tx.request { + if let Some(query) = request.queries.first() { + lua.pushstring(&String::from_utf8_lossy(&query.name)); + return 1; + } + } else if let Some(response) = &tx.response { + if let Some(query) = response.queries.first() { + lua.pushstring(&String::from_utf8_lossy(&query.name)); + return 1; + } + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_rcode(clua: &mut CLuaState, tx: &mut DNSTransaction) -> c_int { + let lua = LuaState { lua: clua }; + + let rcode = tx.rcode(); + if rcode > 0 { + lua.pushstring(&dns_rcode_string(rcode)); + return 1; + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_query_table( + clua: &mut CLuaState, tx: &mut DNSTransaction, +) -> c_int { + let lua = LuaState { lua: clua }; + + let mut i: i64 = 0; + + // Create table now to be consistent with C that always returns + // table even in the absence of any authorities. + lua.newtable(); + + // We first look in the request for queries. However, if there is + // no request, check the response for queries. + if let Some(request) = &tx.request { + for query in &request.queries { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(query.rrtype)); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(&String::from_utf8_lossy(&query.name)); + lua.settable(-3); + + lua.settable(-3); + } + } else if let Some(response) = &tx.response { + for query in &response.queries { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(query.rrtype)); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(&String::from_utf8_lossy(&query.name)); + lua.settable(-3); + + lua.settable(-3); + } + } + + // Again, always return 1 to be consistent with C, even if the + // table is empty. + return 1; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_answer_table( + clua: &mut CLuaState, tx: &mut DNSTransaction, +) -> c_int { + let lua = LuaState { lua: clua }; + + let mut i: i64 = 0; + + // Create table now to be consistent with C that always returns + // table even in the absence of any authorities. + lua.newtable(); + + if let Some(response) = &tx.response { + for answer in &response.answers { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(answer.rrtype)); + lua.settable(-3); + + lua.pushstring("ttl"); + lua.pushinteger(answer.ttl as i64); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(&String::from_utf8_lossy(&answer.name)); + lua.settable(-3); + + // All rdata types are pushed to "addr" for backwards compatibility + match answer.data { + DNSRData::A(ref bytes) | DNSRData::AAAA(ref bytes) => { + if !bytes.is_empty() { + lua.pushstring("addr"); + lua.pushstring(&dns_print_addr(bytes)); + lua.settable(-3); + } + } + DNSRData::CNAME(ref bytes) + | DNSRData::MX(ref bytes) + | DNSRData::NS(ref bytes) + | DNSRData::TXT(ref bytes) + | DNSRData::NULL(ref bytes) + | DNSRData::PTR(ref bytes) + | DNSRData::Unknown(ref bytes) => { + if !bytes.is_empty() { + lua.pushstring("addr"); + lua.pushstring(&String::from_utf8_lossy(bytes)); + lua.settable(-3); + } + } + DNSRData::SOA(ref soa) => { + if !soa.mname.is_empty() { + lua.pushstring("addr"); + lua.pushstring(&String::from_utf8_lossy(&soa.mname)); + lua.settable(-3); + } + } + DNSRData::SSHFP(ref sshfp) => { + lua.pushstring("addr"); + lua.pushstring(&String::from_utf8_lossy(&sshfp.fingerprint)); + lua.settable(-3); + } + DNSRData::SRV(ref srv) => { + lua.pushstring("addr"); + lua.pushstring(&String::from_utf8_lossy(&srv.target)); + lua.settable(-3); + } + } + lua.settable(-3); + } + } + + // Again, always return 1 to be consistent with C, even if the + // table is empty. + return 1; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_authority_table( + clua: &mut CLuaState, tx: &mut DNSTransaction, +) -> c_int { + let lua = LuaState { lua: clua }; + + let mut i: i64 = 0; + + // Create table now to be consistent with C that always returns + // table even in the absence of any authorities. + lua.newtable(); + + if let Some(response) = &tx.response { + for answer in &response.authorities { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(answer.rrtype)); + lua.settable(-3); + + lua.pushstring("ttl"); + lua.pushinteger(answer.ttl as i64); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(&String::from_utf8_lossy(&answer.name)); + lua.settable(-3); + + lua.settable(-3); + } + } + + // Again, always return 1 to be consistent with C, even if the + // table is empty. + return 1; +} |