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->data, flx_address_get_size(a));
48 static void remove_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
53 memset(&foo, 0, sizeof(foo));
56 g_hash_table_remove(l->hash_table, &foo);
59 static void add_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
64 if (g_hash_table_lookup(l->hash_table, &a->address))
65 return; /* Entry already existant */
67 ai = g_new(addr_info, 1);
68 ai->server = l->server;
69 ai->address = a->address;
71 ai->id = flx_server_get_next_id(l->server);
73 flx_server_add_address(l->server, ai->id, a->interface->index, AF_UNSPEC, l->hostname, &ai->address);
75 g_hash_table_replace(l->hash_table, &ai->address, ai);
78 static void handle_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
82 if (!(a->interface->flags & IFF_UP) ||
83 !(a->interface->flags & IFF_RUNNING) ||
84 (a->interface->flags & IFF_LOOPBACK) ||
85 a->scope != RT_SCOPE_UNIVERSE)
92 /* Called whenever a new address becomes available, is changed or removed on the local machine */
93 static void addr_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterfaceAddress *a, gpointer userdata) {
94 flxLocalAddrSource *l = userdata;
99 if (change == FLX_INTERFACE_REMOVE)
105 /* Called whenever a new interface becomes available, is changed or removed on the local machine */
106 static void interface_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterface *i, gpointer userdata) {
107 flxLocalAddrSource *l = userdata;
112 if (change == FLX_INTERFACE_CHANGE) {
113 flxInterfaceAddress *a;
115 for (a = i->addresses; a; a = a->next)
120 static void destroy(gpointer data) {
121 addr_info *ai = data;
122 flx_server_remove(ai->server, ai->id);
126 flxLocalAddrSource *flx_local_addr_source_new(flxServer *s) {
127 flxLocalAddrSource *l;
128 const flxInterface *i;
129 struct utsname utsname;
133 l = g_new(flxLocalAddrSource, 1);
135 l->hash_table = g_hash_table_new_full(addr_hash, addr_equal, NULL, destroy);
137 hn = flx_get_host_name();
138 if ((e = strchr(hn, '.')))
141 l->hostname = g_strdup_printf("%s.local.", hn);
144 flx_interface_monitor_add_address_callback(s->monitor, addr_callback, l);
145 flx_interface_monitor_add_interface_callback(s->monitor, interface_callback, l);
147 for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->next) {
148 flxInterfaceAddress *a;
150 for (a = i->addresses; a; a = a->next)
154 l->hinfo_id = flx_server_get_next_id(l->server);
157 c = g_strdup_printf("%s%c%s%n", g_strup(utsname.machine), 0, g_strup(utsname.sysname), &length);
159 flx_server_add(l->server, l->hinfo_id, 0, AF_UNSPEC,
160 l->hostname, FLX_DNS_TYPE_HINFO, c, length+1);
166 void flx_local_addr_source_free(flxLocalAddrSource *l) {
169 flx_interface_monitor_remove_address_callback(l->server->monitor, addr_callback, l);
170 g_hash_table_destroy(l->hash_table);
171 flx_server_remove(l->server, l->hinfo_id);