X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-common%2Fdomain.c;h=3b1ab683494e9e5caf6094944bd4e2e41ae96bdd;hb=9c0f9c65093cfa53d45f9b68782321eb8063a032;hp=f2e4395a7e3649813cd30840cb25394dc757069c;hpb=f56d3a4e5dec3aa75d25fae761a0642e6ebd7c3c;p=catta diff --git a/avahi-common/domain.c b/avahi-common/domain.c index f2e4395..3b1ab68 100644 --- a/avahi-common/domain.c +++ b/avahi-common/domain.c @@ -1,18 +1,16 @@ -/* $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 @@ -36,43 +34,20 @@ #include "domain.h" #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); -} +#include "address.h" +#include "utf8.h" /* 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; char *d; - + assert(dest); assert(size > 0); assert(name); d = dest; - + for (;;) { if (i >= size) return NULL; @@ -81,10 +56,10 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size) { (*name)++; break; } - + if (**name == 0) break; - + if (**name == '\\') { /* Escaped character */ @@ -93,7 +68,7 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size) { if (**name == 0) /* Ending NUL */ return NULL; - + else if (**name == '\\' || **name == '.') { /* Escaped backslash or dot */ *(d++) = *((*name) ++); @@ -102,7 +77,7 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size) { int n; /* Escaped literal ASCII character */ - + if (!isdigit(*(*name+1)) || !isdigit(*(*name+2))) return NULL; @@ -110,18 +85,18 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size) { if (n > 255 || n == 0) return NULL; - + *(d++) = (char) n; i++; (*name) += 3; } else return NULL; - + } else { /* Normal character */ - + *(d++) = *((*name) ++); i++; } @@ -131,6 +106,9 @@ char *avahi_unescape_label(const char **name, char *dest, size_t size) { *d = 0; + if (!avahi_utf8_valid(dest)) + return NULL; + return dest; } @@ -150,14 +128,14 @@ char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, si if (*src == '.' || *src == '\\') { /* Dot or backslash */ - + if (*ret_size < 3) return NULL; - + *((*ret_name) ++) = '\\'; *((*ret_name) ++) = *src; (*ret_size) -= 2; - + } else if ( *src == '_' || *src == '-' || @@ -166,13 +144,13 @@ char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, si (*src >= 'A' && *src <= 'Z')) { /* Proper character */ - + if (*ret_size < 2) return NULL; - + *((*ret_name)++) = *src; (*ret_size) --; - + } else { /* Everything else */ @@ -184,7 +162,7 @@ char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, si *((*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; } @@ -200,37 +178,41 @@ char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, si 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; + *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 (label[0] == 0) { - if (!empty) { - if (size < 1) - return NULL; - - *(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; } @@ -250,7 +232,7 @@ int avahi_domain_equal(const char *a, const char *b) { if (a == b) return 1; - + for (;;) { char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *r; @@ -261,7 +243,7 @@ int avahi_domain_equal(const char *a, const char *b) { if (strcasecmp(ca, cb)) return 0; - + if (!*a && !*b) return 1; } @@ -269,30 +251,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); @@ -307,7 +265,7 @@ int avahi_is_valid_service_type_generic(const char *t) { if (strlen(label) <= 2 || label[0] != '_') return 0; - + } while (*t); return 1; @@ -321,7 +279,7 @@ int avahi_is_valid_service_type_strict(const char *t) { return 0; /* Application name */ - + if (!(avahi_unescape_label(&t, label, sizeof(label)))) return 0; @@ -332,7 +290,7 @@ int avahi_is_valid_service_type_strict(const char *t) { return 0; /* _tcp or _udp boilerplate */ - + if (!(avahi_unescape_label(&t, label, sizeof(label)))) return 0; @@ -341,7 +299,7 @@ int avahi_is_valid_service_type_strict(const char *t) { if (*t) return 0; - + return 1; } @@ -354,7 +312,7 @@ const char *avahi_get_type_from_subtype(const char *t) { return NULL; /* Subtype name */ - + if (!(avahi_unescape_label(&t, label, sizeof(label)))) return NULL; @@ -365,7 +323,7 @@ const char *avahi_get_type_from_subtype(const char *t) { return NULL; /* String "_sub" */ - + if (!(avahi_unescape_label(&t, label, sizeof(label)))) return NULL; @@ -376,7 +334,7 @@ const char *avahi_get_type_from_subtype(const char *t) { return NULL; ret = t; - + /* Application name */ if (!(avahi_unescape_label(&t, label, sizeof(label)))) @@ -387,9 +345,9 @@ const char *avahi_get_type_from_subtype(const char *t) { if (!*t) return NULL; - + /* _tcp or _udp boilerplate */ - + if (!(avahi_unescape_label(&t, label, sizeof(label)))) return NULL; @@ -409,9 +367,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,9 +379,15 @@ 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); return 1; @@ -433,7 +398,7 @@ int avahi_is_valid_service_name(const char *t) { if (strlen(t) >= AVAHI_LABEL_MAX || !*t) return 0; - + return 1; } @@ -458,7 +423,7 @@ int avahi_is_valid_host_name(const char *t) { unsigned avahi_domain_hash(const char *s) { unsigned hash = 0; - + while (*s) { char c[AVAHI_LABEL_MAX], *p, *r; @@ -472,44 +437,26 @@ 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]; + char escaped_name[AVAHI_LABEL_MAX*4]; char normalized_type[AVAHI_DOMAIN_NAME_MAX]; char normalized_domain[AVAHI_DOMAIN_NAME_MAX]; - + assert(p); /* Validity checks */ - + if ((name && !avahi_is_valid_service_name(name))) return AVAHI_ERR_INVALID_SERVICE_NAME; if (!avahi_is_valid_service_type_generic(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; @@ -524,25 +471,28 @@ int avahi_service_name_join(char *p, size_t size, const char *name, const char * return AVAHI_ERR_INVALID_DOMAIN_NAME; /* Concatenation */ - + snprintf(p, size, "%s%s%s.%s", name ? escaped_name : "", name ? "." : "", normalized_type, normalized_domain); return AVAHI_OK; } +#ifndef HAVE_STRLCPY -char *avahi_strlcpy(char *dest, const char *src, size_t n) { +static size_t strlcpy(char *dest, const char *src, size_t n) { assert(dest); assert(src); - if (n == 0) - return dest; - - strncpy(dest, src, n-1); - dest[n-1] = 0; - return dest; + if (n > 0) { + strncpy(dest, src, n-1); + dest[n-1] = 0; + } + + return strlen(src); } +#endif + 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, @@ -550,7 +500,7 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char * DOMAIN } state; int type_empty = 1, domain_empty = 1; - + assert(p); assert(type); assert(type_size > 0); @@ -563,18 +513,18 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char * state = NAME; } else state = TYPE; - + *type = *domain = 0; - + while (*p) { char buf[64]; - + if (!(avahi_unescape_label(&p, buf, sizeof(buf)))) return -1; switch (state) { case NAME: - avahi_strlcpy(name, buf, name_size); + strlcpy(name, buf, name_size); state = TYPE; break; @@ -585,18 +535,18 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char * if (!type_empty) { if (!type_size) return AVAHI_ERR_NO_MEMORY; - + *(type++) = '.'; type_size --; } else type_empty = 0; - + if (!(avahi_escape_label(buf, strlen(buf), &type, &type_size))) return AVAHI_ERR_NO_MEMORY; break; - } + } state = DOMAIN; /* fall through */ @@ -606,7 +556,7 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char * if (!domain_empty) { if (!domain_size) return AVAHI_ERR_NO_MEMORY; - + *(domain++) = '.'; domain_size --; } else @@ -622,3 +572,38 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char * return 0; } +int avahi_is_valid_fqdn(const char *t) { + char label[AVAHI_LABEL_MAX]; + char normalized[AVAHI_DOMAIN_NAME_MAX]; + const char *k = t; + AvahiAddress a; + assert(t); + + if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX) + return 0; + + if (!avahi_is_valid_domain_name(t)) + return 0; + + /* Check if there are at least two labels*/ + if (!(avahi_unescape_label(&k, label, sizeof(label)))) + return 0; + + if (label[0] == 0 || !k) + return 0; + + if (!(avahi_unescape_label(&k, label, sizeof(label)))) + return 0; + + if (label[0] == 0 || !k) + return 0; + + /* Make sure that the name is not an IP address */ + if (!(avahi_normalize_name(t, normalized, sizeof(normalized)))) + return 0; + + if (avahi_address_parse(normalized, AVAHI_PROTO_UNSPEC, &a)) + return 0; + + return 1; +}