Agrego eliminación de rutas indirectas.

master
Félix Arreola Rodríguez 2022-04-20 00:55:55 -05:00
parent 88bec9eb0d
commit 2e0bdb1ae4
9 changed files with 239 additions and 10 deletions

View File

@ -152,6 +152,10 @@ static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute
table = ni_route_get_table (ni_route); table = ni_route_get_table (ni_route);
priority = ni_route_get_priority (ni_route); priority = ni_route_get_priority (ni_route);
if (family != window_route->priv->family) {
return;
}
/* Preparar el dest-gw */ /* Preparar el dest-gw */
inet_ntop (family, dest, buffer_ip, sizeof (buffer_ip)); inet_ntop (family, dest, buffer_ip, sizeof (buffer_ip));
if (family == AF_INET && prefix == 32) { if (family == AF_INET && prefix == 32) {
@ -507,7 +511,7 @@ GtkWidget *ni_window_route_create_tree_for_routes (GtkTreeModel *store, GtkWidge
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (*tree), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL); gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (*tree), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree)); h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree));
v = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree)); v = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (*tree));
scrolled = gtk_scrolled_window_new (h, v); scrolled = gtk_scrolled_window_new (h, v);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
@ -535,6 +539,11 @@ GtkWidget *ni_window_route_create_tree_for_routes (GtkTreeModel *store, GtkWidge
gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column); gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Tabla", renderer, "text", ROUTE_STORE_TABLE, NULL);
gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
gtk_container_add (GTK_CONTAINER (scrolled), *tree); gtk_container_add (GTK_CONTAINER (scrolled), *tree);
return scrolled; return scrolled;

View File

@ -243,6 +243,9 @@ typedef struct _Route {
/* Los brincos */ /* Los brincos */
GList *nexthops; GList *nexthops;
/* Variable usada para determinar si debemos eliminar la ruta */
int for_delete;
} Route; } Route;
struct _NetworkInadorHandle { struct _NetworkInadorHandle {
@ -252,13 +255,19 @@ struct _NetworkInadorHandle {
NetworkInadorManager *manager; NetworkInadorManager *manager;
/* Estos sockets ejecutan comandos */
struct nl_sock * nl_sock_route; struct nl_sock * nl_sock_route;
struct nl_sock * nl_sock_nl80211; struct nl_sock * nl_sock_nl80211;
/* Estos sockets son de vigilancia de eventos */
NetlinkEventPair route_events; NetlinkEventPair route_events;
NetlinkEventPair nl80211_scan; NetlinkEventPair nl80211_scan;
NetlinkEventPair nl80211_scan_results; NetlinkEventPair nl80211_scan_results;
/* El pipe de vigilancia especial de las rutas eliminadas */
int pipe_routes[2];
guint source_pipe_routes;
}; };
#endif /* __COMMON_H__ */ #endif /* __COMMON_H__ */

View File

@ -31,6 +31,7 @@
#include "common.h" #include "common.h"
#include "interfaces.h" #include "interfaces.h"
#include "routes.h"
#include "ip-address.h" #include "ip-address.h"
#include "wireless_if.h" #include "wireless_if.h"
#include "manager.h" #include "manager.h"
@ -223,6 +224,7 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg,
if (iface->flags != new_flags) { if (iface->flags != new_flags) {
iface->flags = new_flags; iface->flags = new_flags;
route_ask_delayed_delroute (handle);
was_update = 1; was_update = 1;
} }
@ -340,6 +342,7 @@ int interface_receive_message_dellink (struct nl_msg *msg, void *arg) {
return NL_SKIP; return NL_SKIP;
} }
route_ask_delayed_delroute (handle);
printf ("----- Interfaz eliminada: %s\n", iface->name); printf ("----- Interfaz eliminada: %s\n", iface->name);
handle->interfaces = g_list_remove (handle->interfaces, iface); handle->interfaces = g_list_remove (handle->interfaces, iface);

View File

