some more inomcplete work
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Mar 2005 16:48:19 +0000 (16:48 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 18 Mar 2005 16:48:19 +0000 (16:48 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@12 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

address.c
address.h
cache.c
cache.h
dns.c
dns.h
iface.c
iface.h
rr.h
server.c
server.h

index a6a7a52..b46e043 100644 (file)
--- a/address.c
+++ b/address.c
@@ -97,3 +97,19 @@ flxAddress *flx_address_parse(const char *s, guchar family, flxAddress *ret_addr
     
     return ret_addr;
 }
+
+flxAddress *flx_address_from_sockaddr(const struct sockaddr* sa, flxAddress *ret_addr) {
+    g_assert(sa);
+    g_assert(ret_addr);
+
+    g_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
+
+    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));
+    else
+        memcpy(&ret_addr->ipv6, &((struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->ipv6));
+
+    return ret_addr;
+}
index 193a2d1..7005175 100644 (file)
--- a/address.h
+++ b/address.h
@@ -3,6 +3,8 @@
 
 #include <glib.h>
 
+#include <sys/socket.h>
+
 typedef struct {
     guint32 address;
 } flxIPv4Address;
@@ -28,6 +30,8 @@ gchar *flx_address_snprint(char *ret_s, guint length, const flxAddress *a);
 
 flxAddress *flx_address_parse(const char *s, guchar family, flxAddress *ret_addr);
 
+flxAddress *flx_address_from_sockaddr(const struct sockaddr* sa, flxAddress *ret_addr);
+
 gchar* flx_reverse_lookup_name_ipv4(const flxIPv4Address *a);
 gchar* flx_reverse_lookup_name_ipv6_arpa(const flxIPv6Address *a);
 gchar* flx_reverse_lookup_name_ipv6_int(const flxIPv6Address *a);
diff --git a/cache.c b/cache.c
index 6a0a874..9180570 100644 (file)
--- a/cache.c
+++ b/cache.c
@@ -147,3 +147,26 @@ void flx_cache_drop_record(flxCache *c, flxRecord *r) {
     if ((e = flx_cache_lookup_record(c, r))) 
         remove_entry(c, e, TRUE);
 }
+
+static void func(gpointer key, gpointer data, gpointer userdata) {
+    flxCacheEntry *e = data;
+    flxKey *k = key;
+
+    gchar *s, *t;
+
+    s = flx_key_to_string(k);
+    t = flx_record_to_string(e->record);
+
+    fprintf((FILE*) userdata, "%s %s\n", s, t);
+    
+    g_free(s);
+    g_free(t);
+}
+
+void flx_cache_dump(flxCache *c, FILE *f) {
+    g_assert(c);
+    g_assert(f);
+
+    fprintf(f, ";;; CACHE DUMP FOLLOWS ;;;\n");
+    g_hash_table_foreach(c->hash_table, func, f);
+}
diff --git a/cache.h b/cache.h
index ec0e974..7f7d0bd 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -37,6 +37,7 @@ struct flxCacheEntry {
 
 struct _flxCache {
     flxServer *server;
+    
     flxInterface *interface;
     
     GHashTable *hash_table;
@@ -53,4 +54,6 @@ flxCacheEntry *flx_cache_update(flxCache *c, flxRecord *r, gboolean unique, cons
 void flx_cache_drop_key(flxCache *c, flxKey *k);
 void flx_cache_drop_record(flxCache *c,  flxRecord *r);
 
+void flx_cache_dump(flxCache *c, FILE *f);
+
 #endif
diff --git a/dns.c b/dns.c
index 1ac7e6a..5c2180d 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -123,22 +123,10 @@ gint flx_dns_packet_check_valid(flxDnsPacket *p) {
     return 0;
 }
 
-gint flx_dns_packet_check_valid_response(flxDnsPacket *p) {
-    guint16 flags;
+gint flx_dns_packet_is_query(flxDnsPacket *p) {
     g_assert(p);
     
-    if (flx_dns_packet_check_valid(p) < 0)
-        return -1;
-
-    flags = flx_dns_packet_get_field(p, DNS_FIELD_FLAGS);
-
-    if (!(flags & DNS_FLAG_QR))
-        return -1;
-
-    if (flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT) > 0)
-        return -1;
-
-    return 0;
+    return !(flx_dns_packet_get_field(p, DNS_FIELD_FLAGS) & DNS_FLAG_QR);
 }
 
 static gint consume_labels(flxDnsPacket *p, guint index, gchar *ret_name, guint l) {
@@ -258,6 +246,15 @@ gint flx_dns_packet_consume_bytes(flxDnsPacket *p, gpointer ret_data, guint l) {
     return 0;
 }
 
+gconstpointer flx_dns_packet_get_rptr(flxDnsPacket *p) {
+    g_assert(p);
+    
+    if (p->rindex >= p->size)
+        return NULL;
+
+    return p->data + p->rindex;
+}
+
 gint flx_dns_packet_skip(flxDnsPacket *p, guint length) {
     g_assert(p);
 
@@ -267,3 +264,63 @@ gint flx_dns_packet_skip(flxDnsPacket *p, guint length) {
     p->rindex += length;
     return 0;
 }
+
+flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_flush) {
+    gchar name[256];
+    guint16 type, class;
+    guint32 ttl;
+    guint16 rdlength;
+    gconstpointer data;
+
+    g_assert(p);
+    g_assert(ret_cache_flush);
+
+    if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
+        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)
+        return NULL;
+
+    *ret_cache_flush = !!(class & MDNS_CACHE_FLUSH);
+    class &= ~ MDNS_CACHE_FLUSH;
+
+    return flx_record_new_full(name, class, type, data, rdlength, ttl);
+}
+
+flxKey* flx_dns_packet_consume_key(flxDnsPacket *p) {
+    gchar name[256];
+    guint16 type, class;
+
+    g_assert(p);
+
+    if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
+        flx_dns_packet_consume_uint16(p, &type) < 0 ||
+        flx_dns_packet_consume_uint16(p, &class) < 0)
+        return NULL;
+
+    class &= ~ MDNS_CACHE_FLUSH;
+
+    return flx_key_new(name, class, type);
+}
+
+guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k) {
+    guint8 *t;
+    
+    g_assert(p);
+    g_assert(k);
+
+    if (!(t = flx_dns_packet_append_name(p, k->name)) ||
+        !flx_dns_packet_append_uint16(p, k->type) ||
+        !flx_dns_packet_append_uint16(p, k->class))
+        return NULL;
+
+    return t;
+}
+
+guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cache_flush) {
+
+    
+}
diff --git a/dns.h b/dns.h
index 5815a9a..a737536 100644 (file)
--- a/dns.h
+++ b/dns.h
@@ -3,6 +3,8 @@
 
 #include <glib.h>
 
+#include "rr.h"
+
 #define FLX_DNS_MAX_PACKET_SIZE 9000
 
 typedef struct _flxDnsPacket {
@@ -19,13 +21,22 @@ guint8 *flx_dns_packet_append_uint16(flxDnsPacket *p, guint16 v);
 guint8 *flx_dns_packet_append_name(flxDnsPacket *p, const gchar *name);
 guint8 *flx_dns_packet_append_name_compressed(flxDnsPacket *p, const gchar *name, guint8 *prev);
 guint8 *flx_dns_packet_extend(flxDnsPacket *p, guint l);
-gint flx_dns_packet_check_valid_response(flxDnsPacket *p);
+gint flx_dns_packet_is_query(flxDnsPacket *p);
 gint flx_dns_packet_check_valid(flxDnsPacket *p);
 
 gint flx_dns_packet_consume_name(flxDnsPacket *p, gchar *ret_name, guint l);
 gint flx_dns_packet_consume_uint16(flxDnsPacket *p, guint16 *ret_v);
 gint flx_dns_packet_consume_uint32(flxDnsPacket *p, guint32 *ret_v);
 gint flx_dns_packet_consume_bytes(flxDnsPacket *p, gpointer ret_data, guint l);
+
+gconstpointer flx_dns_packet_get_rptr(flxDnsPacket *p);
+
+flxKey* flx_dns_packet_consume_key(flxDnsPacket *p);
+flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_flush);
+
+guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k);
+guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cache_flush);
+
 gint flx_dns_packet_skip(flxDnsPacket *p, guint length);
 
 #define DNS_FIELD_ID 0
