diff options
-rw-r--r-- | .dir-locals.el | 8 | ||||
-rw-r--r-- | .gitignore | 33 | ||||
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | README | 47 | ||||
-rwxr-xr-x | autogen.sh | 66 | ||||
-rw-r--r-- | configure.ac | 62 | ||||
-rw-r--r-- | flymake.mk | 12 | ||||
-rw-r--r-- | m4/attributes.m4 | 258 | ||||
-rw-r--r-- | src/Makefile.am | 35 | ||||
-rw-r--r-- | src/nss-dontstalkme.c | 292 | ||||
-rw-r--r-- | src/nss-dontstalkme.h | 0 |
11 files changed, 820 insertions, 0 deletions
diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..7c483d2 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,8 @@ +( + (c-mode . ( + (c-file-style . "K&R") + (indent-tabs-mode . nil) + (c-indent-level . 4) + (c-basic-offset . 4) + )) + ) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb54e44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +aclocal.m4 +config.guess +config.h +config.h.in +config.log +config.status +config.sub +config.rpath +configure +compile +depcomp +install-sh +ltmain.sh +libtool +missing +nss-dontstalkme-*.tar.gz +nss-dontstalkme-*.tar.xz +Makefile +Makefile.in +run +stamp-* +TAGS +*.la +*.lo +*.log +*.o +*~ +.deps/ +.libs/ +autom4te.cache/ +build-aux/ +m4/libtool*.m4 +m4/lt*.m4 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..15ed2d4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = src + +ACLOCAL_AMFLAGS = -I m4 + +EXTRA_DIST = \ + flymake.mk \ + $(NULL) @@ -0,0 +1,47 @@ +# -*- mode: markdown; -*- + +Overview +-------- +nss-dontstalk me is a nsswitch module that maps host lookups of well known web +trackers to localhost so they become uneffective. + +The idea is to have the same black lists available regardless of the browser/application used. + +While doing this via /etc/host would be possible there's no /etc/hosts.d mechanism to +keep the changes separate. Also maintaining this for ipv4 and ipv6 can be cumbersome. + +Compiling +--------- +nss-dontstalkme uses autotools to build the package: + + ./autogen.sh + ./configure --prefix=/usr + make + +Installation +------------ +Make sure libnss-dontstalkme.so.2 is in your libraries load path +either installing it into the filesystem + + make install + +or, if you want to run from the built source, by setting LD_LIBRARY_PATH + + LD_LIBRARY_PATH=$PWD/src/.libs + +Afterwards add dontstalkme to the hosts entry of /etc/nsswitch.conf e.g. change + + hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns mdns4n + +to + + hosts: files myhostname mdns4_minimal [NOTFOUND=return] dontstalkme dns mdns4 + +It's important to add the `dontstalkme` entry before the `dns` entry. + +Testing +------- +You can test the basic functionality by running + + LD_LIBRARY_PATH=$PWD/src/.libs/ getent ahostsv4 google-analytics.com + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..d224f31 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# This file is part of nss-myhostname. +# +# Copyright 2008 Lennart Poettering +# +# nss-myhostname is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 2.1 of +# the License, or (at your option) any later version. +# +# nss-myhostname is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with nss-myhostname. If not, If not, see +# <http://www.gnu.org/licenses/>. + +VERSION=1.9 + +run_versioned() { + local P + local V + + V=$(echo "$2" | sed -e 's,\.,,g') + + if [ -e "`which $1$V 2> /dev/null`" ] ; then + P="$1$V" + else + if [ -e "`which $1-$2 2> /dev/null`" ] ; then + P="$1-$2" + else + P="$1" + fi + fi + + shift 2 + "$P" "$@" +} + +set -ex + +if [ "x$1" = "xam" ] ; then + run_versioned automake "$VERSION" -a -c --foreign + ./config.status +else + rm -rf autom4te.cache + rm -f config.cache + + touch config.rpath + test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize + + mkdir -p m4 + "$LIBTOOLIZE" -c --force + run_versioned aclocal "$VERSION" -I m4 + run_versioned autoconf 2.59 -Wall + run_versioned autoheader 2.59 + run_versioned automake "$VERSION" --copy --foreign --add-missing + + if test "x$NOCONFIGURE" = "x"; then + CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var "$@" + make clean + fi +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..59dd21b --- /dev/null +++ b/configure.ac @@ -0,0 +1,62 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +# Copyright 2014 Guido Günther <agx@sigxcpu.org> +# +# nss-myhostname is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 2.1 of +# the License, or (at your option) any later version. +# +# nss-dontstalkme is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with nss-dontstalkme. If not, If not, see +# <http://www.gnu.org/licenses/>. +# +# Based on configure.ac from libnss-myhostname + +AC_PREREQ(2.62) +AC_INIT([nss-dontstalkme],[0.0]) +AC_CONFIG_SRCDIR([src/nss-dontstalkme.c]) +dnl Make automake keep quiet about wildcards & other GNUmake-isms +AM_INIT_AUTOMAKE([1.11.1 no-dist-gzip dist-xz -Wno-portability]) +AC_CONFIG_HEADERS([config.h]) +AC_SYS_LARGEFILE + +AM_PROG_CC_C_O +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET + +# libtool stuff +AC_DISABLE_STATIC +LT_PREREQ(2.2) +LT_INIT + +# GCC flags +DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math -fvisibility=hidden -fdiagnostics-show-option" + +for flag in $DESIRED_FLAGS ; do + CC_CHECK_CFLAGS([$flag], [CFLAGS="$CFLAGS $flag"]) +done + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([nss.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_HEADER_TIME + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([gethostbyname]) + +AC_CONFIG_FILES([Makefile src/Makefile]) + +AC_OUTPUT diff --git a/flymake.mk b/flymake.mk new file mode 100644 index 0000000..8228150 --- /dev/null +++ b/flymake.mk @@ -0,0 +1,12 @@ +get_cs_flags = $(foreach target,$(subst .,_,$(subst -,_,$($(2)))),$($(target)_$(1)FLAGS)) +get_cs_all_flags = $(foreach type,$(2),$(call get_cs_flags,$(1),$(type))) +get_cs_compile = $(if $(subst C,,$(1)),$($(1)COMPILE),$(COMPILE)) +get_cs_cmdline = $(call get_cs_compile,$(1)) $(call get_cs_all_flags,$(1),check_PROGRAMS bin_PROGRAMS lib_LTLIBRARIES) -fsyntax-only + +check-syntax: + s=$(suffix $(CHK_SOURCES));\ + if [ "$$s" = ".c" ]; then $(call get_cs_cmdline,C) $(CHK_SOURCES);\ + elif [ "$$s" = ".cpp" ]; then $(call get_cs_cmdline,CXX) $(CHK_SOURCES);\ + else exit 1; fi + +PHONY: check-syntax diff --git a/m4/attributes.m4 b/m4/attributes.m4 new file mode 100644 index 0000000..9c4a0c8 --- /dev/null +++ b/m4/attributes.m4 @@ -0,0 +1,258 @@ +dnl Macros to check the presence of generic (non-typed) symbols. +dnl Copyright (c) 2006-2007 Diego Pettenò <flameeyes@gmail.com> +dnl Copyright (c) 2006-2007 xine project +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +dnl 02110-1301, USA. +dnl +dnl As a special exception, the copyright owners of the +dnl macro gives unlimited permission to copy, distribute and modify the +dnl configure scripts that are the output of Autoconf when processing the +dnl Macro. You need not follow the terms of the GNU General Public +dnl License when using or distributing such scripts, even though portions +dnl of the text of the Macro appear in them. The GNU General Public +dnl License (GPL) does govern all other use of the material that +dnl constitutes the Autoconf Macro. +dnl +dnl This special exception to the GPL applies to versions of the +dnl Autoconf Macro released by this project. When you make and +dnl distribute a modified version of the Autoconf Macro, you may extend +dnl this special exception to the GPL to apply to your modified version as +dnl well. + +AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ + AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_COMPILE_IFELSE([int a;], + [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +AC_DEFUN([CC_CHECK_CFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_cflags_$1]), + CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! + ) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +AC_DEFUN([CC_CHECK_LDFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_ldflags_$1]), + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" + AC_LINK_IFELSE([int main() { return 1; }], + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) + LDFLAGS="$ac_save_LDFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl Check for a -Werror flag or equivalent. -Werror is the GCC +dnl and ICC flag that tells the compiler to treat all the warnings +dnl as fatal. We usually need this option to make sure that some +dnl constructs (like attributes) are not simply ignored. +dnl +dnl Other compilers don't support -Werror per se, but they support +dnl an equivalent flag: +dnl - Sun Studio compiler supports -errwarn=%all +AC_DEFUN([CC_CHECK_WERROR], [ + AC_CACHE_CHECK( + [for $CC way to treat warnings as errors], + [cc_cv_werror], + [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], + [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) + ]) +]) + +AC_DEFUN([CC_CHECK_ATTRIBUTE], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], + AS_TR_SH([cc_cv_attribute_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE([$3], + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], + [AC_DEFINE( + AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, + [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] + ) + $4], + [$5]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ + CC_CHECK_ATTRIBUTE( + [constructor],, + [void __attribute__((constructor)) ctor() { int a; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ + CC_CHECK_ATTRIBUTE( + [format], [format(printf, n, n)], + [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ + CC_CHECK_ATTRIBUTE( + [format_arg], [format_arg(printf)], + [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ + CC_CHECK_ATTRIBUTE( + [visibility_$1], [visibility("$1")], + [void __attribute__((visibility("$1"))) $1_function() { }], + [$2], [$3]) +]) + +AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ + CC_CHECK_ATTRIBUTE( + [nonnull], [nonnull()], + [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ + CC_CHECK_ATTRIBUTE( + [unused], , + [void some_function(void *foo, __attribute__((unused)) void *bar);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ + CC_CHECK_ATTRIBUTE( + [sentinel], , + [void some_function(void *foo, ...) __attribute__((sentinel));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ + CC_CHECK_ATTRIBUTE( + [deprecated], , + [void some_function(void *foo, ...) __attribute__((deprecated));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ + CC_CHECK_ATTRIBUTE( + [alias], [weak, alias], + [void other_function(void *foo) { } + void some_function(void *foo) __attribute__((weak, alias("other_function")));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ + CC_CHECK_ATTRIBUTE( + [malloc], , + [void * __attribute__((malloc)) my_alloc(int n);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_PACKED], [ + CC_CHECK_ATTRIBUTE( + [packed], , + [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONST], [ + CC_CHECK_ATTRIBUTE( + [const], , + [int __attribute__((const)) twopow(int n) { return 1 << n; } ], + [$1], [$2]) +]) + +AC_DEFUN([CC_FLAG_VISIBILITY], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], + [cc_cv_flag_visibility], + [cc_flag_visibility_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], + cc_cv_flag_visibility='yes', + cc_cv_flag_visibility='no') + CFLAGS="$cc_flag_visibility_save_CFLAGS"]) + + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, + [Define this if the compiler supports the -fvisibility flag]) + $1], + [$2]) +]) + +AC_DEFUN([CC_FUNC_EXPECT], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if compiler has __builtin_expect function], + [cc_cv_func_expect], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE( + [int some_function() { + int a = 3; + return (int)__builtin_expect(a, 3); + }], + [cc_cv_func_expect=yes], + [cc_cv_func_expect=no]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([test "x$cc_cv_func_expect" = "xyes"], + [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, + [Define this if the compiler supports __builtin_expect() function]) + $1], + [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], + [cc_cv_attribute_aligned], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + for cc_attribute_align_try in 64 32 16 8 4 2; do + AC_COMPILE_IFELSE([ + int main() { + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; + return c; + }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) + done + CFLAGS="$ac_save_CFLAGS" + ]) + + if test "x$cc_cv_attribute_aligned" != "x"; then + AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], + [Define the highest alignment supported]) + fi +]) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..840bffc --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,35 @@ +# This file is part of nss-dontstalkme. +# +# Copyright 2014 Guido Günther +# +# nss-dontstalkme is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 2.1 of +# the License, or (at your option) any later version. +# +# nss-dontstalkme is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with nss-dontstalkme. If not, If not, see +# <http://www.gnu.org/licenses/>. + +include $(top_srcdir)/flymake.mk + +ACLOCAL_AMFLAGS = -I m4 + +lib_LTLIBRARIES = libnss_dontstalkme.la + +AM_CPPFLAGS = -include $(top_builddir)/config.h + +libnss_dontstalkme_la_SOURCES = \ + nss-dontstalkme.c + +libnss_dontstalkme_la_LDFLAGS = \ + -avoid-version \ + -module \ + -export-dynamic \ + -shrext .so.2 + diff --git a/src/nss-dontstalkme.c b/src/nss-dontstalkme.c new file mode 100644 index 0000000..39bf34b --- /dev/null +++ b/src/nss-dontstalkme.c @@ -0,0 +1,292 @@ +/* + * nss-dontstalkme: Return localhost for tracking host IPs + * + * Copyright (C) 2014 Guido Günther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Guido Günther <agx@sigxcpu.org> + * + * Heavily inspired by nss-myhostname.c which is + * Copyright 2008-2011 Lennart Poettering + */ + +#include <assert.h> +#include <nss.h> +#include <limits.h> +#include <string.h> +#include <sys/types.h> +#include <netdb.h> +#include <errno.h> +#include <net/if.h> + +/* We use 127.0.2.1 as returned address */ +#define LOCALADDRESS_IPV4 (htonl(0x7F000201)) +#define LOCALADDRESS_IPV6 &in6addr_loopback +#define LOOPBACK_INTERFACE "lo" + +#define ALIGN(a) (((a+sizeof(void*)-1)/sizeof(void*))*sizeof(void*)) +#define _public_ __attribute__ ((visibility("default"))) +#define ARRAY_CARDINALITY(Array) (sizeof(Array) / sizeof(*(Array))) + +/* The hosts we blacklist */ +const char* stalkers[] = { "www.google-analytics.com", + "ssl.google-analytics.com", + }; + +enum nss_status _nss_dontstalkme_gethostbyname4_r(const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) _public_; + +enum nss_status _nss_dontstalkme_gethostbyname3_r(const char *name, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) _public_; + +enum nss_status _nss_dontstalkme_gethostbyname2_r(const char *name, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop) _public_; + +enum nss_status _nss_dontstalkme_gethostbyname_r(const char *name, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop) _public_; + + +enum nss_status +_nss_dontstalkme_gethostbyname4_r(const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) +{ + unsigned lo_ifi; + size_t l, idx, ms; + char *r_name; + unsigned int i; + struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; + + lo_ifi = if_nametoindex(LOOPBACK_INTERFACE); + + for (i = 0; i < ARRAY_CARDINALITY(stalkers); i++) { + if (!strcasecmp(stalkers[i], name)) { + break; + } + } + if (i == ARRAY_CARDINALITY(stalkers)) { + *errnop = ENOENT; + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + l = strlen(name); + ms = ALIGN(l+1)+ALIGN(sizeof(struct gaih_addrtuple))*2; + if (buflen < ms) { + *errnop = ENOMEM; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_TRYAGAIN; + } + + /* First, fill in hostname */ + r_name = buffer; + l = strlen(name); + memcpy(r_name, name, l+1); + idx = ALIGN(l+1); + + /* Second, fill in IPv6 tuple */ + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = r_tuple_prev; + r_tuple->name = r_name; + r_tuple->family = AF_INET6; + memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); + r_tuple->scopeid = (uint32_t) lo_ifi; + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + r_tuple_prev = r_tuple; + + /* Third, fill in IPv4 tuple */ + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = r_tuple_prev; + r_tuple->name = r_name; + r_tuple->family = AF_INET; + *(uint32_t*) r_tuple->addr = LOCALADDRESS_IPV4; + r_tuple->scopeid = (uint32_t) lo_ifi; + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + r_tuple_prev = r_tuple; + + /* Verify the size matches */ + assert(idx == ms); + + *pat = r_tuple_prev; + + if (ttlp) + *ttlp = 0; + + return NSS_STATUS_SUCCESS; +} + +static inline size_t +proto_address_size(int proto) +{ + assert(proto == AF_INET || proto == AF_INET6); + return proto == AF_INET6 ? 16 : 4; +} + +static enum nss_status +fill_in_hostent(const char *hn, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) +{ + + size_t l, idx, ms; + char *r_addr, *r_name, *r_aliases, *r_addr_list; + size_t alen; + + alen = proto_address_size(af); + + l = strlen(hn); + ms = ALIGN(l+1)+ + sizeof(char*)+ + ALIGN(alen)+ + 2*sizeof(char*); + + if (buflen < ms) { + *errnop = ENOMEM; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_TRYAGAIN; + } + + /* First, fill in hostname */ + r_name = buffer; + memcpy(r_name, hn, l+1); + idx = ALIGN(l+1); + + /* Second, create (empty) aliases array */ + r_aliases = buffer + idx; + *(char**) r_aliases = NULL; + idx += sizeof(char*); + + /* Third, add addresses */ + r_addr = buffer + idx; + if (af == AF_INET) + *(uint32_t*) r_addr = LOCALADDRESS_IPV4; + else + memcpy(r_addr, LOCALADDRESS_IPV6, 16); + + idx += ALIGN(alen); + + /* Fourth, add address pointer array */ + r_addr_list = buffer + idx; + ((char**) r_addr_list)[0] = r_addr; + ((char**) r_addr_list)[1] = NULL; + idx += 2*sizeof(char*); + + /* Verify the size matches */ + assert(idx == ms); + + result->h_name = r_name; + result->h_aliases = (char**) r_aliases; + result->h_addrtype = af; + result->h_length = alen; + result->h_addr_list = (char**) r_addr_list; + + if (ttlp) + *ttlp = 0; + + if (canonp) + *canonp = r_name; + + return NSS_STATUS_SUCCESS; +} + + +enum nss_status +_nss_dontstalkme_gethostbyname3_r(const char *name, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) +{ + unsigned int i; + + if (af == AF_UNSPEC) + af = AF_INET; + + if (af != AF_INET && af != AF_INET6) { + *errnop = EAFNOSUPPORT; + *h_errnop = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + for (i = 0; i < ARRAY_CARDINALITY(stalkers); i++) { + if (!strcasecmp(stalkers[i], name)) { + break; + } + } + if (i == ARRAY_CARDINALITY(stalkers)) { + *errnop = ENOENT; + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + return fill_in_hostent(name, af, host, buffer, buflen, errnop, h_errnop, ttlp, canonp); +} + + +enum nss_status +_nss_dontstalkme_gethostbyname2_r(const char *name, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop) +{ + return _nss_dontstalkme_gethostbyname3_r(name, + af, + host, + buffer, buflen, + errnop, h_errnop, + NULL, + NULL); +} + + +enum nss_status + _nss_dontstalkme_gethostbyname_r(const char *name, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop) +{ + return _nss_dontstalkme_gethostbyname3_r(name, + AF_UNSPEC, + host, + buffer, buflen, + errnop, h_errnop, + NULL, + NULL); +} diff --git a/src/nss-dontstalkme.h b/src/nss-dontstalkme.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/nss-dontstalkme.h |