@ -35,7 +35,7 @@
#include "ip-address.h" #include "ip-address.h"
#include "interfaces.h" #include "interfaces.h"
#include "manager.h" #include "manager.h"
#include "routes.h"
IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr, uint32_t prefix, void *local_addr) { IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr, uint32_t prefix, void *local_addr) {
GList *g; GList *g;
@ -274,6 +274,8 @@ int ip_address_receive_message_deladdr (struct nl_msg *msg, void *arg) {
} }
} }
route_ask_delayed_delroute (handle);
ip_addr = _ip_address_search_addr (iface, family, &addr, addr_msg->ifa_prefixlen, (has_local ? &local_addr : NULL)); ip_addr = _ip_address_search_addr (iface, family, &addr, addr_msg->ifa_prefixlen, (has_local ? &local_addr : NULL));
if (ip_addr == NULL) { if (ip_addr == NULL) {

View File

@ -55,6 +55,8 @@ static void _init_handle (NetworkInadorHandle *handle) {
memset (handle, 0, sizeof (NetworkInadorHandle)); memset (handle, 0, sizeof (NetworkInadorHandle));
handle->interfaces = NULL; handle->interfaces = NULL;
handle->pipe_routes[0] = -1;
handle->pipe_routes[1] = -1;
} }
static void _sigterm_handler (int signum) { static void _sigterm_handler (int signum) {

View File

@ -32,6 +32,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/un.h> #include <sys/un.h>
#include <linux/if_addr.h> #include <linux/if_addr.h>

View File

@ -20,6 +20,9 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
#include <stdio.h>
#include <unistd.h>
#include <netlink/socket.h> #include <netlink/socket.h>
#include <netlink/msg.h> #include <netlink/msg.h>
@ -70,6 +73,26 @@ static gboolean _netlink_events_handle_read (GIOChannel *source, GIOCondition co
return TRUE; return TRUE;
} }
static gboolean _netlink_events_handle_route_ask (GIOChannel *source, GIOCondition condition, gpointer data) {
NetworkInadorHandle *handle = (NetworkInadorHandle *) data;
char buffer[8192];
int ret;
ret = read (handle->pipe_routes[0], buffer, sizeof (buffer));
if (ret > 0) {
/* Leimos algo en el aviso de re-procesar rutas */
routes_ask (handle);
} else if (ret == 0) {
/* Cerrar el pipe */
close (handle->pipe_routes[0]);
handle->pipe_routes[0] = -1;
return FALSE;
}
return TRUE;
}
void netlink_events_create_pair (NetlinkEventPair *pair, int family) { void netlink_events_create_pair (NetlinkEventPair *pair, int family) {
struct nl_sock * sock_req; struct nl_sock * sock_req;
int fd; int fd;
@ -109,10 +132,25 @@ void netlink_events_clear_pair (NetlinkEventPair *pair) {
} }
void netlink_events_setup (NetworkInadorHandle *handle) { void netlink_events_setup (NetworkInadorHandle *handle) {
int ret;
GIOChannel *channel;
netlink_events_create_pair (&handle->route_events, NETLINK_ROUTE); netlink_events_create_pair (&handle->route_events, NETLINK_ROUTE);
int flags;
nl_socket_add_memberships (handle->route_events.nl_sock, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_IFINFO, RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE, 0); nl_socket_add_memberships (handle->route_events.nl_sock, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_IFINFO, RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE, 0);
nl_socket_modify_cb (handle->route_events.nl_sock, NL_CB_VALID, NL_CB_CUSTOM, _netlink_events_route_dispatcher, handle); nl_socket_modify_cb (handle->route_events.nl_sock, NL_CB_VALID, NL_CB_CUSTOM, _netlink_events_route_dispatcher, handle);
/* Crear un pipe para vigilar y procesar los cambios de rutas */
ret = pipe (handle->pipe_routes);
if (ret < 0) {
handle->pipe_routes[0] = handle->pipe_routes[1] = -1;
} else {
flags = fcntl (handle->pipe_routes[0], F_GETFL);
fcntl (handle->pipe_routes[0], F_SETFL, flags | O_NONBLOCK);
channel = g_io_channel_unix_new (handle->pipe_routes[0]);
handle->source_pipe_routes = g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, _netlink_events_handle_route_ask, handle);
g_io_channel_unref (channel);
}
} }
void netlink_events_clear (NetworkInadorHandle *handle) { void netlink_events_clear (NetworkInadorHandle *handle) {

View File

@ -25,6 +25,7 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
@ -35,6 +36,45 @@
#include "routes.h" #include "routes.h"
#include "manager.h" #include "manager.h"
gint _route_compare_nexthop_v4 (gconstpointer a, gconstpointer b);
gint _route_compare_nexthop_v6 (gconstpointer a, gconstpointer b);
void route_ask_delayed_delroute (NetworkInadorHandle *handle) {
if (handle->pipe_routes[1] > 0) {
write (handle->pipe_routes[1], "", 1);
}
}
int _route_same_list_nexthops (int family, GList *nexthops_a, GList *nexthops_b) {
int count_a, count_b;
RouteNH *nha, *nhb;
GList *p_a, *p_b;
count_a = g_list_length (nexthops_a);
count_b = g_list_length (nexthops_b);
if (count_a != count_b) return 1;
p_a = nexthops_a;
p_b = nexthops_b;
while (p_a != NULL) {
nha = (RouteNH *) p_a->data;
nhb = (RouteNH *) p_b->data;
if (family == AF_INET) {
if (_route_compare_nexthop_v4 (nha, nhb) != 0) return 1;
} else if (family == AF_INET6) {
if (_route_compare_nexthop_v6 (nha, nhb) != 0) return 1;
}
p_a = p_a->next;
p_b = p_b->next;
}
return 0;
}
Route *_route_search_route (GList *list_routes, sa_family_t family, uint8_t type, uint32_t table, void *dest, uint32_t prefix, uint32_t priority) { Route *_route_search_route (GList *list_routes, sa_family_t family, uint8_t type, uint32_t table, void *dest, uint32_t prefix, uint32_t priority) {
GList *g; GList *g;
Route *route; Route *route;
@ -62,6 +102,48 @@ Route *_route_search_route (GList *list_routes, sa_family_t family, uint8_t type
return NULL; return NULL;
} }
gint _route_compare_nexthop_v4 (gconstpointer a, gconstpointer b) {
int ret;
RouteNH *nha = (RouteNH *) a, *nhb = (RouteNH *) b;
ret = memcmp (&nha->gw, &nhb->gw, 4);
if (ret != 0) return ret;
ret = nha->out_index - nhb->out_index;
if (ret != 0) return ret;
ret = nha->nh_weight - nhb->nh_weight;
return ret;
}
gint _route_compare_nexthop_v6 (gconstpointer a, gconstpointer b) {
int ret;
RouteNH *nha = (RouteNH *) a, *nhb = (RouteNH *) b;
ret = memcmp (&nha->gw, &nhb->gw, 16);
if (ret != 0) return ret;
ret = nha->out_index - nhb->out_index;
if (ret != 0) return ret;
ret = nha->nh_weight - nhb->nh_weight;
return ret;
}
GList * _route_sort_nexthops (int family, GList *nexthops) {
if (family == AF_INET) {
return g_list_sort (nexthops, _route_compare_nexthop_v4);
} else if (family == AF_INET6) {
return g_list_sort (nexthops, _route_compare_nexthop_v6);
}
return nexthops;
}
int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg; NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
struct nlmsghdr *reply; struct nlmsghdr *reply;
@ -79,8 +161,9 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
uint8_t route_type; uint8_t route_type;
struct_addr dest; struct_addr dest;
uint32_t priority = 0; uint32_t priority = 0;
int was_new = 0; int was_new = 0, was_update = 0;
GList *route_list = NULL; GList *route_list = NULL;
GList *old_next_hops = NULL;
reply = nlmsg_hdr (msg); reply = nlmsg_hdr (msg);
@ -147,6 +230,7 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
route->prefix = prefix; route->prefix = prefix;
route->priority = priority; route->priority = priority;
route->for_delete = 0;
memcpy (&route->dest, &dest, family_size); memcpy (&route->dest, &dest, family_size);
if (family == AF_INET) { if (family == AF_INET) {
@ -157,13 +241,26 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
was_new = 1; was_new = 1;
} else { } else {
/* Liberar los next-hops, puesto que volverán a ser creados */ /* Liberar los next-hops, puesto que volverán a ser creados */
g_list_free_full (route->nexthops, free); //g_list_free_full (route->nexthops, free);
old_next_hops = route->nexthops;
route->nexthops = NULL; route->nexthops = NULL;
route->for_delete = 0;
} }
if (route->protocol != rtm_hdr->rtm_protocol) {
route->protocol = rtm_hdr->rtm_protocol; route->protocol = rtm_hdr->rtm_protocol;
was_update = 1;
}
if (route->tos != rtm_hdr->rtm_tos) {
route->tos = rtm_hdr->rtm_tos; route->tos = rtm_hdr->rtm_tos;
was_update = 1;
}
if (route->scope != rtm_hdr->rtm_scope) {
route->scope = rtm_hdr->rtm_scope; route->scope = rtm_hdr->rtm_scope;
was_update = 1;
}
/* Pre-reservar el primer siguiente brinco y ligar */ /* Pre-reservar el primer siguiente brinco y ligar */
next_hop = (RouteNH *) malloc (sizeof (RouteNH)); next_hop = (RouteNH *) malloc (sizeof (RouteNH));
@ -224,11 +321,20 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
} }
route->nexthops = g_list_append (route->nexthops, next_hop); route->nexthops = g_list_append (route->nexthops, next_hop);
route->nexthops = _route_sort_nexthops (family, route->nexthops);
if (_route_same_list_nexthops (family, route->nexthops, old_next_hops) == 1) {
/* Son diferentes */
was_update = 1;
}
/* Liberar la lista vieja de next_hops */
g_list_free_full (old_next_hops, free);
if (was_new) { if (was_new) {
/* Enviar aquí evento de ruta agregada */ /* Enviar aquí evento de ruta agregada */
manager_send_event_route_add (handle, route); manager_send_event_route_add (handle, route);
} else { } else if (was_update) {
/* Enviar actualización */ /* Enviar actualización */
manager_send_event_route_update (handle, route); manager_send_event_route_update (handle, route);
} }
@ -325,14 +431,29 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) {
return NL_SKIP; return NL_SKIP;
} }
void routes_init (NetworkInadorHandle *handle) { void routes_ask (NetworkInadorHandle *handle) {
/* Si es la primera vez que nos llaman, descargar una primera lista de interfaces */
struct nl_msg * msg; struct nl_msg * msg;
struct rtmsg rtm_hdr = { struct rtmsg rtm_hdr = {
.rtm_family = AF_UNSPEC, .rtm_family = AF_UNSPEC,
}; };
int ret; int ret;
GList *g, *n;
Route *r;
/* Recorrer todas las rutas en la tabla de ruteo y marcarlas para eliminación */
for (g = handle->route_v4_tables; g != NULL; g = g->next) {
r = (Route *) g->data;
r->for_delete = 1;
}
for (g = handle->route_v6_tables; g != NULL; g = g->next) {
r = (Route *) g->data;
r->for_delete = 1;
}
/* Ahora sí, mandar la petición */
msg = nlmsg_alloc_simple (RTM_GETROUTE, NLM_F_REQUEST | NLM_F_DUMP); msg = nlmsg_alloc_simple (RTM_GETROUTE, NLM_F_REQUEST | NLM_F_DUMP);
if (msg == NULL) { if (msg == NULL) {
return; return;
@ -353,6 +474,46 @@ void routes_init (NetworkInadorHandle *handle) {
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, routes_receive_message_newroute, handle); nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, routes_receive_message_newroute, handle);
nl_recvmsgs_default (handle->nl_sock_route); nl_recvmsgs_default (handle->nl_sock_route);
/* Ejecutar las eliminaciones */
for (g = handle->route_v4_tables; g != NULL; g = n) {
n = g->next;
r = (Route *) g->data;
if (r->for_delete == 0) continue;
handle->route_v4_tables = g_list_remove (handle->route_v4_tables, r);
/* Notificar del evento */
manager_send_event_route_del (handle, r);
/* Eliminar todos los next-hops primero */
g_list_free_full (r->nexthops, free);
free (r);
}
for (g = handle->route_v6_tables; g != NULL; g = n) {
n = g->next;
r = (Route *) g->data;
if (r->for_delete == 0) continue;
handle->route_v6_tables = g_list_remove (handle->route_v6_tables, r);
/* Notificar del evento */
manager_send_event_route_del (handle, r);
/* Eliminar todos los next-hops primero */
g_list_free_full (r->nexthops, free);
free (r);
}
}
void routes_init (NetworkInadorHandle *handle) {
/* Si es la primera vez que nos llaman, descargar una primera lista de interfaces */
routes_ask (handle);
} }
void routes_clean_up (NetworkInadorHandle *handle) { void routes_clean_up (NetworkInadorHandle *handle) {

View File

@ -29,9 +29,12 @@
#include "common.h" #include "common.h"
void routes_init (NetworkInadorHandle *handle); void routes_init (NetworkInadorHandle *handle);
void routes_ask (NetworkInadorHandle *handle);
int routes_receive_message_newroute (struct nl_msg *msg, void *arg); int routes_receive_message_newroute (struct nl_msg *msg, void *arg);
int routes_receive_message_delroute (struct nl_msg *msg, void *arg); int routes_receive_message_delroute (struct nl_msg *msg, void *arg);
void route_ask_delayed_delroute (NetworkInadorHandle *handle);
void routes_clean_up (NetworkInadorHandle *handle); void routes_clean_up (NetworkInadorHandle *handle);
#endif /* __ROUTES_H__ */ #endif /* __ROUTES_H__ */