fix: populate ldns submodule and add autotools to LDNS build stage

- Re-cloned zonemaster-ldns with --recurse-submodules so the bundled
  ldns C library source (including Changelog and configure.ac) is present
- Added autoconf, automake, libtool to Dockerfile.backend ldns-build stage
  so libtoolize + autoreconf can generate ldns/configure during make

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 08:33:38 +02:00
parent 8d4eaa1489
commit eaaa8f6a11
541 changed files with 138189 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
# Standard installation pathnames
# See the file LICENSE for the license
SHELL = @SHELL@
VERSION = @PACKAGE_VERSION@
basesrcdir = $(shell basename `pwd`)
srcdir = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
mandir = @mandir@
CC = @CC@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
LINT = splint
LINTFLAGS = +quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS)
HEADER = config.h
.PHONY: all clean realclean
all: lua
lua: lua-rns
lua-rns: lua-rns.o
$(LINK) `lua-config --libs` -o $@ $+
#lua-rns.o: lua-rns.c
# $(COMPILE) `lua-config --include` -c $<
## implicit rule
%.o: %.c $(HEADER)
$(COMPILE) `lua-config --include` -c $<
clean:
rm -f *.o
rm -f lua-rns
realclean: clean
rm -rf autom4te.cache/
rm -f config.log config.status aclocal.m4 config.h.in configure Makefile
rm -f config.h
lint:
$(LINT) $(LINTFLAGS) -I$(srcdir)/.. lua-rns.c ; \
if [ $$? -ne 0 ] ; then exit 1 ; fi

View File

@@ -0,0 +1 @@
This (for now) an experimental playground. It is only tested on Linux.

View File

@@ -0,0 +1,83 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT(ldns-tests, 1.7.0, dns-team@nlnetlabs.nl, ldns-tests-1.0)
AC_CONFIG_SRCDIR([../ldns/config.h])
AC_AIX
# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
# Checks for libraries.
# Checks for header files.
#AC_HEADER_STDC
#AC_HEADER_SYS_WAIT
# do the very minimum - we can always extend this
AC_CHECK_HEADERS([getopt.h stdlib.h stdio.h assert.h netinet/in.hctype.h])
AC_CHECK_HEADERS(sys/param.h sys/mount.h,,,
[
[
#if HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
]
])
# ripped from http://autoconf-archive.cryp.to/check_ssl.html
# check for ldns
AC_ARG_WITH(ldns, AC_HELP_STRING([--with-ldns=pathname],[]))
AC_MSG_CHECKING(for ldns/ldns.h)
for dir in $withval /usr/local/ldns /usr/lib/ldns /usr/ldns /usr/pkg /usr/local /usr; do
ldnsdir="$dir"
if test -f "$dir/include/ldns/ldns.h"; then
found_ldns="yes";
CFLAGS="$CFLAGS -I$ldnsdir/include/ -DHAVE_LDNS";
CXXFLAGS="$CXXFLAGS -I$ldnsdir/include/ -DHAVE_LDNS";
break;
fi
if test -f "$dir/ldns/ldns.h"; then
found_ldns="yes";
CFLAGS="$CFLAGS -I$ldnsdir/ -DHAVE_LDNS";
CXXFLAGS="$CXXFLAGS -I$ldnsdir/ -DHAVE_LDNS";
break
fi
done
if test x_$found_ldns != x_yes; then
AC_MSG_RESULT(no)
AC_MSG_ERROR(Cannot find ldns libraries)
else
# printf "ldns found in $ldnsdir\n";
LIBS="$LIBS -lldns";
LDFLAGS="$LDFLAGS -L$ldnsdir/lib";
LDFLAGS="$LDFLAGS -L$ldnsdir/.libs"; # hack for dev.
HAVE_LDNS=yes
AC_MSG_RESULT(yes)
fi
AC_SUBST(HAVE_LDNS)
# I don't use these
# Checks for typedefs, structures, and compiler characteristics.
#AC_TYPE_UID_T
#AC_TYPE_MODE_T
#AC_TYPE_OFF_T
#AC_TYPE_SIZE_T
#AC_STRUCT_TM
# Checks for library functions.
# check for ldns
#AC_FUNC_CHOWN
#AC_FUNC_FORK
#AC_FUNC_MALLOC
#AC_FUNC_MKTIME
#AC_FUNC_STAT
#AC_CHECK_FUNCS([mkdir rmdir strchr strrchr strstr])
#AC_DEFINE_UNQUOTED(SYSCONFDIR, "$sysconfdir")
AC_CONFIG_FILES([Makefile])
AC_CONFIG_HEADER([config.h])
AC_OUTPUT

View File

