From: Lennart Poettering Date: Fri, 18 Mar 2005 16:48:19 +0000 (+0000) Subject: some more inomcplete work X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=f0f4bb0c37eeed71934e3191cffa5afb1cfdca0d;p=catta some more inomcplete work git-svn-id: file:///home/lennart/svn/public/avahi/trunk@12 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- 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 +#include + 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 +#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; + };