AvahiSAddressResolver *avahi_s_address_resolver_prepare(
    AvahiServer *server,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    const AvahiAddress *address,
    AvahiLookupFlags flags,
    AvahiSAddressResolverCallback callback,
    void* userdata) {

    AvahiSAddressResolver *r;
    AvahiKey *k;
    char n[AVAHI_DOMAIN_NAME_MAX];

    assert(server);
    assert(address);
    assert(callback);

    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, address->proto == AVAHI_PROTO_INET || address->proto == AVAHI_PROTO_INET6, AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);

    avahi_reverse_lookup_name(address, n, sizeof(n));

    if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        return NULL;
    }

    if (!(r = avahi_new(AvahiSAddressResolver, 1))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        avahi_key_unref(k);
        return NULL;
    }

    r->server = server;
    r->address = *address;
    r->callback = callback;
    r->userdata = userdata;
    r->ptr_record = NULL;
    r->interface = interface;
    r->protocol = protocol;
    r->flags = 0;
    r->retry_with_multicast = 0;
    r->key = k;

    r->record_browser = NULL;
    AVAHI_LLIST_PREPEND(AvahiSAddressResolver, resolver, server->address_resolvers, r);

    r->time_event = NULL;

    if (!(flags & (AVAHI_LOOKUP_USE_MULTICAST|AVAHI_LOOKUP_USE_WIDE_AREA))) {

        if (!server->wide_area_lookup_engine || !avahi_wide_area_has_servers(server->wide_area_lookup_engine))
            flags |= AVAHI_LOOKUP_USE_MULTICAST;
        else {
            flags |= AVAHI_LOOKUP_USE_WIDE_AREA;
            r->retry_with_multicast = 1;
        }
    }

    r->record_browser = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);

    if (!r->record_browser) {
        avahi_s_address_resolver_free(r);
        return NULL;
    }

    start_timeout(r);

    return r;
}
AvahiSAddressResolver *avahi_s_address_resolver_prepare(
    AvahiServer *server,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    const AvahiAddress *address,
    AvahiLookupFlags flags,
    AvahiSAddressResolverCallback callback,
    void* userdata) {

    AvahiSAddressResolver *r;
    AvahiKey *k;
    char n[AVAHI_DOMAIN_NAME_MAX];

    assert(server);
    assert(address);
    assert(callback);

    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, address->proto == AVAHI_PROTO_INET || address->proto == AVAHI_PROTO_INET6, AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);

    avahi_reverse_lookup_name(address, n, sizeof(n));

    if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        return NULL;
    }

    if (!(r = avahi_new(AvahiSAddressResolver, 1))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        avahi_key_unref(k);
        return NULL;
    }

    r->server = server;
    r->address = *address;
    r->callback = callback;
    r->userdata = userdata;
    r->ptr_record = NULL;
    r->interface = interface;
    r->protocol = protocol;
    r->flags = 0;
    r->retry_with_multicast = 0;
    r->key = k;

    r->record_browser = NULL;
    AVAHI_LLIST_PREPEND(AvahiSAddressResolver, resolver, server->address_resolvers, r);

    r->time_event = NULL;

    if (!(flags & (AVAHI_LOOKUP_USE_MULTICAST|AVAHI_LOOKUP_USE_WIDE_AREA))) {

        if (!server->wide_area_lookup_engine || !avahi_wide_area_has_servers(server->wide_area_lookup_engine))
            flags |= AVAHI_LOOKUP_USE_MULTICAST;
        else {
            flags |= AVAHI_LOOKUP_USE_WIDE_AREA;
            r->retry_with_multicast = 1;
        }
    }

    r->record_browser = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);

    if (!r->record_browser) {
        avahi_s_address_resolver_free(r);
        return NULL;
    }

    start_timeout(r);

    return r;
}