]> git.meshlink.io Git - catta/commitdiff
add client part of probing
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Apr 2005 01:41:09 +0000 (01:41 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 14 Apr 2005 01:41:09 +0000 (01:41 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@25 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

14 files changed:
announce.c
announce.h
dns.c
dns.h
flx.h
iface.c
iface.h
main.c
psched.c
psched.h
rr.c
rr.h
server.c
server.h

index 1671758d2fcab2ed844a919a297d0769434bb243..cd2b1fa7c57aed4f630f4986e7d2b93808c353a5 100644 (file)
@@ -15,69 +15,116 @@ static void remove_announcement(flxServer *s, flxAnnouncement *a) {
     g_free(a);
 }
 
-static void elapse_announce(flxTimeEvent *e, void *userdata) {
-    flxAnnouncement *a = userdata;
+static void elapse_announce(flxTimeEvent *e, void *userdata);
+
+static void send_packet(flxAnnouncement *a) {
     GTimeVal tv;
-    gchar *t;
-        
-    g_assert(e);
     g_assert(a);
 
-    flx_interface_post_response(a->interface, NULL, a->entry->record, FALSE);
+/*     g_message("%i -- %u", a->state, a->n_iteration); */
+    
+    if (a->state == FLX_PROBING && a->n_iteration >= 1) {
+        flx_interface_post_probe(a->interface, a->entry->record, FALSE);
+    } else if (a->state == FLX_ANNOUNCING && a->n_iteration >= 1)
+        flx_interface_post_response(a->interface, NULL, a->entry->record, a->entry->flags & FLX_SERVER_ENTRY_UNIQUE, TRUE);
+
+    a->n_iteration++;
 
-    if (a->n_announced++ <= 8)
-        a->sec_delay *= 2;
+    if (a->state == FLX_PROBING) {
 
-    g_message("Announcement #%i on interface %s.%i for entry [%s]", a->n_announced, a->interface->hardware->name, a->interface->protocol, t = flx_record_to_string(a->entry->record));
-    g_free(t);
+        if (a->n_iteration == 1)
+            flx_elapse_time(&tv, 0, 250);
+        else
+            flx_elapse_time(&tv, 250, 0);
+
+        /* Probing done */
+        if (a->n_iteration >= 4) {
+            gchar *t;
+            g_message("Enough probes for record [%s]", t = flx_record_to_string(a->entry->record));
+            g_free(t);
+            a->state = FLX_ANNOUNCING;
+            a->n_iteration = 1;
+        }
+        
+    } else if (a->state == FLX_ANNOUNCING) {
 
-    if (a->n_announced >= 4) {
-        g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record));
-        g_free(t);
-        remove_announcement(a->server, a);
-    } else { 
         flx_elapse_time(&tv, a->sec_delay*1000, FLX_ANNOUNCEMENT_JITTER_MSEC);
-        flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv);
+        
+        if (a->n_iteration < 10)
+            a->sec_delay *= 2;
+
+        /* Announcing done */
+        if (a->n_iteration >= 4) {
+            gchar *t;
+            g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record));
+            g_free(t);
+            remove_announcement(a->server, a);
+            return;
+        }
     }
