static struct uloop_timeout cache_gc;
struct avl_tree services;
-static AVL_TREE(records, avl_strcmp, true, NULL);
+AVL_TREE(records, avl_strcmp, true, NULL);
static void
cache_record_free(struct cache_record *r)
struct cache_record *r, *p;
struct cache_service *s, *t;
- avl_for_each_element_safe(&records, r, avl, p)
- if (cache_is_expired(r->time, r->ttl, 100))
+ avl_for_each_element_safe(&records, r, avl, p) {
+ if (!cache_is_expired(r->time, r->ttl, r->refresh))
+ continue;
+ /* Records other than A(AAA) are handled as services */
+ if (r->type != TYPE_A && r->type != TYPE_AAAA) {
+ if (cache_is_expired(r->time, r->ttl, 100))
+ cache_record_free(r);
+ continue;
+ }
+ if (r->refresh >= 100) {
cache_record_free(r);
+ continue;
+ }
+ r->refresh += 50;
+ dns_send_question(r->iface, (struct sockaddr *)&r->from, r->record, r->type, 0);
+ }
avl_for_each_element_safe(&services, s, avl, t) {
if (!s->host)
continue;
}
s->refresh += 50;
- dns_send_question(s->iface, s->entry, TYPE_PTR, 1);
+ dns_send_question(s->iface, NULL, s->entry, TYPE_PTR, 0);
}
uloop_timeout_set(timeout, 10000);
}
void
-cache_scan(void)
+cache_update(void)
{
struct interface *iface;
struct cache_service *s;
vlist_for_each_element(&interfaces, iface, node)
avl_for_each_element(&services, s, avl)
- dns_send_question(iface, s->entry, TYPE_PTR, 1);
+ dns_send_question(iface, NULL, s->entry, TYPE_PTR, 0);
}
static struct cache_service*
if (!strcmp(s->entry, entry)) {
s->refresh = 50;
s->time = monotonic_time();
+ s->ttl = ttl;
return s;
}
avl_insert(&services, &s->avl);
if (!hlen)
- dns_send_question(iface, entry, TYPE_PTR, !iface->multicast);
+ dns_send_question(iface, NULL, entry, TYPE_PTR, iface->multicast);
return s;
}
return 0;
}
-void
-cache_answer(struct interface *iface, uint8_t *base, int blen, char *name, struct dns_answer *a, uint8_t *rdata, int flush)
+void cache_answer(struct interface *iface, struct sockaddr *from, uint8_t *base,
+ int blen, char *name, struct dns_answer *a, uint8_t *rdata,
+ int flush)
{
struct dns_srv_data *dsd = (struct dns_srv_data *) rdata;
struct cache_record *r;
void *rdata_ptr, *txt_ptr;
int host_len = 0;
static char *rdata_buffer = (char *) mdns_buf;
+ time_t now = monotonic_time();
nlen = strlen(name);
nlen + 1 < rdlength && !strcmp(rdata_buffer + rdlength - nlen, name))
host_len = rdlength - nlen - 1;
- cache_service(iface, rdata_buffer, host_len, a->ttl);
+ if (name[0] == '_')
+ cache_service(iface, rdata_buffer, host_len, a->ttl);
dlen = strlen(rdata_buffer) + 1;
rdata = (uint8_t*)rdata_buffer;
break;
case TYPE_A:
- cache_service(iface, name, strlen(name), a->ttl);
if (a->rdlength != 4)
return;
dlen = 4;
break;
case TYPE_AAAA:
- cache_service(iface, name, strlen(name), a->ttl);
if (a->rdlength != 16)
return;
dlen = 16;
if (r) {
if (!a->ttl) {
DBG(1, "D -> %s %s ttl:%d\n", dns_type_string(r->type), r->record, r->ttl);
- r->time = monotonic_time() + 1 - r->ttl;
+ r->time = now + 1 - r->ttl;
+ r->refresh = 100;
} else {
r->ttl = a->ttl;
+ r->time = now;
+ r->refresh = 50;
DBG(1, "A -> %s %s ttl:%d\n", dns_type_string(r->type), r->record, r->ttl);
}
return;
r->ttl = a->ttl;
r->port = port;
r->rdlength = dlen;
- r->time = monotonic_time();
+ r->time = now;
r->iface = iface;
+ if (iface->v6)
+ memcpy(&r->from, from, sizeof(struct sockaddr_in6));
+ else
+ memcpy(&r->from, from, sizeof(struct sockaddr_in));
+ r->refresh = 50;
if (tlen)
r->txt = memcpy(txt_ptr, rdata_buffer, tlen);