1 #include <sys/socket.h>
3 #include <linux/netlink.h>
4 #include <linux/rtnetlink.h>
6 #include <sys/socket.h>
7 #include <sys/utsname.h>
21 struct _flxLocalAddrSource {
23 GHashTable *hash_table;
28 static gboolean addr_equal(gconstpointer a, gconstpointer b) {
29 return flx_address_cmp(a, b) == 0;
32 static guint hash(gconstpointer v, guint l) {
36 for (c = v; l > 0; c++, l--)
37 hash = 31 * hash + *c;
42 static guint addr_hash(gconstpointer v) {
43 const flxAddress *a = v;
45 return hash(a, sizeof(a->family) + flx_address_get_size(a));
48 static void add_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
54 if (!(a->interface->flags & IFF_UP) ||
55 !(a->interface->flags & IFF_RUNNING) ||
56 (a->interface->flags & IFF_LOOPBACK))
59 if (a->scope != RT_SCOPE_UNIVERSE)
62 ai = g_new(addr_info, 1);
63 ai->server = l->server;
64 ai->address = a->address;
66 ai->id = flx_server_get_next_id(l->server);
67 flx_server_add(l->server, ai->id, l->hostname,
68 ai->address.family == AF_INET ? FLX_DNS_TYPE_A : FLX_DNS_TYPE_AAAA,
69 ai->address.data, flx_address_get_size(&ai->address));
71 r = flx_reverse_lookup_name(&ai->address);
72 flx_server_add(l->server, ai->id, r,
74 l->hostname, strlen(l->hostname)+1);
77 g_hash_table_replace(l->hash_table, &ai->address, ai);
81 /* Called whenever a new address becomes available, is changed or removed on the local machine */
82 static void addr_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterfaceAddress *a, gpointer userdata) {
83 flxLocalAddrSource *l = userdata;
88 if (change == FLX_INTERFACE_REMOVE)
89 g_hash_table_remove(l->hash_table, &a->address);
90 else if (change == FLX_INTERFACE_NEW)
94 static void destroy(gpointer data) {
96 flx_server_remove(ai->server, ai->id);
100 flxLocalAddrSource *flx_local_addr_source_new(flxServer *s) {
101 flxLocalAddrSource *l;
102 const flxInterface *i;
103 struct utsname utsname;
107 l = g_new(flxLocalAddrSource, 1);
109 l->hash_table = g_hash_table_new_full(addr_hash, addr_equal, NULL, destroy);
111 hn = flx_get_host_name();
112 if ((e = strchr(hn, '.')))
115 l->hostname = g_strdup_printf("%s.local.", hn);
118 flx_interface_monitor_add_address_callback(s->monitor, addr_callback, l);
120 for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->next) {
121 flxInterfaceAddress *a;
123 for (a = i->addresses; a; a = a->next)
127 l->hinfo_id = flx_server_get_next_id(l->server);
130 c = g_strdup_printf("%s%c%s%n", g_strup(utsname.machine), 0, g_strup(utsname.sysname), &length);
132 flx_server_add(l->server, l->hinfo_id, l->hostname,
140 void flx_local_addr_source_free(flxLocalAddrSource *l) {
143 flx_interface_monitor_remove_address_callback(l->server->monitor, addr_callback, l);
144 g_hash_table_destroy(l->hash_table);
145 flx_server_remove(l->server, l->hinfo_id);