Agrego eliminación de rutas.

master
Félix Arreola Rodríguez 2022-12-24 18:39:46 -06:00
parent a9afc75ba6
commit fbef149d4f
10 changed files with 416 additions and 30 deletions

View File

@ -222,7 +222,7 @@ static void ni_client_process_interface_response (NIClient *ni_client, gpointer
g_signal_emit (ni_client, signals[NEW_INTERFACE], 0, ni_interface); g_signal_emit (ni_client, signals[NEW_INTERFACE], 0, ni_interface);
} }
static NIRoute *_ni_client_search_route (GList *list_routes, sa_family_t family, uint8_t type, uint32_t table, void *dest, uint32_t prefix, uint32_t priority) { static NIRoute *_ni_client_search_route (GList *list_routes, sa_family_t family, uint8_t tos, uint32_t table, void *dest, uint32_t prefix, uint32_t priority) {
GList *g; GList *g;
NIRoute *ni_route; NIRoute *ni_route;
int family_size = 0; int family_size = 0;
@ -237,7 +237,7 @@ static NIRoute *_ni_client_search_route (GList *list_routes, sa_family_t family,
ni_route = (NIRoute *) g->data; ni_route = (NIRoute *) g->data;
if (ni_route_get_family (ni_route) != family) continue; if (ni_route_get_family (ni_route) != family) continue;
if (ni_route_get_route_type(ni_route) != type) continue; if (ni_route_get_route_tos (ni_route) != tos) continue;
if (ni_route_get_table (ni_route) != table) continue; if (ni_route_get_table (ni_route) != table) continue;
if (ni_route_get_priority( ni_route) != priority) continue; if (ni_route_get_priority( ni_route) != priority) continue;
@ -335,7 +335,7 @@ static void ni_client_process_route_response (NIClient *ni_client, gpointer data
static void ni_client_process_route_del_response (NIClient *ni_client, gpointer data, guint size) { static void ni_client_process_route_del_response (NIClient *ni_client, gpointer data, guint size) {
unsigned char *buffer = (unsigned char *) data; unsigned char *buffer = (unsigned char *) data;
uint8_t family, family_size; uint8_t family, family_size;
uint8_t type, prefix; uint8_t tos, prefix;
uint32_t tabla, prioridad; uint32_t tabla, prioridad;
NIRoute *ni_route; NIRoute *ni_route;
struct_addr dest; struct_addr dest;
@ -351,7 +351,7 @@ static void ni_client_process_route_del_response (NIClient *ni_client, gpointer
list_routes = ni_client->priv->routes_v6; list_routes = ni_client->priv->routes_v6;
} }
type = buffer[3]; tos = buffer[3];
memcpy (&tabla, &buffer[4], 4); memcpy (&tabla, &buffer[4], 4);
prefix = buffer[8]; prefix = buffer[8];
@ -359,7 +359,7 @@ static void ni_client_process_route_del_response (NIClient *ni_client, gpointer
memcpy (&dest, &buffer[13], family_size); memcpy (&dest, &buffer[13], family_size);
ni_route = _ni_client_search_route (list_routes, family, type, tabla, &dest, prefix, prioridad); ni_route = _ni_client_search_route (list_routes, family, tos, tabla, &dest, prefix, prioridad);
if (ni_route == NULL) { if (ni_route == NULL) {
/* ¿No hay ruta? Raro */ /* ¿No hay ruta? Raro */
@ -991,6 +991,45 @@ void ni_client_ask_route_new (NIClient *ni_client, int family, int prefix, struc
send (ni_client->priv->client_socket, buffer, pos, 0); send (ni_client->priv->client_socket, buffer, pos, 0);
} }
void ni_client_ask_route_del (NIClient *ni_client, NIRoute *route) {
unsigned char buffer[80];
int family_size, family;
int pos, c;
const struct_addr *dest;
uint32_t tabla, priority;
if (ni_client->priv->client_socket < 0) {
return;
}
family = ni_route_get_family (route);
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
buffer[0] = NET_INADOR_TYPE_COMMAND;
buffer[1] = NET_INADOR_COMMAND_REMOVE_ROUTE;
buffer[2] = family;
buffer[3] = ni_route_get_route_tos (route);
tabla = ni_route_get_table (route);
memcpy (&buffer[4], &tabla, 4);
buffer[8] = ni_route_get_prefix (route);
priority = ni_route_get_priority (route);
memcpy (&buffer[9], &priority, 4);
dest = ni_route_get_dest (route);
memcpy (&buffer[13], dest, family_size);
pos = 13 + family_size;
send (ni_client->priv->client_socket, buffer, pos, 0);
}
static void ni_client_foreach_has_table (gpointer key, gpointer value, gpointer data) { static void ni_client_foreach_has_table (gpointer key, gpointer value, gpointer data) {
GList **lista = (GList **) data; GList **lista = (GList **) data;

View File

@ -71,6 +71,7 @@ struct _NIClient {
}; };
typedef struct _NIInterface NIInterface; typedef struct _NIInterface NIInterface;
typedef struct _NIRoute NIRoute;
/* /*
* Method definitions. * Method definitions.
@ -96,6 +97,7 @@ GList *ni_client_get_routes_v4 (NIClient *ni_client);
GList *ni_client_get_routes_v6 (NIClient *ni_client); GList *ni_client_get_routes_v6 (NIClient *ni_client);
void ni_client_ask_route_new (NIClient *ni_client, int family, int prefix, struct_addr *dest, int type, uint32_t tabla, int protocol, int tos, int scope, int has_prefsrc, struct_addr *prefsrc, uint32_t priority, GList *gws); void ni_client_ask_route_new (NIClient *ni_client, int family, int prefix, struct_addr *dest, int type, uint32_t tabla, int protocol, int tos, int scope, int has_prefsrc, struct_addr *prefsrc, uint32_t priority, GList *gws);
void ni_client_ask_route_del (NIClient *ni_client, NIRoute *route);
void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_interface); void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_interface);
void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_interface, NIInterface *master); void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_interface, NIInterface *master);

View File

@ -241,7 +241,7 @@ static gboolean ni_route_process_route_response (NIClient *ni_client, unsigned c
/* Tengo suficientes datos, revisar si es mi ruta */ /* Tengo suficientes datos, revisar si es mi ruta */
if (ni_route->priv->family != family) return FALSE; if (ni_route->priv->family != family) return FALSE;
if (ni_route->priv->type != type) return FALSE; if (ni_route->priv->tos != tos) return FALSE;
if (ni_route->priv->table != tabla) return FALSE; if (ni_route->priv->table != tabla) return FALSE;
if (ni_route->priv->priority != prioridad) return FALSE; if (ni_route->priv->priority != prioridad) return FALSE;
@ -351,6 +351,12 @@ guint ni_route_get_route_type (NIRoute *ni_route) {
return ni_route->priv->type; return ni_route->priv->type;
} }
guint ni_route_get_route_tos (NIRoute *ni_route) {
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
return ni_route->priv->tos;
}
guint ni_route_get_family (NIRoute *ni_route) { guint ni_route_get_family (NIRoute *ni_route) {
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0); g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);

View File

@ -80,6 +80,7 @@ NIRoute *ni_route_new (NIClient *ni_client, int family, int type, uint32_t table
NIClient *ni_route_get_client (NIRoute *ni_route); NIClient *ni_route_get_client (NIRoute *ni_route);
guint ni_route_get_family (NIRoute *ni_route); guint ni_route_get_family (NIRoute *ni_route);
guint ni_route_get_route_type (NIRoute *ni_route); guint ni_route_get_route_type (NIRoute *ni_route);
guint ni_route_get_route_tos (NIRoute *ni_route);
const struct_addr *ni_route_get_dest (NIRoute *ni_route); const struct_addr *ni_route_get_dest (NIRoute *ni_route);
guint ni_route_get_prefix (NIRoute *ni_route); guint ni_route_get_prefix (NIRoute *ni_route);
uint32_t ni_route_get_table (NIRoute *ni_route); uint32_t ni_route_get_table (NIRoute *ni_route);

View File

@ -150,6 +150,8 @@ static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute
struct _NIWindowRouteSearchTable for_search; struct _NIWindowRouteSearchTable for_search;
int route_type; int route_type;
char *route_type_desc; char *route_type_desc;
int tos;
char *route_tos_desc;
family = ni_route_get_family (ni_route); family = ni_route_get_family (ni_route);
dest = ni_route_get_dest (ni_route); dest = ni_route_get_dest (ni_route);
@ -157,6 +159,7 @@ static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute
prefix = ni_route_get_prefix (ni_route); prefix = ni_route_get_prefix (ni_route);
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);
tos = ni_route_get_route_tos (ni_route);
if (family != window_route->priv->family) { if (family != window_route->priv->family) {
return; return;
@ -193,12 +196,20 @@ static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute
} else { } else {
snprintf (buffer, sizeof (buffer), "%s/%i", buffer_ip, prefix); snprintf (buffer, sizeof (buffer), "%s/%i", buffer_ip, prefix);
} }
if (route_type_desc != NULL) { if (route_type_desc != NULL) {
snprintf (buffer2, sizeof (buffer2), "%s %s", buffer, route_type_desc); snprintf (buffer2, sizeof (buffer2), "%s %s", buffer, route_type_desc);
} else { } else {
strncpy (buffer2, buffer, sizeof (buffer2)); strncpy (buffer2, buffer, sizeof (buffer2));
} }
route_tos_desc = NULL;
if (tos != 0) {
snprintf (buffer, sizeof (buffer), "%s [TOS 0x%02x]", buffer2, tos);
} else {
strncpy (buffer, buffer2, sizeof (buffer));
}
/* Preparar el pref-src, si lo tiene */ /* Preparar el pref-src, si lo tiene */
buffer_ip[0] = 0; buffer_ip[0] = 0;
if (ni_route_has_prefsrc (ni_route)) { if (ni_route_has_prefsrc (ni_route)) {
@ -218,7 +229,7 @@ static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute
gtk_list_store_insert_with_values (window_route->priv->tables_store, NULL, -1, TABLE_STORE_TABLE, table, TABLE_STORE_NAME, NULL, TABLE_STORE_IS_NEW, FALSE, -1); gtk_list_store_insert_with_values (window_route->priv->tables_store, NULL, -1, TABLE_STORE_TABLE, table, TABLE_STORE_NAME, NULL, TABLE_STORE_IS_NEW, FALSE, -1);
} }
gtk_list_store_insert_with_values (window_route->priv->routes_store, NULL, -1, ROUTE_STORE_TABLE, table, ROUTE_STORE_COL_DST_GW, buffer2, ROUTE_STORE_COL_METRIC, priority, ROUTE_STORE_COL_PREFSRC, buffer_ip, ROUTE_STORE_COL_OBJECT, ni_route, -1); gtk_list_store_insert_with_values (window_route->priv->routes_store, NULL, -1, ROUTE_STORE_TABLE, table, ROUTE_STORE_COL_DST_GW, buffer, ROUTE_STORE_COL_METRIC, priority, ROUTE_STORE_COL_PREFSRC, buffer_ip, ROUTE_STORE_COL_OBJECT, ni_route, -1);
g_signal_connect (ni_route, "updated", G_CALLBACK (ni_window_route_updated_route_cb), window_route); g_signal_connect (ni_route, "updated", G_CALLBACK (ni_window_route_updated_route_cb), window_route);
} }
@ -459,6 +470,32 @@ static void ni_window_interface_delete_route_cb (NIClient *ni_client, NIRoute *n
} }
} }
static void has_route_selected_cb (GtkTreeSelection *selection, gpointer data) {
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
if (gtk_tree_selection_count_selected_rows (selection) > 0) {
gtk_widget_set_sensitive (window_route->priv->del_route_button, TRUE);
} else {
gtk_widget_set_sensitive (window_route->priv->del_route_button, FALSE);
}
}
static void ni_window_route_del_route_button_add_cb (GtkWidget *button, gpointer data) {
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
NIRoute *ni_route;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window_route->priv->tree_routes));
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, ROUTE_STORE_COL_OBJECT, &ni_route, -1);
ni_client_ask_route_del (window_route->priv->ni_client, ni_route);
}
static void ni_window_route_add_route_button_add_cb (GtkWidget *button, gpointer data) { static void ni_window_route_add_route_button_add_cb (GtkWidget *button, gpointer data) {
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data); NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
GtkWidget *dialog; GtkWidget *dialog;
@ -720,12 +757,12 @@ static void ni_window_route_init (NIWindowRoute *window_route) {
priv->del_route_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_LARGE_TOOLBAR); priv->del_route_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_box_pack_start (GTK_BOX (vbox2), priv->del_route_button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox2), priv->del_route_button, FALSE, FALSE, 0);
//g_signal_connect (priv->del_route_button, "clicked", G_CALLBACK (ni_window_interface_addr_v6_button_del_cb), window_iface); g_signal_connect (priv->del_route_button, "clicked", G_CALLBACK (ni_window_route_del_route_button_add_cb), window_route);
gtk_widget_set_sensitive (priv->del_route_button, FALSE); gtk_widget_set_sensitive (priv->del_route_button, FALSE);
/* Conectar la señal de cambio de selección del tree view */ /* Conectar la señal de cambio de selección del tree view */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_routes)); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_routes));
//g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v6_cb), window_iface); g_signal_connect (selection, "changed", G_CALLBACK (has_route_selected_cb), window_route);
/* La botonera inferior */ /* La botonera inferior */
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);

