g_assert(e);
g_assert(a);
- flx_interface_post_response(a->interface, a->entry->record, FALSE);
+ flx_interface_post_response(a->interface, NULL, a->entry->record, FALSE);
if (a->n_announced++ <= 8)
a->sec_delay *= 2;
g_message("New announcement on interface %s.%i for entry [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record));
g_free(t);
- flx_interface_post_response(i, e->record, FALSE);
+ flx_interface_post_response(i, NULL, e->record, FALSE);
a = g_new(flxAnnouncement, 1);
a->server = s;
for (e = s->entries; e; e = e->entry_next)
if (flx_interface_match(i, e->interface, e->protocol)) {
flxRecord *g = make_goodbye_record(e->record);
- flx_interface_post_response(i, g, TRUE);
+ flx_interface_post_response(i, NULL, g, TRUE);
flx_record_unref(g);
}
}
}
-void flx_interface_post_response(flxInterface *i, flxRecord *record, gboolean immediately) {
+void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *record, gboolean immediately) {
g_assert(i);
g_assert(record);
if (flx_interface_relevant(i))
- flx_packet_scheduler_post_response(i->scheduler, record, immediately);
+ flx_packet_scheduler_post_response(i->scheduler, a, record, immediately);
}
void flx_dump_caches(flxInterfaceMonitor *m, FILE *f) {
void flx_interface_send_packet(flxInterface *i, flxDnsPacket *p);
void flx_interface_post_query(flxInterface *i, flxKey *k, gboolean immediately);
-void flx_interface_post_response(flxInterface *i, flxRecord *rr, gboolean immediately);
+void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *rr, gboolean immediately);
void flx_dump_caches(flxInterfaceMonitor *m, FILE *f);
return rj;
}
-void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record, gboolean immediately) {
+void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress *a, flxRecord *record, gboolean immediately) {
flxResponseJob *rj;
GTimeVal tv;
gchar *t;
if (!!record->ttl == !!rj->record->ttl &&
d >= 0 && d <= FLX_RESPONSE_HISTORY_MSEC*1000) {
g_message("WARNING! DUPLICATE RESPONSE SUPPRESSION ACTIVE!");
+
+ /* This job is no longer specific to a single querier, so
+ * make sure it isn't suppressed by known answer
+ * suppresion */
+ rj->address_valid = FALSE;
+
return;
}
rj = response_job_new(s, record);
rj->delivery = tv;
rj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &rj->delivery, response_elapse, rj);
+
+ /* Store the address of the host this messages is intended to, so
+ that we can drop this job in case a truncated message with
+ known answer suppresion entries is recieved */
+
+ if ((rj->address_valid = !!a))
+ rj->address = *a;
}
void flx_packet_scheduler_incoming_query(flxPacketScheduler *s, flxKey *key) {
g_get_current_time(&rj->delivery);
}
+void flx_packet_scheduler_incoming_known_answer(flxPacketScheduler *s, flxRecord *record, const flxAddress *a) {
+ flxResponseJob *rj;
+
+ g_assert(s);
+ g_assert(record);
+ g_assert(a);
+
+ for (rj = s->response_jobs; rj; rj = rj->jobs_next)
+ if (flx_record_equal_no_ttl(rj->record, record) &&
+ rj->address_valid &&
+ flx_address_cmp(&rj->address, a) &&
+ record->ttl >= rj->record->ttl/2) {
+
+ /* Let's suppress it */
+
+ response_job_free(s, rj);
+ break;
+ }
+
+}
+
void flx_packet_scheduler_flush_responses(flxPacketScheduler *s) {
flxResponseJob *rj;
flxPacketScheduler *scheduler;
flxTimeEvent *time_event;
flxRecord *record;
+ flxAddress address;
+ gboolean address_valid;
gboolean done;
GTimeVal delivery;
FLX_LLIST_FIELDS(flxResponseJob, jobs);
void flx_packet_scheduler_free(flxPacketScheduler *s);
void flx_packet_scheduler_post_query(flxPacketScheduler *s, flxKey *key, gboolean immediately);
-void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record, gboolean immediately);
+void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress *a, flxRecord *record, gboolean immediately);
void flx_packet_scheduler_incoming_query(flxPacketScheduler *s, flxKey *key);
void flx_packet_scheduler_incoming_response(flxPacketScheduler *s, flxRecord *record);
+void flx_packet_scheduler_incoming_known_answer(flxPacketScheduler *s, flxRecord *record, const flxAddress *a);
void flx_packet_scheduler_flush_responses(flxPacketScheduler *s);
for (e = s->entries; e; e = e->entry_next)
if (flx_key_pattern_match(k, e->record->key))
if (flx_interface_match(i, e->interface, e->protocol))
- flx_interface_post_response(i, e->record, FALSE);
+ flx_interface_post_response(i, a, e->record, FALSE);
} else {
/* Handle all other queries */
for (e = g_hash_table_lookup(s->rrset_by_key, k); e; e = e->by_key_next)
if (flx_interface_match(i, e->interface, e->protocol))
- flx_interface_post_response(i, e->record, FALSE);
+ flx_interface_post_response(i, a, e->record, FALSE);
}
}
handle_query_key(s, key, i, a);
flx_key_unref(key);
}
+
+ /* Known Answer Suppresion */
+ for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT); n > 0; n --) {
+ flxRecord *record;
+ gboolean unique = FALSE;
+
+ if (!(record = flx_dns_packet_consume_record(p, &unique))) {
+ g_warning("Packet too short (2)");
+ return;
+ }
+
+ flx_packet_scheduler_incoming_known_answer(i->scheduler, record, a);
+ flx_record_unref(record);
+ }
}
static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a) {
g_assert(i);
g_assert(r);
- flx_interface_post_response(i, r, FALSE);
+ flx_interface_post_response(i, NULL, r, FALSE);
}
void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record) {
todo:
* Probing/Conflict resolution
* uniqueness
+
* defend our entries on incoming goodbye
* Unicast responses/queries
* Legacy unicast
-* Known-Answer suppression server part
-* Truncation
-
done:
* really send goodbye packets
* refresh subscribed records only
* FLX_DNS_TYPE_ANY support
* Known-Answer suppression client part
-
+* Known-Answer suppression server part
return tv;
}
+
+gint flx_age(const GTimeVal *a) {
+ GTimeVal now;
+
+ g_assert(a);
+
+ g_get_current_time(&now);
+
+ return flx_timeval_diff(&now, a);
+}
GTimeVal *flx_elapse_time(GTimeVal *tv, guint msec, guint jitter);
+gint flx_age(const GTimeVal *a);
+
#endif