@@ -0,0 +1,68 @@
-- source the lib file with the function
dofile("rns-lib.lua")
-- echo whatever is received
-- this function disfigures the packet
function lua_packet_mangle(orig_packet)
-- Dont do anything just mirror
-- local rr1 = record.new_frm_str("www.miek.nl IN A 127.0.0.1")
-- packet.push_rr(orig_packet, LDNS_SECTION_ANSWER, rr1)
return(packet.to_buf(orig_packet))
end
rdf_ip = rdf.new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1")
socket = udp.server_open(rdf_ip, 5353)
if socket == nil then
os.exit(EXIT_FAILURE)
end
rdf_ip_nameserver = rdf.new_frm_str(LDNS_RDF_TYPE_A, "213.154.224.39")
while true do
-- read from the socket, this blocks...
wirebuf, sockaddr_from = udp.read(socket)
-- wrap this in new functions
if wirebuf == nil then
lua_debug("nothing received")
else
-- somebody is writing
wirepkt = buffer.to_pkt(wirebuf)
packet.print(wirepkt)
wirebuf2 = packet.to_buf(wirepkt)
-- send it to /our/ nameserver
socket_nameserver = udp.open(rdf_ip_nameserver, 53)
if socket_nameserver == nil then
os.exit(EXIT_FAILURE)
end
nameserver_bytes = udp.write(socket_nameserver, wirebuf2, rdf_ip_nameserver, 53)
if nameserver_bytes == nil then
lua_debug("ns write error")
end
nameserver_buf, sockaddr_from_nameserver = udp.read(socket_nameserver)
udp.close(socket_nameserver)
nameserver_pkt = buffer.to_pkt(nameserver_buf)
packet.print(nameserver_pkt)
-- make a new buf and write that back to the client
nsbuf2 = lua_packet_mangle(nameserver_pkt)
bytes = lua_udp_write(socket, nsbuf2, sockaddr_from) --this works
if bytes == nil then
lua_debug("write error")
end
buffer.free(nsbuf2)
buffer.free(nameserver_buf)
buffer.free(wirebuf2)
buffer.free(wirebuf)
end
end
udp.close(socket)

View File

