-#CC=gcc
-CFLAGS=-g -O0 -W -pipe $(shell pkg-config --cflags glib-2.0) -Wno-unused
+CC=gcc
+CFLAGS=-g -O0 -Wall -W -pipe $(shell pkg-config --cflags glib-2.0) -Wno-unused
LIBS=$(shell pkg-config --libs glib-2.0)
all: flexmdns prioq-test
-flexmdns: timeeventq.o main.o iface.o netlink.o server.o address.o util.o prioq.o cache.o rr.o dns.o socket.o psched.o
+flexmdns: timeeventq.o main.o iface.o netlink.o server.o address.o util.o prioq.o cache.o rr.o dns.o socket.o psched.o announce.o
$(CC) -o $@ $^ $(LIBS)
#test-llist: test-llist.o
--- /dev/null
+#include "announce.h"
+#include "util.h"
+
+static void remove_announcement(flxServer *s, flxAnnouncement *a) {
+ g_assert(s);
+ g_assert(a);
+
+ flx_time_event_queue_remove(s->time_event_queue, a->time_event);
+
+ FLX_LLIST_REMOVE(flxAnnouncement, by_interface, a->interface->announcements, a);
+ FLX_LLIST_REMOVE(flxAnnouncement, by_entry, a->entry->announcements, a);
+
+ g_free(a);
+}
+
+static void elapse_announce(flxTimeEvent *e, void *userdata) {
+ flxAnnouncement *a = userdata;
+ GTimeVal tv;
+ gchar *t;
+
+ g_assert(e);
+ g_assert(a);
+
+ if (a->n_announced >= 3) {
+ g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record));
+ g_free(t);
+ remove_announcement(a->server, a);
+ return;
+ }
+
+ flx_interface_post_response(a->interface, a->entry->record);
+ a->n_announced++;
+
+ g_message("Announcement #%i on interface %s.%i for entry [%s]", a->n_announced, a->interface->hardware->name, a->interface->protocol, t = flx_record_to_string(a->entry->record));
+ g_free(t);
+
+ flx_elapse_time(&tv, 1000, 100);
+ flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv);
+}
+
+static void new_announcement(flxServer *s, flxInterface *i, flxServerEntry *e) {
+ flxAnnouncement *a;
+ GTimeVal tv;
+ gchar *t;
+
+ g_assert(s);
+ g_assert(i);
+ g_assert(e);
+
+ if (!flx_interface_match(i, e->interface, e->protocol) || !flx_interface_relevant(i))
+ return;
+
+ /* We don't want duplicates */
+ for (a = e->announcements; a; a = a->by_entry_next)
+ if (a->interface == i)
+ return;
+
+ g_message("New announcement on interface %s.%i for entry [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record));
+ g_free(t);
+
+ flx_interface_post_response(i, e->record);
+
+ a = g_new(flxAnnouncement, 1);
+ a->server = s;
+ a->interface = i;
+ a->entry = e;
+ a->n_announced = 1;
+
+ FLX_LLIST_PREPEND(flxAnnouncement, by_interface, i->announcements, a);
+ FLX_LLIST_PREPEND(flxAnnouncement, by_entry, e->announcements, a);
+
+ flx_elapse_time(&tv, 1000, 100);
+ a->time_event = flx_time_event_queue_add(s->time_event_queue, &tv, elapse_announce, a);
+}
+
+void flx_announce_interface(flxServer *s, flxInterface *i) {
+ flxServerEntry *e;
+
+ g_assert(s);
+ g_assert(i);
+
+ if (!flx_interface_relevant(i))
+ return;
+
+ for (e = s->entries; e; e = e->entry_next)
+ new_announcement(s, i, e);
+}
+
+void flx_announce_entry(flxServer *s, flxServerEntry *e) {
+ g_assert(s);
+ g_assert(e);
+
+ if (e->interface > 0) {
+
+ if (e->protocol != AF_UNSPEC) {
+ flxInterface *i;
+
+ if ((i = flx_interface_monitor_get_interface(s->monitor, e->interface, e->protocol)))
+ new_announcement(s, i, e);
+ } else {
+ flxHwInterface *hw;
+
+ if ((hw = flx_interface_monitor_get_hw_interface(s->monitor, e->interface))) {
+ flxInterface *i;
+
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ new_announcement(s, i, e);
+ }
+ }
+ } else {
+ flxInterface *i;
+
+ for (i = s->monitor->interfaces; i; i = i->interface_next)
+ new_announcement(s, i, e);
+ }
+}
+
+static flxRecord *make_goodbye_record(flxRecord *r) {
+ gchar *t;
+
+ g_assert(r);
+
+ g_message("Preparing goodbye for record [%s]", t = flx_record_to_string(r));
+ g_free(t);
+
+ return flx_record_new(r->key, r->data, r->size, 0);
+}
+
+void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) {
+ g_assert(s);
+ g_assert(i);
+
+ while (i->announcements)
+ remove_announcement(s, i->announcements);
+
+ if (goodbye && flx_interface_relevant(i)) {
+ flxServerEntry *e;
+
+ for (e = s->entries; e; e = e->entry_next)
+ if (flx_interface_match(i, e->interface, e->protocol)) {
+ flxRecord *g = make_goodbye_record(e->record);
+ flx_interface_post_response(i, g);
+ flx_record_unref(g);
+ }
+ }
+}
+
+void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean goodbye) {
+ g_assert(s);
+ g_assert(e);
+
+ while (e->announcements)
+ remove_announcement(s, e->announcements);
+
+ if (goodbye) {
+ flxRecord *g = make_goodbye_record(e->record);
+ flx_server_post_response(s, e->interface, e->protocol, g);
+ flx_record_unref(g);
+ }
+}
+
+void flx_goodbye_all(flxServer *s, gboolean goodbye) {
+ flxServerEntry *e;
+
+ g_assert(s);
+
+ for (e = s->entries; e; e = e->entry_next)
+ flx_goodbye_entry(s, e, goodbye);
+}
--- /dev/null
+#ifndef fooannouncehfoo
+#define fooannouncehfoo
+
+#include <glib.h>
+
+typedef struct _flxAnnouncement flxAnnouncement;
+
+#include "llist.h"
+#include "iface.h"
+#include "server.h"
+#include "timeeventq.h"
+
+struct _flxAnnouncement {
+ flxServer *server;
+ flxInterface *interface;
+ flxServerEntry *entry;
+
+ flxTimeEvent *time_event;
+ guint n_announced;
+
+ FLX_LLIST_FIELDS(flxAnnouncement, by_interface);
+ FLX_LLIST_FIELDS(flxAnnouncement, by_entry);
+};
+
+void flx_announce_interface(flxServer *s, flxInterface *i);
+void flx_announce_entry(flxServer *s, flxServerEntry *e);
+
+void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean send);
+void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean send);
+
+void flx_goodbye_all(flxServer *s, gboolean send);
+
+#endif
g_assert(c);
g_assert(e);
+ g_message("remvoin from cache: %p %p", c, e);
+
if (remove_from_hash_table) {
flxCacheEntry *t;
t = g_hash_table_lookup(c->hash_table, e->record->key);
g_free(e);
}
-flxCache *flx_cache_new(flxServer *server, flxInterface *iface, guchar protocol) {
+flxCache *flx_cache_new(flxServer *server, flxInterface *iface) {
flxCache *c;
g_assert(server);
c = g_new(flxCache, 1);
c->server = server;
c->interface = iface;
- c->protocol = protocol;
c->hash_table = g_hash_table_new((GHashFunc) flx_key_hash, (GEqualFunc) flx_key_equal);
return c;
g_message("Requesting cache entry update at %i%%.", percent);
/* Request a cache update */
- flx_interface_post_query(e->cache->interface, e->cache->protocol, e->record->key);
+ flx_interface_post_query(e->cache->interface, e->record->key);
/* Check again later */
next_expiry(e->cache, e, percent);
static void func(gpointer key, gpointer data, gpointer userdata) {
flxCacheEntry *e = data;
flxKey *k = key;
+ gchar *t;
- 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);
+ fprintf((FILE*) userdata, "%s\n", t);
g_free(t);
}
flxServer *server;
flxInterface *interface;
- guchar protocol;
GHashTable *hash_table;
};
-flxCache *flx_cache_new(flxServer *server, flxInterface *interface, guchar protocol);
+flxCache *flx_cache_new(flxServer *server, flxInterface *interface);
void flx_cache_free(flxCache *c);
flxCacheEntry *flx_cache_lookup_key(flxCache *c, flxKey *k);
memcpy(ptr_name, r->data, r->size);
ptr_name[r->size] = 0;
- if (!flx_dns_packet_append_uint16(p, strlen(ptr_name)) ||
+ if (!flx_dns_packet_append_uint16(p, strlen(ptr_name)+1) ||
!flx_dns_packet_append_name(p, ptr_name))
return NULL;
memcpy(name, r->data+6, r->size-6);
name[r->size-6] = 0;
- if (!flx_dns_packet_append_uint16(p, strlen(name+6)) ||
+ if (!flx_dns_packet_append_uint16(p, strlen(name+6)+1+6) ||
!flx_dns_packet_append_bytes(p, r->data, 6) ||
!flx_dns_packet_append_name(p, name))
return NULL;
void flx_server_remove(flxServer *s, gint id);
-void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *k);
+void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *key);
+void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record);
const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state);
#include "netlink.h"
#include "dns.h"
#include "socket.h"
+#include "announce.h"
static void update_address_rr(flxInterfaceMonitor *m, flxInterfaceAddress *a, int remove) {
g_assert(m);
g_assert(a);
- if (!flx_address_is_relevant(a) || remove) {
+ if (!flx_interface_address_relevant(a) || remove) {
if (a->rr_id >= 0) {
flx_server_remove(m->server, a->rr_id);
a->rr_id = -1;
} else {
if (a->rr_id < 0) {
a->rr_id = flx_server_get_next_id(m->server);
- flx_server_add_address(m->server, a->rr_id, a->interface->index, AF_UNSPEC, FALSE, m->server->hostname, &a->address);
+ flx_server_add_address(m->server, a->rr_id, a->interface->hardware->index, AF_UNSPEC, FALSE, m->server->hostname, &a->address);
}
}
}
update_address_rr(m, a, remove);
}
+static void update_hw_interface_rr(flxInterfaceMonitor *m, flxHwInterface *hw, int remove) {
+ flxInterface *i;
+
+ g_assert(m);
+ g_assert(hw);
+
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ update_interface_rr(m, i, remove);
+}
+
static void free_address(flxInterfaceMonitor *m, flxInterfaceAddress *a) {
g_assert(m);
g_assert(a);
g_assert(a->interface);
- if (a->address.family == AF_INET)
- a->interface->n_ipv4_addrs --;
- else if (a->address.family == AF_INET6)
- a->interface->n_ipv6_addrs --;
-
FLX_LLIST_REMOVE(flxInterfaceAddress, address, a->interface->addresses, a);
-
flx_server_remove(m->server, a->rr_id);
g_free(a);
g_assert(m);
g_assert(i);
- if (i->ipv4_scheduler)
- flx_packet_scheduler_free(i->ipv4_scheduler);
- if (i->ipv6_scheduler)
- flx_packet_scheduler_free(i->ipv6_scheduler);
-
+ flx_goodbye_interface(m->server, i, FALSE);
+ g_assert(!i->announcements);
+
while (i->addresses)
free_address(m, i->addresses);
- if (i->ipv4_cache)
- flx_cache_free(i->ipv4_cache);
- if (i->ipv6_cache)
- flx_cache_free(i->ipv6_cache);
+ flx_packet_scheduler_free(i->scheduler);
+ flx_cache_free(i->cache);
- g_assert(i->n_ipv6_addrs == 0);
- g_assert(i->n_ipv4_addrs == 0);
-
FLX_LLIST_REMOVE(flxInterface, interface, m->interfaces, i);
- g_hash_table_remove(m->hash_table, &i->index);
-
- flx_cache_free(i->ipv4_cache);
- flx_cache_free(i->ipv6_cache);
+ FLX_LLIST_REMOVE(flxInterface, by_hardware, i->hardware->interfaces, i);
- g_free(i->name);
g_free(i);
}
+static void free_hw_interface(flxInterfaceMonitor *m, flxHwInterface *hw) {
+ g_assert(m);
+ g_assert(hw);
+
+ while (hw->interfaces)
+ free_interface(m, hw->interfaces);
+
+ FLX_LLIST_REMOVE(flxHwInterface, hardware, m->hw_interfaces, hw);
+ g_hash_table_remove(m->hash_table, &hw->index);
+
+ g_free(hw->name);
+ g_free(hw);
+}
+
static flxInterfaceAddress* get_address(flxInterfaceMonitor *m, flxInterface *i, const flxAddress *raddr) {
flxInterfaceAddress *ia;
return flx_netlink_send(nl, n, ret_seq);
}
+static void new_interface(flxInterfaceMonitor *m, flxHwInterface *hw, guchar protocol) {
+ flxInterface *i;
+
+ g_assert(m);
+ g_assert(hw);
+ g_assert(protocol != AF_UNSPEC);
+
+ i = g_new(flxInterface, 1);
+ i->monitor = m;
+ i->hardware = hw;
+ i->protocol = protocol;
+ i->relevant = FALSE;
+
+ FLX_LLIST_HEAD_INIT(flxInterfaceAddress, i->addresses);
+ FLX_LLIST_HEAD_INIT(flxAnnouncement, i->announcements);
+
+ i->cache = flx_cache_new(m->server, i);
+ i->scheduler = flx_packet_scheduler_new(m->server, i);
+
+ FLX_LLIST_PREPEND(flxInterface, by_hardware, hw->interfaces, i);
+ FLX_LLIST_PREPEND(flxInterface, interface, m->interfaces, i);
+}
+
+static void check_interface_relevant(flxInterfaceMonitor *m, flxInterface *i) {
+ gboolean b;
+ g_assert(m);
+ g_assert(i);
+
+ b = flx_interface_relevant(i);
+
+ if (b && !i->relevant) {
+ g_message("New relevant interface %s.%i", i->hardware->name, i->protocol);
+
+ flx_announce_interface(m->server, i);
+ } else if (!b && i->relevant) {
+ g_message("Interface %s.%i no longer relevant", i->hardware->name, i->protocol);
+
+ flx_goodbye_interface(m->server, i, FALSE);
+ }
+
+ i->relevant = b;
+}
+
+static void check_hw_interface_relevant(flxInterfaceMonitor *m, flxHwInterface *hw) {
+ flxInterface *i;
+
+ g_assert(m);
+ g_assert(hw);
+
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ check_interface_relevant(m, i);
+}
+
static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
flxInterfaceMonitor *m = userdata;
if (n->nlmsg_type == RTM_NEWLINK) {
struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
- flxInterface *i;
+ flxHwInterface *hw;
struct rtattr *a = NULL;
size_t l;
- int changed;
if (ifinfomsg->ifi_family != AF_UNSPEC)
return;
- if ((i = (flxInterface*) flx_interface_monitor_get_interface(m, ifinfomsg->ifi_index)))
- changed = 1;
- else {
- i = g_new(flxInterface, 1);
- i->monitor = m;
- i->name = NULL;
- i->index = ifinfomsg->ifi_index;
- i->addresses = NULL;
- i->n_ipv4_addrs = i->n_ipv6_addrs = 0;
- FLX_LLIST_PREPEND(flxInterface, interface, m->interfaces, i);
- g_hash_table_insert(m->hash_table, &i->index, i);
- i->mtu = 1500;
- i->ipv4_cache = flx_cache_new(m->server, i, AF_INET);
- i->ipv6_cache = flx_cache_new(m->server, i, AF_INET6);
- i->ipv4_scheduler = flx_packet_scheduler_new(m->server, i, AF_INET);
- i->ipv6_scheduler = flx_packet_scheduler_new(m->server, i, AF_INET6);
+ if (!(hw = g_hash_table_lookup(m->hash_table, &ifinfomsg->ifi_index))) {
+ hw = g_new(flxHwInterface, 1);
+ hw->monitor = m;
+ hw->name = NULL;
+ hw->flags = 0;
+ hw->mtu = 1500;
+ hw->index = ifinfomsg->ifi_index;
+
+ FLX_LLIST_HEAD_INIT(flxInterface, hw->interfaces);
+ FLX_LLIST_PREPEND(flxHwInterface, hardware, m->hw_interfaces, hw);
- changed = 0;
+ g_hash_table_insert(m->hash_table, &hw->index, hw);
+
+ if (m->server->fd_ipv4 >= 0)
+ new_interface(m, hw, AF_INET);
+ if (m->server->fd_ipv6 >= 0)
+ new_interface(m, hw, AF_INET6);
}
- i->flags = ifinfomsg->ifi_flags;
+ hw->flags = ifinfomsg->ifi_flags;
l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
a = IFLA_RTA(ifinfomsg);
while (RTA_OK(a, l)) {
switch(a->rta_type) {
case IFLA_IFNAME:
- g_free(i->name);
- i->name = g_strndup(RTA_DATA(a), RTA_PAYLOAD(a));
+ g_free(hw->name);
+ hw->name = g_strndup(RTA_DATA(a), RTA_PAYLOAD(a));
break;
case IFLA_MTU:
g_assert(RTA_PAYLOAD(a) == sizeof(unsigned int));
- i->mtu = *((unsigned int*) RTA_DATA(a));
+ hw->mtu = *((unsigned int*) RTA_DATA(a));
break;
default:
a = RTA_NEXT(a, l);
}
- update_interface_rr(m, i, 0);
+ update_hw_interface_rr(m, hw, FALSE);
+ check_hw_interface_relevant(m, hw);
+
} else if (n->nlmsg_type == RTM_DELLINK) {
struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
+ flxHwInterface *hw;
flxInterface *i;
if (ifinfomsg->ifi_family != AF_UNSPEC)
return;
- if (!(i = (flxInterface*) flx_interface_monitor_get_interface(m, ifinfomsg->ifi_index)))
+ if (!(hw = flx_interface_monitor_get_hw_interface(m, ifinfomsg->ifi_index)))
return;
- update_interface_rr(m, i, 1);
- free_interface(m, i);
+ update_hw_interface_rr(m, hw, TRUE);
+ free_hw_interface(m, hw);
} else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
flxInterface *i;
struct rtattr *a = NULL;
size_t l;
- int changed;
flxAddress raddr;
int raddr_valid = 0;
if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6)
return;
- if (!(i = (flxInterface*) flx_interface_monitor_get_interface(m, ifaddrmsg->ifa_index)))
+ if (!(i = (flxInterface*) flx_interface_monitor_get_interface(m, ifaddrmsg->ifa_index, ifaddrmsg->ifa_family)))
return;
raddr.family = ifaddrmsg->ifa_family;
default:
;
}
-
+
a = RTA_NEXT(a, l);
}
-
+
if (!raddr_valid)
return;
if (n->nlmsg_type == RTM_NEWADDR) {
flxInterfaceAddress *addr;
- if ((addr = get_address(m, i, &raddr)))
- changed = 1;
- else {
+ if (!(addr = get_address(m, i, &raddr))) {
addr = g_new(flxInterfaceAddress, 1);
+ addr->monitor = m;
addr->address = raddr;
addr->interface = i;
-
- if (raddr.family == AF_INET)
- i->n_ipv4_addrs++;
- else if (raddr.family == AF_INET6)
- i->n_ipv6_addrs++;
-
addr->rr_id = -1;
FLX_LLIST_PREPEND(flxInterfaceAddress, address, i->addresses, addr);
-
- changed = 0;
}
addr->flags = ifaddrmsg->ifa_flags;
addr->scope = ifaddrmsg->ifa_scope;
- update_address_rr(m, addr, 0);
+ update_address_rr(m, addr, FALSE);
+ check_interface_relevant(m, i);
} else {
flxInterfaceAddress *addr;
if (!(addr = get_address(m, i, &raddr)))
return;
- update_address_rr(m, addr, 1);
+ update_address_rr(m, addr, TRUE);
free_address(m, addr);
+
+ check_interface_relevant(m, i);
}
} else if (n->nlmsg_type == NLMSG_DONE) {
-
+
if (m->list == LIST_IFACE) {
m->list = LIST_DONE;
- if (netlink_list_items(m->netlink, RTM_GETADDR, &m->query_addr_seq) < 0) {
+ if (netlink_list_items(m->netlink, RTM_GETADDR, &m->query_addr_seq) < 0)
g_warning("NETLINK: Failed to list addrs: %s", strerror(errno));
- } else
+ else
m->list = LIST_ADDR;
} else
m->list = LIST_DONE;
goto fail;
m->hash_table = g_hash_table_new(g_int_hash, g_int_equal);
- m->interfaces = NULL;
+
+ FLX_LLIST_HEAD_INIT(flxInterface, m->interfaces);
+ FLX_LLIST_HEAD_INIT(flxHwInterface, m->hw_interfaces);
if (netlink_list_items(m->netlink, RTM_GETLINK, &m->query_link_seq) < 0)
goto fail;
if (m->netlink)
flx_netlink_free(m->netlink);
+ while (m->hw_interfaces)
+ free_hw_interface(m, m->hw_interfaces);
+
+ g_assert(!m->interfaces);
+
if (m->hash_table)
g_hash_table_destroy(m->hash_table);
}
-flxInterface* flx_interface_monitor_get_interface(flxInterfaceMonitor *m, gint index) {
+flxInterface* flx_interface_monitor_get_interface(flxInterfaceMonitor *m, gint index, guchar protocol) {
+ flxHwInterface *hw;
+ flxInterface *i;
+
g_assert(m);
g_assert(index > 0);
+ g_assert(protocol != AF_UNSPEC);
- return g_hash_table_lookup(m->hash_table, &index);
-}
-
-flxInterface* flx_interface_monitor_get_first(flxInterfaceMonitor *m) {
- g_assert(m);
- return m->interfaces;
-}
+ if (!(hw = flx_interface_monitor_get_hw_interface(m, index)))
+ return NULL;
-int flx_interface_is_relevant(flxInterface *i) {
- g_assert(i);
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ if (i->protocol == protocol)
+ return i;
- return
- (i->flags & IFF_UP) &&
- (i->flags & IFF_RUNNING) &&
- !(i->flags & IFF_LOOPBACK);
+ return NULL;
}
-int flx_address_is_relevant(flxInterfaceAddress *a) {
- g_assert(a);
+flxHwInterface* flx_interface_monitor_get_hw_interface(flxInterfaceMonitor *m, gint index) {
+ g_assert(m);
+ g_assert(index > 0);
- return
- a->scope == RT_SCOPE_UNIVERSE &&
- flx_interface_is_relevant(a->interface);
+ return g_hash_table_lookup(m->hash_table, &index);
}
-void flx_interface_send_packet(flxInterface *i, guchar protocol, flxDnsPacket *p) {
+
+void flx_interface_send_packet(flxInterface *i, flxDnsPacket *p) {
g_assert(i);
g_assert(p);
- if (!flx_interface_is_relevant(i))
- return;
-
- if ((protocol == AF_INET || protocol == AF_UNSPEC) && i->n_ipv4_addrs > 0) {
- g_message("sending on '%s':IPv4", i->name);
- flx_send_dns_packet_ipv4(i->monitor->server->fd_ipv4, i->index, p);
- }
+ if (i->relevant) {
+ g_message("sending on '%s.%i'", i->hardware->name, i->protocol);
- if ((protocol == AF_INET6 || protocol == AF_UNSPEC) && i->n_ipv6_addrs > 0) {
- g_message("sending on '%s':IPv6", i->name);
- flx_send_dns_packet_ipv6(i->monitor->server->fd_ipv6, i->index, p);
+ if (i->protocol == AF_INET && i->monitor->server->fd_ipv4 >= 0)
+ flx_send_dns_packet_ipv4(i->monitor->server->fd_ipv4, i->hardware->index, p);
+ else if (i->protocol == AF_INET6 && i->monitor->server->fd_ipv6 >= 0)
+ flx_send_dns_packet_ipv6(i->monitor->server->fd_ipv6, i->hardware->index, p);
}
}
-void flx_interface_post_query(flxInterface *i, guchar protocol, flxKey *k) {
+void flx_interface_post_query(flxInterface *i, flxKey *key) {
g_assert(i);
- g_assert(k);
+ g_assert(key);
- if (!flx_interface_is_relevant(i))
- return;
+ if (i->relevant)
+ flx_packet_scheduler_post_query(i->scheduler, key);
+}
- if ((protocol == AF_INET || protocol == AF_UNSPEC) && i->n_ipv4_addrs > 0)
- flx_packet_scheduler_post_query(i->ipv4_scheduler, k);
- if ((protocol == AF_INET6 || protocol == AF_UNSPEC) && i->n_ipv6_addrs > 0)
- flx_packet_scheduler_post_query(i->ipv6_scheduler, k);
+void flx_interface_post_response(flxInterface *i, flxRecord *record) {
+ g_assert(i);
+ g_assert(record);
+
+ if (i->relevant)
+ flx_packet_scheduler_post_response(i->scheduler, record);
+}
+
+void flx_dump_caches(flxInterfaceMonitor *m, FILE *f) {
+ flxInterface *i;
+ g_assert(m);
+
+ for (i = m->interfaces; i; i = i->interface_next) {
+ if (i->relevant) {
+ fprintf(f, ";;; INTERFACE %s.%i ;;;\n", i->hardware->name, i->protocol);
+ flx_cache_dump(i->cache, f);
+ }
+ }
}
-void flx_interface_post_response(flxInterface *i, guchar protocol, flxRecord *rr) {
+gboolean flx_interface_relevant(flxInterface *i) {
g_assert(i);
- g_assert(rr);
- if (!flx_interface_is_relevant(i))
- return;
+ return
+ (i->hardware->flags & IFF_UP) &&
+ (i->hardware->flags & IFF_RUNNING) &&
+ !(i->hardware->flags & IFF_LOOPBACK) &&
+ (i->hardware->flags & IFF_MULTICAST) &&
+ i->addresses;
+}
- if ((protocol == AF_INET || protocol == AF_UNSPEC) && i->n_ipv4_addrs > 0)
- flx_packet_scheduler_post_response(i->ipv4_scheduler, rr);
+gboolean flx_interface_address_relevant(flxInterfaceAddress *a) {
+ g_assert(a);
- if ((protocol == AF_INET6 || protocol == AF_UNSPEC) && i->n_ipv6_addrs > 0)
- flx_packet_scheduler_post_response(i->ipv6_scheduler, rr);
+ return a->scope == RT_SCOPE_UNIVERSE;
}
-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);
- }
+gboolean flx_interface_match(flxInterface *i, gint index, guchar protocol) {
+ g_assert(i);
+
+ if (index > 0 && index != i->hardware->index)
+ return FALSE;
- if (i->n_ipv6_addrs > 0) {
- fprintf(f, ";;; INTERFACE %s; IPv6 ;;;\n", i->name);
- flx_cache_dump(i->ipv6_cache, f);
- }
- }
+ if (protocol != AF_UNSPEC && protocol != i->protocol)
+ return FALSE;
+
+ return TRUE;
}
+
#include <glib.h>
-struct _flxInterfaceMonitor;
typedef struct _flxInterfaceMonitor flxInterfaceMonitor;
-
-struct _flxInterfaceAddress;
typedef struct _flxInterfaceAddress flxInterfaceAddress;
-
-struct _flxInterface;
typedef struct _flxInterface flxInterface;
+typedef struct _flxHwInterface flxHwInterface;
#include "address.h"
#include "server.h"
#include "llist.h"
#include "psched.h"
#include "dns.h"
+#include "announce.h"
struct _flxInterfaceMonitor {
flxServer *server;
GHashTable *hash_table;
FLX_LLIST_HEAD(flxInterface, interfaces);
+ FLX_LLIST_HEAD(flxHwInterface, hw_interfaces);
guint query_addr_seq, query_link_seq;
- enum { LIST_IFACE, LIST_ADDR, LIST_DONE } list;
+ enum {
+ LIST_IFACE,
+ LIST_ADDR,
+ LIST_DONE
+ } list;
};
-struct _flxInterface {
+struct _flxHwInterface {
+ FLX_LLIST_FIELDS(flxHwInterface, hardware);
flxInterfaceMonitor *monitor;
+
gchar *name;
gint index;
guint flags;
+ guint mtu;
- FLX_LLIST_HEAD(flxInterfaceAddress, addresses);
- FLX_LLIST_FIELDS(flxInterface, interface);
+ FLX_LLIST_HEAD(flxInterface, interfaces);
+};
- guint n_ipv6_addrs, n_ipv4_addrs;
- flxCache *ipv4_cache, *ipv6_cache;
+struct _flxInterface {
+ FLX_LLIST_FIELDS(flxInterface, interface);
+ FLX_LLIST_FIELDS(flxInterface, by_hardware);
+ flxInterfaceMonitor *monitor;
+
+ flxHwInterface *hardware;
+ guchar protocol;
+ gboolean relevant;
- guint mtu;
+ flxCache *cache;
+ flxPacketScheduler *scheduler;
- flxPacketScheduler *ipv4_scheduler, *ipv6_scheduler;
+ FLX_LLIST_HEAD(flxInterfaceAddress, addresses);
+ FLX_LLIST_HEAD(flxAnnouncement, announcements);
};
struct _flxInterfaceAddress {
+ FLX_LLIST_FIELDS(flxInterfaceAddress, address);
+ flxInterfaceMonitor *monitor;
+
guchar flags;
guchar scope;
flxAddress address;
- flxInterface *interface;
-
- FLX_LLIST_FIELDS(flxInterfaceAddress, address);
-
gint rr_id;
+ flxInterface *interface;
};
flxInterfaceMonitor *flx_interface_monitor_new(flxServer *server);
void flx_interface_monitor_free(flxInterfaceMonitor *m);
-flxInterface* flx_interface_monitor_get_interface(flxInterfaceMonitor *m, gint index);
-flxInterface* flx_interface_monitor_get_first(flxInterfaceMonitor *m);
+flxInterface* flx_interface_monitor_get_interface(flxInterfaceMonitor *m, gint index, guchar protocol);
+flxHwInterface* flx_interface_monitor_get_hw_interface(flxInterfaceMonitor *m, gint index);
+
+void flx_interface_send_packet(flxInterface *i, flxDnsPacket *p);
-int flx_interface_is_relevant(flxInterface *i);
-int flx_address_is_relevant(flxInterfaceAddress *a);
+void flx_interface_post_query(flxInterface *i, flxKey *k);
+void flx_interface_post_response(flxInterface *i, flxRecord *rr);
-void flx_interface_send_packet(flxInterface *i, guchar protocol, flxDnsPacket *p);
+void flx_dump_caches(flxInterfaceMonitor *m, FILE *f);
-void flx_interface_post_query(flxInterface *i, guchar protocol, flxKey *k);
-void flx_interface_post_response(flxInterface *i, guchar protocol, flxRecord *rr);
+gboolean flx_interface_relevant(flxInterface *i);
+gboolean flx_interface_address_relevant(flxInterfaceAddress *a);
-void flx_dump_caches(flxServer *s, FILE *f);
+gboolean flx_interface_match(flxInterface *i, gint index, guchar protocol);
#endif
/* flx_server_post_query(flx, 0, AF_UNSPEC, k); */
/* flx_key_unref(k); */
- k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
- flx_server_post_query(flx, 0, AF_INET, k);
- flx_key_unref(k);
+/* k = flx_key_new("ecstasy.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A); */
+/* flx_server_post_query(flx, 0, AF_INET, k); */
+/* flx_key_unref(k); */
return FALSE;
}
#include "prioq.h"
-static gint compare(gconstpointer a, gconstpointer b) {
+static gint compare_int(gconstpointer a, gconstpointer b) {
gint i = GPOINTER_TO_INT(a), j = GPOINTER_TO_INT(b);
return i < j ? -1 : (i > j ? 1 : 0);
}
+static int compare_ptr(gconstpointer a, gconstpointer b) {
+ return a < b ? -1 : (a > b ? 1 : 0);
+}
+
static void rec(flxPrioQueueNode *n) {
if (!n)
return;
+ if (n->left)
+ g_assert(n->left->parent == n);
+
+ if (n->right)
+ g_assert(n->right->parent == n);
+
+ if (n->parent) {
+ g_assert(n->parent->left == n || n->parent->right == n);
+
+ if (n->parent->left == n)
+ g_assert(n->next == n->parent->right);
+ }
+
+ if (!n->next) {
+ g_assert(n->queue->last == n);
+
+ if (n->parent && n->parent->left == n)
+ g_assert(n->parent->right == NULL);
+ }
+
+
if (n->parent) {
int a = GPOINTER_TO_INT(n->parent->data), b = GPOINTER_TO_INT(n->data);
if (a > b) {
}
int main(int argc, char *argv[]) {
- flxPrioQueue *q;
+ flxPrioQueue *q, *q2;
gint i, prev;
- q = flx_prio_queue_new(compare);
+ q = flx_prio_queue_new(compare_int);
+ q2 = flx_prio_queue_new(compare_ptr);
srand(time(NULL));
- flx_prio_queue_put(q, GINT_TO_POINTER(255));
- flx_prio_queue_put(q, GINT_TO_POINTER(255));
-
- for (i = 0; i < 10000; i++)
- flx_prio_queue_put(q, GINT_TO_POINTER(random() & 0xFFFF));
+ for (i = 0; i < 10000; i++)
+ flx_prio_queue_put(q2, flx_prio_queue_put(q, GINT_TO_POINTER(random() & 0xFFFF)));
- prev = 0;
- while (q->root) {
- gint v = GPOINTER_TO_INT(q->root->data);
+ while (q2->root) {
rec(q->root);
- printf("%i\n", v);
- flx_prio_queue_remove(q, q->root);
- g_assert(v >= prev);
- prev = v;
+ rec(q2->root);
+
+ g_assert(q->n_nodes == q2->n_nodes);
+
+ printf("%i\n", GPOINTER_TO_INT(((flxPrioQueueNode*)q2->root->data)->data));
+
+ flx_prio_queue_remove(q, q2->root->data);
+ flx_prio_queue_remove(q2, q2->root);
}
+
+/* prev = 0; */
+/* while (q->root) { */
+/* gint v = GPOINTER_TO_INT(q->root->data); */
+/* rec(q->root); */
+/* printf("%i\n", v); */
+/* flx_prio_queue_remove(q, q->root); */
+/* g_assert(v >= prev); */
+/* prev = v; */
+/* } */
+
flx_prio_queue_free(q);
return 0;
}
}
static void exchange_nodes(flxPrioQueue *q, flxPrioQueueNode *a, flxPrioQueueNode *b) {
- flxPrioQueueNode *l, *r, *p, *ap, *an, *bp, *bn;
+ flxPrioQueueNode *l, *r, *p, *ap, *an, *bp, *bn, *apl, *bpl;
gint t;
g_assert(q);
g_assert(a);
}
} else {
/* Swap parents */
- p = a->parent;
+ ap = a->parent;
+ bp = b->parent;
+
+ if (ap)
+ apl = ap->left;
+ if (bp)
+ bpl = bp->left;
- if ((a->parent = b->parent)) {
- if (a->parent->left == b)
- a->parent->left = a;
- else
- a->parent->right = a;
+ if ((a->parent = bp)) {
+ if (bpl == b)
+ bp->left = a;
+ else
+ bp->right = a;
} else
q->root = a;
- if ((b->parent = p)) {
- if (b->parent->left == a)
- b->parent->left = b;
+ if ((b->parent = ap)) {
+ if (apl == a)
+ ap->left = b;
else
- b->parent->right = b;
+ ap->right = b;
} else
q->root = b;
if (q->last) {
g_assert(q->root);
g_assert(q->n_nodes);
-
+
n->y = q->last->y;
n->x = q->last->x+1;
if (n != q->last) {
flxPrioQueueNode *replacement = q->last;
exchange_nodes(q, replacement, n);
- flx_prio_queue_remove(q, q->last);
+ flx_prio_queue_remove(q, n);
flx_prio_queue_shuffle(q, replacement);
return;
}
q->last = n->prev;
- if (n->prev)
+ if (n->prev) {
n->prev->next = NULL;
- else
+ g_assert(n->parent);
+ } else
g_assert(!n->parent);
if (n->parent) {
g_assert(n->prev);
if (n->parent->left == n) {
+ if (n->parent->right != NULL) {
+ g_message("fuck");
+ for (;;);
+
+ }
+
g_assert(n->parent->right == NULL);
n->parent->left = NULL;
} else {
} else {
g_assert(q->root == n);
g_assert(!n->prev);
+ g_assert(q->n_nodes == 1);
q->root = NULL;
}
- q->n_nodes--;
-
g_free(n);
+
+ g_assert(q->n_nodes > 0);
+ q->n_nodes--;
}
+
#include "util.h"
#include "psched.h"
-flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i, guchar protocol) {
+flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i) {
flxPacketScheduler *s;
g_assert(server);
s = g_new(flxPacketScheduler, 1);
s->server = server;
s->interface = i;
- s->protocol = protocol;
FLX_LLIST_HEAD_INIT(flxQueryJob, s->query_jobs);
FLX_LLIST_HEAD_INIT(flxResponseJob, s->response_jobs);
return;
}
- p = flx_dns_packet_new_query(s->interface->mtu - 48);
+ p = flx_dns_packet_new_query(s->interface->hardware->mtu - 48);
d = packet_add_query_job(s, p, qj);
g_assert(d);
n = 1;
}
flx_dns_packet_set_field(p, DNS_FIELD_QDCOUNT, n);
- flx_interface_send_packet(s->interface, s->protocol, p);
+ flx_interface_send_packet(s->interface, p);
flx_dns_packet_free(p);
}
return;
}
- p = flx_dns_packet_new_response(s->interface->mtu - 200);
+ p = flx_dns_packet_new_response(s->interface->hardware->mtu - 200);
d = packet_add_response_job(s, p, rj);
g_assert(d);
n = 1;
}
flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
- flx_interface_send_packet(s->interface, s->protocol, p);
+ flx_interface_send_packet(s->interface, p);
flx_dns_packet_free(p);
}
flxServer *server;
flxInterface *interface;
- guchar protocol;
FLX_LLIST_HEAD(flxQueryJob, query_jobs);
FLX_LLIST_HEAD(flxResponseJob, response_jobs);
};
-flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i, guchar protocol);
+flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i);
void flx_packet_scheduler_free(flxPacketScheduler *s);
void flx_packet_scheduler_post_query(flxPacketScheduler *s, flxKey *key);
g_assert(k);
g_assert(data);
g_assert(size > 0);
- g_assert(ttl > 0);
r = g_new(flxRecord, 1);
r->ref = 1;
inet_ntop(AF_INET6, r->data, t, sizeof(t));
break;
- case FLX_DNS_TYPE_PTR:
- case FLX_DNS_TYPE_TXT: {
+ case FLX_DNS_TYPE_PTR: {
size_t l;
l = r->size;
break;
}
+ case FLX_DNS_TYPE_TXT: {
+ g_assert(((guchar*) r->data)[0] == r->size-1);
+
+ memcpy(t, r->data+1, ((guchar*) r->data)[0]);
+ t[((guchar*) r->data)[0]] = 0;
+ break;
+ }
+
case FLX_DNS_TYPE_HINFO: {
- char *s2;
-
- if ((s2 = memchr(r->data, 0, r->size))) {
- s2++;
- if (memchr(s2, 0, r->size - ((char*) s2 - (char*) r->data)))
- snprintf(t, sizeof(t), "'%s' '%s'", (char*) r->data, s2);
+ gchar *s2;
+ gchar hi1[256], hi2[256];
+ guchar len;
+
+ if ((size_t) (len = ((guchar*) r->data)[0]) + 2 <= r->size) {
+ guchar len2;
+ memcpy(hi1, (gchar*) r->data +1, len);
+ hi1[len] = 0;
+
+ if ((size_t) (len2 = ((guchar*) r->data)[len+1]) + len + 2 <= r->size) {
+ memcpy(hi2, (gchar*) r->data+len+2, len2);
+ hi2[len2] = 0;
+ snprintf(t, sizeof(t), "'%s' '%s'", hi1, hi2);
+ }
+
}
break;
ntohs(((guint16*) r->data)[1]),
ntohs(((guint16*) r->data)[2]),
k);
+ break;
}
}
p = flx_key_to_string(r->key);
- s = g_strdup_printf("%s %s ; ttl=%u", p, t, r->ttl);
+ s = g_strdup_printf("[%s %s ; ttl=%u]", p, t, r->ttl);
g_free(p);
return s;
FLX_DNS_CLASS_IN = 0x01
};
-#define FLX_DEFAULT_TTL 10 /*(120*60)*/
+#define FLX_DEFAULT_TTL (120*60)
typedef struct {
guint ref;
#include "iface.h"
#include "socket.h"
+
static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flxAddress *a) {
- flxEntry *e;
+ flxServerEntry *e;
gchar *txt;
g_assert(s);
g_message("Handling query: %s", txt = flx_key_to_string(k));
g_free(txt);
- 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);
- }
- }
+ for (e = g_hash_table_lookup(s->rrset_by_key, k); e; e = e->by_key_next)
+ if (flx_interface_match(i, e->interface, e->protocol))
+ flx_interface_post_response(i, e->record);
}
static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a) {
g_message("Handling response: %s", txt = flx_record_to_string(record));
g_free(txt);
- 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_cache_update(i->cache, record, cache_flush, a);
+ flx_packet_scheduler_drop_response(i->scheduler, record);
flx_record_unref(record);
}
}
g_message("new packet recieved.");
- if (!(i = flx_interface_monitor_get_interface(s->monitor, iface))) {
+ if (!(i = flx_interface_monitor_get_interface(s->monitor, iface, sa->sa_family))) {
g_warning("Recieved packet from invalid interface.");
return;
}
if (ttl != 255) {
- g_warning("Recieved packet with invalid TTL on interface '%s'.", i->name);
+ g_warning("Recieved packet with invalid TTL on interface '%s.%i'.", i->hardware->name, i->protocol);
return;
}
g_assert(s);
if (s->pollfd_ipv4.revents & G_IO_IN) {
- if ((p = flx_recv_dns_packet_ipv4(s->fd_ipv4, &sa, &iface, &ttl)))
+ if ((p = flx_recv_dns_packet_ipv4(s->fd_ipv4, &sa, &iface, &ttl))) {
dispatch_packet(s, p, (struct sockaddr*) &sa, iface, ttl);
+ flx_dns_packet_free(p);
+ }
}
if (s->pollfd_ipv6.revents & G_IO_IN) {
- if ((p = flx_recv_dns_packet_ipv6(s->fd_ipv6, &sa6, &iface, &ttl)))
+ if ((p = flx_recv_dns_packet_ipv6(s->fd_ipv6, &sa6, &iface, &ttl))) {
dispatch_packet(s, p, (struct sockaddr*) &sa6, iface, ttl);
+ flx_dns_packet_free(p);
+ }
}
return TRUE;
/* Fill in HINFO rr */
uname(&utsname);
- hinfo = g_strdup_printf("%s%c%s%n", g_strup(utsname.machine), 0, g_strup(utsname.sysname), &length);
+ hinfo = g_strdup_printf("%c%s%c%s%n",
+ strlen(utsname.machine), g_strup(utsname.machine),
+ strlen(utsname.sysname), g_strup(utsname.sysname),
+ &length);
flx_server_add_full(s, 0, 0, AF_UNSPEC, TRUE,
- s->hostname, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_HINFO, hinfo, length+1, FLX_DEFAULT_TTL);
+ s->hostname, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_HINFO, hinfo, length, FLX_DEFAULT_TTL);
g_free(hinfo);
s->current_id = 1;
s->rrset_by_id = g_hash_table_new(g_int_hash, g_int_equal);
- s->rrset_by_name = g_hash_table_new((GHashFunc) flx_key_hash, (GEqualFunc) flx_key_equal);
+ s->rrset_by_key = g_hash_table_new((GHashFunc) flx_key_hash, (GEqualFunc) flx_key_equal);
- FLX_LLIST_HEAD_INIT(flxEntry, s->entries);
+ FLX_LLIST_HEAD_INIT(flxServerEntry, s->entries);
s->monitor = flx_interface_monitor_new(s);
s->time_event_queue = flx_time_event_queue_new(s->context);
flx_server_remove(s, 0);
g_hash_table_destroy(s->rrset_by_id);
- g_hash_table_destroy(s->rrset_by_name);
+ g_hash_table_destroy(s->rrset_by_key);
flx_time_event_queue_free(s->time_event_queue);
gboolean unique,
flxRecord *r) {
- flxEntry *e, *t;
+ flxServerEntry *e, *t;
g_assert(s);
g_assert(r);
- e = g_new(flxEntry, 1);
+ e = g_new(flxServerEntry, 1);
e->record = flx_record_ref(r);
e->id = id;
e->interface = interface;
e->protocol = protocol;
e->unique = unique;
- FLX_LLIST_PREPEND(flxEntry, entry, s->entries, e);
+ FLX_LLIST_HEAD_INIT(flxAnnouncement, e->announcements);
+
+ FLX_LLIST_PREPEND(flxServerEntry, entry, s->entries, e);
/* Insert into hash table indexed by id */
t = g_hash_table_lookup(s->rrset_by_id, &e->id);
- FLX_LLIST_PREPEND(flxEntry, by_id, t, e);
+ FLX_LLIST_PREPEND(flxServerEntry, by_id, t, e);
g_hash_table_replace(s->rrset_by_id, &e->id, t);
/* Insert into hash table indexed by name */
- t = g_hash_table_lookup(s->rrset_by_name, e->record->key);
- FLX_LLIST_PREPEND(flxEntry, by_name, t, e);
- g_hash_table_replace(s->rrset_by_name, e->record->key, t);
+ t = g_hash_table_lookup(s->rrset_by_key, e->record->key);
+ FLX_LLIST_PREPEND(flxServerEntry, by_key, t, e);
+ g_hash_table_replace(s->rrset_by_key, e->record->key, t);
+
+ flx_announce_entry(s, e);
}
void flx_server_add_full(
}
const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state) {
- flxEntry **e = (flxEntry**) state;
+ flxServerEntry **e = (flxServerEntry**) state;
g_assert(s);
g_assert(e);
return flx_record_ref((*e)->record);
}
-static void free_entry(flxServer*s, flxEntry *e) {
- flxEntry *t;
+static void free_entry(flxServer*s, flxServerEntry *e) {
+ flxServerEntry *t;
g_assert(e);
+ flx_goodbye_entry(s, e, TRUE);
+
/* Remove from linked list */
- FLX_LLIST_REMOVE(flxEntry, entry, s->entries, e);
+ FLX_LLIST_REMOVE(flxServerEntry, entry, s->entries, e);
/* Remove from hash table indexed by id */
t = g_hash_table_lookup(s->rrset_by_id, &e->id);
- FLX_LLIST_REMOVE(flxEntry, by_id, t, e);
+ FLX_LLIST_REMOVE(flxServerEntry, by_id, t, e);
if (t)
g_hash_table_replace(s->rrset_by_id, &t->id, t);
else
g_hash_table_remove(s->rrset_by_id, &e->id);
/* Remove from hash table indexed by name */
- t = g_hash_table_lookup(s->rrset_by_name, e->record->key);
- FLX_LLIST_REMOVE(flxEntry, by_name, t, e);
+ t = g_hash_table_lookup(s->rrset_by_key, e->record->key);
+ FLX_LLIST_REMOVE(flxServerEntry, by_key, t, e);
if (t)
- g_hash_table_replace(s->rrset_by_name, t->record->key, t);
+ g_hash_table_replace(s->rrset_by_key, t->record->key, t);
else
- g_hash_table_remove(s->rrset_by_name, e->record->key);
+ g_hash_table_remove(s->rrset_by_key, e->record->key);
flx_record_unref(e->record);
g_free(e);
while (s->entries)
free_entry(s, s->entries);
} else {
- flxEntry *e;
+ flxServerEntry *e;
while ((e = g_hash_table_lookup(s->rrset_by_id, &id)))
free_entry(s, e);
}
void flx_server_dump(flxServer *s, FILE *f) {
- flxEntry *e;
+ flxServerEntry *e;
g_assert(s);
g_assert(f);
- fprintf(f, ";;; ZONE DUMP FOLLOWS ;;;\n");
+ fprintf(f, "\n;;; ZONE DUMP FOLLOWS ;;;\n");
for (e = s->entries; e; e = e->entry_next) {
gchar *t;
g_free(t);
}
- flx_dump_caches(s, f);
+ flx_dump_caches(s->monitor, f);
}
void flx_server_add_address(
const gchar *name,
const gchar *text) {
+ gchar buf[256];
+ guint l;
+
g_assert(s);
g_assert(text);
- flx_server_add_full(s, id, interface, protocol, unique, name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT, text, strlen(text), FLX_DEFAULT_TTL);
+ if ((l = strlen(text)) > 255)
+ buf[0] = 255;
+ else
+ buf[0] = (gchar) l;
+
+ memcpy(buf+1, text, l);
+
+ flx_server_add_full(s, id, interface, protocol, unique, name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_TXT, buf, l+1, FLX_DEFAULT_TTL);
}
-void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *k) {
+void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *key) {
g_assert(s);
- g_assert(k);
-
- if (interface <= 0) {
+ g_assert(key);
+
+ if (interface > 0) {
+ if (protocol != AF_UNSPEC) {
+ flxInterface *i;
+
+ if ((i = flx_interface_monitor_get_interface(s->monitor, interface, protocol)))
+ flx_interface_post_query(i, key);
+ } else {
+ flxHwInterface *hw;
+ flxInterface *i;
+
+ if ((hw = flx_interface_monitor_get_hw_interface(s->monitor, interface)))
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ if (flx_interface_match(i, interface, protocol))
+ flx_interface_post_query(i, key);
+ }
+
+ } else {
flxInterface *i;
+
+ for (i = s->monitor->interfaces; i; i = i->interface_next)
+ if (flx_interface_match(i, interface, protocol))
+ flx_interface_post_query(i, key);
+ }
+}
- for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->interface_next)
- flx_interface_post_query(i, protocol, k);
+void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record) {
+ g_assert(s);
+ g_assert(record);
+
+ if (interface > 0) {
+ if (protocol != AF_UNSPEC) {
+ flxInterface *i;
+
+ if ((i = flx_interface_monitor_get_interface(s->monitor, interface, protocol)))
+ flx_interface_post_response(i, record);
+ } else {
+ flxHwInterface *hw;
+ flxInterface *i;
+
+ if ((hw = flx_interface_monitor_get_hw_interface(s->monitor, interface)))
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ if (flx_interface_match(i, interface, protocol))
+ flx_interface_post_response(i, record);
+ }
} else {
flxInterface *i;
-
- if (!(i = flx_interface_monitor_get_interface(s->monitor, interface)))
- return;
-
- flx_interface_post_query(i, protocol, k);
+
+ for (i = s->monitor->interfaces; i; i = i->interface_next)
+ if (flx_interface_match(i, interface, protocol))
+ flx_interface_post_response(i, record);
}
}
#ifndef fooflxserverhfoo
#define fooflxserverhfoo
-typedef struct _flxEntry flxEntry;
+typedef struct _flxServerEntry flxServerEntry;
#include "flx.h"
#include "iface.h"
#include "prioq.h"
#include "llist.h"
#include "timeeventq.h"
+#include "announce.h"
-struct _flxEntry {
+struct _flxServerEntry {
flxRecord *record;
gint id;
gint interface;
gboolean unique;
- FLX_LLIST_FIELDS(flxEntry, entry);
- FLX_LLIST_FIELDS(flxEntry, by_name);
- FLX_LLIST_FIELDS(flxEntry, by_id);
+ FLX_LLIST_FIELDS(flxServerEntry, entry);
+ FLX_LLIST_FIELDS(flxServerEntry, by_key);
+ FLX_LLIST_FIELDS(flxServerEntry, by_id);
+
+ FLX_LLIST_HEAD(flxAnnouncement, announcements);
};
struct _flxServer {
gint current_id;
GHashTable *rrset_by_id;
- GHashTable *rrset_by_name;
+ GHashTable *rrset_by_key;
- FLX_LLIST_HEAD(flxEntry, entries);
+ FLX_LLIST_HEAD(flxServerEntry, entries);
flxTimeEventQueue *time_event_queue;
};
+gboolean flx_server_entry_match_interface(flxServerEntry *e, flxInterface *i);
#endif