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 remove_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
52 g_hash_table_remove(l->hash_table, &a->address);
55 static void add_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
60 if (g_hash_table_lookup(l->hash_table, &a->address))
61 return; /* Entry already existant */
63 ai = g_new(addr_info, 1);
64 ai->server = l->server;
65 ai->address = a->address;
67 ai->id = flx_server_get_next_id(l->server);
69 flx_server_add_address(l->server, ai->id, a->interface->index, l->hostname, &ai->address);
71 g_hash_table_replace(l->hash_table, &ai->address, ai);
74 static void handle_addr(flxLocalAddrSource *l, const flxInterfaceAddress *a) {
78 if (!(a->interface->flags & IFF_UP) ||
79 !(a->interface->flags & IFF_RUNNING) ||
80 (a->interface->flags & IFF_LOOPBACK) ||
81 a->scope != RT_SCOPE_UNIVERSE)
88 /* Called whenever a new address becomes available, is changed or removed on the local machine */
89 static void addr_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterfaceAddress *a, gpointer userdata) {
90 flxLocalAddrSource *l = userdata;
95 if (change == FLX_INTERFACE_REMOVE)
101 /* Called whenever a new interface becomes available, is changed or removed on the local machine */
102 static void interface_callback(flxInterfaceMonitor *m, flxInterfaceChange change, const flxInterface *i, gpointer userdata) {
103 flxLocalAddrSource *l = userdata;
108 if (change == FLX_INTERFACE_CHANGE) {
109 flxInterfaceAddress *a;
111 for (a = i->addresses; a; a = a->next)
116 static void destroy(gpointer data) {
117 addr_info *ai = data;
118 flx_server_remove(ai->server, ai->id);
122 flxLocalAddrSource *flx_local_addr_source_new(flxServer *s) {
123 flxLocalAddrSource *l;
124 const flxInterface *i;
125 struct utsname utsname;
129 l = g_new(flxLocalAddrSource, 1);
131 l->hash_table = g_hash_table_new_full(addr_hash, addr_equal, NULL, destroy);
133 hn = flx_get_host_name();
134 if ((e = strchr(hn, '.')))
137 l->hostname = g_strdup_printf("%s.local.", hn);
140 flx_interface_monitor_add_address_callback(s->monitor, addr_callback, l);
141 flx_interface_monitor_add_interface_callback(s->monitor, interface_callback, l);
143 for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->next) {
144 flxInterfaceAddress *a;
146 for (a = i->addresses; a; a = a->next)
150 l->hinfo_id = flx_server_get_next_id(l->server);
153 c = g_strdup_printf("%s%c%s%n", g_strup(utsname.machine), 0, g_strup(utsname.sysname), &length);
155 flx_server_add(l->server, l->hinfo_id, 0, l->hostname,
163 void flx_local_addr_source_free(flxLocalAddrSource *l) {
166 flx_interface_monitor_remove_address_callback(l->server->monitor, addr_callback, l);
167 g_hash_table_destroy(l->hash_table);
168 flx_server_remove(l->server, l->hinfo_id);