+
+    if (a->time_event) 
+        flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv);
+    else
+        a->time_event = flx_time_event_queue_add(a->server->time_event_queue, &tv, elapse_announce, a);
+}
+
+static void elapse_announce(flxTimeEvent *e, void *userdata) {
+    g_assert(e);
+
+    send_packet(userdata);
+}
+
+static flxAnnouncement *get_announcement(flxServer *s, flxServerEntry *e, flxInterface *i) {
+    flxAnnouncement *a;
+    
+    g_assert(s);
+    g_assert(e);
+    g_assert(i);
+
+    for (a = e->announcements; a; a = a->by_entry_next)
+        if (a->interface == i)
+            return a;
+
+    return NULL;
 }
 
 static void new_announcement(flxServer *s, flxInterface *i, flxServerEntry *e) {
     flxAnnouncement *a;
     GTimeVal tv;
-    gchar *t;
+    gchar *t; 
 
     g_assert(s);
     g_assert(i);
     g_assert(e);
 
-    g_message("NEW ANNOUNCEMENT: %s.%i [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record));
-    g_free(t);
+/*     g_message("NEW ANNOUNCEMENT: %s.%i [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record)); */
+/*     g_free(t); */
     
-    if (!flx_interface_match(i, e->interface, e->protocol) || !i->announcing)
+    if (!flx_interface_match(i, e->interface, e->protocol) || !i->announcing || e->flags & FLX_SERVER_ENTRY_NOANNOUNCE)
+        return;
+
+    /* We don't want duplicate announcements */
+    if (get_announcement(s, e, i))
         return;
 
-    /* We don't want duplicates */
-    for (a = e->announcements; a; a = a->by_entry_next)
-        if (a->interface == i)
-            return;
-    
     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, NULL, e->record, FALSE);
-    
+
     a = g_new(flxAnnouncement, 1);
     a->server = s;
     a->interface = i;
     a->entry = e;
-    a->n_announced = 1;
+
+    a->state = (e->flags & FLX_SERVER_ENTRY_UNIQUE) && !(e->flags & FLX_SERVER_ENTRY_NOPROBE) ? FLX_PROBING : FLX_ANNOUNCING;
+    a->n_iteration = 0;
     a->sec_delay = 1;
+    a->time_event = NULL;
     
     FLX_LLIST_PREPEND(flxAnnouncement, by_interface, i->announcements, a);
     FLX_LLIST_PREPEND(flxAnnouncement, by_entry, e->announcements, a);
-    
-    flx_elapse_time(&tv, a->sec_delay*1000, FLX_ANNOUNCEMENT_JITTER_MSEC);
-    a->time_event = flx_time_event_queue_add(s->time_event_queue, &tv, elapse_announce, a);
+
+    send_packet(a);
 }
 
 void flx_announce_interface(flxServer *s, flxInterface *i) {
@@ -89,7 +136,7 @@ void flx_announce_interface(flxServer *s, flxInterface *i) {
     if (!i->announcing)
         return;
 
-    g_message("ANNOUNCE INTERFACE");
+/*     g_message("ANNOUNCE INTERFACE"); */
     
     for (e = s->entries; e; e = e->entry_next)
         new_announcement(s, i, e);
@@ -109,11 +156,29 @@ void flx_announce_entry(flxServer *s, flxServerEntry *e) {
     g_assert(s);
     g_assert(e);
 
-    g_message("ANNOUNCE ENTRY");
+/*     g_message("ANNOUNCE ENTRY"); */
 
     flx_interface_monitor_walk(s->monitor, e->interface, e->protocol, announce_walk_callback, e);
 }
 
+gboolean flx_entry_established(flxServer *s, flxServerEntry *e, flxInterface *i) {
+    flxAnnouncement *a;
+
+    g_assert(s);
+    g_assert(e);
+    g_assert(i);
+
+    if (!(e->flags & FLX_SERVER_ENTRY_UNIQUE) || (e->flags & FLX_SERVER_ENTRY_NOPROBE))
+        return TRUE;
+
+    if ((a = get_announcement(s, e, i)))
+        if (a->state == FLX_PROBING)
+            return FALSE;
+
+    return TRUE;
+}
+
+
 static flxRecord *make_goodbye_record(flxRecord *r) {
     gchar *t;
     flxRecord *g;
@@ -129,38 +194,64 @@ static flxRecord *make_goodbye_record(flxRecord *r) {
 
     return g;
 }
+
+
+static void send_goodbye_callback(flxInterfaceMonitor *m, flxInterface *i, gpointer userdata) {
+    flxServerEntry *e = userdata;
+    flxRecord *g;
+    
+    g_assert(m);
+    g_assert(i);
+    g_assert(e);
+
+    if (!flx_interface_match(i, e->interface, e->protocol))
+        return;
+
+    if (e->flags & FLX_SERVER_ENTRY_NOANNOUNCE)
+        return;
+
+    if (!flx_entry_established(m->server, e, i))
+        return;
+    
+    g = make_goodbye_record(e->record);
+    flx_interface_post_response(i, NULL, g, e->flags & FLX_SERVER_ENTRY_UNIQUE, TRUE);
+    flx_record_unref(g);
+}
     
 void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) {
     g_assert(s);
     g_assert(i);
 
-    while (i->announcements)
-        remove_announcement(s, i->announcements);
+    g_message("goodbye interface: %s.%u", i->hardware->name, i->protocol);
 
     if (goodbye && flx_interface_relevant(i)) {
         flxServerEntry *e;
         
         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, NULL, g, TRUE);
-                flx_record_unref(g);
-            }
+            send_goodbye_callback(s->monitor, i, e);
     }
+
+    while (i->announcements)
+        remove_announcement(s, i->announcements);
+
+    g_message("goodbye interface done: %s.%u", i->hardware->name, i->protocol);
+
 }
 
 void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean goodbye) {
     g_assert(s);
     g_assert(e);
+
+    g_message("goodbye entry: %p", e);
     
+    if (goodbye)
+        flx_interface_monitor_walk(s->monitor, 0, AF_UNSPEC, send_goodbye_callback, e);
+
     while (e->announcements)
         remove_announcement(s, e->announcements);
-    
-    if (goodbye) {
-        flxRecord *g = make_goodbye_record(e->record);
-        flx_server_post_response(s, e->interface, e->protocol, g);
-        flx_record_unref(g);
-    }
+
+    g_message("goodbye entry done: %p", e);
+
 }
 
 void flx_goodbye_all(flxServer *s, gboolean goodbye) {
@@ -168,6 +259,12 @@ void flx_goodbye_all(flxServer *s, gboolean goodbye) {
     
     g_assert(s);
 
+    g_message("goodbye all: %p", e);
+
     for (e = s->entries; e; e = e->entry_next)
         flx_goodbye_entry(s, e, goodbye);
+
+    g_message("goodbye all done: %p", e);
+
 }
+
index 49c5f132ce81119555596d65a464326321b34821..ab8ce128680d9540bf345e123f75cc3f7e5b7f3c 100644 (file)
@@ -10,13 +10,20 @@ typedef struct _flxAnnouncement flxAnnouncement;
 #include "server.h"
 #include "timeeventq.h"
 
+typedef enum {
+    FLX_PROBING,
+    FLX_ANNOUNCING,
+} flxAnnouncementState;
+
 struct _flxAnnouncement {
     flxServer *server;
     flxInterface *interface;
     flxServerEntry *entry;
-    
+
     flxTimeEvent *time_event;
-    guint n_announced;
+
+    flxAnnouncementState state;
+    guint n_iteration;
     guint sec_delay;
 
     FLX_LLIST_FIELDS(flxAnnouncement, by_interface);
@@ -26,6 +33,8 @@ struct _flxAnnouncement {
 void flx_announce_interface(flxServer *s, flxInterface *i);
 void flx_announce_entry(flxServer *s, flxServerEntry *e);
 
+gboolean flx_entry_established(flxServer *s, flxServerEntry *e, flxInterface *i);
+
 void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean send);
 void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean send);
 
diff --git a/dns.c b/dns.c
index 9126100ac096b3a8944193651d89950923ab1765..073eaba57de5549ac5a6455bfbf02e59a050d60b 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -26,7 +26,7 @@ flxDnsPacket* flx_dns_packet_new_query(guint max_size) {
     flxDnsPacket *p;
 
     p = flx_dns_packet_new(max_size);
-    flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_FLAGS, FLX_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
     return p;
 }
 
@@ -34,7 +34,7 @@ flxDnsPacket* flx_dns_packet_new_response(guint max_size) {
     flxDnsPacket *p;
 
     p = flx_dns_packet_new(max_size);
-    flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, DNS_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_FLAGS, FLX_DNS_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
     return p;
 }
 
@@ -200,9 +200,9 @@ gint flx_dns_packet_check_valid(flxDnsPacket *p) {
     if (p->size < 12)
         return -1;
 
-    flags = flx_dns_packet_get_field(p, DNS_FIELD_FLAGS);
+    flags = flx_dns_packet_get_field(p, FLX_DNS_FIELD_FLAGS);
 
-    if (flags & DNS_FLAG_OPCODE || flags & DNS_FLAG_RCODE)
+    if (flags & FLX_DNS_FLAG_OPCODE || flags & FLX_DNS_FLAG_RCODE)
         return -1;
 
     return 0;
@@ -211,7 +211,7 @@ gint flx_dns_packet_check_valid(flxDnsPacket *p) {
 gint flx_dns_packet_is_query(flxDnsPacket *p) {
     g_assert(p);
     
-    return !(flx_dns_packet_get_field(p, DNS_FIELD_FLAGS) & DNS_FLAG_QR);
+    return !(flx_dns_packet_get_field(p, FLX_DNS_FIELD_FLAGS) & FLX_DNS_FLAG_QR);
 }
 
 static gint consume_labels(flxDnsPacket *p, guint index, gchar *ret_name, guint l) {
@@ -501,8 +501,8 @@ flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_fl
     if ((guint8*) flx_dns_packet_get_rptr(p) - (guint8*) start != rdlength)
         goto fail;
     
-    *ret_cache_flush = !!(class & MDNS_CACHE_FLUSH);
-    class &= ~ MDNS_CACHE_FLUSH;
+    *ret_cache_flush = !!(class & FLX_DNS_CACHE_FLUSH);
+    class &= ~ FLX_DNS_CACHE_FLUSH;
 
     r->ttl = ttl;
 
@@ -526,7 +526,7 @@ flxKey* flx_dns_packet_consume_key(flxDnsPacket *p) {
         flx_dns_packet_consume_uint16(p, &class) < 0)
         return NULL;
 
-    class &= ~ MDNS_CACHE_FLUSH;
+    class &= ~ FLX_DNS_CACHE_FLUSH;
 
     return flx_key_new(name, class, type);
 }
@@ -561,7 +561,7 @@ guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cac
 
     if (!(t = flx_dns_packet_append_name(p, r->key->name)) ||
         !flx_dns_packet_append_uint16(p, r->key->type) ||
-        !flx_dns_packet_append_uint16(p, cache_flush ? (r->key->class | MDNS_CACHE_FLUSH) : (r->key->class &~ MDNS_CACHE_FLUSH)) ||
+        !flx_dns_packet_append_uint16(p, cache_flush ? (r->key->class | FLX_DNS_CACHE_FLUSH) : (r->key->class &~ FLX_DNS_CACHE_FLUSH)) ||
         !flx_dns_packet_append_uint32(p, r->ttl) ||
         !(l = flx_dns_packet_append_uint16(p, 0)))
         goto fail;
@@ -658,3 +658,11 @@ gboolean flx_dns_packet_is_empty(flxDnsPacket *p) {
 
     return p->size <= FLX_DNS_PACKET_HEADER_SIZE;
 }
+
+guint flx_dns_packet_space(flxDnsPacket *p) {
+    g_assert(p);
+
+    g_assert(p->size <= p->max_size);
+    
+    return p->max_size - p->size;
+}
diff --git a/dns.h b/dns.h
index 38944d3d86aebd823b7afdad55afc9fcd0a66079..45151322d291a677389d8fe80ce7737243aae10f 100644 (file)
--- a/dns.h
+++ b/dns.h
@@ -50,20 +50,21 @@ gconstpointer flx_dns_packet_get_rptr(flxDnsPacket *p);
 gint flx_dns_packet_skip(flxDnsPacket *p, guint length);
 
 gboolean flx_dns_packet_is_empty(flxDnsPacket *p);
+guint flx_dns_packet_space(flxDnsPacket *p);
 
-#define DNS_FIELD_ID 0
-#define DNS_FIELD_FLAGS 1
-#define DNS_FIELD_QDCOUNT 2
-#define DNS_FIELD_ANCOUNT 3
-#define DNS_FIELD_NSCOUNT 4
-#define DNS_FIELD_ARCOUNT 5
+#define FLX_DNS_FIELD_ID 0
+#define FLX_DNS_FIELD_FLAGS 1
+#define FLX_DNS_FIELD_QDCOUNT 2
+#define FLX_DNS_FIELD_ANCOUNT 3
+#define FLX_DNS_FIELD_NSCOUNT 4
+#define FLX_DNS_FIELD_ARCOUNT 5
 
-#define DNS_FLAG_QR (1 << 15)
-#define DNS_FLAG_OPCODE (15 << 11)
-#define DNS_FLAG_RCODE (15)
-#define DNS_FLAG_TC (1 << 9)
+#define FLX_DNS_FLAG_QR (1 << 15)
+#define FLX_DNS_FLAG_OPCODE (15 << 11)
+#define FLX_DNS_FLAG_RCODE (15)
+#define FLX_DNS_FLAG_TC (1 << 9)
 
-#define DNS_FLAGS(qr, opcode, aa, tc, rd, ra, z, ad, cd, rcode) \
+#define FLX_DNS_FLAGS(qr, opcode, aa, tc, rd, ra, z, ad, cd, rcode) \
         (((guint16) !!qr << 15) |  \
          ((guint16) (opcode & 15) << 11) | \
          ((guint16) !!aa << 10) | \
@@ -75,7 +76,5 @@ gboolean flx_dns_packet_is_empty(flxDnsPacket *p);
          ((guint16) (rd & 15)))
          
 
-#define MDNS_CACHE_FLUSH 0x8000
-
 #endif
 
diff --git a/flx.h b/flx.h
index 8f8b0bac4c1ddcde36d486ea30862215d07dc90a..d60dede029c39b6c4d67ade7f8ebe22520ce8265 100644 (file)
--- a/flx.h
+++ b/flx.h
@@ -9,6 +9,13 @@ typedef struct _flxServer flxServer;
 #include "address.h"
 #include "rr.h"
 
+typedef enum {
+    FLX_SERVER_ENTRY_NULL = 0,
+    FLX_SERVER_ENTRY_UNIQUE = 1,
+    FLX_SERVER_ENTRY_NOPROBE = 2,
+    FLX_SERVER_ENTRY_NOANNOUNCE = 4
+} flxServerEntryFlags;
+
 flxServer *flx_server_new(GMainContext *c);
 void flx_server_free(flxServer* s);
 
@@ -19,7 +26,7 @@ void flx_server_add(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     flxRecord *r);
 
 void flx_server_add_ptr(
@@ -27,7 +34,7 @@ void flx_server_add_ptr(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     const gchar *dest);
 
@@ -36,7 +43,7 @@ void flx_server_add_address(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     flxAddress *a);
 
@@ -45,7 +52,7 @@ void flx_server_add_text(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     ... /* text records, terminated by NULL */);
 
@@ -54,7 +61,7 @@ void flx_server_add_text_va(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     va_list va);
 
@@ -86,7 +93,7 @@ void flx_server_add_service_va(
 void flx_server_remove(flxServer *s, gint id);
 
 void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *key);
-void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record);
+void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record, gboolean flush_cache);
 
 const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state);
 
diff --git a/iface.c b/iface.c
index d2daf407272509d10bf2024b632da005d4774902..0afdb7094e3c83c7be94a8cfdf6c2d4f1e552262 100644 (file)
--- a/iface.c
+++ b/iface.c
@@ -24,7 +24,7 @@ static void update_address_rr(flxInterfaceMonitor *m, flxInterfaceAddress *a, in
     } else {
         if (a->rr_id < 0) {
             a->rr_id = flx_server_get_next_id(m->server);
-            flx_server_add_address(m->server, a->rr_id, a->interface->hardware->index, AF_UNSPEC, FALSE, m->server->hostname, &a->address);
+            flx_server_add_address(m->server, a->rr_id, a->interface->hardware->index, AF_UNSPEC, 0, NULL, &a->address);
         }
     }
 }
