#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;
}
}
}
- 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) {
g_assert(s);
g_assert(f);
+ fprintf(f, ";;; ZONE DUMP FOLLOWS ;;;\n");
+
for (e = s->entries; e; e = e->entry_next) {
gchar *t;
fprintf(f, "%s\n", t);
g_free(t);
}
+
+ flx_dump_caches(s, f);
}
void flx_server_add_address(
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;
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);
}
}