From b8d0f83e6cea9640a7ee4402c163ad812237355d Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Sun, 10 Dec 2023 11:48:01 +0000 Subject: Initial commit Signed-off-by: Laurent Bercot --- .gitignore | 12 + AUTHORS | 5 + CONTRIBUTING | 5 + COPYING | 13 + DCO | 37 +++ INSTALL | 175 ++++++++++ Makefile | 148 +++++++++ NEWS | 6 + README | 23 ++ README.macos | 3 + README.solaris | 11 + configure | 459 +++++++++++++++++++++++++++ doc/index.html | 181 +++++++++++ doc/shibari-server-tcp.html | 213 +++++++++++++ doc/shibari-server-udp.html | 163 ++++++++++ doc/upgrade.html | 28 ++ package/deps-build | 3 + package/deps.mak | 66 ++++ package/info | 4 + package/modes | 2 + package/targets.mak | 7 + patch-for-solaris | 21 ++ src/cache/dcache-internal.h | 18 ++ src/cache/dcache_add.c | 85 +++++ src/cache/dcache_clean_expired.c | 20 ++ src/cache/dcache_delete.c | 19 ++ src/cache/dcache_free.c | 22 ++ src/cache/dcache_init.c | 55 ++++ src/cache/dcache_load.c | 81 +++++ src/cache/dcache_save.c | 73 +++++ src/cache/dcache_search.c | 15 + src/cache/deps-lib/dcache | 8 + src/common/deps-lib/shibari-common | 10 + src/common/shibari_log_answer.c | 36 +++ src/common/shibari_log_exit.c | 14 + src/common/shibari_log_query.c | 18 ++ src/common/shibari_log_queryplus.c | 24 ++ src/common/shibari_log_start.c | 17 + src/common/shibari_util_get_prefixlen.c | 14 + src/common/shibari_util_qtype_num.c | 121 +++++++ src/common/shibari_util_qtype_str.c | 285 +++++++++++++++++ src/common/shibari_util_rcode_str.c | 41 +++ src/include/shibari/cache.h | 8 + src/include/shibari/client.h | 6 + src/include/shibari/common.h | 9 + src/include/shibari/constants.h | 109 +++++++ src/include/shibari/dcache.h | 54 ++++ src/include/shibari/log.h | 20 ++ src/include/shibari/packet.h | 39 +++ src/include/shibari/server.h | 10 + src/include/shibari/shibari.h | 11 + src/include/shibari/tdb.h | 29 ++ src/include/shibari/util.h | 14 + src/server/deps-exe/shibari-server-tcp | 4 + src/server/deps-exe/shibari-server-udp | 6 + src/server/deps-lib/shibari-server | 13 + src/server/shibari-server-tcp.c | 235 ++++++++++++++ src/server/shibari-server-udp.c | 207 ++++++++++++ src/server/shibari_packet_add_glue.c | 48 +++ src/server/shibari_packet_add_rr.c | 46 +++ src/server/shibari_packet_assert_authority.c | 18 ++ src/server/shibari_packet_begin.c | 32 ++ src/server/shibari_packet_end.c | 13 + src/server/shibari_packet_init.c | 14 + src/server/shibari_packet_tdb_answer_query.c | 93 ++++++ src/server/shibari_tdb_entry_parse.c | 56 ++++ src/server/shibari_tdb_extract_domain.c | 17 + src/server/shibari_tdb_find_authority.c | 46 +++ src/server/shibari_tdb_read_entry.c | 22 ++ tools/gen-deps.sh | 93 ++++++ tools/install.sh | 64 ++++ 71 files changed, 3897 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 CONTRIBUTING create mode 100644 COPYING create mode 100644 DCO create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README create mode 100644 README.macos create mode 100644 README.solaris create mode 100755 configure create mode 100644 doc/index.html create mode 100644 doc/shibari-server-tcp.html create mode 100644 doc/shibari-server-udp.html create mode 100644 doc/upgrade.html create mode 100644 package/deps-build create mode 100644 package/deps.mak create mode 100644 package/info create mode 100644 package/modes create mode 100644 package/targets.mak create mode 100755 patch-for-solaris create mode 100644 src/cache/dcache-internal.h create mode 100644 src/cache/dcache_add.c create mode 100644 src/cache/dcache_clean_expired.c create mode 100644 src/cache/dcache_delete.c create mode 100644 src/cache/dcache_free.c create mode 100644 src/cache/dcache_init.c create mode 100644 src/cache/dcache_load.c create mode 100644 src/cache/dcache_save.c create mode 100644 src/cache/dcache_search.c create mode 100644 src/cache/deps-lib/dcache create mode 100644 src/common/deps-lib/shibari-common create mode 100644 src/common/shibari_log_answer.c create mode 100644 src/common/shibari_log_exit.c create mode 100644 src/common/shibari_log_query.c create mode 100644 src/common/shibari_log_queryplus.c create mode 100644 src/common/shibari_log_start.c create mode 100644 src/common/shibari_util_get_prefixlen.c create mode 100644 src/common/shibari_util_qtype_num.c create mode 100644 src/common/shibari_util_qtype_str.c create mode 100644 src/common/shibari_util_rcode_str.c create mode 100644 src/include/shibari/cache.h create mode 100644 src/include/shibari/client.h create mode 100644 src/include/shibari/common.h create mode 100644 src/include/shibari/constants.h create mode 100644 src/include/shibari/dcache.h create mode 100644 src/include/shibari/log.h create mode 100644 src/include/shibari/packet.h create mode 100644 src/include/shibari/server.h create mode 100644 src/include/shibari/shibari.h create mode 100644 src/include/shibari/tdb.h create mode 100644 src/include/shibari/util.h create mode 100644 src/server/deps-exe/shibari-server-tcp create mode 100644 src/server/deps-exe/shibari-server-udp create mode 100644 src/server/deps-lib/shibari-server create mode 100644 src/server/shibari-server-tcp.c create mode 100644 src/server/shibari-server-udp.c create mode 100644 src/server/shibari_packet_add_glue.c create mode 100644 src/server/shibari_packet_add_rr.c create mode 100644 src/server/shibari_packet_assert_authority.c create mode 100644 src/server/shibari_packet_begin.c create mode 100644 src/server/shibari_packet_end.c create mode 100644 src/server/shibari_packet_init.c create mode 100644 src/server/shibari_packet_tdb_answer_query.c create mode 100644 src/server/shibari_tdb_entry_parse.c create mode 100644 src/server/shibari_tdb_extract_domain.c create mode 100644 src/server/shibari_tdb_find_authority.c create mode 100644 src/server/shibari_tdb_read_entry.c create mode 100755 tools/gen-deps.sh create mode 100755 tools/install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0552150 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.o +*.lo +/config.mak +/src/include/shibari/config.h +/libdcache.a.xyzzy +/libdcache.so.xyzzy +/libshibari-common.a.xyzzy +/libshibari-common.so.xyzzy +/libshibari-server.a.xyzzy +/libshibari-server.so.xyzzy +/shibari-server-tcp +/shibari-server-udp diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6bbf321 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +Main author: + Laurent Bercot + +Thanks to: + Dan J. Bernstein diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..6279422 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,5 @@ + Please add a Signed-Off-By: line at the end of your commit, +which certifies that you have the right and authority to pass +it on as an open-source patch, as explicited in the Developer's +Certificate of Origin available in this project's DCO file, +or at https://developercertificate.org/ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..fe81b1d --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2023 Laurent Bercot + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/DCO b/DCO new file mode 100644 index 0000000..8201f99 --- /dev/null +++ b/DCO @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..5e2d943 --- /dev/null +++ b/INSTALL @@ -0,0 +1,175 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A POSIX-compliant C development environment + - GNU make version 3.81 or later + - skalibs version 2.14.0.1 or later: https://skarnet.org/software/skalibs/ + - s6 version 2.12.0.2 or later: https://skarnet.org/software/s6/ + - for now: s6-dns version 2.3.7.0 or later: https://skarnet.org/software/s6-dns/ + + This software will run on any operating system that implements +POSIX.1-2008, available at: + https://pubs.opengroup.org/onlinepubs/9699919799/ + + +* Standard usage + -------------- + + ./configure && make && sudo make install + + will work for most users. + It will install the binaries in /usr/bin and the static libraries in +/usr/lib/shibari. + + Please note that static libraries in /usr/lib/shibari *will not* +be found by a default linker invocation: you need -L/usr/lib/shibari. +Other skarnet.org software automatically handles that case if the +default configuration is used, but if you change the configuration, +remember to use the appropriate --with-lib configure option. + + You can strip the binaries and libraries of their extra symbols via +"make strip" before the "make install" phase. It will shave a few bytes +off them. + + +* Customization + ------------- + + You can customize paths via flags given to configure. + See ./configure --help for a list of all available configure options. + + +* Environment variables + --------------------- + + Controlling a build process via environment variables is a big and +dangerous hammer. You should try and pass flags to configure instead; +nevertheless, a few standard environment variables are recognized. + + If the CC environment variable is set, its value will override compiler +detection by configure. The --host=HOST option will still add a HOST- +prefix to the value of CC. + + The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags +auto-detected by configure. To entirely override the flags set by +configure instead, use make variables. + + +* Make variables + -------------- + + You can invoke make with a few variables for more configuration. + + CC, CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS, AR, RANLIB, STRIP, INSTALL and +CROSS_COMPILE can all be overridden on the make command line. This is +an even bigger hammer than running ./configure with environment +variables, so it is advised to only do this when it is the only way of +obtaining the behaviour you want. + + DESTDIR can be given on the "make install" command line in order to +install to a staging directory. + + +* Shared libraries + ---------------- + + Software from skarnet.org is small enough that shared libraries are +generally not worth using. Static linking is simpler and incurs less +runtime overhead and less points of failure: so by default, shared +libraries are not built and binaries are linked against the static +versions of the skarnet.org libraries. Nevertheless, you can: + * build shared libraries: --enable-shared + * link binaries against shared libraries: --disable-allstatic + + +* Static binaries + --------------- + + By default, binaries are linked against static versions of all the +libraries they depend on, except for the libc. You can enforce +linking against the static libc with --enable-static-libc. + + (If you are using a GNU/Linux system, be aware that the GNU libc +behaves badly with static linking and produces huge executables, +which is why it is not the default. Other libcs are better suited +to static linking, for instance musl: http://musl-libc.org/) + + +* Cross-compilation + ----------------- + + skarnet.org packages centralize all the difficulty of +cross-compilation in one place: skalibs. Once you have +cross-compiled skalibs, the rest is easy. + + * Use the --host=HOST option to configure, HOST being the triplet +for your target. + * Make sure your cross-toolchain binaries (i.e. prefixed with HOST-) +are accessible via your PATH environment variable. + * Make sure to use the correct version of skalibs for your target, +and the correct sysdeps directory, making use of the +--with-include, --with-lib, --with-dynlib and --with-sysdeps +options as necessary. + + +* The slashpackage convention + --------------------------- + + The slashpackage convention (http://cr.yp.to/slashpackage.html) +is a package installation scheme that provides a few guarantees +over other conventions such as the FHS, for instance fixed +absolute pathnames. skarnet.org packages support it: use the +--enable-slashpackage option to configure, or +--enable-slashpackage=DIR for a prefixed DIR/package tree. +This option will activate slashpackage support during the build +and set slashpackage-compatible installation directories. +If $package_home is the home of the package, defined as +DIR/package/$category/$package-$version with the variables +read from the package/info file, then: + + --dynlibdir is set to $package_home/library.so + --bindir is set to $package_home/command + --sbindir is also set to $package_home/command (slashpackage +differentiates root-only binaries by their Unix rights, not their +location in the filesystem) + --libexecdir is also set to $package_home/command (slashpackage +does not need a specific directory for internal binaries) + --libdir is set to $package_home/library + --includedir is set to $package_home/include + + --prefix is pretty much ignored when you use --enable-slashpackage. +You should probably not use both --enable-slashpackage and --prefix. + + When using slashpackage, two additional Makefile targets are +available after "make install": + - "make update" changes the default version of the software to the +freshly installed one. (This is useful when you have several installed +versions of the same software, which slashpackage supports.) + - "make -L global-links" adds links from /command and /library.so to the +default version of the binaries and shared libraries. The "-L" option to +make is necessary because targets are symbolic links, and the default make +behaviour is to check the pointed file's timestamp and not the symlink's +timestamp. + + +* Absolute pathnames + ------------------ + + You may want to use fixed absolute pathnames even if you're not +following the slashpackage convention: for instance, the Nix packaging +system prefers calling binaries with immutable paths rather than rely on +PATH resolution. If you are in that case, use the --enable-absolute-paths +option to configure. This will ensure that programs calling binaries from +this package will call them with their full installation path (in bindir) +without relying on a PATH search. + + +* Out-of-tree builds + ------------------ + + skarnet.org packages do not support out-of-tree builds. They +are small, so it does not cost much to duplicate the entire +source tree if parallel builds are needed. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b82361b --- /dev/null +++ b/Makefile @@ -0,0 +1,148 @@ +# +# This Makefile requires GNU make. +# +# Do not make changes here. +# Use the included .mak files. +# + +it: all + +make_need := 3.81 +ifeq "" "$(strip $(filter $(make_need), $(firstword $(sort $(make_need) $(MAKE_VERSION)))))" +fail := $(error Your make ($(MAKE_VERSION)) is too old. You need $(make_need) or newer) +endif + +CC = $(error Please use ./configure first) + +STATIC_LIBS := +SHARED_LIBS := +INTERNAL_LIBS := +EXTRA_TARGETS := +LIB_DEFS := + +define library_definition +LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy +ifdef DO_SHARED +SHARED_LIBS += lib$(lastword $(subst =, ,$(1))).so.xyzzy +endif +ifdef DO_STATIC +STATIC_LIBS += lib$(lastword $(subst =, ,$(1))).a.xyzzy +endif +endef + +-include config.mak +include package/targets.mak + +$(foreach var,$(LIB_DEFS),$(eval $(call library_definition,$(var)))) + +include package/deps.mak + +version_m := $(basename $(version)) +version_M := $(basename $(version_m)) +version_l := $(basename $(version_M)) +CPPFLAGS_ALL := $(CPPFLAGS_AUTO) $(CPPFLAGS) +CFLAGS_ALL := $(CFLAGS_AUTO) $(CFLAGS) +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +CFLAGS_SHARED := -fPIC +else +CFLAGS_SHARED := +endif +LDFLAGS_ALL := $(LDFLAGS_AUTO) $(LDFLAGS) +AR := $(CROSS_COMPILE)ar +RANLIB := $(CROSS_COMPILE)ranlib +STRIP := $(CROSS_COMPILE)strip +INSTALL := ./tools/install.sh + +ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) +ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS) +ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) + +all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) $(EXTRA_INCLUDES) + +clean: + @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS) + +distclean: clean + @exec rm -f config.mak src/include/$(package)/config.h + +tgz: distclean + @. package/info && \ + rm -rf /tmp/$$package-$$version && \ + cp -a . /tmp/$$package-$$version && \ + cd /tmp && \ + tar -zpcv --owner=0 --group=0 --numeric-owner --exclude=.git* -f /tmp/$$package-$$version.tar.gz $$package-$$version && \ + exec rm -rf /tmp/$$package-$$version + +strip: $(ALL_LIBS) $(ALL_BINS) +ifneq ($(strip $(STATIC_LIBS)),) + exec $(STRIP) -x -R .note -R .comment $(STATIC_LIBS) +endif +ifneq ($(strip $(ALL_BINS)$(SHARED_LIBS)),) + exec $(STRIP) -R .note -R .comment $(ALL_BINS) $(SHARED_LIBS) +endif + +install: install-dynlib install-libexec install-bin install-lib install-include +install-dynlib: $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(dynlibdir)/lib%.so) +install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) +install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) +install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a) +install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) $(EXTRA_INCLUDES:src/include/%.h=$(DESTDIR)$(includedir)/%.h) + +ifneq ($(exthome),) + +$(DESTDIR)$(exthome): $(DESTDIR)$(home) + exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) + +update: $(DESTDIR)$(exthome) + +global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) + +$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% + exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( + + Please use the mailing-list for +questions about shibari. diff --git a/README.macos b/README.macos new file mode 100644 index 0000000..64e0742 --- /dev/null +++ b/README.macos @@ -0,0 +1,3 @@ + This package will compile and run on Darwin (MacOS X), but the building of +shared libraries is not supported. + Make sure you use the --disable-shared option to configure. diff --git a/README.solaris b/README.solaris new file mode 100644 index 0000000..0450a37 --- /dev/null +++ b/README.solaris @@ -0,0 +1,11 @@ + This package assumes the existence of a POSIX shell in /bin/sh. + On Solaris, /bin/sh is not POSIX. Most versions of Solaris provide +a POSIX shell in /usr/xpg4/bin/sh. + + To compile this package on Solaris, you will need to run + + ./patch-for-solaris + + before you run ./configure. This script will change the #! invocation +of the configure script and various tools so that a POSIX shell is used +for the compilation process. diff --git a/configure b/configure new file mode 100755 index 0000000..efee0c9 --- /dev/null +++ b/configure @@ -0,0 +1,459 @@ +#!/bin/sh + +cd `dirname "$0"` +. package/info + +usage () { +cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } +$1 +EOF + echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" +} + +fail () { + echo "$*" + exit 1 +} + +fnmatch () { + eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" +} + +cmdexists () { + type "$1" >/dev/null 2>&1 +} + +trycc () { + test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO="$*" +} + +stripdir () { + while eval "fnmatch '*/' \"\${$1}\"" ; do + eval "$1=\${$1%/}" + done +} + +tryflag () { + echo "Checking whether compiler accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST "$2" -c -o "$tmpo" "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + +tryldflag () { + echo "Checking whether linker accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CFLAGS_AUTO $CFLAGS $CFLAGS_POST $LDFLAGS_AUTO $LDFLAGS $LDFLAGS_POST -nostdlib "$2" -o "$tmpe" "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + + +# Actual script + +CC_AUTO= +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" +CPPFLAGS_POST="$CPPFLAGS" +CPPFLAGS= +CFLAGS_AUTO="-pipe -Wall" +CFLAGS_POST="$CFLAGS" +CFLAGS=-O2 +LDFLAGS_AUTO= +LDFLAGS_POST="$LDFLAGS" +LDFLAGS= +LDFLAGS_NOSHARED= +LDFLAGS_SHARED=-shared +prefix=/usr +exec_prefix='$prefix' +dynlibdir='$prefix/lib' +libexecdir='$exec_prefix/libexec' +bindir='$exec_prefix/bin' +libdir='$prefix/lib/$package' +includedir='$prefix/include' +sysdeps='$prefix/lib/skalibs/sysdeps' +manualsysdeps=false +shared=false +static=true +allpic=true +slashpackage=false +abspath=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= + +for arg ; do + case "$arg" in + --help) usage ;; + --prefix=*) prefix=${arg#*=} ;; + --exec-prefix=*) exec_prefix=${arg#*=} ;; + --dynlibdir=*) dynlibdir=${arg#*=} ;; + --libexecdir=*) libexecdir=${arg#*=} ;; + --bindir=*) bindir=${arg#*=} ;; + --libdir=*) libdir=${arg#*=} ;; + --includedir=*) includedir=${arg#*=} ;; + --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; + --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;; + --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;; + --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; + --enable-shared|--enable-shared=yes) shared=true ;; + --disable-shared|--enable-shared=no) shared=false ;; + --enable-static|--enable-static=yes) static=true ;; + --disable-static|--enable-static=no) static=false ;; + --enable-allstatic|--enable-allstatic=yes) allstatic=true ;; + --disable-allstatic|--enable-allstatic=no) allstatic=false ; evenmorestatic=false ;; + --enable-static-libc|--enable-static-libc=yes) allstatic=true ; evenmorestatic=true ;; + --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; + --enable-all-pic|--enable-all-pic=yes) allpic=true ;; + --disable-all-pic|--enable-all-pic=no) allpic=false ;; + --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; + --enable-slashpackage) sproot= ; slashpackage=true ;; + --disable-slashpackage) sproot= ; slashpackage=false ;; + --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; + --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + --build=*) build=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) eval "${arg%%=*}=\${arg#*=}" ;; + *) target=$arg ;; + esac +done + +# Expand installation directories +stripdir prefix +for i in exec_prefix dynlibdir libexecdir bindir libdir includedir sysdeps sproot ; do + eval tmp=\${$i} + eval $i=$tmp + stripdir $i +done + +# Get usable temp filenames +i=0 +set -C +while : ; do + i=$(($i+1)) + tmpc="./tmp-configure-$$-$PPID-$i.c" + tmpo="./tmp-configure-$$-$PPID-$i.o" + tmpe="./tmp-configure-$$-$PPID-$i.tmp" + 2>|/dev/null > "$tmpc" && break + 2>|/dev/null > "$tmpo" && break + 2>|/dev/null > "$tmpe" && break + test "$i" -gt 50 && fail "$0: cannot create temporary files" +done +set +C +trap 'rm -f "$tmpc" "$tmpo" "$tmpe"' EXIT ABRT INT QUIT TERM HUP + +# Set slashpackage values +if $slashpackage ; then + home=${sproot}/package/${category}/${package}-${version} + exthome=${sproot}/package/${category}/${package} + if $manualsysdeps ; then + : + else + sysdeps=${DESTDIR}${sproot}/package/prog/skalibs/sysdeps + fi + prefix= + extbinprefix=${exthome}/command + dynlibdir=${home}/library.so + bindir=${home}/command + libdir=${home}/library + libexecdir=$bindir + includedir=${home}/include + while read dep condvar ; do + if test -n "$condvar" ; then + eval "cond=$condvar" + else + cond=true + fi + if $cond ; then + addincpath="$addincpath -I${DESTDIR}${sproot}${dep}/include" + vpaths="$vpaths ${DESTDIR}${sproot}${dep}/library" + addlibspath="$addlibspath -L${DESTDIR}${sproot}${dep}/library" + vpathd="$vpathd ${DESTDIR}${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${DESTDIR}${sproot}${dep}/library.so" + fi + done < package/deps-build +fi + +# Find a C compiler to use +if test -n "$target" && test x${build} != x${target} ; then + cross=${target}- +else + cross= +fi +echo "Checking for C compiler..." +trycc ${CC} +if test -n "$CC_AUTO" ; then + b=`basename "$CC"` + adjust_cross=false + if test "$b" != "$CC" ; then + adjust_cross=true + echo "$0: warning: compiler $CC is declared with its own path. If it's not accessible via PATH, you will need to pass AR, RANLIB and STRIP make variables to the make invocation." 1>&2 + fi + if test -n "$cross" ; then + if test "$b" = "${b##$cross}" ; then + echo "$0: warning: compiler $CC is declared as a cross-compiler for target $target but does not start with prefix ${cross}" 1>&2 + elif $adjust_cross ; then + cross=`dirname "$CC"`/"$cross" + fi + fi +fi +trycc ${cross}gcc +trycc ${cross}clang +trycc ${cross}cc +test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } +echo " ... $CC_AUTO" +echo "Checking whether C compiler works... " +echo "typedef int x;" > "$tmpc" +if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -c -o "$tmpo" "$tmpc" 2>"$tmpe" ; then + echo " ... yes" +else + echo " ... no. Compiler output follows:" + cat < "$tmpe" + exit 1 +fi + +echo "Checking target system type..." +if test -z "$target" ; then + if test -n "$build" ; then + target=$build ; + else + target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown + fi +fi +echo " ... $target" +if test ! -d $sysdeps || test ! -f $sysdeps/target ; then + echo "$0: error: $sysdeps is not a valid sysdeps directory" + exit 1 +fi +if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then + echo "$0: error: target $target does not match the contents of $sysdeps/target" + exit 1 +fi + +spawn_lib=$(cat $sysdeps/spawn.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +timer_lib=$(cat $sysdeps/timer.lib) +util_lib=$(cat $sysdeps/util.lib) + +if $allpic ; then + tryflag CPPFLAGS_AUTO -fPIC +fi +tryflag CFLAGS_AUTO -std=c99 +tryflag CFLAGS -fomit-frame-pointer +tryflag CFLAGS_AUTO -fno-exceptions +tryflag CFLAGS_AUTO -fno-unwind-tables +tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables +tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration +tryflag CPPFLAGS_AUTO -Werror=implicit-int +tryflag CPPFLAGS_AUTO -Werror=pointer-sign +tryflag CPPFLAGS_AUTO -Werror=pointer-arith +tryflag CFLAGS_AUTO -ffunction-sections +tryflag CFLAGS_AUTO -fdata-sections + +tryldflag LDFLAGS_AUTO -Wl,--sort-section=alignment +tryldflag LDFLAGS_AUTO -Wl,--sort-common + +CPPFLAGS_AUTO="${CPPFLAGS_AUTO}${addincpath}" + +if $evenmorestatic ; then + LDFLAGS_NOSHARED=-static +fi + +if $shared ; then + tryldflag LDFLAGS -Wl,--hash-style=both +fi + +LDFLAGS_SHARED="${LDFLAGS_SHARED}${addlibdpath}" + +if test -z "$vpaths" ; then + while read dep ; do + base=$(basename $dep) ; + vpaths="$vpaths /usr/lib/$base" + addlibspath="$addlibspath -L/usr/lib/$base" + done < package/deps-build +fi + +if $allstatic ; then + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" + tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections +else + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" +fi + +echo "Creating config.mak..." +cmdline=$(quote "$0") +for i ; do cmdline="$cmdline $(quote "$i")" ; done +exec 3>&1 1>config.mak +cat << EOF +# This file was generated by: +# $cmdline +# Any changes made here will be lost if configure is re-run. + +target := $target +package := $package +prefix := $prefix +exec_prefix := $exec_prefix +dynlibdir := $dynlibdir +libexecdir := $libexecdir +bindir := $bindir +libdir := $libdir +includedir := $includedir +sysdeps := $sysdeps +slashpackage := $slashpackage +sproot := $sproot +version := $version +home := $home +exthome := $exthome +SPAWN_LIB := ${spawn_lib} +SOCKET_LIB := ${socket_lib} +SYSCLOCK_LIB := ${sysclock_lib} +TIMER_LIB := ${timer_lib} +UTIL_LIB := ${util_lib} + +CC := $CC_AUTO +CPPFLAGS_AUTO := $CPPFLAGS_AUTO +CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST +CFLAGS_AUTO := $CFLAGS_AUTO +CFLAGS := $CFLAGS $CFLAGS_POST +LDFLAGS_AUTO := $LDFLAGS_AUTO +LDFLAGS := $LDFLAGS $LDFLAGS_POST +LDFLAGS_SHARED := $LDFLAGS_SHARED +LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED +CROSS_COMPILE := $cross + +vpath lib%.a$vpaths +vpath lib%.so$vpathd +EOF +if $allstatic ; then + echo ".LIBPATTERNS := lib%.a" + echo "DO_ALLSTATIC := 1" +else + echo ".LIBPATTERNS := lib%.so" +fi +if $static ; then + echo "DO_STATIC := 1" +else + echo "DO_STATIC :=" +fi +if $shared ; then + echo "DO_SHARED := 1" +else + echo "DO_SHARED :=" +fi +if $allpic ; then + echo "STATIC_LIBS_ARE_PIC := 1" +else + echo "STATIC_LIBS_ARE_PIC :=" +fi + +exec 1>&3 3>&- +echo " ... done." + +echo "Creating src/include/${package}/config.h..." +mkdir -p -m 0755 src/include/${package} +exec 3>&1 1> src/include/${package}/config.h +cat <&3 3>&- +echo " ... done." diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..fd59558 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,181 @@ + + + + + + shibari - a collection of DNS tools + + + + + + +

