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; }
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); }
static AvahiEntry *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 */) { AvahiEntry *e; char t[AVAHI_DOMAIN_NAME_MAX], normalized_d[AVAHI_DOMAIN_NAME_MAX], *n; AvahiRecord *r; assert(s); assert(name); AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_USE_WIDE_AREA|AVAHI_PUBLISH_USE_MULTICAST), 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_fqdn(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 (!domain) domain = s->domain_name; transport_flags_from_domain(s, &flags, domain); AVAHI_CHECK_VALIDITY_RETURN_NULL(s, flags & AVAHI_PUBLISH_USE_MULTICAST, AVAHI_ERR_NOT_SUPPORTED); 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))); 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; } 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); return e; }
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; }
static void parse_environment(AvahiDomainBrowser *b) { char buf[AVAHI_DOMAIN_NAME_MAX*3], *e, *t, *p; assert(b); if (!(e = getenv("AVAHI_BROWSE_DOMAINS"))) return; snprintf(buf, sizeof(buf), "%s", e); for (t = strtok_r(buf, ":", &p); t; t = strtok_r(NULL, ":", &p)) { char domain[AVAHI_DOMAIN_NAME_MAX]; if (avahi_normalize_name(t, domain, sizeof(domain))) b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain); } }
static void parse_domain_file(AvahiDomainBrowser *b) { FILE *f; char buf[AVAHI_DOMAIN_NAME_MAX]; assert(b); if (!(f = avahi_xdg_config_open("avahi/browse-domains"))) return; while (fgets(buf, sizeof(buf)-1, f)) { char domain[AVAHI_DOMAIN_NAME_MAX]; buf[strcspn(buf, "\n\r")] = 0; if (avahi_normalize_name(buf, domain, sizeof(domain))) b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain); } }
static int load_config_file(DaemonConfig *c) { int r = -1; AvahiIniFile *f; AvahiIniFileGroup *g; assert(c); if (!(f = avahi_ini_file_load(c->config_file ? c->config_file : AVAHI_CONFIG_FILE))) goto finish; for (g = f->groups; g; g = g->groups_next) { if (strcasecmp(g->name, "server") == 0) { AvahiIniFilePair *p; for (p = g->pairs; p; p = p->pairs_next) { if (strcasecmp(p->key, "host-name") == 0) { avahi_free(c->server_config.host_name); c->server_config.host_name = avahi_strdup(p->value); } else if (strcasecmp(p->key, "domain-name") == 0) { avahi_free(c->server_config.domain_name); c->server_config.domain_name = avahi_strdup(p->value); } else if (strcasecmp(p->key, "browse-domains") == 0) { char **e, **t; e = avahi_split_csv(p->value); for (t = e; *t; t++) { char cleaned[AVAHI_DOMAIN_NAME_MAX]; if (!avahi_normalize_name(*t, cleaned, sizeof(cleaned))) { avahi_log_error("Invalid domain name \"%s\" for key \"%s\" in group \"%s\"\n", *t, p->key, g->name); avahi_strfreev(e); goto finish; } c->server_config.browse_domains = avahi_string_list_add(c->server_config.browse_domains, cleaned); } avahi_strfreev(e); c->server_config.browse_domains = filter_duplicate_domains(c->server_config.browse_domains); } else if (strcasecmp(p->key, "use-ipv4") == 0) c->server_config.use_ipv4 = is_yes(p->value); else if (strcasecmp(p->key, "use-ipv6") == 0) c->server_config.use_ipv6 = is_yes(p->value); else if (strcasecmp(p->key, "check-response-ttl") == 0) c->server_config.check_response_ttl = is_yes(p->value); else if (strcasecmp(p->key, "allow-point-to-point") == 0) c->server_config.allow_point_to_point = is_yes(p->value); else if (strcasecmp(p->key, "use-iff-running") == 0) c->server_config.use_iff_running = is_yes(p->value); else if (strcasecmp(p->key, "disallow-other-stacks") == 0) c->server_config.disallow_other_stacks = is_yes(p->value); else if (strcasecmp(p->key, "host-name-from-machine-id") == 0) { if (*(p->value) == 'y' || *(p->value) == 'Y') { char *machine_id = get_machine_id(); if (machine_id != NULL) { avahi_free(c->server_config.host_name); c->server_config.host_name = machine_id; } } } #ifdef HAVE_DBUS else if (strcasecmp(p->key, "enable-dbus") == 0) { if (*(p->value) == 'w' || *(p->value) == 'W') { c->fail_on_missing_dbus = 0; c->enable_dbus = 1; } else if (*(p->value) == 'y' || *(p->value) == 'Y') { c->fail_on_missing_dbus = 1; c->enable_dbus = 1; } else { c->enable_dbus = 0; } } #endif else if (strcasecmp(p->key, "allow-interfaces") == 0) { char **e, **t; avahi_string_list_free(c->server_config.allow_interfaces); c->server_config.allow_interfaces = NULL; e = avahi_split_csv(p->value); for (t = e; *t; t++) c->server_config.allow_interfaces = avahi_string_list_add(c->server_config.allow_interfaces, *t); avahi_strfreev(e); } else if (strcasecmp(p->key, "deny-interfaces") == 0) { char **e, **t; avahi_string_list_free(c->server_config.deny_interfaces); c->server_config.deny_interfaces = NULL; e = avahi_split_csv(p->value); for (t = e; *t; t++) c->server_config.deny_interfaces = avahi_string_list_add(c->server_config.deny_interfaces, *t); avahi_strfreev(e); } else if (strcasecmp(p->key, "ratelimit-interval-usec") == 0) { AvahiUsec k; if (parse_usec(p->value, &k) < 0) { avahi_log_error("Invalid ratelimit-interval-usec setting %s", p->value); goto finish; } c->server_config.ratelimit_interval = k; } else if (strcasecmp(p->key, "ratelimit-burst") == 0) { unsigned k; if (parse_unsigned(p->value, &k) < 0) { avahi_log_error("Invalid ratelimit-burst setting %s", p->value); goto finish; } c->server_config.ratelimit_burst = k; } else if (strcasecmp(p->key, "cache-entries-max") == 0) { unsigned k; if (parse_unsigned(p->value, &k) < 0) { avahi_log_error("Invalid cache-entries-max setting %s", p->value); goto finish; } c->server_config.n_cache_entries_max = k; #ifdef HAVE_DBUS } else if (strcasecmp(p->key, "clients-max") == 0) { unsigned k; if (parse_unsigned(p->value, &k) < 0) { avahi_log_error("Invalid clients-max setting %s", p->value); goto finish; } c->n_clients_max = k; } else if (strcasecmp(p->key, "objects-per-client-max") == 0) { unsigned k; if (parse_unsigned(p->value, &k) < 0) { avahi_log_error("Invalid objects-per-client-max setting %s", p->value); goto finish; } c->n_objects_per_client_max = k; } else if (strcasecmp(p->key, "entries-per-entry-group-max") == 0) { unsigned k; if (parse_unsigned(p->value, &k) < 0) { avahi_log_error("Invalid entries-per-entry-group-max setting %s", p->value); goto finish; } c->n_entries_per_entry_group_max = k; #endif } else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } } } else if (strcasecmp(g->name, "publish") == 0) { AvahiIniFilePair *p; for (p = g->pairs; p; p = p->pairs_next) { if (strcasecmp(p->key, "publish-addresses") == 0) c->server_config.publish_addresses = is_yes(p->value); else if (strcasecmp(p->key, "publish-hinfo") == 0) c->server_config.publish_hinfo = is_yes(p->value); else if (strcasecmp(p->key, "publish-workstation") == 0) c->server_config.publish_workstation = is_yes(p->value); else if (strcasecmp(p->key, "publish-domain") == 0) c->server_config.publish_domain = is_yes(p->value); else if (strcasecmp(p->key, "publish-resolv-conf-dns-servers") == 0) c->publish_resolv_conf = is_yes(p->value); else if (strcasecmp(p->key, "disable-publishing") == 0) c->server_config.disable_publishing = is_yes(p->value); else if (strcasecmp(p->key, "disable-user-service-publishing") == 0) c->disable_user_service_publishing = is_yes(p->value); else if (strcasecmp(p->key, "add-service-cookie") == 0) c->server_config.add_service_cookie = is_yes(p->value); else if (strcasecmp(p->key, "publish-dns-servers") == 0) { avahi_strfreev(c->publish_dns_servers); c->publish_dns_servers = avahi_split_csv(p->value); } else if (strcasecmp(p->key, "publish-a-on-ipv6") == 0) c->server_config.publish_a_on_ipv6 = is_yes(p->value); else if (strcasecmp(p->key, "publish-aaaa-on-ipv4") == 0) c->server_config.publish_aaaa_on_ipv4 = is_yes(p->value); else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } } } else if (strcasecmp(g->name, "wide-area") == 0) { AvahiIniFilePair *p; for (p = g->pairs; p; p = p->pairs_next) { if (strcasecmp(p->key, "enable-wide-area") == 0) c->server_config.enable_wide_area = is_yes(p->value); else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } } } else if (strcasecmp(g->name, "reflector") == 0) { AvahiIniFilePair *p; for (p = g->pairs; p; p = p->pairs_next) { if (strcasecmp(p->key, "enable-reflector") == 0) c->server_config.enable_reflector = is_yes(p->value); else if (strcasecmp(p->key, "reflect-ipv") == 0) c->server_config.reflect_ipv = is_yes(p->value); else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } } } else if (strcasecmp(g->name, "rlimits") == 0) { AvahiIniFilePair *p; for (p = g->pairs; p; p = p->pairs_next) { if (strcasecmp(p->key, "rlimit-as") == 0) { c->rlimit_as_set = 1; c->rlimit_as = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-core") == 0) { c->rlimit_core_set = 1; c->rlimit_core = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-data") == 0) { c->rlimit_data_set = 1; c->rlimit_data = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-fsize") == 0) { c->rlimit_fsize_set = 1; c->rlimit_fsize = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-nofile") == 0) { c->rlimit_nofile_set = 1; c->rlimit_nofile = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-stack") == 0) { c->rlimit_stack_set = 1; c->rlimit_stack = atoi(p->value); } else if (strcasecmp(p->key, "rlimit-nproc") == 0) { #ifdef RLIMIT_NPROC c->rlimit_nproc_set = 1; c->rlimit_nproc = atoi(p->value); #else avahi_log_error("Ignoring configuration key \"%s\" in group \"%s\"\n", p->key, g->name); #endif } else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } } } else { avahi_log_error("Invalid configuration file group \"%s\".\n", g->name); goto finish; } } r = 0; finish: if (f) avahi_ini_file_free(f); return r; }
int avahi_server_add_address( AvahiServer *s, AvahiSEntryGroup *g, AvahiIfIndex interface, AvahiProtocol protocol, AvahiPublishFlags flags, const char *name, AvahiAddress *a) { char n[AVAHI_DOMAIN_NAME_MAX]; int ret = AVAHI_OK; AvahiEntry *entry = NULL, *reverse = NULL; AvahiRecord *r; assert(s); assert(a); 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_PUBLISH_USE_WIDE_AREA| AVAHI_PUBLISH_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS); AVAHI_CHECK_VALIDITY(s, !name || avahi_is_valid_fqdn(name), AVAHI_ERR_INVALID_HOST_NAME); /* Prepare the host naem */ if (!name) name = s->host_name_fqdn; else { AVAHI_ASSERT_TRUE(avahi_normalize_name(name, n, sizeof(n))); name = n; } transport_flags_from_domain(s, &flags, name); AVAHI_CHECK_VALIDITY(s, flags & AVAHI_PUBLISH_USE_MULTICAST, AVAHI_ERR_NOT_SUPPORTED); /* Create the A/AAAA record */ if (a->proto == AVAHI_PROTO_INET) { 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 finish; } r->data.a.address = a->data.ipv4; } else { 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 finish; } r->data.aaaa.address = a->data.ipv6; } 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 (!entry) { ret = avahi_server_errno(s); goto finish; } /* Create the reverse lookup entry */ if (!(flags & AVAHI_PUBLISH_NO_REVERSE)) { char reverse_n[AVAHI_DOMAIN_NAME_MAX]; avahi_reverse_lookup_name(a, reverse_n, sizeof(reverse_n)); 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; } } 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; }