@@ -51,5 +62,7 @@ gint flx_dns_packet_skip(flxDnsPacket *p, guint length);
          ((guint16) (rd & 15)))
          
 
+#define MDNS_CACHE_FLUSH 0x8000
+
 #endif
 
diff --git a/iface.c b/iface.c
index d3f4719..8c31d8f 100644 (file)
--- a/iface.c
+++ b/iface.c
@@ -370,3 +370,40 @@ void flx_interface_send_query(flxInterface *i, guchar protocol, flxKey *k) {
     
     flx_dns_packet_free(p);
 }
+
+void flx_interface_send_response(flxinterface *i, guchar protocol, flxRecord *rr) {
+    flxDnsPacket+p;
+    
+    g_assert(i);
+    g_assert(rr);
+
+    p = flx_dns_packet_new();
+    flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, DNS_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+    flx_dns_packet_append_name(p, rr->key->name);
+    flx_dns_packet_append_uint16(p, rr->key->type);
+    flx_dns_packet_append_uint16(p, rr->key->class);
+    flx_dns_packet_append_uint16
+}
+
+
+
+void flx_dump_caches(flxServer *s, FILE *f) {
+    flxInterface *i;
+    g_assert(s);
+
+    for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->interface_next) {
+        if (!flx_interface_is_relevant(i))
+            continue;
+        
+        if (i->n_ipv4_addrs > 0) {
+            fprintf(f, ";;; INTERFACE %s; IPv4 ;;;\n", i->name);
+            flx_cache_dump(i->ipv4_cache, f);
+        }
+
+        if (i->n_ipv6_addrs > 0) {
+            fprintf(f, ";;; INTERFACE %s; IPv6 ;;;\n", i->name);
+            flx_cache_dump(i->ipv6_cache, f);
+        }
+    }
+}
diff --git a/iface.h b/iface.h
index f7547b8..207c0b2 100644 (file)
--- a/iface.h
+++ b/iface.h
@@ -65,5 +65,7 @@ int flx_interface_is_relevant(flxInterface *i);
 int flx_address_is_relevant(flxInterfaceAddress *a);
 
 void flx_interface_send_query(flxInterface *i, guchar protocol, flxKey *k);
