X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=server.c;h=0f292a349e84b7d302db79b4a103ee03c87c5bbe;hb=c18626ad35cdf94edbff196070ccbb6ae825abd0;hp=baac24cd1dcd1910241bafc5f0398440d72c90d7;hpb=7bb43bd370e70385a4ccde06f3f4554f488aa6b3;p=catta diff --git a/server.c b/server.c index baac24c..0f292a3 100644 --- a/server.c +++ b/server.c @@ -9,15 +9,86 @@ #include "iface.h" #include "socket.h" +static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flxAddress *a) { + flxEntry *e; + + g_assert(s); + g_assert(k); + g_assert(i); + g_assert(a); + + 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) && + (e->protocol == AF_UNSPEC || e->protocol == a->family)) { + + flx_interface_post_response(i, a->family, e->record); + } + } +} + +static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a) { + guint n; + + g_assert(s); + g_assert(p); + g_assert(i); + 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_key(p))) { + g_warning("Packet too short"); + return; + } + + handle_query_key(s, key, i, a); + flx_key_unref(key); + } +} + +static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a) { + guint n; + + g_assert(s); + g_assert(p); + g_assert(i); + g_assert(a); + + for (n = flx_dns_packet_get_field(p, DNS_FIELD_ANCOUNT); n > 0; n--) { + flxRecord *record; + gboolean cache_flush = FALSE; + + if (!(record = flx_dns_packet_consume_record(p, &cache_flush))) { + g_warning("Packet too short"); + return; + } + + 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); + } +} + 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); - + + g_message("new packet recieved."); + + 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 +105,37 @@ 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, 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 || + flx_dns_packet_get_field(p, DNS_FIELD_ARCOUNT) != 0) { + g_warning("Invalid response packet."); + return; + } + handle_response(s, p, i, &a); + g_message("Handled response"); + } } 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( @@ -410,7 +514,7 @@ void flx_server_send_query(flxServer *s, gint interface, guchar protocol, flxKey flxInterface *i; for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->interface_next) - flx_interface_send_query(i, protocol, k); + flx_interface_post_query(i, protocol, k); } else { flxInterface *i; @@ -418,6 +522,6 @@ void flx_server_send_query(flxServer *s, gint interface, guchar protocol, flxKey if (!(i = flx_interface_monitor_get_interface(s->monitor, interface))) return; - flx_interface_send_query(i, protocol, k); + flx_interface_post_query(i, protocol, k); } }