@@ -0,0 +1,753 @@
/*
* Lua bindings
*
* (c) 2006, NLnet Labs
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdint.h>
/* lua includes */
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
/* ldns include */
#include <ldns/ldns.h>
/* the Lua interpreter */
lua_State* L;
void
usage(FILE *f, char *progname)
{
fprintf(f, "Synopsis: %s lua-script\n", progname);
fprintf(f, " No options are defined (yet)\n");
}
void
version(FILE *f, char *progname)
{
fprintf(f, "%s version %s\n", progname, LDNS_VERSION);
}
/*
=====================================================
Lua bindings for ldns
=====================================================
*/
/*
==========
RDF
==========
*/
static int
l_rdf_new_frm_str(lua_State *L)
{
uint16_t t = (uint16_t)lua_tonumber(L, 1);
char *str = strdup((char*)luaL_checkstring(L, 2));
if (!str) {
return 0;
}
ldns_rdf *new_rdf = ldns_rdf_new_frm_str((ldns_rdf_type)t, str);
if (new_rdf) {
lua_pushlightuserdata(L, new_rdf);
return 1;
} else {
return 0;
}
}
static int
l_rdf_print(lua_State *L)
{
/* we always print to stdout */
ldns_rdf *toprint = (ldns_rdf*)lua_touserdata(L, 1); /* pop from the stack */
if (!toprint) {
return 0;
}
ldns_rdf_print(stdout, toprint);
return 0;
}
static int
l_rdf_free(lua_State *L)
{
ldns_rdf *tofree = (ldns_rdf*)lua_touserdata(L, 1); /* pop from the stack */
if (!tofree) {
return 0;
}
ldns_rdf_free(tofree);
return 0;
}
/*
==========
RR
==========
*/
static int
l_rr_new_frm_str(lua_State *L)
{
/* pop string from stack, make new rr, push rr to
* stack and return 1 - to signal the new pointer
*/
char *str = strdup((char*)luaL_checkstring(L, 1));
uint16_t ttl = (uint16_t)lua_tonumber(L, 2);
ldns_rdf *orig = (ldns_rdf*)lua_touserdata(L, 2);
if (!str) {
return 0;
}
ldns_rr *new_rr = ldns_rr_new_frm_str(str, ttl, orig);
if (new_rr) {
lua_pushlightuserdata(L, new_rr);
return 1;
} else {
return 0;
}
}
static int
l_rr_print(lua_State *L)
{
/* we always print to stdout */
ldns_rr *toprint = (ldns_rr*)lua_touserdata(L, 1); /* pop from the stack */
if (!toprint) {
return 0;
}
ldns_rr_print(stdout, toprint);
return 0;
}
static int
l_rr_free(lua_State *L)
{
ldns_rr *tofree = (ldns_rr*)lua_touserdata(L, 1); /* pop from the stack */
if (!tofree) {
return 0;
}
ldns_rr_free(tofree);
return 0;
}
/*
=========
PACKETS
=========
*/
static int
l_pkt_new(lua_State *L)
{
ldns_pkt *new_pkt = ldns_pkt_new();
if (new_pkt) {
lua_pushlightuserdata(L, new_pkt);
return 1;
} else {
return 0;
}
}
static int
l_pkt_push_rr(lua_State *L)
{
ldns_pkt *pkt = (ldns_pkt*)lua_touserdata(L, 1); /* get the packet */
ldns_pkt_section s = (ldns_pkt_section)lua_tonumber(L, 2); /* the section where to put it */
ldns_rr *rr = (ldns_rr*)lua_touserdata(L, 3); /* the rr to put */
if (!pkt) {
return 0;
}
if (ldns_pkt_push_rr(pkt, s, rr)) {
lua_pushlightuserdata(L, pkt);
return 1;
} else {
return 0;
}
}
static int
l_pkt_insert_rr(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
ldns_rr *rr = (ldns_rr*)lua_touserdata(L, 2);
uint16_t n = (uint16_t)lua_tonumber(L, 3);
if (!p) {
return 0;
}
if(ldns_pkt_insert_rr(p, rr, n)) {
lua_pushlightuserdata(L, p);
return 1;
} else {
return 0;
}
}
static int
l_pkt_get_rr(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1); /* pop from the stack */
uint16_t n = (uint16_t) lua_tonumber(L, 2);
ldns_rr *r;
if (!p) {
return 0;
}
r = ldns_pkt_get_rr(p, n);
if (r) {
lua_pushlightuserdata(L, r);
return 1;
} else {
return 0;
}
}
static int
l_pkt_set_rr(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
ldns_rr *rr = (ldns_rr*)lua_touserdata(L, 2);
uint16_t n = (uint16_t)lua_tonumber(L, 3);
ldns_rr *r;
if (!p || !rr) {
return 0;
}
r = ldns_pkt_set_rr(p, rr, n);
if (r) {
lua_pushlightuserdata(L, r);
return 1;
} else {
return 0;
}
}
static int
l_pkt_rr_count(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, ldns_pkt_section_count(p, LDNS_SECTION_ANY));
return 1;
}
static int
l_pkt_print(lua_State *L)
{
/* we always print to stdout */
ldns_pkt *toprint = (ldns_pkt*)lua_touserdata(L, 1); /* pop from the stack */
if (!toprint) {
return 0;
}
ldns_pkt_print(stdout, toprint);
return 0;
}
/*
===========
NETWORKING
===========
*/
static int
l_server_socket_udp(lua_State *L)
{
ldns_rdf *ip = (ldns_rdf*)lua_touserdata(L, 1); /* get the ip */
uint16_t port = (uint16_t)lua_tonumber(L, 2); /* port number */
struct timeval timeout;
struct sockaddr_storage *to;
size_t socklen;
int sockfd;
if (!ip || port == 0) {
return 0;
}
/* use default timeout - maybe this gets to be configurable */
timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
/* socklen isn't really useful here */
to = ldns_rdf2native_sockaddr_storage(ip, port, &socklen);
if (!to) {
return 0;
}
/* get the socket */
sockfd = ldns_udp_server_connect(to, timeout);
if (sockfd == 0) {
return 0;
}
lua_pushnumber(L, (lua_Number)sockfd);
return 1;
}
static int
l_client_socket_udp(lua_State *L)
{
ldns_rdf *ip = (ldns_rdf*)lua_touserdata(L, 1); /* get the ip */
uint16_t port = (uint16_t)lua_tonumber(L, 2); /* port number */
struct timeval timeout;
struct sockaddr_storage *to;
size_t socklen;
int sockfd;
if (!ip || port == 0) {
return 0;
}
/* use default timeout - maybe this gets to be configurable */
timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
/* socklen isn't really useful here */
to = ldns_rdf2native_sockaddr_storage(ip, port, &socklen);
if (!to) {
return 0;
}
/* get the socket */
sockfd = ldns_udp_connect(to, timeout);
if (sockfd == 0) {
return 0;
}
lua_pushnumber(L, (lua_Number)sockfd);
return 1;
}
static int
l_server_socket_close_udp(lua_State *L)
{
int sockfd = (int)lua_tonumber(L, 1);
if (sockfd == 0) {
return 0;
}
close(sockfd);
}
static int
l_write_wire_udp(lua_State *L)
{
int sockfd = (int)lua_tonumber(L, 1);
ldns_buffer *pktbuf = (ldns_buffer*)lua_touserdata(L, 2);
ldns_rdf *rdf_to = (ldns_rdf*)lua_touserdata(L, 3);
uint16_t port = (uint16_t)lua_tonumber(L, 4); /* port number */
struct sockaddr_storage *to;
size_t socklen;
ssize_t bytes;
if (!pktbuf || !rdf_to || port == 0) {
return 0;
}
/* port number is handled in the socket */
to = ldns_rdf2native_sockaddr_storage(rdf_to, port, &socklen);
if (!to) {
return 0;
}
bytes = ldns_udp_send_query(pktbuf, sockfd, to, (socklen_t)socklen);
if (bytes == 0) {
return 0;
} else {
lua_pushnumber(L, (lua_Number)bytes);
return 1;
}
}
static int
l_read_wire_udp(lua_State *L)
{
int sockfd = (int)lua_tonumber(L, 1);
size_t size;
uint8_t *pktbuf_raw;
ldns_buffer *pktbuf;
struct sockaddr_storage *from;
socklen_t from_len;
if (sockfd == 0) {
return 0;
}
from = LDNS_MALLOC(struct sockaddr_storage);
if (!from) {
return 0;
}
(void)memset(from, 0, sizeof(struct sockaddr_storage));
from_len = sizeof(struct sockaddr_storage); /* set to predefined state */
pktbuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* this /should/ happen in buf_new_frm_data */
if (!pktbuf) {
return 0;
}
pktbuf_raw = ldns_udp_read_wire(sockfd, &size, from, &from_len);
if (!pktbuf_raw) {
return 0;
}
ldns_buffer_new_frm_data(pktbuf, pktbuf_raw, size);
/* push our buffer onto the stack */
/* stack func lua cal in same order buf, from */
lua_pushlightuserdata(L, pktbuf);
lua_pushlightuserdata(L, from);
return 2;
}
/* header bits */
/* read section counters */
static int
l_pkt_qdcount(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, (lua_Number)ldns_pkt_qdcount(p));
return 1;
}
static int
l_pkt_ancount(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, (lua_Number)ldns_pkt_ancount(p));
return 1;
}
static int
l_pkt_nscount(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, (lua_Number)ldns_pkt_nscount(p));
return 1;
}
static int
l_pkt_arcount(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, (lua_Number)ldns_pkt_arcount(p));
return 1;
}
static int
l_pkt_set_ancount(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
uint16_t count = (uint16_t)lua_tonumber(L, 2);
if (!p) {
return 0;
}
(void)ldns_pkt_set_ancount(p, count);
return 0;
}
static int
l_pkt_id(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
if (!p) {
return 0;
}
lua_pushnumber(L, (lua_Number)ldns_pkt_id(p));
return 1;
}
static int
l_pkt_set_id(lua_State *L)
{
ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
uint16_t id = (uint16_t)lua_tonumber(L, 2);
if (!p) {
return 0;
}
ldns_pkt_set_id(p, id);
return 0;
}
/* BUFFERs */
static int
l_buf_free(lua_State *L)
{
ldns_buffer *b = (ldns_buffer *)lua_touserdata(L, 1);
if (!b) {
return 0;
}
ldns_buffer_free(b);
return 0;
}
static int
l_buf_info(lua_State *L)
{
ldns_buffer *b = (ldns_buffer *)lua_touserdata(L, 1);
if (!b) {
return 0;
}
printf("capacity %d; position %d; limit %d\n",
ldns_buffer_capacity(b),
ldns_buffer_position(b),
ldns_buffer_limit(b));
return 0;
}
/*
============
CONVERSION
============
*/
static int
l_buf2pkt(lua_State *L)
{
ldns_buffer *b = (ldns_buffer *)lua_touserdata(L, 1);
ldns_pkt *p;
if (!b) {
return 0;
}
if (ldns_buffer2pkt_wire(&p, b) != LDNS_STATUS_OK) {
return 0;
}
lua_pushlightuserdata(L, p);
return 1;
}
static int
l_pkt2buf(lua_State *L)
{
ldns_pkt *p = (ldns_pkt *)lua_touserdata(L, 1);
ldns_buffer *b;
if (!p) {
return 0;
}
b = ldns_buffer_new(LDNS_MIN_BUFLEN);
if (ldns_pkt2buffer_wire(b, p) != LDNS_STATUS_OK) {
ldns_buffer_free(b);
return 0;
}
lua_pushlightuserdata(L, b);
return 1;
}
static int
l_pkt2string(lua_State *L)
{
ldns_buffer *b;
luaL_Buffer lua_b;
ldns_pkt *p = (ldns_pkt *)lua_touserdata(L, 1);
if (!p) {
return 0;
}
b = ldns_buffer_new(LDNS_MAX_PACKETLEN);
luaL_buffinit(L,&lua_b);
if (ldns_pkt2buffer_wire(b, p) != LDNS_STATUS_OK) {
ldns_buffer_free(b);
return 0;
}
/* this is a memcpy??? */
luaL_addlstring(&lua_b,
(char*)ldns_buffer_begin(b),
ldns_buffer_capacity(b)
);
/* I hope so */
ldns_buffer_free(b);
luaL_pushresult(&lua_b);
return 1;
}
static int
l_sockaddr_storage2rdf(lua_State *L)
{
struct sockaddr_storage *sock;
uint16_t port;
ldns_rdf *addr;
sock = lua_touserdata(L, 1);
if (!sock) {
return 0;
}
addr = ldns_sockaddr_storage2rdf(sock, &port);
if (addr) {
lua_pushlightuserdata(L, addr);
lua_pushnumber(L, (lua_Number)port);
return 2;
} else {
return 0;
}
}
/*
============
EXAMPLES
============
*/
static int
l_average(lua_State *L)
{
int n = lua_gettop(L);
double sum = 0;
int i;
/* loop through each argument */
for (i = 1; i <= n; i++)
{
/* total the arguments */
sum += lua_tonumber(L, i);
}
lua_pushnumber(L, sum / n);
lua_pushnumber(L, sum);
return 2;
}
/*
=====================================================
Lua bindings for ldns
=====================================================
*/
void
register_ldns_functions(void)
{
/* register our functions */
lua_register(L, "l_average", l_average);
/* RDFs */
static const struct luaL_reg l_rdf_lib [] = {
{"new_frm_str", l_rdf_new_frm_str},
{"print", l_rdf_print},
{"free", l_rdf_free},
{"sockaddr_to_rdf", l_sockaddr_storage2rdf},
{NULL, NULL}
};
luaL_openlib(L, "rdf", l_rdf_lib, 0);
/* RRs */
static const struct luaL_reg l_rr_lib [] = {
{"new_frm_str", l_rr_new_frm_str},
{"print", l_rr_print},
{"free", l_rr_free},
{NULL, NULL}
};
luaL_openlib(L, "record", l_rr_lib, 0);
/* PKTs */
static const struct luaL_reg l_pkt_lib [] = {
{"new", l_pkt_new},
{"push_rr", l_pkt_push_rr},
{"get_rr", l_pkt_get_rr},
{"set_rr", l_pkt_set_rr},
{"insert_rr", l_pkt_insert_rr},
{"print", l_pkt_print},
{"qdcount", l_pkt_qdcount},
{"ancount", l_pkt_ancount},
{"nscount", l_pkt_nscount},
{"arcount", l_pkt_arcount},
{"set_ancount", l_pkt_set_ancount},
#if 0
{"set_qdcount", l_pkt_set_qdcount},
{"set_nscount", l_pkt_set_nscount},
{"set_arcount", l_pkt_set_arcount},
#endif
{"rrcount", l_pkt_rr_count},
{"id", l_pkt_id},
{"set_id", l_pkt_set_id},
{"to_string", l_pkt2string},
{"to_buf", l_pkt2buf},
{NULL, NULL}
};
luaL_openlib(L, "packet", l_pkt_lib, 0);
/* BUFFERs */
static const struct luaL_reg l_buf_lib [] = {
{"to_pkt", l_buf2pkt},
{"free", l_buf_free},
{"info", l_buf_info},
{NULL, NULL}
};
luaL_openlib(L, "buffer", l_buf_lib, 0);
/* NETWORKING */
static const struct luaL_reg l_udpnet_lib [] = {
{"write", l_write_wire_udp},
{"read", l_read_wire_udp},
{"server_open", l_server_socket_udp},
{"open", l_client_socket_udp},
{"close", l_server_socket_close_udp},
{NULL, NULL}
};
luaL_openlib(L, "udp", l_udpnet_lib, 0);
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
usage(stderr, argv[0]);
exit(EXIT_FAILURE);
}
if (access(argv[1], R_OK)) {
fprintf(stderr, "File %s is unavailable.\n", argv[1]);
exit(EXIT_FAILURE);
}
L = lua_open();
lua_baselibopen(L);
luaopen_math(L);
luaopen_io(L);
luaopen_string(L);
register_ldns_functions();
/* run the script */
lua_dofile(L, argv[1]);
lua_close(L);
exit(EXIT_SUCCESS);
}

