From f020c14e4f1eb6b643ff673d0b5c35bc41fd4595 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Apr 2006 23:24:34 +0000 Subject: * implement a "minimal" mode * add configure option to allow building of nss-mdns without legacy mDNS queries git-svn-id: file:///home/lennart/svn/public/nss-mdns/trunk@91 0ee8848e-81ea-0310-a63a-f631d1a40d77 --- configure.ac | 60 +++++++++++++++++++-- doc/Makefile.am | 7 +++ src/Makefile.am | 65 ++++++++++++++++++---- src/nss.c | 164 +++++++++++++++++++++++++++++++++++++------------------- src/util.c | 30 ++++++----- src/util.h | 7 ++- 6 files changed, 252 insertions(+), 81 deletions(-) diff --git a/configure.ac b/configure.ac index 1b7034a..cafaa15 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,32 @@ AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET +test_gcc_flag() { + AC_LANG_CONFTEST([int main() {}]) + $CC -c conftest.c $CFLAGS $@ > /dev/null 2> /dev/null + ret=$? + rm -f conftest.o + return $ret +} + +# If using GCC specify some additional parameters +if test "x$GCC" = "xyes" ; then + + # We use gnu99 instead of c99 because many have interpreted the standard + # in a way that int64_t isn't defined on non-64 bit platforms. + DESIRED_FLAGS="-std=gnu99 -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 -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" + + for flag in $DESIRED_FLAGS ; do + AC_MSG_CHECKING([whether $CC accepts $flag]) + if test_gcc_flag $flag ; then + CFLAGS="$CFLAGS $flag" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + done +fi + # libtool stuff AC_DISABLE_STATIC AC_PROG_LIBTOOL @@ -79,14 +105,23 @@ if test x$lynx = xyes ; then AC_CHECK_PROG(have_lynx, lynx, yes, no) if test x$have_lynx = xno ; then - AC_MSG_WARN([*** lynx not found, plain text README will not be built ***]) + lynx=no + AC_CHECK_PROG(have_links, links, yes, no) + if test x$have_links = xno ; then + AC_MSG_WARN([*** neither lynx nor links found, plain text README will not be built ***]) + else + links=yes + fi fi fi AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) +AM_CONDITIONAL([USE_LINKS], [test "x$links" = xyes]) + +### Enable avahi support? AC_ARG_ENABLE(avahi, - AC_HELP_STRING([--enable-avahi],[use Avahi (default=yes)]), + AC_HELP_STRING([--enable-avahi],[Enable lookups with Avahi (default=yes)]), [case "${enableval}" in yes) ENABLE_AVAHI=yes ;; no) ENABLE_AVAHI=no ;; @@ -94,13 +129,32 @@ AC_ARG_ENABLE(avahi, esac], [ENABLE_AVAHI=yes]) dnl Default value - AM_CONDITIONAL([ENABLE_AVAHI], [test "x$ENABLE_AVAHI" = "xyes"]) if test "x$ENABLE_AVAHI" = "xyes" ; then AC_DEFINE(ENABLE_AVAHI, [1], [Try to make use of a running avahi mDNS server before resolving on our own behalf]) fi +### Enable legacy support? + +AC_ARG_ENABLE(legacy, + AC_HELP_STRING([--enable-legacy],[Enable legacy lookups when Avahi isn't available (default=yes)]), + [case "${enableval}" in + yes) ENABLE_LEGACY=yes ;; + no) ENABLE_LEGACY=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-legacy) ;; + esac], + [ENABLE_LEGACY=yes]) dnl Default value + +if test "x$ENABLE_AVAHI" = "xno" -a "x$ENABLE_LEGACY" = "xno"; then + AC_MSG_ERROR(Can't disable legacy lookups if Avahi support is disabled) +fi + +if test "x$ENABLE_LEGACY" = "xyes" ; then + AC_DEFINE(ENABLE_LEGACY, [1], [Enable legacy lookups when Avahi isn't available]) +fi + +AM_CONDITIONAL([ENABLE_LEGACY], [test "x$ENABLE_LEGACY" = "xyes"]) AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile doc/README.html ]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am index 752b2d6..a122244 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -29,6 +29,13 @@ README: README.html CLEANFILES += README endif +if USE_LINKS +README: README.html + links -dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@ + +CLEANFILES += README +endif + tidy: README.html tidy -qe < README.html ; true diff --git a/src/Makefile.am b/src/Makefile.am index e9d5f91..7633c37 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,38 +27,85 @@ AM_CFLAGS = \ # This cool debug trap works on i386/gcc only AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' -noinst_PROGRAMS = nss-test mdns-test -lib_LTLIBRARIES = libnss_mdns.la libnss_mdns4.la libnss_mdns6.la +lib_LTLIBRARIES= \ + libnss_mdns.la \ + libnss_mdns4.la \ + libnss_mdns6.la \ + libnss_mdns_minimal.la \ + libnss_mdns4_minimal.la \ + libnss_mdns6_minimal.la -mdns_test_SOURCES = query.c dns.c util.c mdns-test.c \ - query.h dns.h util.h +noinst_PROGRAMS= \ + nss-test -nss_test_SOURCES = nss-test.c +libnss_mdns_la_SOURCES= \ + nss.c \ + util.c util.h -libnss_mdns_la_SOURCES = query.c dns.c util.c nss.c query.h dns.h util.h libnss_mdns_la_CFLAGS=$(AM_CFLAGS) libnss_mdns_la_LDFLAGS=-avoid-version -module -export-dynamic -shrext .so.2 if ENABLE_AVAHI +libnss_mdns_la_SOURCES += \ + avahi.c avahi.h + noinst_PROGRAMS += avahi-test -avahi_test_SOURCES = avahi.c util.c avahi.h util.h avahi-test.c -libnss_mdns_la_SOURCES += avahi.c avahi.h endif +if ENABLE_LEGACY +libnss_mdns_la_SOURCES += \ + query.c query.h \ + dns.c dns.h + +noinst_PROGRAMS += mdns-test +endif + +libnss_mdns_minimal_la_SOURCES=$(libnss_mdns_la_SOURCES) +libnss_mdns_minimal_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DMDNS_MINIMAL +libnss_mdns_minimal_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) + libnss_mdns4_la_SOURCES=$(libnss_mdns_la_SOURCES) libnss_mdns4_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DNSS_IPV4_ONLY=1 libnss_mdns4_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) +libnss_mdns4_minimal_la_SOURCES=$(libnss_mdns_la_SOURCES) +libnss_mdns4_minimal_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DNSS_IPV4_ONLY=1 -DMDNS_MINIMAL +libnss_mdns4_minimal_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) + libnss_mdns6_la_SOURCES=$(libnss_mdns_la_SOURCES) libnss_mdns6_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DNSS_IPV6_ONLY=1 libnss_mdns6_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) +libnss_mdns6_minimal_la_SOURCES=$(libnss_mdns_la_SOURCES) +libnss_mdns6_minimal_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DNSS_IPV6_ONLY=1 -DMDNS_MINIMAL +libnss_mdns6_minimal_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) + +avahi_test_SOURCES = \ + avahi.c avahi.h \ + util.c util.h \ + avahi-test.c + +mdns_test_SOURCES = \ + query.c query.h \ + dns.c dns.h \ + util.c util.h \ + mdns-test.c + +nss_test_SOURCES = \ + nss-test.c + install-exec-hook: rm -f $(DESTDIR)$(libdir)/libnss_mdns.la + rm -f $(DESTDIR)$(libdir)/libnss_mdns_minimal.la rm -f $(DESTDIR)$(libdir)/libnss_mdns4.la + rm -f $(DESTDIR)$(libdir)/libnss_mdns4_minimal.la rm -f $(DESTDIR)$(libdir)/libnss_mdns6.la + rm -f $(DESTDIR)$(libdir)/libnss_mdns6_minimal.la uninstall-hook: rm -f $(DESTDIR)$(libdir)/libnss_mdns.so.2 + rm -f $(DESTDIR)$(libdir)/libnss_mdns_minimal.so.2 rm -f $(DESTDIR)$(libdir)/libnss_mdns4.so.2 - rm -f $(DESTDIR)$(libdir)/libnss_mdns6.so.2 + rm -f $(DESTDIR)$(libdir)/libnss_mdns4_minimal.so.2 + rm -f $(DESTDIR)$(libdir)/libnss_mdns6.so.2 + rm -f $(DESTDIR)$(libdir)/libnss_mdns6_minimal.so.2 diff --git a/src/nss.c b/src/nss.c index 5b5579a..50e710c 100644 --- a/src/nss.c +++ b/src/nss.c @@ -39,19 +39,32 @@ #include "avahi.h" #endif -#define MAX_ENTRIES 16 - -#ifdef NSS_IPV4_ONLY +#if defined(NSS_IPV4_ONLY) && ! defined(MDNS_MINIMAL) #define _nss_mdns_gethostbyname2_r _nss_mdns4_gethostbyname2_r -#define _nss_mdns_gethostbyname_r _nss_mdns4_gethostbyname_r -#define _nss_mdns_gethostbyaddr_r _nss_mdns4_gethostbyaddr_r -#elif NSS_IPV6_ONLY +#define _nss_mdns_gethostbyname_r _nss_mdns4_gethostbyname_r +#define _nss_mdns_gethostbyaddr_r _nss_mdns4_gethostbyaddr_r +#elif defined(NSS_IPV4_ONLY) && defined(MDNS_MINIMAL) +#define _nss_mdns_gethostbyname2_r _nss_mdns4_minimal_gethostbyname2_r +#define _nss_mdns_gethostbyname_r _nss_mdns4_minimal_gethostbyname_r +#define _nss_mdns_gethostbyaddr_r _nss_mdns4_minimal_gethostbyaddr_r +#elif defined(NSS_IPV6_ONLY) && ! defined(MDNS_MINIMAL) #define _nss_mdns_gethostbyname2_r _nss_mdns6_gethostbyname2_r -#define _nss_mdns_gethostbyname_r _nss_mdns6_gethostbyname_r -#define _nss_mdns_gethostbyaddr_r _nss_mdns6_gethostbyaddr_r +#define _nss_mdns_gethostbyname_r _nss_mdns6_gethostbyname_r +#define _nss_mdns_gethostbyaddr_r _nss_mdns6_gethostbyaddr_r +#elif defined(NSS_IPV6_ONLY) && defined(MDNS_MINIMAL) +#define _nss_mdns_gethostbyname2_r _nss_mdns6_minimal_gethostbyname2_r +#define _nss_mdns_gethostbyname_r _nss_mdns6_minimal_gethostbyname_r +#define _nss_mdns_gethostbyaddr_r _nss_mdns6_minimal_gethostbyaddr_r +#elif defined(MDNS_MINIMAL) +#define _nss_mdns_gethostbyname2_r _nss_mdns_minimal_gethostbyname2_r +#define _nss_mdns_gethostbyname_r _nss_mdns_minimal_gethostbyname_r +#define _nss_mdns_gethostbyaddr_r _nss_mdns_minimal_gethostbyaddr_r #endif -/* the resolv conf page states that they only support 6 domains */ +/* Maximum number of entries to return */ +#define MAX_ENTRIES 16 + +/* The resolv.conf page states that they only support 6 domains */ #define MAX_SEARCH_DOMAINS 6 struct userdata { @@ -113,44 +126,50 @@ static int ends_with(const char *name, const char* suffix) { } static int verify_name_allowed(const char *name) { +#ifndef MDNS_MINIMAL FILE *f; - int valid = 0; +#endif assert(name); - if (!(f = fopen(MDNS_ALLOW_FILE, "r"))) - return ends_with(name, ".local") || ends_with(name, ".local."); - - while (!feof(f)) { - char ln[128], ln2[128], *t; +#ifndef MDNS_MINIMAL + if ((f = fopen(MDNS_ALLOW_FILE, "r"))) { + int valid = 0; - if (!fgets(ln, sizeof(ln), f)) - break; - - ln[strcspn(ln, "#\t\n\r ")] = 0; - - if (ln[0] == 0) - continue; - - if (strcmp(ln, "*") == 0) { - valid = 1; - break; - } - - if (ln[0] != '.') - snprintf(t = ln2, sizeof(ln2), ".%s", ln); - else - t = ln; - - if (ends_with(name, t)) { - valid = 1; - break; + + while (!feof(f)) { + char ln[128], ln2[128], *t; + + if (!fgets(ln, sizeof(ln), f)) + break; + + ln[strcspn(ln, "#\t\n\r ")] = 0; + + if (ln[0] == 0) + continue; + + if (strcmp(ln, "*") == 0) { + valid = 1; + break; + } + + if (ln[0] != '.') + snprintf(t = ln2, sizeof(ln2), ".%s", ln); + else + t = ln; + + if (ends_with(name, t)) { + valid = 1; + break; + } } + + fclose(f); + return valid; } +#endif - fclose(f); - - return valid; + return ends_with(name, ".local") || ends_with(name, ".local."); } static char **alloc_domains(unsigned ndomains) { @@ -268,7 +287,7 @@ enum nss_status _nss_mdns_gethostbyname2_r( struct userdata u; enum nss_status status = NSS_STATUS_UNAVAIL; - int fd = -1, i; + int i; size_t address_length, l, idx, astart; void (*ipv4_func)(const ipv4_address_t *ipv4, void *userdata); void (*ipv6_func)(const ipv6_address_t *ipv6, void *userdata); @@ -279,6 +298,10 @@ enum nss_status _nss_mdns_gethostbyname2_r( uint8_t data[128]; #endif +#ifdef ENABLE_LEGACY + int fd = -1; +#endif + /* DEBUG_TRAP; */ #ifdef NSS_IPV4_ONLY @@ -381,11 +404,14 @@ enum nss_status _nss_mdns_gethostbyname2_r( free_domains(domains); } } +#endif - - if (u.count == 0 && !avahi_works) { +#if defined(ENABLE_LEGACY) && defined(ENABLE_AVAHI) + if (u.count == 0 && !avahi_works) #endif +#if defined(ENABLE_LEGACY) + { if ((fd = mdns_open_socket()) < 0) { *errnop = errno; *h_errnop = NO_RECOVERY; @@ -432,14 +458,13 @@ enum nss_status _nss_mdns_gethostbyname2_r( free_domains(domains); } } - -#ifdef ENABLE_AVAHI } #endif if (u.count == 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; + status = NSS_STATUS_NOTFOUND; goto finish; } @@ -483,8 +508,10 @@ enum nss_status _nss_mdns_gethostbyname2_r( status = NSS_STATUS_SUCCESS; finish: +#ifdef ENABLE_LEGACY if (fd >= 0) close(fd); +#endif return status; } @@ -523,18 +550,23 @@ enum nss_status _nss_mdns_gethostbyaddr_r( struct userdata u; enum nss_status status = NSS_STATUS_UNAVAIL; - int fd = -1, r; + int r; size_t address_length, idx, astart; + #ifdef ENABLE_AVAHI char t[256]; #endif +#ifdef ENABLE_LEGACY + int fd = -1; +#endif *errnop = EINVAL; *h_errnop = NO_RECOVERY; u.count = 0; u.data_len = 0; - + + /* Check for address types */ address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t); if (len != (int) address_length || @@ -551,6 +583,7 @@ enum nss_status _nss_mdns_gethostbyaddr_r( goto finish; } + /* Check for buffer space */ if (buflen < sizeof(char*)+ /* alias names */ address_length) { /* address */ @@ -562,27 +595,45 @@ enum nss_status _nss_mdns_gethostbyaddr_r( goto finish; } -#ifdef ENABLE_AVAHI +#ifdef MDNS_MINIMAL + /* Only query for 169.254.0.0/16 IPv4 in minimal mode */ + if ((af == AF_INET && ((*(uint32_t*) &addr) & 0xFFFF0000UL) != 0xA9FE0000UL) || + (af == AF_INET6 && !(((uint8_t*) &addr)[0] == 0xFE && (((uint8_t*) &addr)[1] >> 6) == 2))) { + + *errnop = EINVAL; + *h_errnop = NO_RECOVERY; + goto finish; + } +#endif + +#ifdef ENABLE_AVAHI + /* Lookup using Avahi */ if ((r = avahi_resolve_address(af, addr, t, sizeof(t))) == 0) { name_callback(t, &u); } else if (r > 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; + status = NSS_STATUS_NOTFOUND; goto finish; - } - -#endif - - if (u.count == 0) { + } +#endif +#if defined(ENABLE_AVAHI) && defined(ENABLE_LEGACY) + else +#endif + +#ifdef ENABLE_LEGACY + /* Lookup using legacy mDNS queries */ + { if ((fd = mdns_open_socket()) < 0) { - *errnop = errno; *h_errnop = NO_RECOVERY; goto finish; } - + + r = -1; + #if ! defined(NSS_IPV6_ONLY) && ! defined(NSS_IPV4_ONLY) if (af == AF_INET) #endif @@ -595,13 +646,14 @@ enum nss_status _nss_mdns_gethostbyaddr_r( #ifndef NSS_IPV4_ONLY r = mdns_query_ipv6(fd, (const ipv6_address_t*) addr, name_callback, &u); #endif - if (r < 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; + status = NSS_STATUS_NOTFOUND; goto finish; } } +#endif /* ENABLE_LEGACY */ /* Alias names */ *((char**) buffer) = NULL; @@ -642,8 +694,10 @@ enum nss_status _nss_mdns_gethostbyaddr_r( status = NSS_STATUS_SUCCESS; finish: +#ifdef ENABLE_LEGACY if (fd >= 0) close(fd); +#endif return status; } diff --git a/src/util.c b/src/util.c index bf37711..1d0cd90 100644 --- a/src/util.c +++ b/src/util.c @@ -31,6 +31,8 @@ #include "util.h" +#ifdef ENABLE_LEGACY + /* Calculate the difference between the two specfified timeval * timestamsps. */ usec_t timeval_diff(const struct timeval *a, const struct timeval *b) { @@ -102,19 +104,6 @@ void timeval_add(struct timeval *tv, usec_t v) { } } -int set_cloexec(int fd) { - int n; - assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFD)) < 0) - return -1; - - if (n & FD_CLOEXEC) - return 0; - - return fcntl(fd, F_SETFD, n|FD_CLOEXEC); -} - int set_nonblock(int fd) { int n; assert(fd >= 0); @@ -203,3 +192,18 @@ int wait_for_read(int fd, struct timeval *end) { } } +#endif + +int set_cloexec(int fd) { + int n; + assert(fd >= 0); + + if ((n = fcntl(fd, F_GETFD)) < 0) + return -1; + + if (n & FD_CLOEXEC) + return 0; + + return fcntl(fd, F_SETFD, n|FD_CLOEXEC); +} + diff --git a/src/util.h b/src/util.h index b227ce0..e2334ad 100644 --- a/src/util.h +++ b/src/util.h @@ -26,6 +26,7 @@ #include #include +#ifdef ENABLE_LEGACY typedef uint64_t usec_t; usec_t timeval_diff(const struct timeval *a, const struct timeval *b); @@ -34,9 +35,13 @@ usec_t timeval_age(const struct timeval *tv); void timeval_add(struct timeval *tv, usec_t v); int set_nonblock(int fd); -int set_cloexec(int fd); int wait_for_write(int fd, struct timeval *end); int wait_for_read(int fd, struct timeval *end); +#endif + +int set_cloexec(int fd); + + #endif -- cgit