From cfc653d0fd2f58ef3f4b5ecb285d5beb5bfaacfb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Apr 2005 22:30:47 +0000 Subject: [PATCH] add known answer suppresion server part git-svn-id: file:///home/lennart/svn/public/avahi/trunk@21 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- announce.c | 6 +++--- iface.c | 4 ++-- iface.h | 2 +- psched.c | 36 +++++++++++++++++++++++++++++++++++- psched.h | 5 ++++- server.c | 20 +++++++++++++++++--- todo | 6 ++---- util.c | 10 ++++++++++ util.h | 2 ++ 9 files changed, 76 insertions(+), 15 deletions(-) diff --git a/announce.c b/announce.c index 5b1e4e7..9229753 100644 --- a/announce.c +++ b/announce.c @@ -23,7 +23,7 @@ static void elapse_announce(flxTimeEvent *e, void *userdata) { 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; @@ -64,7 +64,7 @@ static void new_announcement(flxServer *s, flxInterface *i, flxServerEntry *e) { 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; @@ -138,7 +138,7 @@ void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) { 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); } } diff --git a/iface.c b/iface.c index 24d5a37..d2daf40 100644 --- a/iface.c +++ b/iface.c @@ -447,12 +447,12 @@ void flx_interface_post_query(flxInterface *i, flxKey *key, gboolean immediately } -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) { diff --git a/iface.h b/iface.h index 16e9650..4b0aef8 100644 --- a/iface.h +++ b/iface.h @@ -83,7 +83,7 @@ flxHwInterface* flx_interface_monitor_get_hw_interface(flxInterfaceMonitor *m, g 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); diff --git a/psched.c b/psched.c index 138dd50..1b6d26c 100644 --- a/psched.c +++ b/psched.c @@ -337,7 +337,7 @@ static flxResponseJob* response_job_new(flxPacketScheduler *s, flxRecord *record 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; @@ -361,6 +361,12 @@ void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record 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; } @@ -376,6 +382,13 @@ void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record 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) { @@ -488,6 +501,27 @@ mark_done: 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; diff --git a/psched.h b/psched.h index 3a99ed1..7290265 100644 --- a/psched.h +++ b/psched.h @@ -24,6 +24,8 @@ struct _flxResponseJob { flxPacketScheduler *scheduler; flxTimeEvent *time_event; flxRecord *record; + flxAddress address; + gboolean address_valid; gboolean done; GTimeVal delivery; FLX_LLIST_FIELDS(flxResponseJob, jobs); @@ -50,10 +52,11 @@ flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i) 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); diff --git a/server.c b/server.c index ecf4457..04c7d10 100644 --- a/server.c +++ b/server.c @@ -31,14 +31,14 @@ static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flx 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); } } @@ -61,6 +61,20 @@ static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const f 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) { @@ -583,7 +597,7 @@ static void post_response_callback(flxInterfaceMonitor *m, flxInterface *i, gpoi 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) { diff --git a/todo b/todo index ab2519b..623c0b6 100644 --- a/todo +++ b/todo @@ -1,17 +1,15 @@ 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 diff --git a/util.c b/util.c index b8128c4..47642e8 100644 --- a/util.c +++ b/util.c @@ -113,3 +113,13 @@ GTimeVal *flx_elapse_time(GTimeVal *tv, guint msec, guint jitter) { return tv; } + +gint flx_age(const GTimeVal *a) { + GTimeVal now; + + g_assert(a); + + g_get_current_time(&now); + + return flx_timeval_diff(&now, a); +} diff --git a/util.h b/util.h index 517c2f1..36987a7 100644 --- a/util.h +++ b/util.h @@ -15,4 +15,6 @@ gint flx_wait_for_write(gint fd); GTimeVal *flx_elapse_time(GTimeVal *tv, guint msec, guint jitter); +gint flx_age(const GTimeVal *a); + #endif -- 2.39.5