View File

@@ -0,0 +1,7 @@
-- test rdf stuff
dofile("rns-lib.lua")
rdf = l_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "miek.nl")
l_rdf_print(rdf)
print()

View File

@@ -0,0 +1,126 @@
-- ldns defines - need a better way to keep these current
LDNS_SECTION_QUESTION = 0
LDNS_SECTION_ANSWER = 1
LDNS_SECTION_AUTHORITY = 2
LDNS_SECTION_ADDITIONAL = 3
LDNS_SECTION_ANY = 4
LDNS_SECTION_ANY_NOQUESTION = 5
-- rdf types
LDNS_RDF_TYPE_NONE = 0
LDNS_RDF_TYPE_DNAME = 1
LDNS_RDF_TYPE_INT8 = 1
LDNS_RDF_TYPE_INT16 = 3
LDNS_RDF_TYPE_INT32 = 4
LDNS_RDF_TYPE_A = 5
LDNS_RDF_TYPE_AAAA = 6
LDNS_RDF_TYPE_STR = 7
LDNS_RDF_TYPE_APL = 8
LDNS_RDF_TYPE_B32_EXT = 9
LDNS_RDF_TYPE_B64 = 10
LDNS_RDF_TYPE_HEX = 11
LDNS_RDF_TYPE_NSEC = 12
LDNS_RDF_TYPE_TYPE = 13
LDNS_RDF_TYPE_CLASS = 14
LDNS_RDF_TYPE_CERT = 15
LDNS_RDF_TYPE_ALG = 16
LDNS_RDF_TYPE_UNKNOWN = 17
LDNS_RDF_TYPE_TIME = 18
LDNS_RDF_TYPE_PERIOD = 19
LDNS_RDF_TYPE_TSIGTIME = 20
LDNS_RDF_TYPE_HIP = 21
LDNS_RDF_TYPE_INT16_DATA = 22
LDNS_RDF_TYPE_SERVICE = 23
LDNS_RDF_TYPE_LOC = 24
LDNS_RDF_TYPE_WKS = 25
LDNS_RDF_TYPE_NSAP = 26
LDNS_RDF_TYPE_ATMA = 27
LDNS_RDF_TYPE_IPSECKEY = 28
function lua_debug(...)
print("[lua]", unpack(arg))
end
-- transpose 2 rrs in a pkt --
function lua_record_transpose(pkt, n1, n2)
print("[info] [RR] transpose", n1, n2)
local rr_n1 = packet.get_rr(pkt, n1)
local rr_n2 = packet.set_rr(pkt, rr_n1, n2)
local rr_tm = packet.set_rr(pkt, rr_n2, n1)
record.free(rm_tm)
end
-- _R := random
function lua_record_transpose_R(pkt)
local total = packet.rrcount(pkt) - 1
local rn1 = math.random(0, total)
local rn2 = math.random(0, total)
lua_transpose_record(pkt, rn1, rn2)
end
-- substitute, add, remove
function lua_record_insert(pkt, r, n)
print("[info] [RR] insert after", n)
packet.insert_rr(pkt, r, n)
end
-- add an rr to the end of a pkt --
-- _E := end
function lua_record_insert_E(pkt, r)
local n = packet.rrcount(pkt) - 1
print(n)
lua_insert_rr(pkt, r, n)
end
-- remove an rr from the end of a pkt --
--pop??
function lua_record_remove_E(pkt, n)
print("[info] [RR] remove", "end")
end
-- increment the ancount
function lua_packet_ancount_incr(pkt, n)
print("[info] [PKT] ancount incr", n)
an = packet.ancount(pkt)
n = an + n
packet.set_ancount(pkt, n)
end
---------------------------------
-- higher level --
---------------------------------
-- reverse all the rrs in a pkt --
function lua_packet_reverse(pkt)
local total = packet.rrcount(pkt) - 1
for i=0, (total / 2) do
lua_transpose_rr(pkt, i, total - i)
end
end
-- write a buffer to a socket
function lua_udp_write(socket, buffer_wire, sock_from)
-- convert the sockaddr_storage to something we
-- can work with
-- checks
if socket == 0 then return -1 end
if buffer_wire == nil then return -1 end
if sock_from == nil then return -1 end
rdf_listen, port_listen = rdf.sockaddr_to_rdf(sock_from)
bytes = udp.write(socket, buffer_wire, rdf_listen, port_listen)
return bytes
end
-- initialize the pseudo random number generator
-- frm: http://lua-users.org/wiki/MathLibraryTutorial
function lua_rand_init()
math.randomseed(os.time())
math.random()
math.random()
math.random()
end
lua_rand_init()

