From 4754ed45b607e82450a5e31fea1da3ba61433b04 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Mar 2021 08:54:12 +0100 Subject: Adding upstream version 1.1.0+debian. Signed-off-by: Daniel Baumann --- src/core/assert.h | 46 +++ src/core/channel.c | 169 +++++++++ src/core/channel.h | 41 +++ src/core/channel.hh | 49 +++ src/core/channel.lua | 142 ++++++++ src/core/compat.c | 25 ++ src/core/compat.h | 32 ++ src/core/compat.lua | 41 +++ src/core/log.c | 399 +++++++++++++++++++++ src/core/log.h | 105 ++++++ src/core/log.hh | 44 +++ src/core/log.lua | 639 +++++++++++++++++++++++++++++++++ src/core/object.c | 135 +++++++ src/core/object.h | 51 +++ src/core/object.hh | 28 ++ src/core/object.lua | 177 ++++++++++ src/core/object/dns.c | 471 +++++++++++++++++++++++++ src/core/object/dns.h | 184 ++++++++++ src/core/object/dns.hh | 119 +++++++ src/core/object/dns.lua | 797 ++++++++++++++++++++++++++++++++++++++++++ src/core/object/dns/label.lua | 118 +++++++ src/core/object/dns/q.lua | 52 +++ src/core/object/dns/rr.lua | 85 +++++ src/core/object/ether.c | 45 +++ src/core/object/ether.h | 38 ++ src/core/object/ether.hh | 33 ++ src/core/object/ether.lua | 78 +++++ src/core/object/gre.c | 45 +++ src/core/object/gre.h | 38 ++ src/core/object/gre.hh | 37 ++ src/core/object/gre.lua | 87 +++++ src/core/object/icmp.c | 45 +++ src/core/object/icmp.h | 38 ++ src/core/object/icmp.hh | 33 ++ src/core/object/icmp.lua | 78 +++++ src/core/object/icmp6.c | 45 +++ src/core/object/icmp6.h | 38 ++ src/core/object/icmp6.hh | 33 ++ src/core/object/icmp6.lua | 78 +++++ src/core/object/ieee802.c | 45 +++ src/core/object/ieee802.h | 38 ++ src/core/object/ieee802.hh | 35 ++ src/core/object/ieee802.lua | 84 +++++ src/core/object/ip.c | 45 +++ src/core/object/ip.h | 38 ++ src/core/object/ip.hh | 40 +++ src/core/object/ip.lua | 122 +++++++ src/core/object/ip6.c | 45 +++ src/core/object/ip6.h | 42 +++ src/core/object/ip6.hh | 42 +++ src/core/object/ip6.lua | 130 +++++++ src/core/object/linuxsll.c | 45 +++ src/core/object/linuxsll.h | 38 ++ src/core/object/linuxsll.hh | 35 ++ src/core/object/linuxsll.lua | 84 +++++ src/core/object/loop.c | 45 +++ src/core/object/loop.h | 38 ++ src/core/object/loop.hh | 31 ++ src/core/object/loop.lua | 72 ++++ src/core/object/null.c | 45 +++ src/core/object/null.h | 38 ++ src/core/object/null.hh | 31 ++ src/core/object/null.lua | 72 ++++ src/core/object/payload.c | 50 +++ src/core/object/payload.h | 38 ++ src/core/object/payload.hh | 32 ++ src/core/object/payload.lua | 83 +++++ src/core/object/pcap.c | 50 +++ src/core/object/pcap.h | 38 ++ src/core/object/pcap.hh | 38 ++ src/core/object/pcap.lua | 98 ++++++ src/core/object/tcp.c | 45 +++ src/core/object/tcp.h | 39 +++ src/core/object/tcp.hh | 43 +++ src/core/object/tcp.lua | 110 ++++++ src/core/object/udp.c | 45 +++ src/core/object/udp.h | 38 ++ src/core/object/udp.hh | 34 ++ src/core/object/udp.lua | 86 +++++ src/core/objects.lua | 61 ++++ src/core/producer.c | 23 ++ src/core/producer.h | 28 ++ src/core/producer.hh | 23 ++ src/core/producer.lua | 28 ++ src/core/receiver.c | 23 ++ src/core/receiver.h | 28 ++ src/core/receiver.hh | 23 ++ src/core/receiver.lua | 28 ++ src/core/thread.c | 229 ++++++++++++ src/core/thread.h | 31 ++ src/core/thread.hh | 56 +++ src/core/thread.lua | 141 ++++++++ src/core/timespec.h | 33 ++ src/core/timespec.hh | 24 ++ src/core/timespec.lua | 32 ++ 95 files changed, 7696 insertions(+) create mode 100644 src/core/assert.h create mode 100644 src/core/channel.c create mode 100644 src/core/channel.h create mode 100644 src/core/channel.hh create mode 100644 src/core/channel.lua create mode 100644 src/core/compat.c create mode 100644 src/core/compat.h create mode 100644 src/core/compat.lua create mode 100644 src/core/log.c create mode 100644 src/core/log.h create mode 100644 src/core/log.hh create mode 100644 src/core/log.lua create mode 100644 src/core/object.c create mode 100644 src/core/object.h create mode 100644 src/core/object.hh create mode 100644 src/core/object.lua create mode 100644 src/core/object/dns.c create mode 100644 src/core/object/dns.h create mode 100644 src/core/object/dns.hh create mode 100644 src/core/object/dns.lua create mode 100644 src/core/object/dns/label.lua create mode 100644 src/core/object/dns/q.lua create mode 100644 src/core/object/dns/rr.lua create mode 100644 src/core/object/ether.c create mode 100644 src/core/object/ether.h create mode 100644 src/core/object/ether.hh create mode 100644 src/core/object/ether.lua create mode 100644 src/core/object/gre.c create mode 100644 src/core/object/gre.h create mode 100644 src/core/object/gre.hh create mode 100644 src/core/object/gre.lua create mode 100644 src/core/object/icmp.c create mode 100644 src/core/object/icmp.h create mode 100644 src/core/object/icmp.hh create mode 100644 src/core/object/icmp.lua create mode 100644 src/core/object/icmp6.c create mode 100644 src/core/object/icmp6.h create mode 100644 src/core/object/icmp6.hh create mode 100644 src/core/object/icmp6.lua create mode 100644 src/core/object/ieee802.c create mode 100644 src/core/object/ieee802.h create mode 100644 src/core/object/ieee802.hh create mode 100644 src/core/object/ieee802.lua create mode 100644 src/core/object/ip.c create mode 100644 src/core/object/ip.h create mode 100644 src/core/object/ip.hh create mode 100644 src/core/object/ip.lua create mode 100644 src/core/object/ip6.c create mode 100644 src/core/object/ip6.h create mode 100644 src/core/object/ip6.hh create mode 100644 src/core/object/ip6.lua create mode 100644 src/core/object/linuxsll.c create mode 100644 src/core/object/linuxsll.h create mode 100644 src/core/object/linuxsll.hh create mode 100644 src/core/object/linuxsll.lua create mode 100644 src/core/object/loop.c create mode 100644 src/core/object/loop.h create mode 100644 src/core/object/loop.hh create mode 100644 src/core/object/loop.lua create mode 100644 src/core/object/null.c create mode 100644 src/core/object/null.h create mode 100644 src/core/object/null.hh create mode 100644 src/core/object/null.lua create mode 100644 src/core/object/payload.c create mode 100644 src/core/object/payload.h create mode 100644 src/core/object/payload.hh create mode 100644 src/core/object/payload.lua create mode 100644 src/core/object/pcap.c create mode 100644 src/core/object/pcap.h create mode 100644 src/core/object/pcap.hh create mode 100644 src/core/object/pcap.lua create mode 100644 src/core/object/tcp.c create mode 100644 src/core/object/tcp.h create mode 100644 src/core/object/tcp.hh create mode 100644 src/core/object/tcp.lua create mode 100644 src/core/object/udp.c create mode 100644 src/core/object/udp.h create mode 100644 src/core/object/udp.hh create mode 100644 src/core/object/udp.lua create mode 100644 src/core/objects.lua create mode 100644 src/core/producer.c create mode 100644 src/core/producer.h create mode 100644 src/core/producer.hh create mode 100644 src/core/producer.lua create mode 100644 src/core/receiver.c create mode 100644 src/core/receiver.h create mode 100644 src/core/receiver.hh create mode 100644 src/core/receiver.lua create mode 100644 src/core/thread.c create mode 100644 src/core/thread.h create mode 100644 src/core/thread.hh create mode 100644 src/core/thread.lua create mode 100644 src/core/timespec.h create mode 100644 src/core/timespec.hh create mode 100644 src/core/timespec.lua (limited to 'src/core') 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 . + */ + +#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 . + */ + +#include "config.h" + +#include "core/channel.h" +#include "core/assert.h" + +#include + +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 . + */ + +#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 +#include +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include + +#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 . + */ + +#ifndef __dnsjit_core_compat_h +#define __dnsjit_core_compat_h + +#include + +#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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/log.h" + +#include +#include +#include + +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 . + */ + +#ifndef __dnsjit_core_log_h +#define __dnsjit_core_log_h + +#include +#include +#include + +#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 . + */ + +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 . + +-- 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 . + */ + +#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 . + */ + +#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 +#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 . + */ + +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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/dns.h" +#include "core/object/payload.h" +#include "core/assert.h" + +#include +#include +#ifdef HAVE_ENDIAN_H +#include +#else +#ifdef HAVE_SYS_ENDIAN_H +#include +#else +#ifdef HAVE_MACHINE_ENDIAN_H +#include +#endif +#endif +#endif +#ifdef HAVE_BYTESWAP_H +#include +#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 . + */ + +#include "core/log.h" +#include "core/object.h" + +#ifndef __dnsjit_core_object_dns_h +#define __dnsjit_core_object_dns_h + +#include +#include + +#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 . + */ + +//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 . + +-- 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 . + +-- 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 "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 . + +-- 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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/ether.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_ether_h +#define __dnsjit_core_object_ether_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/gre.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_gre_h +#define __dnsjit_core_object_gre_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/icmp.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_icmp_h +#define __dnsjit_core_object_icmp_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/icmp6.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_icmp6_h +#define __dnsjit_core_object_icmp6_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/ieee802.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_ieee802_h +#define __dnsjit_core_object_ieee802_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/ip.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_ip_h +#define __dnsjit_core_object_ip_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/ip6.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_ip6_h +#define __dnsjit_core_object_ip6_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/linuxsll.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_linuxsll_h +#define __dnsjit_core_object_linuxsll_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/loop.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_loop_h +#define __dnsjit_core_object_loop_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/null.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_null_h +#define __dnsjit_core_object_null_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/payload.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_payload_h +#define __dnsjit_core_object_payload_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/pcap.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/tcp.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_tcp_h +#define __dnsjit_core_object_tcp_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "core/object/udp.h" +#include "core/assert.h" + +#include +#include + +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 . + */ + +#include "core/object.h" +#include "core/timespec.h" + +#ifndef __dnsjit_core_object_udp_h +#define __dnsjit_core_object_udp_h + +#include + +#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 . + */ + +//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 . + +-- 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 . + +-- 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 . + */ + +#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 . + */ + +#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 . + */ + +//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 . + +-- 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 . + */ + +#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 . + */ + +#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 . + */ + +//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 . + +-- 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 . + */ + +#include "config.h" + +#include "globals.h" +#include "core/assert.h" +#include "core/thread.h" + +#include +#include +#include + +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 . + */ + +#include "core/log.h" + +#ifndef __dnsjit_core_thread_h +#define __dnsjit_core_thread_h + +#include +#include + +#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 . + */ + +//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 . + +-- 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 . + */ + +#ifndef __dnsjit_core_timespec_h +#define __dnsjit_core_timespec_h + +#include + +#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 . + */ + +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 . + +-- 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) -- cgit v1.2.3