+Software
+skarnet.org +

+ +

shibari

+ +

What is it ?

+ +

+ shibari is a collection of DNS tools for Unix systems, as an +alternative to BIND, Unbound, djbdns or other similar suites of +programs. +

+ +

+ It was previously named s6-dns. The name of the project was changed to +avoid confusion; despite being written by the same author and with the +same mindset, it is not part of the s6 project. +

+ +

Why "shibari"?

+ +

+ There's a de facto tradition that DNS software has a name related to +binding. shibari aims to be the most pleasant of all DNS software. +

+ +
+ +

Installation

+ +

Requirements

+ +
    +
  • A POSIX-compliant system with a standard C development environment
  • +
  • GNU make, version 3.81 or later
  • +
  • skalibs version +2.14.0.1 or later. It's a build-time requirement. It's also a run-time +requirement if you link against the shared version of the skalibs library.
  • +
  • s6 version +2.12.0.2 or later. It's a build-time requirement. It's also a run-time +requirement if you link against the shared version of the s6 library. That +library is used for the access control and client location features in +shibari-server-udp.
  • +
  • (for now) s6-dns version +2.3.7.0 or later. It's a build-time requirement. It's also a run-time +requirement if you link against the shared version of the s6-dns library.
  • +
+ +

Licensing

+ +

+ shibari is free software. It is available under the +ISC license. +

+ +

Download

+ +
    +
  • The current released version of shibari is 0.0.1.0. +(That is a lie. shibari is currently unreleased, so that link does not work.)
  • +
  • You can checkout a copy of the +shibari +git repository: +
     git clone git://git.skarnet.org/shibari 
  • +
  • There's also a +GitHub mirror +of the shibari git repository.
  • +
+ +

Build and installation

+ +
    +
  • See the enclosed INSTALL file for build and installation details.
  • +
+ +

Upgrade notes

+ +
    +
  • This page lists the differences to be aware of between +the previous versions of shibari and the current one.
  • +
+ +
+ +

Reference

+ +

Commands

+ +

+ All these commands exit 111 if they encounter a temporary error or +hardware error, and +100 if they encounter a permanent error - such as a misuse. Short-lived +commands exit 0 on success. Other exit codes are documented in the +relevant page. +

+ +

Command-line DNS clients programs

+ +
    +
+ +

Caches

+ +
    +
+ +

Servers

+ + + +

Filtering tools

+ +
    +
+ +

Command-line qualification

+ +
    +
+ +

DNS analysis and debug tools

+ +
    +
+ +

Miscellaneous utilities

+ +

Libraries

+ +

Protocol implementation and synchronous resolution

+ +
    +
+ +

Asynchronous resolution

+ +
    +
+ +
+ + +

Related resources

+
+ +

shibari discussion

+ + + +

Similar work

+ + + + + diff --git a/doc/shibari-server-tcp.html b/doc/shibari-server-tcp.html new file mode 100644 index 0000000..5f36087 --- /dev/null +++ b/doc/shibari-server-tcp.html @@ -0,0 +1,213 @@ + + + + + + shibari: the shibari-server-tcp program + + + + + + +

+shibari
+Software
+skarnet.org +

+ +

The shibari-server-tcp program

+ +

+ shibari-server-tcp reads DNS queries on its standard input, and answers them +on its standard output. +

+ +
+

Interface