@@ -447,12 +447,20 @@ void flx_interface_post_query(flxInterface *i, flxKey *key, gboolean immediately
 }
 
 
-void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *record, gboolean immediately) {
+void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *record, gboolean flush_cache, gboolean immediately) {
     g_assert(i);
     g_assert(record);
 
     if (flx_interface_relevant(i))
-        flx_packet_scheduler_post_response(i->scheduler, a, record, immediately);
+        flx_packet_scheduler_post_response(i->scheduler, a, record, flush_cache, immediately);
+}
+
+void flx_interface_post_probe(flxInterface *i, flxRecord *record, gboolean immediately) {
+    g_assert(i);
+    g_assert(record);
+    
+    if (flx_interface_relevant(i))
+        flx_packet_scheduler_post_probe(i->scheduler, record, immediately);
 }
 
 void flx_dump_caches(flxInterfaceMonitor *m, FILE *f) {
diff --git a/iface.h b/iface.h
index 4b0aef876eebedbb6be203b380440a09ec4fdb5b..53d3441c99df59fd8ebac1f89bbad2b15363a6d0 100644 (file)
--- a/iface.h
+++ b/iface.h
@@ -83,7 +83,8 @@ 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, const flxAddress *a, flxRecord *rr, gboolean immediately);
+void flx_interface_post_probe(flxInterface *i, flxRecord *p, gboolean immediately);
+void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *record, gboolean flush_cache, gboolean immediately);
 
 void flx_dump_caches(flxInterfaceMonitor *m, FILE *f);
 