View File

@@ -0,0 +1,128 @@
* Classes of Manglement
from higher to lower level:
- deliberately mess up a resolver ability to recurse
- move RRsets to different sections
- fiddle with the ID
- add/delete RRs
- remove glue, add wrong glue
- add fake signatures
- split up RRsets
== mess with the final packet ==
- distort the compression pointers in the final packet
- swap bytes in the final packet
- swap bits in the final packet
Based on a simple ldns-based nameserver.
A configuration file is needed to tell it what to do. Some form
of random stuff is also required.
Ideally what I want is that you "program" you nameserver to mangle
the packets.
The mangle stage should be seen as a lego system, where you can connect
different boxes together and push the assembled packet through it.
So RNS should be able to deal with raw packets, so you can put it
IN FRONT of another nameserver or it can directly deal with a ldns_packet*.
Best way would be to build RNS is as a filter that can be put between the
resolver and nameserver. Or, if running on localhost, all answers can be
sent to a special IP of the resolver you want to test.
** Mangle Blocks
Each mangle function is effectively called from the configuration file.
From the config file a mangle-engine is built. The packet is then put
through this engine. After that a binary blob (with a length) comes
out. This blob is then sent out to the network.
* Design of RNS
You program the engine in Lua by using ldns building blocks.
I must be able to call C ldns functions from lua and pass data
from and to the functions.
:Binary filter:
Steps:
1. suck in a packet
b: check ip dst address
2. mangle it according to the configuration file
3. rebuilt and put out the new packet. (Or binary blob, or whatever)
* Implementation
A bunch of blob/packet functions-in/out.
So blob_out* lua_mangle_remove_rr(blob_in*, random, extra args??);
See are then chained together by the lua code.
:Packet Mangling:
These are the four basic operations:
Transpose: switching 2 elements
Substitute: replace an element with another one
(could be random)
Add: add an element
Remove: remove an element
Each operation can be done on a different level, we distinguish between the
following levels:
packet-level: the header bits, number of rr in a specific section,
rr-level: placement of rrs (which section)
byte-level: handle specific bytes, like the compression pointers (2
bytes)
bit-level: handle specific bits
All 4 operation can be applied at all levels, this gives us 16 degrees of
freedom in the packet mangling. (ghe ghe :-) )
To keep matters interesting some sort of randomness is required in some
step, otherwise each packet is mangled in the same way. Also this
randomness together with the Lua script needs to be logged so the
actual mangling can be replayed.
:Packet Mangling: address the different elements:
We need a way to address our elements:
elements: (network order)
bytes: numbered from 0 till the end of the packet
bits: within each byte numbered from 0 till 7
sections: numbered from the start of the packet (mnemonics?)
rr: numbered in each section
Ambivalent on whether we need something like addresses: section_answer?
ldns_* provides it. Should we use that?????
::Packet Mangling Implementation::
Example:
Suppose we have a mangling operation that mangles RR (at the rr-level):
transpose_rr(packet, rr1_position, rr2_position)
The 2 rr's are now flipped. We could also use rand0 for the position
thereby letting the system decide. All these mangling functions should
this log what they do.
:: Short Term Implementation ::
Try to switch 2 rrs from one section to another. Complex addressing of
a packet <Section, RR number> probably.... Section can be random, RR number
can be random.
:: Addressing ::
everything is numbered from 0 to n-1, so n objects
this is how things go in side the packet too, so it is the easiest
:: Lua Implementation ::
RR level -> ldns stuff
Packet level -> ldns stuff
Byte level -> Lua string
Bit level -> Lua string, but add C bit ops

