Exemplo n.º 1
0
static void lookup_destroy(AvahiWideAreaLookup *l) {
    AvahiWideAreaLookup *t;
    assert(l);
    
    lookup_stop(l);

    t = avahi_hashmap_lookup(l->engine->lookups_by_key, l->key);
    AVAHI_LLIST_REMOVE(AvahiWideAreaLookup, by_key, t, l);
    if (t)
        avahi_hashmap_replace(l->engine->lookups_by_key, avahi_key_ref(l->key), t);
    else
        avahi_hashmap_remove(l->engine->lookups_by_key, l->key);

    AVAHI_LLIST_REMOVE(AvahiWideAreaLookup, lookups, l->engine->lookups, l);
    
    avahi_hashmap_remove(l->engine->lookups_by_id, &l->id);
    avahi_dns_packet_free(l->packet);

    if (l->key)
        avahi_key_unref(l->key);

    if (l->cname_key)
        avahi_key_unref(l->cname_key);
    
    avahi_free(l);
}
Exemplo n.º 2
0
AvahiLLMNRQuery* avahi_llmnr_query_add(AvahiInterface *i, AvahiKey *key, AvahiLLMNRQueryType type, AvahiLLMNRQueryCallback callback, void *userdata) {
	AvahiLLMNRQuery *lq;
	int c;

	/* Engine maintains a hashmap of 'AvahiLLMNRQuery' objects by id */
	AvahiLLMNRLookupEngine *e = i->monitor->server->llmnr.llmnr_lookup_engine;
	
	assert(i);	
	assert(key);
	assert(callback);

	if(!(lq = avahi_new(AvahiLLMNRQuery, 1)))
		return NULL;

	/* Initialize parameters */
	lq->dead = 0;
	lq->key = avahi_key_ref(key);
	lq->type = type;
	lq->interface = i;
	lq->callback = callback;
	lq->post_id_valid = 0;
	lq->post_id = 0;
	lq->userdata = userdata;

	/* Initialize record lists for this query object */
	lq->c_bit_set = avahi_record_list_new();
	lq->c_bit_clear = avahi_record_list_new();

	c = avahi_record_list_is_empty(lq->c_bit_set);
	assert(c);
	assert(lq->c_bit_clear);
	
	/* Set ID */
	/* KEEP IT 32 BIT for HASHMAP */
	for (;; e->next_id++)
		if(!(find_query(e, e->next_id)))
			break;

	lq->id = e->next_id++;
	
	/* AvahiLLMNRLookupEngine hashmap of queries by ID, 
	'engine-AvahiLLMNRQuery'. (lq->id and lq) */
	avahi_hashmap_insert(e->queries_by_id, &(lq->id), lq);

	/* Schedule this LLMNR query. This will create an 
	'AvahiLLMNRQueryJob' for this query and will issue
	further queries there only. im0 */
	if(!avahi_interface_post_llmnr_query(i, lq, 0)) 
		return NULL;

	return lq;
	
}
Exemplo n.º 3
0
static void add_to_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) {
    AvahiWideAreaCacheEntry *c;
    int is_new;
    
    assert(e);
    assert(r);

    if ((c = find_record_in_cache(e, r))) {
        is_new = 0;

        /* Update the existing entry */
        avahi_record_unref(c->record);
    } else {
        AvahiWideAreaCacheEntry *t;

        is_new = 1;

        /* Enforce cache size */
        if (e->cache_n_entries >= CACHE_ENTRIES_MAX)
            /* Eventually we should improve the caching algorithm here */
            goto finish;
        
        c = avahi_new(AvahiWideAreaCacheEntry, 1);
        c->engine = e;
        c->time_event = NULL;

        AVAHI_LLIST_PREPEND(AvahiWideAreaCacheEntry, cache, e->cache, c);

        /* Add the new entry to the cache entry hash table */
        t = avahi_hashmap_lookup(e->cache_by_key, r->key);
        AVAHI_LLIST_PREPEND(AvahiWideAreaCacheEntry, by_key, t, c);
        avahi_hashmap_replace(e->cache_by_key, avahi_key_ref(r->key), t);

        e->cache_n_entries ++;
    }

    c->record = avahi_record_ref(r);
    
    gettimeofday(&c->timestamp, NULL);
    c->expiry = c->timestamp;
    avahi_timeval_add(&c->expiry, r->ttl * 1000000);

    if (c->time_event)
        avahi_time_event_update(c->time_event, &c->expiry);
    else
        c->time_event = avahi_time_event_new(e->server->time_event_queue, &c->expiry, expiry_event, c);

finish:
    
    if (is_new)
        run_callbacks(e, r);
}
Exemplo n.º 4
0
AvahiSRecordBrowser *avahi_s_record_browser_new(
    AvahiServer *server,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiKey *key,
    AvahiLookupFlags flags,
    AvahiSRecordBrowserCallback callback,
    void* userdata) {

    AvahiSRecordBrowser *b;

    assert(server);
    assert(key);
    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, !avahi_key_is_pattern(key), AVAHI_ERR_IS_PATTERN);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_key_is_valid(key), AVAHI_ERR_INVALID_KEY);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !(flags & AVAHI_LOOKUP_USE_WIDE_AREA) || !(flags & AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);

    if (!(b = avahi_new(AvahiSRecordBrowser, 1))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        return NULL;
    }

    b->dead = 0;
    b->server = server;
    b->interface = interface;
    b->protocol = protocol;
    b->key = avahi_key_ref(key);
    b->flags = flags;
    b->callback = callback;
    b->userdata = userdata;
    b->n_lookups = 0;
    AVAHI_LLIST_HEAD_INIT(AvahiSRBLookup, b->lookups);
    b->root_lookup = NULL;

    AVAHI_LLIST_PREPEND(AvahiSRecordBrowser, browser, server->record_browsers, b);

    /* The currently cached entries are scanned a bit later, and than we will start querying, too */
    b->defer_time_event = avahi_time_event_new(server->time_event_queue, NULL, defer_callback, b);
    assert(b->defer_time_event);

    return b;
}
Exemplo n.º 5
0
static void cache_entry_free(AvahiWideAreaCacheEntry *c) {
    AvahiWideAreaCacheEntry *t;
    assert(c);

    if (c->time_event)
        avahi_time_event_free(c->time_event);

    AVAHI_LLIST_REMOVE(AvahiWideAreaCacheEntry, cache, c->engine->cache, c);

    t = avahi_hashmap_lookup(c->engine->cache_by_key, c->record->key);
    AVAHI_LLIST_REMOVE(AvahiWideAreaCacheEntry, by_key, t, c);
    if (t)
        avahi_hashmap_replace(c->engine->cache_by_key, avahi_key_ref(c->record->key), t);
    else
        avahi_hashmap_remove(c->engine->cache_by_key, c->record->key);

    c->engine->cache_n_entries --;

    avahi_record_unref(c->record);
    avahi_free(c);
}
Exemplo n.º 6
0
static AvahiSRBLookup* lookup_new(
    AvahiSRecordBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiLookupFlags flags,
    AvahiKey *key) {

    AvahiSRBLookup *l;

    assert(b);
    assert(AVAHI_IF_VALID(interface));
    assert(AVAHI_PROTO_VALID(protocol));

    if (b->n_lookups >= AVAHI_LOOKUPS_PER_BROWSER_MAX)
        /* We don't like cyclic CNAMEs */
        return NULL;

    if (!(l = avahi_new(AvahiSRBLookup, 1)))
        return NULL;

    l->ref = 1;
    l->record_browser = b;
    l->interface = interface;
    l->protocol = protocol;
    l->key = avahi_key_ref(key);
    l->wide_area = NULL;
    l->multicast = NULL;
    l->llmnr = NULL;
    l->cname_lookups = NULL;
    l->flags = flags;

    transport_flags_from_domain(b->server, &l->flags, key->name);

    AVAHI_LLIST_PREPEND(AvahiSRBLookup, lookups, b->lookups, l);

    b->n_lookups ++;

    return l;
}
Exemplo n.º 7
0
static AvahiQueryJob* job_new(AvahiQueryScheduler *s, AvahiKey *key, int done) {
    AvahiQueryJob *qj;

    assert(s);
    assert(key);

    if (!(qj = avahi_new(AvahiQueryJob, 1))) {
        avahi_log_error(__FILE__": Out of memory");
        return NULL;
    }

    qj->scheduler = s;
    qj->key = avahi_key_ref(key);
    qj->time_event = NULL;
    qj->n_posted = 1;
    qj->id = s->next_id++;

    if ((qj->done = done))
        AVAHI_LLIST_PREPEND(AvahiQueryJob, jobs, s->history, qj);
    else
        AVAHI_LLIST_PREPEND(AvahiQueryJob, jobs, s->jobs, qj);

    return qj;
}
Exemplo n.º 8
0
AvahiWideAreaLookup *avahi_wide_area_lookup_new(
    AvahiWideAreaLookupEngine *e,
    AvahiKey *key,
    AvahiWideAreaLookupCallback callback,
    void *userdata) {
    
    struct timeval tv;
    AvahiWideAreaLookup *l, *t;
    uint8_t *p;

    assert(e);
    assert(key);
    assert(callback);
    assert(userdata);

    l = avahi_new(AvahiWideAreaLookup, 1);
    l->engine = e;
    l->dead = 0;
    l->key = avahi_key_ref(key);
    l->cname_key = avahi_key_new_cname(l->key);
    l->callback = callback;
    l->userdata = userdata;

    /* If more than 65K wide area quries are issued simultaneously,
     * this will break. This should be limited by some higher level */

    for (;; e->next_id++)
        if (!find_lookup(e, e->next_id))
            break; /* This ID is not yet used. */

    l->id = e->next_id++;
    
    /* We keep the packet around in case we need to repeat our query */
    l->packet = avahi_dns_packet_new(0);

    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_ID, (uint16_t) l->id);
    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0, 0));

    p = avahi_dns_packet_append_key(l->packet, key, 0);
    assert(p);
    
    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1);

    if (send_to_dns_server(l, l->packet) < 0) {
        avahi_log_error(__FILE__": Failed to send packet.");
        avahi_dns_packet_free(l->packet);
        avahi_key_unref(l->key);
        if (l->cname_key)
            avahi_key_unref(l->cname_key);
        avahi_free(l);
        return NULL;
    }

    l->n_send = 1;
    
    l->time_event = avahi_time_event_new(e->server->time_event_queue, avahi_elapse_time(&tv, 500, 0), sender_timeout_callback, l);

    avahi_hashmap_insert(e->lookups_by_id, &l->id, l);

    t = avahi_hashmap_lookup(e->lookups_by_key, l->key);
    AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, by_key, t, l);
    avahi_hashmap_replace(e->lookups_by_key, avahi_key_ref(l->key), t);

    AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, lookups, e->lookups, l);
    
    return l;
}