summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-03-13 07:54:12 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-03-13 07:54:12 +0000
commit4754ed45b607e82450a5e31fea1da3ba61433b04 (patch)
tree3554490bdc003e6004f605abe41929cdf98b0651 /src/core
parentInitial commit. (diff)
downloaddnsjit-4754ed45b607e82450a5e31fea1da3ba61433b04.tar.xz
dnsjit-4754ed45b607e82450a5e31fea1da3ba61433b04.zip
Adding upstream version 1.1.0+debian.upstream/1.1.0+debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/assert.h46
-rw-r--r--src/core/channel.c169
-rw-r--r--src/core/channel.h41
-rw-r--r--src/core/channel.hh49
-rw-r--r--src/core/channel.lua142
-rw-r--r--src/core/compat.c25
-rw-r--r--src/core/compat.h32
-rw-r--r--src/core/compat.lua41
-rw-r--r--src/core/log.c399
-rw-r--r--src/core/log.h105
-rw-r--r--src/core/log.hh44
-rw-r--r--src/core/log.lua639
-rw-r--r--src/core/object.c135
-rw-r--r--src/core/object.h51
-rw-r--r--src/core/object.hh28
-rw-r--r--src/core/object.lua177
-rw-r--r--src/core/object/dns.c471
-rw-r--r--src/core/object/dns.h184
-rw-r--r--src/core/object/dns.hh119
-rw-r--r--src/core/object/dns.lua797
-rw-r--r--src/core/object/dns/label.lua118
-rw-r--r--src/core/object/dns/q.lua52
-rw-r--r--src/core/object/dns/rr.lua85
-rw-r--r--src/core/object/ether.c45
-rw-r--r--src/core/object/ether.h38
-rw-r--r--src/core/object/ether.hh33
-rw-r--r--src/core/object/ether.lua78
-rw-r--r--src/core/object/gre.c45
-rw-r--r--src/core/object/gre.h38
-rw-r--r--src/core/object/gre.hh37
-rw-r--r--src/core/object/gre.lua87
-rw-r--r--src/core/object/icmp.c45
-rw-r--r--src/core/object/icmp.h38
-rw-r--r--src/core/object/icmp.hh33
-rw-r--r--src/core/object/icmp.lua78
-rw-r--r--src/core/object/icmp6.c45
-rw-r--r--src/core/object/icmp6.h38
-rw-r--r--src/core/object/icmp6.hh33
-rw-r--r--src/core/object/icmp6.lua78
-rw-r--r--src/core/object/ieee802.c45
-rw-r--r--src/core/object/ieee802.h38
-rw-r--r--src/core/object/ieee802.hh35
-rw-r--r--src/core/object/ieee802.lua84
-rw-r--r--src/core/object/ip.c45
-rw-r--r--src/core/object/ip.h38
-rw-r--r--src/core/object/ip.hh40
-rw-r--r--src/core/object/ip.lua122
-rw-r--r--src/core/object/ip6.c45
-rw-r--r--src/core/object/ip6.h42
-rw-r--r--src/core/object/ip6.hh42
-rw-r--r--src/core/object/ip6.lua130
-rw-r--r--src/core/object/linuxsll.c45
-rw-r--r--src/core/object/linuxsll.h38
-rw-r--r--src/core/object/linuxsll.hh35
-rw-r--r--src/core/object/linuxsll.lua84
-rw-r--r--src/core/object/loop.c45
-rw-r--r--src/core/object/loop.h38
-rw-r--r--src/core/object/loop.hh31
-rw-r--r--src/core/object/loop.lua72
-rw-r--r--src/core/object/null.c45
-rw-r--r--src/core/object/null.h38
-rw-r--r--src/core/object/null.hh31
-rw-r--r--src/core/object/null.lua72
-rw-r--r--src/core/object/payload.c50
-rw-r--r--src/core/object/payload.h38
-rw-r--r--src/core/object/payload.hh32
-rw-r--r--src/core/object/payload.lua83
-rw-r--r--src/core/object/pcap.c50
-rw-r--r--src/core/object/pcap.h38
-rw-r--r--src/core/object/pcap.hh38
-rw-r--r--src/core/object/pcap.lua98
-rw-r--r--src/core/object/tcp.c45
-rw-r--r--src/core/object/tcp.h39
-rw-r--r--src/core/object/tcp.hh43
-rw-r--r--src/core/object/tcp.lua110
-rw-r--r--src/core/object/udp.c45
-rw-r--r--src/core/object/udp.h38
-rw-r--r--src/core/object/udp.hh34
-rw-r--r--src/core/object/udp.lua86
-rw-r--r--src/core/objects.lua61
-rw-r--r--src/core/producer.c23
-rw-r--r--src/core/producer.h28
-rw-r--r--src/core/producer.hh23
-rw-r--r--src/core/producer.lua28
-rw-r--r--src/core/receiver.c23
-rw-r--r--src/core/receiver.h28
-rw-r--r--src/core/receiver.hh23
-rw-r--r--src/core/receiver.lua28
-rw-r--r--src/core/thread.c229
-rw-r--r--src/core/thread.h31
-rw-r--r--src/core/thread.hh56
-rw-r--r--src/core/thread.lua141
-rw-r--r--src/core/timespec.h33
-rw-r--r--src/core/timespec.hh24
-rw-r--r--src/core/timespec.lua32
95 files changed, 7696 insertions, 0 deletions
diff --git a/src/core/assert.h b/src/core/assert.h
new file mode 100644
index 0000000..3f2f503
--- /dev/null
+++ b/src/core/assert.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __dnsjit_core_assert_h
+#define __dnsjit_core_assert_h
+
+#include "core/log.h"
+
+#define mlassert_self() \
+ if (!self) \
+ core_log_fatal(&_log, __FILE__, __LINE__, "self is nil")
+#define glassert_self() \
+ if (!self) \
+ core_log_fatal(0, __FILE__, __LINE__, "self is nil")
+
+#define lassert(expression, msg...) \
+ if (!(expression)) \
+ core_log_fatal(&self->_log, __FILE__, __LINE__, msg)
+#define lpassert(expression, msg...) \
+ if (!(expression)) \
+ core_log_fatal(self->_log, __FILE__, __LINE__, msg)
+#define mlassert(expression, msg...) \
+ if (!(expression)) \
+ core_log_fatal(&_log, __FILE__, __LINE__, msg)
+#define glassert(expression, msg...) \
+ if (!(expression)) \
+ core_log_fatal(0, __FILE__, __LINE__, msg)
+
+#endif
diff --git a/src/core/channel.c b/src/core/channel.c
new file mode 100644
index 0000000..691ad1a
--- /dev/null
+++ b/src/core/channel.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/channel.h"
+#include "core/assert.h"
+
+#include <sched.h>
+
+static core_log_t _log = LOG_T_INIT("core.channel");
+static core_channel_t _defaults = {
+ LOG_T_INIT_OBJ("core.channel"),
+ 0, { 0 }, 0, 0,
+ 0, 0
+};
+
+core_log_t* core_channel_log()
+{
+ return &_log;
+}
+
+static inline bool _is_pow2(size_t num)
+{
+ while (num != 1) {
+ if (num % 2 != 0)
+ return false;
+ num = num / 2;
+ }
+ return true;
+}
+
+void core_channel_init(core_channel_t* self, size_t capacity)
+{
+ mlassert_self();
+ if (capacity < 4 || !_is_pow2(capacity)) {
+ mlfatal("invalid capacity");
+ }
+
+ *self = _defaults;
+ self->capacity = capacity;
+
+ lfatal_oom(self->ring_buf = malloc(sizeof(ck_ring_buffer_t) * capacity));
+ ck_ring_init(&self->ring, capacity);
+}
+
+void core_channel_destroy(core_channel_t* self)
+{
+ mlassert_self();
+ free(self->ring_buf);
+}
+
+void core_channel_put(core_channel_t* self, const void* obj)
+{
+ mlassert_self();
+ lassert(self->ring_buf, "ring_buf is nil");
+
+ while (!ck_ring_enqueue_spsc(&self->ring, self->ring_buf, (void*)obj)) {
+ sched_yield();
+ }
+}
+
+int core_channel_try_put(core_channel_t* self, const void* obj)
+{
+ mlassert_self();
+ lassert(self->ring_buf, "ring_buf is nil");
+
+ if (!ck_ring_enqueue_spsc(&self->ring, self->ring_buf, (void*)obj)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void* core_channel_get(core_channel_t* self)
+{
+ void* obj = 0;
+ mlassert_self();
+ lassert(self->ring_buf, "ring_buf is nil");
+
+ while (!ck_ring_dequeue_spsc(&self->ring, self->ring_buf, &obj)) {
+ sched_yield();
+ if (ck_pr_load_int(&self->closed)) {
+ linfo("channel closed");
+ return 0;
+ }
+ }
+
+ return obj;
+}
+
+void* core_channel_try_get(core_channel_t* self)
+{
+ void* obj = 0;
+ mlassert_self();
+ lassert(self->ring_buf, "ring_buf is nil");
+
+ if (!ck_ring_dequeue_spsc(&self->ring, self->ring_buf, &obj)) {
+ return 0;
+ }
+
+ return obj;
+}
+
+int core_channel_size(core_channel_t* self)
+{
+ mlassert_self();
+ return ck_ring_size(&self->ring);
+}
+
+bool core_channel_full(core_channel_t* self)
+{
+ mlassert_self();
+
+ /* ck_ring can only hold capacity minus one enties at a time */
+ if (ck_ring_size(&self->ring) < (self->capacity - 1)) {
+ return false;
+ }
+ return true;
+}
+
+void core_channel_close(core_channel_t* self)
+{
+ mlassert_self();
+ ck_pr_store_int(&self->closed, 1);
+}
+
+core_receiver_t core_channel_receiver()
+{
+ return (core_receiver_t)core_channel_put;
+}
+
+void core_channel_run(core_channel_t* self)
+{
+ void* obj = 0;
+ mlassert_self();
+ lassert(self->ring_buf, "ring_buf is nil");
+ if (!self->recv) {
+ lfatal("no receiver set");
+ }
+
+ for (;;) {
+ while (!ck_ring_dequeue_spsc(&self->ring, self->ring_buf, &obj)) {
+ sched_yield();
+ if (ck_pr_load_int(&self->closed)) {
+ linfo("channel closed");
+ return;
+ }
+ }
+ self->recv(self->ctx, obj);
+ }
+}
diff --git a/src/core/channel.h b/src/core/channel.h
new file mode 100644
index 0000000..75e84ac
--- /dev/null
+++ b/src/core/channel.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/log.h"
+#include "core/receiver.h"
+
+#ifndef __dnsjit_core_channel_h
+#define __dnsjit_core_channel_h
+
+#if defined(__GNUC__) || defined(__SUNPRO_C)
+#include "gcc/ck_cc.h"
+#ifdef CK_CC_RESTRICT
+#undef CK_CC_RESTRICT
+#define CK_CC_RESTRICT __restrict__
+#endif
+#endif
+
+#include <ck_ring.h>
+#include <ck_pr.h>
+#include <stdbool.h>
+
+#include "core/channel.hh"
+
+#endif
diff --git a/src/core/channel.hh b/src/core/channel.hh
new file mode 100644
index 0000000..e6ec0e0
--- /dev/null
+++ b/src/core/channel.hh
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.compat_h")
+//lua:require("dnsjit.core.log")
+//lua:require("dnsjit.core.receiver_h")
+
+typedef struct core_channel {
+ core_log_t _log;
+ ck_ring_buffer_t* ring_buf;
+ ck_ring_t ring;
+ int closed;
+ size_t capacity;
+
+ core_receiver_t recv;
+ void* ctx;
+} core_channel_t;
+
+core_log_t* core_channel_log();
+
+void core_channel_init(core_channel_t* self, size_t capacity);
+void core_channel_destroy(core_channel_t* self);
+void core_channel_put(core_channel_t* self, const void* obj);
+int core_channel_try_put(core_channel_t* self, const void* obj);
+void* core_channel_get(core_channel_t* self);
+void* core_channel_try_get(core_channel_t* self);
+int core_channel_size(core_channel_t* self);
+bool core_channel_full(core_channel_t* self);
+void core_channel_close(core_channel_t* self);
+
+core_receiver_t core_channel_receiver();
+void core_channel_run(core_channel_t* self);
diff --git a/src/core/channel.lua b/src/core/channel.lua
new file mode 100644
index 0000000..b837cc4
--- /dev/null
+++ b/src/core/channel.lua
@@ -0,0 +1,142 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.channel
+-- Send data to another thread
+-- local chan = require("dnsjit.core.channel").new()
+-- local thr = require("dnsjit.core.thread").new()
+-- thr:start(function(thr)
+-- local chan = thr:pop()
+-- local obj = chan:get()
+-- ...
+-- end)
+-- thr:push(chan)
+-- chan:put(...)
+-- chan:close()
+-- thr:stop()
+--
+-- A channel can be used to send data to another thread, this is done by
+-- putting a pointer to the data into a wait-free and lock-free ring buffer
+-- (concurrency kit).
+-- The channel uses the single producer, single consumer model (SPSC) so
+-- there can only be one writer and one reader.
+-- .SS Attributes
+-- .TP
+-- int closed
+-- Is 1 if the channel has been closed.
+module(...,package.seeall)
+
+require("dnsjit.core.channel_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_channel_t"
+local core_channel_t
+local Channel = {}
+
+-- Create a new Channel, use the optional
+-- .I capacity
+-- to specify the capacity of the channel (buffer).
+-- Capacity must be a power-of-two greater than or equal to 4.
+-- Default capacity is 2048.
+function Channel.new(capacity)
+ if capacity == nil then
+ capacity = 2048
+ end
+ local self = core_channel_t()
+ C.core_channel_init(self, capacity)
+ ffi.gc(self, C.core_channel_destroy)
+ return self
+end
+
+-- Return the Log object to control logging of this instance or module.
+function Channel:log()
+ if self == nil then
+ return C.core_channel_log()
+ end
+ return self._log
+end
+
+-- Return information to use when sharing this object between threads.
+function Channel:share()
+ return ffi.cast("void*", self), t_name.."*", "dnsjit.core.channel"
+end
+
+-- Put an object into the channel, if the channel is full then it will
+-- stall and wait until space becomes available.
+-- Object may be nil.
+function Channel:put(obj)
+ C.core_channel_put(self, obj)
+end
+
+-- Try and put an object into the channel.
+-- Returns 0 on success.
+function Channel:put(obj)
+ C.core_channel_try_put(self, obj)
+end
+
+-- Get an object from the channel, if the channel is empty it will wait until
+-- an object is available.
+-- Returns nil if the channel is closed or if a nil object was explicitly put
+-- into the channel.
+function Channel:get()
+ return C.core_channel_get(self)
+end
+
+-- Try and get an object from the channel.
+-- Returns nil if there was no objects to get.
+function Channel:try_get()
+ return C.core_channel_try_get(self)
+end
+
+-- Return number of enqueued objects.
+function Channel:size()
+ return C.core_channel_size(self)
+end
+
+-- Returns true when channel is full.
+function Channel:full()
+ return C.core_channel_full(self)
+end
+
+-- Close the channel.
+function Channel:close()
+ C.core_channel_close(self)
+end
+
+-- Return the C functions and context for receiving objects.
+function Channel:receive()
+ return C.core_channel_receiver(), self
+end
+
+-- Set the receiver to pass objects to.
+-- NOTE; The channel keeps no reference of the receiver, it needs to live as
+-- long as the channel does.
+function Channel:receiver(o)
+ self.recv, self.ctx = o:receive()
+end
+
+-- Retrieve all objects from the channel and send it to the receiver.
+function Channel:run()
+ C.core_channel_run(self)
+end
+
+core_channel_t = ffi.metatype(t_name, { __index = Channel })
+
+-- dnsjit.core.thread (3)
+return Channel
diff --git a/src/core/compat.c b/src/core/compat.c
new file mode 100644
index 0000000..9f2be98
--- /dev/null
+++ b/src/core/compat.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "core/compat.hh"
diff --git a/src/core/compat.h b/src/core/compat.h
new file mode 100644
index 0000000..c9486c3
--- /dev/null
+++ b/src/core/compat.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __dnsjit_core_compat_h
+#define __dnsjit_core_compat_h
+
+#include <unistd.h>
+
+#ifdef __ssize_t_defined
+typedef ssize_t luajit_ssize_t;
+#else
+typedef long luajit_ssize_t;
+#endif
+
+#endif
diff --git a/src/core/compat.lua b/src/core/compat.lua
new file mode 100644
index 0000000..bb6d45c
--- /dev/null
+++ b/src/core/compat.lua
@@ -0,0 +1,41 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.compat
+-- Cross platform compatibility support
+-- require("dnsjit.core.compat_h")
+--
+-- This module defines various system structures so they can be exposed into
+-- Lua but not really used. The size is generated at compile time to match
+-- that of the structures on the platform.
+-- .SS Structures
+-- .TP
+-- pthread_t
+-- .TP
+-- pthread_cond_t
+-- .TP
+-- pthread_mutex_t
+-- .TP
+-- struct sockaddr_storage
+-- .TP
+-- ck_ring_t
+-- .TP
+-- ck_ring_buffer_t
+module(...,package.seeall)
+
+require("dnsjit.core.compat_h")
diff --git a/src/core/log.c b/src/core/log.c
new file mode 100644
index 0000000..a334e8e
--- /dev/null
+++ b/src/core/log.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/log.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+static core_log_t _log = LOG_T_INIT("core");
+
+void core_log_debug(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ if (!l) {
+ if (_log.settings.debug != 3) {
+ return;
+ }
+ } else {
+ if (l->settings.debug) {
+ if (l->settings.debug != 3) {
+ return;
+ }
+ } else if (l->module && l->module->debug) {
+ if (l->module->debug != 3) {
+ return;
+ }
+ } else if (_log.settings.debug != 3) {
+ return;
+ }
+ }
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] debug: %s\n", file, line, l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s debug: %s\n", file, line, l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s debug: %s\n", file, line, _log.name, buf);
+ return;
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] debug: %s\n", l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s debug: %s\n", l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s debug: %s\n", _log.name, buf);
+}
+
+void core_log_info(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ if (!l) {
+ if (_log.settings.info != 3) {
+ return;
+ }
+ } else {
+ if (l->settings.info) {
+ if (l->settings.info != 3) {
+ return;
+ }
+ } else if (l->module && l->module->info) {
+ if (l->module->info != 3) {
+ return;
+ }
+ } else if (_log.settings.info != 3) {
+ return;
+ }
+ }
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] info: %s\n", file, line, l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s info: %s\n", file, line, l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s info: %s\n", file, line, _log.name, buf);
+ return;
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] info: %s\n", l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s info: %s\n", l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s info: %s\n", _log.name, buf);
+}
+
+void core_log_notice(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ if (!l) {
+ if (_log.settings.notice != 3) {
+ return;
+ }
+ } else {
+ if (l->settings.notice) {
+ if (l->settings.notice != 3) {
+ return;
+ }
+ } else if (l->module && l->module->notice) {
+ if (l->module->notice != 3) {
+ return;
+ }
+ } else if (_log.settings.notice != 3) {
+ return;
+ }
+ }
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] notice: %s\n", file, line, l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s notice: %s\n", file, line, l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s notice: %s\n", file, line, _log.name, buf);
+ return;
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] notice: %s\n", l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s notice: %s\n", l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s notice: %s\n", _log.name, buf);
+}
+
+void core_log_warning(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ if (!l) {
+ if (_log.settings.warning != 3) {
+ return;
+ }
+ } else {
+ if (l->settings.warning) {
+ if (l->settings.warning != 3) {
+ return;
+ }
+ } else if (l->module && l->module->warning) {
+ if (l->module->warning != 3) {
+ return;
+ }
+ } else if (_log.settings.warning != 3) {
+ return;
+ }
+ }
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] warning: %s\n", file, line, l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s warning: %s\n", file, line, l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s warning: %s\n", file, line, _log.name, buf);
+ return;
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] warning: %s\n", l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s warning: %s\n", l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s warning: %s\n", _log.name, buf);
+}
+
+void core_log_critical(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] critical: %s\n", file, line, l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s critical: %s\n", file, line, l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s[%zu] %s critical: %s\n", file, line, _log.name, buf);
+ return;
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] critical: %s\n", l->name, l, buf);
+ return;
+ }
+ fprintf(stderr, "%s critical: %s\n", l->name, buf);
+ return;
+ }
+ fprintf(stderr, "%s critical: %s\n", _log.name, buf);
+}
+
+void core_log_fatal(const core_log_t* l, const char* file, size_t line, const char* msg, ...)
+{
+ char buf[512];
+ va_list ap;
+ va_start(ap, msg);
+ vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = 0;
+ for (;;) {
+ if (!l) {
+ if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ } else {
+ if (l->settings.display_file_line) {
+ if (l->settings.display_file_line != 3) {
+ break;
+ }
+ } else if (l->module && l->module->display_file_line) {
+ if (l->module->display_file_line != 3) {
+ break;
+ }
+ } else if (_log.settings.display_file_line != 3) {
+ break;
+ }
+ }
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%zu] %s[%p] fatal: %s\n", file, line, l->name, l, buf);
+ exit(1);
+ }
+ fprintf(stderr, "%s[%zu] %s fatal: %s\n", file, line, l->name, buf);
+ exit(1);
+ }
+ fprintf(stderr, "%s[%zu] %s fatal: %s\n", file, line, _log.name, buf);
+ exit(1);
+ }
+
+ if (l) {
+ if (l->is_obj) {
+ fprintf(stderr, "%s[%p] fatal: %s\n", l->name, l, buf);
+ exit(1);
+ }
+ fprintf(stderr, "%s fatal: %s\n", l->name, buf);
+ exit(1);
+ }
+ fprintf(stderr, "%s fatal: %s\n", _log.name, buf);
+ exit(1);
+}
+
+core_log_t* core_log_log()
+{
+ return &_log;
+}
+
+#include "core/log_errstr.c"
diff --git a/src/core/log.h b/src/core/log.h
new file mode 100644
index 0000000..d17c733
--- /dev/null
+++ b/src/core/log.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __dnsjit_core_log_h
+#define __dnsjit_core_log_h
+
+#include <stdlib.h>
+#include <errno.h>
+#include <stdint.h>
+
+#define LOG_SETTINGS_T_INIT \
+ { \
+ 0, 0, 0, 0, 0 \
+ }
+#define LOG_T_INIT(name) \
+ { \
+ name, 0, LOG_SETTINGS_T_INIT, 0 \
+ }
+#define LOG_T_INIT_OBJ(name) \
+ { \
+ name, 1, LOG_SETTINGS_T_INIT, &_log.settings \
+ }
+
+#include "core/log.hh"
+
+#ifdef DNSJIT_NO_LOGGING
+#define ldebug(msg...)
+#define linfo(msg...)
+#define lnotice(msg...)
+#define lwarning(msg...)
+#define lcritical(msg...)
+#define lpdebug(msg...)
+#define lpinfo(msg...)
+#define lpnotice(msg...)
+#define lpwarning(msg...)
+#define lpcritical(msg...)
+#define mldebug(msg...)
+#define mlinfo(msg...)
+#define mlnotice(msg...)
+#define mlwarning(msg...)
+#define mlcritical(msg...)
+#define gldebug(msg...)
+#define glinfo(msg...)
+#define glnotice(msg...)
+#define glwarning(msg...)
+#define glcritical(msg...)
+#else
+#define ldebug(msg...) core_log_debug(&self->_log, __FILE__, __LINE__, msg)
+#define linfo(msg...) core_log_info(&self->_log, __FILE__, __LINE__, msg)
+#define lnotice(msg...) core_log_notice(&self->_log, __FILE__, __LINE__, msg)
+#define lwarning(msg...) core_log_warning(&self->_log, __FILE__, __LINE__, msg)
+#define lcritical(msg...) core_log_critical(&self->_log, __FILE__, __LINE__, msg)
+#define lpdebug(msg...) core_log_debug(self->_log, __FILE__, __LINE__, msg)
+#define lpinfo(msg...) core_log_info(self->_log, __FILE__, __LINE__, msg)
+#define lpnotice(msg...) core_log_notice(self->_log, __FILE__, __LINE__, msg)
+#define lpwarning(msg...) core_log_warning(self->_log, __FILE__, __LINE__, msg)
+#define lpcritical(msg...) core_log_critical(self->_log, __FILE__, __LINE__, msg)
+#define mldebug(msg...) core_log_debug(&_log, __FILE__, __LINE__, msg)
+#define mlinfo(msg...) core_log_info(&_log, __FILE__, __LINE__, msg)
+#define mlnotice(msg...) core_log_notice(&_log, __FILE__, __LINE__, msg)
+#define mlwarning(msg...) core_log_warning(&_log, __FILE__, __LINE__, msg)
+#define mlcritical(msg...) core_log_critical(&_log, __FILE__, __LINE__, msg)
+#define gldebug(msg...) core_log_debug(0, __FILE__, __LINE__, msg)
+#define glinfo(msg...) core_log_info(0, __FILE__, __LINE__, msg)
+#define glnotice(msg...) core_log_notice(0, __FILE__, __LINE__, msg)
+#define glwarning(msg...) core_log_warning(0, __FILE__, __LINE__, msg)
+#define glcritical(msg...) core_log_critical(0, __FILE__, __LINE__, msg)
+#endif
+
+#define lfatal(msg...) core_log_fatal(&self->_log, __FILE__, __LINE__, msg)
+#define lpfatal(msg...) core_log_fatal(self->_log, __FILE__, __LINE__, msg)
+#define mlfatal(msg...) core_log_fatal(&_log, __FILE__, __LINE__, msg)
+#define glfatal(msg...) core_log_fatal(0, __FILE__, __LINE__, msg)
+
+#define lfatal_oom(expression) \
+ if (!(expression)) \
+ core_log_fatal(&self->_log, __FILE__, __LINE__, "out of memory")
+#define lpfatal_oom(expression) \
+ if (!(expression)) \
+ core_log_fatal(self->_log, __FILE__, __LINE__, "out of memory")
+#define mlfatal_oom(expression) \
+ if (!(expression)) \
+ core_log_fatal(&_log, __FILE__, __LINE__, "out of memory")
+#define glfatal_oom(expression) \
+ if (!(expression)) \
+ core_log_fatal(0, __FILE__, __LINE__, "out of memory")
+
+#endif
diff --git a/src/core/log.hh b/src/core/log.hh
new file mode 100644
index 0000000..7273879
--- /dev/null
+++ b/src/core/log.hh
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct core_log_settings {
+ uint8_t debug;
+ uint8_t info;
+ uint8_t notice;
+ uint8_t warning;
+ uint8_t display_file_line;
+} core_log_settings_t;
+
+typedef struct core_log {
+ char name[32];
+ uint8_t is_obj;
+ core_log_settings_t settings;
+ const core_log_settings_t* module;
+} core_log_t;
+
+void core_log_debug(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+void core_log_info(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+void core_log_notice(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+void core_log_warning(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+void core_log_critical(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+void core_log_fatal(const core_log_t* l, const char* file, size_t line, const char* msg, ...);
+const char* core_log_errstr(int err);
+
+core_log_t* core_log_log();
diff --git a/src/core/log.lua b/src/core/log.lua
new file mode 100644
index 0000000..d62cbbc
--- /dev/null
+++ b/src/core/log.lua
@@ -0,0 +1,639 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.log
+-- Core logging facility
+-- .SS Usage to control global log level
+-- local log = require("dnsjit.core.log")
+-- log.enable("all")
+-- log.disable("debug")
+-- .SS Usage to control module log level
+-- local example = require("example") -- Example as below
+-- example.log():enable("all")
+-- example.log():disable("debug")
+-- .SS Usage to control object instance log level
+-- local example = require("example") -- Example as below
+-- local obj = example.new()
+-- obj:log():enable("all")
+-- obj:log():disable("debug")
+-- .SS Usage in C module
+-- .B NOTE
+-- naming of variables and module only globals are required to exactly as
+-- described in order for the macros to work;
+-- .B self
+-- is the pointer to the object instance,
+-- .B self->_log
+-- is the object instance logging configuration struct,
+-- .B _log
+-- is the module logging configuration struct.
+-- .LP
+-- Include logging:
+-- #include "core/log.h"
+-- .LP
+-- Add the logging struct to the module struct:
+-- typedef struct example {
+-- core_log_t _log;
+-- ...
+-- } example_t;
+-- .LP
+-- Add a module logging configuration and a struct default:
+-- static core_log_t _log = LOG_T_INIT("example");
+-- static example_t _defaults = {
+-- LOG_T_INIT_OBJ("example"),
+-- ...
+-- };
+-- .LP
+-- Use new/free and/or init/destroy functions (depends if you create the
+-- object in Lua or not):
+-- example_t* example_new() {
+-- example_t* self = calloc(1, sizeof(example_t));
+-- .
+-- *self = _defaults;
+-- ldebug("new()");
+-- .
+-- return self;
+-- }
+-- .
+-- void example_free(example_t* self) {
+-- ldebug("free()");
+-- free(self);
+-- }
+-- .
+-- int example_init(example_t* self) {
+-- *self = _defaults;
+-- .
+-- ldebug("init()");
+-- .
+-- return 0;
+-- }
+-- .
+-- void example_destroy(example_t* self) {
+-- ldebug("destroy()");
+-- ...
+-- }
+-- .LP
+-- In the Lua part of the C module you need to create a function that
+-- returns either the object instance Log or the modules Log.
+-- .LP
+-- Add C function to get module only Log:
+-- core_log_t* example_log() {
+-- return &_log;
+-- }
+-- .LP
+-- For the structures metatable add the following function:
+-- local ffi = require("ffi")
+-- local C = ffi.C
+-- .
+-- function Example:log()
+-- if self == nil then
+-- return C.example_log()
+-- end
+-- return self._log
+-- end
+-- .SS Usage in pure Lua module
+-- local log = require("dnsjit.core.log")
+-- local ffi = require("ffi")
+-- local C = ffi.C
+-- .
+-- local Example = {}
+-- local module_log = log.new("example")
+-- .
+-- function Example.new()
+-- local self = setmetatable({
+-- _log = log.new("example", module_log),
+-- }, { __index = Example })
+-- .
+-- self._log:debug("new()")
+-- .
+-- return self
+-- end
+-- .
+-- function Example:log()
+-- if self == nil then
+-- return module_log
+-- end
+-- return self._log
+-- end
+--
+-- Core logging facility used by all modules.
+-- .SS Log levels
+-- .TP
+-- all
+-- Keyword to enable/disable all changeable log levels.
+-- .TP
+-- debug
+-- Used for debug information.
+-- .TP
+-- info
+-- Used for informational processing messages.
+-- .TP
+-- notice
+-- Used for messages of that may have impact on processing.
+-- .TP
+-- warning
+-- Used for messages that has impact on processing.
+-- .TP
+-- critical
+-- Used for messages that have severe impact on processing, this level can
+-- not be disabled.
+-- .TP
+-- fatal
+-- Used to display a message before stopping all processing and existing,
+-- this level can not be disabled.
+-- .SS C macros
+-- .TP
+-- Object instance macros
+-- The following macros uses
+-- .IR &self->_log :
+-- .BR ldebug(msg...) ,
+-- .BR linfo(msg...) ,
+-- .BR lnotice(msg...) ,
+-- .BR lwarning(msg...) ,
+-- .BR lcritical(msg...) ,
+-- .BR lfatal(msg...) .
+-- .TP
+-- Object pointer instance macros
+-- The following macros uses
+-- .IR self->_log :
+-- .BR lpdebug(msg...) ,
+-- .BR lpinfo(msg...) ,
+-- .BR lpnotice(msg...) ,
+-- .BR lpwarning(msg...) ,
+-- .BR lpcritical(msg...) ,
+-- .BR lpfatal(msg...) .
+-- .TP
+-- Module macros
+-- The following macros uses
+-- .IR &_log :
+-- .BR mldebug(msg...) ,
+-- .BR mlinfo(msg...) ,
+-- .BR mlnotice(msg...) ,
+-- .BR mlwarning(msg...) ,
+-- .BR mlcritical(msg...) ,
+-- .BR mlfatal(msg...) .
+-- .TP
+-- Global macros
+-- The following macros uses the global logging configuration:
+-- .BR gldebug(msg...) ,
+-- .BR glinfo(msg...) ,
+-- .BR glnotice(msg...) ,
+-- .BR glwarning(msg...) ,
+-- .BR glcritical(msg...) ,
+-- .BR glfatal(msg...) .
+module(...,package.seeall)
+
+require("dnsjit.core.log_h")
+local ffi = require("ffi")
+local C = ffi.C
+local L = C.core_log_log()
+
+local t_name = "core_log_t"
+local core_log_t
+local Log = {}
+
+-- Create a new Log object with the given module
+-- .I name
+-- and an optional shared
+-- .I module
+-- Log object.
+function Log.new(name, module)
+ local self
+ if ffi.istype(t_name, module) then
+ self = core_log_t({ is_obj = 1, module = module.settings })
+ else
+ self = core_log_t()
+ end
+
+ local len = #name
+ if len > 31 then
+ len = 31
+ end
+ ffi.copy(self.name, name, len)
+ self.name[len] = 0
+
+ return self
+end
+
+-- Enable specified log level.
+function Log:enable(level)
+ if not ffi.istype(t_name, self) then
+ level = self
+ self = L
+ end
+ if level == "all" then
+ self.settings.debug = 3
+ self.settings.info = 3
+ self.settings.notice = 3
+ self.settings.warning = 3
+ elseif level == "debug" then
+ self.settings.debug = 3
+ elseif level == "info" then
+ self.settings.info = 3
+ elseif level == "notice" then
+ self.settings.notice = 3
+ elseif level == "warning" then
+ self.settings.warning = 3
+ else
+ error("invalid log level: "..level)
+ end
+end
+
+-- Disable specified log level.
+function Log:disable(level)
+ if not ffi.istype(t_name, self) then
+ level = self
+ self = L
+ end
+ if level == "all" then
+ self.settings.debug = 2
+ self.settings.info = 2
+ self.settings.notice = 2
+ self.settings.warning = 2
+ elseif level == "debug" then
+ self.settings.debug = 2
+ elseif level == "info" then
+ self.settings.info = 2
+ elseif level == "notice" then
+ self.settings.notice = 2
+ elseif level == "warning" then
+ self.settings.warning = 2
+ else
+ error("invalid log level: "..level)
+ end
+end
+
+-- Clear specified log level, which means it will revert back to default
+-- or inherited settings.
+function Log:clear(level)
+ if not ffi.istype(t_name, self) then
+ level = self
+ self = L
+ end
+ if level == "all" then
+ self.settings.debug = 0
+ self.settings.info = 0
+ self.settings.notice = 0
+ self.settings.warning = 0
+ elseif level == "debug" then
+ self.settings.debug = 0
+ elseif level == "info" then
+ self.settings.info = 0
+ elseif level == "notice" then
+ self.settings.notice = 0
+ elseif level == "warning" then
+ self.settings.warning = 0
+ else
+ error("invalid log level: "..level)
+ end
+end
+
+-- Enable or disable the displaying of file and line for messages.
+function Log:display_file_line(bool)
+ if not ffi.istype(t_name, self) then
+ bool = self
+ self = L
+ end
+ if bool == true then
+ self.settings.display_file_line = 3
+ else
+ self.settings.display_file_line = 0
+ end
+end
+
+-- Convert error number to its text representation.
+function Log.errstr(errno)
+ return ffi.string(C.core_log_errstr(errno))
+end
+
+-- Generate a debug message.
+function Log.debug(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ if not self then
+ if L.settings.debug ~= 3 then
+ return
+ end
+ else
+ if self.settings.debug ~= 0 then
+ if self.settings.debug ~= 3 then
+ return
+ end
+ elseif self.module ~= nil and self.module.debug ~= 0 then
+ if self.module.debug ~= 3 then
+ return
+ end
+ elseif L.settings.debug ~= 3 then
+ return
+ end
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_debug(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_debug(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_debug(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_debug(self, nil, 0, ...)
+end
+
+-- Generate an info message.
+function Log.info(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ if not self then
+ if L.settings.info ~= 3 then
+ return
+ end
+ else
+ if self.settings.info ~= 0 then
+ if self.settings.info ~= 3 then
+ return
+ end
+ elseif self.module ~= nil and self.module.info ~= 0 then
+ if self.module.info ~= 3 then
+ return
+ end
+ elseif L.settings.info ~= 3 then
+ return
+ end
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_info(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_info(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_info(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_info(self, nil, 0, ...)
+end
+
+-- Generate a notice message.
+function Log.notice(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ if not self then
+ if L.settings.notice ~= 3 then
+ return
+ end
+ else
+ if self.settings.notice ~= 0 then
+ if self.settings.notice ~= 3 then
+ return
+ end
+ elseif self.module ~= nil and self.module.notice ~= 0 then
+ if self.module.notice ~= 3 then
+ return
+ end
+ elseif L.settings.notice ~= 3 then
+ return
+ end
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_notice(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_notice(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_notice(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_notice(self, nil, 0, ...)
+end
+
+-- Generate a warning message.
+function Log.warning(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ if not self then
+ if L.settings.warning ~= 3 then
+ return
+ end
+ else
+ if self.settings.warning ~= 0 then
+ if self.settings.warning ~= 3 then
+ return
+ end
+ elseif self.module ~= nil and self.module.warning ~= 0 then
+ if self.module.warning ~= 3 then
+ return
+ end
+ elseif L.settings.warning ~= 3 then
+ return
+ end
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_warning(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_warning(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_warning(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_warning(self, nil, 0, ...)
+end
+
+-- Generate a critical message.
+function Log.critical(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_critical(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_critical(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_critical(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_critical(self, nil, 0, ...)
+end
+
+-- Generate a fatal message.
+function Log.fatal(self, ...)
+ local format
+ if not ffi.istype(t_name, self) then
+ format = self
+ self = nil
+ end
+ while true do
+ if not self then
+ if L.settings.display_file_line ~= 3 then
+ break
+ end
+ else
+ if self.settings.display_file_line ~= 0 then
+ if self.settings.display_file_line ~= 3 then
+ break
+ end
+ elseif self.module ~= nil and self.module.display_file_line ~= 0 then
+ if self.module.display_file_line ~= 3 then
+ break
+ end
+ elseif L.settings.display_file_line ~= 3 then
+ break
+ end
+ end
+ local info = debug.getinfo(2, "S")
+ if format then
+ C.core_log_fatal(self, info.source, info.linedefined, format, ...)
+ return
+ end
+ C.core_log_fatal(self, info.source, info.linedefined, ...)
+ return
+ end
+
+ if format then
+ C.core_log_fatal(self, nil, 0, format, ...)
+ return
+ end
+ C.core_log_fatal(self, nil, 0, ...)
+end
+
+core_log_t = ffi.metatype(t_name, { __index = Log })
+
+return Log
diff --git a/src/core/object.c b/src/core/object.c
new file mode 100644
index 0000000..8356f25
--- /dev/null
+++ b/src/core/object.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object.h"
+#include "core/assert.h"
+#include "core/object/pcap.h"
+#include "core/object/ether.h"
+#include "core/object/null.h"
+#include "core/object/loop.h"
+#include "core/object/linuxsll.h"
+#include "core/object/ieee802.h"
+#include "core/object/gre.h"
+#include "core/object/ip.h"
+#include "core/object/ip6.h"
+#include "core/object/icmp.h"
+#include "core/object/icmp6.h"
+#include "core/object/udp.h"
+#include "core/object/tcp.h"
+#include "core/object/payload.h"
+#include "core/object/dns.h"
+
+core_object_t* core_object_copy(const core_object_t* self)
+{
+ glassert_self();
+
+ switch (self->obj_type) {
+ case CORE_OBJECT_PCAP:
+ return (core_object_t*)core_object_pcap_copy((core_object_pcap_t*)self);
+ case CORE_OBJECT_ETHER:
+ return (core_object_t*)core_object_ether_copy((core_object_ether_t*)self);
+ case CORE_OBJECT_NULL:
+ return (core_object_t*)core_object_null_copy((core_object_null_t*)self);
+ case CORE_OBJECT_LOOP:
+ return (core_object_t*)core_object_loop_copy((core_object_loop_t*)self);
+ case CORE_OBJECT_LINUXSLL:
+ return (core_object_t*)core_object_linuxsll_copy((core_object_linuxsll_t*)self);
+ case CORE_OBJECT_IEEE802:
+ return (core_object_t*)core_object_ieee802_copy((core_object_ieee802_t*)self);
+ case CORE_OBJECT_GRE:
+ return (core_object_t*)core_object_gre_copy((core_object_gre_t*)self);
+ case CORE_OBJECT_IP:
+ return (core_object_t*)core_object_ip_copy((core_object_ip_t*)self);
+ case CORE_OBJECT_IP6:
+ return (core_object_t*)core_object_ip6_copy((core_object_ip6_t*)self);
+ case CORE_OBJECT_ICMP:
+ return (core_object_t*)core_object_icmp_copy((core_object_icmp_t*)self);
+ case CORE_OBJECT_ICMP6:
+ return (core_object_t*)core_object_icmp6_copy((core_object_icmp6_t*)self);
+ case CORE_OBJECT_UDP:
+ return (core_object_t*)core_object_udp_copy((core_object_udp_t*)self);
+ case CORE_OBJECT_TCP:
+ return (core_object_t*)core_object_tcp_copy((core_object_tcp_t*)self);
+ case CORE_OBJECT_PAYLOAD:
+ return (core_object_t*)core_object_payload_copy((core_object_payload_t*)self);
+ case CORE_OBJECT_DNS:
+ return (core_object_t*)core_object_dns_copy((core_object_dns_t*)self);
+ default:
+ glfatal("unknown type %d", self->obj_type);
+ }
+ return 0;
+}
+
+void core_object_free(core_object_t* self)
+{
+ glassert_self();
+
+ switch (self->obj_type) {
+ case CORE_OBJECT_PCAP:
+ core_object_pcap_free((core_object_pcap_t*)self);
+ break;
+ case CORE_OBJECT_ETHER:
+ core_object_ether_free((core_object_ether_t*)self);
+ break;
+ case CORE_OBJECT_NULL:
+ core_object_null_free((core_object_null_t*)self);
+ break;
+ case CORE_OBJECT_LOOP:
+ core_object_loop_free((core_object_loop_t*)self);
+ break;
+ case CORE_OBJECT_LINUXSLL:
+ core_object_linuxsll_free((core_object_linuxsll_t*)self);
+ break;
+ case CORE_OBJECT_IEEE802:
+ core_object_ieee802_free((core_object_ieee802_t*)self);
+ break;
+ case CORE_OBJECT_GRE:
+ core_object_gre_free((core_object_gre_t*)self);
+ break;
+ case CORE_OBJECT_IP:
+ core_object_ip_free((core_object_ip_t*)self);
+ break;
+ case CORE_OBJECT_IP6:
+ core_object_ip6_free((core_object_ip6_t*)self);
+ break;
+ case CORE_OBJECT_ICMP:
+ core_object_icmp_free((core_object_icmp_t*)self);
+ break;
+ case CORE_OBJECT_ICMP6:
+ core_object_icmp6_free((core_object_icmp6_t*)self);
+ break;
+ case CORE_OBJECT_UDP:
+ core_object_udp_free((core_object_udp_t*)self);
+ break;
+ case CORE_OBJECT_TCP:
+ core_object_tcp_free((core_object_tcp_t*)self);
+ break;
+ case CORE_OBJECT_PAYLOAD:
+ core_object_payload_free((core_object_payload_t*)self);
+ break;
+ case CORE_OBJECT_DNS:
+ core_object_dns_free((core_object_dns_t*)self);
+ break;
+ default:
+ glfatal("unknown type %d", self->obj_type);
+ }
+}
diff --git a/src/core/object.h b/src/core/object.h
new file mode 100644
index 0000000..c2eebb0
--- /dev/null
+++ b/src/core/object.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __dnsjit_core_object_h
+#define __dnsjit_core_object_h
+
+#define CORE_OBJECT_NONE 0
+#define CORE_OBJECT_PCAP 1
+/* link level objects */
+#define CORE_OBJECT_ETHER 10
+#define CORE_OBJECT_NULL 11
+#define CORE_OBJECT_LOOP 12
+#define CORE_OBJECT_LINUXSLL 13
+#define CORE_OBJECT_IEEE802 14
+#define CORE_OBJECT_GRE 15
+/* protocol objects */
+#define CORE_OBJECT_IP 20
+#define CORE_OBJECT_IP6 21
+#define CORE_OBJECT_ICMP 22
+#define CORE_OBJECT_ICMP6 23
+/* payload carrying objects */
+#define CORE_OBJECT_UDP 30
+#define CORE_OBJECT_TCP 31
+/* payload */
+#define CORE_OBJECT_PAYLOAD 40
+/* service object(s) */
+#define CORE_OBJECT_DNS 50
+
+#include <stdint.h>
+#include "core/object.hh"
+
+#define CORE_OBJECT_INIT(type, prev) (core_object_t*)prev, type
+
+#endif
diff --git a/src/core/object.hh b/src/core/object.hh
new file mode 100644
index 0000000..b19f858
--- /dev/null
+++ b/src/core/object.hh
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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 objectd a copy of the GNU General Public License
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct core_object core_object_t;
+struct core_object {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+};
+
+core_object_t* core_object_copy(const core_object_t* self);
+void core_object_free(core_object_t* self);
diff --git a/src/core/object.lua b/src/core/object.lua
new file mode 100644
index 0000000..7f58829
--- /dev/null
+++ b/src/core/object.lua
@@ -0,0 +1,177 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object
+-- Base object that is passed between receiver and receivee
+-- require("dnsjit.core.object")
+-- print(object:type())
+-- packet = object:cast()
+--
+-- This is the base object that can be casted to other objects that to
+-- describe a DNS message, how it was captured or generated.
+-- Objects can be chained together, for example a DNS message is created
+-- ontop of a packet.
+-- .SS Attributes
+-- .TP
+-- obj_type
+-- The enum of the object type.
+-- .TP
+-- obj_prev
+-- The previous object in the object chain.
+module(...,package.seeall)
+
+require("dnsjit.core.object_h")
+require("dnsjit.core.object.pcap_h")
+require("dnsjit.core.object.ether_h")
+require("dnsjit.core.object.null_h")
+require("dnsjit.core.object.loop_h")
+require("dnsjit.core.object.linuxsll_h")
+require("dnsjit.core.object.ieee802_h")
+require("dnsjit.core.object.gre_h")
+require("dnsjit.core.object.ip_h")
+require("dnsjit.core.object.ip6_h")
+require("dnsjit.core.object.icmp_h")
+require("dnsjit.core.object.icmp6_h")
+require("dnsjit.core.object.udp_h")
+require("dnsjit.core.object.tcp_h")
+require("dnsjit.core.object.payload_h")
+require("dnsjit.core.object.dns_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_t"
+local core_object_t
+local Object = {
+ NONE = 0,
+ PCAP = 1,
+ ETHER = 10,
+ NULL = 11,
+ LOOP = 12,
+ LINUXSLL = 13,
+ IEEE802 = 14,
+ GRE = 15,
+ IP = 20,
+ IP6 = 21,
+ ICMP = 22,
+ ICMP6 = 23,
+ UDP = 30,
+ TCP = 31,
+ PAYLOAD = 40,
+ DNS = 50
+}
+
+local _type = {}
+_type[Object.PCAP] = "pcap"
+_type[Object.ETHER] = "ether"
+_type[Object.NULL] = "null"
+_type[Object.LOOP] = "loop"
+_type[Object.LINUXSLL] = "linuxsll"
+_type[Object.IEEE802] = "ieee802"
+_type[Object.GRE] = "gre"
+_type[Object.IP] = "ip"
+_type[Object.IP6] = "ip6"
+_type[Object.ICMP] = "icmp"
+_type[Object.ICMP6] = "icmp6"
+_type[Object.UDP] = "udp"
+_type[Object.TCP] = "tcp"
+_type[Object.PAYLOAD] = "payload"
+_type[Object.DNS] = "dns"
+
+_type[Object.NONE] = "none"
+
+-- Return the textual type of the object.
+function Object:type()
+ return _type[self.obj_type]
+end
+
+-- Return the previous object.
+function Object:prev()
+ return self.obj_prev
+end
+
+local _cast = {}
+_cast[Object.PCAP] = "core_object_pcap_t*"
+_cast[Object.ETHER] = "core_object_ether_t*"
+_cast[Object.NULL] = "core_object_null_t*"
+_cast[Object.LOOP] = "core_object_loop_t*"
+_cast[Object.LINUXSLL] = "core_object_linuxsll_t*"
+_cast[Object.IEEE802] = "core_object_ieee802_t*"
+_cast[Object.GRE] = "core_object_gre_t*"
+_cast[Object.IP] = "core_object_ip_t*"
+_cast[Object.IP6] = "core_object_ip6_t*"
+_cast[Object.ICMP] = "core_object_icmp_t*"
+_cast[Object.ICMP6] = "core_object_icmp6_t*"
+_cast[Object.UDP] = "core_object_udp_t*"
+_cast[Object.TCP] = "core_object_tcp_t*"
+_cast[Object.PAYLOAD] = "core_object_payload_t*"
+_cast[Object.DNS] = "core_object_dns_t*"
+
+-- Cast the object to the underlining object module and return it.
+function Object:cast()
+ return ffi.cast(_cast[self.obj_type], self)
+end
+
+-- Cast the object to the specified object module and return it.
+-- Returns nil if the object chain doesn't contained the specified object type.
+function Object:cast_to(obj_type)
+ if obj_type == nil then
+ obj_type = self.obj_type
+ end
+
+ local obj = self
+ while obj.obj_type ~= obj_type do
+ obj = obj.obj_prev
+ if obj == nil then return nil end
+ end
+
+ return ffi.cast(_cast[obj_type], obj)
+end
+
+-- Cast the object to the generic object module and return it.
+function Object:uncast()
+ return self
+end
+
+-- Make a copy of the object and return it.
+function Object:copy()
+ return C.core_object_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Object:free()
+ C.core_object_free(self)
+end
+
+core_object_t = ffi.metatype(t_name, { __index = Object })
+
+-- dnsjit.core.object.pcap (3),
+-- dnsjit.core.object.ether (3),
+-- dnsjit.core.object.null (3),
+-- dnsjit.core.object.loop (3),
+-- dnsjit.core.object.linuxsll (3),
+-- dnsjit.core.object.ieee802 (3),
+-- dnsjit.core.object.gre (3),
+-- dnsjit.core.object.ip (3),
+-- dnsjit.core.object.ip6 (3),
+-- dnsjit.core.object.icmp (3),
+-- dnsjit.core.object.icmp6 (3),
+-- dnsjit.core.object.udp (3),
+-- dnsjit.core.object.tcp (3),
+-- dnsjit.core.object.payload (3),
+-- dnsjit.core.object.dns (3)
+return Object
diff --git a/src/core/object/dns.c b/src/core/object/dns.c
new file mode 100644
index 0000000..49aec6d
--- /dev/null
+++ b/src/core/object/dns.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/dns.h"
+#include "core/object/payload.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#endif
+#endif
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+#ifndef bswap_16
+#ifndef bswap16
+#define bswap_16(x) swap16(x)
+#define bswap_32(x) swap32(x)
+#define bswap_64(x) swap64(x)
+#else
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+#endif
+#endif
+
+#define _ERR_MALFORMED -2
+#define _ERR_NEEDLABELS -3
+
+static core_log_t _log = LOG_T_INIT("core.object.dns");
+static core_object_dns_t _defaults = CORE_OBJECT_DNS_INIT(0);
+
+static core_object_dns_label_t _defaults_label = { 0 };
+static core_object_dns_rr_t _defaults_rr = { 0 };
+static core_object_dns_q_t _defaults_q = { 0 };
+
+core_log_t* core_object_dns_log()
+{
+ return &_log;
+}
+
+core_object_dns_t* core_object_dns_new()
+{
+ core_object_dns_t* self;
+
+ mlfatal_oom(self = malloc(sizeof(core_object_dns_t)));
+ *self = _defaults;
+
+ return self;
+}
+
+core_object_dns_t* core_object_dns_copy(const core_object_dns_t* self)
+{
+ core_object_dns_t* copy;
+ mlassert_self();
+
+ mlfatal_oom(copy = malloc(sizeof(core_object_dns_t)));
+ memcpy(copy, self, sizeof(core_object_dns_t));
+ copy->obj_prev = 0;
+
+ return (core_object_dns_t*)copy;
+}
+
+void core_object_dns_free(core_object_dns_t* self)
+{
+ mlassert_self();
+ free(self);
+}
+
+#define need8(v, p, l) \
+ if (l < 1) { \
+ break; \
+ } \
+ v = *p; \
+ p += 1; \
+ l -= 1
+
+static inline uint16_t _need16(const void* ptr)
+{
+ uint16_t v;
+ memcpy(&v, ptr, sizeof(v));
+ return be16toh(v);
+}
+
+#define need16(v, p, l) \
+ if (l < 2) { \
+ break; \
+ } \
+ v = _need16(p); \
+ p += 2; \
+ l -= 2
+
+static inline uint32_t _need32(const void* ptr)
+{
+ uint32_t v;
+ memcpy(&v, ptr, sizeof(v));
+ return be32toh(v);
+}
+
+#define need32(v, p, l) \
+ if (l < 4) { \
+ break; \
+ } \
+ v = _need32(p); \
+ p += 4; \
+ l -= 4
+
+#define needxb(b, x, p, l) \
+ if (l < x) { \
+ break; \
+ } \
+ memcpy(b, p, x); \
+ p += x; \
+ l -= x
+
+#define advancexb(x, p, l) \
+ if (l < x) { \
+ break; \
+ } \
+ p += x; \
+ l -= x
+
+int core_object_dns_parse_header(core_object_dns_t* self)
+{
+ const core_object_payload_t* payload;
+ uint8_t byte;
+ mlassert_self();
+
+ if (!(payload = (core_object_payload_t*)self->obj_prev) || payload->obj_type != CORE_OBJECT_PAYLOAD) {
+ mlfatal("no obj_prev or invalid type");
+ }
+ if (!payload->payload || !payload->len) {
+ mlfatal("no payload set or zero length");
+ }
+
+ self->payload = self->at = payload->payload;
+ self->len = self->left = payload->len;
+
+ for (;;) {
+ if (self->includes_dnslen) {
+ need16(self->dnslen, self->at, self->left);
+ self->have_dnslen = 1;
+ }
+ need16(self->id, self->at, self->left);
+ self->have_id = 1;
+
+ need8(byte, self->at, self->left);
+ self->qr = byte & (1 << 7) ? 1 : 0;
+ self->opcode = (byte >> 3) & 0xf;
+ self->aa = byte & (1 << 2) ? 1 : 0;
+ self->tc = byte & (1 << 1) ? 1 : 0;
+ self->rd = byte & (1 << 0) ? 1 : 0;
+ self->have_qr = self->have_opcode = self->have_aa = self->have_tc = self->have_rd = 1;
+
+ need8(byte, self->at, self->left);
+ self->ra = byte & (1 << 7) ? 1 : 0;
+ self->z = byte & (1 << 6) ? 1 : 0;
+ self->ad = byte & (1 << 5) ? 1 : 0;
+ self->cd = byte & (1 << 4) ? 1 : 0;
+ self->rcode = byte & 0xf;
+ self->have_ra = self->have_z = self->have_ad = self->have_cd = self->have_rcode = 1;
+
+ need16(self->qdcount, self->at, self->left);
+ self->have_qdcount = 1;
+
+ need16(self->ancount, self->at, self->left);
+ self->have_ancount = 1;
+
+ need16(self->nscount, self->at, self->left);
+ self->have_nscount = 1;
+
+ need16(self->arcount, self->at, self->left);
+ self->have_arcount = 1;
+
+ return 0;
+ }
+
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+}
+
+static inline size_t _rdata_labels(uint16_t type)
+{
+ switch (type) {
+ case CORE_OBJECT_DNS_TYPE_NS:
+ case CORE_OBJECT_DNS_TYPE_MD:
+ case CORE_OBJECT_DNS_TYPE_MF:
+ case CORE_OBJECT_DNS_TYPE_CNAME:
+ case CORE_OBJECT_DNS_TYPE_MB:
+ case CORE_OBJECT_DNS_TYPE_MG:
+ case CORE_OBJECT_DNS_TYPE_MR:
+ case CORE_OBJECT_DNS_TYPE_PTR:
+ case CORE_OBJECT_DNS_TYPE_NXT:
+ case CORE_OBJECT_DNS_TYPE_DNAME:
+ case CORE_OBJECT_DNS_TYPE_NSEC:
+ case CORE_OBJECT_DNS_TYPE_TKEY:
+ case CORE_OBJECT_DNS_TYPE_TSIG:
+ return 1;
+
+ case CORE_OBJECT_DNS_TYPE_SOA:
+ case CORE_OBJECT_DNS_TYPE_MINFO:
+ case CORE_OBJECT_DNS_TYPE_RP:
+ case CORE_OBJECT_DNS_TYPE_TALINK:
+ return 2;
+
+ case CORE_OBJECT_DNS_TYPE_MX:
+ case CORE_OBJECT_DNS_TYPE_AFSDB:
+ case CORE_OBJECT_DNS_TYPE_RT:
+ case CORE_OBJECT_DNS_TYPE_KX:
+ case CORE_OBJECT_DNS_TYPE_LP:
+ return 1;
+
+ case CORE_OBJECT_DNS_TYPE_PX:
+ return 2;
+
+ case CORE_OBJECT_DNS_TYPE_SIG:
+ case CORE_OBJECT_DNS_TYPE_RRSIG:
+ return 1;
+
+ case CORE_OBJECT_DNS_TYPE_SRV:
+ return 1;
+
+ case CORE_OBJECT_DNS_TYPE_NAPTR:
+ return 1;
+
+ case CORE_OBJECT_DNS_TYPE_HIP:
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline size_t _label(core_object_dns_t* self, core_object_dns_label_t* label, size_t labels)
+{
+ size_t n;
+
+ for (n = 0; self->left && n < labels; n++) {
+ core_object_dns_label_t* l = &label[n];
+ *l = _defaults_label;
+
+ need8(l->length, self->at, self->left);
+
+ if ((l->length & 0xc0) == 0xc0) {
+ need8(l->offset, self->at, self->left);
+ l->offset |= (l->length & 0x3f) << 8;
+ l->have_offset = 1;
+ return n;
+ } else if (l->length & 0xc0) {
+ l->extension_bits = l->length >> 6;
+ l->have_extension_bits = 1;
+ return n;
+ } else if (l->length) {
+ l->have_length = 1;
+
+ l->offset = self->at - self->payload - 1;
+ advancexb(l->length, self->at, self->left);
+ l->have_dn = 1;
+ } else {
+ l->is_end = 1;
+ return n;
+ }
+ }
+
+ return n;
+}
+
+int core_object_dns_parse_q(core_object_dns_t* self, core_object_dns_q_t* q, core_object_dns_label_t* label, size_t labels)
+{
+ mlassert_self();
+ mlassert(q, "q is nil");
+ mlassert(label, "label is nil");
+ mlassert(labels, "labels is zero");
+ mlassert(self->at, "at is nil");
+
+ for (;;) {
+ *q = _defaults_q;
+ q->labels = _label(self, label, labels);
+ if (q->labels < labels) {
+ core_object_dns_label_t* l = &label[q->labels];
+ if (!(l->have_offset | l->have_extension_bits | l->is_end)) {
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+ }
+ } else {
+ mlwarning("need more labels, aborting DNS parsing");
+ return _ERR_NEEDLABELS;
+ }
+ q->labels++;
+
+ need16(q->type, self->at, self->left);
+ q->have_type = 1;
+
+ need16(q->class, self->at, self->left);
+ q->have_class = 1;
+
+ return 0;
+ }
+
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+}
+
+int core_object_dns_parse_rr(core_object_dns_t* self, core_object_dns_rr_t* rr, core_object_dns_label_t* label, size_t labels)
+{
+ size_t rdata_label_sets;
+ mlassert_self();
+ mlassert(rr, "rr is nil");
+ mlassert(label, "label is nil");
+ mlassert(labels, "labels is zero");
+ mlassert(self->at, "at is nil");
+
+ for (;;) {
+ *rr = _defaults_rr;
+ rr->labels = _label(self, label, labels);
+ if (rr->labels < labels) {
+ core_object_dns_label_t* l = &label[rr->labels];
+ if (!(l->have_offset | l->have_extension_bits | l->is_end)) {
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+ }
+ } else {
+ mlwarning("need more labels, aborting DNS parsing");
+ return _ERR_NEEDLABELS;
+ }
+ rr->labels++;
+
+ need16(rr->type, self->at, self->left);
+ rr->have_type = 1;
+
+ need16(rr->class, self->at, self->left);
+ rr->have_class = 1;
+
+ need32(rr->ttl, self->at, self->left);
+ rr->have_ttl = 1;
+
+ need16(rr->rdlength, self->at, self->left);
+ rr->have_rdlength = 1;
+
+ rr->rdata_offset = self->at - self->payload;
+ if (!(rdata_label_sets = _rdata_labels(rr->type))) {
+ advancexb(rr->rdlength, self->at, self->left);
+ rr->have_rdata = 1;
+ return 0;
+ }
+
+ switch (rr->type) {
+ case CORE_OBJECT_DNS_TYPE_MX:
+ case CORE_OBJECT_DNS_TYPE_AFSDB:
+ case CORE_OBJECT_DNS_TYPE_RT:
+ case CORE_OBJECT_DNS_TYPE_KX:
+ case CORE_OBJECT_DNS_TYPE_LP:
+ case CORE_OBJECT_DNS_TYPE_PX:
+ advancexb(2, self->at, self->left);
+ break;
+
+ case CORE_OBJECT_DNS_TYPE_SIG:
+ case CORE_OBJECT_DNS_TYPE_RRSIG:
+ advancexb(18, self->at, self->left);
+ break;
+
+ case CORE_OBJECT_DNS_TYPE_SRV:
+ advancexb(6, self->at, self->left);
+ break;
+
+ case CORE_OBJECT_DNS_TYPE_NAPTR: {
+ uint8_t naptr_length;
+
+ advancexb(4, self->at, self->left);
+ need8(naptr_length, self->at, self->left);
+ advancexb(naptr_length, self->at, self->left);
+ need8(naptr_length, self->at, self->left);
+ advancexb(naptr_length, self->at, self->left);
+ need8(naptr_length, self->at, self->left);
+ advancexb(naptr_length, self->at, self->left);
+ } break;
+
+ case CORE_OBJECT_DNS_TYPE_HIP: {
+ uint8_t hit_length;
+ uint16_t pk_length;
+
+ need8(hit_length, self->at, self->left);
+ advancexb(1, self->at, self->left);
+ need16(pk_length, self->at, self->left);
+ advancexb(hit_length, self->at, self->left);
+ advancexb(pk_length, self->at, self->left);
+
+ if (self->at - self->payload >= rr->rdata_offset + rr->rdlength) {
+ rdata_label_sets = 0;
+ }
+ } break;
+ }
+
+ while (rdata_label_sets) {
+ rr->rdata_labels += _label(self, &label[rr->labels + rr->rdata_labels], labels - rr->labels - rr->rdata_labels);
+ if (rr->labels + rr->rdata_labels < labels) {
+ core_object_dns_label_t* l = &label[rr->labels + rr->rdata_labels];
+ if (!(l->have_offset | l->have_extension_bits | l->is_end)) {
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+ }
+ } else {
+ mlwarning("need more labels, aborting DNS parsing");
+ return _ERR_NEEDLABELS;
+ }
+ rr->rdata_labels++;
+
+ if (rr->type == CORE_OBJECT_DNS_TYPE_HIP && self->at - self->payload < rr->rdata_offset + rr->rdlength) {
+ continue;
+ }
+
+ rdata_label_sets--;
+ }
+
+ if (self->at - self->payload < rr->rdata_offset + rr->rdlength) {
+ rr->padding_offset = self->at - self->payload;
+ rr->padding_length = rr->rdlength - (rr->padding_offset - rr->rdata_offset);
+
+ advancexb(rr->padding_length, self->at, self->left);
+
+ /*
+ * TODO:
+ *
+ * This can indicate padding but we do not set that we have padding
+ * yet because we need to fully understand all record types before
+ * that and process valid data after the labels
+ *
+ rr->have_padding = 1;
+ */
+ } else if (self->at - self->payload > rr->rdata_offset + rr->rdlength) {
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+ }
+ rr->have_rdata = 1;
+
+ return 0;
+ }
+
+ // TODO: error here on malformed/truncated? could be quite spammy
+ return _ERR_MALFORMED;
+}
diff --git a/src/core/object/dns.h b/src/core/object/dns.h
new file mode 100644
index 0000000..5fbaf53
--- /dev/null
+++ b/src/core/object/dns.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/log.h"
+#include "core/object.h"
+
+#ifndef __dnsjit_core_object_dns_h
+#define __dnsjit_core_object_dns_h
+
+#include <netinet/in.h>
+#include <sys/types.h>
+
+#include "core/object/dns.hh"
+
+#define CORE_OBJECT_DNS_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_DNS, prev) \
+ , \
+ 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ }
+
+/*
+ * 2016-12-09 https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
+ */
+
+#define CORE_OBJECT_DNS_CLASS_IN 1
+#define CORE_OBJECT_DNS_CLASS_CH 3
+#define CORE_OBJECT_DNS_CLASS_HS 4
+#define CORE_OBJECT_DNS_CLASS_NONE 254
+#define CORE_OBJECT_DNS_CLASS_ANY 255
+
+#define CORE_OBJECT_DNS_TYPE_A 1
+#define CORE_OBJECT_DNS_TYPE_NS 2
+#define CORE_OBJECT_DNS_TYPE_MD 3
+#define CORE_OBJECT_DNS_TYPE_MF 4
+#define CORE_OBJECT_DNS_TYPE_CNAME 5
+#define CORE_OBJECT_DNS_TYPE_SOA 6
+#define CORE_OBJECT_DNS_TYPE_MB 7
+#define CORE_OBJECT_DNS_TYPE_MG 8
+#define CORE_OBJECT_DNS_TYPE_MR 9
+#define CORE_OBJECT_DNS_TYPE_NULL 10
+#define CORE_OBJECT_DNS_TYPE_WKS 11
+#define CORE_OBJECT_DNS_TYPE_PTR 12
+#define CORE_OBJECT_DNS_TYPE_HINFO 13
+#define CORE_OBJECT_DNS_TYPE_MINFO 14
+#define CORE_OBJECT_DNS_TYPE_MX 15
+#define CORE_OBJECT_DNS_TYPE_TXT 16
+#define CORE_OBJECT_DNS_TYPE_RP 17
+#define CORE_OBJECT_DNS_TYPE_AFSDB 18
+#define CORE_OBJECT_DNS_TYPE_X25 19
+#define CORE_OBJECT_DNS_TYPE_ISDN 20
+#define CORE_OBJECT_DNS_TYPE_RT 21
+#define CORE_OBJECT_DNS_TYPE_NSAP 22
+#define CORE_OBJECT_DNS_TYPE_NSAP_PTR 23
+#define CORE_OBJECT_DNS_TYPE_SIG 24
+#define CORE_OBJECT_DNS_TYPE_KEY 25
+#define CORE_OBJECT_DNS_TYPE_PX 26
+#define CORE_OBJECT_DNS_TYPE_GPOS 27
+#define CORE_OBJECT_DNS_TYPE_AAAA 28
+#define CORE_OBJECT_DNS_TYPE_LOC 29
+#define CORE_OBJECT_DNS_TYPE_NXT 30
+#define CORE_OBJECT_DNS_TYPE_EID 31
+#define CORE_OBJECT_DNS_TYPE_NIMLOC 32
+#define CORE_OBJECT_DNS_TYPE_SRV 33
+#define CORE_OBJECT_DNS_TYPE_ATMA 34
+#define CORE_OBJECT_DNS_TYPE_NAPTR 35
+#define CORE_OBJECT_DNS_TYPE_KX 36
+#define CORE_OBJECT_DNS_TYPE_CERT 37
+#define CORE_OBJECT_DNS_TYPE_A6 38
+#define CORE_OBJECT_DNS_TYPE_DNAME 39
+#define CORE_OBJECT_DNS_TYPE_SINK 40
+#define CORE_OBJECT_DNS_TYPE_OPT 41
+#define CORE_OBJECT_DNS_TYPE_APL 42
+#define CORE_OBJECT_DNS_TYPE_DS 43
+#define CORE_OBJECT_DNS_TYPE_SSHFP 44
+#define CORE_OBJECT_DNS_TYPE_IPSECKEY 45
+#define CORE_OBJECT_DNS_TYPE_RRSIG 46
+#define CORE_OBJECT_DNS_TYPE_NSEC 47
+#define CORE_OBJECT_DNS_TYPE_DNSKEY 48
+#define CORE_OBJECT_DNS_TYPE_DHCID 49
+#define CORE_OBJECT_DNS_TYPE_NSEC3 50
+#define CORE_OBJECT_DNS_TYPE_NSEC3PARAM 51
+#define CORE_OBJECT_DNS_TYPE_TLSA 52
+#define CORE_OBJECT_DNS_TYPE_SMIMEA 53
+#define CORE_OBJECT_DNS_TYPE_HIP 55
+#define CORE_OBJECT_DNS_TYPE_NINFO 56
+#define CORE_OBJECT_DNS_TYPE_RKEY 57
+#define CORE_OBJECT_DNS_TYPE_TALINK 58
+#define CORE_OBJECT_DNS_TYPE_CDS 59
+#define CORE_OBJECT_DNS_TYPE_CDNSKEY 60
+#define CORE_OBJECT_DNS_TYPE_OPENPGPKEY 61
+#define CORE_OBJECT_DNS_TYPE_CSYNC 62
+#define CORE_OBJECT_DNS_TYPE_SPF 99
+#define CORE_OBJECT_DNS_TYPE_UINFO 100
+#define CORE_OBJECT_DNS_TYPE_UID 101
+#define CORE_OBJECT_DNS_TYPE_GID 102
+#define CORE_OBJECT_DNS_TYPE_UNSPEC 103
+#define CORE_OBJECT_DNS_TYPE_NID 104
+#define CORE_OBJECT_DNS_TYPE_L32 105
+#define CORE_OBJECT_DNS_TYPE_L64 106
+#define CORE_OBJECT_DNS_TYPE_LP 107
+#define CORE_OBJECT_DNS_TYPE_EUI48 108
+#define CORE_OBJECT_DNS_TYPE_EUI64 109
+#define CORE_OBJECT_DNS_TYPE_TKEY 249
+#define CORE_OBJECT_DNS_TYPE_TSIG 250
+#define CORE_OBJECT_DNS_TYPE_IXFR 251
+#define CORE_OBJECT_DNS_TYPE_AXFR 252
+#define CORE_OBJECT_DNS_TYPE_MAILB 253
+#define CORE_OBJECT_DNS_TYPE_MAILA 254
+#define CORE_OBJECT_DNS_TYPE_ANY 255
+#define CORE_OBJECT_DNS_TYPE_URI 256
+#define CORE_OBJECT_DNS_TYPE_CAA 257
+#define CORE_OBJECT_DNS_TYPE_AVC 258
+#define CORE_OBJECT_DNS_TYPE_TA 32768
+#define CORE_OBJECT_DNS_TYPE_DLV 32769
+
+#define CORE_OBJECT_DNS_OPCODE_QUERY 0
+#define CORE_OBJECT_DNS_OPCODE_IQUERY 1
+#define CORE_OBJECT_DNS_OPCODE_STATUS 2
+#define CORE_OBJECT_DNS_OPCODE_NOTIFY 4
+#define CORE_OBJECT_DNS_OPCODE_UPDATE 5
+
+#define CORE_OBJECT_DNS_RCODE_NOERROR 0
+#define CORE_OBJECT_DNS_RCODE_FORMERR 1
+#define CORE_OBJECT_DNS_RCODE_SERVFAIL 2
+#define CORE_OBJECT_DNS_RCODE_NXDOMAIN 3
+#define CORE_OBJECT_DNS_RCODE_NOTIMP 4
+#define CORE_OBJECT_DNS_RCODE_REFUSED 5
+#define CORE_OBJECT_DNS_RCODE_YXDOMAIN 6
+#define CORE_OBJECT_DNS_RCODE_YXRRSET 7
+#define CORE_OBJECT_DNS_RCODE_NXRRSET 8
+#define CORE_OBJECT_DNS_RCODE_NOTAUTH 9
+#define CORE_OBJECT_DNS_RCODE_NOTZONE 10
+#define CORE_OBJECT_DNS_RCODE_BADVERS 16
+#define CORE_OBJECT_DNS_RCODE_BADSIG 16
+#define CORE_OBJECT_DNS_RCODE_BADKEY 17
+#define CORE_OBJECT_DNS_RCODE_BADTIME 18
+#define CORE_OBJECT_DNS_RCODE_BADMODE 19
+#define CORE_OBJECT_DNS_RCODE_BADNAME 20
+#define CORE_OBJECT_DNS_RCODE_BADALG 21
+#define CORE_OBJECT_DNS_RCODE_BADTRUNC 22
+#define CORE_OBJECT_DNS_RCODE_BADCOOKIE 23
+
+#define CORE_OBJECT_DNS_AFSDB_SUBTYPE_AFS3LOCSRV 1
+#define CORE_OBJECT_DNS_AFSDB_SUBTYPE_DCENCA_ROOT 2
+
+#define CORE_OBJECT_DNS_DHCID_TYPE_1OCTET 0
+#define CORE_OBJECT_DNS_DHCID_TYPE_DATAOCTET 1
+#define CORE_OBJECT_DNS_DHCID_TYPE_CLIENT_DUID 2
+
+#define CORE_OBJECT_DNS_EDNS0_OPT_LLQ 1
+#define CORE_OBJECT_DNS_EDNS0_OPT_UL 2
+#define CORE_OBJECT_DNS_EDNS0_OPT_NSID 3
+#define CORE_OBJECT_DNS_EDNS0_OPT_DAU 5
+#define CORE_OBJECT_DNS_EDNS0_OPT_DHU 6
+#define CORE_OBJECT_DNS_EDNS0_OPT_N3U 7
+#define CORE_OBJECT_DNS_EDNS0_OPT_CLIENT_SUBNET 8
+#define CORE_OBJECT_DNS_EDNS0_OPT_EXPIRE 9
+#define CORE_OBJECT_DNS_EDNS0_OPT_COOKIE 10
+#define CORE_OBJECT_DNS_EDNS0_OPT_TCP_KEEPALIVE 11
+#define CORE_OBJECT_DNS_EDNS0_OPT_PADDING 12
+#define CORE_OBJECT_DNS_EDNS0_OPT_CHAIN 13
+#define CORE_OBJECT_DNS_EDNS0_OPT_DEVICEID 26946
+
+#endif
diff --git a/src/core/object/dns.hh b/src/core/object/dns.hh
new file mode 100644
index 0000000..dfe9719
--- /dev/null
+++ b/src/core/object/dns.hh
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.log")
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_dns_label {
+ uint8_t is_end;
+ uint8_t have_length;
+ uint8_t have_offset;
+ uint8_t have_extension_bits;
+ uint8_t have_dn;
+ uint8_t extension_bits;
+
+ uint8_t length;
+ uint16_t offset;
+} core_object_dns_label_t;
+
+typedef struct core_object_dns_rr {
+ uint8_t have_type;
+ uint8_t have_class;
+ uint8_t have_ttl;
+ uint8_t have_rdlength;
+ uint8_t have_rdata;
+ uint8_t have_rdata_labels;
+ uint8_t have_padding;
+
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength;
+
+ size_t labels;
+ size_t rdata_offset;
+ size_t rdata_labels;
+ size_t padding_offset;
+ size_t padding_length;
+} core_object_dns_rr_t;
+
+typedef struct core_object_dns_q {
+ uint8_t have_type;
+ uint8_t have_class;
+
+ uint16_t type;
+ uint16_t class;
+
+ size_t labels;
+} core_object_dns_q_t;
+
+typedef struct core_object_dns {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ int includes_dnslen;
+ const uint8_t *payload, *at;
+ size_t len, left;
+
+ uint8_t have_dnslen;
+ uint8_t have_id;
+ uint8_t have_qr;
+ uint8_t have_opcode;
+ uint8_t have_aa;
+ uint8_t have_tc;
+ uint8_t have_rd;
+ uint8_t have_ra;
+ uint8_t have_z;
+ uint8_t have_ad;
+ uint8_t have_cd;
+ uint8_t have_rcode;
+ uint8_t have_qdcount;
+ uint8_t have_ancount;
+ uint8_t have_nscount;
+ uint8_t have_arcount;
+
+ uint16_t dnslen;
+ uint16_t id;
+ int8_t qr;
+ uint8_t opcode;
+ uint8_t aa;
+ uint8_t tc;
+ uint8_t rd;
+ uint8_t ra;
+ uint8_t z;
+ uint8_t ad;
+ uint8_t cd;
+ uint8_t rcode;
+ uint16_t qdcount;
+ uint16_t ancount;
+ uint16_t nscount;
+ uint16_t arcount;
+} core_object_dns_t;
+
+core_log_t* core_object_dns_log();
+
+core_object_dns_t* core_object_dns_new();
+core_object_dns_t* core_object_dns_copy(const core_object_dns_t* self);
+void core_object_dns_free(core_object_dns_t* self);
+void core_object_dns_reset(core_object_dns_t* self, const core_object_t* obj);
+
+int core_object_dns_parse_header(core_object_dns_t* self);
+int core_object_dns_parse_q(core_object_dns_t* self, core_object_dns_q_t* q, core_object_dns_label_t* label, size_t labels);
+int core_object_dns_parse_rr(core_object_dns_t* self, core_object_dns_rr_t* rr, core_object_dns_label_t* label, size_t labels);
diff --git a/src/core/object/dns.lua b/src/core/object/dns.lua
new file mode 100644
index 0000000..e8fb12b
--- /dev/null
+++ b/src/core/object/dns.lua
@@ -0,0 +1,797 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.dns
+-- Container of a DNS message
+-- .SS Parse DNS header and check if query or response
+-- local dns = require("dnsjit.core.object.dns").new(payload)
+-- if dns:parse_header() == 0 then
+-- if dns.qr == 0 then
+-- print(dns.id, dns.opcode_tostring(dns.opcode))
+-- else
+-- print(dns.id, dns.rcode_tostring(dns.rcode))
+-- end
+-- end
+-- .SS Print a DNS payload
+-- local dns = require("dnsjit.core.object.dns").new(payload)
+-- dns:print()
+-- .SS Parse a DNS payload
+-- local dns = require("dnsjit.core.object.dns").new(payload)
+-- local qs, q_labels, rrs, rr_labels = dns:parse()
+-- if qs and q_labels then
+-- ...
+-- if rrs and rr_labels then
+-- ...
+-- end
+-- end
+--
+-- The object that describes a DNS message.
+-- .SS Attributes
+-- .TP
+-- includes_dnslen
+-- If non-zero then this indicates that the DNS length is included in the
+-- payload (for example if the transport is TCP) and will affect parsing of it.
+-- .TP
+-- have_dnslen
+-- Set if the dnslen was included in the payload and could be read.
+-- .TP
+-- have_id
+-- Set if there is a DNS ID.
+-- .TP
+-- have_qr
+-- Set if there is a QR flag.
+-- .TP
+-- have_opcode
+-- Set if there is an OPCODE.
+-- .TP
+-- have_aa
+-- Set if there is a AA flag.
+-- .TP
+-- have_tc
+-- Set if there is a TC flag.
+-- .TP
+-- have_rd
+-- Set if there is a RD flag.
+-- .TP
+-- have_ra
+-- Set if there is a RA flag.
+-- .TP
+-- have_z
+-- Set if there is a Z flag.
+-- .TP
+-- have_ad
+-- Set if there is a AD flag.
+-- .TP
+-- have_cd
+-- Set if there is a CD flag.
+-- .TP
+-- have_rcode
+-- Set if there is a RCODE.
+-- .TP
+-- have_qdcount
+-- Set if there is an QDCOUNT.
+-- .TP
+-- have_ancount
+-- Set if there is an ANCOUNT.
+-- .TP
+-- have_nscount
+-- Set if there is a NSCOUNT.
+-- .TP
+-- have_arcount
+-- Set if there is an ARCOUNT.
+-- .TP
+-- dnslen
+-- The DNS length found in the payload.
+-- .TP
+-- id
+-- The DNS ID.
+-- .TP
+-- qr
+-- The QR flag.
+-- .TP
+-- opcode
+-- The OPCODE.
+-- .TP
+-- aa
+-- The AA flag.
+-- .TP
+-- tc
+-- The TC flag.
+-- .TP
+-- rd
+-- The RD flag.
+-- .TP
+-- ra
+-- The RA flag.
+-- .TP
+-- z
+-- The Z flag.
+-- .TP
+-- ad
+-- The AD flag.
+-- .TP
+-- cd
+-- The CD flag.
+-- .TP
+-- rcode
+-- The RCODE.
+-- .TP
+-- qdcount
+-- The QDCOUNT.
+-- .TP
+-- ancount
+-- The ANCOUNT.
+-- .TP
+-- nscount
+-- The NSCOUNT.
+-- .TP
+-- arcount
+-- The ARCOUNT.
+-- .SS Constants
+-- The following tables exists for DNS parameters, taken from
+-- .I https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
+-- on the 2016-12-09.
+-- .LP
+-- .IR CLASS ,
+-- .IR CLASS_STR ,
+-- .IR TYPE ,
+-- .IR TYPE_STR ,
+-- .IR OPCODE ,
+-- .IR OPCODE_STR ,
+-- .IR RCODE ,
+-- .IR RCODE_STR ,
+-- .IR AFSDB ,
+-- .IR AFSDB_STR ,
+-- .IR DHCID ,
+-- .IR DHCID_STR ,
+-- .IR ENDS0 ,
+-- .IR ENDS0_STR
+-- .LP
+-- The
+-- .I *_STR
+-- tables can be used to get a textual representation of the numbers, see also
+-- .IR class_tostring() ,
+-- .IR type_tostring() ,
+-- .IR opcode_tostring() ,
+-- .IR rcode_tostring() ,
+-- .IR afsdb_tostring() ,
+-- .I dhcid_tostring()
+-- and
+-- .IR edns0_tostring() .
+module(...,package.seeall)
+
+require("dnsjit.core.object.dns_h")
+local label = require("dnsjit.core.object.dns.label")
+local Q = require("dnsjit.core.object.dns.q")
+local RR = require("dnsjit.core.object.dns.rr")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_dns_t"
+local core_object_dns_t
+local Dns = {
+ CLASS = {
+ IN = 1,
+ CH = 3,
+ HS = 4,
+ NONE = 254,
+ ANY = 255,
+ },
+ TYPE = {
+ A = 1,
+ NS = 2,
+ MD = 3,
+ MF = 4,
+ CNAME = 5,
+ SOA = 6,
+ MB = 7,
+ MG = 8,
+ MR = 9,
+ NULL = 10,
+ WKS = 11,
+ PTR = 12,
+ HINFO = 13,
+ MINFO = 14,
+ MX = 15,
+ TXT = 16,
+ RP = 17,
+ AFSDB = 18,
+ X25 = 19,
+ ISDN = 20,
+ RT = 21,
+ NSAP = 22,
+ NSAP_PTR = 23,
+ SIG = 24,
+ KEY = 25,
+ PX = 26,
+ GPOS = 27,
+ AAAA = 28,
+ LOC = 29,
+ NXT = 30,
+ EID = 31,
+ NIMLOC = 32,
+ SRV = 33,
+ ATMA = 34,
+ NAPTR = 35,
+ KX = 36,
+ CERT = 37,
+ A6 = 38,
+ DNAME = 39,
+ SINK = 40,
+ OPT = 41,
+ APL = 42,
+ DS = 43,
+ SSHFP = 44,
+ IPSECKEY = 45,
+ RRSIG = 46,
+ NSEC = 47,
+ DNSKEY = 48,
+ DHCID = 49,
+ NSEC3 = 50,
+ NSEC3PARAM = 51,
+ TLSA = 52,
+ SMIMEA = 53,
+ HIP = 55,
+ NINFO = 56,
+ RKEY = 57,
+ TALINK = 58,
+ CDS = 59,
+ CDNSKEY = 60,
+ OPENPGPKEY = 61,
+ CSYNC = 62,
+ SPF = 99,
+ UINFO = 100,
+ UID = 101,
+ GID = 102,
+ UNSPEC = 103,
+ NID = 104,
+ L32 = 105,
+ L64 = 106,
+ LP = 107,
+ EUI48 = 108,
+ EUI64 = 109,
+ TKEY = 249,
+ TSIG = 250,
+ IXFR = 251,
+ AXFR = 252,
+ MAILB = 253,
+ MAILA = 254,
+ ANY = 255,
+ URI = 256,
+ CAA = 257,
+ AVC = 258,
+ TA = 32768,
+ DLV = 32769,
+ },
+ OPCODE = {
+ QUERY = 0,
+ IQUERY = 1,
+ STATUS = 2,
+ NOTIFY = 4,
+ UPDATE = 5,
+ },
+ RCODE = {
+ NOERROR = 0,
+ FORMERR = 1,
+ SERVFAIL = 2,
+ NXDOMAIN = 3,
+ NOTIMP = 4,
+ REFUSED = 5,
+ YXDOMAIN = 6,
+ YXRRSET = 7,
+ NXRRSET = 8,
+ NOTAUTH = 9,
+ NOTZONE = 10,
+ BADVERS = 16,
+ BADSIG = 16,
+ BADKEY = 17,
+ BADTIME = 18,
+ BADMODE = 19,
+ BADNAME = 20,
+ BADALG = 21,
+ BADTRUNC = 22,
+ BADCOOKIE = 23,
+ },
+ AFSDB = {
+ SUBTYPE_AFS3LOCSRV = 1,
+ SUBTYPE_DCENCA_ROOT = 2,
+ },
+ DHCID = {
+ TYPE_1OCTET = 0,
+ TYPE_DATAOCTET = 1,
+ TYPE_CLIENT_DUID = 2,
+ },
+ EDNS0 = {
+ OPT_LLQ = 1,
+ OPT_UL = 2,
+ OPT_NSID = 3,
+ OPT_DAU = 5,
+ OPT_DHU = 6,
+ OPT_N3U = 7,
+ OPT_CLIENT_SUBNET = 8,
+ OPT_EXPIRE = 9,
+ OPT_COOKIE = 10,
+ OPT_TCP_KEEPALIVE = 11,
+ OPT_PADDING = 12,
+ OPT_CHAIN = 13,
+ OPT_DEVICEID = 26946,
+ },
+}
+local _CLASS = {}
+_CLASS[Dns.CLASS.IN] = "IN"
+_CLASS[Dns.CLASS.CH] = "CH"
+_CLASS[Dns.CLASS.HS] = "HS"
+_CLASS[Dns.CLASS.NONE] = "NONE"
+_CLASS[Dns.CLASS.ANY] = "ANY"
+local _TYPE = {}
+_TYPE[Dns.TYPE.A] = "A"
+_TYPE[Dns.TYPE.NS] = "NS"
+_TYPE[Dns.TYPE.MD] = "MD"
+_TYPE[Dns.TYPE.MF] = "MF"
+_TYPE[Dns.TYPE.CNAME] = "CNAME"
+_TYPE[Dns.TYPE.SOA] = "SOA"
+_TYPE[Dns.TYPE.MB] = "MB"
+_TYPE[Dns.TYPE.MG] = "MG"
+_TYPE[Dns.TYPE.MR] = "MR"
+_TYPE[Dns.TYPE.NULL] = "NULL"
+_TYPE[Dns.TYPE.WKS] = "WKS"
+_TYPE[Dns.TYPE.PTR] = "PTR"
+_TYPE[Dns.TYPE.HINFO] = "HINFO"
+_TYPE[Dns.TYPE.MINFO] = "MINFO"
+_TYPE[Dns.TYPE.MX] = "MX"
+_TYPE[Dns.TYPE.TXT] = "TXT"
+_TYPE[Dns.TYPE.RP] = "RP"
+_TYPE[Dns.TYPE.AFSDB] = "AFSDB"
+_TYPE[Dns.TYPE.X25] = "X25"
+_TYPE[Dns.TYPE.ISDN] = "ISDN"
+_TYPE[Dns.TYPE.RT] = "RT"
+_TYPE[Dns.TYPE.NSAP] = "NSAP"
+_TYPE[Dns.TYPE.NSAP_PTR] = "NSAP_PTR"
+_TYPE[Dns.TYPE.SIG] = "SIG"
+_TYPE[Dns.TYPE.KEY] = "KEY"
+_TYPE[Dns.TYPE.PX] = "PX"
+_TYPE[Dns.TYPE.GPOS] = "GPOS"
+_TYPE[Dns.TYPE.AAAA] = "AAAA"
+_TYPE[Dns.TYPE.LOC] = "LOC"
+_TYPE[Dns.TYPE.NXT] = "NXT"
+_TYPE[Dns.TYPE.EID] = "EID"
+_TYPE[Dns.TYPE.NIMLOC] = "NIMLOC"
+_TYPE[Dns.TYPE.SRV] = "SRV"
+_TYPE[Dns.TYPE.ATMA] = "ATMA"
+_TYPE[Dns.TYPE.NAPTR] = "NAPTR"
+_TYPE[Dns.TYPE.KX] = "KX"
+_TYPE[Dns.TYPE.CERT] = "CERT"
+_TYPE[Dns.TYPE.A6] = "A6"
+_TYPE[Dns.TYPE.DNAME] = "DNAME"
+_TYPE[Dns.TYPE.SINK] = "SINK"
+_TYPE[Dns.TYPE.OPT] = "OPT"
+_TYPE[Dns.TYPE.APL] = "APL"
+_TYPE[Dns.TYPE.DS] = "DS"
+_TYPE[Dns.TYPE.SSHFP] = "SSHFP"
+_TYPE[Dns.TYPE.IPSECKEY] = "IPSECKEY"
+_TYPE[Dns.TYPE.RRSIG] = "RRSIG"
+_TYPE[Dns.TYPE.NSEC] = "NSEC"
+_TYPE[Dns.TYPE.DNSKEY] = "DNSKEY"
+_TYPE[Dns.TYPE.DHCID] = "DHCID"
+_TYPE[Dns.TYPE.NSEC3] = "NSEC3"
+_TYPE[Dns.TYPE.NSEC3PARAM] = "NSEC3PARAM"
+_TYPE[Dns.TYPE.TLSA] = "TLSA"
+_TYPE[Dns.TYPE.SMIMEA] = "SMIMEA"
+_TYPE[Dns.TYPE.HIP] = "HIP"
+_TYPE[Dns.TYPE.NINFO] = "NINFO"
+_TYPE[Dns.TYPE.RKEY] = "RKEY"
+_TYPE[Dns.TYPE.TALINK] = "TALINK"
+_TYPE[Dns.TYPE.CDS] = "CDS"
+_TYPE[Dns.TYPE.CDNSKEY] = "CDNSKEY"
+_TYPE[Dns.TYPE.OPENPGPKEY] = "OPENPGPKEY"
+_TYPE[Dns.TYPE.CSYNC] = "CSYNC"
+_TYPE[Dns.TYPE.SPF] = "SPF"
+_TYPE[Dns.TYPE.UINFO] = "UINFO"
+_TYPE[Dns.TYPE.UID] = "UID"
+_TYPE[Dns.TYPE.GID] = "GID"
+_TYPE[Dns.TYPE.UNSPEC] = "UNSPEC"
+_TYPE[Dns.TYPE.NID] = "NID"
+_TYPE[Dns.TYPE.L32] = "L32"
+_TYPE[Dns.TYPE.L64] = "L64"
+_TYPE[Dns.TYPE.LP] = "LP"
+_TYPE[Dns.TYPE.EUI48] = "EUI48"
+_TYPE[Dns.TYPE.EUI64] = "EUI64"
+_TYPE[Dns.TYPE.TKEY] = "TKEY"
+_TYPE[Dns.TYPE.TSIG] = "TSIG"
+_TYPE[Dns.TYPE.IXFR] = "IXFR"
+_TYPE[Dns.TYPE.AXFR] = "AXFR"
+_TYPE[Dns.TYPE.MAILB] = "MAILB"
+_TYPE[Dns.TYPE.MAILA] = "MAILA"
+_TYPE[Dns.TYPE.ANY] = "ANY"
+_TYPE[Dns.TYPE.URI] = "URI"
+_TYPE[Dns.TYPE.CAA] = "CAA"
+_TYPE[Dns.TYPE.AVC] = "AVC"
+_TYPE[Dns.TYPE.TA] = "TA"
+_TYPE[Dns.TYPE.DLV] = "DLV"
+local _OPCODE = {}
+_OPCODE[Dns.OPCODE.QUERY] = "QUERY"
+_OPCODE[Dns.OPCODE.IQUERY] = "IQUERY"
+_OPCODE[Dns.OPCODE.STATUS] = "STATUS"
+_OPCODE[Dns.OPCODE.NOTIFY] = "NOTIFY"
+_OPCODE[Dns.OPCODE.UPDATE] = "UPDATE"
+local _RCODE = {}
+_RCODE[Dns.RCODE.NOERROR] = "NOERROR"
+_RCODE[Dns.RCODE.FORMERR] = "FORMERR"
+_RCODE[Dns.RCODE.SERVFAIL] = "SERVFAIL"
+_RCODE[Dns.RCODE.NXDOMAIN] = "NXDOMAIN"
+_RCODE[Dns.RCODE.NOTIMP] = "NOTIMP"
+_RCODE[Dns.RCODE.REFUSED] = "REFUSED"
+_RCODE[Dns.RCODE.YXDOMAIN] = "YXDOMAIN"
+_RCODE[Dns.RCODE.YXRRSET] = "YXRRSET"
+_RCODE[Dns.RCODE.NXRRSET] = "NXRRSET"
+_RCODE[Dns.RCODE.NOTAUTH] = "NOTAUTH"
+_RCODE[Dns.RCODE.NOTZONE] = "NOTZONE"
+_RCODE[Dns.RCODE.BADVERS] = "BADVERS"
+_RCODE[Dns.RCODE.BADSIG] = "BADSIG"
+_RCODE[Dns.RCODE.BADKEY] = "BADKEY"
+_RCODE[Dns.RCODE.BADTIME] = "BADTIME"
+_RCODE[Dns.RCODE.BADMODE] = "BADMODE"
+_RCODE[Dns.RCODE.BADNAME] = "BADNAME"
+_RCODE[Dns.RCODE.BADALG] = "BADALG"
+_RCODE[Dns.RCODE.BADTRUNC] = "BADTRUNC"
+_RCODE[Dns.RCODE.BADCOOKIE] = "BADCOOKIE"
+local _AFSDB = {}
+_AFSDB[Dns.AFSDB.SUBTYPE_AFS3LOCSRV] = "SUBTYPE_AFS3LOCSRV"
+_AFSDB[Dns.AFSDB.SUBTYPE_DCENCA_ROOT] = "SUBTYPE_DCENCA_ROOT"
+local _DHCID = {}
+_DHCID[Dns.DHCID.TYPE_1OCTET] = "TYPE_1OCTET"
+_DHCID[Dns.DHCID.TYPE_DATAOCTET] = "TYPE_DATAOCTET"
+_DHCID[Dns.DHCID.TYPE_CLIENT_DUID] = "TYPE_CLIENT_DUID"
+local _EDNS0 = {}
+_EDNS0[Dns.EDNS0.OPT_LLQ] = "OPT_LLQ"
+_EDNS0[Dns.EDNS0.OPT_UL] = "OPT_UL"
+_EDNS0[Dns.EDNS0.OPT_NSID] = "OPT_NSID"
+_EDNS0[Dns.EDNS0.OPT_DAU] = "OPT_DAU"
+_EDNS0[Dns.EDNS0.OPT_DHU] = "OPT_DHU"
+_EDNS0[Dns.EDNS0.OPT_N3U] = "OPT_N3U"
+_EDNS0[Dns.EDNS0.OPT_CLIENT_SUBNET] = "OPT_CLIENT_SUBNET"
+_EDNS0[Dns.EDNS0.OPT_EXPIRE] = "OPT_EXPIRE"
+_EDNS0[Dns.EDNS0.OPT_COOKIE] = "OPT_COOKIE"
+_EDNS0[Dns.EDNS0.OPT_TCP_KEEPALIVE] = "OPT_TCP_KEEPALIVE"
+_EDNS0[Dns.EDNS0.OPT_PADDING] = "OPT_PADDING"
+_EDNS0[Dns.EDNS0.OPT_CHAIN] = "OPT_CHAIN"
+_EDNS0[Dns.EDNS0.OPT_DEVICEID] = "OPT_DEVICEID"
+Dns.CLASS_STR = _CLASS
+Dns.TYPE_STR = _TYPE
+Dns.OPCODE_STR = _OPCODE
+Dns.RCODE_STR = _RCODE
+Dns.AFSDB_STR = _AFSDB
+Dns.DHCID_STR = _DHCID
+Dns.EDNS0_STR = _EDNS0
+
+-- Create a new DNS object, optionally on-top of another object.
+function Dns.new(obj)
+ local self = C.core_object_dns_new()
+ self.obj_prev = obj
+ ffi.gc(self, C.core_object_dns_free)
+ return self
+end
+
+-- Return the textual type of the object.
+function Dns:type()
+ return "dns"
+end
+
+-- Return the previous object.
+function Dns:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Dns:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Dns:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Dns:copy()
+ return C.core_object_dns_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Dns:free()
+ C.core_object_dns_free(self)
+end
+
+-- Return the Log object to control logging of this module.
+function Dns:log()
+ return C.core_object_dns_log()
+end
+
+-- Begin parsing the underlaying object, first the header is parsed then
+-- optionally continue calling
+-- .IR parse_q ()
+-- for the number of questions (see
+-- .IR qdcount ).
+-- After that continue calling
+-- .IR parse_rr ()
+-- for the number of answers, authorities and additionals resource records
+-- (see
+-- .IR ancount ", "
+-- .I nscount
+-- and
+-- .IR arcount ).
+-- Returns 0 on success or negative integer on error which can be for
+-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
+function Dns:parse_header()
+ return C.core_object_dns_parse_header(self)
+end
+
+-- Parse the next resource record as a question.
+-- Returns 0 on success or negative integer on error which can be for
+-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
+function Dns:parse_q(q, labels, num_labels)
+ return C.core_object_dns_parse_q(self, q, labels, num_labels)
+end
+
+-- Parse the next resource record.
+-- Returns 0 on success or negative integer on error which can be for
+-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
+function Dns:parse_rr(rr, labels, num_labels)
+ return C.core_object_dns_parse_rr(self, rr, labels, num_labels)
+end
+
+-- Begin parsing the underlaying object using
+-- .IR parse_header "(), "
+-- .IR parse_q ()
+-- and
+-- .IR parse_rr ().
+-- The optional
+-- .I num_labels
+-- can be used to set a specific number of labels used for each question
+-- and resource record (default 16).
+-- Returns result code, an array of questions, an array of question labels,
+-- an array of resource records and an array of resource records labels.
+-- Result code is 0 on success or negative integer on error which can be for
+-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
+function Dns:parse(num_labels)
+ local qs, qls, rrs, rrls = {}, {}, {}, {}
+ if num_labels == nil then
+ num_labels = 16
+ end
+
+ ret = self:parse_header()
+ if ret ~= 0 then
+ return ret, qs, qls, rrs, rrls
+ end
+ for n = 1, self.qdcount do
+ local labels = label.new(num_labels)
+ local q = Q.new()
+ local ret = C.core_object_dns_parse_q(self, q, labels, num_labels)
+
+ if ret ~= 0 then
+ return ret, qs, qls, rrs, rrls
+ end
+ table.insert(qs, q)
+ table.insert(qls, labels)
+ end
+ for n = 1, self.ancount do
+ local labels = label.new(num_labels)
+ local rr = RR.new()
+ local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
+
+ if ret ~= 0 then
+ return ret, qs, qls, rrs, rrls
+ end
+ table.insert(rrs, rr)
+ table.insert(rrls, labels)
+ end
+ for n = 1, self.nscount do
+ local labels = label.new(num_labels)
+ local rr = RR.new()
+ local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
+
+ if ret ~= 0 then
+ return ret, qs, qls, rrs, rrls
+ end
+ table.insert(rrs, rr)
+ table.insert(rrls, labels)
+ end
+ for n = 1, self.arcount do
+ local labels = label.new(num_labels)
+ local rr = RR.new()
+ local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
+
+ if ret ~= 0 then
+ return ret, qs, qls, rrs, rrls
+ end
+ table.insert(rrs, rr)
+ table.insert(rrls, labels)
+ end
+
+ return 0, qs, qls, rrs, rrls
+end
+
+-- Begin parsing the underlaying object using
+-- .IR parse_header "(), "
+-- .IR parse_q ()
+-- and
+-- .IR parse_rr (),
+-- and print it's content.
+-- The optional
+-- .I num_labels
+-- can be used to set a specific number of labels used for each question
+-- and resource record (default 16).
+function Dns:print(num_labels)
+ if num_labels == nil then
+ num_labels = 16
+ end
+ local labels = label.new(num_labels)
+ local q = Q.new()
+ local rr = RR.new()
+
+ if self:parse_header() ~= 0 then
+ return
+ end
+
+ local flags = {}
+ if self.have_aa and self.aa == 1 then
+ table.insert(flags, "AA")
+ end
+ if self.have_tc and self.tc == 1 then
+ table.insert(flags, "TC")
+ end
+ if self.have_rd and self.rd == 1 then
+ table.insert(flags, "RD")
+ end
+ if self.have_ra and self.ra == 1 then
+ table.insert(flags, "RA")
+ end
+ if self.have_z and self.z == 1 then
+ table.insert(flags, "Z")
+ end
+ if self.have_ad and self.ad == 1 then
+ table.insert(flags, "AD")
+ end
+ if self.have_cd and self.cd == 1 then
+ table.insert(flags, "CD")
+ end
+
+ print("id:", self.id)
+ print("", "qr:", self.qr)
+ print("", "opcode:", Dns.opcode_tostring(self.opcode))
+ print("", "flags:", table.concat(flags, " "))
+ print("", "rcode:", Dns.rcode_tostring(self.rcode))
+ print("", "qdcount:", self.qdcount)
+ print("", "ancount:", self.ancount)
+ print("", "nscount:", self.nscount)
+ print("", "arcount:", self.arcount)
+
+ if self.qdcount > 0 then
+ print("questions:", "class", "type", "labels")
+ for n = 1, self.qdcount do
+ if C.core_object_dns_parse_q(self, q, labels, num_labels) ~= 0 then
+ return
+ end
+ print("", Dns.class_tostring(q.class), Dns.type_tostring(q.type), label.tooffstr(self, labels, num_labels))
+ end
+ end
+ if self.ancount > 0 then
+ print("answers:", "class", "type", "ttl", "labels", "RR labels")
+ for n = 1, self.ancount do
+ if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
+ return
+ end
+ if rr.rdata_labels == 0 then
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
+ else
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
+ end
+ end
+ end
+ if self.nscount > 0 then
+ print("authorities:", "class", "type", "ttl", "labels", "RR labels")
+ for n = 1, self.nscount do
+ if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
+ return
+ end
+ if rr.rdata_labels == 0 then
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
+ else
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
+ end
+ end
+ end
+ if self.arcount > 0 then
+ print("additionals:", "class", "type", "ttl", "labels", "RR labels")
+ for n = 1, self.arcount do
+ if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
+ return
+ end
+ if rr.rdata_labels == 0 then
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
+ else
+ print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
+ end
+ end
+ end
+end
+
+-- Return the textual name for a class.
+function Dns.class_tostring(class)
+ if Dns.CLASS_STR[class] == nil then
+ return "UNKNOWN("..class..")"
+ end
+ return Dns.CLASS_STR[class]
+end
+
+-- Return the textual name for a type.
+function Dns.type_tostring(type)
+ if Dns.TYPE_STR[type] == nil then
+ return "UNKNOWN("..type..")"
+ end
+ return Dns.TYPE_STR[type]
+end
+
+-- Return the textual name for an opcode.
+function Dns.opcode_tostring(opcode)
+ if Dns.OPCODE_STR[opcode] == nil then
+ return "UNKNOWN("..opcode..")"
+ end
+ return Dns.OPCODE_STR[opcode]
+end
+
+-- Return the textual name for a rcode.
+function Dns.rcode_tostring(rcode)
+ if Dns.RCODE_STR[rcode] == nil then
+ return "UNKNOWN("..rcode..")"
+ end
+ return Dns.RCODE_STR[rcode]
+end
+
+-- Return the textual name for an afsdb subtype.
+function Dns.afsdb_tostring(afsdb)
+ if Dns.AFSDB_STR[afsdb] == nil then
+ return "UNKNOWN("..afsdb..")"
+ end
+ return Dns.AFSDB_STR[afsdb]
+end
+
+-- Return the textual name for a dhcid type.
+function Dns.dhcid_tostring(dhcid)
+ if Dns.DHCID_STR[dhcid] == nil then
+ return "UNKNOWN("..dhcid..")"
+ end
+ return Dns.DHCID_STR[dhcid]
+end
+
+-- Return the textual name for an EDNS0 OPT record.
+function Dns.edns0_tostring(edns0)
+ if Dns.EDNS0_STR[edns0] == nil then
+ return "UNKNOWN("..edns0..")"
+ end
+ return Dns.EDNS0_STR[edns0]
+end
+
+core_object_dns_t = ffi.metatype(t_name, { __index = Dns })
+
+-- dnsjit.core.object (3),
+-- dnsjit.core.object.payload (3),
+-- dnsjit.core.object.dns.label (3),
+-- dnsjit.core.object.dns.q (3),
+-- dnsjit.core.object.dns.rr (3)
+return Dns
diff --git a/src/core/object/dns/label.lua b/src/core/object/dns/label.lua
new file mode 100644
index 0000000..bc78758
--- /dev/null
+++ b/src/core/object/dns/label.lua
@@ -0,0 +1,118 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.dns.label
+-- Container of a DNS label
+--
+-- The object that describes a DNS label.
+-- To extract a domain name label first check that
+-- .I have_dn
+-- is set, then use
+-- .I "offset + 1"
+-- to indicate where in the payload the label start and
+-- .I length
+-- for how many bytes long it is.
+-- .SS Attributes
+-- .TP
+-- is_end
+-- .TP
+-- have_length
+-- Set if there is a length.
+-- .TP
+-- have_offset
+-- Set if there is an offset.
+-- .TP
+-- have_extension_bits
+-- Set if there is extension bits.
+-- .TP
+-- have_dn
+-- Set if the label contained a domain name.
+-- .TP
+-- extension_bits
+-- The extension bits.
+-- .TP
+-- length
+-- The length of the domain name.
+-- .TP
+-- offset
+-- If
+-- .I have_dn
+-- is set then this contains the offset within the payload to where this label
+-- start otherwise it contains the offset to another label.
+module(...,package.seeall)
+
+require("dnsjit.core.object.dns_h")
+local ffi = require("ffi")
+
+local Label = {}
+
+-- Create a new array of labels.
+function Label.new(size)
+ return ffi.new("core_object_dns_label_t[?]", size)
+end
+
+-- Returns labels as a string and an offset to the next label.
+-- The string may be nil if the first label was an offset.
+-- The offset may be nil if the last label was an extension bits or end marker.
+function Label.tostring(dns, labels, num_labels, offset_labels)
+ if offset_labels == nil then
+ offset_labels = 0
+ end
+ local dn
+ for n = 1, tonumber(num_labels) do
+ local label = labels[n - 1 + offset_labels]
+
+ if label.have_dn == 1 then
+ if dn == nil then
+ dn = ""
+ end
+ dn = dn .. ffi.string(dns.payload + label.offset + 1, label.length) .. "."
+ elseif label.have_offset == 1 then
+ return dn, label.offset
+ else
+ return dn, nil
+ end
+ end
+ return dn, nil
+end
+
+-- Returns labels as a string which also includes a textual notation of the
+-- offset in the form of
+-- .IR "<offset>label" .
+function Label.tooffstr(dns, labels, num_labels, offset_labels)
+ if offset_labels == nil then
+ offset_labels = 0
+ end
+ local dn = ""
+ for n = 1, tonumber(num_labels) do
+ local label = labels[n - 1 + offset_labels]
+
+ if label.have_dn == 1 then
+ dn = dn .. "<" .. tonumber(label.offset) .. ">" .. ffi.string(dns.payload + label.offset + 1, label.length) .. "."
+ elseif label.have_offset == 1 then
+ dn = dn .. "<" .. tonumber(label.offset) .. ">"
+ break
+ else
+ break
+ end
+ end
+ return dn
+end
+
+-- dnsjit.core.object.dns (3)
+return Label
diff --git a/src/core/object/dns/q.lua b/src/core/object/dns/q.lua
new file mode 100644
index 0000000..f65d9e8
--- /dev/null
+++ b/src/core/object/dns/q.lua
@@ -0,0 +1,52 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.dns.q
+-- Container of a DNS question
+--
+-- The object that describes a DNS question.
+-- .SS Attributes
+-- .TP
+-- have_type
+-- Set if there is a type.
+-- .TP
+-- have_class
+-- Set if there is a class.
+-- .TP
+-- type
+-- The type.
+-- .TP
+-- class
+-- The class.
+-- .TP
+-- labels
+-- The number of labels found in the question.
+module(...,package.seeall)
+
+require("dnsjit.core.object.dns_h")
+local ffi = require("ffi")
+
+local Q = {}
+
+-- Create a new question.
+function Q.new(size)
+ return ffi.new("core_object_dns_q_t")
+end
+
+-- dnsjit.core.object.dns (3)
+return Q
diff --git a/src/core/object/dns/rr.lua b/src/core/object/dns/rr.lua
new file mode 100644
index 0000000..d360d96
--- /dev/null
+++ b/src/core/object/dns/rr.lua
@@ -0,0 +1,85 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.dns.rr
+-- Container of a DNS resource record
+--
+-- The object that describes a DNS resource record.
+-- .SS Attributes
+-- .TP
+-- have_type
+-- Set if there is a type.
+-- .TP
+-- have_class
+-- Set if there is a class.
+-- .TP
+-- have_ttl
+-- Set if there is a ttl.
+-- .TP
+-- have_rdlength
+-- Set if there is a rdlength.
+-- .TP
+-- have_rdata
+-- Set if there is resource record data.
+-- .TP
+-- have_rdata_labels
+-- Set if there are any labels within the rdata.
+-- .TP
+-- have_padding
+-- Set if there is padding.
+-- .TP
+-- type
+-- The type.
+-- .TP
+-- class
+-- The class.
+-- .TP
+-- ttl
+-- The TTL.
+-- .TP
+-- rdlength
+-- The resource record data length.
+-- .TP
+-- labels
+-- The number of labels found in the record.
+-- .TP
+-- rdata_offset
+-- The offset within the payload for the resource record data.
+-- .TP
+-- rdata_labels
+-- The number of labels found inside the resource record data.
+-- .TP
+-- padding_offset
+-- The offset within the payload where the padding starts.
+-- .TP
+-- padding_length
+-- The length of the padding.
+module(...,package.seeall)
+
+require("dnsjit.core.object.dns_h")
+local ffi = require("ffi")
+
+local Rr = {}
+
+-- Create a new resource record.
+function Rr.new()
+ return ffi.new("core_object_dns_rr_t")
+end
+
+-- dnsjit.core.object.dns (3)
+return Rr
diff --git a/src/core/object/ether.c b/src/core/object/ether.c
new file mode 100644
index 0000000..dd7cd98
--- /dev/null
+++ b/src/core/object/ether.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/ether.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_ether_t* core_object_ether_copy(const core_object_ether_t* self)
+{
+ core_object_ether_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_ether_t)));
+ memcpy(copy, self, sizeof(core_object_ether_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_ether_free(core_object_ether_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/ether.h b/src/core/object/ether.h
new file mode 100644
index 0000000..e35ecb2
--- /dev/null
+++ b/src/core/object/ether.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_ether_h
+#define __dnsjit_core_object_ether_h
+
+#include <stddef.h>
+
+#include "core/object/ether.hh"
+
+#define CORE_OBJECT_ETHER_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_ETHER, prev) \
+ , \
+ { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, 0 \
+ }
+
+#endif
diff --git a/src/core/object/ether.hh b/src/core/object/ether.hh
new file mode 100644
index 0000000..3b7a0cc
--- /dev/null
+++ b/src/core/object/ether.hh
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_ether {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint8_t dhost[6];
+ uint8_t shost[6];
+ uint16_t type;
+} core_object_ether_t;
+
+core_object_ether_t* core_object_ether_copy(const core_object_ether_t* self);
+void core_object_ether_free(core_object_ether_t* self);
diff --git a/src/core/object/ether.lua b/src/core/object/ether.lua
new file mode 100644
index 0000000..3359d1f
--- /dev/null
+++ b/src/core/object/ether.lua
@@ -0,0 +1,78 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.ether
+-- Ether part of a packet
+--
+-- The ether part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- dhost
+-- The destination ether address.
+-- .TP
+-- shost
+-- The source ether address.
+-- .TP
+-- type
+-- The packet type ID field / EtherType field.
+module(...,package.seeall)
+
+require("dnsjit.core.object.ether_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_ether_t"
+local core_object_ether_t
+local Ether = {}
+
+-- Return the textual type of the object.
+function Ether:type()
+ return "ether"
+end
+
+-- Return the previous object.
+function Ether:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Ether:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Ether:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Ether:copy()
+ return C.core_object_ether_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Ether:free()
+ C.core_object_ether_free(self)
+end
+
+core_object_ether_t = ffi.metatype(t_name, { __index = Ether })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Ether
diff --git a/src/core/object/gre.c b/src/core/object/gre.c
new file mode 100644
index 0000000..9a467c3
--- /dev/null
+++ b/src/core/object/gre.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/gre.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_gre_t* core_object_gre_copy(const core_object_gre_t* self)
+{
+ core_object_gre_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_gre_t)));
+ memcpy(copy, self, sizeof(core_object_gre_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_gre_free(core_object_gre_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/gre.h b/src/core/object/gre.h
new file mode 100644
index 0000000..8efa93c
--- /dev/null
+++ b/src/core/object/gre.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_gre_h
+#define __dnsjit_core_object_gre_h
+
+#include <stddef.h>
+
+#include "core/object/gre.hh"
+
+#define CORE_OBJECT_GRE_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_GRE, prev) \
+ , \
+ 0, 0, 0, 0, 0 \
+ }
+
+#endif
diff --git a/src/core/object/gre.hh b/src/core/object/gre.hh
new file mode 100644
index 0000000..67a89b1
--- /dev/null
+++ b/src/core/object/gre.hh
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_gre {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint16_t gre_flags;
+ uint16_t ether_type;
+ uint16_t checksum;
+ uint16_t offset;
+ uint32_t key;
+ uint32_t sequence;
+ // TODO: routing list, check RFC 1701.
+} core_object_gre_t;
+
+core_object_gre_t* core_object_gre_copy(const core_object_gre_t* self);
+void core_object_gre_free(core_object_gre_t* self);
diff --git a/src/core/object/gre.lua b/src/core/object/gre.lua
new file mode 100644
index 0000000..703b02f
--- /dev/null
+++ b/src/core/object/gre.lua
@@ -0,0 +1,87 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.gre
+-- Generic Routing Encapsulation (GRE) part of a packet
+--
+-- The GRE part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- See RFC 1701.
+-- .SS Attributes
+-- .TP
+-- gre_flags
+-- The GRE flags.
+-- .TP
+-- ether_type
+-- The protocol type of the payload packet.
+-- .TP
+-- checksum
+-- The checksum of the GRE header and the payload packet.
+-- .TP
+-- key
+-- The Key field contains a four octet number which was inserted by
+-- the encapsulator.
+-- .TP
+-- sequence
+-- The Sequence Number field contains an unsigned 32 bit integer which is
+-- inserted by the encapsulator.
+module(...,package.seeall)
+
+require("dnsjit.core.object.gre_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_gre_t"
+local core_object_gre_t
+local Gre = {}
+
+-- Return the textual type of the object.
+function Gre:type()
+ return "gre"
+end
+
+-- Return the previous object.
+function Gre:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Gre:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Gre:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Gre:copy()
+ return C.core_object_gre_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Gre:free()
+ C.core_object_gre_free(self)
+end
+
+core_object_gre_t = ffi.metatype(t_name, { __index = Gre })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Gre
diff --git a/src/core/object/icmp.c b/src/core/object/icmp.c
new file mode 100644
index 0000000..ebd13dc
--- /dev/null
+++ b/src/core/object/icmp.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/icmp.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_icmp_t* core_object_icmp_copy(const core_object_icmp_t* self)
+{
+ core_object_icmp_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_icmp_t)));
+ memcpy(copy, self, sizeof(core_object_icmp_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_icmp_free(core_object_icmp_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/icmp.h b/src/core/object/icmp.h
new file mode 100644
index 0000000..346a3ea
--- /dev/null
+++ b/src/core/object/icmp.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_icmp_h
+#define __dnsjit_core_object_icmp_h
+
+#include <stddef.h>
+
+#include "core/object/icmp.hh"
+
+#define CORE_OBJECT_ICMP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_ICMP, prev) \
+ , \
+ 0, 0, 0 \
+ }
+
+#endif
diff --git a/src/core/object/icmp.hh b/src/core/object/icmp.hh
new file mode 100644
index 0000000..1a7aa88
--- /dev/null
+++ b/src/core/object/icmp.hh
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_icmp {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint8_t type;
+ uint8_t code;
+ uint16_t cksum;
+} core_object_icmp_t;
+
+core_object_icmp_t* core_object_icmp_copy(const core_object_icmp_t* self);
+void core_object_icmp_free(core_object_icmp_t* self);
diff --git a/src/core/object/icmp.lua b/src/core/object/icmp.lua
new file mode 100644
index 0000000..52062ad
--- /dev/null
+++ b/src/core/object/icmp.lua
@@ -0,0 +1,78 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.icmp
+-- An ICMP packet
+--
+-- An ICMP packet which is usually at the top of the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- type
+-- The type of ICMP message.
+-- .TP
+-- code
+-- The (response/error) code for the ICMP type message.
+-- .TP
+-- cksum
+-- The ICMP checksum.
+module(...,package.seeall)
+
+require("dnsjit.core.object.icmp_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_icmp_t"
+local core_object_icmp_t
+local Icmp = {}
+
+-- Return the textual type of the object.
+function Icmp:type()
+ return "icmp"
+end
+
+-- Return the previous object.
+function Icmp:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Icmp:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Icmp:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Icmp:copy()
+ return C.core_object_icmp_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Icmp:free()
+ C.core_object_icmp_free(self)
+end
+
+core_object_icmp_t = ffi.metatype(t_name, { __index = Icmp })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Icmp
diff --git a/src/core/object/icmp6.c b/src/core/object/icmp6.c
new file mode 100644
index 0000000..b79fb17
--- /dev/null
+++ b/src/core/object/icmp6.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/icmp6.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_icmp6_t* core_object_icmp6_copy(const core_object_icmp6_t* self)
+{
+ core_object_icmp6_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_icmp6_t)));
+ memcpy(copy, self, sizeof(core_object_icmp6_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_icmp6_free(core_object_icmp6_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/icmp6.h b/src/core/object/icmp6.h
new file mode 100644
index 0000000..569bf7f
--- /dev/null
+++ b/src/core/object/icmp6.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_icmp6_h
+#define __dnsjit_core_object_icmp6_h
+
+#include <stddef.h>
+
+#include "core/object/icmp6.hh"
+
+#define CORE_OBJECT_ICMP6_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_ICMP6, prev) \
+ , \
+ 0, 0, 0 \
+ }
+
+#endif
diff --git a/src/core/object/icmp6.hh b/src/core/object/icmp6.hh
new file mode 100644
index 0000000..2aa1ed4
--- /dev/null
+++ b/src/core/object/icmp6.hh
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_icmp6 {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint8_t type;
+ uint8_t code;
+ uint16_t cksum;
+} core_object_icmp6_t;
+
+core_object_icmp6_t* core_object_icmp6_copy(const core_object_icmp6_t* self);
+void core_object_icmp6_free(core_object_icmp6_t* self);
diff --git a/src/core/object/icmp6.lua b/src/core/object/icmp6.lua
new file mode 100644
index 0000000..a3929bf
--- /dev/null
+++ b/src/core/object/icmp6.lua
@@ -0,0 +1,78 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.icmp6
+-- An ICMPv6 packet
+--
+-- An ICMPv6 packet which is usually at the top of the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- type
+-- The type of ICMPv6 message.
+-- .TP
+-- code
+-- The (response/error) code for the ICMPv6 type message.
+-- .TP
+-- cksum
+-- The ICMPv6 checksum.
+module(...,package.seeall)
+
+require("dnsjit.core.object.icmp6_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_icmp6_t"
+local core_object_icmp6_t
+local Icmp6 = {}
+
+-- Return the textual type of the object.
+function Icmp6:type()
+ return "icmp6"
+end
+
+-- Return the previous object.
+function Icmp6:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Icmp6:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Icmp6:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Icmp6:copy()
+ return C.core_object_icmp6_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Icmp6:free()
+ C.core_object_icmp6_free(self)
+end
+
+core_object_icmp6_t = ffi.metatype(t_name, { __index = Icmp6 })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Icmp6
diff --git a/src/core/object/ieee802.c b/src/core/object/ieee802.c
new file mode 100644
index 0000000..80dd4ea
--- /dev/null
+++ b/src/core/object/ieee802.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/ieee802.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_ieee802_t* core_object_ieee802_copy(const core_object_ieee802_t* self)
+{
+ core_object_ieee802_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_ieee802_t)));
+ memcpy(copy, self, sizeof(core_object_ieee802_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_ieee802_free(core_object_ieee802_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/ieee802.h b/src/core/object/ieee802.h
new file mode 100644
index 0000000..ca4847c
--- /dev/null
+++ b/src/core/object/ieee802.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_ieee802_h
+#define __dnsjit_core_object_ieee802_h
+
+#include <stddef.h>
+
+#include "core/object/ieee802.hh"
+
+#define CORE_OBJECT_IEEE802_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_IEEE802, prev) \
+ , \
+ 0, 0, 0, 0, 0 \
+ }
+
+#endif
diff --git a/src/core/object/ieee802.hh b/src/core/object/ieee802.hh
new file mode 100644
index 0000000..1bce670
--- /dev/null
+++ b/src/core/object/ieee802.hh
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_ieee802 {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint16_t tpid;
+ uint8_t pcp;
+ uint8_t dei;
+ uint8_t vid;
+ uint16_t ether_type;
+} core_object_ieee802_t;
+
+core_object_ieee802_t* core_object_ieee802_copy(const core_object_ieee802_t* self);
+void core_object_ieee802_free(core_object_ieee802_t* self);
diff --git a/src/core/object/ieee802.lua b/src/core/object/ieee802.lua
new file mode 100644
index 0000000..77519ef
--- /dev/null
+++ b/src/core/object/ieee802.lua
@@ -0,0 +1,84 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.ieee802
+-- IEEE802 part of a packet
+--
+-- The IEEE802 part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- tpid
+-- Tag protocol identifier.
+-- .TP
+-- pcp
+-- Priority code point.
+-- .TP
+-- dei
+-- Drop eligible indicator.
+-- .TP
+-- vid
+-- VLAN identifier.
+-- .TP
+-- ether_type
+-- The packet type ID field / EtherType field.
+module(...,package.seeall)
+
+require("dnsjit.core.object.ieee802_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_ieee802_t"
+local core_object_ieee802_t
+local Ieee802 = {}
+
+-- Return the textual type of the object.
+function Ieee802:type()
+ return "ieee802"
+end
+
+-- Return the previous object.
+function Ieee802:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Ieee802:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Ieee802:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Ieee802:copy()
+ return C.core_object_ieee802_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Ieee802:free()
+ C.core_object_ieee802_free(self)
+end
+
+core_object_ieee802_t = ffi.metatype(t_name, { __index = Ieee802 })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Ieee802
diff --git a/src/core/object/ip.c b/src/core/object/ip.c
new file mode 100644
index 0000000..4e50b60
--- /dev/null
+++ b/src/core/object/ip.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/ip.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_ip_t* core_object_ip_copy(const core_object_ip_t* self)
+{
+ core_object_ip_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_ip_t)));
+ memcpy(copy, self, sizeof(core_object_ip_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_ip_free(core_object_ip_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/ip.h b/src/core/object/ip.h
new file mode 100644
index 0000000..c2b9312
--- /dev/null
+++ b/src/core/object/ip.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_ip_h
+#define __dnsjit_core_object_ip_h
+
+#include <stddef.h>
+
+#include "core/object/ip.hh"
+
+#define CORE_OBJECT_IP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_IP, prev) \
+ , \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, \
+ }
+
+#endif
diff --git a/src/core/object/ip.hh b/src/core/object/ip.hh
new file mode 100644
index 0000000..9a379a4
--- /dev/null
+++ b/src/core/object/ip.hh
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_ip {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint8_t v;
+ uint8_t hl;
+ uint8_t tos;
+ uint16_t len;
+ uint16_t id;
+ uint16_t off;
+ uint8_t ttl;
+ uint8_t p;
+ uint16_t sum;
+ uint8_t src[4], dst[4];
+} core_object_ip_t;
+
+core_object_ip_t* core_object_ip_copy(const core_object_ip_t* self);
+void core_object_ip_free(core_object_ip_t* self);
diff --git a/src/core/object/ip.lua b/src/core/object/ip.lua
new file mode 100644
index 0000000..0294612
--- /dev/null
+++ b/src/core/object/ip.lua
@@ -0,0 +1,122 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.ip
+-- An IP packet
+--
+-- An IP packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- v
+-- Version.
+-- .TP
+-- hl
+-- Header length.
+-- .TP
+-- tos
+-- Type of service.
+-- .TP
+-- len
+-- Total length.
+-- .TP
+-- id
+-- Identification.
+-- .TP
+-- off
+-- Fragment offset field.
+-- .TP
+-- ttl
+-- Time to live.
+-- .TP
+-- p
+-- Protocol.
+-- .TP
+-- sum
+-- Checksum.
+-- .TP
+-- src
+-- Source address.
+-- .TP
+-- dst
+-- Destination address.
+-- .TP
+-- payload
+-- A pointer to the payload.
+-- .TP
+-- plen
+-- The length of the payload.
+-- .TP
+-- pad_len
+-- The length of padding found, if any.
+module(...,package.seeall)
+
+require("dnsjit.core.object.ip_h")
+local ffi = require("ffi")
+local C = ffi.C
+local libip = require("dnsjit.lib.ip")
+
+local t_name = "core_object_ip_t"
+local core_object_ip_t
+local Ip = {}
+
+-- Return the textual type of the object.
+function Ip:type()
+ return "ip"
+end
+
+-- Return the previous object.
+function Ip:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Ip:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Ip:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Ip:copy()
+ return C.core_object_ip_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Ip:free()
+ C.core_object_ip_free(self)
+end
+
+-- Return the IP source as a string.
+function Ip:source()
+ return libip.ipstring(self.src)
+end
+
+-- Return the IP destination as a string.
+function Ip:destination()
+ return libip.ipstring(self.dst)
+end
+
+core_object_ip_t = ffi.metatype(t_name, { __index = Ip })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Ip
diff --git a/src/core/object/ip6.c b/src/core/object/ip6.c
new file mode 100644
index 0000000..45db361
--- /dev/null
+++ b/src/core/object/ip6.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/ip6.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_ip6_t* core_object_ip6_copy(const core_object_ip6_t* self)
+{
+ core_object_ip6_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_ip6_t)));
+ memcpy(copy, self, sizeof(core_object_ip6_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_ip6_free(core_object_ip6_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/ip6.h b/src/core/object/ip6.h
new file mode 100644
index 0000000..711f1a5
--- /dev/null
+++ b/src/core/object/ip6.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_ip6_h
+#define __dnsjit_core_object_ip6_h
+
+#include <stddef.h>
+
+#include "core/object/ip6.hh"
+
+#define CORE_OBJECT_IP6_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_IP6, prev) \
+ , \
+ 0, 0, 0, 0, \
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ 0, 0, 0, 0, \
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ }
+
+#endif
diff --git a/src/core/object/ip6.hh b/src/core/object/ip6.hh
new file mode 100644
index 0000000..5411dda
--- /dev/null
+++ b/src/core/object/ip6.hh
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_ip6 {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint32_t flow;
+ uint16_t plen;
+ uint8_t nxt;
+ uint8_t hlim;
+ uint8_t src[16];
+ uint8_t dst[16];
+
+ uint8_t is_frag;
+ uint8_t have_rtdst;
+ uint16_t frag_offlg;
+ uint16_t frag_ident;
+ uint8_t rtdst[16];
+} core_object_ip6_t;
+
+core_object_ip6_t* core_object_ip6_copy(const core_object_ip6_t* self);
+void core_object_ip6_free(core_object_ip6_t* self);
diff --git a/src/core/object/ip6.lua b/src/core/object/ip6.lua
new file mode 100644
index 0000000..5271be3
--- /dev/null
+++ b/src/core/object/ip6.lua
@@ -0,0 +1,130 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.ip6
+-- An IPv6 packet
+--
+-- An IPv6 packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- flow
+-- 4 bits version, 8 bits TC and 20 bits flow-ID.
+-- .TP
+-- plen
+-- Payload length (as in the IPv6 header).
+-- .TP
+-- nxt
+-- Next header.
+-- .TP
+-- hlim
+-- Hop limit.
+-- .TP
+-- src
+-- Source address.
+-- .TP
+-- dst
+-- Destination address.
+-- .TP
+-- is_frag
+-- 1 bit, set if packet is a fragment.
+-- .TP
+-- have_rtdst
+-- 1 bit, set if
+-- .I rtdst
+-- is set.
+-- .TP
+-- frag_offlg
+-- Offset, reserved, and flag taken from the fragment header.
+-- .TP
+-- frag_ident
+-- Identification taken from the fragment header.
+-- .TP
+-- rtdst
+-- Destination address found in the routing extension header.
+-- .TP
+-- payload
+-- A pointer to the payload.
+-- .TP
+-- len
+-- The length of the payload.
+-- .TP
+-- pad_len
+-- The length of padding found, if any.
+module(...,package.seeall)
+
+require("dnsjit.core.object.ip6_h")
+local ffi = require("ffi")
+local C = ffi.C
+local libip = require("dnsjit.lib.ip")
+
+local t_name = "core_object_ip6_t"
+local core_object_ip6_t
+local Ip6 = {}
+
+-- Return the textual type of the object.
+function Ip6:type()
+ return "ip6"
+end
+
+-- Return the previous object.
+function Ip6:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Ip6:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Ip6:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Ip6:copy()
+ return C.core_object_ip6_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Ip6:free()
+ C.core_object_ip6_free(self)
+end
+
+-- Return the IPv6 source as a string.
+-- If
+-- .I pretty
+-- is true then return an easier to read IPv6 address.
+function Ip6:source(pretty)
+ return libip.ip6string(self.src, pretty)
+end
+
+-- Return the IPv6 destination as a string.
+-- If
+-- .I pretty
+-- is true then return an easier to read IPv6 address.
+function Ip6:destination(pretty)
+ return libip.ip6string(self.dst, pretty)
+end
+
+core_object_ip6_t = ffi.metatype(t_name, { __index = Ip6 })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Ip6
diff --git a/src/core/object/linuxsll.c b/src/core/object/linuxsll.c
new file mode 100644
index 0000000..cacd23a
--- /dev/null
+++ b/src/core/object/linuxsll.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/linuxsll.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_linuxsll_t* core_object_linuxsll_copy(const core_object_linuxsll_t* self)
+{
+ core_object_linuxsll_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_linuxsll_t)));
+ memcpy(copy, self, sizeof(core_object_linuxsll_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_linuxsll_free(core_object_linuxsll_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/linuxsll.h b/src/core/object/linuxsll.h
new file mode 100644
index 0000000..9484c0d
--- /dev/null
+++ b/src/core/object/linuxsll.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_linuxsll_h
+#define __dnsjit_core_object_linuxsll_h
+
+#include <stddef.h>
+
+#include "core/object/linuxsll.hh"
+
+#define CORE_OBJECT_LINUXSLL_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_LINUXSLL, prev) \
+ , \
+ 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0 \
+ }
+
+#endif
diff --git a/src/core/object/linuxsll.hh b/src/core/object/linuxsll.hh
new file mode 100644
index 0000000..e808f96
--- /dev/null
+++ b/src/core/object/linuxsll.hh
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_linuxsll {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint16_t packet_type;
+ uint16_t arp_hardware;
+ uint16_t link_layer_address_length;
+ uint8_t link_layer_address[8];
+ uint16_t ether_type;
+} core_object_linuxsll_t;
+
+core_object_linuxsll_t* core_object_linuxsll_copy(const core_object_linuxsll_t* self);
+void core_object_linuxsll_free(core_object_linuxsll_t* self);
diff --git a/src/core/object/linuxsll.lua b/src/core/object/linuxsll.lua
new file mode 100644
index 0000000..6b47525
--- /dev/null
+++ b/src/core/object/linuxsll.lua
@@ -0,0 +1,84 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.linuxsll
+-- Linux cooked-mode capture (SLL) part of a packet
+--
+-- The SLL part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- packet_type
+-- The packet type.
+-- .TP
+-- arp_hardware
+-- The link-layer device type.
+-- .TP
+-- link_layer_address_length
+-- The length of the link-layer address.
+-- .TP
+-- link_layer_address
+-- The link-layer address.
+-- .TP
+-- ether_type
+-- An Ethernet protocol type.
+module(...,package.seeall)
+
+require("dnsjit.core.object.linuxsll_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_linuxsll_t"
+local core_object_linuxsll_t
+local Linuxsll = {}
+
+-- Return the textual type of the object.
+function Linuxsll:type()
+ return "linuxsll"
+end
+
+-- Return the previous object.
+function Linuxsll:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Linuxsll:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Linuxsll:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Linuxsll:copy()
+ return C.core_object_linuxsll_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Linuxsll:free()
+ C.core_object_linuxsll_free(self)
+end
+
+core_object_linuxsll_t = ffi.metatype(t_name, { __index = Linuxsll })
+
+-- dnsjit.core.object (3).
+-- dnsjit.filter.layer (3)
+return Linuxsll
diff --git a/src/core/object/loop.c b/src/core/object/loop.c
new file mode 100644
index 0000000..4149f71
--- /dev/null
+++ b/src/core/object/loop.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/loop.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_loop_t* core_object_loop_copy(const core_object_loop_t* self)
+{
+ core_object_loop_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_loop_t)));
+ memcpy(copy, self, sizeof(core_object_loop_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_loop_free(core_object_loop_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/loop.h b/src/core/object/loop.h
new file mode 100644
index 0000000..1d8670f
--- /dev/null
+++ b/src/core/object/loop.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_loop_h
+#define __dnsjit_core_object_loop_h
+
+#include <stddef.h>
+
+#include "core/object/loop.hh"
+
+#define CORE_OBJECT_LOOP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_LOOP, prev) \
+ , \
+ 0 \
+ }
+
+#endif
diff --git a/src/core/object/loop.hh b/src/core/object/loop.hh
new file mode 100644
index 0000000..e8c5573
--- /dev/null
+++ b/src/core/object/loop.hh
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_loop {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint32_t family;
+} core_object_loop_t;
+
+core_object_loop_t* core_object_loop_copy(const core_object_loop_t* self);
+void core_object_loop_free(core_object_loop_t* self);
diff --git a/src/core/object/loop.lua b/src/core/object/loop.lua
new file mode 100644
index 0000000..2cb441f
--- /dev/null
+++ b/src/core/object/loop.lua
@@ -0,0 +1,72 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.loop
+-- OpenBSD loopback encapsulation (loop) part of a packet
+--
+-- The loop part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- family
+-- The link-layer header describing what type of packet is encapsulated.
+module(...,package.seeall)
+
+require("dnsjit.core.object.loop_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_loop_t"
+local core_object_loop_t
+local Loop = {}
+
+-- Return the textual type of the object.
+function Loop:type()
+ return "loop"
+end
+
+-- Return the previous object.
+function Loop:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Loop:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Loop:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Loop:copy()
+ return C.core_object_loop_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Loop:free()
+ C.core_object_loop_free(self)
+end
+
+core_object_loop_t = ffi.metatype(t_name, { __index = Loop })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Loop
diff --git a/src/core/object/null.c b/src/core/object/null.c
new file mode 100644
index 0000000..7fe617a
--- /dev/null
+++ b/src/core/object/null.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/null.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_null_t* core_object_null_copy(const core_object_null_t* self)
+{
+ core_object_null_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_null_t)));
+ memcpy(copy, self, sizeof(core_object_null_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_null_free(core_object_null_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/null.h b/src/core/object/null.h
new file mode 100644
index 0000000..0317fce
--- /dev/null
+++ b/src/core/object/null.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_null_h
+#define __dnsjit_core_object_null_h
+
+#include <stddef.h>
+
+#include "core/object/null.hh"
+
+#define CORE_OBJECT_NULL_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_NULL, prev) \
+ , \
+ 0 \
+ }
+
+#endif
diff --git a/src/core/object/null.hh b/src/core/object/null.hh
new file mode 100644
index 0000000..2e6c639
--- /dev/null
+++ b/src/core/object/null.hh
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_null {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint32_t family;
+} core_object_null_t;
+
+core_object_null_t* core_object_null_copy(const core_object_null_t* self);
+void core_object_null_free(core_object_null_t* self);
diff --git a/src/core/object/null.lua b/src/core/object/null.lua
new file mode 100644
index 0000000..e6dfc5d
--- /dev/null
+++ b/src/core/object/null.lua
@@ -0,0 +1,72 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.null
+-- BSD loopback encapsulation (null) part of a packet
+--
+-- The null part of a packet that usually can be found in the object chain
+-- after parsing with, for example, Layer filter.
+-- .SS Attributes
+-- .TP
+-- family
+-- The link-layer header describing what type of packet is encapsulated.
+module(...,package.seeall)
+
+require("dnsjit.core.object.null_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_null_t"
+local core_object_null_t
+local Null = {}
+
+-- Return the textual type of the object.
+function Null:type()
+ return "null"
+end
+
+-- Return the previous object.
+function Null:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Null:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Null:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Null:copy()
+ return C.core_object_null_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Null:free()
+ C.core_object_null_free(self)
+end
+
+core_object_null_t = ffi.metatype(t_name, { __index = Null })
+
+-- dnsjit.core.object (3),
+-- dnsjit.filter.layer (3)
+return Null
diff --git a/src/core/object/payload.c b/src/core/object/payload.c
new file mode 100644
index 0000000..d6d2ee4
--- /dev/null
+++ b/src/core/object/payload.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/payload.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_payload_t* core_object_payload_copy(const core_object_payload_t* self)
+{
+ core_object_payload_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_payload_t) + self->len + self->padding));
+ memcpy(copy, self, sizeof(core_object_payload_t));
+ copy->obj_prev = 0;
+
+ if (copy->payload) {
+ copy->payload = (void*)copy + sizeof(core_object_payload_t);
+ memcpy((void*)copy->payload, self->payload, self->len + self->padding);
+ }
+
+ return copy;
+}
+
+void core_object_payload_free(core_object_payload_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/payload.h b/src/core/object/payload.h
new file mode 100644
index 0000000..4b42a7c
--- /dev/null
+++ b/src/core/object/payload.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_payload_h
+#define __dnsjit_core_object_payload_h
+
+#include <stddef.h>
+
+#include "core/object/payload.hh"
+
+#define CORE_OBJECT_PAYLOAD_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_PAYLOAD, prev) \
+ , \
+ 0, 0, 0 \
+ }
+
+#endif
diff --git a/src/core/object/payload.hh b/src/core/object/payload.hh
new file mode 100644
index 0000000..fc2ad71
--- /dev/null
+++ b/src/core/object/payload.hh
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_payload {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ const uint8_t* payload;
+ size_t len, padding;
+} core_object_payload_t;
+
+core_object_payload_t* core_object_payload_copy(const core_object_payload_t* self);
+void core_object_payload_free(core_object_payload_t* self);
diff --git a/src/core/object/payload.lua b/src/core/object/payload.lua
new file mode 100644
index 0000000..61ea867
--- /dev/null
+++ b/src/core/object/payload.lua
@@ -0,0 +1,83 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.payload
+-- Application data payload
+--
+-- Payload object contains the data carried by the underlying transport
+-- protocol.
+-- Payload is usually at the top of the object chain after parsing with,
+-- for example,
+-- .IR dnsjit.filter.layer .
+-- .SS Attributes
+-- .TP
+-- payload
+-- A pointer to the payload.
+-- .TP
+-- len
+-- The length of the payload.
+-- .TP
+-- padding
+-- The length of padding in the underlying packet.
+module(...,package.seeall)
+
+require("dnsjit.core.object.payload_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_payload_t"
+local core_object_payload_t
+local Payload = {}
+
+-- Return the textual type of the object.
+function Payload:type()
+ return "payload"
+end
+
+-- Return the previous object.
+function Payload:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Payload:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Payload:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Payload:copy()
+ return C.core_object_payload_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Payload:free()
+ C.core_object_payload_free(self)
+end
+
+core_object_payload_t = ffi.metatype(t_name, { __index = Payload })
+
+-- dnsjit.core.object (3),
+-- dnsjit.core.object.udp (3),
+-- dnsjit.core.object.tcp (3),
+-- dnsjit.filter.layer (3)
+return Payload
diff --git a/src/core/object/pcap.c b/src/core/object/pcap.c
new file mode 100644
index 0000000..576a94e
--- /dev/null
+++ b/src/core/object/pcap.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/pcap.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_pcap_t* core_object_pcap_copy(const core_object_pcap_t* self)
+{
+ core_object_pcap_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_pcap_t) + self->caplen));
+ memcpy(copy, self, sizeof(core_object_pcap_t));
+ copy->obj_prev = 0;
+
+ if (copy->bytes) {
+ copy->bytes = (void*)copy + sizeof(core_object_pcap_t);
+ memcpy((void*)copy->bytes, self->bytes, self->caplen);
+ }
+
+ return copy;
+}
+
+void core_object_pcap_free(core_object_pcap_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/pcap.h b/src/core/object/pcap.h
new file mode 100644
index 0000000..093549b
--- /dev/null
+++ b/src/core/object/pcap.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_pcap_h
+#define __dnsjit_core_object_pcap_h
+
+#include "core/object/pcap.hh"
+
+#define CORE_OBJECT_PCAP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_PCAP, prev) \
+ , \
+ 0, 0, \
+ { 0, 0 }, 0, 0, 0, \
+ 0 \
+ }
+
+#endif
diff --git a/src/core/object/pcap.hh b/src/core/object/pcap.hh
new file mode 100644
index 0000000..642a7e7
--- /dev/null
+++ b/src/core/object/pcap.hh
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+//lua:require("dnsjit.core.timespec_h")
+
+typedef struct core_object_pcap {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint32_t snaplen, linktype;
+
+ core_timespec_t ts;
+ uint32_t caplen, len;
+ const unsigned char* bytes;
+
+ uint8_t is_swapped;
+} core_object_pcap_t;
+
+core_object_pcap_t* core_object_pcap_copy(const core_object_pcap_t* self);
+void core_object_pcap_free(core_object_pcap_t* self);
diff --git a/src/core/object/pcap.lua b/src/core/object/pcap.lua
new file mode 100644
index 0000000..3d49326
--- /dev/null
+++ b/src/core/object/pcap.lua
@@ -0,0 +1,98 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.pcap
+-- Container of a packet found in a PCAP
+--
+-- Container of a PCAP packet which contains information both from the PCAP
+-- itself and the
+-- .I pcap_pkthdr
+-- object receied for each packet in the PCAP.
+-- .SS Attributes
+-- .TP
+-- snaplen
+-- Max length saved portion of each packet.
+-- .TP
+-- linktype
+-- Data link type for the PCAP.
+-- .TP
+-- ts
+-- Time stamp of this packet.
+-- .TP
+-- caplen
+-- Length of portion present.
+-- .TP
+-- len
+-- Length of this packet (off wire).
+-- .TP
+-- bytes
+-- A pointer to the packet.
+-- .TP
+-- is_swapped
+-- Indicate if the byte order of the PCAP is different then the host.
+-- This is used in, for example, the Layer filter to correctly parse null
+-- objects since they are stored in the capturers host byte order.
+module(...,package.seeall)
+
+require("dnsjit.core.object.pcap_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_pcap_t"
+local core_object_pcap_t
+local Pcap = {}
+
+-- Return the textual type of the object.
+function Pcap:type()
+ return "pcap"
+end
+
+-- Return the previous object.
+function Pcap:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Pcap:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Pcap:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Pcap:copy()
+ return C.core_object_pcap_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Pcap:free()
+ C.core_object_pcap_free(self)
+end
+
+core_object_pcap_t = ffi.metatype(t_name, { __index = Pcap })
+
+-- dnsjit.core.object (3),
+-- dnsjit.input.pcap (3),
+-- dnsjit.input.fpcap (3),
+-- dnsjit.input.mmpcap (3),
+-- dnsjit.filter.layer (3),
+-- dnsjit.output.pcap (3)
+return Pcap
diff --git a/src/core/object/tcp.c b/src/core/object/tcp.c
new file mode 100644
index 0000000..37f9548
--- /dev/null
+++ b/src/core/object/tcp.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/tcp.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_tcp_t* core_object_tcp_copy(const core_object_tcp_t* self)
+{
+ core_object_tcp_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_tcp_t)));
+ memcpy(copy, self, sizeof(core_object_tcp_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_tcp_free(core_object_tcp_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/tcp.h b/src/core/object/tcp.h
new file mode 100644
index 0000000..e62ad42
--- /dev/null
+++ b/src/core/object/tcp.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_tcp_h
+#define __dnsjit_core_object_tcp_h
+
+#include <stddef.h>
+
+#include "core/object/tcp.hh"
+
+#define CORE_OBJECT_TCP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_TCP, prev) \
+ , \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ { 0 }, 0 \
+ }
+
+#endif
diff --git a/src/core/object/tcp.hh b/src/core/object/tcp.hh
new file mode 100644
index 0000000..bd3167d
--- /dev/null
+++ b/src/core/object/tcp.hh
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_tcp {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint16_t sport;
+ uint16_t dport;
+ uint32_t seq;
+ uint32_t ack;
+ uint8_t off : 4;
+ uint8_t x2 : 4;
+ uint8_t flags;
+ uint16_t win;
+ uint16_t sum;
+ uint16_t urp;
+
+ uint8_t opts[64];
+ size_t opts_len;
+} core_object_tcp_t;
+
+core_object_tcp_t* core_object_tcp_copy(const core_object_tcp_t* self);
+void core_object_tcp_free(core_object_tcp_t* self);
diff --git a/src/core/object/tcp.lua b/src/core/object/tcp.lua
new file mode 100644
index 0000000..e1d6dc2
--- /dev/null
+++ b/src/core/object/tcp.lua
@@ -0,0 +1,110 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.tcp
+-- A TCP segment header
+--
+-- A TCP segment header.
+-- The data itself is in the
+-- .I dnsjit.core.object.payload
+-- object, which is the next object in the chain after parsing with,
+-- for example,
+-- .IR dnsjit.filter.layer .
+-- .SS Attributes
+-- .TP
+-- sport
+-- Source port.
+-- .TP
+-- dport
+-- Destination port.
+-- .TP
+-- seq
+-- Sequence number.
+-- .TP
+-- ack
+-- Acknowledgement number.
+-- .TP
+-- off
+-- Data offset.
+-- .TP
+-- x2
+-- Unused.
+-- .TP
+-- flags
+-- TCP flags.
+-- .TP
+-- win
+-- Window.
+-- .TP
+-- sum
+-- Checksum.
+-- .TP
+-- urp
+-- Urgent pointer.
+-- .TP
+-- opts
+-- Array of bytes with the TCP options found.
+-- .TP
+-- opts_len
+-- Length of the TCP options.
+module(...,package.seeall)
+
+require("dnsjit.core.object.tcp_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_tcp_t"
+local core_object_tcp_t
+local Tcp = {}
+
+-- Return the textual type of the object.
+function Tcp:type()
+ return "tcp"
+end
+
+-- Return the previous object.
+function Tcp:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Tcp:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Tcp:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Tcp:copy()
+ return C.core_object_tcp_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Tcp:free()
+ C.core_object_tcp_free(self)
+end
+
+core_object_tcp_t = ffi.metatype(t_name, { __index = Tcp })
+
+-- dnsjit.core.object (3),
+-- dnsjit.core.object.payload (3),
+-- dnsjit.filter.layer (3)
+return Tcp
diff --git a/src/core/object/udp.c b/src/core/object/udp.c
new file mode 100644
index 0000000..3d05002
--- /dev/null
+++ b/src/core/object/udp.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/object/udp.h"
+#include "core/assert.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+core_object_udp_t* core_object_udp_copy(const core_object_udp_t* self)
+{
+ core_object_udp_t* copy;
+ glassert_self();
+
+ glfatal_oom(copy = malloc(sizeof(core_object_udp_t)));
+ memcpy(copy, self, sizeof(core_object_udp_t));
+ copy->obj_prev = 0;
+
+ return copy;
+}
+
+void core_object_udp_free(core_object_udp_t* self)
+{
+ glassert_self();
+ free(self);
+}
diff --git a/src/core/object/udp.h b/src/core/object/udp.h
new file mode 100644
index 0000000..147e80b
--- /dev/null
+++ b/src/core/object/udp.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+#include "core/timespec.h"
+
+#ifndef __dnsjit_core_object_udp_h
+#define __dnsjit_core_object_udp_h
+
+#include <stddef.h>
+
+#include "core/object/udp.hh"
+
+#define CORE_OBJECT_UDP_INIT(prev) \
+ { \
+ CORE_OBJECT_INIT(CORE_OBJECT_UDP, prev) \
+ , \
+ 0, 0, 0, 0, \
+ }
+
+#endif
diff --git a/src/core/object/udp.hh b/src/core/object/udp.hh
new file mode 100644
index 0000000..5efbd92
--- /dev/null
+++ b/src/core/object/udp.hh
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef struct core_object_udp {
+ const core_object_t* obj_prev;
+ int32_t obj_type;
+
+ uint16_t sport;
+ uint16_t dport;
+ uint16_t ulen;
+ uint16_t sum;
+} core_object_udp_t;
+
+core_object_udp_t* core_object_udp_copy(const core_object_udp_t* self);
+void core_object_udp_free(core_object_udp_t* self);
diff --git a/src/core/object/udp.lua b/src/core/object/udp.lua
new file mode 100644
index 0000000..1652574
--- /dev/null
+++ b/src/core/object/udp.lua
@@ -0,0 +1,86 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.object.udp
+-- A UDP datagram header
+--
+-- A UDP datagram header.
+-- The data itself is in the
+-- .I dnsjit.core.object.payload
+-- object, which is the next object in the chain after parsing with,
+-- for example,
+-- .IR dnsjit.filter.layer .
+-- .SS Attributes
+-- .TP
+-- sport
+-- Source port.
+-- .TP
+-- dport
+-- Destination port.
+-- .TP
+-- ulen
+-- UDP length (as described in the UDP header).
+-- .TP
+-- sum
+-- Checksum.
+module(...,package.seeall)
+
+require("dnsjit.core.object.udp_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_object_udp_t"
+local core_object_udp_t
+local Udp = {}
+
+-- Return the textual type of the object.
+function Udp:type()
+ return "udp"
+end
+
+-- Return the previous object.
+function Udp:prev()
+ return self.obj_prev
+end
+
+-- Cast the object to the underlining object module and return it.
+function Udp:cast()
+ return self
+end
+
+-- Cast the object to the generic object module and return it.
+function Udp:uncast()
+ return ffi.cast("core_object_t*", self)
+end
+
+-- Make a copy of the object and return it.
+function Udp:copy()
+ return C.core_object_udp_copy(self)
+end
+
+-- Free the object, should only be used on copies or otherwise allocated.
+function Udp:free()
+ C.core_object_udp_free(self)
+end
+
+core_object_udp_t = ffi.metatype(t_name, { __index = Udp })
+
+-- dnsjit.core.object (3),
+-- dnsjit.core.object.payload (3),
+-- dnsjit.filter.layer (3)
+return Udp
diff --git a/src/core/objects.lua b/src/core/objects.lua
new file mode 100644
index 0000000..ce83cd0
--- /dev/null
+++ b/src/core/objects.lua
@@ -0,0 +1,61 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.objects
+-- Easy way to import all objects
+-- require("dnsjit.core.objects")
+--
+-- Helper module to require all available objects, returns what
+-- .I dnsjit.core.object
+-- returned so that constants like object types can be used.
+module(...,package.seeall)
+
+local object = require("dnsjit.core.object")
+require("dnsjit.core.object.pcap")
+require("dnsjit.core.object.ether")
+require("dnsjit.core.object.null")
+require("dnsjit.core.object.loop")
+require("dnsjit.core.object.linuxsll")
+require("dnsjit.core.object.ieee802")
+require("dnsjit.core.object.gre")
+require("dnsjit.core.object.ip")
+require("dnsjit.core.object.ip6")
+require("dnsjit.core.object.icmp")
+require("dnsjit.core.object.icmp6")
+require("dnsjit.core.object.udp")
+require("dnsjit.core.object.tcp")
+require("dnsjit.core.object.payload")
+require("dnsjit.core.object.dns")
+
+-- dnsjit.core.object (3),
+-- dnsjit.core.object.pcap (3),
+-- dnsjit.core.object.ether (3),
+-- dnsjit.core.object.null (3),
+-- dnsjit.core.object.loop (3),
+-- dnsjit.core.object.linuxsll (3),
+-- dnsjit.core.object.ieee802 (3),
+-- dnsjit.core.object.gre (3),
+-- dnsjit.core.object.ip (3),
+-- dnsjit.core.object.ip6 (3),
+-- dnsjit.core.object.icmp (3),
+-- dnsjit.core.object.icmp6 (3),
+-- dnsjit.core.object.udp (3),
+-- dnsjit.core.object.tcp (3),
+-- dnsjit.core.object.payload (3),
+-- dnsjit.core.object.dns (3)
+return object
diff --git a/src/core/producer.c b/src/core/producer.c
new file mode 100644
index 0000000..8a85c93
--- /dev/null
+++ b/src/core/producer.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/producer.h"
diff --git a/src/core/producer.h b/src/core/producer.h
new file mode 100644
index 0000000..e78d48b
--- /dev/null
+++ b/src/core/producer.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+
+#ifndef __dnsjit_core_producer_h
+#define __dnsjit_core_producer_h
+
+#include "core/producer.hh"
+
+#endif
diff --git a/src/core/producer.hh b/src/core/producer.hh
new file mode 100644
index 0000000..2d64035
--- /dev/null
+++ b/src/core/producer.hh
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef const core_object_t* (*core_producer_t)(void* ctx);
diff --git a/src/core/producer.lua b/src/core/producer.lua
new file mode 100644
index 0000000..42f3e44
--- /dev/null
+++ b/src/core/producer.lua
@@ -0,0 +1,28 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.producer
+-- Producer interfaces
+-- require("dnsjit.core.producer_h")
+--
+-- Producer interfaces are used by input, filter and output modules to pass
+-- objects for processing.
+module(...,package.seeall)
+
+-- dnsjit.core.object (3)
+return
diff --git a/src/core/receiver.c b/src/core/receiver.c
new file mode 100644
index 0000000..f67be0e
--- /dev/null
+++ b/src/core/receiver.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "core/receiver.h"
diff --git a/src/core/receiver.h b/src/core/receiver.h
new file mode 100644
index 0000000..f592c0c
--- /dev/null
+++ b/src/core/receiver.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/object.h"
+
+#ifndef __dnsjit_core_receiver_h
+#define __dnsjit_core_receiver_h
+
+#include "core/receiver.hh"
+
+#endif
diff --git a/src/core/receiver.hh b/src/core/receiver.hh
new file mode 100644
index 0000000..316c9be
--- /dev/null
+++ b/src/core/receiver.hh
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.object_h")
+
+typedef void (*core_receiver_t)(void* ctx, const core_object_t* obj);
diff --git a/src/core/receiver.lua b/src/core/receiver.lua
new file mode 100644
index 0000000..02aa39d
--- /dev/null
+++ b/src/core/receiver.lua
@@ -0,0 +1,28 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.receiver
+-- Receiver interfaces
+-- require("dnsjit.core.receiver_h")
+--
+-- Receiver interfaces are used by input, filter and output modules to pass
+-- objects for processing.
+module(...,package.seeall)
+
+-- dnsjit.core.object (3)
+return
diff --git a/src/core/thread.c b/src/core/thread.c
new file mode 100644
index 0000000..189c720
--- /dev/null
+++ b/src/core/thread.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "globals.h"
+#include "core/assert.h"
+#include "core/thread.h"
+
+#include <string.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+static core_log_t _log = LOG_T_INIT("core.thread");
+static core_thread_t _defaults = {
+ LOG_T_INIT_OBJ("core.thread"),
+ 0, 0, 0, 0,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,
+ 0, 0
+};
+
+core_log_t* core_thread_log()
+{
+ return &_log;
+}
+
+void core_thread_init(core_thread_t* self)
+{
+ mlassert_self();
+
+ *self = _defaults;
+}
+
+void core_thread_destroy(core_thread_t* self)
+{
+ core_thread_item_t* item;
+ mlassert_self();
+
+ free(self->bytecode);
+ while ((item = self->stack)) {
+ self->stack = item->next;
+ free(item);
+ }
+}
+
+static void* _thread(void* vp)
+{
+ core_thread_t* self = (core_thread_t*)vp;
+ lua_State* L;
+ mlassert_self();
+
+ // TODO: move to dnsjit_newstate()
+ L = luaL_newstate();
+ lassert(L, "could not create new Lua state");
+ luaL_openlibs(L);
+ dnsjit_globals(L);
+
+ for (;;) {
+ lua_getfield(L, LUA_GLOBALSINDEX, "require");
+ lua_pushstring(L, "dnsjit.core.thread");
+ if (lua_pcall(L, 1, 1, 0)) {
+ lcritical("%s", lua_tostring(L, -1));
+ break;
+ }
+ lua_getfield(L, -1, "_in_thread");
+ lua_pushlightuserdata(L, (void*)self);
+ lua_pushlstring(L, self->bytecode, self->bytecode_len);
+ if (lua_pcall(L, 2, 0, 0)) {
+ lcritical("%s", lua_tostring(L, -1));
+ }
+ break;
+ }
+
+ lua_close(L);
+ return 0;
+}
+
+int core_thread_start(core_thread_t* self, const char* bytecode, size_t len)
+{
+ int err;
+ mlassert_self();
+
+ if (self->bytecode) {
+ lfatal("bytecode already set");
+ }
+
+ lfatal_oom(self->bytecode = malloc(len));
+ memcpy(self->bytecode, bytecode, len);
+ self->bytecode_len = len;
+
+ if ((err = pthread_create(&self->thr_id, 0, _thread, (void*)self))) {
+ lcritical("pthread_create() error: %s", core_log_errstr(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+int core_thread_stop(core_thread_t* self)
+{
+ int err;
+ mlassert_self();
+
+ if ((err = pthread_join(self->thr_id, 0))) {
+ lcritical("pthread_join() error: %s", core_log_errstr(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+inline static void _push(core_thread_t* self, core_thread_item_t* item)
+{
+ if (pthread_mutex_lock(&self->lock)) {
+ lfatal("mutex lock failed");
+ }
+ if (!self->last) {
+ self->stack = self->last = item;
+ } else {
+ self->last->next = item;
+ self->last = item;
+ }
+ if (pthread_cond_signal(&self->cond)) {
+ lfatal("cond signal failed");
+ }
+ if (pthread_mutex_unlock(&self->lock)) {
+ lfatal("mutex unlock failed");
+ }
+}
+
+void core_thread_push(core_thread_t* self, void* ptr, const char* type, size_t type_len, const char* module, size_t module_len)
+{
+ core_thread_item_t* item;
+ mlassert_self();
+ lassert(ptr, "ptr is nil");
+ lassert(type, "type is nil");
+ lassert(type_len, "type_len is zero");
+ lassert(module, "module is nil");
+ lassert(module_len, "module_len is zero");
+
+ lfatal_oom(item = malloc(sizeof(core_thread_item_t) + type_len + module_len + 2));
+ item->next = 0;
+ item->ptr = ptr;
+ item->type = ((void*)item) + sizeof(core_thread_item_t);
+ memcpy(item->type, type, type_len);
+ item->type[type_len] = 0;
+ item->module = item->type + type_len + 1;
+ memcpy(item->module, module, module_len);
+ item->module[module_len] = 0;
+
+ _push(self, item);
+}
+
+void core_thread_push_string(core_thread_t* self, const char* str, size_t len)
+{
+ core_thread_item_t* item;
+ mlassert_self();
+ lassert(str, "str is nil");
+ lassert(len, "len is zero");
+
+ lfatal_oom(item = malloc(sizeof(core_thread_item_t) + len + 1));
+ item->next = 0;
+ item->ptr = 0;
+ item->str = ((void*)item) + sizeof(core_thread_item_t);
+ memcpy(item->str, str, len);
+ item->str[len] = 0;
+
+ _push(self, item);
+}
+
+void core_thread_push_int64(core_thread_t* self, int64_t i64)
+{
+ core_thread_item_t* item;
+ mlassert_self();
+
+ lfatal_oom(item = malloc(sizeof(core_thread_item_t)));
+ item->next = 0;
+ item->ptr = 0;
+ item->str = 0;
+ item->i64 = i64;
+
+ _push(self, item);
+}
+
+const core_thread_item_t* core_thread_pop(core_thread_t* self)
+{
+ mlassert_self();
+
+ if (pthread_mutex_lock(&self->lock)) {
+ lfatal("mutex lock failed");
+ }
+ if (!self->at) {
+ while (!self->stack) {
+ if (pthread_cond_wait(&self->cond, &self->lock)) {
+ lfatal("cond wait failed");
+ }
+ }
+ self->at = self->stack;
+ } else {
+ while (!self->at->next) {
+ if (pthread_cond_wait(&self->cond, &self->lock)) {
+ lfatal("cond wait failed");
+ }
+ }
+ self->at = self->at->next;
+ }
+ if (pthread_mutex_unlock(&self->lock)) {
+ lfatal("mutex unlock failed");
+ }
+
+ return self->at;
+}
diff --git a/src/core/thread.h b/src/core/thread.h
new file mode 100644
index 0000000..fc047d4
--- /dev/null
+++ b/src/core/thread.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "core/log.h"
+
+#ifndef __dnsjit_core_thread_h
+#define __dnsjit_core_thread_h
+
+#include <pthread.h>
+#include <unistd.h>
+
+#include "core/thread.hh"
+
+#endif
diff --git a/src/core/thread.hh b/src/core/thread.hh
new file mode 100644
index 0000000..a61f8c9
--- /dev/null
+++ b/src/core/thread.hh
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//lua:require("dnsjit.core.compat_h")
+//lua:require("dnsjit.core.log")
+
+typedef struct core_thread_item core_thread_item_t;
+struct core_thread_item {
+ core_thread_item_t* next;
+ void* ptr;
+ char * type, *module;
+
+ char* str;
+ int64_t i64;
+};
+
+typedef struct core_thread {
+ core_log_t _log;
+ pthread_t thr_id;
+ core_thread_item_t * stack, *last;
+ const core_thread_item_t* at;
+
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+
+ char* bytecode;
+ size_t bytecode_len;
+} core_thread_t;
+
+core_log_t* core_thread_log();
+
+void core_thread_init(core_thread_t* self);
+void core_thread_destroy(core_thread_t* self);
+int core_thread_start(core_thread_t* self, const char* bytecode, size_t len);
+int core_thread_stop(core_thread_t* self);
+void core_thread_push(core_thread_t* self, void* ptr, const char* type, size_t type_len, const char* module, size_t module_len);
+void core_thread_push_string(core_thread_t* self, const char* str, size_t len);
+void core_thread_push_int64(core_thread_t* self, int64_t i64);
+const core_thread_item_t* core_thread_pop(core_thread_t* self);
diff --git a/src/core/thread.lua b/src/core/thread.lua
new file mode 100644
index 0000000..f225726
--- /dev/null
+++ b/src/core/thread.lua
@@ -0,0 +1,141 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.thread
+-- POSIX thread with separate Lua state
+-- local thr = require("dnsjit.core.thread").new()
+-- thr:start(function(thr)
+-- print("Hello from thread")
+-- print("got:", thr:pop(), " = ", thr:pop(3))
+-- end)
+-- thr:push("value from main", 1, 2, 3)
+-- thr:stop()
+--
+-- Start a new POSIX thread with it's own Lua state.
+-- Sharable objects can be passed to the thread by pushing and poping them of
+-- the thread stack.
+-- The Thread object and any other objects passed to the thread needs to be
+-- kept alive as long as the thread is running.
+module(...,package.seeall)
+
+require("dnsjit.core.thread_h")
+local ffi = require("ffi")
+local C = ffi.C
+
+local t_name = "core_thread_t"
+local core_thread_t
+local Thread = {
+ _in_thread = function(thr, bytecode)
+ thr = ffi.cast("core_thread_t*", thr)
+ loadstring(bytecode)(thr)
+ end
+}
+
+-- Create a new Thread object.
+function Thread.new()
+ local self = core_thread_t()
+ C.core_thread_init(self)
+ ffi.gc(self, C.core_thread_destroy)
+ return self
+end
+
+-- Return the Log object to control logging of this instance or module.
+function Thread:log()
+ if self == nil then
+ return C.core_thread_log()
+ end
+ return self._log
+end
+
+-- Start the thread and execute the given function in a separate Lua state,
+-- first argument to the function will be the Thread object that created it.
+-- Returns 0 on success.
+function Thread:start(func)
+ local bc = string.dump(func)
+ return C.core_thread_start(self, bc, #bc)
+end
+
+-- Wait for the thread to return.
+-- Returns 0 on success.
+function Thread:stop()
+ return C.core_thread_stop(self)
+end
+
+-- Push string(s), number(s) or sharable object(s) onto the thread stack so
+-- they can be retrieved inside the thread using
+-- .IR pop() .
+-- The sharable object(s) needs to be kept alive as long as the thread is
+-- running, strings and numbers are copied.
+function Thread:push(...)
+ for _, obj in pairs({...}) do
+ local t = type(obj)
+ if t == "string" then
+ C.core_thread_push_string(self, obj, #obj)
+ elseif t == "number" then
+ C.core_thread_push_int64(self, obj)
+ else
+ local ptr, type, module = obj:share()
+ C.core_thread_push(self, ptr, type, #type, module, #module)
+ end
+ end
+end
+
+-- Pop value(s) off the thread stack, should only be called within the thread.
+-- If
+-- .I num
+-- is not given then one value is poped.
+-- Returns nil if no values are left on the stack.
+function Thread:pop(num)
+ if num == nil or num == 1 then
+ local item = C.core_thread_pop(self)
+ if item == nil then
+ return
+ end
+ if item.ptr == nil then
+ if item.str == nil then
+ return tonumber(item.i64)
+ end
+ return ffi.string(item.str)
+ end
+ require(ffi.string(item.module))
+ return ffi.cast(ffi.string(item.type), item.ptr)
+ end
+
+ local ret = {}
+ for n = 1, num do
+ local item = C.core_thread_pop(self)
+ if item == nil then break end
+
+ if item.ptr == nil then
+ if item.str == nil then
+ table.insert(ret, tonumber(item.i64))
+ else
+ table.insert(ret, ffi.string(item.str))
+ end
+ else
+ require(ffi.string(item.module))
+ table.insert(ret, ffi.cast(ffi.string(item.type), item.ptr))
+ end
+ end
+ return unpack(ret)
+end
+
+core_thread_t = ffi.metatype(t_name, { __index = Thread })
+
+-- dnsjit.core.channel (3)
+return Thread
diff --git a/src/core/timespec.h b/src/core/timespec.h
new file mode 100644
index 0000000..e0aefce
--- /dev/null
+++ b/src/core/timespec.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __dnsjit_core_timespec_h
+#define __dnsjit_core_timespec_h
+
+#include <stdint.h>
+
+#include "core/timespec.hh"
+
+#define CORE_TIMESPEC_INIT \
+ { \
+ 0, 0 \
+ }
+
+#endif
diff --git a/src/core/timespec.hh b/src/core/timespec.hh
new file mode 100644
index 0000000..17a9551
--- /dev/null
+++ b/src/core/timespec.hh
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * This file is part of dnsjit.
+ *
+ * dnsjit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dnsjit 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
+ * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct core_timespec {
+ int64_t sec;
+ int64_t nsec;
+} core_timespec_t;
diff --git a/src/core/timespec.lua b/src/core/timespec.lua
new file mode 100644
index 0000000..0db4dd3
--- /dev/null
+++ b/src/core/timespec.lua
@@ -0,0 +1,32 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit 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
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.core.receiver
+-- Non-system depended time specification structure definition
+-- typedef struct core_timespec {
+-- uint64_t sec;
+-- uint64_t nsec;
+-- } core_timespec_t;
+-- .SS C
+-- #include "core/timespec.h"
+-- .SS Lua
+-- require("dnsjit.core.timespec_h")
+--
+-- Mainly used in C modules for a system independent time specification
+-- structure that can be passed to Lua.
+module(...,package.seeall)