diff --git a/main.c b/main.c
index 3bf4360bc9cad3168437d6bbc7c58058f6a7cf0e..139279c6808cf42da61bfe10245dcb8242ba5809 100644 (file)
--- a/main.c
+++ b/main.c
@@ -15,13 +15,13 @@ static gboolean send_timeout(gpointer data) {
     flxServer *flx = data;
     flxKey *k;
 
-    k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT);
-    flx_server_post_query(flx, 0, AF_UNSPEC, k);
-    flx_key_unref(k);
+/*     k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT); */
+/*     flx_server_post_query(flx, 0, AF_UNSPEC, k); */
+/*     flx_key_unref(k); */
 
-    k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
-    flx_server_post_query(flx, 0, AF_INET, k);
-    flx_key_unref(k);
+/*     k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A); */
+/*     flx_server_post_query(flx, 0, AF_INET, k); */
+/*     flx_key_unref(k); */
 
     return FALSE;
 }
@@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
 
     flx = flx_server_new(NULL);
 
-    flx_server_add_text(flx, 0, 0, AF_UNSPEC, FALSE, NULL, "hallo", NULL);
+    flx_server_add_text(flx, 0, 0, AF_UNSPEC, FLX_SERVER_ENTRY_UNIQUE, NULL, "hallo", NULL);
     flx_server_add_service(flx, 0, 0, AF_UNSPEC, "_http._tcp", "gurke", NULL, NULL, 80, "foo", NULL);
 
 /*     k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_ANY); */
index 1b6d26c8763d0f1b2c94be24d1bf2a89d1cfc353..e9f77b9e08e1d0bf7d622b673dc7a720fb455431 100644 (file)
--- a/psched.c
+++ b/psched.c
@@ -3,11 +3,12 @@
 #include "util.h"
 #include "psched.h"
 
-#define FLX_QUERY_HISTORY_MSEC 700
+#define FLX_QUERY_HISTORY_MSEC 100
 #define FLX_QUERY_DEFER_MSEC 100
 #define FLX_RESPONSE_HISTORY_MSEC 700
 #define FLX_RESPONSE_DEFER_MSEC 20
 #define FLX_RESPONSE_JITTER_MSEC 100
+#define FLX_PROBE_DEFER_MSEC 100
 
 flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i) {
     flxPacketScheduler *s;
@@ -22,6 +23,7 @@ flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i)
     FLX_LLIST_HEAD_INIT(flxQueryJob, s->query_jobs);
     FLX_LLIST_HEAD_INIT(flxResponseJob, s->response_jobs);
     FLX_LLIST_HEAD_INIT(flxKnownAnswer, s->known_answers);
+    FLX_LLIST_HEAD_INIT(flxProbeJob, s->probe_jobs);
     
     return s;
 }
@@ -50,9 +52,22 @@ static void response_job_free(flxPacketScheduler *s, flxResponseJob *rj) {
     g_free(rj);
 }
 