View File

@@ -0,0 +1,68 @@
-- source the lib file with the function
dofile("rns-lib.lua")
-- echo whatever is received
-- this function disfigures the packet
function lua_packet_mangle(orig_packet)
-- MANGLE IT
local rr1 = record.new_frm_str("www.miek.nl IN A 127.0.0.1")
packet.push_rr(orig_packet, LDNS_SECTION_ANSWER, rr1)
return(packet.to_buf(orig_packet))
end
rdf_ip = rdf.new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1")
socket = udp.server_open(rdf_ip, 5353)
if socket == nil then
os.exit(EXIT_FAILURE)
end
rdf_ip_nameserver = rdf.new_frm_str(LDNS_RDF_TYPE_A, "213.154.224.39")
while true do
-- read from the socket, this blocks...
wirebuf, sockaddr_from = udp.read(socket)
-- wrap this in new functions
if wirebuf == nil then
lua_debug("nothing received")
else
-- somebody is writing
wirepkt = buffer.to_pkt(wirebuf)
packet.print(wirepkt)
wirebuf2 = packet.to_buf(wirepkt)
-- send it to /our/ nameserver
socket_nameserver = udp.open(rdf_ip_nameserver, 53)
if socket_nameserver == nil then
os.exit(EXIT_FAILURE)
end
nameserver_bytes = udp.write(socket_nameserver, wirebuf2, rdf_ip_nameserver, 53)
if nameserver_bytes == nil then
lua_debug("ns write error")
end
nameserver_buf, sockaddr_from_nameserver = udp.read(socket_nameserver)
udp.close(socket_nameserver)
nameserver_pkt = buffer.to_pkt(nameserver_buf)
packet.print(nameserver_pkt)
-- make a new buf and write that back to the client
nsbuf2 = lua_packet_mangle(nameserver_pkt)
bytes = lua_udp_write(socket, nsbuf2, sockaddr_from) --this works
if bytes == nil then
lua_debug("write error")
end
buffer.free(nsbuf2)
buffer.free(nameserver_buf)
buffer.free(wirebuf2)
buffer.free(wirebuf)
end
end
udp.close(socket)

