X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-common%2Fdomain.c;fp=avahi-common%2Fdomain.c;h=0000000000000000000000000000000000000000;hb=f1de9dcaab953757252d51b4725cbfa36daa10a5;hp=3b1ab683494e9e5caf6094944bd4e2e41ae96bdd;hpb=7a5b2f69af7d36d6cd4153142f125fa011784e03;p=catta diff --git a/avahi-common/domain.c b/avahi-common/domain.c deleted file mode 100644 index 3b1ab68..0000000 --- a/avahi-common/domain.c +++ /dev/null @@ -1,609 +0,0 @@ -/*** - 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 -#include -#include - -#include "domain.h" -#include "malloc.h" -#include "error.h" -#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; - - if (**name == '.') { - (*name)++; - break; - } - - if (**name == 0) - break; - - if (**name == '\\') { - /* Escaped character */ - - (*name) ++; - - if (**name == 0) - /* 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++; - } - } - - assert(i < size); - - *d = 0; - - if (!avahi_utf8_valid(dest)) - return NULL; - - return dest; -} - -/* Escape "\" and ".", append \0 */ -char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, size_t *ret_size) { - char *r; - - assert(src); - assert(ret_name); - assert(*ret_name); - assert(ret_size); - assert(*ret_size > 0); - - r = *ret_name; - - 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 { - - /* 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++; - } - - **ret_name = 0; - - 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; - *ret_s = 0; - - while (*s) { - char label[AVAHI_LABEL_MAX]; - - if (!(avahi_unescape_label(&s, label, sizeof(label)))) - return NULL; - - if (label[0] == 0) { - - if (*s == 0 && empty) - return ret_s; - - return NULL; - } - - if (!empty) { - if (size < 1) - return NULL; - - *(r++) = '.'; - size--; - - } else - empty = 0; - - avahi_escape_label(label, strlen(label), &r, &size); - } - - 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); - - if (a == b) - return 1; - - for (;;) { - char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *r; - - r = avahi_unescape_label(&a, ca, sizeof(ca)); - assert(r); - r = avahi_unescape_label(&b, cb, sizeof(cb)); - assert(r); - - if (strcasecmp(ca, cb)) - return 0; - - if (!*a && !*b) - return 1; - } - - return 1; -} - -int avahi_is_valid_service_type_generic(const char *t) { - assert(t); - - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t) - return 0; - - do { - char label[AVAHI_LABEL_MAX]; - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return 0; - - if (strlen(label) <= 2 || label[0] != '_') - return 0; - - } while (*t); - - return 1; -} - -int avahi_is_valid_service_type_strict(const char *t) { - char label[AVAHI_LABEL_MAX]; - assert(t); - - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t) - return 0; - - /* Application name */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return 0; - - if (strlen(label) <= 2 || label[0] != '_') - return 0; - - if (!*t) - return 0; - - /* _tcp or _udp boilerplate */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return 0; - - if (strcasecmp(label, "_tcp") && strcasecmp(label, "_udp")) - return 0; - - if (*t) - return 0; - - return 1; -} - -const char *avahi_get_type_from_subtype(const char *t) { - char label[AVAHI_LABEL_MAX]; - const char *ret; - assert(t); - - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t) - return NULL; - - /* Subtype name */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return NULL; - - if (strlen(label) <= 2 || label[0] != '_') - return NULL; - - if (!*t) - return NULL; - - /* String "_sub" */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return NULL; - - if (strcasecmp(label, "_sub")) - return NULL; - - if (!*t) - return NULL; - - ret = t; - - /* Application name */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return NULL; - - if (strlen(label) <= 2 || label[0] != '_') - return NULL; - - if (!*t) - return NULL; - - /* _tcp or _udp boilerplate */ - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return NULL; - - if (strcasecmp(label, "_tcp") && strcasecmp(label, "_udp")) - return NULL; - - if (*t) - return NULL; - - return ret; -} - -int avahi_is_valid_service_subtype(const char *t) { - assert(t); - - return !!avahi_get_type_from_subtype(t); -} - -int avahi_is_valid_domain_name(const char *t) { - int is_first = 1; - assert(t); - - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX) - return 0; - - do { - char label[AVAHI_LABEL_MAX]; - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return 0; - - /* 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; -} - -int avahi_is_valid_service_name(const char *t) { - assert(t); - - if (strlen(t) >= AVAHI_LABEL_MAX || !*t) - return 0; - - return 1; -} - -int avahi_is_valid_host_name(const char *t) { - char label[AVAHI_LABEL_MAX]; - assert(t); - - if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t) - return 0; - - if (!(avahi_unescape_label(&t, label, sizeof(label)))) - return 0; - - if (strlen(label) < 1) - return 0; - - if (*t) - return 0; - - return 1; -} - -unsigned avahi_domain_hash(const char *s) { - unsigned hash = 0; - - while (*s) { - char c[AVAHI_LABEL_MAX], *p, *r; - - r = avahi_unescape_label(&s, c, sizeof(c)); - assert(r); - - for (p = c; *p; p++) - hash = 31 * hash + tolower(*p); - } - - return hash; -} - -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]; - 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; - r = avahi_escape_label(name, strlen(name), &e, &l); - assert(r); - } - - 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; - - /* Concatenation */ - - snprintf(p, size, "%s%s%s.%s", name ? escaped_name : "", name ? "." : "", normalized_type, normalized_domain); - - return AVAHI_OK; -} - -#ifndef HAVE_STRLCPY - -static size_t strlcpy(char *dest, const char *src, size_t n) { - assert(dest); - assert(src); - - 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, - TYPE, - DOMAIN - } state; - int type_empty = 1, domain_empty = 1; - - 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; - - switch (state) { - case NAME: - strlcpy(name, buf, name_size); - state = TYPE; - break; - - case TYPE: - - if (buf[0] == '_') { - - 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 */ - - 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; -} - -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; -}