View File

@ -233,9 +233,9 @@ typedef struct _Route {
uint32_t table; uint32_t table;
struct_addr dest; struct_addr dest;
uint8_t prefix; uint8_t prefix;
uint8_t tos;
uint8_t protocol; uint8_t protocol;
uint8_t tos;
uint8_t scope; uint8_t scope;
struct_addr prefsrc; struct_addr prefsrc;
@ -248,10 +248,18 @@ typedef struct _Route {
int for_delete; int for_delete;
} Route; } Route;
typedef struct _RouteTable {
uint32_t table;
char name[256];
int for_delete, was_new;
} RouteTable;
struct _NetworkInadorHandle { struct _NetworkInadorHandle {
GList *interfaces; GList *interfaces;
GList *route_v4_tables; GList *route_v4_tables;
GList *route_v6_tables; GList *route_v6_tables;
GList *route_tables_names;
NetworkInadorManager *manager; NetworkInadorManager *manager;

View File

@ -1106,7 +1106,7 @@ void _manager_send_route_del (ManagerClientInfo *manager_client, Route *route) {
family_size = sizeof (struct in6_addr); family_size = sizeof (struct in6_addr);
} }
buffer[2] = route->family; buffer[2] = route->family;
buffer[3] = route->type; buffer[3] = route->tos;
memcpy (&buffer[4], &route->table, 4); memcpy (&buffer[4], &route->table, 4);
buffer[8] = route->prefix; buffer[8] = route->prefix;
memcpy (&buffer[9], &route->priority, 4); memcpy (&buffer[9], &route->priority, 4);
@ -1275,6 +1275,102 @@ void _manager_execute_add_route (ManagerClientInfo *manager_client, unsigned cha
} }
} }
void _manager_execute_del_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
Route route;
int ret;
int family_size, wanted_size, family;
int g, rem, pos;
if (buffer_len < 13) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_REMOVE_ROUTE);
return;
}
family = buffer[2];
if (family != AF_INET && family != AF_INET6) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_REMOVE_ROUTE);
return;
}
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
/* Ya puedo revisar el resto de la longitud */
wanted_size = 13 + family_size;
if (buffer_len < wanted_size) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_REMOVE_ROUTE);
return;
}
memset (&route, 0, sizeof (route));
/* Ejecutar el parsing */
route.family = family;
route.tos = buffer[3];
memcpy (&route.table, &buffer[4], 4);
route.prefix = buffer[8];
memcpy (&route.priority, &buffer[9], 4);
memcpy (&route.dest, &buffer[13], family_size);
ret = routes_del (manager_client->manager->handle, &route);
if (ret == 0) {
/* OK */
_manager_send_executed (manager_client);
} else {
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_REMOVE_ROUTE);
}
}
void _manager_send_route_table (ManagerClientInfo *manager_client, RouteTable *rtable, gboolean is_event) {
unsigned char buffer[80];
int name_len;
if (is_event) {
buffer[0] = NET_INADOR_TYPE_EVENT;
buffer[1] = NET_INADOR_EVENT_ROUTE_TABLE_ADDED;
} else {
buffer[0] = NET_INADOR_TYPE_RESPONSE;
buffer[1] = NET_INADOR_RESPONSE_ROUTE_TABLE;
}
memcpy (&buffer[2], &rtable->table, 4);
name_len = strlen (rtable->name);
buffer[6] = name_len;
memcpy (&buffer[7], rtable->name, name_len);
send (manager_client->fd, buffer, 7 + name_len, 0);
}
void _manager_send_list_route_tables (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
GList *g;
RouteTable *rtable;
uint32_t table;
if (buffer_len < 6) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_LIST_ROUTE_TABLES);
return;
}
memcpy (&table, &buffer[2], 4);
for (g = manager_client->manager->handle->route_v4_tables; g != NULL; g = g->next) {
rtable = (RouteTable *) g->data;
if (table != 0 && rtable->table != table) continue;
_manager_send_route_table (manager_client, rtable, FALSE);
}
_manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTE_TABLES);
}
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) { static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
ManagerClientInfo *manager_client = (ManagerClientInfo *) data; ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
NetworkInadorManager *manager = manager_client->manager; NetworkInadorManager *manager = manager_client->manager;
@ -1380,7 +1476,10 @@ static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition
_manager_execute_add_route (manager_client, buffer, bytes); _manager_execute_add_route (manager_client, buffer, bytes);
break; break;
case NET_INADOR_COMMAND_REMOVE_ROUTE: case NET_INADOR_COMMAND_REMOVE_ROUTE:
_manager_execute_del_route (manager_client, buffer, bytes);
break;
case NET_INADOR_COMMAND_LIST_ROUTE_TABLES:
_manager_send_list_route_tables (manager_client, buffer, bytes);
break; break;
default: default:
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command); _manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);