View File

@@ -0,0 +1,63 @@
-- source the lib file with the function
dofile("rns-lib.lua")
rr1 = record.new_frm_str("www.miek.nl IN A 192.168.1.2", 0, nil)
rr2 = record.new_frm_str("miek.nl IN ns gaap", 0, nil)
rr3 = record.new_frm_str("miek.nl IN ns gaap2", 0, nil)
rr4 = record.new_frm_str("www.atoom.net. IN A 192.168.1.2", 0, nil)
rr5 = record.new_frm_str("www.nlnetlabs.nl IN A 192.168.1.2", 0, nil)
rr6 = record.new_frm_str("www.nlnet.nl IN A 192.168.1.2", 0, nil)
pkt = packet.new()
pkt = packet.push_rr(pkt, LDNS_SECTION_ANSWER, rr1)
pkt = packet.push_rr(pkt, LDNS_SECTION_ANSWER, rr4)
pkt = packet.push_rr(pkt, LDNS_SECTION_AUTHORITY, rr2)
pkt = packet.push_rr(pkt, LDNS_SECTION_AUTHORITY, rr3)
---- Setup a server to listen to UDP -- bit strange to first
-- make a rdf out of it and then continue with the sockaddr struct
rdf_ip = rdf.new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1")
socket = udp.server_open(rdf_ip, 5353)
if socket == nil then
os.exit(EXIT_FAILURE)
end
while true do
-- read from the socket, this blocks...
wirebuf, sockaddr_from = udp.read(socket)
-- wrap this in new functions
if wirebuf == nil then
lua_debug("nothing received")
else
-- somebody is writing
wirepkt = buffer.to_pkt(wirebuf)
lua_debug("received from the interface")
-- next we must send it to our recursive nameserver
-- and pick up the result
-- then we modify the result somewhat and sent it back
-- to the client
id = packet.id(wirepkt);
packet.print(wirepkt)
-- set the id on the outgoing packet
packet.set_id(pkt, id)
lua_packet_ancount_incr(pkt, 2)
wirebuf2 = packet.to_buf(pkt)
-- write back to the client
bytes = lua_udp_write(socket, wirebuf2, sockaddr_from)
if bytes == -1 then
lua_debug("write error")
else
lua_debug("wrote bytes", bytes)
packet.print(pkt)
end
end
end
udp.close(socket)

