From: Lennart Poettering Date: Tue, 25 Oct 2005 22:20:37 +0000 (+0000) Subject: * replace AF_UNSPEC by AVAHI_PROTO_UNSPEC in client-test.c X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=c3575017e2137ef664e4735bd6f9ff1209653ef3;p=catta * replace AF_UNSPEC by AVAHI_PROTO_UNSPEC in client-test.c * remove some functions from the public API in avahi-common/{domain,address}.[ch] and move them into avahi-core/{domain-util,add-util}.[ch] * properly generate CNAME responses * add some more comments to server.c git-svn-id: file:///home/lennart/svn/public/avahi/trunk@871 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- diff --git a/avahi-client/client-test.c b/avahi-client/client-test.c index f9913e6..5c9c092 100644 --- a/avahi-client/client-test.c +++ b/avahi-client/client-test.c @@ -286,7 +286,7 @@ int main (int argc, char *argv[]) { else printf ("Successfully created hostname resolver object\n"); - aar = avahi_address_parse ("224.0.0.251", AF_UNSPEC, aar); + aar = avahi_address_parse ("224.0.0.251", AVAHI_PROTO_UNSPEC, aar); if (aar == NULL) { printf ("failed to create address object\n"); } else { @@ -299,10 +299,8 @@ int main (int argc, char *argv[]) { printf ("*** success, added address\n"); avahi_entry_group_commit (group2); } - } - avahi_elapse_time(&tv, 8000, 0); poll_api->timeout_new(poll_api, &tv, test_entry_group_reset, group); avahi_elapse_time(&tv, 15000, 0); diff --git a/avahi-common/address.c b/avahi-common/address.c index d02d997..56b4058 100644 --- a/avahi-common/address.c +++ b/avahi-common/address.c @@ -34,7 +34,7 @@ #include "address.h" #include "malloc.h" -size_t avahi_address_get_size(const AvahiAddress *a) { +static size_t address_get_size(const AvahiAddress *a) { assert(a); if (a->proto == AVAHI_PROTO_INET) @@ -52,7 +52,7 @@ int avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b) { if (a->proto != b->proto) return -1; - return memcmp(a->data.data, b->data.data, avahi_address_get_size(a)); + return memcmp(a->data.data, b->data.data, address_get_size(a)); } char *avahi_address_snprint(char *s, size_t length, const AvahiAddress *a) { @@ -126,49 +126,6 @@ AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol proto, AvahiAddre return ret_addr; } -AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr) { - assert(sa); - assert(ret_addr); - - assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); - - ret_addr->proto = avahi_af_to_proto(sa->sa_family); - - if (sa->sa_family == AF_INET) - memcpy(&ret_addr->data.ipv4, &((const struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4)); - else - memcpy(&ret_addr->data.ipv6, &((const struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6)); - - return ret_addr; -} - -uint16_t avahi_port_from_sockaddr(const struct sockaddr* sa) { - assert(sa); - - assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); - - if (sa->sa_family == AF_INET) - return ntohs(((const struct sockaddr_in*) sa)->sin_port); - else - return ntohs(((const struct sockaddr_in6*) sa)->sin6_port); -} - -int avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) { - - static const uint8_t ipv4_in_ipv6[] = { - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF - }; - - assert(a); - - if (a->proto != AVAHI_PROTO_INET6) - return 0; - - return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0; -} - int avahi_proto_to_af(AvahiProtocol proto) { if (proto == AVAHI_PROTO_INET) return AF_INET; diff --git a/avahi-common/address.h b/avahi-common/address.h index c383250..95eb392 100644 --- a/avahi-common/address.h +++ b/avahi-common/address.h @@ -24,8 +24,8 @@ /** \file address.h Definitions and functions to manipulate IP addresses. */ -#include #include +#include #include @@ -65,7 +65,6 @@ typedef struct { uint32_t address; /**< Address data in network byte order. */ } AvahiIPv4Address; - /** An IPv6 address */ typedef struct { uint8_t address[16]; /**< Address data */ @@ -78,13 +77,10 @@ typedef struct { union { AvahiIPv6Address ipv6; /** Address when IPv6 */ AvahiIPv4Address ipv4; /** Address when IPv4 */ - uint8_t data[1]; /** Type independant data field */ + uint8_t data[1]; /** Type independant data field */ } data; } AvahiAddress; -/** Return the address data size of the specified address. (4 for IPv4, 16 for IPv6) */ -size_t avahi_address_get_size(const AvahiAddress *a); - /** Compare two addresses. Returns 0 when equal, a negative value when a < b, a positive value when a > b. */ int avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b); @@ -96,19 +92,9 @@ char *avahi_address_snprint(char *ret_s, size_t length, const AvahiAddress *a); * family detection. */ AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol af, AvahiAddress *ret_addr); -/** Make an address structture of a sockaddr structure */ -AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr); - -/** Return the port number of a sockaddr structure (either IPv4 or IPv6) */ -uint16_t avahi_port_from_sockaddr(const struct sockaddr* sa); - /** Generate the DNS reverse lookup name for an IPv4 or IPv6 address. */ char* avahi_reverse_lookup_name(char *ret_s, size_t length, const AvahiAddress *a); -/** Check whether the specified IPv6 address is in fact an - * encapsulated IPv4 address, returns 1 if yes, 0 otherwise */ -int avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a); - /** Map AVAHI_PROTO_xxx constants to Unix AF_xxx constants */ int avahi_proto_to_af(AvahiProtocol proto); diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c index 9926a1f..b765532 100644 --- a/avahi-common/domain-test.c +++ b/avahi-common/domain-test.c @@ -37,9 +37,6 @@ int main(int argc, char *argv[]) { size_t size; char name[64], type[AVAHI_DOMAIN_NAME_MAX], domain[AVAHI_DOMAIN_NAME_MAX]; - printf("host name: %s\n", s = avahi_get_host_name_strdup()); - avahi_free(s); - printf("%s\n", s = avahi_normalize_name_strdup("foo.foo\\046.")); avahi_free(s); @@ -82,8 +79,6 @@ int main(int argc, char *argv[]) { p = r; printf("unescaped: <%s>\n", avahi_unescape_label(&p, t, sizeof(t))); - assert(avahi_domain_ends_with("foo.bar.\\065\\\\\\.aaaa", "\\065\\\\\\.aaaa")); - assert(avahi_is_valid_service_type_generic("_foo._bar._waldo")); assert(!avahi_is_valid_service_type_strict("_foo._bar._waldo")); assert(!avahi_is_valid_service_subtype("_foo._bar._waldo")); diff --git a/avahi-common/domain.c b/avahi-common/domain.c index 7d954de..4927086 100644 --- a/avahi-common/domain.c +++ b/avahi-common/domain.c @@ -37,31 +37,6 @@ #include "malloc.h" #include "error.h" -char *avahi_get_host_name(char *ret_s, size_t size) { -#ifdef HOST_NAME_MAX - char t[HOST_NAME_MAX]; -#else - char t[256]; -#endif - - assert(ret_s); - assert(size > 0); - - gethostname(t, sizeof(t)); - t[sizeof(t)-1] = 0; - - return avahi_normalize_name(t, ret_s, size); -} - -char *avahi_get_host_name_strdup(void) { - char t[AVAHI_DOMAIN_NAME_MAX]; - - if (!(avahi_get_host_name(t, sizeof(t)))) - return NULL; - - return avahi_strdup(t); -} - /* Read the first label from string *name, unescape "\" and write it to dest */ char *avahi_unescape_label(const char **name, char *dest, size_t size) { unsigned i = 0; @@ -273,30 +248,6 @@ int avahi_domain_equal(const char *a, const char *b) { return 1; } -int avahi_binary_domain_cmp(const char *a, const char *b) { - assert(a); - assert(b); - - if (a == b) - return 0; - - for (;;) { - char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *p; - int r; - - p = avahi_unescape_label(&a, ca, sizeof(ca)); - assert(p); - p = avahi_unescape_label(&b, cb, sizeof(cb)); - assert(p); - - if ((r = strcmp(ca, cb))) - return r; - - if (!*a && !*b) - return 0; - } -} - int avahi_is_valid_service_type_generic(const char *t) { assert(t); @@ -483,24 +434,6 @@ unsigned avahi_domain_hash(const char *s) { return hash; } -int avahi_domain_ends_with(const char *domain, const char *suffix) { - assert(domain); - assert(suffix); - - for (;;) { - char dummy[AVAHI_LABEL_MAX], *r; - - if (*domain == 0) - return 0; - - if (avahi_domain_equal(domain, suffix)) - return 1; - - r = avahi_unescape_label(&domain, dummy, sizeof(dummy)); - assert(r); - } -} - int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain) { char escaped_name[AVAHI_LABEL_MAX*4]; char normalized_type[AVAHI_DOMAIN_NAME_MAX]; diff --git a/avahi-common/domain.h b/avahi-common/domain.h index 4e3aa55..e5869ce 100644 --- a/avahi-common/domain.h +++ b/avahi-common/domain.h @@ -44,7 +44,7 @@ AVAHI_C_DECL_BEGIN * the string brings us to 1014. */ #define AVAHI_DOMAIN_NAME_MAX 1014 -/** Maxium size of an unescaped label */ +/** Maximum size of an unescaped label */ #define AVAHI_LABEL_MAX 64 /** Normalize a domain name into canonical form. This drops trailing @@ -56,18 +56,9 @@ char *avahi_normalize_name(const char *s, char *ret_s, size_t size); * result! */ char *avahi_normalize_name_strdup(const char *s); -/** Return the local host name. */ -char *avahi_get_host_name(char *ret_s, size_t size); - -/** Return the local host name. avahi_free() the result! */ -char *avahi_get_host_name_strdup(void); - /** Return 1 when the specified domain names are equal, 0 otherwise */ int avahi_domain_equal(const char *a, const char *b); -/** Do a binary comparison of to specified domain names, return -1, 0, or 1, depending on the order. */ -int avahi_binary_domain_cmp(const char *a, const char *b); - /** Read the first label from the textual domain name *name, unescape * it and write it to dest, *name is changed to point to the next label*/ char *avahi_unescape_label(const char **name, char *dest, size_t size); @@ -75,6 +66,9 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size); /** Escape the domain name in *src and write it to *ret_name */ char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, size_t *ret_size); +/** Return a pointer to the type section of a subtype i.e. _foo._sub._bar._tcp => _bar._tcp */ +const char *avahi_get_type_from_subtype(const char *t); + /** Return 1 when the specified string contains a valid generic * service type (i.e. a series of words starting with "_"), 0 * otherwise */ @@ -88,9 +82,6 @@ int avahi_is_valid_service_type_strict(const char *t); /** Return 1 when the specified string contains a valid service subtype, 0 otherwise */ int avahi_is_valid_service_subtype(const char *t); -/** Return a pointer to the type section of a subtype i.e. _foo._sub._bar._tcp => _bar._tcp */ -const char *avahi_get_type_from_subtype(const char *t); - /** Return 1 when the specified string contains a valid domain name, 0 otherwise */ int avahi_is_valid_domain_name(const char *t); @@ -103,9 +94,6 @@ int avahi_is_valid_host_name(const char *t); /** Return some kind of hash value for the domain, useful for using domains as hash table keys. */ unsigned avahi_domain_hash(const char *name); -/** Returns 1 if the the end labels of domain are eqal to suffix */ -int avahi_domain_ends_with(const char *domain, const char *suffix); - /** Construct a valid complete service name from a name, a type and a domain */ int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain); diff --git a/avahi-core/Makefile.am b/avahi-core/Makefile.am index 9516615..cc93265 100644 --- a/avahi-core/Makefile.am +++ b/avahi-core/Makefile.am @@ -76,7 +76,9 @@ libavahi_core_la_SOURCES = \ hashmap.c hashmap.h \ wide-area.c wide-area.h \ multicast-lookup.c multicast-lookup.h \ - querier.c querier.h + querier.c querier.h \ + addr-util.h addr-util.c \ + domain-util.h domain-util.c if HAVE_NETLINK libavahi_core_la_SOURCES += \ @@ -130,7 +132,8 @@ dns_test_SOURCES = \ log.c log.h \ util.c util.h \ rr.c rr.h \ - hashmap.c hashmap.h + hashmap.c hashmap.h \ + domain-util.c domain-util.h dns_test_CFLAGS = $(AM_CFLAGS) dns_test_LDADD = $(AM_LDADD) ../avahi-common/libavahi-common.la diff --git a/avahi-core/addr-util.c b/avahi-core/addr-util.c new file mode 100644 index 0000000..7b9bb03 --- /dev/null +++ b/avahi-core/addr-util.c @@ -0,0 +1,79 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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 avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "addr-util.h" + +AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr) { + assert(sa); + assert(ret_addr); + + assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + + ret_addr->proto = avahi_af_to_proto(sa->sa_family); + + if (sa->sa_family == AF_INET) + memcpy(&ret_addr->data.ipv4, &((const struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4)); + else + memcpy(&ret_addr->data.ipv6, &((const struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6)); + + return ret_addr; +} + +uint16_t avahi_port_from_sockaddr(const struct sockaddr* sa) { + assert(sa); + + assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + + if (sa->sa_family == AF_INET) + return ntohs(((const struct sockaddr_in*) sa)->sin_port); + else + return ntohs(((const struct sockaddr_in6*) sa)->sin6_port); +} + +int avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) { + + static const uint8_t ipv4_in_ipv6[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + assert(a); + + if (a->proto != AVAHI_PROTO_INET6) + return 0; + + return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0; +} + + + diff --git a/avahi-core/addr-util.h b/avahi-core/addr-util.h new file mode 100644 index 0000000..4134de1 --- /dev/null +++ b/avahi-core/addr-util.h @@ -0,0 +1,45 @@ +#ifndef fooaddrutilhfoo +#define fooaddrutilhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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 avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include +#include + +AVAHI_C_DECL_BEGIN + +/** Make an address structture of a sockaddr structure */ +AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr); + +/** Return the port number of a sockaddr structure (either IPv4 or IPv6) */ +uint16_t avahi_port_from_sockaddr(const struct sockaddr* sa); + +/** Check whether the specified IPv6 address is in fact an + * encapsulated IPv4 address, returns 1 if yes, 0 otherwise */ +int avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c index 754988c..51a3a03 100644 --- a/avahi-core/avahi-test.c +++ b/avahi-core/avahi-test.c @@ -149,6 +149,7 @@ static void remove_entries(void) { static void create_entries(int new_name) { AvahiAddress a; + AvahiRecord *r; remove_entries(); @@ -185,6 +186,14 @@ static void create_entries(int new_name) { goto fail; } + r = avahi_record_new_full("cname.local", AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_CNAME, AVAHI_DEFAULT_TTL); + r->data.cname.name = avahi_strdup("cocaine.local"); + + if (avahi_server_add(server, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, r) < 0) { + avahi_log_error("Failed to add CNAME record"); + goto fail; + } + avahi_s_entry_group_commit(group); return; @@ -345,7 +354,7 @@ int main(int argc, char *argv[]) { r = avahi_s_record_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, k, 0, record_browser_callback, NULL); avahi_key_unref(k); - hnr = avahi_s_host_name_resolver_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "cocaine.local", AVAHI_PROTO_UNSPEC, 0, hnr_callback, NULL); + hnr = avahi_s_host_name_resolver_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "cname.local", AVAHI_PROTO_UNSPEC, 0, hnr_callback, NULL); ar = avahi_s_address_resolver_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, avahi_address_parse("192.168.50.1", AVAHI_PROTO_INET, &a), 0, ar_callback, NULL); diff --git a/avahi-core/browse.c b/avahi-core/browse.c index 5fd3a01..cb2d326 100644 --- a/avahi-core/browse.c +++ b/avahi-core/browse.c @@ -35,6 +35,7 @@ #include "browse.h" #include "log.h" #include "querier.h" +#include "domain-util.h" #define AVAHI_LOOKUPS_PER_BROWSER_MAX 15 @@ -278,7 +279,6 @@ static void lookup_multicast_callback( lookup_handle_cname(l, interface, protocol, b->flags, r); else { /* It's a normal record, so let's call the user callback */ - assert(avahi_key_equal(b->key, l->key)); if (avahi_server_is_record_local(b->server, interface, protocol, r)) flags |= AVAHI_LOOKUP_RESULT_LOCAL; diff --git a/avahi-core/domain-util.c b/avahi-core/domain-util.c new file mode 100644 index 0000000..d4cc2ad --- /dev/null +++ b/avahi-core/domain-util.c @@ -0,0 +1,101 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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 avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "domain-util.h" + +char *avahi_get_host_name(char *ret_s, size_t size) { +#ifdef HOST_NAME_MAX + char t[HOST_NAME_MAX]; +#else + char t[256]; +#endif + + assert(ret_s); + assert(size > 0); + + gethostname(t, sizeof(t)); + t[sizeof(t)-1] = 0; + + return avahi_normalize_name(t, ret_s, size); +} + +char *avahi_get_host_name_strdup(void) { + char t[AVAHI_DOMAIN_NAME_MAX]; + + if (!(avahi_get_host_name(t, sizeof(t)))) + return NULL; + + return avahi_strdup(t); +} + +int avahi_binary_domain_cmp(const char *a, const char *b) { + assert(a); + assert(b); + + if (a == b) + return 0; + + for (;;) { + char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *p; + int r; + + p = avahi_unescape_label(&a, ca, sizeof(ca)); + assert(p); + p = avahi_unescape_label(&b, cb, sizeof(cb)); + assert(p); + + if ((r = strcmp(ca, cb))) + return r; + + if (!*a && !*b) + return 0; + } +} + +int avahi_domain_ends_with(const char *domain, const char *suffix) { + assert(domain); + assert(suffix); + + for (;;) { + char dummy[AVAHI_LABEL_MAX], *r; + + if (*domain == 0) + return 0; + + if (avahi_domain_equal(domain, suffix)) + return 1; + + r = avahi_unescape_label(&domain, dummy, sizeof(dummy)); + assert(r); + } +} + diff --git a/avahi-core/domain-util.h b/avahi-core/domain-util.h new file mode 100644 index 0000000..01233d8 --- /dev/null +++ b/avahi-core/domain-util.h @@ -0,0 +1,47 @@ +#ifndef foodomainutilhfoo +#define foodomainutilhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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 avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include +#include + +AVAHI_C_DECL_BEGIN + +/** Return the local host name. */ +char *avahi_get_host_name(char *ret_s, size_t size); + +/** Return the local host name. avahi_free() the result! */ +char *avahi_get_host_name_strdup(void); + +/** Do a binary comparison of to specified domain names, return -1, 0, or 1, depending on the order. */ +int avahi_binary_domain_cmp(const char *a, const char *b); + +/** Returns 1 if the the end labels of domain are eqal to suffix */ +int avahi_domain_ends_with(const char *domain, const char *suffix); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-core/rr.c b/avahi-core/rr.c index ef1c3d6..e7fac13 100644 --- a/avahi-core/rr.c +++ b/avahi-core/rr.c @@ -37,6 +37,7 @@ #include "log.h" #include "util.h" #include "hashmap.h" +#include "domain-util.h" AvahiKey *avahi_key_new(const char *name, uint16_t class, uint16_t type) { AvahiKey *k; diff --git a/avahi-core/rr.h b/avahi-core/rr.h index 63dc18d..21d6d63 100644 --- a/avahi-core/rr.h +++ b/avahi-core/rr.h @@ -98,7 +98,7 @@ typedef struct { struct { char *name; - } ptr; /**< Data for PTR an CNAME records */ + } ptr, ns, cname; /**< Data for PTR, NS and CNAME records */ struct { char *cpu; diff --git a/avahi-core/server.c b/avahi-core/server.c index 3edd96e..5cac056 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -45,26 +45,38 @@ #include "log.h" #include "util.h" #include "dns-srv-rr.h" +#include "addr-util.h" +#include "domain-util.h" static void enum_aux_records(AvahiServer *s, AvahiInterface *i, const char *name, uint16_t type, void (*callback)(AvahiServer *s, AvahiRecord *r, int flush_cache, void* userdata), void* userdata) { - AvahiKey *k; - AvahiEntry *e; - assert(s); assert(i); assert(name); assert(callback); - assert(type != AVAHI_DNS_TYPE_ANY); - - if (!(k = avahi_key_new(name, AVAHI_DNS_CLASS_IN, type))) - return; /** OOM */ - - for (e = avahi_hashmap_lookup(s->entries_by_key, k); e; e = e->by_key_next) - if (!e->dead && avahi_entry_is_registered(s, e, i)) - callback(s, e->record, e->flags & AVAHI_PUBLISH_UNIQUE, userdata); + if (type == AVAHI_DNS_TYPE_ANY) { + AvahiEntry *e; + + for (e = s->entries; e; e = e->entries_next) + if (!e->dead && + avahi_entry_is_registered(s, e, i) && + e->record->key->clazz == AVAHI_DNS_CLASS_IN && + avahi_domain_equal(name, e->record->key->name)) + callback(s, e->record, e->flags & AVAHI_PUBLISH_UNIQUE, userdata); - avahi_key_unref(k); + } else { + AvahiEntry *e; + AvahiKey *k; + + if (!(k = avahi_key_new(name, AVAHI_DNS_CLASS_IN, type))) + return; /** OOM */ + + for (e = avahi_hashmap_lookup(s->entries_by_key, k); e; e = e->by_key_next) + if (!e->dead && avahi_entry_is_registered(s, e, i)) + callback(s, e->record, e->flags & AVAHI_PUBLISH_UNIQUE, userdata); + + avahi_key_unref(k); + } } void avahi_server_enumerate_aux_records(AvahiServer *s, AvahiInterface *i, AvahiRecord *r, void (*callback)(AvahiServer *s, AvahiRecord *r, int flush_cache, void* userdata), void* userdata) { @@ -72,6 +84,8 @@ void avahi_server_enumerate_aux_records(AvahiServer *s, AvahiInterface *i, Avahi assert(i); assert(r); assert(callback); + + /* Call the specified callback far all records referenced by the one specified in *r */ if (r->key->clazz == AVAHI_DNS_CLASS_IN) { if (r->key->type == AVAHI_DNS_TYPE_PTR) { @@ -80,7 +94,8 @@ void avahi_server_enumerate_aux_records(AvahiServer *s, AvahiInterface *i, Avahi } else if (r->key->type == AVAHI_DNS_TYPE_SRV) { enum_aux_records(s, i, r->data.srv.name, AVAHI_DNS_TYPE_A, callback, userdata); enum_aux_records(s, i, r->data.srv.name, AVAHI_DNS_TYPE_AAAA, callback, userdata); - } + } else if (r->key->type == AVAHI_DNS_TYPE_CNAME) + enum_aux_records(s, i, r->data.cname.name, AVAHI_DNS_TYPE_ANY, callback, userdata); } } @@ -93,17 +108,14 @@ void avahi_server_prepare_response(AvahiServer *s, AvahiInterface *i, AvahiEntry } void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i, AvahiKey *k, int unicast_response) { - AvahiEntry *e; -/* char *txt; */ - assert(s); assert(i); assert(k); -/* avahi_log_debug("Posting responses matching [%s]", txt = avahi_key_to_string(k)); */ -/* avahi_free(txt); */ + /* Push all records that match the specified key to the record list */ if (avahi_key_is_pattern(k)) { + AvahiEntry *e; /* Handle ANY query */ @@ -112,6 +124,7 @@ void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i, avahi_server_prepare_response(s, i, e, unicast_response, 0); } else { + AvahiEntry *e; /* Handle all other queries */ @@ -119,21 +132,40 @@ void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i, if (!e->dead && avahi_entry_is_registered(s, e, i)) avahi_server_prepare_response(s, i, e, unicast_response, 0); } + + /* Look for CNAME records */ + + if ((k->clazz == AVAHI_DNS_CLASS_IN || k->clazz == AVAHI_DNS_CLASS_ANY) + && k->type != AVAHI_DNS_TYPE_CNAME && k->type != AVAHI_DNS_TYPE_ANY) { + + AvahiKey *cname_key; + + if (!(cname_key = avahi_key_new(k->name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_CNAME))) + return; + + avahi_server_prepare_matching_responses(s, i, cname_key, unicast_response); + avahi_key_unref(cname_key); + } } static void withdraw_entry(AvahiServer *s, AvahiEntry *e) { assert(s); assert(e); + + /* Withdraw the specified entry, and if is part of an entry group, + * put that into COLLISION state */ + + if (e->dead) + return; if (e->group) { AvahiEntry *k; - for (k = e->group->entries; k; k = k->by_group_next) { + for (k = e->group->entries; k; k = k->by_group_next) if (!k->dead) { avahi_goodbye_entry(s, k, 0, 1); k->dead = 1; } - } e->group->n_probing = 0; @@ -152,24 +184,22 @@ static void withdraw_rrset(AvahiServer *s, AvahiKey *key) { assert(s); assert(key); - for (e = avahi_hashmap_lookup(s->entries_by_key, key); e; e = e->by_key_next) - if (!e->dead) - withdraw_entry(s, e); + /* Withdraw an entry RRSset */ + + for (e = avahi_hashmap_lookup(s->entries_by_key, key); e; e = e->by_key_next) + withdraw_entry(s, e); } static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface *i) { AvahiEntry *e, *n; - char *t; int ours = 0, won = 0, lost = 0; assert(s); assert(record); assert(i); - t = avahi_record_to_string(record); - -/* avahi_log_debug("incoming_probe()"); */ - + /* Handle incoming probes and check if they conflict our own probes */ + for (e = avahi_hashmap_lookup(s->entries_by_key, record->key); e; e = n) { int cmp; n = e->by_key_next; @@ -192,17 +222,17 @@ static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface * } if (!ours) { - + char *t = avahi_record_to_string(record); + if (won) avahi_log_debug("Recieved conflicting probe [%s]. Local host won.", t); else if (lost) { avahi_log_debug("Recieved conflicting probe [%s]. Local host lost. Withdrawing.", t); withdraw_rrset(s, record->key); - }/* else */ -/* avahi_log_debug("Not conflicting probe"); */ + } + + avahi_free(t); } - - avahi_free(t); } static int handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord *record, int unique, const AvahiAddress *a) { @@ -213,9 +243,8 @@ static int handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord *recor assert(i); assert(record); - -/* avahi_log_debug("CHECKING FOR CONFLICT: [%s]", t); */ - + /* Check whether an incoming record conflicts with one of our own */ + for (e = avahi_hashmap_lookup(s->entries_by_key, record->key); e; e = n) { n = e->by_key_next; @@ -286,8 +315,6 @@ static int handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord *recor } } -/* avahi_log_debug("ours=%i conflict=%i", ours, conflict); */ - if (!ours && conflict) { char *t; diff --git a/avahi-core/socket.c b/avahi-core/socket.c index fcc63fa..0487023 100644 --- a/avahi-core/socket.c +++ b/avahi-core/socket.c @@ -679,7 +679,6 @@ AvahiDnsPacket* avahi_recv_dns_packet_ipv6(int fd, struct sockaddr_in6 *ret_sa, uint8_t aux[64]; ssize_t l; int ms; - struct cmsghdr *cmsg; int found_ttl = 0, found_iface = 0; diff --git a/avahi-core/update-test.c b/avahi-core/update-test.c index bd42c75..fbfd51a 100644 --- a/avahi-core/update-test.c +++ b/avahi-core/update-test.c @@ -24,6 +24,7 @@ #endif #include +#include #include #include diff --git a/avahi-core/wide-area.c b/avahi-core/wide-area.c index 9dd1e73..d12267a 100644 --- a/avahi-core/wide-area.c +++ b/avahi-core/wide-area.c @@ -38,6 +38,7 @@ #include "log.h" #include "hashmap.h" #include "wide-area.h" +#include "addr-util.h" #define CACHE_ENTRIES_MAX 500 diff --git a/docs/TODO b/docs/TODO index 65a606a..757fb82 100644 --- a/docs/TODO +++ b/docs/TODO @@ -1,11 +1,11 @@ for 0.6: * remove outgoing queries from queue if the browse object they were issued from is destroyed * add API to allow user to tell the server that some service is not reachable -* generate local CNAME responses * add support for subtypes in static services * Add static host configuration like static services [lathiat] * wrap avahi_server_add_record() via DBUS and in avahi-client [lathiat] -* unify argument oder of functions returning a string in a user supplied buffer +* unify argument order of functions returning a string in a user supplied buffer +* remove irrelevant functions from pubic rr.h API later: * add simplification routine for adding services @@ -96,3 +96,4 @@ done: * drop partially created created entries on failure * add error state for server and entry group * make sure that all limit definitions end with _MAX +* generate local CNAME responses