summaryrefslogtreecommitdiffstats
path: root/local.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-12-23 16:08:40 +0000
committerLennart Poettering <lennart@poettering.net>2004-12-23 16:08:40 +0000
commit33ccd714ea9469b5b7d3b36bbe468ba1b0f31dfc (patch)
tree833e8c3331b1f2d9a3e16c131852bf7fe1a00998 /local.c
parent2095aa52444f9ab598475ddcf8ca1773a02f8e13 (diff)
initial commit
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@3 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'local.c')
-rw-r--r--local.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/local.c b/local.c
new file mode 100644
index 0000000..4a63274
--- /dev/null
+++ b/local.c
@@ -0,0 +1,148 @@
+#include <sys/socket.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <net/if.h>
+
+#include "flx.h"
+#include "server.h"
+#include "util.h"
+#include "iface.h"
+
+typedef struct {
+ flxServer *server;
+ flxAddress address;
+ gint id;
+} addr_info;
+
+struct _flxLocalAddrSource {
+ flxServer *server;
+ GHashTable *hash_table;
+ gint hinfo_id;
+ gchar *hostname;
+};
+
+static gboolean addr_equal(gconstpointer a, gconstpointer b) {
+ return flx_address_cmp(a, b) == 0;
+}
+
+static guint hash(gconstpointer v, guint l) {
+ const guint8 *c;
+ guint hash = 0;
+
+ for (c = v; l > 0; c++, l--)
+ hash = 31 * hash + *c;
+
+ return hash;
+}
+
+static guint addr_hash(gconstpointer v) {
+ const flxAddress *a = v;
+
+ return hash(a, sizeof(a->family) + flx_address_get_size(a));
+}
+
+static void add_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
+ addr_info *ai;
+ gchar *r;
+ g_assert(l);
+ g_assert(a);
+
+ if (!(a->interface->flags & IFF_UP) ||
+ !(a->interface->flags & IFF_RUNNING) ||
+ (a->interface->flags & IFF_LOOPBACK))
+ return;
+
+ if (a->scope != RT_SCOPE_UNIVERSE)
+ return;
+
+ ai = g_new(addr_info, 1);
+ ai->server = l->server;
+ ai->address = a->address;
+
+ ai->id = flx_server_get_next_id(l->server);
+ flx_server_add(l->server, ai->id, l->hostname,
+ ai->address.family == AF_INET ? FLX_DNS_TYPE_A : FLX_DNS_TYPE_AAAA,
+ ai->address.data, flx_address_get_size(&ai->address));
+
+ r = flx_reverse_lookup_name(&ai->address);
+ flx_server_add(l->server, ai->id, r,
+ FLX_DNS_TYPE_PTR,
+ l->hostname, strlen(l->hostname)+1);
+ g_free(r);
+
+ g_hash_table_replace(l->hash_table, &ai->address, ai);
+
+}
+
+/* Called whenever a new address becomes available, is changed or removed on the local machine */
+static void addr_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterfaceAddress *a, gpointer userdata) {
+ flxLocalAddrSource *l = userdata;
+ g_assert(m);
+ g_assert(a);
+ g_assert(l);
+
+ if (change == FLX_INTERFACE_REMOVE)
+ g_hash_table_remove(l->hash_table, &a->address);
+ else if (change == FLX_INTERFACE_NEW)
+ add_addr(l, a);
+}
+
+static void destroy(gpointer data) {
+ addr_info *ai = data;
+ flx_server_remove(ai->server, ai->id);
+ g_free(ai);
+}
+
+flxLocalAddrSource *flx_local_addr_source_new(flxServer *s) {
+ flxLocalAddrSource *l;
+ const flxInterface *i;
+ struct utsname utsname;
+ gint length;
+ gchar *e, *hn, *c;
+
+ l = g_new(flxLocalAddrSource, 1);
+ l->server = s;
+ l->hash_table = g_hash_table_new_full(addr_hash, addr_equal, NULL, destroy);
+
+ hn = flx_get_host_name();
+ if ((e = strchr(hn, '.')))
+ *e = 0;
+
+ l->hostname = g_strdup_printf("%s.local.", hn);
+ g_free(hn);
+
+ flx_interface_monitor_add_address_callback(s->monitor, addr_callback, l);
+
+ for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->next) {
+ flxInterfaceAddress *a;
+
+ for (a = i->addresses; a; a = a->next)
+ add_addr(l, a);
+ }
+
+ l->hinfo_id = flx_server_get_next_id(l->server);
+
+ uname(&utsname);
+ c = g_strdup_printf("%s%c%s%n", g_strup(utsname.machine), 0, g_strup(utsname.sysname), &length);
+
+ flx_server_add(l->server, l->hinfo_id, l->hostname,
+ FLX_DNS_TYPE_HINFO,
+ c, length+1);
+ g_free(c);
+
+ return l;
+}
+
+void flx_local_addr_source_free(flxLocalAddrSource *l) {
+ g_assert(l);
+
+ flx_interface_monitor_remove_address_callback(l->server->monitor, addr_callback, l);
+ g_hash_table_destroy(l->hash_table);
+ flx_server_remove(l->server, l->hinfo_id);
+ g_free(l->hostname);
+ g_free(l);
+}