View File

@@ -0,0 +1,32 @@
-- source the lib file with the function
dofile("rns-lib.lua")
-- Now the scary ldns_* stuff
my_rr = record.new_frm_str("www.miek.nl IN A 192.168.1.2")
my_rr2 = record.new_frm_str("www.miek.nl")
my_rr4 = record.new_frm_str("www.atoom.net. IN A 192.168.1.2")
record.print(my_rr)
record.print(my_rr2)
record.print(my_rr4)
my_pkt = packet.new();
my_pkt = packet.push_rr(my_pkt, LDNS_SECTION_ANSWER, my_rr)
packet.print(my_pkt)
my_pkt = packet.push_rr(my_pkt, LDNS_SECTION_ANSWER, my_rr2)
my_rr3 = packet.get_rr(my_pkt, 0);
record.print(my_rr3)
my_rr3 = packet.get_rr(my_pkt, 1);
record.print(my_rr3)
packet.print(my_pkt)
my_rr5 = packet.set_rr(my_pkt, my_rr4, 1)
record.print(my_rr5)
packet.set_id(my_pkt, 1505)
packet.print(my_pkt)

View File

@@ -0,0 +1,22 @@
-- source the lib file with the function
dofile("rns-lib.lua")
my_pkt = packet.new()
my_rdf = rdf.new_frm_str(LDNS_RDF_TYPE_DNAME, "miek.nl")
if my_rdf == nil then
print("failure")
end
rdf.print(my_rdf)
my_rr = record.new_frm_str("www.miek.nl in a 192.168.1.1")
record.print(my_rr)
my_pkt = packet.new()
packet.push_rr(my_pkt, LDNS_SECTION_ANSWER, my_rr)
packet.push_rr(my_pkt, LDNS_SECTION_ANSWER, my_rr)
packet.push_rr(my_pkt, LDNS_SECTION_ANSWER, my_rr)
lua_record_insert(my_pkt, my_rr, 2)
packet.print(my_pkt)