g_assert(a);
if (!flx_interface_address_relevant(a) || remove) {
- if (a->rr_id >= 0) {
- flx_server_remove(m->server, a->rr_id);
- a->rr_id = -1;
+ if (a->entry_group) {
+ flx_entry_group_free(a->entry_group);
+ a->entry_group = NULL;
}
} 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->hardware->index, AF_UNSPEC, FALSE, m->server->hostname, &a->address);
+ if (!a->entry_group) {
+/* a->entry_group = flx_entry_group_new(m->server, NULL, NULL); */
+/* flx_server_add_address(m->server, a->entry_group, a->interface->hardware->index, AF_UNSPEC, 0, NULL, &a->address); */
+/* flx_entry_group_commit(a->entry_group); */
}
}
}
g_assert(a->interface);
FLX_LLIST_REMOVE(flxInterfaceAddress, address, a->interface->addresses, a);
- flx_server_remove(m->server, a->rr_id);
+
+ if (a->entry_group)
+ flx_entry_group_free(a->entry_group);
g_free(a);
}
-static void free_interface(flxInterfaceMonitor *m, flxInterface *i) {
+static void free_interface(flxInterfaceMonitor *m, flxInterface *i, gboolean send_goodbye) {
g_assert(m);
g_assert(i);
- flx_goodbye_interface(m->server, i, FALSE);
+ g_message("removing interface %s.%i", i->hardware->name, i->protocol);
+ flx_goodbye_interface(m->server, i, send_goodbye);
+ g_message("flushing...");
+ flx_packet_scheduler_flush_responses(i->scheduler);
+ g_message("done");
+
g_assert(!i->announcements);
while (i->addresses)
g_free(i);
}
-static void free_hw_interface(flxInterfaceMonitor *m, flxHwInterface *hw) {
+static void free_hw_interface(flxInterfaceMonitor *m, flxHwInterface *hw, gboolean send_goodbye) {
g_assert(m);
g_assert(hw);
while (hw->interfaces)
- free_interface(m, hw->interfaces);
+ free_interface(m, hw->interfaces, send_goodbye);
FLX_LLIST_REMOVE(flxHwInterface, hardware, m->hw_interfaces, hw);
g_hash_table_remove(m->hash_table, &hw->index);
i->monitor = m;
i->hardware = hw;
i->protocol = protocol;
- i->relevant = FALSE;
+ i->announcing = FALSE;
FLX_LLIST_HEAD_INIT(flxInterfaceAddress, i->addresses);
FLX_LLIST_HEAD_INIT(flxAnnouncement, i->announcements);
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) {
+ if (b && !i->announcing) {
g_message("New relevant interface %s.%i", i->hardware->name, i->protocol);
+ if (i->protocol == AF_INET)
+ flx_mdns_mcast_join_ipv4 (i->hardware->index, m->server->fd_ipv4);
+ if (i->protocol == AF_INET6)
+ flx_mdns_mcast_join_ipv6 (i->hardware->index, m->server->fd_ipv6);
+
+ i->announcing = TRUE;
flx_announce_interface(m->server, i);
- } else if (!b && i->relevant) {
+ } else if (!b && i->announcing) {
g_message("Interface %s.%i no longer relevant", i->hardware->name, i->protocol);
flx_goodbye_interface(m->server, i, FALSE);
- }
- i->relevant = b;
+ if (i->protocol == AF_INET)
+ flx_mdns_mcast_leave_ipv4 (i->hardware->index, m->server->fd_ipv4);
+ if (i->protocol == AF_INET6)
+ flx_mdns_mcast_leave_ipv6 (i->hardware->index, m->server->fd_ipv6);
+
+ i->announcing = FALSE;
+ }
}
static void check_hw_interface_relevant(flxInterfaceMonitor *m, flxHwInterface *hw) {
return;
update_hw_interface_rr(m, hw, TRUE);
- free_hw_interface(m, hw);
+ free_hw_interface(m, hw, FALSE);
} else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
addr->monitor = m;
addr->address = raddr;
addr->interface = i;
- addr->rr_id = -1;
+ addr->entry_group = NULL;
FLX_LLIST_PREPEND(flxInterfaceAddress, address, i->addresses, addr);
}
g_warning("NETLINK: Failed to list addrs: %s", strerror(errno));
else
m->list = LIST_ADDR;
- } else
+ } else {
m->list = LIST_DONE;
+ g_message("Enumeration complete");
+ }
} else if (n->nlmsg_type == NLMSG_ERROR && (n->nlmsg_seq == m->query_link_seq || n->nlmsg_seq == m->query_addr_seq)) {
struct nlmsgerr *e = NLMSG_DATA (n);
m = g_new0(flxInterfaceMonitor, 1);
m->server = s;
- if (!(m->netlink = flx_netlink_new(s->context, RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR, callback, m)))
+ if (!(m->netlink = flx_netlink_new(s->context, G_PRIORITY_DEFAULT-10, RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR, callback, m)))
goto fail;
m->hash_table = g_hash_table_new(g_int_hash, g_int_equal);
goto fail;
m->list = LIST_IFACE;
-
+
return m;
fail:
return NULL;
}
-void flx_interface_monitor_free(flxInterfaceMonitor *m) {
+void flx_interface_monitor_sync(flxInterfaceMonitor *m) {
g_assert(m);
+
+ while (m->list != LIST_DONE) {
+ if (!flx_netlink_work(m->netlink, TRUE))
+ break;
+ }
+}
- if (m->netlink)
- flx_netlink_free(m->netlink);
+void flx_interface_monitor_free(flxInterfaceMonitor *m) {
+ g_assert(m);
while (m->hw_interfaces)
- free_hw_interface(m, m->hw_interfaces);
+ free_hw_interface(m, m->hw_interfaces, TRUE);
g_assert(!m->interfaces);
+
+
+ if (m->netlink)
+ flx_netlink_free(m->netlink);
if (m->hash_table)
g_hash_table_destroy(m->hash_table);
g_assert(i);
g_assert(p);
- if (i->relevant) {
+ if (flx_interface_relevant(i)) {
g_message("sending on '%s.%i'", i->hardware->name, i->protocol);
if (i->protocol == AF_INET && i->monitor->server->fd_ipv4 >= 0)
}
}
-void flx_interface_post_query(flxInterface *i, flxKey *key) {
+void flx_interface_post_query(flxInterface *i, flxKey *key, gboolean immediately) {
g_assert(i);
g_assert(key);
- if (i->relevant)
- flx_packet_scheduler_post_query(i->scheduler, key);
+ if (flx_interface_relevant(i))
+ flx_packet_scheduler_post_query(i->scheduler, key, immediately);
}
-void flx_interface_post_response(flxInterface *i, flxRecord *record) {
+void flx_interface_post_response(flxInterface *i, const flxAddress *a, flxRecord *record, gboolean flush_cache, gboolean immediately) {
g_assert(i);
g_assert(record);
- if (i->relevant)
- flx_packet_scheduler_post_response(i->scheduler, record);
+ if (flx_interface_relevant(i))
+ flx_packet_scheduler_post_response(i->scheduler, a, record, flush_cache, immediately);
+}
+
+void flx_interface_post_probe(flxInterface *i, flxRecord *record, gboolean immediately) {
+ g_assert(i);
+ g_assert(record);
+
+ if (flx_interface_relevant(i))
+ flx_packet_scheduler_post_probe(i->scheduler, record, immediately);
}
void flx_dump_caches(flxInterfaceMonitor *m, FILE *f) {
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);
+ if (flx_interface_relevant(i)) {
+ fprintf(f, "\n;;; INTERFACE %s.%i ;;;\n", i->hardware->name, i->protocol);
flx_cache_dump(i->cache, f);
}
}
+ fprintf(f, "\n");
}
gboolean flx_interface_relevant(flxInterface *i) {
return TRUE;
}
+
+void flx_interface_monitor_walk(flxInterfaceMonitor *m, gint interface, guchar protocol, flxInterfaceMonitorWalkCallback callback, gpointer userdata) {
+ g_assert(m);
+ g_assert(callback);
+
+ if (interface > 0) {
+ if (protocol != AF_UNSPEC) {
+ flxInterface *i;
+
+ if ((i = flx_interface_monitor_get_interface(m, interface, protocol)))
+ callback(m, i, userdata);
+
+ } else {
+ flxHwInterface *hw;
+ flxInterface *i;
+
+ if ((hw = flx_interface_monitor_get_hw_interface(m, interface)))
+ for (i = hw->interfaces; i; i = i->by_hardware_next)
+ if (flx_interface_match(i, interface, protocol))
+ callback(m, i, userdata);
+ }
+
+ } else {
+ flxInterface *i;
+
+ for (i = m->interfaces; i; i = i->interface_next)
+ if (flx_interface_match(i, interface, protocol))
+ callback(m, i, userdata);
+ }
+}