diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 11 | ||||
| -rw-r--r-- | src/avahi-test.c | 48 | ||||
| -rw-r--r-- | src/avahi.c | 145 | ||||
| -rw-r--r-- | src/avahi.h | 33 | ||||
| -rw-r--r-- | src/nss.c | 103 | ||||
| -rw-r--r-- | src/query.c | 2 | 
6 files changed, 307 insertions, 35 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 032ee3f..ac24af2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,6 @@ AM_CFLAGS=-D_GNU_SOURCE -DMDNS_ALLOW_FILE=\"$(sysconfdir)/mdns.allow\"  AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'  noinst_PROGRAMS = nss-test mdns-test -  lib_LTLIBRARIES = libnss_mdns.la libnss_mdns4.la libnss_mdns6.la  mdns_test_SOURCES = query.c dns.c util.c mdns-test.c \ @@ -32,12 +31,16 @@ mdns_test_SOURCES = query.c dns.c util.c mdns-test.c \  nss_test_SOURCES = nss-test.c -libnss_mdns_la_SOURCES = query.c dns.c util.c nss.c \ -			 query.h dns.h 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 +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 +  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) diff --git a/src/avahi-test.c b/src/avahi-test.c new file mode 100644 index 0000000..e66421e --- /dev/null +++ b/src/avahi-test.c @@ -0,0 +1,48 @@ +/* $Id$ */ + +/*** +  This file is part of nss-mdns. +  +  nss-mdns 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 of the +  License, or (at your option) any later version. +  +  nss-mdns is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  General Public License for more details. +  +  You should have received a copy of the GNU Lesser General Public +  License along with nss-mdns; if not, write to the Free Software +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +  USA. +***/ + +#include <arpa/inet.h> +#include <stdio.h> + +#include "avahi.h" + +int main(int argc, char *argv[]) { +    uint8_t data[64]; +    char t[256]; +    int r; + +    if ((r = avahi_resolve_name(AF_INET, argc >= 2 ? argv[1] : "whiskey.local", data)) == 0) +        printf("AF_INET: %s\n", inet_ntop(AF_INET, data, t, sizeof(t))); +    else +        printf("AF_INET: failed (%i).\n", r); + +    if ((r = avahi_resolve_name(AF_INET6, argc >= 2 ? argv[1] : "whiskey.local", data)) == 0) +        printf("AF_INET6: %s\n", inet_ntop(AF_INET6, data, t, sizeof(t))); +    else +        printf("AF_INET6: failed (%i).\n", r); + +    if ((r = avahi_resolve_address(AF_INET6, data, t, sizeof(t))) == 0) +        printf("REVERSE: %s\n", t); +    else +        printf("REVERSE: failed (%i).\n", r); + +    return 0; +} diff --git a/src/avahi.c b/src/avahi.c new file mode 100644 index 0000000..cd4db00 --- /dev/null +++ b/src/avahi.c @@ -0,0 +1,145 @@ +/* $Id$ */ + +/*** +  This file is part of nss-mdns. +  +  nss-mdns 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 of the +  License, or (at your option) any later version. +  +  nss-mdns is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  General Public License for more details. +  +  You should have received a copy of the GNU Lesser General Public +  License along with nss-mdns; if not, write to the Free Software +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +  USA. +***/ + + +#include <sys/socket.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <arpa/inet.h> +#include <sys/un.h> +#include <assert.h> +#include <unistd.h> + +#include "avahi.h" +#include "util.h" + +#define AVAHI_SOCKET "/var/run/avahi/socket" + +static FILE *open_socket(void) { +    int fd = -1; +    struct sockaddr_un sa; +    FILE *f; + +    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) +        goto fail; + +    set_cloexec(fd); +     +    memset(&sa, 0, sizeof(sa)); +    sa.sun_family = AF_UNIX; +    strncpy(sa.sun_path, AVAHI_SOCKET, sizeof(sa.sun_path)-1); +    sa.sun_path[sizeof(sa.sun_path)-1] = 0; + +    if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) +        goto fail; + +    if (!(f = fdopen(fd, "r+"))) +        goto fail; + +    return f; +     +fail: +    if (fd >= 0) +        close(fd); + +    return NULL; +     +} + +int avahi_resolve_name(int af, const char* name, void* data) { +    FILE *f; +    char *e, *p; +    int ret = -1; +    char ln[256]; + +    assert(af == AF_INET || af == AF_INET6); +     +    if (!(f = open_socket())) +        goto finish; + +    fprintf(f, "RESOLVE-HOSTNAME%s %s\n", af == AF_INET ? "-IPV4" : "-IPV6", name); +    fflush(f); + +    if (!(fgets(ln, sizeof(ln), f))) +        goto finish; + +    if (ln[0] != '+') { +        ret = 1; +        goto finish; +    } + +    p = ln+1; +    p += strspn(p, "\t "); +    e = p + strcspn(p, "\n\r\t "); +    *e = 0; + +    if (inet_pton(af, p, data) <= 0) +        goto finish; + +    ret = 0; +     +finish: + +    if (f) +        fclose(f); + +    return ret; +} + +int avahi_resolve_address(int af, const void *data, char* name, size_t name_len) { +    FILE *f; +    char *e, *p; +    int ret = -1; +    char a[256], ln[256]; + +    assert(af == AF_INET || af == AF_INET6); +     +    if (!(f = open_socket())) +        goto finish; + +    fprintf(f, "RESOLVE-ADDRESS %s\n", inet_ntop(af, data, a, sizeof(a))); +     +    if (!(fgets(ln, sizeof(ln), f))) +        goto finish; + +    if (ln[0] != '+') { +        ret = 1; +        goto finish; +    } + +    p = ln+1; +    p += strspn(p, "\t "); +    e = p + strcspn(p, "\n\r\t "); +    *e = 0; + +    strncpy(name, p, name_len-1); +    name[name_len-1] = 0; + +    ret = 0; +      +finish: + +    if (f) +        fclose(f); + +    return ret; +} diff --git a/src/avahi.h b/src/avahi.h new file mode 100644 index 0000000..79d1c86 --- /dev/null +++ b/src/avahi.h @@ -0,0 +1,33 @@ +#ifndef fooavahihfoo +#define fooavahihfoo + +/* $Id$ */ + +/*** +  This file is part of nss-mdns. +  +  nss-mdns 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 of the +  License, or (at your option) any later version. +  +  nss-mdns is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  General Public License for more details. +  +  You should have received a copy of the GNU Lesser General Public +  License along with nss-mdns; if not, write to the Free Software +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +  USA. +***/ + + +#include <inttypes.h> +#include <sys/types.h> + +int avahi_resolve_name(int af, const char* name, void* data); + +int avahi_resolve_address(int af, const void *data, char* name, size_t name_len); + +#endif @@ -34,6 +34,10 @@  #include "query.h" +#ifdef ENABLE_AVAHI +#include "avahi.h" +#endif +  #define MAX_ENTRIES 16  #ifdef NSS_IPV4_ONLY @@ -161,6 +165,10 @@ enum nss_status _nss_mdns_gethostbyname2_r(      void (*ipv4_func)(const ipv4_address_t *ipv4, void *userdata);      void (*ipv6_func)(const ipv6_address_t *ipv6, void *userdata); +#ifdef ENABLE_AVAHI +    uint8_t data[128]; +#endif +  /*     DEBUG_TRAP; */  #ifdef NSS_IPV4_ONLY @@ -195,39 +203,56 @@ enum nss_status _nss_mdns_gethostbyname2_r(          goto finish;      } -    if ((fd = mdns_open_socket()) < 0) { - -        *errnop = errno; -        *h_errnop = NO_RECOVERY; -        goto finish; -    } -      u.count = 0;      u.data_len = 0; -#ifndef NSS_IPV6_ONLY -    ipv4_func = af == AF_INET ? ipv4_callback : NULL; -#else +#ifdef NSS_IPV6_ONLY      ipv4_func = NULL; +#else +    ipv4_func = af == AF_INET ? ipv4_callback : NULL;  #endif     -#ifndef NSS_IPV4_ONLY -    ipv6_func = af == AF_INET6 ? ipv6_callback : NULL; -#else +#ifdef NSS_IPV4_ONLY      ipv6_func = NULL; +#else +    ipv6_func = af == AF_INET6 ? ipv6_callback : NULL;  #endif -     -    if ((r = mdns_query_name(fd, name, ipv4_func, ipv6_func, &u)) < 0) { + +#ifdef ENABLE_AVAHI + +    if ((r = avahi_resolve_name(af, name, data)) == 0) { +        if (af == AF_INET && ipv4_func) +            ipv4_func((ipv4_address_t*) data, &u); +        if (af == AF_INET6 && ipv4_func) +            ipv6_func((ipv6_address_t*)data, &u); +    } else if (r > 0) {          *errnop = ETIMEDOUT;          *h_errnop = HOST_NOT_FOUND;          goto finish;      } +     +#endif +    if (u.count == 0) { +        if ((fd = mdns_open_socket()) < 0) { +             +            *errnop = errno; +            *h_errnop = NO_RECOVERY; +            goto finish; +        } +         +        if ((r = mdns_query_name(fd, name, ipv4_func, ipv6_func, &u)) < 0) { +            *errnop = ETIMEDOUT; +            *h_errnop = HOST_NOT_FOUND; +            goto finish; +        } +    } +              /* Alias names */      *((char**) buffer) = NULL;      result->h_aliases = (char**) buffer;      index = sizeof(char*); - +          /* Official name */      strcpy(buffer+index, name);       result->h_name = buffer+index; @@ -235,7 +260,7 @@ enum nss_status _nss_mdns_gethostbyname2_r(      result->h_addrtype = af;      result->h_length = address_length; - +          /* Check if there's enough space for the addresses */      if (buflen < index+u.data_len+sizeof(char*)*(u.count+1)) {          *errnop = ERANGE; @@ -302,6 +327,9 @@ enum nss_status _nss_mdns_gethostbyaddr_r(      enum nss_status status = NSS_STATUS_UNAVAIL;      int fd = -1, r;      size_t address_length, index, astart; +#ifdef ENABLE_AVAHI +    char t[256]; +#endif      *errnop = EINVAL;      *h_errnop = NO_RECOVERY; @@ -335,31 +363,46 @@ enum nss_status _nss_mdns_gethostbyaddr_r(          goto finish;      } -     -    if ((fd = mdns_open_socket()) < 0) { -        *errnop = errno; -        *h_errnop = NO_RECOVERY; +#ifdef ENABLE_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;          goto finish;      } +#endif  + +    if (u.count == 0) { + +        if ((fd = mdns_open_socket()) < 0) { +             +            *errnop = errno; +            *h_errnop = NO_RECOVERY; +            goto finish; +        } +          #if ! defined(NSS_IPV6_ONLY) && ! defined(NSS_IPV4_ONLY) -    if (af == AF_INET) +        if (af == AF_INET)  #endif  #ifndef NSS_IPV6_ONLY         -        r = mdns_query_ipv4(fd, (ipv4_address_t*) addr, name_callback, &u); +            r = mdns_query_ipv4(fd, (ipv4_address_t*) addr, name_callback, &u);  #endif  #if ! defined(NSS_IPV6_ONLY) && ! defined(NSS_IPV4_ONLY) -    else +        else  #endif  #ifndef NSS_IPV4_ONLY         -        r = mdns_query_ipv6(fd, (ipv6_address_t*) addr, name_callback, &u); +            r = mdns_query_ipv6(fd, (ipv6_address_t*) addr, name_callback, &u);  #endif -     -    if (r < 0) { -        *errnop = ETIMEDOUT; -        *h_errnop = HOST_NOT_FOUND; -        goto finish; +         +        if (r < 0) { +            *errnop = ETIMEDOUT; +            *h_errnop = HOST_NOT_FOUND; +            goto finish; +        }      }      /* Alias names */ diff --git a/src/query.c b/src/query.c index b59513e..32401fc 100644 --- a/src/query.c +++ b/src/query.c @@ -220,7 +220,7 @@ static int send_dns_packet(int fd, struct dns_packet *p) {      return n_sent;  } -static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t* ret_ttl, struct timeval *end) { +static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t *ret_ttl, struct timeval *end) {      struct dns_packet *p= NULL;      struct msghdr msg;      struct iovec io;  | 