+static void probe_job_free(flxPacketScheduler *s, flxProbeJob *pj) {
+    g_assert(pj);
+
+    if (pj->time_event)
+        flx_time_event_queue_remove(pj->scheduler->server->time_event_queue, pj->time_event);
+
+    FLX_LLIST_REMOVE(flxProbeJob, jobs, s->probe_jobs, pj);
+
+    flx_record_unref(pj->record);
+    g_free(pj);
+}
+
 void flx_packet_scheduler_free(flxPacketScheduler *s) {
     flxQueryJob *qj;
     flxResponseJob *rj;
+    flxProbeJob *pj;
     flxTimeEvent *e;
 
     g_assert(s);
@@ -63,6 +78,8 @@ void flx_packet_scheduler_free(flxPacketScheduler *s) {
         query_job_free(s, qj);
     while ((rj = s->response_jobs))
         response_job_free(s, rj);
+    while ((pj = s->probe_jobs))
+        probe_job_free(s, pj);
 
     g_free(s);
 }
@@ -126,8 +143,8 @@ static void append_known_answers_and_send(flxPacketScheduler *s, flxDnsPacket *p
 
             g_assert(!flx_dns_packet_is_empty(p));
 
-            flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, flx_dns_packet_get_field(p, DNS_FIELD_FLAGS) | DNS_FLAG_TC);
-            flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
+            flx_dns_packet_set_field(p, FLX_DNS_FIELD_FLAGS, flx_dns_packet_get_field(p, FLX_DNS_FIELD_FLAGS) | FLX_DNS_FLAG_TC);
+            flx_dns_packet_set_field(p, FLX_DNS_FIELD_ANCOUNT, n);
             flx_interface_send_packet(s->interface, p);
             flx_dns_packet_free(p);
 
@@ -142,7 +159,7 @@ static void append_known_answers_and_send(flxPacketScheduler *s, flxDnsPacket *p
         n++;
     }
     
-    flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_ANCOUNT, n);
     flx_interface_send_packet(s->interface, p);
     flx_dns_packet_free(p);
 }
@@ -182,7 +199,7 @@ static void query_elapse(flxTimeEvent *e, gpointer data) {
         n++;
     }
 
-    flx_dns_packet_set_field(p, DNS_FIELD_QDCOUNT, n);
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_QDCOUNT, n);
 
     /* Now add known answers */
     append_known_answers_and_send(s, p);
@@ -242,7 +259,7 @@ static guint8* packet_add_response_job(flxPacketScheduler *s, flxDnsPacket *p, f
     g_assert(p);
     g_assert(rj);
 
-    if ((d = flx_dns_packet_append_record(p, rj->record, FALSE))) {
+    if ((d = flx_dns_packet_append_record(p, rj->record, rj->flush_cache))) {
         GTimeVal tv;
 
         rj->done = 1;
@@ -286,7 +303,7 @@ static void send_response_packet(flxPacketScheduler *s, flxResponseJob *rj) {
         n++;
     }
 
-    flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_ANCOUNT, n);
     flx_interface_send_packet(s->interface, p);
     flx_dns_packet_free(p);
 }
@@ -331,13 +348,15 @@ static flxResponseJob* response_job_new(flxPacketScheduler *s, flxRecord *record
     rj->record = flx_record_ref(record);
     rj->done = FALSE;
     rj->time_event = NULL;
+    rj->address_valid = FALSE;
+    rj->flush_cache = FALSE;
     
     FLX_LLIST_PREPEND(flxResponseJob, jobs, s->response_jobs, rj);
 
     return rj;
 }
 
-void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress *a, flxRecord *record, gboolean immediately) {
+void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress *a, flxRecord *record, gboolean flush_cache, gboolean immediately) {
     flxResponseJob *rj;
     GTimeVal tv;
     gchar *t;
@@ -365,7 +384,11 @@ void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress
             /* 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;
+
+            if (rj->address_valid && (!a || flx_address_cmp(a, &rj->address) != 0))
+                rj->address_valid = FALSE;
+
+            rj->flush_cache = flush_cache;
             
             return;
         }
@@ -380,6 +403,7 @@ void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress
 
     /* Create a new job and schedule it */
     rj = response_job_new(s, record);
+    rj->flush_cache = flush_cache;
     rj->delivery = tv;
     rj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &rj->delivery, response_elapse, rj);
 
