summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-03-18 16:48:19 +0000
committerLennart Poettering <lennart@poettering.net>2005-03-18 16:48:19 +0000
commitf0f4bb0c37eeed71934e3191cffa5afb1cfdca0d (patch)
tree154a6321b51c1af31f8633d61dde98968263f280
parent7bb43bd370e70385a4ccde06f3f4554f488aa6b3 (diff)
some more inomcplete work
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@12 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
-rw-r--r--address.c16
-rw-r--r--address.h4
-rw-r--r--cache.c23
-rw-r--r--cache.h3
-rw-r--r--dns.c85
-rw-r--r--dns.h15
-rw-r--r--iface.c37
-rw-r--r--iface.h4
-rw-r--r--rr.h2
-rw-r--r--server.c112
-rw-r--r--server.h1
11 files changed, 281 insertions, 21 deletions
diff --git a/address.c b/address.c
index a6a7a52..b46e043 100644
--- 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;
+}
diff --git a/address.h b/address.h
index 193a2d1..7005175 100644
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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! */
diff --git a/server.c b/server.c
index baac24c..d4dd4ac 100644
--- 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(
diff --git a/server.h b/server.h
index 4566926..63f2bf6 100644
--- a/server.h
+++ b/server.h
@@ -48,6 +48,7 @@ struct _flxServer {
GPollFD pollfd_ipv4, pollfd_ipv6;
GSource *source;
+
};