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; }
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; }
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_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_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; } }
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_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_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_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; }
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; }
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; }
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; }
static void add_static_service_group_to_server(StaticServiceGroup *g) { StaticService *s; assert(g); if (g->entry_group && !avahi_s_entry_group_is_empty(g->entry_group)) /* This service group is already registered in the server */ return; if (!g->chosen_name || (g->replace_wildcards && strstr(g->name, "%h"))) { avahi_free(g->chosen_name); if (g->replace_wildcards) { char label[AVAHI_LABEL_MAX]; const char *p; p = avahi_server_get_host_name(avahi_server); avahi_unescape_label(&p, label, sizeof(label)); g->chosen_name = replacestr(g->name, "%h", label); } else g->chosen_name = avahi_strdup(g->name); } if (!g->entry_group) g->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, g); assert(avahi_s_entry_group_is_empty(g->entry_group)); for (s = g->services; s; s = s->services_next) { AvahiStringList *i; if (avahi_server_add_service_strlst( avahi_server, g->entry_group, s->interface, s->protocol, 0, g->chosen_name, s->type, s->domain_name, s->host_name, s->port, s->txt_records) < 0) { avahi_log_error("Failed to add service '%s' of type '%s', ignoring service group (%s): %s", g->chosen_name, s->type, g->filename, avahi_strerror(avahi_server_errno(avahi_server))); remove_static_service_group_from_server(g); return; } for (i = s->subtypes; i; i = i->next) { if (avahi_server_add_service_subtype( avahi_server, g->entry_group, AVAHI_IF_UNSPEC, s->protocol, 0, g->chosen_name, s->type, s->domain_name, (char*) i->text) < 0) { avahi_log_error("Failed to add subtype '%s' for service '%s' of type '%s', ignoring subtype (%s): %s", i->text, g->chosen_name, s->type, g->filename, avahi_strerror(avahi_server_errno(avahi_server))); } } } avahi_s_entry_group_commit(g->entry_group); }