]> git.meshlink.io Git - catta/commitdiff
* add announcing/goodbye
authorLennart Poettering <lennart@poettering.net>
Fri, 25 Mar 2005 21:52:55 +0000 (21:52 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 25 Mar 2005 21:52:55 +0000 (21:52 +0000)
* add cache maintaince
* fix a bug in prioq.c

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@16 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

18 files changed:
Makefile
announce.c [new file with mode: 0644]
announce.h [new file with mode: 0644]
cache.c
cache.h
dns.c
flx.h
iface.c
iface.h
main.c
prioq-test.c
prioq.c
psched.c
psched.h
rr.c
rr.h
server.c
server.h

index c9ad682a1931a7429cfe4400ef778865d6b4a506..2731696676c035d32d8e150f413cd1557b859828 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
-#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
diff --git a/announce.c b/announce.c
new file mode 100644 (file)
index 0000000..db983d4
--- /dev/null
@@ -0,0 +1,169 @@
+#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);
+}
diff --git a/announce.h b/announce.h
new file mode 100644 (file)
index 0000000..0e65eae
--- /dev/null
@@ -0,0 +1,33 @@
+#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
diff --git a/cache.c b/cache.c
index 9025d1d76e7924a19cd18d60eec757495982319d..b668d3338730612f646951ac90a9c44f676764bb 100644 (file)
--- a/cache.c
+++ b/cache.c
@@ -6,6 +6,8 @@ static void remove_entry(flxCache *c, flxCacheEntry *e, gboolean remove_from_has
     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);
@@ -24,14 +26,13 @@ static void remove_entry(flxCache *c, flxCacheEntry *e, gboolean remove_from_has
     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;
@@ -119,7 +120,7 @@ static void elapse_func(flxTimeEvent *t, void *userdata) {
         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);
@@ -232,15 +233,10 @@ void flx_cache_drop_record(flxCache *c, flxRecord *r) {
 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);
 }
 
diff --git a/cache.h b/cache.h
index 263d9a1039661ad516d59bf326db73f0ec319b92..f51e18e6069eeda0fe3f7bf95e3d4bafc2ffa185 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -40,12 +40,11 @@ struct _flxCache {
     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);
diff --git a/dns.c b/dns.c
index a33f1ab12303073c71236c2abe10f8c9ec476469..726eb211857cca8948659677e04927de73e96084 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -438,7 +438,7 @@ guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cac
             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;
 
@@ -452,7 +452,7 @@ guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cac
             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;
diff --git a/flx.h b/flx.h
index ea616472f4e7a3d29f9b1deae184a8b76deb2eb9..1debd89e069522baec73722a103cd17ae675e5ab 100644 (file)
--- a/flx.h
+++ b/flx.h
@@ -56,7 +56,8 @@ void flx_server_add_text(
 
 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);
 
diff --git a/iface.c b/iface.c
index 54638950290cbbbf0b823971a50aafbc15793701..5e6c94a095218f29a4f59067f807ff1a93a9257f 100644 (file)
--- a/iface.c
+++ b/iface.c
 #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;
@@ -23,7 +24,7 @@ static void update_address_rr(flxInterfaceMonitor *m, flxInterfaceAddress *a, in
     } 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);
         }
     }
 }
@@ -37,18 +38,22 @@ static void update_interface_rr(flxInterfaceMonitor *m, flxInterface *i, int rem
         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);
