]> git.meshlink.io Git - catta/commitdiff
* add cache management
authorLennart Poettering <lennart@poettering.net>
Thu, 24 Mar 2005 21:52:46 +0000 (21:52 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 24 Mar 2005 21:52:46 +0000 (21:52 +0000)
* add support for SRV records

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@15 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

14 files changed:
Makefile
address.c
address.h
cache.c
cache.h
dns.c
flx.h
iface.c
main.c
psched.c
rr.c
rr.h
server.c
socket.c

index 306bbfee1b0cf57e0d346b17a59446e27ee65e8f..c9ad682a1931a7429cfe4400ef778865d6b4a506 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,5 @@
-CFLAGS=-g -O0 -Wall -W -pipe $(shell pkg-config --cflags glib-2.0) -Wno-unused
+#CC=gcc
+CFLAGS=-g -O0 -W -pipe $(shell pkg-config --cflags glib-2.0) -Wno-unused
 LIBS=$(shell pkg-config --libs glib-2.0)
 
 all: flexmdns prioq-test
index b46e043c22698e4301bdaeaa77312a77a722bfb7..dffd3ee4a44a29aa33c5a69fbce71465c20a6ea5 100644 (file)
--- a/address.c
+++ b/address.c
@@ -23,14 +23,14 @@ gint flx_address_cmp(const flxAddress *a, const flxAddress *b) {
     if (a->family != b->family)
         return -1;
 
-    return memcmp(a->data, b->data, flx_address_get_size(a));
+    return memcmp(a->data.data, b->data.data, flx_address_get_size(a));
 }
 
 gchar *flx_address_snprint(char *s, guint length, const flxAddress *a) {
     g_assert(s);
     g_assert(length);
     g_assert(a);
-    return (gchar*) inet_ntop(a->family, a->data, s, length);
+    return (gchar*) inet_ntop(a->family, a->data.data, s, length);
 }
 
 gchar* flx_reverse_lookup_name_ipv4(const flxIPv4Address *a) {
@@ -90,7 +90,7 @@ flxAddress *flx_address_parse(const char *s, guchar family, flxAddress *ret_addr
     g_assert(ret_addr);
     g_assert(s);
 
-    if (inet_pton(family, s, ret_addr->data) < 0)
+    if (inet_pton(family, s, ret_addr->data.data) < 0)
         return NULL;
 
     ret_addr->family = family;
@@ -107,9 +107,9 @@ flxAddress *flx_address_from_sockaddr(const struct sockaddr* sa, flxAddress *ret
     ret_addr->family = sa->sa_family;
 
     if (sa->sa_family == AF_INET)
-        memcpy(&ret_addr->ipv4, &((struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->ipv4));
+        memcpy(&ret_addr->data.ipv4, &((struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4));
     else
-        memcpy(&ret_addr->ipv6, &((struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->ipv6));
+        memcpy(&ret_addr->data.ipv6, &((struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6));
 
     return ret_addr;
 }
index 7005175f873d78e8f521c836fdb2af6ecd2be501..66b3b1f4f72f1ff8baf76bb4d9d4c6e604685fcb 100644 (file)
--- a/address.h
+++ b/address.h
@@ -20,7 +20,7 @@ typedef struct {
         flxIPv6Address ipv6;
         flxIPv4Address ipv4;
         guint8 data[0];
-    };
+    } data;
 } flxAddress;
 
 guint flx_address_get_size(const flxAddress *a);
diff --git a/cache.c b/cache.c
index 9180570b9b63eac0d3fb2c9bdd60b3733d65b951..9025d1d76e7924a19cd18d60eec757495982319d 100644 (file)
--- a/cache.c
+++ b/cache.c
@@ -8,25 +8,30 @@ static void remove_entry(flxCache *c, flxCacheEntry *e, gboolean remove_from_has
 
     if (remove_from_hash_table) {
         flxCacheEntry *t;
-        t = g_hash_table_lookup(c->hash_table, &e->record->key);
+        t = g_hash_table_lookup(c->hash_table, e->record->key);
         FLX_LLIST_REMOVE(flxCacheEntry, by_name, t, e);
         if (t)
-            g_hash_table_replace(c->hash_table, &t->record->key, t);
+            g_hash_table_replace(c->hash_table, t->record->key, t);
         else
-            g_hash_table_remove(c->hash_table, &e->record->key);
+            g_hash_table_remove(c->hash_table, e->record->key);
     }
         
     flx_record_unref(e->record);
+
+    if (e->time_event)
+        flx_time_event_queue_remove(c->server->time_event_queue, e->time_event);
+    
     g_free(e);
 }
 
-flxCache *flx_cache_new(flxServer *server, flxInterface *iface) {
+flxCache *flx_cache_new(flxServer *server, flxInterface *iface, guchar protocol) {
     flxCache *c;
     g_assert(server);
 
     c = g_new(flxCache, 1);
     c->server = server;
     c->interface = iface;
+    c->protocol = protocol;
     c->hash_table = g_hash_table_new((GHashFunc) flx_key_hash, (GEqualFunc) flx_key_equal);
 
     return c;
@@ -71,58 +76,134 @@ flxCacheEntry *flx_cache_lookup_record(flxCache *c, flxRecord *r) {
     return NULL;
 }
 
+static void next_expiry(flxCache *c, flxCacheEntry *e, guint percent);
+
+static void elapse_func(flxTimeEvent *t, void *userdata) {
+    flxCacheEntry *e = userdata;
+    
+    g_assert(t);
+    g_assert(e);
+
+    if (e->state == FLX_CACHE_FINAL) {
+        remove_entry(e->cache, e, TRUE);
+        g_message("Removing entry from cache due to expiration");
+    } else {
+        guint percent = 0;
+    
+        switch (e->state) {
+            case FLX_CACHE_VALID:
+                e->state = FLX_CACHE_EXPIRY1;
+                percent = 85;
+                break;
+                
+            case FLX_CACHE_EXPIRY1:
+                e->state = FLX_CACHE_EXPIRY2;
+                percent = 90;
+                break;
+            case FLX_CACHE_EXPIRY2:
+                e->state = FLX_CACHE_EXPIRY3;
+                percent = 95;
+                break;
+                
+            case FLX_CACHE_EXPIRY3:
+                e->state = FLX_CACHE_FINAL;
+                percent = 100;
+                break;
+
+            default:
+                ;
+        }
+
+        g_assert(percent > 0);
+
+        g_message("Requesting cache entry update at %i%%.", percent);
+
+        /* Request a cache update */
+        flx_interface_post_query(e->cache->interface, e->cache->protocol, e->record->key);
+
+        /* Check again later */
+        next_expiry(e->cache, e, percent);
+    }
+}
+
+static void next_expiry(flxCache *c, flxCacheEntry *e, guint percent) {
+    gulong usec;
+
+    g_assert(c);
+    g_assert(e);
+    g_assert(percent > 0 && percent <= 100);
+
+    e->expiry = e->timestamp;
+
+    usec = e->record->ttl * 10000;
+
+    /* 2% jitter */
+    usec = g_random_int_range(usec*percent, usec*(percent+2));
+    
+    g_time_val_add(&e->expiry, usec);
+
+    if (e->time_event)
+        flx_time_event_queue_update(c->server->time_event_queue, e->time_event, &e->expiry);
+    else
+        e->time_event = flx_time_event_queue_add(c->server->time_event_queue, &e->expiry, elapse_func, e);
+}
+
 flxCacheEntry *flx_cache_update(flxCache *c, flxRecord *r, gboolean unique, const flxAddress *a) {
     flxCacheEntry *e, *t;
+    gchar *txt;
     
     g_assert(c);
-    g_assert(r);
+    g_assert(r && r->ref >= 1);
+
+    g_message("cache update: %s", (txt = flx_record_to_string(r)));
+    g_free(txt);
 
     if ((t = e = flx_cache_lookup_key(c, r->key))) {
 
+/*         g_message("found prev cache entry"); */
+
         if (unique) {
-            flxCacheEntry *n;
             /* Drop all entries but the first which we replace */
-
             while (e->by_name_next)
                 remove_entry(c, e->by_name_next, TRUE);
 
-            g_free(e->record->data);
-            e->record->data = g_memdup(r->data, r->size);
-            e->record->size = r->size;
-            e->record->ttl = r->ttl;
-
         } else {
             /* Look for exactly the same entry */
-
-            for (; e; e = e->by_name_next) {
-                if (e->record->size == r->size &&
-                    !memcmp(e->record->data, r->data, r->size)) {
-
-                    /* We found it, so let's update the TTL */
-                    e->record->ttl = r->ttl;
+            for (; e; e = e->by_name_next)
+                if (flx_record_equal(e->record, r))
                     break;
-                }
-            }
         }
     }
+    
+    if (e) {
+
+/*         g_message("found matching cache entry"); */
+
+        /* We are the first in the linked list so let's replace the hash table key with the new one */
+        if (e->by_name_prev == NULL)
+            g_hash_table_replace(c->hash_table, r->key, e);
+        
+        /* Update the record */
+        flx_record_unref(e->record);
+        e->record = flx_record_ref(r);
 
-    if (!e) {
+        
+    } else {
         /* No entry found, therefore we create a new one */
+
+/*         g_message("couldn't find matching cache entry"); */
         
         e = g_new(flxCacheEntry, 1);
-        e->node = NULL;
-
+        e->cache = c;
+        e->time_event = NULL;
         e->record = flx_record_ref(r);
         FLX_LLIST_PREPEND(flxCacheEntry, by_name, t, e);
-        g_hash_table_replace(c->hash_table, e->record->key, e);
+        g_hash_table_replace(c->hash_table, e->record->key, t);
     } 
 
     e->origin = *a;
-    
     g_get_current_time(&e->timestamp);
-    e->expiry = e->timestamp;
-    g_time_val_add(&e->expiry, e->record->ttl * 1000000);
-
+    next_expiry(c, e, 80);
     e->state = FLX_CACHE_VALID;
 
     return e;
diff --git a/cache.h b/cache.h
index 7f7d0bdc3bcd87d1f01c993919946957bb6e79ac..263d9a1039661ad516d59bf326db73f0ec319b92 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -9,18 +9,20 @@ typedef struct _flxCache flxCache;
 #include "prioq.h"
 #include "server.h"
 #include "llist.h"
+#include "timeeventq.h"
 
 typedef enum {
     FLX_CACHE_VALID,
     FLX_CACHE_EXPIRY1,
     FLX_CACHE_EXPIRY2,
-    FLX_CACHE_EXPIRY3
-        
+    FLX_CACHE_EXPIRY3,
+    FLX_CACHE_FINAL
 } flxCacheEntryState;
 
 typedef struct flxCacheEntry flxCacheEntry;
 
 struct flxCacheEntry {
+    flxCache *cache;
     flxRecord *record;
     GTimeVal timestamp;
     GTimeVal expiry;
@@ -28,10 +30,9 @@ struct flxCacheEntry {
     flxAddress origin;
 
     flxCacheEntryState state;
+    flxTimeEvent *time_event;
 
     FLX_LLIST_FIELDS(flxCacheEntry, by_name);
-
-    flxPrioQueueNode *node;
     
 };
 
@@ -39,11 +40,12 @@ struct _flxCache {
     flxServer *server;
     
     flxInterface *interface;
+    guchar protocol;
     
     GHashTable *hash_table;
 };
 
-flxCache *flx_cache_new(flxServer *server, flxInterface *interface);
+flxCache *flx_cache_new(flxServer *server, flxInterface *interface, guchar protocol);
 void flx_cache_free(flxCache *c);
 
 flxCacheEntry *flx_cache_lookup_key(flxCache *c, flxKey *k);
diff --git a/dns.c b/dns.c
index 6824fd3ed5551f0f0ed8d7108e4a9ae85cd4d0b7..a33f1ab12303073c71236c2abe10f8c9ec476469 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -330,7 +330,7 @@ gint flx_dns_packet_skip(flxDnsPacket *p, guint length) {
 }
 
 flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_flush) {
-    gchar name[256];
+    gchar name[257], buf[257+6];
     guint16 type, class;
     guint32 ttl;
     guint16 rdlength;
@@ -343,11 +343,43 @@ flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_fl
         flx_dns_packet_consume_uint16(p, &type) < 0 ||
         flx_dns_packet_consume_uint16(p, &class) < 0 ||
         flx_dns_packet_consume_uint32(p, &ttl) < 0 ||
-        flx_dns_packet_consume_uint16(p, &rdlength) < 0 ||
-        !(data = flx_dns_packet_get_rptr(p)) ||
-        flx_dns_packet_skip(p, rdlength) < 0)
+        flx_dns_packet_consume_uint16(p, &rdlength) < 0)
         return NULL;
 
+    switch (type) {
+        case FLX_DNS_TYPE_PTR:
+        case FLX_DNS_TYPE_CNAME:
+            if (flx_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
+                return NULL;
+            
+            data = buf;
+            rdlength = strlen(buf);
+            break;
+
+        case FLX_DNS_TYPE_SRV: {
+            const guint8 *t = flx_dns_packet_get_rptr(p);
+
+            if (flx_dns_packet_skip(p, 6) < 0)
+                return NULL;
+            
+            memcpy(buf, t, 6);
+
+            if (flx_dns_packet_consume_name(p, buf+6, sizeof(buf)-6) < 0)
+                return NULL;
+
+            data = buf;
+            rdlength = 6 + strlen(buf+6);
+            break;
+        }
+            
+        default:
+            if (!(data = flx_dns_packet_get_rptr(p)) ||
+                flx_dns_packet_skip(p, rdlength) < 0)
+                return NULL;
+
+            break;
+    }
+
     *ret_cache_flush = !!(class & MDNS_CACHE_FLUSH);
     class &= ~ MDNS_CACHE_FLUSH;
 
@@ -393,10 +425,46 @@ 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_uint32(p, r->ttl) ||
-        !flx_dns_packet_append_uint16(p, r->size) ||
-        !flx_dns_packet_append_bytes(p, r->data, r->size))
+        !flx_dns_packet_append_uint32(p, r->ttl))
         return NULL;
 
+    switch (r->key->type) {
+        
+        case FLX_DNS_TYPE_PTR:
+        case FLX_DNS_TYPE_CNAME: {
+            char ptr_name[257];
+
+            g_assert((size_t) r->size+1 <= sizeof(ptr_name));
+            memcpy(ptr_name, r->data, r->size);
+            ptr_name[r->size] = 0;
+            
+            if (!flx_dns_packet_append_uint16(p, strlen(ptr_name)) ||
+                !flx_dns_packet_append_name(p, ptr_name))
+                return NULL;
+
+            break;
+        }
+
+        case FLX_DNS_TYPE_SRV: {
+            char name[257];
+
+            g_assert(r->size >= 6 && (size_t) r->size-6+1 <= sizeof(name));
+            memcpy(name, r->data+6, r->size-6);
+            name[r->size-6] = 0;
+
+            if (!flx_dns_packet_append_uint16(p, strlen(name+6)) ||
+                !flx_dns_packet_append_bytes(p, r->data, 6) ||
+                !flx_dns_packet_append_name(p, name))
+                return NULL;
+
+            break;
+        }
+
+        default:
+            if (!flx_dns_packet_append_uint16(p, r->size) ||
+                !flx_dns_packet_append_bytes(p, r->data, r->size))
+                return NULL;
+    }
+
     return t;
 }
diff --git a/flx.h b/flx.h
index 331dd2623062e597d5aac6aa0bf4bbbd130452e5..ea616472f4e7a3d29f9b1deae184a8b76deb2eb9 100644 (file)
--- a/flx.h
+++ b/flx.h
@@ -56,7 +56,7 @@ void flx_server_add_text(
 
 void flx_server_remove(flxServer *s, gint id);
 
-void flx_server_send_query(flxServer *s, gint interface, guchar protocol, flxKey *k);
+void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *k);
 
 const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state);
 
diff --git a/iface.c b/iface.c
index c4bd0ff5827cfae3523bf7471e41165809401946..54638950290cbbbf0b823971a50aafbc15793701 100644 (file)
--- a/iface.c
+++ b/iface.c
@@ -146,8 +146,8 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
             FLX_LLIST_PREPEND(flxInterface, interface, m->interfaces, i);
             g_hash_table_insert(m->hash_table, &i->index, i);
             i->mtu = 1500;
-            i->ipv4_cache = flx_cache_new(m->server, i);
-            i->ipv6_cache = flx_cache_new(m->server, i);
+            i->ipv4_cache = flx_cache_new(m->server, i, AF_INET);
+            i->ipv6_cache = flx_cache_new(m->server, i, AF_INET6);
             i->ipv4_scheduler = flx_packet_scheduler_new(m->server, i, AF_INET);
             i->ipv6_scheduler = flx_packet_scheduler_new(m->server, i, AF_INET6);
             
@@ -220,7 +220,7 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
                         (raddr.family == AF_INET && RTA_PAYLOAD(a) != 4))
                         return;
 
-                    memcpy(raddr.data, RTA_DATA(a), RTA_PAYLOAD(a));
+                    memcpy(raddr.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
                     raddr_valid = 1;
 
                     break;
diff --git a/main.c b/main.c
index 94d78ac5701a2d309bb52b95c7e1fef1aca912b6..92f349117025d13b5bb79f22a084592a305fc04a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -14,16 +14,23 @@ static gboolean send_timeout(gpointer data) {
     flxServer *flx = data;
     flxKey *k;
 
-    flx_server_dump(flx, stdout);
-
+    /*     k = flx_key_new("cocaine.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A); */
+/*     flx_server_post_query(flx, 0, AF_UNSPEC, k); */
+/*     flx_key_unref(k); */
 
-    k = flx_key_new("cocaine.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
-    flx_server_send_query(flx, 0, AF_UNSPEC, 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;
 }
 
+static gboolean dump_timeout(gpointer data) {
+    flxServer *flx = data;
+    flx_server_dump(flx, stdout);
+    return TRUE;
+}
+
 int main(int argc, char *argv[]) {
     flxServer *flx;
     gchar *r;
@@ -35,8 +42,9 @@ int main(int argc, char *argv[]) {
 
     loop = g_main_loop_new(NULL, FALSE);
     
-    /*g_timeout_add(1000*5, quit_timeout, loop);*/
+    g_timeout_add(1000*60, quit_timeout, loop);
     g_timeout_add(1000, send_timeout, flx);
+    g_timeout_add(1000*10, dump_timeout, flx);
     
     g_main_loop_run(loop);
 
index 7b740536cf18c52a4ead1eb1e53dd142aa34de89..ca1e00766ded358136c8322c9cb3073e897a8c38 100644 (file)
--- a/psched.c
+++ b/psched.c
@@ -93,7 +93,7 @@ static void query_elapse(flxTimeEvent *e, gpointer data) {
         return;
     }
 
-    p = flx_dns_packet_new_query(s->interface->mtu - 200);
+    p = flx_dns_packet_new_query(s->interface->mtu - 48);
     d = packet_add_query_job(s, p, qj);
     g_assert(d);
     n = 1;
diff --git a/rr.c b/rr.c
index 5acc09baa8dc33706e05d2e6663509ac6f190835..a6ecfbd3903b063e73538b13f28d3596a39a6bcc 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -17,6 +17,8 @@ flxKey *flx_key_new(const gchar *name, guint16 class, guint16 type) {
     k->class = class;
     k->type = type;
 
+/*     g_message("%p %% ref=1", k); */
+    
     return k;
 }
 
@@ -25,6 +27,9 @@ flxKey *flx_key_ref(flxKey *k) {
     g_assert(k->ref >= 1);
 
     k->ref++;
+
+/*     g_message("%p ++ ref=%i", k, k->ref); */
+
     return k;
 }
 
@@ -32,6 +37,8 @@ void flx_key_unref(flxKey *k) {
     g_assert(k);
     g_assert(k->ref >= 1);
 
+/*     g_message("%p -- ref=%i", k, k->ref-1); */
+    
     if ((--k->ref) <= 0) {
         g_free(k->name);
         g_free(k);
@@ -95,6 +102,8 @@ const gchar *flx_dns_class_to_string(guint16 class) {
 
 const gchar *flx_dns_type_to_string(guint16 type) {
     switch (type) {
+        case FLX_DNS_TYPE_CNAME:
+            return "CNAME";
         case FLX_DNS_TYPE_A:
             return "A";
         case FLX_DNS_TYPE_AAAA:
@@ -105,6 +114,8 @@ const gchar *flx_dns_type_to_string(guint16 type) {
             return "HINFO";
         case FLX_DNS_TYPE_TXT:
             return "TXT";
+        case FLX_DNS_TYPE_SRV:
+            return "SRV";
         default:
             return NULL;
     }
@@ -120,33 +131,63 @@ gchar *flx_key_to_string(flxKey *k) {
 
 gchar *flx_record_to_string(flxRecord *r) {
     gchar *p, *s;
-    char t[256] = "<unparsable>";
-
-    if (r->key->type == FLX_DNS_TYPE_A)
-        inet_ntop(AF_INET, r->data, t, sizeof(t));
-    else if (r->key->type == FLX_DNS_TYPE_AAAA)
-        inet_ntop(AF_INET6, r->data, t, sizeof(t));
-    else if (r->key->type == FLX_DNS_TYPE_PTR || r->key->type == FLX_DNS_TYPE_TXT) {
-        size_t l;
-        
-        l = r->size;
-        if (l > sizeof(t)-1)
-            l = sizeof(t)-1;
-        
-        memcpy(t, r->data, l);
-        t[l] = 0;
-    } else if (r->key->type == FLX_DNS_TYPE_HINFO) {
-        char *s2;
+    char t[257] = "<unparsable>";
+
+    switch (r->key->type) {
+        case FLX_DNS_TYPE_A:
+            inet_ntop(AF_INET, r->data, t, sizeof(t));
+            break;
+            
+        case FLX_DNS_TYPE_AAAA:
+            inet_ntop(AF_INET6, r->data, t, sizeof(t));
+            break;
+            
+        case FLX_DNS_TYPE_PTR:
+        case FLX_DNS_TYPE_TXT: {
+            size_t l;
         
-        if ((s2 = memchr(r->data, 0, r->size))) {
-            s2++;
-            if (memchr(s2, 0, r->size - ((char*) s2 - (char*) r->data)))
-                snprintf(t, sizeof(t), "'%s' '%s'", (char*) r->data, s2);
+            l = r->size;
+            if (l > sizeof(t)-1)
+                l = sizeof(t)-1;
+            
+            memcpy(t, r->data, l);
+            t[l] = 0;
+            break;
+        }
+
+        case FLX_DNS_TYPE_HINFO: {
+            char *s2;
+            
+            if ((s2 = memchr(r->data, 0, r->size))) {
+                s2++;
+                if (memchr(s2, 0, r->size - ((char*) s2 - (char*) r->data)))
+                    snprintf(t, sizeof(t), "'%s' '%s'", (char*) r->data, s2);
+            }
+
+            break;
+        }
+
+        case FLX_DNS_TYPE_SRV: {
+            char k[257];
+            size_t l;
+
+            l = r->size-6;
+            if (l > sizeof(k)-1)
+                l = sizeof(k)-1;
+            
+            memcpy(k, r->data+6, l);
+            k[l] = 0;
+            
+            snprintf(t, sizeof(t), "%u %u %u %s",
+                     ntohs(((guint16*) r->data)[0]),
+                     ntohs(((guint16*) r->data)[1]),
+                     ntohs(((guint16*) r->data)[2]),
+                     k);
         }
     }
 
     p = flx_key_to_string(r->key);
-    s = g_strdup_printf("%s %s", p, t);
+    s = g_strdup_printf("%s %s ; ttl=%u", p, t, r->ttl);
     g_free(p);
     
     return s;
@@ -155,6 +196,8 @@ gchar *flx_record_to_string(flxRecord *r) {
 gboolean flx_key_equal(const flxKey *a, const flxKey *b) {
     g_assert(a);
     g_assert(b);
+
+/*     g_message("equal: %p %p", a, b); */
     
     return strcmp(a->name, b->name) == 0 && a->type == b->type && a->class == b->class;
 }
diff --git a/rr.h b/rr.h
index e3d36544adff5ea544e89e88150dd52fc5222f62..d37cb64ac4d61a1ced1763a9373bd905b41160e8 100644 (file)
--- a/rr.h
+++ b/rr.h
@@ -13,13 +13,14 @@ enum {
     FLX_DNS_TYPE_MX = 0x0F,
     FLX_DNS_TYPE_TXT = 0x10,
     FLX_DNS_TYPE_AAAA = 0x1C,
+    FLX_DNS_TYPE_SRV = 0x21
 };
 
 enum {
     FLX_DNS_CLASS_IN = 0x01
 };
 
-#define FLX_DEFAULT_TTL (120*60)
+#define FLX_DEFAULT_TTL 10 /*(120*60)*/
 
 typedef struct {
     guint ref;
index 0f292a349e84b7d302db79b4a103ee03c87c5bbe..2b354bdf63d8421782b26e1a9125a54df07a3637 100644 (file)
--- a/server.c
+++ b/server.c
 
 static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flxAddress *a) {
     flxEntry *e;
+    gchar *txt;
     
     g_assert(s);
     g_assert(k);
     g_assert(i);
     g_assert(a);
 
+    g_message("Handling query: %s", txt = flx_key_to_string(k));
+    g_free(txt);
+
     for (e = g_hash_table_lookup(s->rrset_by_name, k); e; e = e->by_name_next) {
 
         if ((e->interface <= 0 || e->interface == i->index) &&
@@ -56,15 +60,20 @@ 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); n > 0; n--) {
+    for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT) +
+             flx_dns_packet_get_field(p, DNS_FIELD_ARCOUNT); n > 0; n--) {
         flxRecord *record;
         gboolean cache_flush = FALSE;
+        gchar *txt;
         
         if (!(record = flx_dns_packet_consume_record(p, &cache_flush))) {
             g_warning("Packet too short");
             return;
         }
 
+        g_message("Handling response: %s", txt = flx_record_to_string(record));
+        g_free(txt);
+
         flx_cache_update(a->family == AF_INET ? i->ipv4_cache : i->ipv6_cache, record, cache_flush, a);
         flx_packet_scheduler_drop_response(a->family == AF_INET ? i->ipv4_scheduler : i->ipv6_scheduler, record);
         flx_record_unref(record);
@@ -112,7 +121,6 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
 
     flx_address_from_sockaddr(sa, &a);
 
-    
     if (flx_dns_packet_is_query(p)) {
 
         if (flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT) == 0 ||
@@ -127,8 +135,7 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
     } 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 ||
-            flx_dns_packet_get_field(p, DNS_FIELD_ARCOUNT) != 0) {
+            flx_dns_packet_get_field(p, DNS_FIELD_NSCOUNT) != 0) {
             g_warning("Invalid response packet.");
             return;
         }
@@ -465,9 +472,9 @@ void flx_server_add_address(
     if (a->family == AF_INET) {
         gchar *r;
         
-        flx_server_add_full(s, id, interface, protocol, unique, n, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A, &a->ipv4, sizeof(a->ipv4), FLX_DEFAULT_TTL);
+        flx_server_add_full(s, id, interface, protocol, unique, n, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A, &a->data.ipv4, sizeof(a->data.ipv4), FLX_DEFAULT_TTL);
 
-        r = flx_reverse_lookup_name_ipv4(&a->ipv4);
+        r = flx_reverse_lookup_name_ipv4(&a->data.ipv4);
         g_assert(r);
         flx_server_add_full(s, id, interface, protocol, unique, r, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_PTR, n, strlen(n)+1, FLX_DEFAULT_TTL);
         g_free(r);
@@ -475,14 +482,14 @@ void flx_server_add_address(
     } else {
         gchar *r;
             
-        flx_server_add_full(s, id, interface, protocol, unique, n, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_AAAA, &a->ipv6, sizeof(a->ipv6), FLX_DEFAULT_TTL);
+        flx_server_add_full(s, id, interface, protocol, unique, n, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_AAAA, &a->data.ipv6, sizeof(a->data.ipv6), FLX_DEFAULT_TTL);
 
-        r = flx_reverse_lookup_name_ipv6_arpa(&a->ipv6);
+        r = flx_reverse_lookup_name_ipv6_arpa(&a->data.ipv6);
         g_assert(r);
         flx_server_add_full(s, id, interface, protocol, unique, r, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_PTR, n, strlen(n)+1, FLX_DEFAULT_TTL);
         g_free(r);
     
-        r = flx_reverse_lookup_name_ipv6_int(&a->ipv6);
+        r = flx_reverse_lookup_name_ipv6_int(&a->data.ipv6);
         g_assert(r);
         flx_server_add_full(s, id, interface, protocol, unique, r, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_PTR, n, strlen(n)+1, FLX_DEFAULT_TTL);
         g_free(r);
@@ -506,7 +513,7 @@ void flx_server_add_text(
     flx_server_add_full(s, id, interface, protocol, unique, name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT, text, strlen(text), FLX_DEFAULT_TTL);
 }
 
-void flx_server_send_query(flxServer *s, gint interface, guchar protocol, flxKey *k) {
+void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *k) {
     g_assert(s);
     g_assert(k);
 
index cc43f160a458e15c795ec31a225eb0091124fdc5..54433d6e026042fd54cbf3561dacc73c1913cb43 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -410,8 +410,6 @@ flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gin
     
     *ret_ttl = 0;
 
-    g_message("pre");
-    
     for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
         if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
             *ret_ttl = *(uint8_t *) CMSG_DATA(cmsg);
@@ -422,13 +420,8 @@ flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gin
             *ret_iface = ((struct in6_pktinfo*) CMSG_DATA(cmsg))->ipi6_ifindex;
             found_iface = TRUE;
         }
-
-        g_message("-- %u -- %u\n", cmsg->cmsg_level, cmsg->cmsg_type);
     }
 
-    g_message("post");
-
     g_assert(found_iface);
     g_assert(found_ttl);