@@ -508,18 +532,22 @@ void flx_packet_scheduler_incoming_known_answer(flxPacketScheduler *s, flxRecord
     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) {
+    for (rj = s->response_jobs; rj; rj = rj->jobs_next) {
+
+        g_assert(record->ttl > 0);
+        g_assert(rj->record->ttl/2);
+        
+        if (flx_record_equal_no_ttl(rj->record, record))
+            if (rj->address_valid)
+                if (flx_address_cmp(&rj->address, a))
+                    if (record->ttl >= rj->record->ttl/2) {
 
             /* Let's suppress it */
 
             response_job_free(s, rj);
             break;
         }
-    
+    }
 }
 
 void flx_packet_scheduler_flush_responses(flxPacketScheduler *s) {
@@ -533,3 +561,152 @@ void flx_packet_scheduler_flush_responses(flxPacketScheduler *s) {
         if (!rj->done)
             send_response_packet(s, rj);
 }
+
+static flxProbeJob* probe_job_new(flxPacketScheduler *s, flxRecord *record) {
+    flxProbeJob *pj;
+    
+    g_assert(s);
+    g_assert(record);
+
+    pj = g_new(flxProbeJob, 1);
+    pj->scheduler = s;
+    pj->record = flx_record_ref(record);
+    pj->time_event = NULL;
+    pj->chosen = FALSE;
+    
+    FLX_LLIST_PREPEND(flxProbeJob, jobs, s->probe_jobs, pj);
+
+    return pj;
+}
+
+static guint8* packet_add_probe_query(flxPacketScheduler *s, flxDnsPacket *p, flxProbeJob *pj) {
+    guint size;
+    guint8 *r;
+    flxKey *k;
+
+    g_assert(s);
+    g_assert(p);
+    g_assert(pj);
+
+    g_assert(!pj->chosen);
+    
+    /* Estimate the size for this record */
+    size =
+        flx_key_get_estimate_size(pj->record->key) +
+        flx_record_get_estimate_size(pj->record);
+
+    /* Too large */
+    if (size > flx_dns_packet_space(p))
+        return NULL;
+
+    /* Create the probe query */
+    k = flx_key_new(pj->record->key->name, pj->record->key->class, FLX_DNS_TYPE_ANY);
+    r = flx_dns_packet_append_key(p, k);
+
+    /* Mark this job for addition to the packet */
+    pj->chosen = TRUE;
+
+    /* Scan for more jobs whith matching key pattern */
+    for (pj = s->probe_jobs; pj; pj = pj->jobs_next) {
+        if (pj->chosen)
+            continue;
+
+        /* Does the record match the probe? */
+        if (k->class != pj->record->key->class || strcmp(k->name, pj->record->key->name))
+            continue;
+        
+        /* This job wouldn't fit in */
+        if (flx_record_get_estimate_size(pj->record) > flx_dns_packet_space(p))
+            break;
+
+        /* Mark this job for addition to the packet */
+        pj->chosen = TRUE;
+    }
+
+    flx_key_unref(k);
+            
+    return r;
+}
+
+static void probe_elapse(flxTimeEvent *e, gpointer data) {
+    flxProbeJob *pj = data, *next;
+    flxPacketScheduler *s;
+    flxDnsPacket *p;
+    guint n;
+    guint8 *d;
+
+    g_assert(pj);
+    s = pj->scheduler;
+
+    p = flx_dns_packet_new_query(s->interface->hardware->mtu - 48);
+
+    /* Add the import probe */
+    if (!packet_add_probe_query(s, p, pj)) {
+        g_warning("Record too large!");
+        flx_dns_packet_free(p);
+        return;
+    }
+
+    n = 1;
+    
+    /* Try to fill up packet with more probes, if available */
+    for (pj = s->probe_jobs; pj; pj = pj->jobs_next) {
+
+        if (pj->chosen)
+            continue;
+        
+        if (!packet_add_probe_query(s, p, pj))
+            break;
+        
+        n++;
+    }
+
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_QDCOUNT, n);
+
+    n = 0;
+
+    /* Now add the chosen records to the authorative section */
+    for (pj = s->probe_jobs; pj; pj = next) {
+
+        next = pj->jobs_next;
+
+        if (!pj->chosen)
+            continue;
+
+        if (!flx_dns_packet_append_record(p, pj->record, TRUE)) {
+            g_warning("Bad probe size estimate!");
+
+            /* Unmark all following jobs */
+            for (; pj; pj = pj->jobs_next)
+                pj->chosen = FALSE;
+            
+            break;
+        }
+
+        probe_job_free(s, pj);
+        n ++;
+    }
+    
+    flx_dns_packet_set_field(p, FLX_DNS_FIELD_NSCOUNT, n);
+
+    /* Send it now */
+    flx_interface_send_packet(s->interface, p);
+    flx_dns_packet_free(p);
+}
+
+void flx_packet_scheduler_post_probe(flxPacketScheduler *s, flxRecord *record, gboolean immediately) {
+    flxProbeJob *pj;
+    GTimeVal tv;
+    
+    g_assert(s);
+    g_assert(record);
+    g_assert(!flx_key_is_pattern(record->key));
+    
+    flx_elapse_time(&tv, immediately ? 0 : FLX_PROBE_DEFER_MSEC, 0);
+
+    /* No duplication check here... */
+    /* Create a new job and schedule it */
+    pj = probe_job_new(s, record);
+    pj->delivery = tv;
+    pj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &pj->delivery, probe_elapse, pj);
+}
index 7290265c1d957b09881f2a7beca8496524a438b3..9866f2f9a0464781151365c421d2d7c7a2e7729d 100644 (file)
--- a/psched.h
+++ b/psched.h
@@ -5,6 +5,7 @@ typedef struct _flxQueryJob flxQueryJob;
 typedef struct _flxResponseJob flxResponseJob;
 typedef struct _flxPacketScheduler flxPacketScheduler;
 typedef struct _flxKnownAnswer flxKnownAnswer;
+typedef struct _flxProbeJob flxProbeJob;
 
 #include "timeeventq.h"
 #include "rr.h"
@@ -28,6 +29,7 @@ struct _flxResponseJob {
     gboolean address_valid;
     gboolean done;
     GTimeVal delivery;
+    gboolean flush_cache;
     FLX_LLIST_FIELDS(flxResponseJob, jobs);
 };
 
@@ -38,6 +40,17 @@ struct _flxKnownAnswer {
     FLX_LLIST_FIELDS(flxKnownAnswer, known_answer);
 };
 
+struct _flxProbeJob {
+    flxPacketScheduler *scheduler;
+    flxTimeEvent *time_event;
+    flxRecord *record;
+
+    gboolean chosen; /* Use for packet assembling */
+    GTimeVal delivery;
+    
+    FLX_LLIST_FIELDS(flxProbeJob, jobs);
+};
+
 struct _flxPacketScheduler {
     flxServer *server;
     
@@ -46,13 +59,15 @@ struct _flxPacketScheduler {
     FLX_LLIST_HEAD(flxQueryJob, query_jobs);
     FLX_LLIST_HEAD(flxResponseJob, response_jobs);
     FLX_LLIST_HEAD(flxKnownAnswer, known_answers);
+    FLX_LLIST_HEAD(flxProbeJob, probe_jobs);
 };
 
 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, const flxAddress *a, flxRecord *record, gboolean immediately);
+void flx_packet_scheduler_post_response(flxPacketScheduler *s, const flxAddress *a, flxRecord *record, gboolean flush_cache, gboolean immediately);
+void flx_packet_scheduler_post_probe(flxPacketScheduler *s, flxRecord *record, gboolean immediately);
 
 void flx_packet_scheduler_incoming_query(flxPacketScheduler *s, flxKey *key);
 void flx_packet_scheduler_incoming_response(flxPacketScheduler *s, flxRecord *record);
