#endif
#include <stdio.h>
+#include <string.h>
+#include <assert.h>
#include "domain.h"
#include "malloc.h"
int main(int argc, char *argv[]) {
char *s;
- char t[256];
+ char t[256], r[256];
+ const char *p;
+ 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());
+ printf("host name: %s\n", s = avahi_get_host_name_strdup());
avahi_free(s);
- printf("%s\n", s = avahi_normalize_name("foo.foo."));
+ printf("%s\n", s = avahi_normalize_name_strdup("foo.foo\\046."));
avahi_free(s);
- printf("%s\n", s = avahi_normalize_name("foo\.foo."));
+ printf("%s\n", s = avahi_normalize_name_strdup("foo.foo\\.foo."));
avahi_free(s);
- printf("%s\n", s = avahi_normalize_name("\\f\\o\\\\o\\..\\f\\ \\o\\o."));
+ printf("%s\n", s = avahi_normalize_name_strdup("fo\\\\o\\..f oo."));
avahi_free(s);
- printf("%i\n", avahi_domain_equal("\\aaa bbb\\.cccc\\\\.dee.fff.", "aaa\\ bbb\\.cccc\\\\.dee.fff"));
- printf("%i\n", avahi_domain_equal("\\A", "a"));
+ printf("%i\n", avahi_domain_equal("\\065aa bbb\\.\\046cc.cc\\\\.dee.fff.", "Aaa BBB\\.\\.cc.cc\\\\.dee.fff"));
+ printf("%i\n", avahi_domain_equal("A", "a"));
printf("%i\n", avahi_domain_equal("a", "aaa"));
- printf("%u = %u\n", avahi_domain_hash("\\Aaaab\\\\."), avahi_domain_hash("aaaa\\b\\\\"));
+ printf("%u = %u\n", avahi_domain_hash("ccc\\065aa.aa\\.b\\\\."), avahi_domain_hash("cccAaa.aa\\.b\\\\"));
- avahi_service_name_snprint(t, sizeof(t), "foo.foo.foo \.", "_http._tcp", "test.local");
+ avahi_service_name_join(t, sizeof(t), "foo.foo.foo \.", "_http._tcp", "test.local");
printf("<%s>\n", t);
-
- avahi_service_name_snprint(t, sizeof(t), NULL, "_http._tcp", "one.two\. .local");
+ avahi_service_name_split(t, name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+ printf("name: <%s>; type: <%s>; domain <%s>\n", name, type, domain);
+
+ avahi_service_name_join(t, sizeof(t), NULL, "_http._tcp", "one.two\. .local");
printf("<%s>\n", t);
+ avahi_service_name_split(t, NULL, 0, type, sizeof(type), domain, sizeof(domain));
+ printf("name: <>; type: <%s>; domain <%s>\n", type, domain);
+
+
+ p = "--:---\\\\\\123\\065_äöü\\064\\.\\\\sjöödfhh.sdfjhskjdf";
+ printf("unescaped: <%s>, rest: %s\n", avahi_unescape_label(&p, t, sizeof(t)), p);
+
+ size = sizeof(r);
+ s = r;
+ printf("escaped: <%s>\n", avahi_escape_label(t, strlen(t), &s, &size));
+
+ 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("_foo._bar._waldo"));
+ assert(!avahi_is_valid_service_type("_foo._bar.waldo"));
+ assert(!avahi_is_valid_service_type(""));
+
+ assert(!avahi_is_valid_host_name("sf.ooo."));
+ assert(avahi_is_valid_host_name("sfooo."));
+ assert(avahi_is_valid_host_name("sfooo"));
+
return 0;
}
#include "malloc.h"
#include "error.h"
-char *avahi_get_host_name(void) {
+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
- gethostname(t, sizeof(t));
- t[sizeof(t)-1] = 0;
- return avahi_normalize_name(t);
-}
-
-static char *unescape_uneeded(const char *src, char *ret_dest, size_t size) {
- int escaped = 0;
- assert(src);
- assert(ret_dest);
+ assert(ret_s);
assert(size > 0);
- for (; *src; src++) {
-
- if (!escaped && *src == '\\')
- escaped = 1;
- else if (escaped && (*src == '.' || *src == '\\')) {
-
- if ((size -= 2) <= 1) break;
-
- *(ret_dest++) = '\\';
- *(ret_dest++) = *src;
- escaped = 0;
- } else {
- if (--size <= 1) break;
-
- *(ret_dest++) = *src;
- escaped = 0;
- }
-
- }
-
- *ret_dest = 0;
+ gethostname(t, sizeof(t));
+ t[sizeof(t)-1] = 0;
- return ret_dest;
+ return avahi_normalize_name(t, ret_s, size);
}
-char *avahi_normalize_name(const char *s) {
- char tmp[256];
- size_t l;
-
- assert(s);
-
- unescape_uneeded(s, tmp, sizeof(tmp));
-
- l = strlen(tmp);
+char *avahi_get_host_name_strdup(void) {
+ char t[AVAHI_DOMAIN_NAME_MAX];
- while (l > 0 && tmp[l-1] == '.')
- tmp[--l] = 0;
+ if (!(avahi_get_host_name(t, sizeof(t))))
+ return NULL;
- return avahi_strdup(tmp);
+ 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;
assert(size > 0);
assert(name);
- if (!**name)
- return NULL;
-
d = dest;
for (;;) {
break;
if (**name == '\\') {
+ /* Escaped character */
+
(*name) ++;
-
+
if (**name == 0)
- break;
+ /* Ending NUL */
+ return NULL;
+
+ else if (**name == '\\' || **name == '.') {
+ /* Escaped backslash or dot */
+ *(d++) = *((*name) ++);
+ i++;
+ } else if (isdigit(**name)) {
+ int n;
+
+ /* Escaped literal ASCII character */
+
+ if (!isdigit(*(*name+1)) || !isdigit(*(*name+2)))
+ return NULL;
+
+ n = ((uint8_t) (**name - '0') * 100) + ((uint8_t) (*(*name+1) - '0') * 10) + ((uint8_t) (*(*name +2) - '0'));
+
+ if (n > 255 || n == 0)
+ return NULL;
+
+ *(d++) = (char) n;
+ i++;
+
+ (*name) += 3;
+ } else
+ return NULL;
+
+ } else {
+
+ /* Normal character */
+
+ *(d++) = *((*name) ++);
+ i++;
}
-
- *(d++) = *((*name) ++);
- i++;
}
assert(i < size);
}
/* Escape "\" and ".", append \0 */
-char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size) {
+char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, size_t *ret_size) {
char *r;
assert(src);
while (src_length > 0) {
if (*src == '.' || *src == '\\') {
+
+ /* Dot or backslash */
+
if (*ret_size < 3)
return NULL;
*((*ret_name) ++) = '\\';
+ *((*ret_name) ++) = *src;
+ (*ret_size) -= 2;
+
+ } else if (
+ *src == '_' ||
+ *src == '-' ||
+ (*src >= '0' && *src <= '9') ||
+ (*src >= 'a' && *src <= 'z') ||
+ (*src >= 'A' && *src <= 'Z')) {
+
+ /* Proper character */
+
+ if (*ret_size < 2)
+ return NULL;
+
+ *((*ret_name)++) = *src;
(*ret_size) --;
- }
+
+ } else {
- if (*ret_size < 2)
- return NULL;
-
- *((*ret_name)++) = *src;
- (*ret_size) --;
+ /* Everything else */
+
+ if (*ret_size < 5)
+ return NULL;
+
+ *((*ret_name) ++) = '\\';
+ *((*ret_name) ++) = '0' + (char) ((uint8_t) *src / 100);
+ *((*ret_name) ++) = '0' + (char) (((uint8_t) *src / 10) % 10);
+ *((*ret_name) ++) = '0' + (char) ((uint8_t) *src % 10);
+
+ (*ret_size) -= 4;
+ }
src_length --;
src++;
return r;
}
+char *avahi_normalize_name(const char *s, char *ret_s, size_t size) {
+ int empty = 1;
+ char *r;
+
+ assert(s);
+ assert(ret_s);
+ assert(size > 0);
+
+ r = ret_s;
+ 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;
+
+ *(r++) = '.';
+ size--;
+
+ } else
+ empty = 0;
+
+ avahi_escape_label(label, strlen(label), &r, &size);
+ }
+ }
+
+ if (empty)
+ return NULL;
+
+ return ret_s;
+}
+
+char *avahi_normalize_name_strdup(const char *s) {
+ char t[AVAHI_DOMAIN_NAME_MAX];
+ assert(s);
+
+ if (!(avahi_normalize_name(s, t, sizeof(t))))
+ return NULL;
+
+ return avahi_strdup(t);
+}
+
int avahi_domain_equal(const char *a, const char *b) {
assert(a);
assert(b);
return 1;
for (;;) {
- char ca[65], cb[65], *pa, *pb;
+ char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *r;
- pa = avahi_unescape_label(&a, ca, sizeof(ca));
- pb = avahi_unescape_label(&b, cb, sizeof(cb));
+ r = avahi_unescape_label(&a, ca, sizeof(ca));
+ assert(r);
+ r = avahi_unescape_label(&b, cb, sizeof(cb));
+ assert(r);
- if (!pa && !pb)
- return 1;
- else if ((pa && !pb) || (!pa && pb))
- return 0;
-
- if (strcasecmp(pa, pb))
+ if (strcasecmp(ca, cb))
return 0;
+
+ if (!*a && !*b)
+ return 1;
}
return 1;
return 0;
for (;;) {
- char ca[65], cb[65], *pa, *pb;
+ char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *p;
int r;
- pa = avahi_unescape_label(&a, ca, sizeof(ca));
- pb = avahi_unescape_label(&b, cb, sizeof(cb));
+ p = avahi_unescape_label(&a, ca, sizeof(ca));
+ assert(p);
+ p = avahi_unescape_label(&b, cb, sizeof(cb));
+ assert(p);
- if (!pa && !pb)
- return 0;
- else if (pa && !pb)
- return 1;
- else if (!pa && pb)
- return -1;
-
- if ((r = strcmp(pa, pb)))
+ if ((r = strcmp(ca, cb)))
return r;
+
+ if (!*a && !*b)
+ return 0;
}
}
int avahi_is_valid_service_type(const char *t) {
- const char *p;
assert(t);
- if (strlen(t) < 5)
- return 0;
-
- if (*t != '_')
+ if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
return 0;
- if (!(p = strchr(t, '.')))
- return 0;
+ do {
+ char label[AVAHI_LABEL_MAX];
- if (p - t > 63 || p - t < 2)
- return 0;
-
- if (*(++p) != '_')
- return 0;
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return 0;
- if (strchr(p, '.'))
- return 0;
+ if (strlen(label) <= 2 || label[0] != '_')
+ return 0;
+
+ } while (*t);
- if (strlen(p) > 63 || strlen(p) < 2)
- return 0;
-
return 1;
}
int avahi_is_valid_domain_name(const char *t) {
- const char *p, *dp;
- int dot = 0;
-
assert(t);
- if (*t == 0)
- return 0;
-
- /* Domains may not start with a dot */
- if (*t == '.')
+ if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
return 0;
- dp = t;
+ do {
+ char label[AVAHI_LABEL_MAX];
- for (p = t; *p; p++) {
-
- if (*p == '.') {
- if (dot) /* Two subsequent dots */
- return 0;
-
- if (p - dp > 63)
- return 0;
-
- dot = 1;
- dp = p + 1;
- } else
- dot = 0;
-
- }
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return 0;
- if (p - dp > 63)
- return 0;
+ if (strlen(label) < 1)
+ return 0;
+
+ } while (*t);
- /* A trailing dot IS allowed */
-
return 1;
}
int avahi_is_valid_service_name(const char *t) {
assert(t);
- if (*t == 0)
+ if (strlen(t) >= AVAHI_LABEL_MAX || !*t)
return 0;
-
- if (strlen(t) > 63)
- return 0;
-
+
return 1;
}
int avahi_is_valid_host_name(const char *t) {
+ char label[AVAHI_LABEL_MAX];
assert(t);
- if (*t == 0)
+ if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
+ return 0;
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
return 0;
- if (strlen(t) > 63)
+ if (strlen(label) < 1)
return 0;
- if (strchr(t, '.'))
+ if (*t)
return 0;
return 1;
unsigned avahi_domain_hash(const char *s) {
unsigned hash = 0;
- for (;;) {
- char c[65], *p;
-
- if (!avahi_unescape_label(&s, c, sizeof(c)))
- return hash;
+ while (*s) {
+ char c[AVAHI_LABEL_MAX], *p, *r;
- if (!c[0])
- continue;
+ r = avahi_unescape_label(&s, c, sizeof(c));
+ assert(r);
for (p = c; *p; p++)
hash = 31 * hash + tolower(*p);
}
+
+ return hash;
}
int avahi_domain_ends_with(const char *domain, const char *suffix) {
assert(domain);
assert(suffix);
- assert(avahi_is_valid_domain_name(domain));
- assert(avahi_is_valid_domain_name(suffix));
-
for (;;) {
- char dummy[64];
+ char dummy[AVAHI_LABEL_MAX], *r;
+
+ if (*domain == 0)
+ return 0;
if (avahi_domain_equal(domain, suffix))
return 1;
- if (!(avahi_unescape_label(&domain, dummy, sizeof(dummy))))
- return 0;
+ r = avahi_unescape_label(&domain, dummy, sizeof(dummy));
+ assert(r);
}
}
-static void escape_service_name(char *d, size_t size, const char *s) {
- assert(d);
- assert(size);
- assert(s);
+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];
+ char normalized_type[AVAHI_DOMAIN_NAME_MAX];
+ char normalized_domain[AVAHI_DOMAIN_NAME_MAX];
+
+ assert(p);
- while (*s && size >= 2) {
- if (*s == '.' || *s == '\\') {
- if (size < 3)
- break;
+ /* Validity checks */
+
+ if ((name && !avahi_is_valid_service_name(name)))
+ return AVAHI_ERR_INVALID_SERVICE_NAME;
- *(d++) = '\\';
- size--;
- }
-
- *(d++) = *(s++);
- size--;
+ if (!avahi_is_valid_service_type(type))
+ return AVAHI_ERR_INVALID_SERVICE_TYPE;
+
+ if (!avahi_is_valid_domain_name(domain))
+ return AVAHI_ERR_INVALID_DOMAIN_NAME;
+
+ /* Preparation */
+
+ if (name) {
+ size_t l = sizeof(escaped_name);
+ char *e = escaped_name, *r;
+ r = avahi_escape_label(name, strlen(name), &e, &l);
+ assert(r);
}
- assert(size > 0);
- *(d++) = 0;
-}
+ if (!(avahi_normalize_name(type, normalized_type, sizeof(normalized_type))))
+ return AVAHI_ERR_INVALID_SERVICE_TYPE;
+ if (!(avahi_normalize_name(domain, normalized_domain, sizeof(normalized_domain))))
+ return AVAHI_ERR_INVALID_DOMAIN_NAME;
-int avahi_service_name_snprint(char *p, size_t size, const char *name, const char *type, const char *domain) {
- char *t = NULL, *d = NULL;
- char ename[64];
- int ret;
+ /* Concatenation */
- assert(p);
+ snprintf(p, size, "%s%s%s.%s", name ? escaped_name : "", name ? "." : "", normalized_type, normalized_domain);
- if ((name && !avahi_is_valid_service_name(name))) {
- ret = AVAHI_ERR_INVALID_SERVICE_NAME;
- goto fail;
- }
+ return AVAHI_OK;
+}
- if (!avahi_is_valid_service_type(type)) {
- ret = AVAHI_ERR_INVALID_SERVICE_TYPE;
- goto fail;
- }
-
- if (!avahi_is_valid_domain_name(domain)) {
- ret = AVAHI_ERR_INVALID_DOMAIN_NAME;
- goto fail;
- }
+
+char *avahi_strlcpy(char *dest, const char *src, size_t n) {
+ assert(dest);
+ assert(src);
+
+ if (n == 0)
+ return dest;
- if (name)
- escape_service_name(ename, sizeof(ename), name);
+ strncpy(dest, src, n-1);
+ dest[n-1] = 0;
+ return dest;
+}
+
+int avahi_service_name_split(const char *p, char *name, size_t name_size, char *type, size_t type_size, char *domain, size_t domain_size) {
+ enum {
+ NAME,
+ TYPE,
+ DOMAIN
+ } state;
+ int type_empty = 1, domain_empty = 1;
- if (!(d = avahi_normalize_name(domain)) ||
- !(t = avahi_normalize_name(type))) {
- ret = AVAHI_ERR_NO_MEMORY;
- goto fail;
- }
+ assert(p);
+ assert(type);
+ assert(type_size > 0);
+ assert(domain);
+ assert(domain_size > 0);
+
+ if (name) {
+ assert(name_size > 0);
+ *name = 0;
+ state = NAME;
+ } else
+ state = TYPE;
+
+ *type = *domain = 0;
+
+ while (*p) {
+ char buf[64];
+
+ if (!(avahi_unescape_label(&p, buf, sizeof(buf))))
+ return -1;
- snprintf(p, size, "%s%s%s.%s", name ? ename : "", name ? "." : "", t, d);
+ switch (state) {
+ case NAME:
+ avahi_strlcpy(name, buf, name_size);
+ state = TYPE;
+ break;
- ret = AVAHI_OK;
-
-fail:
+ case TYPE:
+
+ if (buf[0] == '_') {
+
+ if (!type_empty) {
+ if (!type_size)
+ return AVAHI_ERR_NO_MEMORY;
+
+ *(type++) = '.';
+ type_size --;
- avahi_free(t);
- avahi_free(d);
+ } else
+ type_empty = 0;
+
+ if (!(avahi_escape_label(buf, strlen(buf), &type, &type_size)))
+ return AVAHI_ERR_NO_MEMORY;
- return ret;
+ break;
+ }
+
+ state = DOMAIN;
+ /* fall through */
+
+ case DOMAIN:
+
+ if (!domain_empty) {
+ if (!domain_size)
+ return AVAHI_ERR_NO_MEMORY;
+
+ *(domain++) = '.';
+ domain_size --;
+ } else
+ domain_empty = 0;
+
+ if (!(avahi_escape_label(buf, strlen(buf), &domain, &domain_size)))
+ return AVAHI_ERR_NO_MEMORY;
+
+ break;
+ }
+ }
+
+ return 0;
}
+
* the string brings us to 1014. */
#define AVAHI_DOMAIN_NAME_MAX 1014
+/** Maxium size of an unescaped label */
+#define AVAHI_LABEL_MAX 64
+
+/** Normalize a domain name into canonical form. This drops trailing
+ * dots and removes useless backslash escapes. */
+char *avahi_normalize_name(const char *s, char *ret_s, size_t size);
+
/** Normalize a domain name into canonical form. This drops trailing
* dots and removes useless backslash escapes. avahi_free() the
* result! */
-char *avahi_normalize_name(const char *s);
+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(void);
+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);
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 uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size);
+char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, size_t *ret_size);
/** Return 1 when the specified string contains a valid service type, 0 otherwise */
int avahi_is_valid_service_type(const char *t);
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_snprint(char *p, size_t size, const char *name, const char *type, const char *domain);
+int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain);
+
+/** Split a full service name into name, type and domain */
+int avahi_service_name_split(const char *p, char *name, size_t name_size, char *type, size_t type_size, char *domain, size_t domain_size);
+
+/** Just like OpenBSD strlcpy */
+char *avahi_strlcpy(char *dest, const char *src, size_t n);
#ifndef DOXYGEN_SHOULD_SKIP_THIS
AVAHI_C_DECL_END
if ((p = avahi_new0(char, (l = avahi_string_list_serialize(txt, NULL, 0))+1)))
avahi_string_list_serialize(txt, p, l);
- ret = avahi_service_name_snprint(full_name, sizeof(full_name), name, type, domain);
+ ret = avahi_service_name_join(full_name, sizeof(full_name), name, type, domain);
assert(ret == AVAHI_OK);
strcat(full_name, ".");
assert(regtype);
assert(domain);
- if (avahi_service_name_snprint(fullName, kDNSServiceMaxDomainName, service, regtype, domain) < 0)
+ if (avahi_service_name_join(fullName, kDNSServiceMaxDomainName, service, regtype, domain) < 0)
return -1;
return 0;
sdref->service_register_callback = callback;
sdref->service_name = avahi_strdup(name);
- sdref->service_regtype = regtype ? avahi_normalize_name(regtype) : NULL;
- sdref->service_domain = domain ? avahi_normalize_name(domain) : NULL;
- sdref->service_host = host ? avahi_normalize_name(host) : NULL;
+ sdref->service_regtype = regtype ? avahi_normalize_name_strdup(regtype) : NULL;
+ sdref->service_domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
+ sdref->service_host = host ? avahi_normalize_name_strdup(host) : NULL;
sdref->service_interface = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
sdref->service_port = ntohs(port);
sdref->service_txt = txtRecord ? avahi_string_list_parse(txtRecord, txtLen) : NULL;
struct AvahiSDNSServerBrowser {
AvahiServer *server;
- char *domain_name;
AvahiSRecordBrowser *record_browser;
AvahiSDNSServerBrowserCallback callback;
AvahiLookupFlags flags,
AvahiSDNSServerBrowserCallback callback,
void* userdata) {
+
+ static const char * const type_table[AVAHI_DNS_SERVER_MAX] = {
+ "_domain._udp",
+ "_dns-update._udp"
+ };
AvahiSDNSServerBrowser *b;
- AvahiKey *k;
- char *n = NULL;
+ AvahiKey *k = NULL;
+ char n[AVAHI_DOMAIN_NAME_MAX];
+ int r;
assert(server);
assert(callback);
- assert(type == AVAHI_DNS_SERVER_RESOLVE || type == AVAHI_DNS_SERVER_UPDATE);
- if (domain && !avahi_is_valid_domain_name(domain)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
- return NULL;
- }
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(aprotocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, type < AVAHI_DNS_SERVER_MAX, AVAHI_ERR_INVALID_FLAGS);
if (!domain)
domain = server->domain_name;
- if (!AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
+ if ((r = avahi_service_name_join(n, sizeof(n), NULL, type_table[type], domain)) < 0) {
+ avahi_server_set_errno(server, r);
return NULL;
}
-
+
if (!(b = avahi_new(AvahiSDNSServerBrowser, 1))) {
avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
return NULL;
}
b->server = server;
- b->domain_name = avahi_normalize_name(domain);
b->callback = callback;
b->userdata = userdata;
b->aprotocol = aprotocol;
AVAHI_LLIST_HEAD_INIT(AvahiDNSServerInfo, b->info);
AVAHI_LLIST_PREPEND(AvahiSDNSServerBrowser, browser, server->dns_server_browsers, b);
- n = avahi_strdup_printf("%s.%s",type == AVAHI_DNS_SERVER_RESOLVE ? "_domain._udp" : "_dns-update._udp", b->domain_name);
- k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
- avahi_free(n);
+ if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
- b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b);
+ if (!(b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b)))
+ goto fail;
+
avahi_key_unref(k);
- if (!b->record_browser) {
- avahi_s_dns_server_browser_free(b);
- return NULL;
- }
-
return b;
+
+fail:
+
+ if (k)
+ avahi_key_unref(k);
+
+ avahi_s_dns_server_browser_free(b);
+ return NULL;
}
void avahi_s_dns_server_browser_free(AvahiSDNSServerBrowser *b) {
if (b->record_browser)
avahi_s_record_browser_free(b->record_browser);
- avahi_free(b->domain_name);
+
avahi_free(b);
}
struct AvahiSDomainBrowser {
AvahiServer *server;
- char *domain_name;
AvahiSRecordBrowser *record_browser;
- AvahiLookupResultFlags flags;
AvahiSDomainBrowserCallback callback;
void* userdata;
if (record) {
assert(record->key->type == AVAHI_DNS_TYPE_PTR);
- n = avahi_normalize_name(record->data.ptr.name);
+ n = record->data.ptr.name;
}
b->callback(b, interface, protocol, event, n, flags, b->userdata);
- avahi_free(n);
}
+
AvahiSDomainBrowser *avahi_s_domain_browser_new(
AvahiServer *server,
AvahiIfIndex interface,
AvahiLookupFlags flags,
AvahiSDomainBrowserCallback callback,
void* userdata) {
+
+ static const char * const type_table[AVAHI_DOMAIN_BROWSER_MAX] = {
+ "r",
+ "dr",
+ "b",
+ "db",
+ "lb"
+ };
AvahiSDomainBrowser *b;
- AvahiKey *k;
- char *n = NULL;
+ AvahiKey *k = NULL;
+ char n[AVAHI_DOMAIN_NAME_MAX];
+ int r;
assert(server);
assert(callback);
- if (type >= AVAHI_DOMAIN_BROWSER_MAX) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
- return NULL;
- }
-
- if (!AVAHI_IF_VALID(interface)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_INTERFACE);
- return NULL;
- }
-
- if (domain && !avahi_is_valid_domain_name(domain)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
- return NULL;
- }
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, type < AVAHI_DOMAIN_BROWSER_MAX, AVAHI_ERR_INVALID_FLAGS);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
if (!domain)
domain = server->domain_name;
-
- if (!AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
+
+ if ((r = avahi_service_name_join(n, sizeof(n), type_table[type], "_dns-sd._udp", domain)) < 0) {
+ avahi_server_set_errno(server, r);
return NULL;
}
}
b->server = server;
- b->domain_name = avahi_normalize_name(domain);
b->callback = callback;
b->userdata = userdata;
+ b->record_browser = NULL;
AVAHI_LLIST_PREPEND(AvahiSDomainBrowser, browser, server->domain_browsers, b);
- switch (type) {
- case AVAHI_DOMAIN_BROWSER_BROWSE:
- n = avahi_strdup_printf("b._dns-sd._udp.%s", b->domain_name);
- break;
- case AVAHI_DOMAIN_BROWSER_BROWSE_DEFAULT:
- n = avahi_strdup_printf("db._dns-sd._udp.%s", b->domain_name);
- break;
- case AVAHI_DOMAIN_BROWSER_REGISTER:
- n = avahi_strdup_printf("r._dns-sd._udp.%s", b->domain_name);
- break;
- case AVAHI_DOMAIN_BROWSER_REGISTER_DEFAULT:
- n = avahi_strdup_printf("dr._dns-sd._udp.%s", b->domain_name);
- break;
- case AVAHI_DOMAIN_BROWSER_BROWSE_LEGACY:
- n = avahi_strdup_printf("lb._dns-sd._udp.%s", b->domain_name);
- break;
-
- case AVAHI_DOMAIN_BROWSER_MAX:
- assert(0);
- break;
+ if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
}
-
- assert(n);
-
- k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
- avahi_free(n);
- b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b);
- avahi_key_unref(k);
-
- if (!b->record_browser) {
- avahi_s_domain_browser_free(b);
- return NULL;
- }
+ if (!(b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b)))
+ goto fail;
+ avahi_key_unref(k);
return b;
+
+fail:
+
+ if (k)
+ avahi_key_unref(k);
+
+ avahi_s_domain_browser_free(b);
+
+ return NULL;
}
void avahi_s_domain_browser_free(AvahiSDomainBrowser *b) {
if (b->record_browser)
avahi_s_record_browser_free(b->record_browser);
- avahi_free(b->domain_name);
avahi_free(b);
}
struct AvahiSServiceTypeBrowser {
AvahiServer *server;
char *domain_name;
-
+
AvahiSRecordBrowser *record_browser;
AvahiSServiceTypeBrowserCallback callback;
void* userdata) {
AvahiSServiceTypeBrowser *b = userdata;
- char *n = NULL, *c = NULL;
assert(rr);
assert(b);
if (record) {
- char *e;
+ char type[AVAHI_DOMAIN_NAME_MAX], domain[AVAHI_DOMAIN_NAME_MAX];
assert(record->key->type == AVAHI_DNS_TYPE_PTR);
-
- n = avahi_normalize_name(record->data.ptr.name);
-
- if (*n != '_')
- goto fail;
-
- for (c = e = n; *c == '_';) {
- c += strcspn(c, ".");
-
- if (*c == 0)
- goto fail;
-
- assert(*c == '.');
- e = c;
- c++;
+
+ if (avahi_service_name_split(record->data.ptr.name, NULL, 0, type, sizeof(type), domain, sizeof(domain)) < 0) {
+ avahi_log_warn("Invalid service type '%s'", record->key->name);
+ return;
}
-
- *e = 0;
-
- if (!avahi_domain_equal(c, b->domain_name))
- goto fail;
- }
-
- b->callback(b, interface, protocol, event, n, c, flags, b->userdata);
- avahi_free(n);
-
- return;
-fail:
- avahi_log_warn("Invalid service type '%s'", n);
- avahi_free(n);
+ b->callback(b, interface, protocol, event, type, domain, flags, b->userdata);
+ } else
+ b->callback(b, interface, protocol, event, NULL, b->domain_name, flags, b->userdata);
}
AvahiSServiceTypeBrowser *avahi_s_service_type_browser_new(
void* userdata) {
AvahiSServiceTypeBrowser *b;
- AvahiKey *k;
- char *n = NULL;
+ AvahiKey *k = NULL;
+ char n[AVAHI_DOMAIN_NAME_MAX];
+ int r;
assert(server);
assert(callback);
- if (domain && !avahi_is_valid_domain_name(domain)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
- return NULL;
- }
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
if (!domain)
domain = server->domain_name;
- if (!AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
+ if ((r = avahi_service_name_join(n, sizeof(n), NULL, "_services._dns-sd._udp", domain)) < 0) {
+ avahi_server_set_errno(server, r);
return NULL;
}
-
+
if (!(b = avahi_new(AvahiSServiceTypeBrowser, 1))) {
avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
return NULL;
}
b->server = server;
- b->domain_name = avahi_normalize_name(domain);
b->callback = callback;
b->userdata = userdata;
-
+ b->record_browser = NULL;
+
AVAHI_LLIST_PREPEND(AvahiSServiceTypeBrowser, browser, server->service_type_browsers, b);
- n = avahi_strdup_printf("_services._dns-sd._udp.%s", b->domain_name);
- k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
- avahi_free(n);
+ if (!(b->domain_name = avahi_normalize_name_strdup(domain))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
- b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b);
+ if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
+
+ if (!(b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b)))
+ goto fail;
+
avahi_key_unref(k);
- if (!b->record_browser)
- return NULL;
-
return b;
+
+fail:
+ if (k)
+ avahi_key_unref(k);
+
+ avahi_s_service_type_browser_free(b);
+
+ return NULL;
}
void avahi_s_service_type_browser_free(AvahiSServiceTypeBrowser *b) {
if (b->record_browser)
avahi_s_record_browser_free(b->record_browser);
-
+
avahi_free(b->domain_name);
avahi_free(b);
}
void* userdata) {
AvahiSServiceBrowser *b = userdata;
- char *n = NULL, *c = NULL, *s = NULL;
- char service[128];
assert(rr);
assert(b);
if (record) {
- char *e;
+ char service[AVAHI_LABEL_MAX], type[AVAHI_DOMAIN_NAME_MAX], domain[AVAHI_DOMAIN_NAME_MAX];
+
assert(record->key->type == AVAHI_DNS_TYPE_PTR);
-
- c = n = avahi_normalize_name(record->data.ptr.name);
-
- if (!(avahi_unescape_label((const char**) &c, service, sizeof(service))))
- goto fail;
-
- for (s = e = c; *c == '_';) {
- c += strcspn(c, ".");
-
- if (*c == 0)
- goto fail;
-
- assert(*c == '.');
- e = c;
- c++;
- }
-
- *e = 0;
- if (!avahi_domain_equal(c, b->domain_name))
- goto fail;
- }
-
- b->callback(b, interface, protocol, event, record ? service : NULL, s, c, flags, b->userdata);
- avahi_free(n);
+ if (avahi_service_name_split(record->data.ptr.name, service, sizeof(service), type, sizeof(type), domain, sizeof(domain)) < 0) {
+ avahi_log_warn("Failed to split '%s'", record->key->name);
+ return;
+ }
- return;
+ b->callback(b, interface, protocol, event, service, type, domain, flags, b->userdata);
+
+ } else
+ b->callback(b, interface, protocol, event, NULL, b->service_type, b->domain_name, flags, b->userdata);
-fail:
- avahi_log_warn("Invalid service '%s'", n);
- avahi_free(n);
}
AvahiSServiceBrowser *avahi_s_service_browser_new(
void* userdata) {
AvahiSServiceBrowser *b;
- AvahiKey *k;
- char *n = NULL;
+ AvahiKey *k = NULL;
+ char n[AVAHI_DOMAIN_NAME_MAX];
+ int r;
assert(server);
assert(callback);
assert(service_type);
- if (!avahi_is_valid_service_type(service_type)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_TYPE);
- return NULL;
- }
-
- if (domain && !avahi_is_valid_domain_name(domain)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
- return NULL;
- }
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_is_valid_service_type(service_type), AVAHI_ERR_INVALID_SERVICE_TYPE);
if (!domain)
domain = server->domain_name;
-
- if (!AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
+
+ if ((r = avahi_service_name_join(n, sizeof(n), NULL, service_type, domain)) < 0) {
+ avahi_server_set_errno(server, r);
return NULL;
}
}
b->server = server;
- b->domain_name = avahi_normalize_name(domain);
- b->service_type = avahi_normalize_name(service_type);
+ b->domain_name = b->service_type = NULL;
b->callback = callback;
b->userdata = userdata;
+ b->record_browser = NULL;
+
AVAHI_LLIST_PREPEND(AvahiSServiceBrowser, browser, server->service_browsers, b);
- n = avahi_strdup_printf("%s.%s", b->service_type, b->domain_name);
- k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
- avahi_free(n);
+ if (!(b->domain_name = avahi_normalize_name_strdup(domain)) ||
+ !(b->service_type = avahi_normalize_name_strdup(service_type))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
+
+ if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) {
+ avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
- b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b);
+ if (!(b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b)))
+ goto fail;
avahi_key_unref(k);
- if (!b->record_browser) {
- avahi_s_service_browser_free(b);
- return NULL;
- }
-
return b;
+
+fail:
+
+ if (k)
+ avahi_key_unref(k);
+
+ avahi_s_service_browser_free(b);
+ return NULL;
}
void avahi_s_service_browser_free(AvahiSServiceBrowser *b) {
}
}
-#define CHECK_VALIDITY_RETURN_NULL(server, expression, error) { \
- if (!(expression)) { \
- avahi_server_set_errno((server), (error)); \
- return NULL; \
- } \
-}
-
AvahiSRecordBrowser *avahi_s_record_browser_new(
AvahiServer *server,
AvahiIfIndex interface,
assert(key);
assert(callback);
- CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
- CHECK_VALIDITY_RETURN_NULL(server, !avahi_key_is_pattern(key), AVAHI_ERR_IS_PATTERN);
- CHECK_VALIDITY_RETURN_NULL(server, avahi_key_is_valid(key), AVAHI_ERR_INVALID_KEY);
- CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
- CHECK_VALIDITY_RETURN_NULL(server, !(flags & AVAHI_LOOKUP_USE_WIDE_AREA) || !(flags & AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !avahi_key_is_pattern(key), AVAHI_ERR_IS_PATTERN);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_key_is_valid(key), AVAHI_ERR_INVALID_KEY);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !(flags & AVAHI_LOOKUP_USE_WIDE_AREA) || !(flags & AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
if (!(b = avahi_new(AvahiSRecordBrowser, 1))) {
avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
b->flags = flags;
b->callback = callback;
b->userdata = userdata;
-
b->n_lookups = 0;
AVAHI_LLIST_HEAD_INIT(AvahiSRBLookup, b->lookups);
b->root_lookup = NULL;
const char *pname;
char label[64], *u;
-
/* Check whether we can compress this name. */
if (p->name_table && (prev = avahi_hashmap_lookup(p->name_table, name))) {
} else
first_label = 0;
- if (!(avahi_escape_label(AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
+ if (!(avahi_escape_label((char*) AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
return -1;
idx += n;
switch (type) {
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
/* avahi_log_debug("ptr"); */
switch (r->key->type) {
case AVAHI_DNS_TYPE_PTR:
- case AVAHI_DNS_TYPE_CNAME :
-
+ case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
+
if (!(avahi_dns_packet_append_name(p, r->data.ptr.name)))
goto fail;
/** The type of DNS server */
typedef enum {
AVAHI_DNS_SERVER_RESOLVE, /**< Unicast DNS servers for normal resolves (_domain._udp)*/
- AVAHI_DNS_SERVER_UPDATE /**< Unicast DNS servers for updates (_dns-update._udp)*/
+ AVAHI_DNS_SERVER_UPDATE, /**< Unicast DNS servers for updates (_dns-update._udp)*/
+ AVAHI_DNS_SERVER_MAX
} AvahiDNSServerType;
/** Publish the specified unicast DNS server address via mDNS. You may
}
r->server = server;
- r->host_name = avahi_normalize_name(host_name);
+ r->host_name = avahi_normalize_name_strdup(host_name);
r->callback = callback;
r->userdata = userdata;
r->address_record = NULL;
AvahiSServiceResolver *r;
AvahiKey *k;
- char t[256];
+ char n[AVAHI_DOMAIN_NAME_MAX];
int ret;
assert(server);
assert(type);
assert(callback);
- assert(aprotocol == AVAHI_PROTO_UNSPEC || aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_INET6);
-
- if (!AVAHI_IF_VALID(interface)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_INTERFACE);
- return NULL;
- }
-
- if (name && !avahi_is_valid_service_name(name)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_NAME);
- return NULL;
- }
-
- if (!avahi_is_valid_service_type(type)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_TYPE);
- return NULL;
- }
-
- if (domain && !avahi_is_valid_domain_name(domain)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
- return NULL;
- }
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(aprotocol), AVAHI_ERR_INVALID_PROTOCOL);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !name || avahi_is_valid_service_name(name), AVAHI_ERR_INVALID_SERVICE_NAME);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_is_valid_service_type(type), AVAHI_ERR_INVALID_SERVICE_TYPE);
+ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST|AVAHI_LOOKUP_NO_TXT|AVAHI_LOOKUP_NO_ADDRESS), AVAHI_ERR_INVALID_FLAGS);
if (!domain)
domain = server->domain_name;
-
- if (!AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST|AVAHI_LOOKUP_NO_TXT|AVAHI_LOOKUP_NO_ADDRESS)) {
- avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
+
+ if ((ret = avahi_service_name_join(n, sizeof(n), name, type, domain)) < 0) {
+ avahi_server_set_errno(server, ret);
return NULL;
}
r->server = server;
r->service_name = avahi_strdup(name);
- r->service_type = avahi_normalize_name(type);
- r->domain_name = avahi_normalize_name(domain);
+ r->service_type = avahi_normalize_name_strdup(type);
+ r->domain_name = avahi_normalize_name_strdup(domain);
r->callback = callback;
r->userdata = userdata;
r->address_protocol = aprotocol;
r->time_event = NULL;
AVAHI_LLIST_PREPEND(AvahiSServiceResolver, resolver, server->service_resolvers, r);
- if ((ret = avahi_service_name_snprint(t, sizeof(t), name, r->service_type, r->domain_name)) < 0) {
- avahi_server_set_errno(server, ret);
- avahi_s_service_resolver_free(r);
- return NULL;
- }
-
- k = avahi_key_new(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
+ k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
r->record_browser_srv = avahi_s_record_browser_new(server, interface, protocol, k, flags & ~(AVAHI_LOOKUP_NO_TXT|AVAHI_LOOKUP_NO_ADDRESS), record_browser_callback, r);
avahi_key_unref(k);
}
if (!(flags & AVAHI_LOOKUP_NO_TXT)) {
- k = avahi_key_new(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT);
+ k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT);
r->record_browser_txt = avahi_s_record_browser_new(server, interface, protocol, k, flags & ~(AVAHI_LOOKUP_NO_TXT|AVAHI_LOOKUP_NO_ADDRESS), record_browser_callback, r);
avahi_key_unref(k);
return NULL;
}
- if (!(k->name = avahi_normalize_name(name))) {
+ if (!(k->name = avahi_normalize_name_strdup(name))) {
avahi_log_error("avahi_normalize_name() failed.");
avahi_free(k);
return NULL;
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
avahi_free(r->data.ptr.name);
break;
return "SRV";
case AVAHI_DNS_TYPE_ANY:
return "ANY";
+ case AVAHI_DNS_TYPE_SOA:
+ return "SOA";
+ case AVAHI_DNS_TYPE_NS:
+ return "NS";
default:
return NULL;
}
break;
case AVAHI_DNS_TYPE_PTR:
- case AVAHI_DNS_TYPE_CNAME :
+ case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
t = r->data.ptr.name;
break;
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
return avahi_domain_equal(a->data.ptr.name, b->data.ptr.name);
case AVAHI_DNS_TYPE_HINFO:
switch (r->key->type) {
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
if (!(copy->data.ptr.name = avahi_strdup(r->data.ptr.name)))
goto fail;
break;
switch (r->key->type) {
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
n += strlen(r->data.ptr.name) + 1;
break;
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
return avahi_binary_domain_cmp(a->data.ptr.name, b->data.ptr.name);
case AVAHI_DNS_TYPE_SRV: {
case AVAHI_DNS_TYPE_PTR:
case AVAHI_DNS_TYPE_CNAME:
+ case AVAHI_DNS_TYPE_NS:
return avahi_is_valid_domain_name(r->data.ptr.name);
case AVAHI_DNS_TYPE_SRV:
withdraw_host_rrs(s);
avahi_free(s->host_name);
- s->host_name = host_name ? avahi_normalize_name(host_name) : avahi_get_host_name();
+ s->host_name = host_name ? avahi_normalize_name_strdup(host_name) : avahi_get_host_name_strdup();
s->host_name[strcspn(s->host_name, ".")] = 0;
update_fqdn(s);
withdraw_host_rrs(s);
avahi_free(s->domain_name);
- s->domain_name = domain_name ? avahi_normalize_name(domain_name) : avahi_strdup("local");
+ s->domain_name = domain_name ? avahi_normalize_name_strdup(domain_name) : avahi_strdup("local");
update_fqdn(s);
register_stuff(s);
} while (s->local_service_cookie == AVAHI_SERVICE_COOKIE_INVALID);
/* Get host name */
- s->host_name = s->config.host_name ? avahi_normalize_name(s->config.host_name) : avahi_get_host_name();
+ s->host_name = s->config.host_name ? avahi_normalize_name_strdup(s->config.host_name) : avahi_get_host_name_strdup();
s->host_name[strcspn(s->host_name, ".")] = 0;
- s->domain_name = s->config.domain_name ? avahi_normalize_name(s->config.domain_name) : avahi_strdup("local");
+ s->domain_name = s->config.domain_name ? avahi_normalize_name_strdup(s->config.domain_name) : avahi_strdup("local");
s->host_name_fqdn = NULL;
update_fqdn(s);
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);
- r->data.ptr.name = avahi_normalize_name(dest);
+ r->data.ptr.name = avahi_normalize_name_strdup(dest);
ret = avahi_server_add(s, g, interface, protocol, flags, r);
avahi_record_unref(r);
return ret;
if (!name)
name = s->host_name_fqdn;
else {
- if (!(n = avahi_normalize_name(name)))
+ if (!(n = avahi_normalize_name_strdup(name)))
return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);
name = n;
assert(s);
- if (!(r = avahi_record_new_full(name ? name : s->host_name_fqdn, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, ttl)))
+ 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);
+ }
r->data.txt.string_list = strlst;
ret = avahi_server_add(s, g, interface, protocol, flags, r);
uint16_t port,
AvahiStringList *strlst) {
- char ptr_name[256], svc_name[256], enum_ptr[256];
- char *t = NULL, *d = NULL, *h = NULL;
+ 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;
}
if (host && !avahi_is_valid_domain_name(host)) {
- return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
+ ret = avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
goto fail;
}
if (!host)
host = s->host_name_fqdn;
- if (!(d = avahi_normalize_name(domain)) ||
- !(t = avahi_normalize_name(type)) ||
- !(h = avahi_normalize_name(host))) {
+ if (!(h = avahi_normalize_name_strdup(host))) {
ret = avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);
goto fail;
}
- if ((ret = avahi_service_name_snprint(svc_name, sizeof(svc_name), name, t, d)) < 0 ||
- (ret = avahi_service_name_snprint(ptr_name, sizeof(ptr_name), NULL, t, d)) < 0) {
- avahi_server_set_errno(s, ret);
+ if ((ret = avahi_service_name_join(svc_name, sizeof(svc_name), name, type, domain)) < 0 ||
+ (ret = avahi_service_name_join(ptr_name, sizeof(ptr_name), NULL, type, domain)) < 0 ||
+ (ret = avahi_service_name_join(enum_ptr, sizeof(enum_ptr), NULL, "_services._dns-sd._udp", domain)) < 0)
goto fail;
- }
if ((ret = avahi_server_add_ptr(s, g, interface, protocol, flags & AVAHI_PUBLISH_IS_PROXY, AVAHI_DEFAULT_TTL, ptr_name, svc_name)) < 0)
goto fail;
if (ret < 0)
goto fail;
- snprintf(enum_ptr, sizeof(enum_ptr), "_services._dns-sd._udp.%s", d);
ret = avahi_server_add_ptr(s, g, interface, protocol, (flags & AVAHI_PUBLISH_IS_PROXY), AVAHI_DEFAULT_TTL, enum_ptr, ptr_name);
fail:
- avahi_free(d);
- avahi_free(t);
- avahi_free(h);
-
avahi_string_list_free(strlst);
+ avahi_free(h);
return ret;
}
const char *domain,
const char *host,
uint16_t port,
- va_list va){
+ va_list va) {
assert(s);
assert(type);
va_start(va, port);
ret = avahi_server_add_service_va(s, g, interface, protocol, flags, name, type, domain, host, port, va);
va_end(va);
+
return ret;
}
if (!domain)
domain = s->domain_name;
- if (!(n = avahi_normalize_name(name)) ||
- !(d = avahi_normalize_name(domain))) {
+ 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 (domain && !avahi_is_valid_domain_name(domain))
return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME);
- if ((ret = avahi_service_name_snprint(n, sizeof(n), name, type, domain) < 0))
+ if ((ret = avahi_service_name_join(n, sizeof(n), name, type, domain) < 0))
return avahi_server_set_errno(s, ret);
if (!(key = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV)))
int avahi_server_set_errno(AvahiServer *s, int error);
+#define AVAHI_CHECK_VALIDITY_RETURN_NULL(server, expression, error) { \
+ if (!(expression)) { \
+ avahi_server_set_errno((server), (error)); \
+ return NULL; \
+ } \
+}
+
#endif