From e865e3dba3c6ee5de5581dbfbafc025aa5c9947e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Oct 2005 20:21:39 +0000 Subject: [PATCH] * correctly handle empty domain names (i.e. the root zone) * fix memory initialization error in wide-area.c * make server_add_xx() functions atomic, i.e. clean up half-created entries on failure * add some more validity checking macros and change everything to make use of them * clean up avahi_server_add_address() * change some functions from domain.[ch] to work on a stack buffer instead of malloced memory * update avahi-test.c a little * replace avahi_reverse_lookup_name_{ipv4,ipv6}() with a single function avahi_reverse_lookup_name() * remove avahi_server_add_dns_server_name() from public API git-svn-id: file:///home/lennart/svn/public/avahi/trunk@845 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-common/address.c | 73 +++---- avahi-common/address.h | 7 +- avahi-common/domain-test.c | 7 + avahi-common/domain.c | 43 ++-- avahi-core/avahi-test.c | 3 +- avahi-core/dns-srv-rr.h | 14 -- avahi-core/entry.c | 397 +++++++++++++++++++---------------- avahi-core/internal.h | 15 +- avahi-core/resolve-address.c | 18 +- avahi-core/rr.c | 1 - avahi-core/socket.c | 12 +- avahi-core/wide-area.c | 23 +- 12 files changed, 320 insertions(+), 293 deletions(-) diff --git a/avahi-common/address.c b/avahi-common/address.c index f3f3a67..d02d997 100644 --- a/avahi-common/address.c +++ b/avahi-common/address.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "address.h" #include "malloc.h" @@ -65,48 +66,42 @@ char *avahi_address_snprint(char *s, size_t length, const AvahiAddress *a) { return s; } -char* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a) { - uint32_t n = ntohl(a->address); +char* avahi_reverse_lookup_name(char *ret_s, size_t length, const AvahiAddress *a) { + assert(ret_s); + assert(length > 0); assert(a); - return avahi_strdup_printf("%u.%u.%u.%u.in-addr.arpa", n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, n >> 24); -} + if (a->proto == AVAHI_PROTO_INET) { + uint32_t n = ntohl(a->data.ipv4.address); + snprintf( + ret_s, length, + "%u.%u.%u.%u.in-addr.arpa", + n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, n >> 24); + } else { + assert(a->proto == AVAHI_PROTO_INET6); + + snprintf( + ret_s, length, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", + a->data.ipv6.address[15] & 0xF, a->data.ipv6.address[15] >> 4, + a->data.ipv6.address[14] & 0xF, a->data.ipv6.address[14] >> 4, + a->data.ipv6.address[13] & 0xF, a->data.ipv6.address[13] >> 4, + a->data.ipv6.address[12] & 0xF, a->data.ipv6.address[12] >> 4, + a->data.ipv6.address[11] & 0xF, a->data.ipv6.address[11] >> 4, + a->data.ipv6.address[10] & 0xF, a->data.ipv6.address[10] >> 4, + a->data.ipv6.address[ 9] & 0xF, a->data.ipv6.address[ 9] >> 4, + a->data.ipv6.address[ 8] & 0xF, a->data.ipv6.address[ 8] >> 4, + a->data.ipv6.address[ 7] & 0xF, a->data.ipv6.address[ 7] >> 4, + a->data.ipv6.address[ 6] & 0xF, a->data.ipv6.address[ 6] >> 4, + a->data.ipv6.address[ 5] & 0xF, a->data.ipv6.address[ 5] >> 4, + a->data.ipv6.address[ 4] & 0xF, a->data.ipv6.address[ 4] >> 4, + a->data.ipv6.address[ 3] & 0xF, a->data.ipv6.address[ 3] >> 4, + a->data.ipv6.address[ 2] & 0xF, a->data.ipv6.address[ 2] >> 4, + a->data.ipv6.address[ 1] & 0xF, a->data.ipv6.address[ 1] >> 4, + a->data.ipv6.address[ 0] & 0xF, a->data.ipv6.address[ 0] >> 4); + } -char *avahi_reverse_lookup_name_ipv6(const AvahiIPv6Address *a) { - - return avahi_strdup_printf("%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", - a->address[15] & 0xF, - a->address[15] >> 4, - a->address[14] & 0xF, - a->address[14] >> 4, - a->address[13] & 0xF, - a->address[13] >> 4, - a->address[12] & 0xF, - a->address[12] >> 4, - a->address[11] & 0xF, - a->address[11] >> 4, - a->address[10] & 0xF, - a->address[10] >> 4, - a->address[9] & 0xF, - a->address[9] >> 4, - a->address[8] & 0xF, - a->address[8] >> 4, - a->address[7] & 0xF, - a->address[7] >> 4, - a->address[6] & 0xF, - a->address[6] >> 4, - a->address[5] & 0xF, - a->address[5] >> 4, - a->address[4] & 0xF, - a->address[4] >> 4, - a->address[3] & 0xF, - a->address[3] >> 4, - a->address[2] & 0xF, - a->address[2] >> 4, - a->address[1] & 0xF, - a->address[1] >> 4, - a->address[0] & 0xF, - a->address[0] >> 4); + return ret_s; } AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol proto, AvahiAddress *ret_addr) { diff --git a/avahi-common/address.h b/avahi-common/address.h index f1ac428..c383250 100644 --- a/avahi-common/address.h +++ b/avahi-common/address.h @@ -102,11 +102,8 @@ AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddres /** 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 address. avahi_free() the result! */ -char* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a); - -/** Generate the modern DNS reverse lookup name for an IPv6 address, ending in ipv6.arpa. avahi_free() the result! */ -char* avahi_reverse_lookup_name_ipv6(const AvahiIPv6Address *a); +/** 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 */ diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c index f1313cb..279be72 100644 --- a/avahi-common/domain-test.c +++ b/avahi-common/domain-test.c @@ -110,5 +110,12 @@ int main(int argc, char *argv[]) { assert(avahi_is_valid_host_name("sfooo.")); assert(avahi_is_valid_host_name("sfooo")); + assert(avahi_is_valid_domain_name(".")); + assert(avahi_is_valid_domain_name("")); + + assert(avahi_normalize_name(".", t, sizeof(t))); + assert(avahi_normalize_name("", t, sizeof(t))); + + return 0; } diff --git a/avahi-common/domain.c b/avahi-common/domain.c index 988ba7e..7d954de 100644 --- a/avahi-common/domain.c +++ b/avahi-common/domain.c @@ -206,31 +206,35 @@ char *avahi_normalize_name(const char *s, char *ret_s, size_t size) { assert(size > 0); r = ret_s; + *ret_s = 0; + while (*s) { char label[AVAHI_LABEL_MAX]; if (!(avahi_unescape_label(&s, label, sizeof(label)))) return NULL; - if (strlen(label) > 0) { - - if (!empty) { - if (size < 1) - return NULL; + if (label[0] == 0) { - *(r++) = '.'; - size--; + if (*s == 0 && empty) + return ret_s; - } else - empty = 0; - - avahi_escape_label(label, strlen(label), &r, &size); + return NULL; } + + if (!empty) { + if (size < 1) + return NULL; + + *(r++) = '.'; + size--; + + } else + empty = 0; + + avahi_escape_label(label, strlen(label), &r, &size); } - if (empty) - return NULL; - return ret_s; } @@ -409,9 +413,10 @@ int avahi_is_valid_service_subtype(const char *t) { } int avahi_is_valid_domain_name(const char *t) { + int is_first = 1; assert(t); - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t) + if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX) return 0; do { @@ -420,7 +425,13 @@ int avahi_is_valid_domain_name(const char *t) { if (!(avahi_unescape_label(&t, label, sizeof(label)))) return 0; - if (strlen(label) < 1) + /* Explicitly allow the root domain name */ + if (is_first && label[0] == 0 && *t == 0) + return 1; + + is_first = 0; + + if (label[0] == 0) return 0; } while (*t); diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c index 51deaea..754988c 100644 --- a/avahi-core/avahi-test.c +++ b/avahi-core/avahi-test.c @@ -124,7 +124,8 @@ static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntry static void server_callback(AvahiServer *s, AvahiServerState state, void* userdata) { - avahi_log_debug("server state: %i", state); + server = s; + avahi_log_debug("server state: %i", state); if (state == AVAHI_SERVER_RUNNING) { avahi_log_debug("Server startup complete. Host name is <%s>. Service cookie is %u", avahi_server_get_host_name_fqdn(s), avahi_server_get_local_service_cookie(s)); diff --git a/avahi-core/dns-srv-rr.h b/avahi-core/dns-srv-rr.h index 6111ff6..c6a5770 100644 --- a/avahi-core/dns-srv-rr.h +++ b/avahi-core/dns-srv-rr.h @@ -59,20 +59,6 @@ int avahi_server_add_dns_server_address( const AvahiAddress *address, uint16_t port /** should be 53 */); -/** Similar to avahi_server_add_dns_server_address(), but specify a -host name instead of an address. The specified host name should be -resolvable via mDNS */ -int avahi_server_add_dns_server_name( - AvahiServer *s, - AvahiSEntryGroup *g, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiPublishFlags flags, - const char *domain, - AvahiDNSServerType type, - const char *name, - uint16_t port /** should be 53 */); - /** Callback prototype for AvahiSDNSServerBrowser events */ typedef void (*AvahiSDNSServerBrowserCallback)( AvahiSDNSServerBrowser *b, diff --git a/avahi-core/entry.c b/avahi-core/entry.c index 18fe431..5ef2a67 100644 --- a/avahi-core/entry.c +++ b/avahi-core/entry.c @@ -149,46 +149,34 @@ static int check_record_conflict(AvahiServer *s, AvahiIfIndex interface, AvahiPr return 0; } -int avahi_server_add( +static AvahiEntry * server_add_internal( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, AvahiProtocol protocol, AvahiPublishFlags flags, AvahiRecord *r) { + + AvahiEntry *e; assert(s); assert(r); - if (!AVAHI_IF_VALID(interface)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_INTERFACE); - - if (!AVAHI_PROTO_VALID(protocol)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); - - if (!AVAHI_FLAGS_VALID( - flags, - AVAHI_PUBLISH_NO_ANNOUNCE| - AVAHI_PUBLISH_NO_PROBE| - AVAHI_PUBLISH_UNIQUE| - AVAHI_PUBLISH_ALLOW_MULTIPLE| - AVAHI_PUBLISH_UPDATE)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); - - if (!avahi_is_valid_domain_name(r->key->name)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME); - - if (r->ttl == 0) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_TTL); - - if (avahi_key_is_pattern(r->key)) - return avahi_server_set_errno(s, AVAHI_ERR_IS_PATTERN); - - if (!avahi_record_is_valid(r)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_RECORD); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_FLAGS_VALID( + flags, + AVAHI_PUBLISH_NO_ANNOUNCE| + AVAHI_PUBLISH_NO_PROBE| + AVAHI_PUBLISH_UNIQUE| + AVAHI_PUBLISH_ALLOW_MULTIPLE| + AVAHI_PUBLISH_UPDATE), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_is_valid_domain_name(r->key->name), AVAHI_ERR_INVALID_HOST_NAME); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, r->ttl != 0, AVAHI_ERR_INVALID_TTL); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, !avahi_key_is_pattern(r->key), AVAHI_ERR_IS_PATTERN); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_record_is_valid(r), AVAHI_ERR_INVALID_RECORD); if (flags & AVAHI_PUBLISH_UPDATE) { - AvahiEntry *e; AvahiRecord *old_record; int is_first = 1; @@ -203,8 +191,10 @@ int avahi_server_add( } /* Hmm, nothing found? */ - if (!e) - return avahi_server_set_errno(s, AVAHI_ERR_NOT_FOUND); + if (!e) { + avahi_server_set_errno(s, AVAHI_ERR_NOT_FOUND); + return NULL; + } /* Update the entry */ old_record = e->record; @@ -229,15 +219,19 @@ int avahi_server_add( avahi_record_unref(old_record); } else { - AvahiEntry *e, *t; + AvahiEntry *t; /* Add a new record */ - if (check_record_conflict(s, interface, protocol, r, flags) < 0) - return avahi_server_set_errno(s, AVAHI_ERR_LOCAL_COLLISION); + if (check_record_conflict(s, interface, protocol, r, flags) < 0) { + avahi_server_set_errno(s, AVAHI_ERR_LOCAL_COLLISION); + return NULL; + } - if (!(e = avahi_new(AvahiEntry, 1))) - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + if (!(e = avahi_new(AvahiEntry, 1))) { + avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + return NULL; + } e->server = s; e->record = avahi_record_ref(r); @@ -263,6 +257,20 @@ int avahi_server_add( avahi_announce_entry(s, e); } + return e; +} + +int avahi_server_add( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + AvahiRecord *r) { + + if (!server_add_internal(s, g, interface, protocol, flags, r)) + return avahi_server_errno(s); + return AVAHI_OK; } @@ -314,7 +322,7 @@ int avahi_server_dump(AvahiServer *s, AvahiDumpCallback callback, void* userdata return AVAHI_OK; } -int avahi_server_add_ptr( +static AvahiEntry *server_add_ptr_internal( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, @@ -325,24 +333,46 @@ int avahi_server_add_ptr( const char *dest) { AvahiRecord *r; - int ret; - + AvahiEntry *e; + assert(s); assert(dest); - if ((name && !avahi_is_valid_domain_name(name)) || !avahi_is_valid_domain_name(dest)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, !name || avahi_is_valid_domain_name(name), AVAHI_ERR_INVALID_HOST_NAME); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_is_valid_domain_name(dest), AVAHI_ERR_INVALID_HOST_NAME); if (!name) name = s->host_name_fqdn; - if (!(r = avahi_record_new_full(name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR, ttl))) - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + if (!(r = avahi_record_new_full(name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR, ttl))) { + avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + return NULL; + } r->data.ptr.name = avahi_normalize_name_strdup(dest); - ret = avahi_server_add(s, g, interface, protocol, flags, r); + e = server_add_internal(s, g, interface, protocol, flags, r); avahi_record_unref(r); - return ret; + return e; +} + +int avahi_server_add_ptr( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + uint32_t ttl, + const char *name, + const char *dest) { + + AvahiEntry *e; + + assert(s); + + if (!(e = server_add_ptr_internal(s, g, interface, protocol, flags, ttl, name, dest))) + return avahi_server_errno(s); + + return AVAHI_OK; } int avahi_server_add_address( @@ -354,98 +384,83 @@ int avahi_server_add_address( const char *name, AvahiAddress *a) { - char *n = NULL; + char n[AVAHI_DOMAIN_NAME_MAX]; int ret = AVAHI_OK; + AvahiEntry *entry = NULL, *reverse = NULL; + AvahiRecord *r; assert(s); assert(a); - if (!AVAHI_IF_VALID(interface)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_INTERFACE); + AVAHI_CHECK_VALIDITY(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); + AVAHI_CHECK_VALIDITY(s, AVAHI_PROTO_VALID(protocol) && AVAHI_PROTO_VALID(a->proto), AVAHI_ERR_INVALID_PROTOCOL); + AVAHI_CHECK_VALIDITY(s, AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_REVERSE|AVAHI_PUBLISH_NO_ANNOUNCE|AVAHI_PUBLISH_NO_PROBE|AVAHI_PUBLISH_UPDATE), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY(s, !name || avahi_is_valid_domain_name(name), AVAHI_ERR_INVALID_HOST_NAME); - if (!AVAHI_PROTO_VALID(protocol) || !AVAHI_PROTO_VALID(a->proto)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); - - if (!AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_REVERSE|AVAHI_PUBLISH_NO_ANNOUNCE|AVAHI_PUBLISH_NO_PROBE|AVAHI_PUBLISH_UPDATE)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); + /* Prepare the host naem */ - if (name && !avahi_is_valid_domain_name(name)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME); - if (!name) name = s->host_name_fqdn; else { - if (!(n = avahi_normalize_name_strdup(name))) - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - + AVAHI_ASSERT_TRUE(avahi_normalize_name(name, n, sizeof(n))); name = n; } + + /* Create the A/AAAA record */ if (a->proto == AVAHI_PROTO_INET) { - AvahiRecord *r; if (!(r = avahi_record_new_full(name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, AVAHI_DEFAULT_TTL_HOST_NAME))) { ret = avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - goto fail; + goto finish; } r->data.a.address = a->data.ipv4; - ret = avahi_server_add(s, g, interface, protocol, (flags & ~ AVAHI_PUBLISH_NO_REVERSE) | AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_ALLOW_MULTIPLE, r); - avahi_record_unref(r); - - if (ret < 0) - goto fail; - - if (!(flags & AVAHI_PUBLISH_NO_REVERSE)) { - char *reverse; - - if (!(reverse = avahi_reverse_lookup_name_ipv4(&a->data.ipv4))) { - ret = avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - goto fail; - } - - ret = avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_PUBLISH_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name); - avahi_free(reverse); - } } else { - AvahiRecord *r; - assert(a->proto == AVAHI_PROTO_INET6); if (!(r = avahi_record_new_full(name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, AVAHI_DEFAULT_TTL_HOST_NAME))) { ret = avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - goto fail; + goto finish; } r->data.aaaa.address = a->data.ipv6; - ret = avahi_server_add(s, g, interface, protocol, (flags & ~ AVAHI_PUBLISH_NO_REVERSE) | AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_ALLOW_MULTIPLE, r); - avahi_record_unref(r); - - if (ret < 0) - goto fail; + } + + entry = server_add_internal(s, g, interface, protocol, (flags & ~ AVAHI_PUBLISH_NO_REVERSE) | AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_ALLOW_MULTIPLE, r); + avahi_record_unref(r); - if (!(flags & AVAHI_PUBLISH_NO_REVERSE)) { - char *reverse; + if (!entry) { + ret = avahi_server_errno(s); + goto finish; + } - if (!(reverse = avahi_reverse_lookup_name_ipv6(&a->data.ipv6))) { - ret = avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - goto fail; - } + /* Create the reverse lookup entry */ + + if (!(flags & AVAHI_PUBLISH_NO_REVERSE)) { + char reverse_n[AVAHI_DOMAIN_NAME_MAX]; + avahi_reverse_lookup_name(reverse_n, sizeof(reverse_n), a); - ret = avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_PUBLISH_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name); - avahi_free(reverse); + if (!(reverse = server_add_ptr_internal(s, g, interface, protocol, flags | AVAHI_PUBLISH_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse_n, name))) { + ret = avahi_server_errno(s); + goto finish; } } - -fail: - avahi_free(n); +finish: + + if (ret != AVAHI_OK && !(flags & AVAHI_PUBLISH_UPDATE)) { + if (entry) + avahi_entry_free(s, entry); + if (reverse) + avahi_entry_free(s, reverse); + } return ret; } -static int server_add_txt_strlst_nocopy( +static AvahiEntry *server_add_txt_strlst_nocopy( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, @@ -456,20 +471,21 @@ static int server_add_txt_strlst_nocopy( AvahiStringList *strlst) { AvahiRecord *r; - int ret; + AvahiEntry *e; assert(s); if (!(r = avahi_record_new_full(name ? name : s->host_name_fqdn, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, ttl))) { avahi_string_list_free(strlst); - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + return NULL; } r->data.txt.string_list = strlst; - ret = avahi_server_add(s, g, interface, protocol, flags, r); + e = server_add_internal(s, g, interface, protocol, flags, r); avahi_record_unref(r); - return ret; + return e; } static AvahiStringList *add_magic_cookie( @@ -504,6 +520,7 @@ static int server_add_service_strlst_nocopy( char ptr_name[AVAHI_DOMAIN_NAME_MAX], svc_name[AVAHI_DOMAIN_NAME_MAX], enum_ptr[AVAHI_DOMAIN_NAME_MAX], *h = NULL; AvahiRecord *r = NULL; int ret = AVAHI_OK; + AvahiEntry *srv_entry = NULL, *txt_entry = NULL, *ptr_entry = NULL, *enum_entry = NULL; assert(s); assert(type); @@ -537,8 +554,10 @@ static int server_add_service_strlst_nocopy( /* Add service enumeration PTR record */ - if ((ret = avahi_server_add_ptr(s, g, interface, protocol, 0, AVAHI_DEFAULT_TTL, ptr_name, svc_name)) < 0) + if (!(ptr_entry = server_add_ptr_internal(s, g, interface, protocol, 0, AVAHI_DEFAULT_TTL, ptr_name, svc_name))) { + ret = avahi_server_errno(s); goto fail; + } /* Add SRV record */ @@ -552,28 +571,45 @@ static int server_add_service_strlst_nocopy( r->data.srv.port = port; r->data.srv.name = h; h = NULL; - ret = avahi_server_add(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE, r); + srv_entry = server_add_internal(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE, r); avahi_record_unref(r); - if (ret < 0) + if (!srv_entry) { + ret = avahi_server_errno(s); goto fail; + } /* Add TXT record */ if (!(flags & AVAHI_PUBLISH_NO_COOKIE)) strlst = add_magic_cookie(s, strlst); - ret = server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE, AVAHI_DEFAULT_TTL, svc_name, strlst); + txt_entry = server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE, AVAHI_DEFAULT_TTL, svc_name, strlst); strlst = NULL; - if (ret < 0) + if (!txt_entry) { + ret = avahi_server_errno(s); goto fail; + } /* Add service type enumeration record */ - ret = avahi_server_add_ptr(s, g, interface, protocol, 0, AVAHI_DEFAULT_TTL, enum_ptr, ptr_name); + if (!(enum_entry = server_add_ptr_internal(s, g, interface, protocol, 0, AVAHI_DEFAULT_TTL, enum_ptr, ptr_name))) { + ret = avahi_server_errno(s); + goto fail; + } fail: + if (ret != AVAHI_OK && !(flags & AVAHI_PUBLISH_UPDATE)) { + if (srv_entry) + avahi_entry_free(s, srv_entry); + if (txt_entry) + avahi_entry_free(s, txt_entry); + if (ptr_entry) + avahi_entry_free(s, ptr_entry); + if (enum_entry) + avahi_entry_free(s, enum_entry); + } avahi_string_list_free(strlst); avahi_free(h); @@ -637,6 +673,7 @@ static int server_update_service_txt_strlst_nocopy( char svc_name[AVAHI_DOMAIN_NAME_MAX]; int ret = AVAHI_OK; + AvahiEntry *e; assert(s); assert(type); @@ -661,9 +698,12 @@ static int server_update_service_txt_strlst_nocopy( if (!(flags & AVAHI_PUBLISH_NO_COOKIE)) strlst = add_magic_cookie(s, strlst); - ret = server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_UPDATE, AVAHI_DEFAULT_TTL, svc_name, strlst); + e = server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_UPDATE, AVAHI_DEFAULT_TTL, svc_name, strlst); strlst = NULL; + if (!e) + ret = avahi_server_errno(s); + fail: avahi_string_list_free(strlst); @@ -772,7 +812,7 @@ static void hexstring(char *s, size_t sl, const void *p, size_t pl) { *s = 0; } -int avahi_server_add_dns_server_address( +static AvahiEntry * server_add_dns_server_name( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, @@ -780,59 +820,52 @@ int avahi_server_add_dns_server_address( AvahiPublishFlags flags, const char *domain, AvahiDNSServerType type, - const AvahiAddress *address, + const char *name, uint16_t port /** should be 53 */) { + AvahiEntry *e; + char t[AVAHI_DOMAIN_NAME_MAX], normalized_d[AVAHI_DOMAIN_NAME_MAX], *n; + AvahiRecord *r; - int ret; - char n[64], h[64]; - + assert(s); - assert(address); - - if (!AVAHI_IF_VALID(interface)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_INTERFACE); + assert(name); - if (!AVAHI_PROTO_VALID(protocol) || !AVAHI_PROTO_VALID(address->proto)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_FLAGS_VALID(flags, 0), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, type == AVAHI_DNS_SERVER_UPDATE || type == AVAHI_DNS_SERVER_RESOLVE, AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, port != 0, AVAHI_ERR_INVALID_PORT); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_is_valid_domain_name(name), AVAHI_ERR_INVALID_HOST_NAME); + AVAHI_CHECK_VALIDITY_RETURN_NULL(s, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME); - if (!AVAHI_FLAGS_VALID(flags, 0) || (type != AVAHI_DNS_SERVER_UPDATE && type != AVAHI_DNS_SERVER_RESOLVE)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); - - if (port == 0) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PORT); - - if (domain && !avahi_is_valid_domain_name(domain)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME); - if (!domain) domain = s->domain_name; - if (address->proto == AVAHI_PROTO_INET) { - hexstring(h, sizeof(h), &address->data, sizeof(AvahiIPv4Address)); - snprintf(n, sizeof(n), "ip-%s.%s", h, domain); - r = avahi_record_new_full(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, AVAHI_DEFAULT_TTL_HOST_NAME); - r->data.a.address = address->data.ipv4; - } else { - hexstring(h, sizeof(h), &address->data, sizeof(AvahiIPv6Address)); - snprintf(n, sizeof(n), "ip6-%s.%s", h, domain); - r = avahi_record_new_full(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, AVAHI_DEFAULT_TTL_HOST_NAME); - r->data.aaaa.address = address->data.ipv6; + if (!(n = avahi_normalize_name_strdup(name))) { + avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + return NULL; } + + AVAHI_ASSERT_TRUE(avahi_normalize_name(domain, normalized_d, sizeof(normalized_d))); - if (!r) - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + snprintf(t, sizeof(t), "%s.%s", type == AVAHI_DNS_SERVER_RESOLVE ? "_domain._udp" : "_dns-update._udp", normalized_d); + + if (!(r = avahi_record_new_full(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV, AVAHI_DEFAULT_TTL_HOST_NAME))) { + avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + avahi_free(n); + return NULL; + } - ret = avahi_server_add(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_ALLOW_MULTIPLE, r); + r->data.srv.priority = 0; + r->data.srv.weight = 0; + r->data.srv.port = port; + r->data.srv.name = n; + e = server_add_internal(s, g, interface, protocol, 0, r); avahi_record_unref(r); - if (ret < 0) - return ret; - - return avahi_server_add_dns_server_name(s, g, interface, protocol, flags, domain, type, n, port); + return e; } -int avahi_server_add_dns_server_name( +int avahi_server_add_dns_server_address( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, @@ -840,60 +873,54 @@ int avahi_server_add_dns_server_name( AvahiPublishFlags flags, const char *domain, AvahiDNSServerType type, - const char *name, + const AvahiAddress *address, uint16_t port /** should be 53 */) { - int ret = -1; - char t[256], *d = NULL, *n = NULL; AvahiRecord *r; - - assert(s); - assert(name); - - if (!AVAHI_IF_VALID(interface)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_INTERFACE); - - if (!AVAHI_PROTO_VALID(protocol)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); + char n[64], h[64]; + AvahiEntry *a_entry, *s_entry; - if (!AVAHI_FLAGS_VALID(flags, 0) || (type != AVAHI_DNS_SERVER_UPDATE && type != AVAHI_DNS_SERVER_RESOLVE)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); - - if (port == 0) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PORT); + assert(s); + assert(address); - if (!avahi_is_valid_domain_name(name)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME); + AVAHI_CHECK_VALIDITY(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); + AVAHI_CHECK_VALIDITY(s, AVAHI_PROTO_VALID(protocol) && AVAHI_PROTO_VALID(address->proto), AVAHI_ERR_INVALID_PROTOCOL); + AVAHI_CHECK_VALIDITY(s, AVAHI_FLAGS_VALID(flags, 0), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY(s, type == AVAHI_DNS_SERVER_UPDATE || type == AVAHI_DNS_SERVER_RESOLVE, AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY(s, port != 0, AVAHI_ERR_INVALID_PORT); + AVAHI_CHECK_VALIDITY(s, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME); - if (domain && !avahi_is_valid_domain_name(domain)) - return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME); - if (!domain) domain = s->domain_name; - if (!(n = avahi_normalize_name_strdup(name)) || - !(d = avahi_normalize_name_strdup(domain))) { - avahi_free(n); - avahi_free(d); - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + if (address->proto == AVAHI_PROTO_INET) { + hexstring(h, sizeof(h), &address->data, sizeof(AvahiIPv4Address)); + snprintf(n, sizeof(n), "ip-%s.%s", h, domain); + r = avahi_record_new_full(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, AVAHI_DEFAULT_TTL_HOST_NAME); + r->data.a.address = address->data.ipv4; + } else { + hexstring(h, sizeof(h), &address->data, sizeof(AvahiIPv6Address)); + snprintf(n, sizeof(n), "ip6-%s.%s", h, domain); + r = avahi_record_new_full(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, AVAHI_DEFAULT_TTL_HOST_NAME); + r->data.aaaa.address = address->data.ipv6; } - snprintf(t, sizeof(t), "%s.%s", type == AVAHI_DNS_SERVER_RESOLVE ? "_domain._udp" : "_dns-update._udp", d); - avahi_free(d); - - if (!(r = avahi_record_new_full(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV, AVAHI_DEFAULT_TTL_HOST_NAME))) { - avahi_free(n); + if (!r) return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); - } - r->data.srv.priority = 0; - r->data.srv.weight = 0; - r->data.srv.port = port; - r->data.srv.name = n; - ret = avahi_server_add(s, g, interface, protocol, 0, r); + a_entry = server_add_internal(s, g, interface, protocol, AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_ALLOW_MULTIPLE, r); avahi_record_unref(r); - return ret; + if (!a_entry) + return avahi_server_errno(s); + + if (!(s_entry = server_add_dns_server_name(s, g, interface, protocol, flags, domain, type, n, port))) { + if (!(flags & AVAHI_PUBLISH_UPDATE)) + avahi_entry_free(s, a_entry); + return avahi_server_errno(s); + } + + return AVAHI_OK; } void avahi_s_entry_group_change_state(AvahiSEntryGroup *g, AvahiEntryGroupState state) { diff --git a/avahi-core/internal.h b/avahi-core/internal.h index 27edde8..8f18219 100644 --- a/avahi-core/internal.h +++ b/avahi-core/internal.h @@ -194,7 +194,10 @@ int avahi_server_add_ptr( const char *dest); - +#define AVAHI_CHECK_VALIDITY(server, expression, error) { \ + if (!(expression)) \ + return avahi_server_set_errno((server), (error)); \ +} #define AVAHI_CHECK_VALIDITY_RETURN_NULL(server, expression, error) { \ if (!(expression)) { \ @@ -210,4 +213,14 @@ int avahi_server_add_ptr( } \ } +#define AVAHI_ASSERT_TRUE(expression) { \ + int __tmp = !!(expression); \ + assert(__tmp); \ +} + +#define AVAHI_ASSERT_SUCCESS(expression) { \ + int __tmp = (expression); \ + assert(__tmp == 0); \ +} + #endif diff --git a/avahi-core/resolve-address.c b/avahi-core/resolve-address.c index 08168b6..c9aae0c 100644 --- a/avahi-core/resolve-address.c +++ b/avahi-core/resolve-address.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "browse.h" @@ -184,7 +185,7 @@ AvahiSAddressResolver *avahi_s_address_resolver_new( AvahiSAddressResolver *r; AvahiKey *k; - char *n; + char n[AVAHI_DOMAIN_NAME_MAX]; assert(server); assert(address); @@ -202,20 +203,9 @@ AvahiSAddressResolver *avahi_s_address_resolver_new( return NULL; } - if (address->proto == AVAHI_PROTO_INET) - n = avahi_reverse_lookup_name_ipv4(&address->data.ipv4); - else - n = avahi_reverse_lookup_name_ipv6(&address->data.ipv6); + avahi_reverse_lookup_name(n, sizeof(n), address); - if (!n) { - avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY); - return NULL; - } - - k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR); - avahi_free(n); - - if (!k) { + if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) { avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY); return NULL; } diff --git a/avahi-core/rr.c b/avahi-core/rr.c index c1faa50..ef1c3d6 100644 --- a/avahi-core/rr.c +++ b/avahi-core/rr.c @@ -72,7 +72,6 @@ AvahiKey *avahi_key_new_cname(AvahiKey *key) { return avahi_key_new(key->name, key->clazz, AVAHI_DNS_TYPE_CNAME); } - AvahiKey *avahi_key_ref(AvahiKey *k) { assert(k); assert(k->ref >= 1); diff --git a/avahi-core/socket.c b/avahi-core/socket.c index 9be9ece..1360110 100644 --- a/avahi-core/socket.c +++ b/avahi-core/socket.c @@ -451,17 +451,17 @@ int avahi_send_dns_packet_ipv4(int fd, int interface, AvahiDnsPacket *p, const A #ifdef IP_PKTINFO if (interface >= 0) { + struct in_pktinfo *pkti; + memset(cmsg_data, 0, sizeof(cmsg_data)); cmsg = (struct cmsghdr*) cmsg_data; cmsg->cmsg_len = sizeof(cmsg_data); cmsg->cmsg_level = IPPROTO_IP; - { - struct in_pktinfo *pkti; + cmsg->cmsg_type = IP_PKTINFO; + + pkti = (struct in_pktinfo*) (cmsg_data + sizeof(struct cmsghdr)); + pkti->ipi_ifindex = interface; - cmsg->cmsg_type = IP_PKTINFO; - pkti = (struct in_pktinfo*) (cmsg_data + sizeof(struct cmsghdr)); - pkti->ipi_ifindex = interface; - } msg.msg_control = cmsg_data; msg.msg_controllen = sizeof(cmsg_data); } else { diff --git a/avahi-core/wide-area.c b/avahi-core/wide-area.c index c5508b0..83337a5 100644 --- a/avahi-core/wide-area.c +++ b/avahi-core/wide-area.c @@ -119,33 +119,34 @@ static AvahiWideAreaLookup* find_lookup(AvahiWideAreaLookupEngine *e, uint16_t i return l; } -static int send_to_dns_server(AvahiWideAreaLookupEngine *e, AvahiDnsPacket *p) { +static int send_to_dns_server(AvahiWideAreaLookup *l, AvahiDnsPacket *p) { AvahiAddress *a; - assert(e); + assert(l); assert(p); - if (e->n_dns_servers <= 0) + if (l->engine->n_dns_servers <= 0) return -1; - assert(e->current_dns_server < e->n_dns_servers); + assert(l->engine->current_dns_server < l->engine->n_dns_servers); - a = &e->dns_servers[e->current_dns_server]; + a = &l->engine->dns_servers[l->engine->current_dns_server]; + l->dns_server_used = *a; if (a->proto == AVAHI_PROTO_INET) { - if (e->fd_ipv4 < 0) + if (l->engine->fd_ipv4 < 0) return -1; - return avahi_send_dns_packet_ipv4(e->fd_ipv4, AVAHI_IF_UNSPEC, p, &a->data.ipv4, AVAHI_DNS_PORT); + return avahi_send_dns_packet_ipv4(l->engine->fd_ipv4, AVAHI_IF_UNSPEC, p, &a->data.ipv4, AVAHI_DNS_PORT); } else { assert(a->proto == AVAHI_PROTO_INET6); - if (e->fd_ipv6 < 0) + if (l->engine->fd_ipv6 < 0) return -1; - return avahi_send_dns_packet_ipv6(e->fd_ipv6, AVAHI_IF_UNSPEC, p, &a->data.ipv6, AVAHI_DNS_PORT); + return avahi_send_dns_packet_ipv6(l->engine->fd_ipv6, AVAHI_IF_UNSPEC, p, &a->data.ipv6, AVAHI_DNS_PORT); } } @@ -182,7 +183,7 @@ static void sender_timeout_callback(AvahiTimeEvent *e, void *userdata) { } assert(l->packet); - send_to_dns_server(l->engine, l->packet); + send_to_dns_server(l, l->packet); l->n_send++; avahi_time_event_update(e, avahi_elapse_time(&tv, 1000, 0)); @@ -231,7 +232,7 @@ AvahiWideAreaLookup *avahi_wide_area_lookup_new( avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1); - if (send_to_dns_server(e, l->packet) < 0) { + if (send_to_dns_server(l, l->packet) < 0) { avahi_log_error(__FILE__": Failed to send packet."); avahi_dns_packet_free(l->packet); avahi_key_unref(l->key); -- 2.39.5