diff --git a/rr.c b/rr.c
index fe475eb0e5a58f69ed11cab5d5c0214130802877..f72557b055ebf01101a00707cfad7c3cc5d82ff8 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -121,6 +121,9 @@ void flx_record_unref(flxRecord *r) {
 }
 
 const gchar *flx_dns_class_to_string(guint16 class) {
+    if (class & FLX_DNS_CACHE_FLUSH) 
+        return "FLUSH";
+    
     if (class == FLX_DNS_CLASS_IN)
         return "IN";
 
@@ -143,6 +146,8 @@ const gchar *flx_dns_type_to_string(guint16 type) {
             return "TXT";
         case FLX_DNS_TYPE_SRV:
             return "SRV";
+        case FLX_DNS_TYPE_ANY:
+            return "ANY";
         default:
             return NULL;
     }
@@ -344,3 +349,49 @@ flxRecord *flx_record_copy(flxRecord *r) {
 
     return copy;
 }
+
+
+guint flx_key_get_estimate_size(flxKey *k) {
+    g_assert(k);
+
+    return strlen(k->name)+1+4;
+}
+
+guint flx_record_get_estimate_size(flxRecord *r) {
+    guint n;
+    g_assert(r);
+
+    n = flx_key_get_estimate_size(r->key) + 4 + 2;
+
+    switch (r->key->type) {
+        case FLX_DNS_TYPE_PTR:
+        case FLX_DNS_TYPE_CNAME:
+            n += strlen(r->data.ptr.name) + 1;
+            break;
+
+        case FLX_DNS_TYPE_SRV:
+            n += 6 + strlen(r->data.srv.name) + 1;
+            break;
+
+        case FLX_DNS_TYPE_HINFO:
+            n += strlen(r->data.hinfo.os) + 1 + strlen(r->data.hinfo.cpu) + 1;
+            break;
+
+        case FLX_DNS_TYPE_TXT:
+            n += flx_string_list_serialize(r->data.txt.string_list, NULL, 0);
+            break;
+
+        case FLX_DNS_TYPE_A:
+            n += sizeof(flxIPv4Address);
+            break;
+
+        case FLX_DNS_TYPE_AAAA:
+            n += sizeof(flxIPv6Address);
+            break;
+
+        default:
+            n += r->data.generic.size;
+    }
+
+    return n;
+}
diff --git a/rr.h b/rr.h
index 1ba6d958533abed0051669e74a852a57c3658e33..483fcaae7e1724d5bac5b787ccb91bf0ed47b12d 100644 (file)
--- a/rr.h
+++ b/rr.h
@@ -21,7 +21,8 @@ enum {
 };
 
 enum {
-    FLX_DNS_CLASS_IN = 0x01
+    FLX_DNS_CLASS_IN = 0x01,
+    FLX_DNS_CACHE_FLUSH = 0x8000
 };
 
 #define FLX_DEFAULT_TTL (120*60)
@@ -103,4 +104,12 @@ gboolean flx_record_equal_no_ttl(const flxRecord *a, const flxRecord *b);
 
 flxRecord *flx_record_copy(flxRecord *r);
 
+/* returns a maximum estimate for the space that is needed to store
+ * this key in a DNS packet */
+guint flx_key_get_estimate_size(flxKey *k);
+
+/* ditto */
+guint flx_record_get_estimate_size(flxRecord *r);
+
+
 #endif
index fcf42487d9a85dfb9aef65c2306a345636e53e3b..56e4d813600b53cd656866e1d84a390d98d5828f 100644 (file)
--- a/server.c
+++ b/server.c
@@ -30,15 +30,15 @@ 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, a, e->record, FALSE);
+                if (flx_interface_match(i, e->interface, e->protocol) && flx_entry_established(s, e, i))
+                    flx_interface_post_response(i, a, e->record, e->flags & FLX_SERVER_ENTRY_UNIQUE, 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, a, e->record, FALSE);
+            if (flx_interface_match(i, e->interface, e->protocol) && flx_entry_established(s, e, i))
+                flx_interface_post_response(i, a, e->record, e->flags & FLX_SERVER_ENTRY_UNIQUE, FALSE);
     }
 }
 
@@ -50,7 +50,7 @@ static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const f
     g_assert(i);
     g_assert(a);
 
-    for (n = flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT); n > 0; n --) {
+    for (n = flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT); n > 0; n --) {
         flxKey *key;
 
         if (!(key = flx_dns_packet_consume_key(p))) {
@@ -63,7 +63,7 @@ static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const f
     }
 
     /* Known Answer Suppresion */
-    for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT); n > 0; n --) {
+    for (n = flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT); n > 0; n --) {
         flxRecord *record;
         gboolean unique = FALSE;
 
@@ -85,8 +85,8 @@ static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, cons
     g_assert(i);
     g_assert(a);
     
-    for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT) +
-             flx_dns_packet_get_field(p, DNS_FIELD_ARCOUNT); n > 0; n--) {
+    for (n = flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT) +
+             flx_dns_packet_get_field(p, FLX_DNS_FIELD_ARCOUNT); n > 0; n--) {
         flxRecord *record;
         gboolean cache_flush = FALSE;
         gchar *txt;
@@ -152,9 +152,8 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
 
     if (flx_dns_packet_is_query(p)) {
 
-        if (flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT) == 0 ||
-            flx_dns_packet_get_field(p, DNS_FIELD_ARCOUNT) != 0 ||
-            flx_dns_packet_get_field(p, DNS_FIELD_NSCOUNT) != 0) {
+        if (flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT) == 0 ||
+            flx_dns_packet_get_field(p, FLX_DNS_FIELD_ARCOUNT) != 0) {
             g_warning("Invalid query packet.");
             return;
         }
@@ -162,9 +161,9 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
         handle_query(s, p, i, &a);    
         g_message("Handled query");
     } else {
-        if (flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT) != 0 ||
-            flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT) == 0 ||
-            flx_dns_packet_get_field(p, DNS_FIELD_NSCOUNT) != 0) {
+        if (flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT) != 0 ||
+            flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT) == 0 ||
+            flx_dns_packet_get_field(p, FLX_DNS_FIELD_NSCOUNT) != 0) {
             g_warning("Invalid response packet.");
             return;
         }
