]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust: lua support for DNS based Rust
authorJason Ish <ish@unx.ca>
Mon, 1 May 2017 23:14:08 +0000 (17:14 -0600)
committerJason Ish <ish@unx.ca>
Mon, 5 Jun 2017 20:57:21 +0000 (14:57 -0600)
Uses Rust wrappers around Lua to populate Lua
data structures.

rust/src/dns/log.rs
rust/src/dns/lua.rs [new file with mode: 0644]
rust/src/dns/mod.rs
src/util-lua-dns.c

index 3fe4133c84a5e65c502fc1262ef54661377bad5f..e2440cc243e51bc29c0f6577f3ddbee5934469dc 100644 (file)
@@ -24,7 +24,7 @@ use json::*;
 use dns::dns::*;
 use log::*;
 
-fn dns_rrtype_string(rrtype: u16) -> String {
+pub fn dns_rrtype_string(rrtype: u16) -> String {
     match rrtype {
         DNS_RTYPE_A => "A",
         DNS_RTYPE_CNAME => "CNAME",
@@ -51,7 +51,7 @@ fn dns_rcode_string(flags: u16) -> String {
 }
 
 /// Format bytes as an IP address string.
-fn dns_print_addr(addr: &Vec<u8>) -> std::string::String {
+pub fn dns_print_addr(addr: &Vec<u8>) -> std::string::String {
     if addr.len() == 4 {
         return format!("{}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]);
     }
diff --git a/rust/src/dns/lua.rs b/rust/src/dns/lua.rs
new file mode 100644 (file)
index 0000000..bcd7a7c
--- /dev/null
@@ -0,0 +1,203 @@
+/* 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 lua::*;
+use dns::dns::*;
+use dns::log::*;
+
+#[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,
+    };
+
+    for request in &tx.request {
+        for query in &request.queries {
+            lua.pushstring(query.name());
+            return 1;
+        }
+    }
+
+    for response in &tx.response {
+        for query in &response.queries {
+            lua.pushstring(query.name());
+            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;
+
+    for request in &tx.request {
+
+        if request.queries.len() == 0 {
+            break;
+        }
+
+        lua.newtable();
+
+        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(query.name());
+            lua.settable(-3);
+
+            lua.settable(-3);
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
+
+#[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;
+
+    for response in &tx.response {
+
+        if response.answers.len() == 0 {
+            break;
+        }
+
+        lua.newtable();
+
+        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(answer.name());
+            lua.settable(-3);
+
+            if answer.data.len() > 0 {
+                lua.pushstring("addr");
+                match answer.rrtype {
+                    DNS_RTYPE_A | DNS_RTYPE_AAAA => {
+                        lua.pushstring(&dns_print_addr(&answer.data));
+                    }
+                    _ => {
+                        lua.pushstring(answer.data_to_string());
+                    }
+                }
+                lua.settable(-3);
+            }
+            lua.settable(-3);
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
+
+#[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;
+
+    for response in &tx.response {
+
+        if response.authorities.len() == 0 {
+            break;
+        }
+
+        lua.newtable();
+
+        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(answer.name());
+            lua.settable(-3);
+
+            lua.settable(-3);
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
index d6693b0a9ad2aad1fbe75718775d603c060ad60a..5da27124fbc95da4551cb0ea943da33000764af3 100644 (file)
@@ -18,3 +18,6 @@
 pub mod parser;
 pub mod dns;
 pub mod log;
+
+#[cfg(feature = "lua")]
+pub mod lua;
index 761b1f7c9a8f7e109c0956de98dbe0746a8173dd..c1fe6533c02c39af82c06813940de224ae00fb4f 100644 (file)
@@ -60,6 +60,7 @@
 
 #ifdef HAVE_RUST
 #include "rust-dns-dns-gen.h"
+#include "rust-dns-lua-gen.h"
 #endif
 
 static int DnsGetDnsRrname(lua_State *luastate)
@@ -68,31 +69,10 @@ static int DnsGetDnsRrname(lua_State *luastate)
         return LuaCallbackError(luastate, "error: protocol not dns");
 #ifdef HAVE_RUST
     RSDNSTransaction *tx = LuaStateGetTX(luastate);
-    if (tx == NULL)
+    if (tx == NULL) {
         return LuaCallbackError(luastate, "internal error: no tx");
-
-    for (uint16_t i = 0;; i++) {
-        uint32_t buf_len;
-        uint8_t *buf;
-
-        if (!rs_dns_tx_get_query_name(tx, i, &buf, &buf_len)) {
-            break;
-        }
-
-        char *rrname = BytesToString(buf, buf_len);
-        if (rrname != NULL) {
-            size_t input_len = strlen(rrname);
-            /* sanity check */
-            if (input_len > (size_t)(2 * buf_len)) {
-                SCFree(rrname);
-                return LuaCallbackError(luastate, "invalid length");
-            }
-            int ret = LuaPushStringBuffer(luastate, (uint8_t *)rrname,
-                input_len);
-            SCFree(rrname);
-            return ret;
-        }
     }
+    return rs_dns_lua_get_rrname(luastate, tx);
 #else
     DNSTransaction *tx = LuaStateGetTX(luastate);
     if (tx == NULL)
@@ -126,10 +106,10 @@ static int DnsGetTxid(lua_State *luastate)
         return LuaCallbackError(luastate, "error: protocol not dns");
 #ifdef HAVE_RUST
     RSDNSTransaction *tx = LuaStateGetTX(luastate);
-    if (tx == NULL)
+    if (tx == NULL) {
         return LuaCallbackError(luastate, "internal error: no tx");
-    uint16_t tx_id = rs_dns_tx_get_tx_id(tx);
-    lua_pushinteger(luastate, tx_id);
+    }
+    rs_dns_lua_get_tx_id(luastate, tx);
 #else
     DNSTransaction *tx = LuaStateGetTX(luastate);
     if (tx == NULL)
@@ -173,12 +153,11 @@ static int DnsGetRecursionDesired(lua_State *luastate)
         return LuaCallbackError(luastate, "error: protocol not dns");
 #ifdef HAVE_RUST
     RSDNSTransaction *tx = LuaStateGetTX(luastate);
-    if (tx == NULL)
+    if (tx == NULL) {
         return LuaCallbackError(luastate, "internal error: no tx");
-
+    }
     uint16_t flags = rs_dns_tx_get_response_flags(tx);
     int recursion_desired = flags & 0x0080 ? 1 : 0;
-
     lua_pushboolean(luastate, recursion_desired);
 #else
     DNSTransaction *tx = LuaStateGetTX(luastate);
@@ -192,59 +171,15 @@ static int DnsGetRecursionDesired(lua_State *luastate)
 
 static int DnsGetQueryTable(lua_State *luastate)
 {
-#ifdef HAVE_RUST
     if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
         return LuaCallbackError(luastate, "error: protocol not dns");
-
+#ifdef HAVE_RUST
     RSDNSTransaction *tx = LuaStateGetTX(luastate);
-    if (tx == NULL)
+    if (tx == NULL) {
         return LuaCallbackError(luastate, "internal error: no tx");
-
-    lua_newtable(luastate);
-
-    uint8_t *name;
-    uint32_t name_len;
-
-    for (uint16_t i = 0;; i++) {
-
-        if (!rs_dns_tx_get_query_name(tx, i, &name, &name_len)) {
-            break;
-        }
-
-        lua_pushinteger(luastate, i);
-        lua_newtable(luastate);
-
-        uint16_t rrtype;
-        if (rs_dns_tx_get_query_rrtype(tx, i, &rrtype)) {
-            char s_rrtype[16] = "";
-            DNSCreateTypeString(rrtype, s_rrtype, sizeof(s_rrtype));
-            lua_pushstring(luastate, "type");
-            lua_pushstring(luastate, s_rrtype);
-            lua_settable(luastate, -3);
-        }
-
-        char *s = BytesToString(name, name_len);
-        if (s != NULL) {
-            size_t slen = strlen(s);
-            if (slen > name_len * 2) {
-                SCFree(s);
-                return LuaCallbackError(luastate, "invalid length");
-            }
-            lua_pushstring(luastate, "rrname");
-            LuaPushStringBuffer(luastate, (uint8_t *)s, slen);
-            lua_settable(luastate, -3);
-            SCFree(s);
-        }
-
-        lua_pushinteger(luastate, i++);
-
     }
-
-    return 1;
+    return rs_dns_lua_get_query_table(luastate, tx);
 #else
-    if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
-        return LuaCallbackError(luastate, "error: protocol not dns");
-
     DNSTransaction *tx = LuaStateGetTX(luastate);
     if (tx == NULL)
         return LuaCallbackError(luastate, "internal error: no tx");
@@ -290,13 +225,12 @@ static int DnsGetQueryTable(lua_State *luastate)
 
 static int DnsGetAnswerTable(lua_State *luastate)
 {
-#ifdef HAVE_RUST
-    SCLogNotice("DnsGetAnswerTable not implemented for Rust DNS.");
-    return 1;
-#else
     if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
         return LuaCallbackError(luastate, "error: protocol not dns");
-
+#ifdef HAVE_RUST
+    RSDNSTransaction *tx = LuaStateGetTX(luastate);
+    return rs_dns_lua_get_answer_table(luastate, tx);
+#else
     DNSTransaction *tx = LuaStateGetTX(luastate);
     if (tx == NULL)
         return LuaCallbackError(luastate, "internal error: no tx");
@@ -359,13 +293,12 @@ static int DnsGetAnswerTable(lua_State *luastate)
 
 static int DnsGetAuthorityTable(lua_State *luastate)
 {
-#ifdef HAVE_RUST
-    SCLogNotice("DnsGetAuthorityTable not implemented for Rust DNS");
-    return 1;
-#else
     if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
         return LuaCallbackError(luastate, "error: protocol not dns");
-
+#ifdef HAVE_RUST
+    RSDNSTransaction *tx = LuaStateGetTX(luastate);
+    return rs_dns_lua_get_authority_table(luastate, tx);
+#else
     DNSTransaction *tx = LuaStateGetTX(luastate);
     if (tx == NULL)
         return LuaCallbackError(luastate, "internal error: no tx");