@@ -58,32 +63,35 @@ static void free_interface(flxInterfaceMonitor *m, flxInterface *i) {
     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;
     
@@ -117,6 +125,59 @@ static int netlink_list_items(flxNetlink *nl, guint16 type, guint *ret_seq) {
     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;
     
@@ -126,35 +187,33 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer 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);
@@ -162,13 +221,13 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
         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:
@@ -178,19 +237,22 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
             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) {
 
@@ -198,14 +260,13 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
         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;
@@ -228,58 +289,52 @@ static void callback(flxNetlink *nl, struct nlmsghdr *n, gpointer userdata) {
                 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;
@@ -301,7 +356,9 @@ flxInterfaceMonitor *flx_interface_monitor_new(flxServer *s) {
         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;
@@ -321,6 +378,11 @@ void flx_interface_monitor_free(flxInterfaceMonitor *m) {
     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);
 
@@ -328,97 +390,102 @@ void flx_interface_monitor_free(flxInterfaceMonitor *m) {
 }
 
 
-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;
 }
+
diff --git a/iface.h b/iface.h
index 50cc98f09c25bf64c1e1b8d8cc15ee5ffe9d2a5e..85e535ca13be8a504b59fbbbf4eaee19f280e58f 100644 (file)
--- a/iface.h
+++ b/iface.h
@@ -3,14 +3,10 @@
 
 #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"
@@ -19,6 +15,7 @@ typedef struct _flxInterface flxInterface;
 #include "llist.h"
 #include "psched.h"
 #include "dns.h"
+#include "announce.h"
 
 struct _flxInterfaceMonitor {
     flxServer *server;
@@ -26,55 +23,73 @@ struct _flxInterfaceMonitor {
     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
diff --git a/main.c b/main.c
index 92f349117025d13b5bb79f22a084592a305fc04a..47f3cd76226df63b233a510a85e67d9b685e4f2a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -18,9 +18,9 @@ static gboolean send_timeout(gpointer data) {
 /*     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;
 }
index a54c1ff5a5ca6a6b8a7939fdd3609cc0bff75349..d8640c16f4a751791255db5dd4f89fd40e713e56 100644 (file)
@@ -4,16 +4,41 @@
 
 #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) {
@@ -27,29 +52,40 @@ static void rec(flxPrioQueueNode *n) {
 }
 
 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;
 }
diff --git a/prioq.c b/prioq.c
index 09d781f92389002916a688455e5d7bc385f9ed17..9e49b81f3f41ff3a4f1d98d15edb0bfe127e8e75 100644 (file)
--- a/prioq.c
+++ b/prioq.c
@@ -45,7 +45,7 @@ static flxPrioQueueNode* get_node_at_xy(flxPrioQueue *q, guint x, guint y) {
 }
 
 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);
@@ -129,21 +129,27 @@ static void exchange_nodes(flxPrioQueue *q, flxPrioQueueNode *a, flxPrioQueueNod
         }
     } 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;
 
@@ -258,7 +264,7 @@ flxPrioQueueNode* flx_prio_queue_put(flxPrioQueue *q, gpointer data) {
     if (q->last) {
         g_assert(q->root);
         g_assert(q->n_nodes);
-        
+         
         n->y = q->last->y;
         n->x = q->last->x+1;
 
@@ -302,7 +308,7 @@ void flx_prio_queue_remove(flxPrioQueue *q, flxPrioQueueNode *n) {
     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;
     }
@@ -314,14 +320,21 @@ void flx_prio_queue_remove(flxPrioQueue *q, flxPrioQueueNode *n) {
 
     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 {
@@ -332,10 +345,13 @@ void flx_prio_queue_remove(flxPrioQueue *q, flxPrioQueueNode *n) {
     } 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--;
 }
+
index ca1e00766ded358136c8322c9cb3073e897a8c38..ebae9d38e6003697fb6f233ad9500d0f768e80a9 100644 (file)
--- a/psched.c
+++ b/psched.c
@@ -1,7 +1,7 @@
 #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);
@@ -10,7 +10,6 @@ flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i,
     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);
@@ -93,7 +92,7 @@ static void query_elapse(flxTimeEvent *e, gpointer data) {
         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;
@@ -111,7 +110,7 @@ static void query_elapse(flxTimeEvent *e, gpointer data) {
     }
 
     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);
 }
 
@@ -186,7 +185,7 @@ static void response_elapse(flxTimeEvent *e, gpointer data) {
         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;
@@ -204,7 +203,7 @@ static void response_elapse(flxTimeEvent *e, gpointer data) {
     }
 
     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);
 }
 
index 90b67dba001cbbac3521bb1a320c028a06367b70..fae5d91dce3cea45ee308ffc6755b42e7f168271 100644 (file)
--- a/psched.h
+++ b/psched.h
@@ -30,13 +30,12 @@ struct _flxPacketScheduler {
     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);
diff --git a/rr.c b/rr.c
index a6ecfbd3903b063e73538b13f28d3596a39a6bcc..c984934bfd510bcceecac8f35847d9d11a5a7c96 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -51,7 +51,6 @@ flxRecord *flx_record_new(flxKey *k, gconstpointer data, guint16 size, guint32 t
     g_assert(k);
     g_assert(data);
     g_assert(size > 0);
-    g_assert(ttl > 0);
 
     r = g_new(flxRecord, 1);
     r->ref = 1;
@@ -142,8 +141,7 @@ gchar *flx_record_to_string(flxRecord *r) {
             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;
@@ -155,13 +153,30 @@ gchar *flx_record_to_string(flxRecord *r) {
             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;
@@ -183,11 +198,12 @@ gchar *flx_record_to_string(flxRecord *r) {
                      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;
diff --git a/rr.h b/rr.h
index d37cb64ac4d61a1ced1763a9373bd905b41160e8..a31b632065ebce93336a529cc1850714ba247019 100644 (file)
--- a/rr.h
+++ b/rr.h
@@ -20,7 +20,7 @@ enum {
     FLX_DNS_CLASS_IN = 0x01
 };
 
-#define FLX_DEFAULT_TTL 10 /*(120*60)*/
+#define FLX_DEFAULT_TTL (120*60)
 
 typedef struct {
     guint ref;
index 2b354bdf63d8421782b26e1a9125a54df07a3637..0aaaed1cb98bf762961732a52427bab7f3ffc408 100644 (file)
--- a/server.c
+++ b/server.c
@@ -9,8 +9,9 @@
 #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);
@@ -21,14 +22,9 @@ static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flx
     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) {
@@ -74,8 +70,8 @@ static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, cons
         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);
     }
 }
@@ -91,13 +87,13 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa,
 
     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;
     }
 
@@ -155,13 +151,17 @@ static gboolean work(flxServer *s) {
     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;
@@ -205,10 +205,13 @@ static void add_default_entries(flxServer *s) {
     
     /* 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);
 
@@ -256,9 +259,9 @@ flxServer *flx_server_new(GMainContext *c) {
     
     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);
@@ -299,7 +302,7 @@ void flx_server_free(flxServer* s) {
     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);
 
@@ -331,28 +334,32 @@ void flx_server_add(
     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(
@@ -379,7 +386,7 @@ 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);
 
@@ -394,29 +401,31 @@ const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state) {
     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);
@@ -429,7 +438,7 @@ void flx_server_remove(flxServer *s, gint id) {
         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);
@@ -437,11 +446,11 @@ void flx_server_remove(flxServer *s, gint id) {
 }
 
 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;
@@ -451,7 +460,7 @@ void flx_server_dump(flxServer *s, FILE *f) {
         g_free(t);
     }
 
-    flx_dump_caches(s, f);
+    flx_dump_caches(s->monitor, f);
 }
 
 void flx_server_add_address(
@@ -507,28 +516,76 @@ void flx_server_add_text(
     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);
     }
 }
index fbd5715445c392891b2e146ab4f4d6c333c223c8..b7addf641b313cac15e0607696e20477453530ba 100644 (file)
--- a/server.h
+++ b/server.h
@@ -1,15 +1,16 @@
 #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;
@@ -17,9 +18,11 @@ struct _flxEntry {
 
     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 {
@@ -29,9 +32,9 @@ 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;
     
@@ -44,5 +47,6 @@ struct _flxServer {
     
 };
 
+gboolean flx_server_entry_match_interface(flxServerEntry *e, flxInterface *i);
 
 #endif