-    
+
+void flx_dump_caches(flxServer *s, FILE *f);
+
 #endif
diff --git a/rr.h b/rr.h
index bcd684e..0e61a73 100644 (file)
--- a/rr.h
+++ b/rr.h
@@ -49,7 +49,7 @@ flxRecord *flx_record_new_full(const gchar *name, guint16 class, guint16 type, g
 flxRecord *flx_record_ref(flxRecord *r);
 void flx_record_unref(flxRecord *r);
 
-const gchar *flxdns_class_to_string(guint16 class);
+const gchar *flx_dns_class_to_string(guint16 class);
 const gchar *flx_dns_type_to_string(guint16 type);
 
 gchar *flx_key_to_string(flxKey *k); /* g_free() the result! */
index baac24c..d4dd4ac 100644 (file)
--- a/server.c
+++ b/server.c
@@ -9,15 +9,82 @@
 #include "iface.h"
 #include "socket.h"
 
+static void post_response(flxServer *s, flxRecord *r, gint iface, const flxAddress *a) {
+}
+
+static void handle_query_key(flxServer *s, flxKey *k, gint iface, const flxAddress *a) {
+    flxEntry *e;
+    
+    g_assert(s);
+    g_assert(k);
+    g_assert(a);
+
+    for (e = g_hash_table_lookup(s->rrset_by_name, k); e; e = e->next_by_name) {
+
+        if ((e->interface <= 0 || e->interface == iface) &&
+            (e->protocol == AF_UNSPEC || e->protocol == a->family))
+            post_response(s, e->record, iface, a);
+    }
+}
+
+static void handle_query(flxServer *s, flxDnsPacket *p, gint iface, const flxAddress *a) {
+    guint n;
+    
+    g_assert(s);
+    g_assert(p);
+    g_assert(a);
+
+    for (n = flx_dns_packet_get_field(p, DNS_FIELD_QDCOUNT); n > 0; n --) {
+
+        flxKey *key;
+
+        if (!(key = flx_dns_packet_consume_query(p))) {
+            g_warning("Packet too short");
+            return;
+        }
+
+        handle_query_key(s, key, iface, a);
+        flx_key_unref(key);
+    }
+}
+
+static void add_response_to_cache(flxCache *c, flxDnsPacket *p, const flxAddress *a) {
+    guint n;
+    
+    g_assert(c);
+    g_assert(p);
+    g_assert(a);
+    for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT); n > 0; n--) {
+
+        flxRecord *rr;
+        gboolean cache_flush = FALSE;
+        
+        if (!(rr = flx_dns_packet_consume_rr(p, &cache_flush))) {
+            g_warning("Packet too short");
+            return;
+        }
+
+        flx_cache_update(c, rr, cache_flush, a);
+        flx_record_unref(rr);
+    }
+}
+
 static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa, gint iface, gint ttl) {
+    flxInterface *i;
+    flxAddress a;
+    
     g_assert(s);
     g_assert(p);
     g_assert(sa);
     g_assert(iface > 0);
-    
+
+    if (!(i = flx_interface_monitor_get_interface(s->monitor, iface))) {
+        g_warning("Recieved packet from invalid interface.");
+        return;
+    }
+
     if (ttl != 255) {
-        flxInterface *i = flx_interface_monitor_get_interface(s->monitor, iface);
-        g_warning("Recieved packet with invalid TTL on interface '%s'.", i ? i->name : "unknown");
+        g_warning("Recieved packet with invalid TTL on interface '%s'.", i->name);
         return;
     }
 
@@ -34,8 +101,41 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
         }
     }
 