View File

@ -44,6 +44,8 @@ enum {
NET_INADOR_COMMAND_ADD_ROUTE, NET_INADOR_COMMAND_ADD_ROUTE,
NET_INADOR_COMMAND_REMOVE_ROUTE, NET_INADOR_COMMAND_REMOVE_ROUTE,
NET_INADOR_COMMAND_LIST_ROUTE_TABLES = 72,
NET_INADOR_COMMAND_SET_EVENT_MASK = 192, NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
/* Los siguientes comandos son para uso interno */ /* Los siguientes comandos son para uso interno */
@ -72,6 +74,9 @@ enum {
NET_INADOR_EVENT_ROUTE_ADDED = 10, NET_INADOR_EVENT_ROUTE_ADDED = 10,
NET_INADOR_EVENT_ROUTE_REMOVED, NET_INADOR_EVENT_ROUTE_REMOVED,
NET_INADOR_EVENT_ROUTE_TABLE_ADDED = 14,
NET_INADOR_EVENT_ROUTE_TABLE_REMOVED,
}; };
enum { enum {
@ -83,6 +88,8 @@ enum {
NET_INADOR_RESPONSE_DHCP_STATUS = 6, NET_INADOR_RESPONSE_DHCP_STATUS = 6,
NET_INADOR_RESPONSE_ROUTE = 10, NET_INADOR_RESPONSE_ROUTE = 10,
NET_INADOR_RESPONSE_ROUTE_TABLE = 14
}; };
enum { enum {

View File

@ -26,6 +26,8 @@
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
@ -75,7 +77,7 @@ int _route_same_list_nexthops (int family, GList *nexthops_a, GList *nexthops_b)
return 0; 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 tos, uint32_t table, void *dest, uint32_t prefix, uint32_t priority) {
GList *g; GList *g;
Route *route; Route *route;
int family_size = 0; int family_size = 0;
@ -90,8 +92,11 @@ Route *_route_search_route (GList *list_routes, sa_family_t family, uint8_t type
route = (Route *) g->data; route = (Route *) g->data;
if (route->family != family) continue; if (route->family != family) continue;
if (route->type != type) continue;
/* Por tos si genera diferencia */
if (route->tos != tos) continue;
if (route->table != table) continue; if (route->table != table) continue;
/* Por métrica */
if (route->priority != priority) continue; if (route->priority != priority) continue;
if (memcmp (&route->dest, dest, family_size) == 0 && route->prefix == prefix) { if (memcmp (&route->dest, dest, family_size) == 0 && route->prefix == prefix) {
@ -158,7 +163,7 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
int rtnhp_len; int rtnhp_len;
int multipath_len; int multipath_len;
unsigned char *p; unsigned char *p;
uint8_t route_type; uint8_t route_type, tos;
struct_addr dest; struct_addr dest;
uint32_t priority = 0; uint32_t priority = 0;
int was_new = 0, was_update = 0; int was_new = 0, was_update = 0;
@ -183,7 +188,9 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
route_list = handle->route_v6_tables; route_list = handle->route_v6_tables;
} }
/* Recuperar el tipo de ruta */ /* Recuperar el tos, porque marca diferencia entre rutas */
tos = rtm_hdr->rtm_tos;
route_type = rtm_hdr->rtm_type; route_type = rtm_hdr->rtm_type;
/* Recuperar el prefijo */ /* Recuperar el prefijo */
@ -217,7 +224,7 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
} }
} }
/* TODO: Revisar si la ruta que procesamos ya existe */ /* TODO: Revisar si la ruta que procesamos ya existe */
route = _route_search_route (route_list, family, route_type, table, &dest, prefix, priority); route = _route_search_route (route_list, family, tos, table, &dest, prefix, priority);
if (route == NULL) { if (route == NULL) {
/* Nueva ruta */ /* Nueva ruta */
@ -228,6 +235,7 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
route->type = route_type; route->type = route_type;
route->table = table; route->table = table;
route->prefix = prefix; route->prefix = prefix;
route->tos = tos;
route->priority = priority; route->priority = priority;
route->for_delete = 0; route->for_delete = 0;
@ -252,11 +260,6 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
was_update = 1; was_update = 1;
} }
if (route->tos != rtm_hdr->rtm_tos) {
route->tos = rtm_hdr->rtm_tos;
was_update = 1;
}
if (route->scope != rtm_hdr->rtm_scope) { if (route->scope != rtm_hdr->rtm_scope) {
route->scope = rtm_hdr->rtm_scope; route->scope = rtm_hdr->rtm_scope;
was_update = 1; was_update = 1;
@ -350,7 +353,7 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) {
int family, family_size = 0; int family, family_size = 0;
struct rtmsg *rtm_hdr; struct rtmsg *rtm_hdr;
struct nlattr *attr; struct nlattr *attr;
uint8_t route_type; uint8_t route_tos;
struct_addr dest; struct_addr dest;
uint32_t priority = 0; uint32_t priority = 0;
GList *route_list = NULL; GList *route_list = NULL;
@ -372,8 +375,8 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) {
route_list = handle->route_v6_tables; route_list = handle->route_v6_tables;
} }
/* Recuperar el tipo de ruta */ /* Recuperar el tos de la ruta*/
route_type = rtm_hdr->rtm_type; route_tos = rtm_hdr->rtm_tos;
/* Recuperar el prefijo */ /* Recuperar el prefijo */
prefix = rtm_hdr->rtm_dst_len; prefix = rtm_hdr->rtm_dst_len;
@ -406,7 +409,7 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) {
} }
} }
route = _route_search_route (route_list, family, route_type, table, &dest, prefix, priority); route = _route_search_route (route_list, family, route_tos, table, &dest, prefix, priority);
if (route == NULL) { if (route == NULL) {
/* ¿Notificación de eliminar una ruta que no existe? Super raro */ /* ¿Notificación de eliminar una ruta que no existe? Super raro */
@ -591,7 +594,61 @@ int routes_del (NetworkInadorHandle *handle, Route *route) {
RouteNH *nh; RouteNH *nh;
GList *g; GList *g;
/* TODO: Pendiente escribir esto */ memset (&route_hdr, 0, sizeof (route_hdr));
route_hdr.rtm_family = route->family;
route_hdr.rtm_dst_len = route->prefix;
route_hdr.rtm_tos = route->tos;
route_hdr.rtm_table = route->table;
msg = nlmsg_alloc_simple (RTM_DELROUTE, NLM_F_REQUEST);
ret = nlmsg_append (msg, &route_hdr, sizeof (route_hdr), NLMSG_ALIGNTO);
if (ret != 0) {
nlmsg_free (msg);
return -1;
}
if (route->family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (route->family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
ret = nla_put (msg, RTA_DST, family_size, &route->dest);
if (route->priority != 0) {
ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority);
}
if (ret != 0) {
nlmsg_free (msg);
return -1;
}
nl_complete_msg (handle->nl_sock_route, msg);
ret = nl_send (handle->nl_sock_route, msg);
nlmsg_free (msg);
if (ret <= 0) {
return -1;
}
error = 0;
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _route_wait_error, &error);
ret = nl_recvmsgs_default (handle->nl_sock_route);
if (ret < 0 || error < 0) {
return -1;
}
return 0;
} }
void routes_ask (NetworkInadorHandle *handle) { void routes_ask (NetworkInadorHandle *handle) {
@ -674,9 +731,138 @@ void routes_ask (NetworkInadorHandle *handle) {
} }
} }
gint _routes_table_find_by_number (gconstpointer left, gconstpointer right) {
RouteTable *a, *b;
a = (RouteTable *) left;
b = (RouteTable *) right;
return a->table != b->table;
}
void _routes_table_parse_file (NetworkInadorHandle *handle, FILE *fd) {
GList *g;
RouteTable *rtable, temp_table;
char buffer[2048];
while (fgets (buffer, sizeof (buffer), fd), feof (fd) != 0) {
sscanf (buffer, "%d %s", &(temp_table.table), temp_table.name);
g = g_list_find_custom (handle->route_tables_names, &temp_table, _routes_table_find_by_number);
if (g != NULL) {
/* El número de tabla ya existe, marcar y actualizar el nombre */
rtable = (RouteTable *) g->data;
rtable->for_delete = 0;
rtable->was_new = 0;
} else {
/* No existe, crear nueva */
rtable = (RouteTable *) g_malloc (sizeof (RouteTable));
rtable->table = temp_table.table;
rtable->for_delete = 0;
rtable->was_new = 1;
}
/* En cualquier caso actualizar el nombre */
strncpy (rtable->name, temp_table.name, sizeof (rtable->name));
}
}
void routes_tables_read (NetworkInadorHandle *handle, int do_notify) {
FILE *fd;
GList *g, *h;
RouteTable *rtable;
DIR *dir;
struct dirent *direntry;
int len;
char buffer[4096];
g = handle->route_tables_names;
while (g != NULL) {
rtable = (RouteTable *) g->data;
rtable->for_delete = 1;
rtable->was_new = 0;
g = g->next;
}
//g_list_free_full (handle->route_tables_names, g_free);
//handle->route_tables_names = NULL;
/* Intentar abrir /etc/iproute2/rt_tables */
fd = fopen ("/etc/iproute2/rt_tables", "r");
if (fd != NULL) {
_routes_table_parse_file (handle, fd);
fclose (fd);
}
/* Ahora leer todo el directorio /etc/iproute2/rt_tables.d/ y buscar archivos *.conf */
dir = opendir ("/etc/iproute2/rt_tables.d");
if (dir != NULL) {
while (direntry = readdir (dir), direntry != NULL) {
len = strlen (direntry->d_name);
/* Buscar por archivos que terminen en .conf */
if (len > 5 && strcmp (&(direntry->d_name[len - 5]), ".conf") == 0) {
/* Intentar abrir este archivo y parsearlo */
snprintf (buffer, sizeof (buffer), "/etc/iproute2/rt_tables.d/%s", direntry->d_name);
fd = fopen (buffer, "r");
if (fd != NULL) {
_routes_table_parse_file (handle, fd);
fclose (fd);
}
}
}
closedir (dir);
}
/* Ahora, todas las tablas que están marcadas para eliminar, eliminarlas */
g = handle->route_tables_names;
while (g != NULL) {
h = g->next;
rtable = (RouteTable *) g->data;
if (rtable->for_delete) {
handle->route_tables_names = g_list_delete_link (handle->route_tables_names, g);
if (do_notify) {
/* TODO: Notificar al manager que esta tabla fué eliminada */
}
g_free (rtable);
}
g = h;
}
g = handle->route_tables_names;
while (g != NULL) {
rtable = (RouteTable *) g->data;
if (rtable->was_new) {
if (do_notify) {
/* TODO: Notificar al manager que esta tabla fué agregada */
}
rtable->was_new = 0;
}
g = g->next;
}
}
void routes_init (NetworkInadorHandle *handle) { void routes_init (NetworkInadorHandle *handle) {
/* Si es la primera vez que nos llaman, descargar una primera lista de interfaces */ /* Si es la primera vez que nos llaman, descargar una primera lista de interfaces */
routes_ask (handle); routes_ask (handle);
/* Inicializar los nombres de las tablas de ruteo */
routes_tables_read (handle, FALSE);
} }
void routes_clean_up (NetworkInadorHandle *handle) { void routes_clean_up (NetworkInadorHandle *handle) {

View File

@ -33,6 +33,7 @@ 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);
int routes_add (NetworkInadorHandle *handle, Route *route); int routes_add (NetworkInadorHandle *handle, Route *route);
int routes_del (NetworkInadorHandle *handle, Route *route);
void route_ask_delayed_delroute (NetworkInadorHandle *handle); void route_ask_delayed_delroute (NetworkInadorHandle *handle);