@@ -242,15 +241,15 @@ static void add_default_entries(flxServer *s) {
     uname(&utsname);
     r->data.hinfo.cpu = g_strdup(g_strup(utsname.machine));
     r->data.hinfo.os = g_strdup(g_strup(utsname.sysname));
-    flx_server_add(s, 0, 0, AF_UNSPEC, TRUE, r);
+    flx_server_add(s, 0, 0, AF_UNSPEC, FLX_SERVER_ENTRY_UNIQUE, r);
     flx_record_unref(r);
 
     /* Add localhost entries */
     flx_address_parse("127.0.0.1", AF_INET, &a);
-    flx_server_add_address(s, 0, 0, AF_UNSPEC, TRUE, "localhost", &a);
+    flx_server_add_address(s, 0, 0, AF_UNSPEC, FLX_SERVER_ENTRY_UNIQUE|FLX_SERVER_ENTRY_NOPROBE|FLX_SERVER_ENTRY_NOANNOUNCE, "localhost", &a);
 
     flx_address_parse("::1", AF_INET6, &a);
-    flx_server_add_address(s, 0, 0, AF_UNSPEC, TRUE, "ip6-localhost", &a);
+    flx_server_add_address(s, 0, 0, AF_UNSPEC, FLX_SERVER_ENTRY_UNIQUE|FLX_SERVER_ENTRY_NOPROBE|FLX_SERVER_ENTRY_NOANNOUNCE, "ip6-localhost", &a);
 }
 
 flxServer *flx_server_new(GMainContext *c) {
@@ -368,7 +367,7 @@ void flx_server_add(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     flxRecord *r) {
     
     flxServerEntry *e, *t;
@@ -382,7 +381,7 @@ void flx_server_add(
     e->id = id;
     e->interface = interface;
     e->protocol = protocol;
-    e->unique = unique;
+    e->flags = flags;
 
     FLX_LLIST_HEAD_INIT(flxAnnouncement, e->announcements);
 
@@ -483,7 +482,7 @@ void flx_server_add_ptr(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     const gchar *dest) {
 
@@ -493,7 +492,7 @@ void flx_server_add_ptr(
 
     r = flx_record_new_full(name ? name : s->hostname, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_PTR);
     r->data.ptr.name = flx_normalize_name(dest);
-    flx_server_add(s, id, interface, protocol, unique, r);
+    flx_server_add(s, id, interface, protocol, flags, r);
     flx_record_unref(r);
 
 }
@@ -503,7 +502,7 @@ void flx_server_add_address(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     flxAddress *a) {
 
@@ -519,12 +518,12 @@ void flx_server_add_address(
 
         r = flx_record_new_full(name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
         r->data.a.address = a->data.ipv4;
-        flx_server_add(s, id, interface, protocol, unique, r);
+        flx_server_add(s, id, interface, protocol, flags, r);
         flx_record_unref(r);
         
         reverse = flx_reverse_lookup_name_ipv4(&a->data.ipv4);
         g_assert(reverse);
-        flx_server_add_ptr(s, id, interface, protocol, unique, reverse, name);
+        flx_server_add_ptr(s, id, interface, protocol, flags, reverse, name);
         g_free(reverse);
         
     } else {
@@ -533,17 +532,17 @@ void flx_server_add_address(
             
         r = flx_record_new_full(name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_AAAA);
         r->data.aaaa.address = a->data.ipv6;
-        flx_server_add(s, id, interface, protocol, unique, r);
+        flx_server_add(s, id, interface, protocol, flags, r);
         flx_record_unref(r);
 
         reverse = flx_reverse_lookup_name_ipv6_arpa(&a->data.ipv6);
         g_assert(reverse);
-        flx_server_add_ptr(s, id, interface, protocol, unique, reverse, name);
+        flx_server_add_ptr(s, id, interface, protocol, flags, reverse, name);
         g_free(reverse);
     
         reverse = flx_reverse_lookup_name_ipv6_int(&a->data.ipv6);
         g_assert(reverse);
-        flx_server_add_ptr(s, id, interface, protocol, unique, reverse, name);
+        flx_server_add_ptr(s, id, interface, protocol, flags, reverse, name);
         g_free(reverse);
     }
     
@@ -555,7 +554,7 @@ void flx_server_add_text_va(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     va_list va) {
 
@@ -565,7 +564,7 @@ void flx_server_add_text_va(
     
     r = flx_record_new_full(name ? name : s->hostname, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT);
     r->data.txt.string_list = flx_string_list_new_va(va);
-    flx_server_add(s, id, interface, protocol, unique, r);
+    flx_server_add(s, id, interface, protocol, flags, r);
     flx_record_unref(r);
 }
 
@@ -574,7 +573,7 @@ void flx_server_add_text(
     gint id,
     gint interface,
     guchar protocol,
-    gboolean unique,
+    flxServerEntryFlags flags,
     const gchar *name,
     ...) {
 
@@ -583,7 +582,7 @@ void flx_server_add_text(
     g_assert(s);
 
     va_start(va, name);
-    flx_server_add_text_va(s, id, interface, protocol, unique, name, va);
+    flx_server_add_text_va(s, id, interface, protocol, flags, name, va);
     va_end(va);
 }
 
@@ -699,19 +698,29 @@ void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey
     flx_interface_monitor_walk(s->monitor, interface, protocol, post_query_callback, key);
 }
 
+struct tmpdata {
+    flxRecord *record;
+    gboolean flush_cache;
+};
+
 static void post_response_callback(flxInterfaceMonitor *m, flxInterface *i, gpointer userdata) {
-    flxRecord *r = userdata;
+    struct tmpdata *tmpdata = userdata;
 
     g_assert(m);
     g_assert(i);
-    g_assert(r);
+    g_assert(tmpdata);
 
-    flx_interface_post_response(i, NULL, r, FALSE);
+    flx_interface_post_response(i, NULL, tmpdata->record, tmpdata->flush_cache, FALSE);
 }
 
-void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record) {
+void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record, gboolean flush_cache) {
+    struct tmpdata tmpdata;
+    
     g_assert(s);
     g_assert(record);
 
-    flx_interface_monitor_walk(s->monitor, interface, protocol, post_response_callback, record);
+    tmpdata.record = record;
+    tmpdata.flush_cache = flush_cache;
+
+    flx_interface_monitor_walk(s->monitor, interface, protocol, post_response_callback, &tmpdata);
 }
index d050bcc1574682171244de69484dd712019eaf89..f90bfe77aaa11e009ca7b63f2e884417502cb74b 100644 (file)
--- a/server.h
+++ b/server.h
@@ -17,7 +17,7 @@ struct _flxServerEntry {
     gint interface;
     guchar protocol;
 
-    gboolean unique;
+    flxServerEntryFlags flags;
 
     FLX_LLIST_FIELDS(flxServerEntry, entry);
     FLX_LLIST_FIELDS(flxServerEntry, by_key);