+
+ +
+     shibari-server-tcp [ -v verbosity [ -f tdbfile ] [ -r rtimeout ] [ -w wtimeout ]
+
+ +
    +
  • shibari-server-tcp reads a stream of DNS queries on its stdin (encoded +in the TCP DNS way, i.e. 2 bytes of length then the payload), and tries to fulfill them, +sending answers to stdout. It logs its actions to stderr.
  • +
  • It supports normal queries and AXFR queries.
  • +
  • It reads DNS data information from a +cdb database; the +database must use the output format from +tinydns-data.
  • +
+ +
+

Common usage

+
+ +

+ shibari-server-tcp is intended to be run under a TCP super-server such as +s6-tcpserver. +It delegates to the super-server the job of binding and listening to +the socket, accepting connections, and spawning a separate process to handle a +given connection. +

+ +

+ As such, a command line for shibari-server-tcp, running as user dns, listening +on address ${ip}, would typically look like this: +

+ +
+     s6-envuidgid dns s6-tcpserver -U -- ${ip} 53 s6-tcpserver-access -x rules.cdb -- shibari-server-tcp
+
+ +

+ Most users will want to run these command lines as services, i.e. daemons +run in the background when the machine starts. The examples/ subdirectory +of the shibari package provides service templates to help you run shibari-server-tcp under +OpenRC, +s6 and +s6-rc. +

+ +
+

Exit codes

+
+ +
+
0
Clean exit. There was a successful series of DNS exchanges +and tipideed received EOF, or timed out while the client was idle.
+
1
Invalid DNS query. The client spoke garbage.
+
100
Bad usage. shibari-server-tcp was run in an incorrect way: bad command +line options, or missing environment variables, etc.
+
101
Cannot happen. This signals a bug in shibari-server-tcp, and comes with an +error message asking you to report the bug. Please do so, on the +skaware mailing-list.
+
102
Misconfiguration. shibari-server-tcp found something in its DNS data file +that it does not like.
+
111
System call failed. This usually signals an issue with the +underlying operating system.
+
+ +
+

Environment variables

+
+ +

+ shibari-server-tcp expects the following variables in its environment, and will exit +with an error message if they are undefined. When run under +s6-tcpserver, +these variables are automatically set by the super-server. This is the way +shibari-server-tcp gets its network information without having to perform network +operations itself. +

+ +
+
TCPLOCALIP
+
The local IP address that the super-server is listening on.
+ +
TCPLOCALPORT
+
The local port that the super-server is listening on. In normal usage +this will be 53.
+ +
TCPREMOTEIP
+
The IP address of the client.
+ +
TCPREMOTEPORT
+
The remote port that the client is connecting from.
+
+ +

+ The following variables are optional, but will inform shibari-server-tcp's +behaviour. They are typically set by +s6-tcpserver-access +with the -i or -x option, when the access rules database +defines environment variables depending on client IP ranges. +

+ +
+
AXFR
+
If this variable is set, it controls what zones the client is allowed +to make AXFR queries for. A value of * (star) means the client is +allowed to make AXFR queries for any zone, same as when the variable is not +defined. Else, the value needs to be a space-, comma-, semicolon-, or +slash-separated list of zones; these are the allowed zones.
+ +
LOC
+
If this variable is set, it defines a client location that is used to +implement views. A client location is at most two charaters; if the value +is lo, then the client will be granted access to DNS data guarded +by a %lo location indicator in the +tinydns-data file. +Note that shibari-server-tcp ignores client IP prefix matching compiled in +the database via %lo:ipprefix lines: it only takes its location +information from the LOC variable, and will use the contents of LOC to match +lines ending with :%lo. The idea is to only have one place centralizing +what clients are authorized to do depending on their IP, and that place is the +s6-tcpserver-access +rules database.
+
+ +
+

Options

+
+ +
+
-v verbosity
+
Be more or less verbose. +A verbosity of 0 means no warnings, no logs, only error messages. 1 +means warnings and terse logs. 2 or more means more logs. +Default is 1.
+ +
-f tdbfile
+
Read DNS data from tdbfile. +The default is data.cdb, in the current working +directory of the shibari-server-tcp process.
+ +
-r rtimeout
+
Read timeout. If rtimeout milliseconds +elapse while shibari-server-tcp is waiting for a DNS query, just exit. +The default is 0, meaning infinite: shibari-server-tcp +will never close the connection until it receives EOF.
+ +
-w wtimeout
+
Write timeout. If shibari-server-tcp is unable +to send its answer in wtimeout milliseconds, which means the network is +congested, give up and close the connection. The default is 0, which +means infinite: shibari-server-tcp will wait forever until the network decongests in +order to send its answer.
+
+ +
+

Notes

+
+ +
    +
  • The DNS database can be changed at any time via an invocation of +tinydns-data. +shibari-server-tcp will keep using the old data until its current stream +ends and it exits. The next instance of shibari-server-tcp, +spawned by the super-server, will use the new data.
  • +
  • shibari-server-tcp is a drop-in replacement for +axfrdns, with one +caveat: client location information needs to be migrated from the DNS +database to LOC definitions in the TCP access rules database. For instance, +if you have a %lo:1.2.3 line in your text data file, you need to +add the following entries to your TCP access rules database: +
      +
    • ip4/1.2.3.0_24/allow (may be empty)
    • +
    • ip4/1.2.3.0_24/env/LOC containing lo
    • +
  • +
  • If you are using such an access rules database via a +s6-tcpserver-access +invocation, make sure your +shibari-server-udp service is using the +same database via the -i or -x option. You +don't want to give different permissions, or different location information, +depending on whether a query is made over TCP or UDP.
  • +
+ + + diff --git a/doc/shibari-server-udp.html b/doc/shibari-server-udp.html new file mode 100644 index 0000000..c8e46f8 --- /dev/null +++ b/doc/shibari-server-udp.html @@ -0,0 +1,163 @@ + + + + + + shibari: the shibari-server-udp program + + + + + + +

+shibari
+Software
+skarnet.org +

+ +

The shibari-server-udp program

+ +

+ shibari-server-udp is a long-lived process. It binds to a UDP socket, then +answers DNS queries it receives, until it is killed. +

+ +
+

Interface

+
+ +
+     shibari-server-udp [ -v verbosity ] [ -d notif ] [ -f tdbfile ] [ -i rulesdir ] [ -x rulesfile ] [ -p port ] ip
+
+ +
    +
  • shibari-server-udp creates a UDP socket and binds it to address ip +on port 53. ip can be IPv4 or IPv6.
  • +
  • It listens to non-recursive DNS queries, sent by DNS caches, and, if +appropriate, answers with data it reads from its data file.
  • +
  • It reloads its data file on SIGHUP, and exits 0 on SIGTERM.
  • +
  • The data file is a +cdb database; it +must use the output format from +tinydns-data.
  • +
+ +
+

Exit codes

+
+ +
+
0
Clean exit. shibari-server-udp received a SIGTERM and exited.
+
100
Bad usage. shibari-server-udp was run in an incorrect way: +typically bad command line options.
+
101
Cannot happen. This signals a bug in shibari-server-udp, and comes with an +error message asking you to report the bug. Please do so, on the +skaware mailing-list.
+
102
Misconfiguration. shibari-server-udp found something in its DNS data file +that it does not like.
+
111
System call failed. This usually signals an issue with the +underlying operating system.
+
+ +
+

Options

+
+ +
+
-v verbosity
+
Be more or less verbose. +A verbosity of 0 means no warnings, no logs, only error messages. 1 +means warnings and terse logs. 2 or more means more logs. +Default is 1.
+ +
-d notif
+
Write a newline to file descriptor notif, then close it, when +shibari-server-udp has bound its socket, opened its file, and is ready to serve. +This is the s6 +readiness notification mechanism. By default, when this option isn't given +no readiness notification is sent.
+ +
-f tdbfile
+
Read DNS data from tdbfile. +The default is data.cdb, in the current working +directory of the shibari-server-udp process.
+ +
-i rulesdir
+
Use rulesdir as a filesystem-based +access rules +database: ignore any message whose originating IP address isn't +explicitly allowed. The access rules database is also used to get +client location information. +If something in rulesdir changes while shibari-server-udp is +running, it will immediately pick up the change.
+ +
-x rulesfile
+
Use rulesfile as a cdb +access rules +database, see description of -i above. -i and +-x are equivalent; you can switch between rulesdir +and rulesfile via the +s6-accessrules-cdb-from-fs and +s6-accessrules-fs-from-cdb +programs. The cdb format is more efficient but more static than the +filesystem format. If rulesfile changes while shibari-server-udp +is running, it will continue to use the old data until it receives a SIGHUP.
+ +
-p port
+
Binds to port port. Default is 53.
+
+ +
+

Client location

+
+ +

+ shibari-server-udp ignores client location information given as +%lo:ipprefix lines in the file created by +tinydns-data. +Instead, it reads client location information in LOC definitions +present in the rulesdir or rulesfile +access rules database. For instance, +if you have a %lo:1.2.3 line in your text data file, meaning +that clients whose IP address is in the 1.2.3.0/24 IPv4 +range are identified with the lo location and that DNS data +entries ending with :lo are visible to them, you need to +translate this information into the accessrules format. Your +rulesdir must contain the following files: +

+ +
    +
  • ip4/1.2.3.0_24/allow (may be empty)
  • +
  • ip4/1.2.3.0_24/env/LOC containing lo
  • +
+ +

+ (To use the -x option instead, you'd do the same, then run +s6-accessrules-cdb-from-fs rulesfile rulesdir +to compile the information into rulesfile.) +

+ +
+

Notes

+
+ +
    +
  • The DNS database can be changed at any time via an invocation of +tinydns-data. +shibari-server-udp will keep using the old data until it receives a +SIGHUP, at which point it will reopen its database.
  • +
  • shibari-server-udp is a drop-in replacement for +tinydns, with the +caveat of the client location mechanism.
  • +
  • If you are using the -i or -x option, the +access rules database can, and should, be the same one that is used by the +s6-tcpserver-access +program in your +shibari-server-tcp service. You +don't want to give different permissions, or different location information, +depending on whether a query is made over TCP or UDP.
  • +
+ + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..52eeaa5 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ + + + + + + shibari: how to upgrade + + + + + + +

+shibari
+Software
+skarnet.org +

+ +

What has changed in shibari

+ +

in 0.0.1.0

+ +
    +
  • Initial release.
  • +
+ + + diff --git a/package/deps-build b/package/deps-build new file mode 100644 index 0000000..e2af791 --- /dev/null +++ b/package/deps-build @@ -0,0 +1,3 @@ +/package/prog/skalibs +/package/admin/s6 +/package/web/s6-dns diff --git a/package/deps.mak b/package/deps.mak new file mode 100644 index 0000000..5fbe083 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,66 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/include/shibari/cache.h: src/include/shibari/dcache.h +src/include/shibari/common.h: src/include/shibari/constants.h src/include/shibari/util.h +src/include/shibari/packet.h: src/include/shibari/tdb.h +src/include/shibari/server.h: src/include/shibari/log.h src/include/shibari/packet.h src/include/shibari/tdb.h +src/include/shibari/shibari.h: src/include/shibari/cache.h src/include/shibari/client.h src/include/shibari/common.h src/include/shibari/server.h +src/cache/dcache-internal.h: src/include/shibari/dcache.h +src/cache/dcache_add.o src/cache/dcache_add.lo: src/cache/dcache_add.c src/cache/dcache-internal.h src/include/shibari/dcache.h +src/cache/dcache_clean_expired.o src/cache/dcache_clean_expired.lo: src/cache/dcache_clean_expired.c src/cache/dcache-internal.h src/include/shibari/dcache.h +src/cache/dcache_delete.o src/cache/dcache_delete.lo: src/cache/dcache_delete.c src/cache/dcache-internal.h src/include/shibari/dcache.h +src/cache/dcache_free.o src/cache/dcache_free.lo: src/cache/dcache_free.c src/include/shibari/dcache.h +src/cache/dcache_init.o src/cache/dcache_init.lo: src/cache/dcache_init.c src/include/shibari/dcache.h +src/cache/dcache_load.o src/cache/dcache_load.lo: src/cache/dcache_load.c src/include/shibari/dcache.h +src/cache/dcache_save.o src/cache/dcache_save.lo: src/cache/dcache_save.c src/include/shibari/dcache.h +src/cache/dcache_search.o src/cache/dcache_search.lo: src/cache/dcache_search.c src/cache/dcache-internal.h src/include/shibari/dcache.h +src/common/shibari_log_answer.o src/common/shibari_log_answer.lo: src/common/shibari_log_answer.c src/include/shibari/log.h src/include/shibari/util.h +src/common/shibari_log_exit.o src/common/shibari_log_exit.lo: src/common/shibari_log_exit.c src/include/shibari/log.h +src/common/shibari_log_query.o src/common/shibari_log_query.lo: src/common/shibari_log_query.c src/include/shibari/log.h src/include/shibari/util.h +src/common/shibari_log_queryplus.o src/common/shibari_log_queryplus.lo: src/common/shibari_log_queryplus.c src/include/shibari/log.h src/include/shibari/util.h +src/common/shibari_log_start.o src/common/shibari_log_start.lo: src/common/shibari_log_start.c src/include/shibari/log.h +src/common/shibari_util_get_prefixlen.o src/common/shibari_util_get_prefixlen.lo: src/common/shibari_util_get_prefixlen.c src/include/shibari/util.h +src/common/shibari_util_qtype_num.o src/common/shibari_util_qtype_num.lo: src/common/shibari_util_qtype_num.c src/include/shibari/util.h +src/common/shibari_util_qtype_str.o src/common/shibari_util_qtype_str.lo: src/common/shibari_util_qtype_str.c src/include/shibari/util.h +src/common/shibari_util_rcode_str.o src/common/shibari_util_rcode_str.lo: src/common/shibari_util_rcode_str.c src/include/shibari/util.h +src/server/shibari-server-tcp.o src/server/shibari-server-tcp.lo: src/server/shibari-server-tcp.c src/include/shibari/common.h src/include/shibari/server.h +src/server/shibari-server-udp.o src/server/shibari-server-udp.lo: src/server/shibari-server-udp.c src/include/shibari/common.h src/include/shibari/server.h +src/server/shibari_packet_add_glue.o src/server/shibari_packet_add_glue.lo: src/server/shibari_packet_add_glue.c src/include/shibari/constants.h src/include/shibari/packet.h src/include/shibari/tdb.h src/include/shibari/util.h +src/server/shibari_packet_add_rr.o src/server/shibari_packet_add_rr.lo: src/server/shibari_packet_add_rr.c src/include/shibari/constants.h src/include/shibari/packet.h +src/server/shibari_packet_assert_authority.o src/server/shibari_packet_assert_authority.lo: src/server/shibari_packet_assert_authority.c src/include/shibari/constants.h src/include/shibari/packet.h src/include/shibari/tdb.h src/include/shibari/util.h +src/server/shibari_packet_begin.o src/server/shibari_packet_begin.lo: src/server/shibari_packet_begin.c src/include/shibari/constants.h src/include/shibari/packet.h +src/server/shibari_packet_end.o src/server/shibari_packet_end.lo: src/server/shibari_packet_end.c src/include/shibari/packet.h +src/server/shibari_packet_init.o src/server/shibari_packet_init.lo: src/server/shibari_packet_init.c src/include/shibari/packet.h +src/server/shibari_packet_tdb_answer_query.o src/server/shibari_packet_tdb_answer_query.lo: src/server/shibari_packet_tdb_answer_query.c src/include/shibari/constants.h src/include/shibari/packet.h src/include/shibari/tdb.h +src/server/shibari_tdb_entry_parse.o src/server/shibari_tdb_entry_parse.lo: src/server/shibari_tdb_entry_parse.c src/include/shibari/constants.h src/include/shibari/tdb.h +src/server/shibari_tdb_extract_domain.o src/server/shibari_tdb_extract_domain.lo: src/server/shibari_tdb_extract_domain.c src/include/shibari/constants.h src/include/shibari/tdb.h +src/server/shibari_tdb_find_authority.o src/server/shibari_tdb_find_authority.lo: src/server/shibari_tdb_find_authority.c src/include/shibari/constants.h src/include/shibari/tdb.h +src/server/shibari_tdb_read_entry.o src/server/shibari_tdb_read_entry.lo: src/server/shibari_tdb_read_entry.c src/include/shibari/tdb.h + +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +libdcache.a.xyzzy: src/cache/dcache_add.o src/cache/dcache_clean_expired.o src/cache/dcache_delete.o src/cache/dcache_free.o src/cache/dcache_init.o src/cache/dcache_load.o src/cache/dcache_save.o src/cache/dcache_search.o +else +libdcache.a.xyzzy: src/cache/dcache_add.lo src/cache/dcache_clean_expired.lo src/cache/dcache_delete.lo src/cache/dcache_free.lo src/cache/dcache_init.lo src/cache/dcache_load.lo src/cache/dcache_save.lo src/cache/dcache_search.lo +endif +libdcache.so.xyzzy: EXTRA_LIBS := +libdcache.so.xyzzy: src/cache/dcache_add.lo src/cache/dcache_clean_expired.lo src/cache/dcache_delete.lo src/cache/dcache_free.lo src/cache/dcache_init.lo src/cache/dcache_load.lo src/cache/dcache_save.lo src/cache/dcache_search.lo +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +libshibari-common.a.xyzzy: src/common/shibari_log_answer.o src/common/shibari_log_exit.o src/common/shibari_log_query.o src/common/shibari_log_queryplus.o src/common/shibari_log_start.o src/common/shibari_util_qtype_num.o src/common/shibari_util_qtype_str.o src/common/shibari_util_rcode_str.o src/common/shibari_util_get_prefixlen.o +else +libshibari-common.a.xyzzy: src/common/shibari_log_answer.lo src/common/shibari_log_exit.lo src/common/shibari_log_query.lo src/common/shibari_log_queryplus.lo src/common/shibari_log_start.lo src/common/shibari_util_qtype_num.lo src/common/shibari_util_qtype_str.lo src/common/shibari_util_rcode_str.lo src/common/shibari_util_get_prefixlen.lo +endif +libshibari-common.so.xyzzy: EXTRA_LIBS := -lskarnet +libshibari-common.so.xyzzy: src/common/shibari_log_answer.lo src/common/shibari_log_exit.lo src/common/shibari_log_query.lo src/common/shibari_log_queryplus.lo src/common/shibari_log_start.lo src/common/shibari_util_qtype_num.lo src/common/shibari_util_qtype_str.lo src/common/shibari_util_rcode_str.lo src/common/shibari_util_get_prefixlen.lo +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +libshibari-server.a.xyzzy: src/server/shibari_packet_init.o src/server/shibari_packet_begin.o src/server/shibari_packet_end.o src/server/shibari_packet_add_rr.o src/server/shibari_tdb_entry_parse.o src/server/shibari_tdb_extract_domain.o src/server/shibari_tdb_find_authority.o src/server/shibari_tdb_read_entry.o src/server/shibari_packet_add_glue.o src/server/shibari_packet_assert_authority.o src/server/shibari_packet_tdb_answer_query.o +else +libshibari-server.a.xyzzy: src/server/shibari_packet_init.lo src/server/shibari_packet_begin.lo src/server/shibari_packet_end.lo src/server/shibari_packet_add_rr.lo src/server/shibari_tdb_entry_parse.lo src/server/shibari_tdb_extract_domain.lo src/server/shibari_tdb_find_authority.lo src/server/shibari_tdb_read_entry.lo src/server/shibari_packet_add_glue.lo src/server/shibari_packet_assert_authority.lo src/server/shibari_packet_tdb_answer_query.lo +endif +libshibari-server.so.xyzzy: EXTRA_LIBS := -ls6dns -lskarnet +libshibari-server.so.xyzzy: src/server/shibari_packet_init.lo src/server/shibari_packet_begin.lo src/server/shibari_packet_end.lo src/server/shibari_packet_add_rr.lo src/server/shibari_tdb_entry_parse.lo src/server/shibari_tdb_extract_domain.lo src/server/shibari_tdb_find_authority.lo src/server/shibari_tdb_read_entry.lo src/server/shibari_packet_add_glue.lo src/server/shibari_packet_assert_authority.lo src/server/shibari_packet_tdb_answer_query.lo +shibari-server-tcp: EXTRA_LIBS := -ls6dns -lskarnet +shibari-server-tcp: src/server/shibari-server-tcp.o ${LIBSHIBARI_SERVER} ${LIBSHIBARI_COMMON} +shibari-server-udp: EXTRA_LIBS := -ls6dns -ls6 -lskarnet ${SOCKET_LIB} +shibari-server-udp: src/server/shibari-server-udp.o ${LIBSHIBARI_SERVER} ${LIBSHIBARI_COMMON} diff --git a/package/info b/package/info new file mode 100644 index 0000000..d1c92dc --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=shibari +version=0.0.1.0 +category=web +package_macro_name=SHIBARI diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..94bdf3e --- /dev/null +++ b/package/modes @@ -0,0 +1,2 @@ +shibari-server-tcp 0755 +shibari-server-udp 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..0f2d479 --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,7 @@ +BIN_TARGETS := \ +shibari-server-tcp \ +shibari-server-udp + +LIBEXEC_TARGETS := + +LIB_DEFS := SHIBARI_SERVER=shibari-server SHIBARI_COMMON=shibari-common DCACHE=dcache diff --git a/patch-for-solaris b/patch-for-solaris new file mode 100755 index 0000000..2d1296b --- /dev/null +++ b/patch-for-solaris @@ -0,0 +1,21 @@ +#!/usr/xpg4/bin/sh + +patchit () { + echo '#!/usr/xpg4/bin/sh' > $1.tmp + tail -n +2 $1 >> $1.tmp + mv -f $1.tmp $1 + chmod 755 $1 +} + +# Solaris doesn't understand POSIX.1-2008 either. +sed -e 's/XOPEN_SOURCE=700/XOPEN_SOURCE=600/' < configure > configure.tmp +mv -f configure.tmp configure + +patchit ./configure +patchit ./tools/install.sh +patchit ./tools/gen-deps.sh + +echo 'SHELL := /usr/xpg4/bin/sh' > Makefile.tmp +echo >> Makefile.tmp +cat Makefile >> Makefile.tmp +mv -f Makefile.tmp Makefile diff --git a/src/cache/dcache-internal.h b/src/cache/dcache-internal.h new file mode 100644 index 0000000..2a2e36f --- /dev/null +++ b/src/cache/dcache-internal.h @@ -0,0 +1,18 @@ +/* ISC license. */ + +#ifndef SHIBARI_DCACHE_INTERNAL_H +#define SHIBARI_DCACHE_INTERNAL_H + +#include + +#include +#include + +#include + +#define DNODE(z, i) GENSETDYN_P(dcache_node_t, &(z)->storage, i) +#define DCACHE_NODE_OVERHEAD (32 + sizeof(dcache_node_t) + 3 * sizeof(avlnode)) + +extern void dcache_delete (dcache_t *, uint32_t) ; + +#endif diff --git a/src/cache/dcache_add.c b/src/cache/dcache_add.c new file mode 100644 index 0000000..7260726 --- /dev/null +++ b/src/cache/dcache_add.c @@ -0,0 +1,85 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "dcache-internal.h" + +static void uniquify (avltree const *tree, tain *stamp) +{ + static tain const nano = { .sec = TAI_ZERO, .nano = 1 } ; + uint32_t dummy ; + while (avltree_search(tree, stamp, &dummy)) + tain_add(stamp, stamp, &nano) ; +} + +static inline void dcache_gc_by_entry (dcache_t *z, uint64_t max) +{ + while (z->size > max) + { + uint32_t oldest ; + if (!avltree_min(&z->by_entry, &oldest)) break ; + dcache_delete(z, oldest) ; + } +} + +static inline int dcache_add_node (dcache_t *z, dcache_node_t const *node) +{ + uint32_t i ; + dcache_node_t *y ; + if (!gensetdyn_new(&z->storage, &i)) return 0 ; + y = DNODE(z, i) ; *y = *node ; + uniquify(&z->by_entry, &y->entry) ; + uniquify(&z->by_expire, &y->expire) ; + if (!avltree_insert(&z->by_key, i)) goto err1 ; + if (!avltree_insert(&z->by_entry, i)) goto err2 ; + if (!avltree_insert(&z->by_expire, i)) goto err3 ; + return 1 ; + + err3: + avltree_delete(&z->by_entry, &y->entry) ; + err2: + avltree_delete(&z->by_key, &y->key) ; + err1: + gensetdyn_delete(&z->storage, i) ; + return 0 ; +} + +static inline int dcache_add_unbounded (dcache_t *z, char const *key, uint16_t keylen, char const *data, uint16_t datalen, tain const *expire, tain const *stamp) +{ + uint32_t len = (uint32_t)keylen + (uint32_t)datalen ; + dcache_node_t y = { .key = { .s = alloc(len) } } ; + if (!y.key.s) return 0 ; + memcpy(y.key.s, key, keylen) ; + memcpy(y.key.s + keylen, data, datalen) ; + y.key.len = keylen ; + y.datalen = datalen ; + y.entry = *stamp ; + y.expire = *expire ; + if (!dcache_add_node(z, &y)) + { + alloc_free(y.key.s) ; + return 0 ; + } + z->size += DCACHE_NODE_OVERHEAD + len ; + z->motion += DCACHE_NODE_OVERHEAD + len ; + return 1 ; +} + +int dcache_add (dcache_t *z, uint64_t max, char const *key, uint16_t keylen, char const *data, uint16_t datalen, tain const *expire, tain const *stamp) +{ + uint64_t size = DCACHE_NODE_OVERHEAD + keylen + datalen ; + if (size > max) return (errno = EINVAL, 0) ; + if (z->size > max - size) dcache_clean_expired(z, stamp) ; + if (z->size > max - size) dcache_gc_by_entry(z, max - size) ; + return dcache_add_unbounded(z, key, keylen, data, datalen, expire, stamp) ; +} diff --git a/src/cache/dcache_clean_expired.c b/src/cache/dcache_clean_expired.c new file mode 100644 index 0000000..0e23443 --- /dev/null +++ b/src/cache/dcache_clean_expired.c @@ -0,0 +1,20 @@ +/* ISC license. */ + +#include + +#include +#include + +#include +#include "dcache-internal.h" + +void dcache_clean_expired (dcache_t *z, tain const *stamp) +{ + for (;;) + { + uint32_t i ; + if (!avltree_min(&z->by_expire, &i)) break ; + if (tain_less(stamp, &DNODE(z, i)->expire)) break ; + dcache_delete(z, i) ; + } +} diff --git a/src/cache/dcache_delete.c b/src/cache/dcache_delete.c new file mode 100644 index 0000000..92a5fcc --- /dev/null +++ b/src/cache/dcache_delete.c @@ -0,0 +1,19 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include "dcache-internal.h" + +void dcache_delete (dcache_t *z, uint32_t i) +{ + dcache_node_t *y = DNODE(z, i) ; + avltree_delete(&z->by_expire, &y->expire) ; + avltree_delete(&z->by_entry, &y->entry) ; + avltree_delete(&z->by_key, &y->key) ; + alloc_free(y->key.s) ; + z->size -= DCACHE_NODE_OVERHEAD + y->key.len + y->datalen ; + gensetdyn_delete(&z->storage, i) ; +} diff --git a/src/cache/dcache_free.c b/src/cache/dcache_free.c new file mode 100644 index 0000000..16c074e --- /dev/null +++ b/src/cache/dcache_free.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include +#include + +#include + +static void dcache_node_free (void *p) +{ + alloc_free(((dcache_node_t *)p)->key.s) ; +} + +void dcache_free (dcache_t *z) +{ + static dcache_t const dcache_zero = DCACHE_ZERO ; + avltree_free(&z->by_expire) ; + avltree_free(&z->by_entry) ; + avltree_free(&z->by_key) ; + gensetdyn_deepfree(&z->storage, &dcache_node_free) ; + *z = dcache_zero ; +} diff --git a/src/cache/dcache_init.c b/src/cache/dcache_init.c new file mode 100644 index 0000000..d42ec62 --- /dev/null +++ b/src/cache/dcache_init.c @@ -0,0 +1,55 @@ +/* ISC license. */ + +#include +#include + +#include +#include +#include +#include + +#include + +static int key_cmp (void const *a, void const *b, void *x) +{ + dcache_key_t const *ka = a ; + dcache_key_t const *kb = b ; + if (ka->len < kb->len) return -1 ; + if (kb->len < ka->len) return 1 ; + (void)x ; + return memcmp(ka->s, kb->s, ka->len) ; +} + +static int tain_cmp (void const *a, void const *b, void *x) +{ + tain const *ta = a ; + tain const *tb = b ; + (void)x ; + return tain_less(ta, tb) ? -1 : tain_less(tb, ta) ; +} + +static void *key_dtok (uint32_t d, void *x) +{ + return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->key ; +} + +static void *entry_dtok (uint32_t d, void *x) +{ + return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->entry ; +} + +static void *expire_dtok (uint32_t d, void *x) +{ + return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->expire ; +} + + +void dcache_init (dcache_t *z, uint64_t max) +{ + gensetdyn_init(&z->storage, sizeof(dcache_node_t), max >> 9, 3, 8) ; + avltree_init(&z->by_key, max >> 9, 3, 8, &key_dtok, &key_cmp, &z->storage) ; + avltree_init(&z->by_entry, max >> 9, 3, 8, &entry_dtok, &tain_cmp, &z->storage) ; + avltree_init(&z->by_expire, max >> 9, 3, 8, &expire_dtok, &tain_cmp, &z->storage) ; + z->size = 0 ; + z->motion = 0 ; +} diff --git a/src/cache/dcache_load.c b/src/cache/dcache_load.c new file mode 100644 index 0000000..a0ff233 --- /dev/null +++ b/src/cache/dcache_load.c @@ -0,0 +1,81 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static inline int dcache_load_node (dcache_t *z, uint64_t max, buffer *b) +{ + tain entry = { .nano = 0 } ; + tain expire = { .nano = 0 } ; + uint16_t keylen ; + uint16_t datalen ; + char pack[TAI_PACK * 2 + 4] ; + ssize_t r = buffer_get(b, pack, TAI_PACK * 2 + 4) ; + if (!r) return 0 ; + if (r < TAI_PACK * 2 + 4) return -1 ; + tai_unpack(pack, tain_secp(&entry)) ; + tai_unpack(pack + TAI_PACK, tain_secp(&expire)) ; + uint16_unpack_big(pack + TAI_PACK * 2, &keylen) ; + uint16_unpack_big(pack + TAI_PACK * 2 + 2, &datalen) ; + { + uint32_t len = (uint32_t)keylen + (uint32_t)datalen ; + char blob[len+1] ; /* 128 kB max, it's ok */ + r = buffer_get(b, blob, len+1) ; + if (!r) return (errno = EPIPE, -1) ; + if (r < len) return -1 ; + if (blob[len]) return (errno = EPROTO, -1) ; + if (!dcache_add(z, max, blob, keylen, blob + keylen, datalen, &expire, &entry)) return -1 ; + } + return 1 ; +} + +static inline int dcache_load_from_buffer (dcache_t *z, uint64_t max, buffer *b) +{ + { + char banner[sizeof(DCACHE_MAGIC) - 1] ; + char pack[8] ; + if (buffer_get(b, banner, sizeof(DCACHE_MAGIC) - 1) < sizeof(DCACHE_MAGIC) - 1) + return 0 ; + if (memcmp(banner, DCACHE_MAGIC, sizeof(DCACHE_MAGIC) - 1)) return 0 ; + if (buffer_get(b, pack, 8) < 8) return 0 ; + uint64_unpack_big(pack, &z->size) ; + if (buffer_get(b, pack, 8) < 8) return 0 ; + uint64_unpack_big(pack, &z->motion) ; + } + for (;;) + { + int r = dcache_load_node(z, max, b) ; + if (r < 0) return 0 ; + if (!r) break ; + } + return 1 ; +} + +#define N 8192 + +int dcache_load (dcache_t *z, uint64_t max, char const *file) +{ + char buf[N] ; + buffer b ; + int fd = open_readb(file) ; + if (fd == -1) return 0 ; + buffer_init(&b, &buffer_read, fd, buf, N) ; + if (!dcache_load_from_buffer(z, max, &b)) goto err ; + fd_close(fd) ; + return 1 ; + + err: + dcache_free(z) ; + fd_close(fd) ; + return 0 ; +} diff --git a/src/cache/dcache_save.c b/src/cache/dcache_save.c new file mode 100644 index 0000000..7277771 --- /dev/null +++ b/src/cache/dcache_save.c @@ -0,0 +1,73 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int write_node_iter (void *data, void *aux) +{ + dcache_node_t *y = data ; + buffer *b = aux ; + char pack[TAI_PACK * 2 + 4] ; + tai_pack(pack, tain_secp(&y->entry)) ; + tai_pack(pack + TAI_PACK, tain_secp(&y->expire)) ; + uint16_pack(pack + TAI_PACK * 2, y->key.len) ; + uint16_pack(pack + TAI_PACK * 2 + 2, y->datalen) ; + if (buffer_put(b, pack, TAI_PACK * 2 + 4) == -1) return 0 ; + if (buffer_put(b, y->key.s, y->key.len + y->datalen) == -1) return 0 ; + if (buffer_put(b, "", 1) == -1) return 0 ; + return 1 ; +} + +static inline int dcache_save_to_buffer (dcache_t const *z, buffer *b) +{ + char pack[16] ; + if (buffer_puts(b, DCACHE_MAGIC) == -1) return 0 ; + uint64_pack_big(pack, z->size) ; + uint64_pack_big(pack + 8, z->motion) ; + if (buffer_put(b, pack, 16) < 16) return 0 ; + + /* XXX: can gensetdyn_iter blow up the stack if z->storage is huge? */ + if (gensetdyn_iter_nocancel((gensetdyn *)&z->storage, gensetdyn_n(&z->storage), &write_node_iter, b) < gensetdyn_n(&z->storage)) return 0 ; + + return buffer_flush(b) ; +} + +#define N 8192 + +int dcache_save (dcache_t const *z, char const *file) +{ + size_t len = strlen(file) ; + int fd ; + buffer b ; + char buf[N] ; + char tmp[len + 20] ; + memcpy(tmp, file, len) ; + memcpy(tmp + len, ":dcache_save:XXXXXX", 20) ; + fd = mkstemp(tmp) ; + if (fd == -1) return 0 ; + buffer_init(&b, &buffer_write, fd, buf, N) ; + if (!dcache_save_to_buffer(z, &b) || fsync(fd) < 0) goto err2 ; + fd_close(fd) ; + if (rename(tmp, file) == -1) goto err1 ; + return 1 ; + + err2: + fd_close(fd) ; + err1: + unlink_void(tmp) ; + return 0 ; +} diff --git a/src/cache/dcache_search.c b/src/cache/dcache_search.c new file mode 100644 index 0000000..0239b88 --- /dev/null +++ b/src/cache/dcache_search.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include + +#include + +#include +#include "dcache-internal.h" + +dcache_node_t *dcache_search (dcache_t *z, char const *key, uint16_t keylen) +{ + uint32_t i ; + dcache_key_t k = { .s = (char *)key, .len = keylen } ; + return avltree_search(&z->by_key, &k, &i) ? DNODE(z, i) : 0 ; +} diff --git a/src/cache/deps-lib/dcache b/src/cache/deps-lib/dcache new file mode 100644 index 0000000..fcc09a0 --- /dev/null +++ b/src/cache/deps-lib/dcache @@ -0,0 +1,8 @@ +dcache_add.o +dcache_clean_expired.o +dcache_delete.o +dcache_free.o +dcache_init.o +dcache_load.o +dcache_save.o +dcache_search.o diff --git a/src/common/deps-lib/shibari-common b/src/common/deps-lib/shibari-common new file mode 100644 index 0000000..a5c44a4 --- /dev/null +++ b/src/common/deps-lib/shibari-common @@ -0,0 +1,10 @@ +shibari_log_answer.o +shibari_log_exit.o +shibari_log_query.o +shibari_log_queryplus.o +shibari_log_start.o +shibari_util_qtype_num.o +shibari_util_qtype_str.o +shibari_util_rcode_str.o +shibari_util_get_prefixlen.o +-lskarnet diff --git a/src/common/shibari_log_answer.c b/src/common/shibari_log_answer.c new file mode 100644 index 0000000..f34cee5 --- /dev/null +++ b/src/common/shibari_log_answer.c @@ -0,0 +1,36 @@ +/* ISC license. */ + +#include +#include + +#include + +#include +#include + +void shibari_log_answer (uint32_t v, s6dns_message_header_t const *hdr, uint16_t len) +{ + if (v < 2) return ; + if (hdr->rcode) + { + char fmtr[UINT16_FMT] ; + fmtr[uint16_fmt(fmtr, hdr->rcode)] = 0 ; + strerr_warni4x("answer ", fmtr, " ", shibari_util_rcode_str(hdr->rcode)) ; + } + else + { + size_t pos = 0 ; + char fmt[UINT16_FMT << 2] ; + char fmtl[UINT16_FMT] ; + pos += uint16_fmt(fmt + pos, hdr->counts.qd) ; + fmt[pos++] = '+' ; + pos += uint16_fmt(fmt + pos, hdr->counts.an) ; + fmt[pos++] = '+' ; + pos += uint16_fmt(fmt + pos, hdr->counts.ns) ; + fmt[pos++] = '+' ; + pos += uint16_fmt(fmt + pos, hdr->counts.qd) ; + fmt[pos] = 0 ; + fmtl[uint16_fmt(fmtl, len)] = 0 ; + strerr_warni5x("answer 0 noerror ", fmt, " len ", fmtl, hdr->tc ? " tc" : "") ; + } +} diff --git a/src/common/shibari_log_exit.c b/src/common/shibari_log_exit.c new file mode 100644 index 0000000..8e383c6 --- /dev/null +++ b/src/common/shibari_log_exit.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include +#include + +#include + +void shibari_log_exit (uint32_t v, int e) +{ + char fmt[UINT_FMT] ; + if (v < 2) return ; + fmt[uint_fmt(fmt, (unsigned int)e)] = 0 ; + strerr_warni2x("exit ", fmt) ; +} diff --git a/src/common/shibari_log_query.c b/src/common/shibari_log_query.c new file mode 100644 index 0000000..b04ee27 --- /dev/null +++ b/src/common/shibari_log_query.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include + +#include + +#include +#include + +void shibari_log_query (uint32_t v, s6dns_domain_t const *q, uint16_t qtype) +{ + char qs[256] ; + s6dns_domain_t qe ; + if (v < 2) return ; + qe = *q ; + if (!s6dns_domain_encode(&qe) || !s6dns_domain_tostring(qs, 256, &qe)) return ; + strerr_warni4x("query ", shibari_util_qtype_str(qtype), " ", qs) ; +} diff --git a/src/common/shibari_log_queryplus.c b/src/common/shibari_log_queryplus.c new file mode 100644 index 0000000..7e7fecc --- /dev/null +++ b/src/common/shibari_log_queryplus.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include +#include +#include + +#include + +#include +#include + +void shibari_log_queryplus (uint32_t v, s6dns_domain_t const *q, uint16_t qtype, ip46 const *ip, uint16_t port) +{ + char qs[256] ; + char fmti[IP46_FMT] ; + char fmtp[UINT16_FMT] ; + s6dns_domain_t qe ; + if (v < 2) return ; + qe = *q ; + if (!s6dns_domain_encode(&qe) || !s6dns_domain_tostring(qs, 256, &qe)) return ; + fmti[ip46_fmt(fmti, ip)] = 0 ; + fmtp[uint16_fmt(fmtp, port)] = 0 ; + strerr_warni8x("query ", shibari_util_qtype_str(qtype), " ", qs, " ip ", fmti, " port ", fmtp) ; +} diff --git a/src/common/shibari_log_start.c b/src/common/shibari_log_start.c new file mode 100644 index 0000000..214dc60 --- /dev/null +++ b/src/common/shibari_log_start.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include +#include +#include + +#include + +void shibari_log_start (uint32_t v, ip46 const *ip, uint16_t port) +{ + char fmti[IP46_FMT] ; + char fmtp[UINT16_FMT] ; + if (v < 2) return ; + fmti[ip46_fmt(fmti, ip)] = 0 ; + fmtp[uint16_fmt(fmtp, port)] = 0 ; + strerr_warni4x("start ip ", fmti, " port ", fmtp) ; +} diff --git a/src/common/shibari_util_get_prefixlen.c b/src/common/shibari_util_get_prefixlen.c new file mode 100644 index 0000000..784a3ee --- /dev/null +++ b/src/common/shibari_util_get_prefixlen.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include +#include + +#include + +int shibari_util_get_prefixlen (char const *name, uint16_t namelen, char const *zone, uint16_t zonelen) +{ + return + namelen < zonelen ? -1 : + memcmp(name + namelen - zonelen, zone, zonelen) ? -1 : + namelen - zonelen ; +} diff --git a/src/common/shibari_util_qtype_num.c b/src/common/shibari_util_qtype_num.c new file mode 100644 index 0000000..350e268 --- /dev/null +++ b/src/common/shibari_util_qtype_num.c @@ -0,0 +1,121 @@ +/* ISC license. */ + +#include +#include +#include + +#include + +struct map_s +{ + char const *s ; + uint16_t num ; +} ; + +static int map_cmp (void const *a, void const *b) +{ + return strcasecmp((char const *)a, ((struct map_s const *)b)->s) ; +} + +#define BSEARCH(key, array) bsearch(key, (array), sizeof(array)/sizeof(struct map_s), sizeof(struct map_s), &map_cmp) + +static struct map_s const qtype_table[] = +{ + { "*", 255 }, + { "A", 1 }, + { "A6", 38 }, + { "AAAA", 28 }, + { "AFSDB", 18 }, + { "AMTRELAY", 260 }, + { "ANY", 255 }, + { "APL", 42 }, + { "ATMA", 34 }, + { "AVC", 258 }, + { "AXFR", 252 }, + { "CAA", 257 }, + { "CDNSKEY", 60 }, + { "CDS", 59 }, + { "CERT", 37 }, + { "CNAME", 5 }, + { "CSYNC", 62 }, + { "DHCID", 49 }, + { "DLV", 32769 }, + { "DNAME", 39 }, + { "DNSKEY", 48 }, + { "DOA", 259 }, + { "DS", 43 }, + { "EID", 31 }, + { "EUI48", 108 }, + { "EUI64", 109 }, + { "GID", 102 }, + { "GPOS", 27 }, + { "HINFO", 13 }, + { "HIP", 55 }, + { "HTTPS", 65 }, + { "IPSECKEY", 45 }, + { "ISDN", 20 }, + { "IXFR", 251 }, + { "KEY", 25 }, + { "KX", 36 }, + { "L32", 105 }, + { "L64", 106 }, + { "LOC", 29 }, + { "LP", 107 }, + { "MAILA", 254 }, + { "MAILB", 253 }, + { "MB", 7 }, + { "MD", 3 }, + { "MF", 4 }, + { "MG", 8 }, + { "MINFO", 14 }, + { "MR", 9 }, + { "MX", 15 }, + { "NAPTR", 35 }, + { "NID", 104 }, + { "NIMLOC", 32 }, + { "NINFO", 56 }, + { "NS", 2 }, + { "NSAP", 22 }, + { "NSAP-PTR", 23 }, + { "NSEC", 47 }, + { "NSEC3", 50 }, + { "NSEC3PARAM", 51 }, + { "NULL", 10 }, + { "NXT", 30 }, + { "OPENPGPKEY", 61 }, + { "OPT", 41 }, + { "PTR", 12 }, + { "PX", 26 }, + { "RESINFO", 261 }, + { "RKEY", 57 }, + { "RP", 17 }, + { "RRSIG", 46 }, + { "RT", 21 }, + { "SIG", 24 }, + { "SINK", 40 }, + { "SMIMEA", 53 }, + { "SOA", 6 }, + { "SPF", 99 }, + { "SRV", 33 }, + { "SSHFP", 44 }, + { "SVCB", 64 }, + { "TA", 32768 }, + { "TALINK", 58 }, + { "TKEY", 249 }, + { "TLSA", 52 }, + { "TSIG", 250 }, + { "TXT", 16 }, + { "UID", 101 }, + { "UINFO", 100 }, + { "UNSPEC", 103 }, + { "URI", 256 }, + { "WKS", 11 }, + { "X25", 19 }, + { "ZONEMD", 63 } +} ; + +uint16_t shibari_util_qtype_num (char const *s) +{ + struct map_s const *p = BSEARCH(s, qtype_table) ; + return p ? p->num : 0 ; +} diff --git a/src/common/shibari_util_qtype_str.c b/src/common/shibari_util_qtype_str.c new file mode 100644 index 0000000..97b701d --- /dev/null +++ b/src/common/shibari_util_qtype_str.c @@ -0,0 +1,285 @@ +/* ISC license. */ + +#include + +#include + +static char const *const qtype_table[262] = +{ + "error", + "A", + "NS", + "MD", + "MF", + "CNAME", + "SOA", + "MB" + "MG", + "MR", + "NULL", + "WKS", + "PTR", + "HINFO", + "MINFO", + "MX", + "TXT", + "RP", + "AFSDB", + "X25", + "ISDN", + "RT", + "NSAP", + "NSAP-PTR", + "SIG", + "KEY", + "PX", + "GPOS", + "AAAA", + "LOC", + "NXT", + "EID", + "NIMLOC", + "SRV", + "ATMA", + "NAPTR", + "KX", + "CERT", + "A6", + "DNAME", + "SINK", + "OPT", + "APL", + "DS", + "SSHFP", + "IPSECKEY", + "RRSIG", + "NSEC", + "DNSKEY", + "DHCID", + "NSEC3", + "NSEC3PARAM", + "TLSA", + "SMIMEA", + "unassigned", + "HIP", + "NINFO", + "RKEY", + "TALINK", + "CDS", + "CDNSKEY", + "OPENPGPKEY", + "CSYNC", + "ZONEMD", + "SVCB", + "HTTPS", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "SPF", + "UINFO", + "UID", + "GID", + "UNSPEC", + "NID", + "L32", + "L64", + "LP", + "EUI48", + "EUI64", + + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + + "TKEY", + "TSIG", + "IXFR", + "AXFR", + "MAILB", + "MAILA", + "*", + "URI", + "CAA", + "AVC", + "DOA", + "AMTRELAY", + "RESINFO" +} ; + + +char const *shibari_util_qtype_str (uint16_t qtype) +{ + if (qtype < 262) return qtype_table[qtype] ; + if (qtype < 32768) return "unassigned" ; + if (qtype == 32768) return "TA" ; + if (qtype == 32769) return "DLV" ; + if (qtype < 65279) return "unassigned" ; + if (qtype < 65535) return "private" ; + return "reserved" ; +} diff --git a/src/common/shibari_util_rcode_str.c b/src/common/shibari_util_rcode_str.c new file mode 100644 index 0000000..142cc0e --- /dev/null +++ b/src/common/shibari_util_rcode_str.c @@ -0,0 +1,41 @@ +/* ISC license. */ + +#include + +#include + +char const *shibari_util_rcode_str (uint16_t rcode) +{ + static char const *const rcode_table[24] = + { + "noerror", + "formerr", + "servfail", + "nxdomain", + "notimp", + "refused", + "yxdomain", + "yxrrset", + "nxrrset", + "notauth", + "notzone", + "dsotypeni", + "unassigned", + "unassigned", + "unassigned", + "unassigned", + "badsig", + "badkey", + "badtime", + "badmode", + "badname", + "badalg", + "badtrunc", + "badcookie" + } ; + if (rcode < 24) return rcode_table[rcode] ; + if (rcode < 3841) return "unassigned" ; + if (rcode < 4096) return "private" ; + if (rcode < 65535) return "unassigned" ; + return "reserved" ; +} diff --git a/src/include/shibari/cache.h b/src/include/shibari/cache.h new file mode 100644 index 0000000..d0c6004 --- /dev/null +++ b/src/include/shibari/cache.h @@ -0,0 +1,8 @@ +/* ISC license. */ + +#ifndef SHIBARI_CACHE_H +#define SHIBARI_CACHE_H + +#include + +#endif diff --git a/src/include/shibari/client.h b/src/include/shibari/client.h new file mode 100644 index 0000000..03f8b1b --- /dev/null +++ b/src/include/shibari/client.h @@ -0,0 +1,6 @@ +/* ISC license. */ + +#ifndef SHIBARI_CLIENT_H +#define SHIBARI_CLIENT_H + +#endif diff --git a/src/include/shibari/common.h b/src/include/shibari/common.h new file mode 100644 index 0000000..d36d055 --- /dev/null +++ b/src/include/shibari/common.h @@ -0,0 +1,9 @@ +/* ISC license. */ + +#ifndef SHIBARI_COMMON_H +#define SHIBARI_COMMON_H + +#include +#include + +#endif diff --git a/src/include/shibari/constants.h b/src/include/shibari/constants.h new file mode 100644 index 0000000..a4f86f3 --- /dev/null +++ b/src/include/shibari/constants.h @@ -0,0 +1,109 @@ +/* ISC license. */ + +#ifndef SHIBARI_CONSTANTS_H +#define SHIBARI_CONSTANTS_H + +enum shibari_qclass_e +{ + SHIBARI_C_IN = 1, + SHIBARI_C_CH = 3, + SHIBARI_C_HS = 4, + SHIBARI_C_NONE = 254, + SHIBARI_C_ANY = 255, +} ; + +enum shibari_qtype_e +{ + SHIBARI_T_A = 1, + SHIBARI_T_NS = 2, + SHIBARI_T_MD = 3, + SHIBARI_T_MF = 4, + SHIBARI_T_CNAME = 5, + SHIBARI_T_SOA = 6, + SHIBARI_T_MB = 7, + SHIBARI_T_MG = 8, + SHIBARI_T_MR = 9, + SHIBARI_T_NULL = 10, + SHIBARI_T_WKS = 11, + SHIBARI_T_PTR = 12, + SHIBARI_T_HINFO = 13, + SHIBARI_T_MINFO = 14, + SHIBARI_T_MX = 15, + SHIBARI_T_TXT = 16, + SHIBARI_T_RP = 17, + SHIBARI_T_AFSDB = 18, + SHIBARI_T_X25 = 19, + SHIBARI_T_ISDN = 20, + SHIBARI_T_RT = 21, + SHIBARI_T_NSAP = 22, + SHIBARI_T_NSAP_PTR = 23, + SHIBARI_T_SIG = 24, + SHIBARI_T_KEY = 25, + SHIBARI_T_PX = 26, + SHIBARI_T_GPOS = 27, + SHIBARI_T_AAAA = 28, + SHIBARI_T_LOC = 29, + SHIBARI_T_NXT = 30, + SHIBARI_T_EID = 31, + SHIBARI_T_NIMLOC = 32, + SHIBARI_T_SRV = 33, + SHIBARI_T_ATMA = 34, + SHIBARI_T_NAPTR = 35, + SHIBARI_T_KX = 36, + SHIBARI_T_CERT = 37, + SHIBARI_T_A6 = 38, + SHIBARI_T_DNAME = 39, + SHIBARI_T_SINK = 40, + SHIBARI_T_OPT = 41, + SHIBARI_T_APL = 42, + SHIBARI_T_DS = 43, + SHIBARI_T_SSHFP = 44, + SHIBARI_T_IPSECKEY = 45, + SHIBARI_T_RRSIG = 46, + SHIBARI_T_NSEC = 47, + SHIBARI_T_DNSKEY = 48, + SHIBARI_T_DHCID = 49, + SHIBARI_T_NSEC3 = 50, + SHIBARI_T_NSEC3PARAM = 51, + SHIBARI_T_TLSA = 52, + SHIBARI_T_SMIMEA = 53, + SHIBARI_T_HIP = 55, + SHIBARI_T_NINFO = 56, + SHIBARI_T_RKEY = 57, + SHIBARI_T_TALINK = 58, + SHIBARI_T_CDS = 59, + SHIBARI_T_CDNSKEY = 60, + SHIBARI_T_OPENPGPKEY = 61, + SHIBARI_T_CSYNC = 62, + SHIBARI_T_ZONEMD = 63, + SHIBARI_T_SVCB = 64, + SHIBARI_T_HTTPS = 65, + SHIBARI_T_SPF = 99, + SHIBARI_T_UINFO = 100, + SHIBARI_T_UID = 101, + SHIBARI_T_GID = 102, + SHIBARI_T_UNSPEC = 103, + SHIBARI_T_NID = 104, + SHIBARI_T_L32 = 105, + SHIBARI_T_L64 = 106, + SHIBARI_T_LP = 107, + SHIBARI_T_EUI48 = 108, + SHIBARI_T_EUI64 = 109, + SHIBARI_T_TKEY = 249, + SHIBARI_T_TSIG = 250, + SHIBARI_T_IXFR = 251, + SHIBARI_T_AXFR = 252, + SHIBARI_T_MAILB = 253, + SHIBARI_T_MAILA = 254, + SHIBARI_T_ANY = 255, + SHIBARI_T_URI = 256, + SHIBARI_T_CAA = 257, + SHIBARI_T_AVC = 258, + SHIBARI_T_DOA = 259, + SHIBARI_T_AMIRELAY = 260, + SHIBARI_T_RESINFO = 261, + SHIBARI_T_TA = 32768, + SHIBARI_T_DLV = 32769 +} ; + +#endif diff --git a/src/include/shibari/dcache.h b/src/include/shibari/dcache.h new file mode 100644 index 0000000..6e0d0ab --- /dev/null +++ b/src/include/shibari/dcache.h @@ -0,0 +1,54 @@ +/* ISC license. */ + +#ifndef SHIBARI_DCACHE_H +#define SHIBARI_DCACHE_H + +#include + +#include +#include +#include +#include + +#define DCACHE_MAGIC "--DCACHE--\n" + +typedef struct dcache_key_s dcache_key_t, *dcache_key_t_ref ; +struct dcache_key_s +{ + char *s ; + uint16_t len ; +} ; + +typedef struct dcache_node_s dcache_node_t, *dcache_node_t_ref ; +struct dcache_node_s +{ + dcache_key_t key ; + uint16_t datalen ; + tain entry ; + tain expire ; +} ; + +typedef struct dcache_s dcache_t, *dcache_t_ref ; +struct dcache_s +{ + gensetdyn storage ; /* dcache_node_t */ + avltree by_key ; + avltree by_entry ; + avltree by_expire ; + uint64_t size ; + uint64_t motion ; +} ; +#define DCACHE_ZERO { .storage = GENSETDYN_ZERO, .by_key = AVLTREE_ZERO, .by_entry = AVLTREE_ZERO, .by_expire = AVLTREE_ZERO, .size = 0, .motion = 0 } + +extern void dcache_init (dcache_t *, uint64_t) ; +extern dcache_node_t *dcache_search (dcache_t *, char const *, uint16_t) ; +extern int dcache_add (dcache_t *, uint64_t, char const *, uint16_t, char const *, uint16_t, tain const *, tain const *) ; +#define dcache_add_g(d, max, key, keylen, data, datalen, expire) dcache_add(d, max, key, keylen, data, datalen, (expire), &STAMP) +extern void dcache_clean_expired (dcache_t *, tain const *) ; +#define dcache_clean_expired_g(d) dcache_clean_expired((d), &STAMP) +extern void dcache_free (dcache_t *) ; + +extern int dcache_save (dcache_t const *, char const *) ; +extern int dcache_load (dcache_t *, uint64_t, char const *) ; + +#endif diff --git a/src/include/shibari/log.h b/src/include/shibari/log.h new file mode 100644 index 0000000..a01e499 --- /dev/null +++ b/src/include/shibari/log.h @@ -0,0 +1,20 @@ +/* ISC license. */ + +#ifndef SHIBARI_LOG_H +#define SHIBARI_LOG_H + +#include + +#include + +#include +#include + +extern void shibari_log_start (uint32_t, ip46 const *, uint16_t) ; +extern void shibari_log_exit (uint32_t, int) ; + +extern void shibari_log_query (uint32_t, s6dns_domain_t const *, uint16_t) ; +extern void shibari_log_queryplus (uint32_t, s6dns_domain_t const *, uint16_t, ip46 const *, uint16_t) ; +extern void shibari_log_answer (uint32_t, s6dns_message_header_t const *, uint16_t) ; + +#endif diff --git a/src/include/shibari/packet.h b/src/include/shibari/packet.h new file mode 100644 index 0000000..1f4fa93 --- /dev/null +++ b/src/include/shibari/packet.h @@ -0,0 +1,39 @@ +/* ISC license. */ + +#ifndef SHIBARI_PACKET_H +#define SHIBARI_PACKET_H + +#include + +#include +#include + +#include +#include + +#include + +typedef struct shibari_packet_s shibari_packet, *shibari_packet_ref ; +struct shibari_packet_s +{ + s6dns_message_header_t hdr ; + char *buf ; + uint16_t max ; + uint16_t pos ; + uint8_t flagtcp : 1 ; +} ; +#define SHIBARI_PACKET_ZERO { .hdr = S6DNS_MESSAGE_HEADER_ZERO, .buf = "", .pos = 0, .flagtcp = 0 } +#define SHIBARI_PACKET_INIT(rbuf, rmax, tcp) { .hdr = S6DNS_MESSAGE_HEADER_ZERO, .buf = tcp ? rbuf + 2 : rbuf, .max = tcp ? rmax - 2 : rmax, .pos = 0, .flagtcp = !!tcp } + +extern void shibari_packet_init (shibari_packet *, char *, uint32_t, int) ; + +extern void shibari_packet_begin (shibari_packet *, uint16_t, s6dns_domain_t const *, uint16_t) ; +extern void shibari_packet_end (shibari_packet *) ; + +extern int shibari_packet_add_rr (shibari_packet *, shibari_tdb_entry const *, int, uint16_t, unsigned int) ; +extern unsigned int shibari_packet_add_glue (shibari_packet *, cdb const *, char const *, uint16_t, uint16_t, char const *, uint16_t, uint16_t, uint16_t, char const *, tain const *) ; +extern unsigned int shibari_packet_assert_authority (shibari_packet *, cdb const *, char const *, uint16_t, uint16_t, char const *, tain const *) ; + +extern unsigned int shibari_packet_tdb_answer_query (shibari_packet *, cdb const *, s6dns_message_header_t const *, s6dns_domain_t const *, uint16_t, char const *, tain const *) ; + +#endif diff --git a/src/include/shibari/server.h b/src/include/shibari/server.h new file mode 100644 index 0000000..db5af40 --- /dev/null +++ b/src/include/shibari/server.h @@ -0,0 +1,10 @@ +/* ISC license. */ + +#ifndef SHIBARI_SERVER_H +#define SHIBARI_SERVER_H + +#include +#include +#include + +#endif diff --git a/src/include/shibari/shibari.h b/src/include/shibari/shibari.h new file mode 100644 index 0000000..a9242d3 --- /dev/null +++ b/src/include/shibari/shibari.h @@ -0,0 +1,11 @@ +/* ISC license. */ + +#ifndef SHIBARI_H +#define SHIBARI_H + +#include +#include +#include +#include + +#endif diff --git a/src/include/shibari/tdb.h b/src/include/shibari/tdb.h new file mode 100644 index 0000000..f61df5b --- /dev/null +++ b/src/include/shibari/tdb.h @@ -0,0 +1,29 @@ +/* ISC license. */ + +#ifndef SHIBARI_TDB_H +#define SHIBARI_TDB_H + +#include + +#include +#include + +#include + +typedef struct shibari_tdb_entry_s shibari_tdb_entry, *shibari_tdb_entry_ref ; +struct shibari_tdb_entry_s +{ + uint16_t type ; + uint16_t len ; + uint32_t ttl ; + uint32_t flags ; + cdb_data key ; + cdb_data data ; +} ; + +extern int shibari_tdb_entry_parse (shibari_tdb_entry *, char const *, uint16_t, uint16_t, unsigned int, char const *, tain const *) ; +extern int shibari_tdb_read_entry (cdb const *, cdb_find_state *, shibari_tdb_entry *, char const *, uint16_t, uint16_t, unsigned int, char const *, tain const *, uint32_t *) ; +extern int shibari_tdb_extract_domain (shibari_tdb_entry const *, cdb_data *) ; +extern int shibari_tdb_find_authority (cdb const *, char const *, uint16_t, char const *, tain const *, int *) ; + +#endif diff --git a/src/include/shibari/util.h b/src/include/shibari/util.h new file mode 100644 index 0000000..82092a3 --- /dev/null +++ b/src/include/shibari/util.h @@ -0,0 +1,14 @@ +/* ISC license. */ + +#ifndef SHIBARI_UTIL_H +#define SHIBARI_UTIL_H + +#include + +extern char const *shibari_util_qtype_str (uint16_t) ; +extern uint16_t shibari_util_qtype_num (char const *) ; +extern char const *shibari_util_rcode_str (uint16_t) ; + +extern int shibari_util_get_prefixlen (char const *, uint16_t, char const *, uint16_t) ; + +#endif diff --git a/src/server/deps-exe/shibari-server-tcp b/src/server/deps-exe/shibari-server-tcp new file mode 100644 index 0000000..c25f645 --- /dev/null +++ b/src/server/deps-exe/shibari-server-tcp @@ -0,0 +1,4 @@ +${LIBSHIBARI_SERVER} +${LIBSHIBARI_COMMON} +-ls6dns +-lskarnet diff --git a/src/server/deps-exe/shibari-server-udp b/src/server/deps-exe/shibari-server-udp new file mode 100644 index 0000000..0c1f81d --- /dev/null +++ b/src/server/deps-exe/shibari-server-udp @@ -0,0 +1,6 @@ +${LIBSHIBARI_SERVER} +${LIBSHIBARI_COMMON} +-ls6dns +-ls6 +-lskarnet +${SOCKET_LIB} diff --git a/src/server/deps-lib/shibari-server b/src/server/deps-lib/shibari-server new file mode 100644 index 0000000..7c5b981 --- /dev/null +++ b/src/server/deps-lib/shibari-server @@ -0,0 +1,13 @@ +shibari_packet_init.o +shibari_packet_begin.o +shibari_packet_end.o +shibari_packet_add_rr.o +shibari_tdb_entry_parse.o +shibari_tdb_extract_domain.o +shibari_tdb_find_authority.o +shibari_tdb_read_entry.o +shibari_packet_add_glue.o +shibari_packet_assert_authority.o +shibari_packet_tdb_answer_query.o +-ls6dns +-lskarnet diff --git a/src/server/shibari-server-tcp.c b/src/server/shibari-server-tcp.c new file mode 100644 index 0000000..e646a44 --- /dev/null +++ b/src/server/shibari-server-tcp.c @@ -0,0 +1,235 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define PROGNAME "shibari-server-tcp" +#define USAGE PROGNAME " [ -v verbosity ] [ -f cdbfile ] [ -r timeout ] [ -w timeout ]" +#define dieusage() strerr_dieusage(100, USAGE) + +#define QMAX 2048 +#define RMAX 65535 + +static uint32_t verbosity = 1 ; + +static inline void get_socket_info (ip46 *localip, uint16_t *localport, ip46 *remoteip, uint16_t *remoteport) +{ + char const *x = getenv("PROTO") ; + if (!x) strerr_dienotset(100, "PROTO") ; + { + size_t protolen = strlen(x) ; + char var[protolen + 11] ; + memcpy(var, x, protolen) ; + memcpy(var + protolen, "LOCALIP", 8) ; + x = getenv(var) ; + if (!x) strerr_dienotset(100, var) ; + if (!ip46_scan(x, localip)) strerr_dieinvalid(100, var) ; + memcpy(var + protolen + 5, "PORT", 5) ; + x = getenv(var) ; + if (!x) strerr_dienotset(100, var) ; + if (!uint160_scan(x, localport)) strerr_dieinvalid(100, var) ; + memcpy(var + protolen, "REMOTEIP", 9) ; + x = getenv(var) ; + if (!x) strerr_dienotset(100, var) ; + if (!ip46_scan(x, remoteip)) strerr_dieinvalid(100, var) ; + memcpy(var + protolen + 6, "PORT", 5) ; + x = getenv(var) ; + if (!x) strerr_dienotset(100, var) ; + if (!uint160_scan(x, remoteport)) strerr_dieinvalid(100, var) ; + } +} + +static void add (shibari_packet *pkt, shibari_tdb_entry const *entry, int prefixlen, uint16_t id, s6dns_domain_t const *zone, tain const *deadline) +{ + if (!shibari_packet_add_rr(pkt, entry, prefixlen, 0, 2)) + { + shibari_packet_end(pkt) ; + if (!buffer_timed_put_g(buffer_1, pkt->buf - 2, pkt->pos + 2, deadline)) + strerr_diefu1sys(111, "write to stdout") ; + shibari_packet_begin(pkt, id, zone, SHIBARI_T_AXFR) ; + if (!shibari_packet_add_rr(pkt, entry, prefixlen, 0, 2)) + strerr_dief1x(101, "can't happen: record too long to fit in single packet") ; + } +} + +static inline int axfr (char const *axfrok, char const *loc, cdb const *tdb, s6dns_message_header_t const *qhdr, s6dns_domain_t const *zone, shibari_packet *pkt, tain const *deadline, tain const *wstamp) +{ + shibari_tdb_entry soa ; + shibari_tdb_entry cur ; + uint32_t pos = CDB_TRAVERSE_INIT() ; + if (!axfrok) return 5 ; + if (axfrok[0] != '*') + { + s6dns_domain_t decoded = *zone ; + unsigned int zonelen ; + size_t len = strlen(axfrok) + 1 ; + char buf[256] ; + if (!s6dns_domain_decode(&decoded)) return 1 ; + zonelen = s6dns_domain_tostring(buf, 256, &decoded) ; + while (len >= zonelen) + { + if (!strncmp(buf, axfrok, zonelen) && (!axfrok[zonelen] || strchr("/,; \t\n", axfrok[zonelen]))) break ; + axfrok += zonelen + 1 ; + len -= zonelen + 1 ; + } + if (len < zonelen) return 5 ; + } + + { + cdb_find_state state = CDB_FIND_STATE_ZERO ; + int r = shibari_tdb_read_entry(tdb, &state, &soa, zone->s, zone->len, SHIBARI_T_SOA, 0, loc, wstamp, 0) ; + if (r == -1) return 2 ; + if (!r) return 9 ; + } + + shibari_packet_begin(pkt, qhdr->id, zone, SHIBARI_T_AXFR) ; + pkt->hdr.aa = 1 ; + add(pkt, &soa, 0, qhdr->id, zone, deadline) ; + + for (;;) + { + cdb_data data ; + int prefixlen ; + int r = cdb_traverse_next(tdb, &cur.key, &data, &pos) ; + if (r == -1) return 2 ; + if (!r) break ; + prefixlen = shibari_util_get_prefixlen(cur.key.s, cur.key.len, zone->s, zone->len) ; + if (prefixlen == -1) continue ; + r = shibari_tdb_entry_parse(&cur, data.s, data.len, SHIBARI_T_ANY, 2, loc, wstamp) ; + if (r == -1) return 2 ; + if (!r) continue ; + if (cur.type == SHIBARI_T_SOA) continue ; + add(pkt, &cur, prefixlen, qhdr->id, zone, deadline) ; + } + + add(pkt, &soa, 0, qhdr->id, zone, deadline) ; + shibari_packet_end(pkt) ; + return 0 ; +} + +int main (int argc, char const *const *argv) +{ + cdb tdb = CDB_ZERO ; + char const *axfrok = getenv("AXFR") ; + char const *loc = getenv("LOC") ; + tain rtto = TAIN_INFINITE_RELATIVE, wtto = TAIN_INFINITE_RELATIVE ; + ip46 localip, remoteip ; + uint16_t localport, remoteport ; + char progbuf[sizeof(PROGNAME) + 5 + PID_FMT] = PROGNAME ": pid " ; + char buf[RMAX + 2] ; + shibari_packet pkt = SHIBARI_PACKET_INIT(buf, RMAX + 2, 1) ; + PROG = "shibari-server-tcp" ; + + { + size_t pos = sizeof(PROGNAME) + 5 ; + pos += pid_fmt(progbuf + pos, getpid()) ; + progbuf[pos++] = 0 ; + } + + { + char const *tdbfile = "data.cdb" ; + uint32_t r = 0, w = 0 ; + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "v:f:r:w:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : if (!uint320_scan(l.arg, &verbosity)) dieusage() ; break ; + case 'f' : tdbfile = l.arg ; break ; + case 'r' : if (!uint320_scan(l.arg, &r)) dieusage() ; break ; + case 'w' : if (!uint320_scan(l.arg, &w)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (r) tain_from_millisecs(&rtto, r) ; + if (w) tain_from_millisecs(&wtto, w) ; + get_socket_info(&localip, &localport, &remoteip, &remoteport) ; + PROG = progbuf ; + if (!cdb_init(&tdb, tdbfile)) strerr_diefu2sys(111, "open DNS database file ", tdbfile) ; + } + + if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ; + tain_now_set_stopwatch_g() ; + shibari_log_start(verbosity, &remoteip, remoteport) ; + + for (;;) + { + tain wstamp ; + size_t w ; + tain deadline ; + s6dns_message_header_t hdr ; + s6dns_message_counts_t counts ; + s6dns_domain_t name ; + unsigned int rcode ; + uint16_t qtype ; + uint16_t len ; + tain_add_g(&deadline, &rtto) ; + w = buffer_timed_get_g(buffer_0, buf, 2, &deadline) ; + if (w == 1) strerr_dief1x(1, "invalid request") ; + if (!w) + { + if (errno != EPIPE && errno != ETIMEDOUT) + strerr_diefu1sys(111, "read from stdin") ; + else break ; + } + uint16_unpack_big(buf, &len) ; + if (len > QMAX) strerr_dief1x(1, "request too large") ; + if (buffer_timed_get_g(buffer_0, buf, len, &deadline) < len) + strerr_diefu1sys(111, "read from stdin") ; + + if (!s6dns_message_parse_init(&hdr, &counts, buf, len, &rcode)) + strerr_diefu1sys(111, "parse message") ; + if (hdr.opcode) { rcode = 4 ; goto answer ; } + if (!s6dns_message_parse_question(&counts, &name, &qtype, buf, len, &rcode) || !s6dns_domain_encode(&name)) + { + rcode = errno == ENOTSUP ? 4 : 1 ; + goto answer ; + } + shibari_log_query(verbosity, &name, qtype) ; + tain_add_g(&deadline, &wtto) ; + tain_wallclock_read(&wstamp) ; + rcode = qtype == SHIBARI_T_AXFR ? + axfr(axfrok, loc, &tdb, &hdr, &name, &pkt, &deadline, &wstamp) : + shibari_packet_tdb_answer_query(&pkt, &tdb, &hdr, &name, qtype, loc, &wstamp) ; + + answer: + if (rcode && rcode != 3) + { + shibari_packet_begin(&pkt, hdr.id, &name, qtype) ; + pkt.hdr.rcode = rcode ; + shibari_packet_end(&pkt) ; + } + shibari_log_answer(verbosity, &pkt.hdr, pkt.pos) ; + if (!buffer_timed_put_g(buffer_1, buf, pkt.pos + 2, &deadline) + || !buffer_timed_flush_g(buffer_1, &deadline)) + strerr_diefu1sys(111, "write to stdout") ; + } + + shibari_log_exit(verbosity, 0) ; + return 0 ; +} diff --git a/src/server/shibari-server-udp.c b/src/server/shibari-server-udp.c new file mode 100644 index 0000000..d834c94 --- /dev/null +++ b/src/server/shibari-server-udp.c @@ -0,0 +1,207 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define USAGE "shibari-server-udp [ -v verbosity ] [ -d notif ] [ -f cdbfile ] [ -i rulesdir | -x rulesfile ] [ -p port ] ip" +#define dieusage() strerr_dieusage(100, USAGE) + +#define VAR "LOC" + +static char const *tdbfile = "data.cdb" ; +static cdb tdb = CDB_ZERO ; +static cdb rules = CDB_ZERO ; +static char const *rulesfile = 0 ; +static unsigned int rulestype = 0 ; +static int cont = 1 ; +static uint32_t verbosity = 1 ; + +static void on_term (int s) +{ + (void)s ; + cont = 0 ; +} + +static void on_hup (int s) +{ + cdb newtdb = CDB_ZERO ; + (void)s ; + if (!cdb_init(&newtdb, tdbfile)) + { + if (verbosity) strerr_warnwu2sys("reopen DNS data file ", tdbfile) ; + } + else + { + cdb_free(&tdb) ; + tdb = newtdb ; + } + if (rulestype == 2) + { + cdb newrules = CDB_ZERO ; + if (!cdb_init(&newrules, rulesfile)) + { + if (verbosity) strerr_warnwu2sys("reopen access rules file ", rulesfile) ; + } + else + { + cdb_free(&rules) ; + rules = newrules ; + } + } +} + +static int check_rules (ip46 const *remoteip, s6_accessrules_params_t *params, char const **loc) +{ + s6_accessrules_result_t r ; + params->env.len = 0 ; + params->exec.len = 0 ; + r = rulestype == 2 ? + s6_accessrules_ip46_cdb(remoteip, &rules, params) : + s6_accessrules_ip46_fs(remoteip, rulesfile, params) ; + if (r != S6_ACCESSRULES_ALLOW) return 0 ; + + if (params->env.len) + { + char const *p ; + if (params->env.s[params->env.len - 1]) + { + if (verbosity) + { + char fmt[IP46_FMT] ; + fmt[ip46_fmt(fmt, remoteip)] = 0 ; + strerr_warnw6x("invalid environment parameters in rules ", rulestype == 2 ? "cdb " : "directory ", rulesfile, " for ip ", fmt, " - denying connection") ; + } + return 0 ; + } + p = memmem(params->env.s, params->env.len - 1, VAR "=", sizeof(VAR)) ; + if (p && (p == params->env.s || !p[-1])) *loc = p + sizeof(VAR) ; + } + return 1 ; +} + +int main (int argc, char const *const *argv) +{ + s6_accessrules_params_t params = S6_ACCESSRULES_PARAMS_ZERO ; + int s ; + unsigned int notif = 0 ; + char buf[512] ; + shibari_packet pkt = SHIBARI_PACKET_INIT(buf, 512, 0) ; + uint16_t localport = 53 ; + ip46 localip ; + + PROG = "shibari-server-udp" ; + + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "v:d:f:i:x:p:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : if (!uint320_scan(l.arg, &verbosity)) dieusage() ; break ; + case 'd' : if (!uint0_scan(l.arg, ¬if)) dieusage() ; break ; + case 'f' : tdbfile = l.arg ; break ; + case 'i' : rulesfile = l.arg ; rulestype = 1 ; break ; + case 'x' : rulesfile = l.arg ; rulestype = 2 ; break ; + case 'p' : if (!uint160_scan(l.arg, &localport)) dieusage() ; break ; + default : strerr_dieusage(10, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (!argc) dieusage() ; + if (!ip46_scan(argv[0], &localip)) dieusage() ; + + if (notif) + { + if (notif < 3) strerr_dief1x(100, "notification fd cannot be 0, 1 or 2") ; + if (fcntl(notif, F_GETFD) == -1) strerr_diefu1sys(111, "check notification fd") ; + } + + close(0) ; + close(1) ; + s = socket_udp46_b(ip46_is6(&localip)) ; + if (s == -1) strerr_diefu1sys(111, "create socket") ; + if (socket_bind46_reuse(s, &localip, localport) == -1) strerr_diefu1sys(111, "bind socket") ; + + if (!cdb_init(&tdb, tdbfile)) strerr_diefu2sys(111, "open cdb file ", tdbfile) ; + if (rulestype == 2 && !cdb_init(&rules, rulesfile)) strerr_diefu2sys(111, "open rules file ", rulesfile) ; + if (!sig_catch(SIGHUP, &on_hup)) strerr_diefu1sys(111, "catch SIGHUP") ; + if (!sig_catch(SIGTERM, &on_term)) strerr_diefu1sys(111, "catch SIGTERM") ; + + shibari_log_start(verbosity, &localip, localport) ; + if (notif) + { + write(notif, "\n", 1) ; + close(notif) ; + } + + for (; cont ; sig_unblock(SIGHUP)) + { + tain wstamp ; + char const *loc = 0 ; + s6dns_message_header_t hdr ; + s6dns_message_counts_t counts ; + s6dns_domain_t name ; + unsigned int rcode ; + ssize_t r ; + uint16_t qtype ; + uint16_t remoteport ; + ip46 remoteip ; + + r = socket_recv46(s, buf, 512, &remoteip, &remoteport) ; + if (r == -1) strerr_diefu1sys(111, "recv from socket") ; + if (!r) strerr_dief1x(111, "huh? got EOF on a connection-less socket") ; + sig_block(SIGHUP) ; + if (rulestype && !check_rules(&remoteip, ¶ms, &loc)) continue ; + if (!s6dns_message_parse_init(&hdr, &counts, buf, r, &rcode)) continue ; + if (hdr.opcode) { rcode = 4 ; goto answer ; } + if (!s6dns_message_parse_question(&counts, &name, &qtype, buf, r, &rcode) || !s6dns_domain_encode(&name)) + { + rcode = errno == ENOTSUP ? 4 : 1 ; + goto answer ; + } + shibari_log_queryplus(verbosity, &name, qtype, &remoteip, remoteport) ; + tain_wallclock_read(&wstamp) ; + rcode = shibari_packet_tdb_answer_query(&pkt, &tdb, &hdr, &name, qtype, loc, &wstamp) ; + + answer: + if (rcode && rcode != 3) + { + shibari_packet_begin(&pkt, hdr.id, &name, qtype) ; + pkt.hdr.rcode = rcode ; + shibari_packet_end(&pkt) ; + } + shibari_log_answer(verbosity, &pkt.hdr, pkt.pos) ; + if (socket_send46(s, buf, pkt.pos, &remoteip, remoteport) < pkt.pos && verbosity) + strerr_warnwu1sys("send answer") ; + } + + shibari_log_exit(verbosity, 0) ; + return 0 ; +} diff --git a/src/server/shibari_packet_add_glue.c b/src/server/shibari_packet_add_glue.c new file mode 100644 index 0000000..4a0abf1 --- /dev/null +++ b/src/server/shibari_packet_add_glue.c @@ -0,0 +1,48 @@ +/* ISC license. */ + +#include + +#include +#include +#include +#include + +static int shibari_packet_add_glue_for_rr (shibari_packet *pkt, cdb const *tdb, char const *s, uint16_t len, uint16_t prefixlen, uint16_t offset, char const *loc, tain const *stamp) +{ + cdb_find_state state = CDB_FIND_STATE_ZERO ; + for (;;) + { + shibari_tdb_entry entry ; + int r = shibari_tdb_read_entry(tdb, &state, &entry, s, len, SHIBARI_T_ANY, 0, loc, stamp, 0) ; + if (r == -1) return 2 ; + if (!r) break ; + if (entry.type != SHIBARI_T_A && entry.type != SHIBARI_T_AAAA) continue ; + if (!shibari_packet_add_rr(pkt, &entry, prefixlen, offset, 4)) + { + pkt->hdr.tc = 1 ; + return 0 ; + } + } + return -1 ; +} + +unsigned int shibari_packet_add_glue (shibari_packet *pkt, cdb const *tdb, char const *s, uint16_t len, uint16_t qtype, char const *z, uint16_t zlen, uint16_t zoffset, uint16_t wildpos, char const *loc, tain const *stamp) +{ + cdb_find_state state = CDB_FIND_STATE_ZERO ; + for (;;) + { + shibari_tdb_entry entry ; + cdb_data domain ; + int zprefixlen, sprefixlen ; + int r = shibari_tdb_read_entry(tdb, &state, &entry, s + wildpos, len - wildpos, qtype, !!wildpos, loc, stamp, 0) ; + if (r == -1) return 2 ; + if (!r) break ; + if (!shibari_tdb_extract_domain(&entry, &domain)) continue ; + zprefixlen = shibari_util_get_prefixlen(domain.s, domain.len, z, zlen) ; + if (zprefixlen == -1) continue ; + sprefixlen = shibari_util_get_prefixlen(domain.s, domain.len, s, len) ; + r = shibari_packet_add_glue_for_rr(pkt, tdb, domain.s, domain.len, sprefixlen == -1 ? zprefixlen : sprefixlen, sprefixlen == -1 ? zoffset : 0, loc, stamp) ; + if (r >= 0) return r ; + } + return 0 ; +} diff --git a/src/server/shibari_packet_add_rr.c b/src/server/shibari_packet_add_rr.c new file mode 100644 index 0000000..b92e8dd --- /dev/null +++ b/src/server/shibari_packet_add_rr.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include +#include + +#include +#include + +#include +#include + +int shibari_packet_add_rr (shibari_packet *p, shibari_tdb_entry const *entry, int prefixlen, uint16_t offset, unsigned int section) +{ + uint16_t *count[4] = { &p->hdr.counts.qd, &p->hdr.counts.an, &p->hdr.counts.ns, &p->hdr.counts.nr } ; + uint16_t rrlen = 10 + entry->data.len + (entry->flags & 1 ? 2 : 0) + (prefixlen >= 0 ? prefixlen + 2 : entry->key.len) ; + if (p->max - p->pos < rrlen) return 0 ; + if (entry->flags & 1) + { + p->buf[p->pos++] = 1 ; + p->buf[p->pos++] = '*' ; + } + if (prefixlen >= 0) + { + memcpy(p->buf + p->pos, entry->key.s, prefixlen) ; + p->pos += prefixlen ; + uint16_pack_big(p->buf + p->pos, 49164 + offset) ; + p->pos += 2 ; + } + else + { + memcpy(p->buf + p->pos, entry->key.s, entry->key.len) ; + p->pos += entry->key.len ; + } + uint16_pack_big(p->buf + p->pos, entry->type) ; + p->pos += 2 ; + uint16_pack_big(p->buf + p->pos, SHIBARI_C_IN) ; + p->pos += 2 ; + uint32_pack_big(p->buf + p->pos, entry->ttl) ; + p->pos += 4 ; + uint16_pack_big(p->buf + p->pos, entry->data.len) ; + p->pos += 2 ; + memcpy(p->buf + p->pos, entry->data.s, entry->data.len) ; + p->pos += entry->data.len ; + (*count[section-1])++ ; + return 1 ; +} diff --git a/src/server/shibari_packet_assert_authority.c b/src/server/shibari_packet_assert_authority.c new file mode 100644 index 0000000..18c8299 --- /dev/null +++ b/src/server/shibari_packet_assert_authority.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include + +#include +#include +#include +#include + +unsigned int shibari_packet_assert_authority (shibari_packet *pkt, cdb const *tdb, char const *z, uint16_t zlen, uint16_t zoffset, char const *loc, tain const *stamp) +{ + cdb_find_state state = CDB_FIND_STATE_ZERO ; + shibari_tdb_entry soa ; + int r = shibari_tdb_read_entry(tdb, &state, &soa, z, zlen, SHIBARI_T_SOA, 0, loc, stamp, 0) ; + if (r <= 0) return 2 ; + if (!shibari_packet_add_rr(pkt, &soa, 0, zoffset, 3)) pkt->hdr.tc = 1 ; + return 0 ; +} diff --git a/src/server/shibari_packet_begin.c b/src/server/shibari_packet_begin.c new file mode 100644 index 0000000..5ea7b16 --- /dev/null +++ b/src/server/shibari_packet_begin.c @@ -0,0 +1,32 @@ +/* ISC license. */ + +#include + +#include + +#include +#include + +void shibari_packet_begin (shibari_packet *p, uint16_t id, s6dns_domain_t const *q, uint16_t qtype) +{ + p->hdr.id = id ; + p->hdr.qr = 1 ; + p->hdr.opcode = 0 ; + p->hdr.aa = 0 ; + p->hdr.tc = 0 ; + p->hdr.rd = 0 ; + p->hdr.ra = 0 ; + p->hdr.z = 0 ; + p->hdr.rcode = 0 ; + p->hdr.counts.qd = 1 ; + p->hdr.counts.an = 0 ; + p->hdr.counts.ns = 0 ; + p->hdr.counts.nr = 0 ; + p->pos = 12 ; + memcpy(p->buf + p->pos, q->s, q->len) ; + p->pos += q->len ; + uint16_pack_big(p->buf + p->pos, qtype) ; + p->pos += 2 ; + uint16_pack_big(p->buf + p->pos, SHIBARI_C_IN) ; + p->pos += 2 ; +} diff --git a/src/server/shibari_packet_end.c b/src/server/shibari_packet_end.c new file mode 100644 index 0000000..41aca87 --- /dev/null +++ b/src/server/shibari_packet_end.c @@ -0,0 +1,13 @@ +/* ISC license. */ + +#include + +#include + +#include + +void shibari_packet_end (shibari_packet *p) +{ + s6dns_message_header_pack(p->buf, &p->hdr) ; + if (p->flagtcp) uint16_pack_big(p->buf - 2, p->pos) ; +} diff --git a/src/server/shibari_packet_init.c b/src/server/shibari_packet_init.c new file mode 100644 index 0000000..a0aff97 --- /dev/null +++ b/src/server/shibari_packet_init.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include + +#include + +void shibari_packet_init (shibari_packet *p, char *buf, uint32_t max, int istcp) +{ + p->hdr = s6dns_message_header_zero ; + p->buf = istcp ? buf + 2 : buf ; + p->max = istcp ? max - 2 : max ; + p->pos = 0 ; + p->flagtcp = !!istcp ; +} diff --git a/src/server/shibari_packet_tdb_answer_query.c b/src/server/shibari_packet_tdb_answer_query.c new file mode 100644 index 0000000..a22927f --- /dev/null +++ b/src/server/shibari_packet_tdb_answer_query.c @@ -0,0 +1,93 @@ +/* ISC license. */ + +#include + +#include +#include +#include + +static unsigned int childzone (shibari_packet *pkt, cdb const *tdb, s6dns_domain_t const *q, char const *loc, tain const *stamp, uint16_t nplen, uint16_t zplen) +{ + cdb_find_state state = CDB_FIND_STATE_ZERO ; + unsigned int gr ; + for (;;) + { + shibari_tdb_entry ns ; + int r = shibari_tdb_read_entry(tdb, &state, &ns, q->s + nplen, q->len - nplen, SHIBARI_T_NS, 0, loc, stamp, 0) ; + if (r == -1) return 2 ; + if (!r) break ; + r = shibari_packet_add_rr(pkt, &ns, nplen, 0, 3) ; + if (!r) { pkt->hdr.tc = 1 ; goto end ; } + } + gr = shibari_packet_add_glue(pkt, tdb, q->s + nplen, q->len - nplen, SHIBARI_T_NS, q->s + zplen, q->len - zplen, zplen, 0, loc, stamp) ; + if (gr > 0) return gr ; + end: + shibari_packet_end(pkt) ; + return 0 ; +} + +unsigned int shibari_packet_tdb_answer_query (shibari_packet *pkt, cdb const *tdb, s6dns_message_header_t const *qhdr, s6dns_domain_t const *q, uint16_t qtype, char const *loc, tain const *stamp) +{ + unsigned int rcode = 0 ; + cdb_find_state state = CDB_FIND_STATE_ZERO ; + uint32_t flagyxdomain = 0 ; + int nplen, zplen ; + uint16_t gluetype = 0 ; + uint16_t wildpos = 0 ; + + shibari_packet_begin(pkt, qhdr->id, q, qtype) ; + pkt->hdr.rd = qhdr->rd ; + zplen = shibari_tdb_find_authority(tdb, q->s, q->len, loc, stamp, &nplen) ; + switch (zplen) + { + case -2 : return 9 ; + case -1 : return 2 ; + default : break ; + } + if (nplen >= 0 && nplen < zplen) + return childzone(pkt, tdb, q, loc, stamp, nplen, zplen) ; + + pkt->hdr.aa = 1 ; /* we're in the zone, man */ + + while (wildpos <= zplen) + { + for (;;) + { + shibari_tdb_entry entry ; + int r = shibari_tdb_read_entry(tdb, &state, &entry, q->s + wildpos, q->len + wildpos, qtype, !!wildpos, loc, stamp, &flagyxdomain) ; + if (r == -1) return 2 ; + if (!r) break ; + if (!shibari_packet_add_rr(pkt, &entry, 0, 0, 2)) + { + pkt->hdr.tc = 1 ; + return 0 ; + } + switch (entry.type) + { + case SHIBARI_T_NS : + case SHIBARI_T_MX : + case SHIBARI_T_CNAME : /* we're not supposed to but meh */ + gluetype = entry.type ; + default : break ; + } + } + if (pkt->hdr.counts.an) break ; + wildpos += 1 + q->s[wildpos] ; + } + + if (!flagyxdomain) pkt->hdr.rcode = 3 ; + + if (!pkt->hdr.counts.an) + { + unsigned int r = shibari_packet_assert_authority(pkt, tdb, q->s + zplen, q->len - zplen, zplen, loc, stamp) ; + if (r) return r ; + } + else if (gluetype) + { + unsigned int r = shibari_packet_add_glue(pkt, tdb, q->s, q->len, gluetype, q->s + zplen, q->len - zplen, zplen, wildpos, loc, stamp) ; + if (r) return r ; + } + + shibari_packet_end(pkt) ; + return rcode ; +} diff --git a/src/server/shibari_tdb_entry_parse.c b/src/server/shibari_tdb_entry_parse.c new file mode 100644 index 0000000..61f076f --- /dev/null +++ b/src/server/shibari_tdb_entry_parse.c @@ -0,0 +1,56 @@ +/* ISC license. */ + +#include + +#include +#include +#include + +#include +#include + +int shibari_tdb_entry_parse (shibari_tdb_entry *out, char const *s, uint16_t len, uint16_t qtype, unsigned int wild, char const *loc, tain const *stamp) +{ + tai ttd ; + uint32_t ttl ; + uint32_t flags = 0 ; + uint16_t type ; + if (len < 15) return -1 ; + uint16_unpack_big(s, &type) ; + if (qtype != SHIBARI_T_ANY && qtype != type && type != SHIBARI_T_CNAME) return 0 ; + s += 3 ; len -= 3 ; + switch (s[-1]) + { + case '+' : flags |= 1 ; + case '>' : + if (len < 14) return -1 ; + if (loc && loc[0] && (loc[0] != s[0] || loc[1] != s[1])) return 0 ; + s += 2 ; len -= 2 ; + break ; + case '*' : flags |= 1 ; + case '=' : break ; + default : return -1 ; + } + if (wild < 2 && wild != (flags & 1)) return 0 ; + uint32_unpack_big(s, &ttl) ; + s += 4 ; len -= 4 ; + tai_unpack(s, &ttd) ; + s += 8 ; len -= 8 ; + if (tai_sec(&ttd)) + { + if (!ttl == !tai_less(tain_secp(stamp), &ttd)) return 0 ; + if (!ttl) + { + tai t ; + tai_sub(&t, &ttd, tain_secp(stamp)) ; + if (tai_sec(&t) < 2) ttl = 2 ; + else if (tai_sec(&t) > 3600 && qtype != SHIBARI_T_ANY) ttl = 3600 ; + } + } + out->ttl = ttl ; + out->flags = flags ; + out->type = type ; + out->data.s = s ; + out->data.len = len ; + return 1 ; +} diff --git a/src/server/shibari_tdb_extract_domain.c b/src/server/shibari_tdb_extract_domain.c new file mode 100644 index 0000000..dfa6009 --- /dev/null +++ b/src/server/shibari_tdb_extract_domain.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include +#include + +int shibari_tdb_extract_domain (shibari_tdb_entry const *entry, cdb_data *domain) +{ + switch (entry->type) + { + case SHIBARI_T_CNAME : + case SHIBARI_T_NS : + *domain = entry->data ; break ; + case SHIBARI_T_MX : domain->s = entry->data.s + 2 ; domain->len = entry->data.len - 2 ; break ; + default : return 0 ; + } + return 1 ; +} diff --git a/src/server/shibari_tdb_find_authority.c b/src/server/shibari_tdb_find_authority.c new file mode 100644 index 0000000..5550f52 --- /dev/null +++ b/src/server/shibari_tdb_find_authority.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include + +#include + +#include +#include + +static int find_ns_and_soa (cdb const *tdb, char const *s, uint16_t len, char const *loc, tain const *stamp) +{ + cdb_find_state state = CDB_FIND_STATE_ZERO ; + unsigned int flags = 0 ; + for (;;) + { + shibari_tdb_entry entry ; + cdb_data data ; + int r = cdb_findnext(tdb, &data, s, len, &state) ; + if (r == -1) return -1 ; + if (!r) break ; + r = shibari_tdb_entry_parse(&entry, data.s, data.len, SHIBARI_T_ANY, 0, loc, stamp) ; + if (r == -1) return -1 ; + if (!r) continue ; + if (entry.type == SHIBARI_T_SOA) flags |= 1 ; + else if (entry.type == SHIBARI_T_NS) flags |= 2 ; + } + return flags ; +} + +int shibari_tdb_find_authority (cdb const *tdb, char const *s, uint16_t len, char const *loc, tain const *stamp, int *npl) +{ + uint16_t pos = 0 ; + uint16_t zplen = 0 ; + int nplen = -1 ; + while (pos < len) + { + int flags = find_ns_and_soa(tdb, s + pos, len - pos, loc, stamp) ; + if (flags == -1) return -1 ; + if (flags & 2) nplen = pos ; + if (flags & 1) { zplen = pos ; break ; } + pos += 1 + (uint8_t)s[pos] ; + } + if (pos >= len) return -2 ; /* out of bailiwick */ + *npl = nplen ; + return zplen ; +} diff --git a/src/server/shibari_tdb_read_entry.c b/src/server/shibari_tdb_read_entry.c new file mode 100644 index 0000000..b2d877c --- /dev/null +++ b/src/server/shibari_tdb_read_entry.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include + +#include + +int shibari_tdb_read_entry (cdb const *tdb, cdb_find_state *state, shibari_tdb_entry *out, char const *s, uint16_t len, uint16_t qtype, unsigned int wild, char const *loc, tain const *stamp, uint32_t *flags) +{ + cdb_data data ; + int r = 0 ; + while (!r) + { + r = cdb_findnext(tdb, &data, s, len, state) ; + if (r <= 0) return r ; + if (flags) *flags |= 1 ; + r = shibari_tdb_entry_parse(out, data.s, data.len, qtype, wild, loc, stamp) ; + if (r == -1) return -1 ; + } + out->key.s = s ; + out->key.len = len ; + return 1 ; +} diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..27e5b3e --- /dev/null +++ b/tools/gen-deps.sh @@ -0,0 +1,93 @@ +#!/bin/sh -e + +. package/info + +echo '#' +echo '# This file has been generated by tools/gen-deps.sh' +echo '#' +echo + +for dir in src/include/${package} src/* ; do + for file in $(ls -1 $dir | grep -- \\.h$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps= + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + if test -n "$deps" ; then + echo "${dir}/${file}:${deps}" + fi + } + done +done + +for dir in src/* ; do + for file in $(ls -1 $dir | grep -- \\.c$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps=" ${dir}/$file" + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + o=$(echo $file | sed s/\\.c$/.o/) + lo=$(echo $file | sed s/\\.c$/.lo/) + echo "${dir}/${o} ${dir}/${lo}:${deps}" + } + done +done +echo + +for dir in $(ls -1 src | grep -v ^include) ; do + for file in $(ls -1 src/$dir/deps-lib) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps src/$dir/$dep" + fi + done < src/$dir/deps-lib/$file + echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' + echo "lib${file}.a.xyzzy:$deps" + echo else + echo "lib${file}.a.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + echo endif + echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" + echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + done + + for file in $(ls -1 src/$dir/deps-exe) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -- \\.o$ ; then + dep="src/$dir/$dep" + fi + if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps $dep" + fi + done < src/$dir/deps-exe/$file + echo "$file: EXTRA_LIBS :=$libs" + echo "$file: src/$dir/$file.o$deps" + done +done diff --git a/tools/install.sh b/tools/install.sh new file mode 100755 index 0000000..89f9428 --- /dev/null +++ b/tools/install.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +usage() { + echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 + exit 1 +} + +mkdirp=false +symlink=false +mode=0755 + +while getopts Dlm: name ; do + case "$name" in + D) mkdirp=true ;; + l) symlink=true ;; + m) mode=$OPTARG ;; + ?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +test "$#" -eq 2 || usage +src=$1 +dst=$2 +tmp="$dst.tmp.$$" + +case "$dst" in + */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; +esac + +set -C +set -e + +if $mkdirp ; then + umask 022 + case "$2" in + */*) mkdir -p "${dst%/*}" ;; + esac +fi + +trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP + +umask 077 + +if $symlink ; then + ln -s "$src" "$tmp" +else + cat < "$1" > "$tmp" + chmod "$mode" "$tmp" +fi + +mv -f "$tmp" "$dst" +if test -d "$dst" ; then + rm -f "$dst/$(basename $tmp)" + if $symlink ; then + mkdir "$tmp" + ln -s "$src" "$tmp/$(basename $dst)" + mv -f "$tmp/$(basename $dst)" "${dst%/*}" + rmdir "$tmp" + else + echo "$0: $dst is a directory" 1>&2 + exit 1 + fi +fi -- cgit v1.2.3