-    g_message("Recieved packet");
+    if (flx_dns_packet_check_valid(p) < 0) {
+        g_warning("Recieved invalid packet.");
+        return;
+    }
 
+
+    flx_address_from_sockaddr(sa, &a);
+    
+    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) {
+            g_warning("Invalid query packet.");
+            return;
+        }
+                
+        handle_query(s, p, iface, &a);    
+        g_message("Handled query");
+    } else {
+        flxCache *c;
+
+        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) {
+            g_warning("Invalid response packet.");
+            return;
+        }
+
+        c = a.family == AF_INET ? i->ipv4_cache : i->ipv6_cache;
+        add_response_to_cache(c, p, &a);
+
+        g_message("Handled responnse");
+    }
 }
 
 static gboolean work(flxServer *s) {
@@ -334,6 +434,8 @@ void flx_server_dump(flxServer *s, FILE *f) {
     g_assert(s);
     g_assert(f);
 
+    fprintf(f, ";;; ZONE DUMP FOLLOWS ;;;\n");
+
     for (e = s->entries; e; e = e->entry_next) {
         gchar *t;
 
@@ -341,6 +443,8 @@ void flx_server_dump(flxServer *s, FILE *f) {
         fprintf(f, "%s\n", t);
         g_free(t);
     }
+
+    flx_dump_caches(s, f);
 }
 
 void flx_server_add_address(
index 4566926..63f2bf6 100644 (file)
--- a/server.h
+++ b/server.h
@@ -48,6 +48,7 @@ struct _flxServer {
 
     GPollFD pollfd_ipv4, pollfd_ipv6;
     GSource *source;
+    
 };