Agrego rutas en el cliente gtk.
parent
d1a75017b6
commit
88bec9eb0d
|
@ -13,6 +13,8 @@ inador_gtk_client_SOURCES = main.c \
|
|||
ni-ip-add-dialog.c ni-ip-add-dialog.h \
|
||||
ni-interface-filter.c ni-interface-filter.h \
|
||||
ni-interface-chooser-dialog.c ni-interface-chooser-dialog.h \
|
||||
ni-route.c ni-route.h \
|
||||
ni-window-route.c ni-window-route.h \
|
||||
$(BUILT_SOURCES)
|
||||
|
||||
#inador_gtk_client_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "ni-client.h"
|
||||
#include "ni-interface.h"
|
||||
#include "ni-window-interface.h"
|
||||
#include "ni-window-route.h"
|
||||
|
||||
#include "../src/link-types.h"
|
||||
|
||||
enum {
|
||||
|
@ -54,6 +56,8 @@ GtkWidget *main_vbox, *network_vbox;
|
|||
GtkWidget *empty_label = NULL;
|
||||
GHashTable *network_blocks_list;
|
||||
GtkWidget *create_bridge_menu;
|
||||
GtkWidget *route_v4_menu, *route_v6_menu;
|
||||
GtkWidget *route_v4_window = NULL, *route_v6_window = NULL;
|
||||
|
||||
static void click_interface_cb (GtkIconView *iconview, GtkTreePath *path, gpointer data) {
|
||||
UINetworkType *network_block = (UINetworkType *) data;
|
||||
|
@ -74,6 +78,22 @@ static void click_interface_cb (GtkIconView *iconview, GtkTreePath *path, gpoint
|
|||
gtk_widget_show (ventana);
|
||||
}
|
||||
|
||||
static void click_open_route_table_v4 (GtkWidget *widget, gpointer data) {
|
||||
if (route_v4_window == NULL) {
|
||||
route_v4_window = ni_window_route_new (ni_client, AF_INET);
|
||||
}
|
||||
|
||||
gtk_widget_show (route_v4_window);
|
||||
}
|
||||
|
||||
static void click_open_route_table_v6 (GtkWidget *widget, gpointer data) {
|
||||
if (route_v6_window == NULL) {
|
||||
route_v6_window = ni_window_route_new (ni_client, AF_INET6);
|
||||
}
|
||||
|
||||
gtk_widget_show (route_v6_window);
|
||||
}
|
||||
|
||||
int guess_interface_type (NIInterface *ni_interface) {
|
||||
guint type;
|
||||
|
||||
|
@ -321,6 +341,32 @@ int main (int argc, char *argv[]) {
|
|||
|
||||
gtk_widget_show_all (menu);
|
||||
|
||||
/* Menú de las tablas de ruteo */
|
||||
menu_item = gtk_menu_item_new_with_mnemonic ("Tablas de _ruteo");
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
|
||||
|
||||
/* La tabla de ruteo de IPv4 */
|
||||
route_v4_menu = gtk_image_menu_item_new_with_mnemonic ("Tabla de IPv_4");
|
||||
if (connected == FALSE) {
|
||||
gtk_widget_set_sensitive (route_v4_menu, FALSE);
|
||||
}
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), route_v4_menu);
|
||||
g_signal_connect (route_v4_menu, "activate", G_CALLBACK (click_open_route_table_v4), NULL);
|
||||
|
||||
/* La tabla de ruteo de IPv6 */
|
||||
route_v6_menu = gtk_image_menu_item_new_with_mnemonic ("Tabla de IPv_6");
|
||||
if (connected == FALSE) {
|
||||
gtk_widget_set_sensitive (route_v6_menu, FALSE);
|
||||
}
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), route_v6_menu);
|
||||
g_signal_connect (route_v6_menu, "activate", G_CALLBACK (click_open_route_table_v6), NULL);
|
||||
|
||||
gtk_widget_show_all (menu);
|
||||
|
||||
/* El resto de la interfaz */
|
||||
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "ni-client.h"
|
||||
#include "ni-interface.h"
|
||||
#include "ni-marshal.h"
|
||||
#include "ni-route.h"
|
||||
|
||||
#include "../src/network-inador-manager.h"
|
||||
|
||||
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
|
||||
|
@ -50,6 +52,8 @@ struct _NIClientPrivate {
|
|||
|
||||
gchar *socket_path;
|
||||
GHashTable *interfaces;
|
||||
|
||||
GList *routes_v4, *routes_v6;
|
||||
guint source;
|
||||
guint events;
|
||||
};
|
||||
|
@ -66,9 +70,11 @@ enum {
|
|||
DATA_READ,
|
||||
|
||||
NEW_INTERFACE,
|
||||
|
||||
DELETE_INTERFACE,
|
||||
|
||||
NEW_ROUTE,
|
||||
DELETE_ROUTE,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -158,13 +164,36 @@ static void ni_client_class_init (NIClientClass *klass) {
|
|||
1,
|
||||
NI_TYPE_INTERFACE);
|
||||
|
||||
signals[NEW_ROUTE] = g_signal_new ("new-route",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NIClientClass, new_route),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
NI_TYPE_ROUTE);
|
||||
|
||||
signals[DELETE_ROUTE] = g_signal_new ("delete-route",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NIClientClass, delete_route),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
NI_TYPE_ROUTE);
|
||||
|
||||
klass->data_response = ni_client_data_read;
|
||||
klass->new_interface = NULL;
|
||||
klass->delete_interface = NULL;
|
||||
klass->new_route = NULL;
|
||||
klass->delete_route = NULL;
|
||||
}
|
||||
|
||||
static void ni_client_process_interface_response (NIClient *ni_client, gpointer data, guint size) {
|
||||
printf ("Interface response\n");
|
||||
NIInterface *ni_interface;
|
||||
unsigned char *buffer = (unsigned char *) data;
|
||||
|
||||
|
@ -193,6 +222,163 @@ static void ni_client_process_interface_response (NIClient *ni_client, gpointer
|
|||
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) {
|
||||
GList *g;
|
||||
NIRoute *ni_route;
|
||||
int family_size = 0;
|
||||
|
||||
if (family == AF_INET) {
|
||||
family_size = sizeof (struct in_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
family_size = sizeof (struct in6_addr);
|
||||
}
|
||||
|
||||
for (g = list_routes; g != NULL; g = g->next) {
|
||||
ni_route = (NIRoute *) g->data;
|
||||
|
||||
if (ni_route_get_family(ni_route) != family) continue;
|
||||
if (ni_route_get_route_type(ni_route) != type) continue;
|
||||
if (ni_route_get_table(ni_route) != table) continue;
|
||||
if (ni_route_get_priority(ni_route) != priority) continue;
|
||||
|
||||
if (memcmp (ni_route_get_dest (ni_route), dest, family_size) == 0 && ni_route_get_prefix(ni_route) == prefix) {
|
||||
return ni_route;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ni_client_process_route_response (NIClient *ni_client, gpointer data, guint size) {
|
||||
unsigned char *buffer = (unsigned char *) data;
|
||||
uint8_t family, family_size;
|
||||
uint8_t type, protocol, tos, scope, prefix;
|
||||
uint32_t tabla, prioridad;
|
||||
uint8_t num_nexthops;
|
||||
gboolean has_prefsrc;
|
||||
int pos, g;
|
||||
NIRouteNH nexthops[16];
|
||||
NIRoute *ni_route;
|
||||
struct_addr dest, prefsrc;
|
||||
|
||||
memset (nexthops, 0, sizeof (nexthops));
|
||||
family = buffer[2];
|
||||
|
||||
if (family == AF_INET) {
|
||||
family_size = sizeof (struct in_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
family_size = sizeof (struct in6_addr);
|
||||
}
|
||||
|
||||
type = buffer[3];
|
||||
|
||||
memcpy (&tabla, &buffer[4], 4);
|
||||
prefix = buffer[8];
|
||||
protocol = buffer[9];
|
||||
tos = buffer[10];
|
||||
scope = buffer[11];
|
||||
|
||||
has_prefsrc = FALSE;
|
||||
if (buffer[12] & 0x01) {
|
||||
has_prefsrc = TRUE;
|
||||
}
|
||||
|
||||
num_nexthops = buffer[13];
|
||||
|
||||
memcpy (&prioridad, &buffer[14], 4);
|
||||
|
||||
memcpy (&dest, &buffer[18], family_size);
|
||||
|
||||
pos = 18 + family_size;
|
||||
if (has_prefsrc) {
|
||||
memcpy (&prefsrc, &buffer[pos], family_size);
|
||||
pos += family_size;
|
||||
}
|
||||
|
||||
if (num_nexthops > 16) {
|
||||
num_nexthops = 16;
|
||||
}
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
nexthops[g].has_gw = FALSE;
|
||||
if (buffer[pos] & 0x01) {
|
||||
/* Tiene GW */
|
||||
nexthops[g].has_gw = TRUE;
|
||||
}
|
||||
pos++;
|
||||
|
||||
nexthops[g].flags = buffer[pos];
|
||||
pos++;
|
||||
|
||||
nexthops[g].weight = buffer[pos];
|
||||
pos++;
|
||||
|
||||
pos++; /* El byte ignorado */
|
||||
|
||||
memcpy (&nexthops[g].out_index, &buffer[pos], 4);
|
||||
pos +=4;
|
||||
|
||||
if (nexthops[g].has_gw) {
|
||||
memcpy (&nexthops[g].gw, &buffer[pos], family_size);
|
||||
pos += family_size;
|
||||
}
|
||||
}
|
||||
ni_route = ni_route_new (ni_client, family, type, tabla, &dest, prefix, protocol, tos, scope, (has_prefsrc ? &prefsrc : NULL), prioridad, num_nexthops, nexthops);
|
||||
|
||||
if (family == AF_INET) {
|
||||
ni_client->priv->routes_v4 = g_list_append (ni_client->priv->routes_v4, ni_route);
|
||||
} else if (family == AF_INET6) {
|
||||
ni_client->priv->routes_v6 = g_list_append (ni_client->priv->routes_v6, ni_route);
|
||||
}
|
||||
g_signal_emit (ni_client, signals[NEW_ROUTE], 0, ni_route);
|
||||
}
|
||||
|
||||
static void ni_client_process_route_del_response (NIClient *ni_client, gpointer data, guint size) {
|
||||
unsigned char *buffer = (unsigned char *) data;
|
||||
uint8_t family, family_size;
|
||||
uint8_t type, prefix;
|
||||
uint32_t tabla, prioridad;
|
||||
NIRoute *ni_route;
|
||||
struct_addr dest;
|
||||
GList *list_routes;
|
||||
|
||||
family = buffer[2];
|
||||
|
||||
if (family == AF_INET) {
|
||||
family_size = sizeof (struct in_addr);
|
||||
list_routes = ni_client->priv->routes_v4;
|
||||
} else if (family == AF_INET6) {
|
||||
family_size = sizeof (struct in6_addr);
|
||||
list_routes = ni_client->priv->routes_v6;
|
||||
}
|
||||
|
||||
type = buffer[3];
|
||||
|
||||
memcpy (&tabla, &buffer[4], 4);
|
||||
prefix = buffer[8];
|
||||
memcpy (&prioridad, &buffer[9], 4);
|
||||
|
||||
memcpy (&dest, &buffer[13], family_size);
|
||||
|
||||
ni_route = _ni_client_search_route (list_routes, family, type, tabla, &dest, prefix, prioridad);
|
||||
|
||||
if (ni_route == NULL) {
|
||||
/* ¿No hay ruta? Raro */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Desligar la ruta */
|
||||
if (family == AF_INET) {
|
||||
ni_client->priv->routes_v4 = g_list_remove (ni_client->priv->routes_v4, ni_route);
|
||||
} else if (family == AF_INET6) {
|
||||
ni_client->priv->routes_v6 = g_list_remove (ni_client->priv->routes_v6, ni_route);
|
||||
}
|
||||
|
||||
g_signal_emit (ni_client, signals[DELETE_ROUTE], 0, ni_route);
|
||||
|
||||
/* Liberar el objeto */
|
||||
g_object_unref (ni_route);
|
||||
}
|
||||
|
||||
static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint size) {
|
||||
unsigned char *buffer = (unsigned char *) data;
|
||||
uint32_t index;
|
||||
|
@ -243,6 +429,16 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s
|
|||
/* Dejar pasar el evento para que la propia interfaz lo procese */
|
||||
return FALSE;
|
||||
break;
|
||||
case NET_INADOR_EVENT_ROUTE_REMOVED:
|
||||
/* Eliminar una ruta es ligeramente mas complejo porque necesitamos que haga match con varios valores para eliminarla */
|
||||
ni_client_process_route_del_response (ni_client, data, size);
|
||||
return TRUE;
|
||||
break;
|
||||
case NET_INADOR_EVENT_ROUTE_ADDED:
|
||||
/* TODO: Revisar si la ruta existe, entonces, en teoría, es una actualización */
|
||||
ni_client_process_route_response (ni_client, data, size);
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
} else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) {
|
||||
switch (buffer[1]) {
|
||||
|
@ -262,7 +458,6 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s
|
|||
case NET_INADOR_RESPONSE_DHCP_STATUS:
|
||||
memcpy (&index, &buffer[2], 4);
|
||||
|
||||
/* Si la interfaz no existe, proccesarla yo, para que se cree el objeto, si la interfaz ya existe, dejar pasar el mensaje */
|
||||
ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index));
|
||||
if (ni_interface == NULL) {
|
||||
/* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */
|
||||
|
@ -272,6 +467,11 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s
|
|||
/* Dejar pasar el evento para que la propia interfaz lo procese */
|
||||
return FALSE;
|
||||
break;
|
||||
case NET_INADOR_RESPONSE_ROUTE:
|
||||
/* Cuando hacemos listado, no hay problemas de actualización */
|
||||
ni_client_process_route_response (ni_client, data, size);
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,8 +574,10 @@ static void ni_client_init (NIClient *ni_client) {
|
|||
|
||||
priv->client_socket = -1;
|
||||
priv->socket_path = NULL;
|
||||
priv->routes_v4 = NULL;
|
||||
priv->routes_v6 = NULL;
|
||||
priv->source = 0;
|
||||
priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP | NET_INADOR_EVENT_MASK_DHCP_STATUS;
|
||||
priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP | NET_INADOR_EVENT_MASK_DHCP_STATUS | NET_INADOR_EVENT_MASK_ROUTES;
|
||||
|
||||
priv->interfaces = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
}
|
||||
|
@ -407,6 +609,21 @@ void ni_client_ask_interfaces (NIClient *ni_client) {
|
|||
send (ni_client->priv->client_socket, buffer, 2, 0);
|
||||
}
|
||||
|
||||
void ni_client_ask_routes (NIClient *ni_client) {
|
||||
unsigned char buffer[8];
|
||||
|
||||
if (ni_client->priv->client_socket < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[0] = NET_INADOR_TYPE_COMMAND;
|
||||
buffer[1] = NET_INADOR_COMMAND_LIST_ROUTES;
|
||||
memset (&buffer[2], 0, 4);
|
||||
buffer[6] = AF_UNSPEC;
|
||||
|
||||
send (ni_client->priv->client_socket, buffer, 7, 0);
|
||||
}
|
||||
|
||||
void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr, uint32_t *cacheinfo) {
|
||||
unsigned char buffer[80];
|
||||
uint32_t index;
|
||||
|
@ -713,6 +930,18 @@ NIInterface *ni_client_get_interface_by_index (NIClient *ni_client, guint index)
|
|||
return g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index));
|
||||
}
|
||||
|
||||
GList *ni_client_get_routes_v4 (NIClient *ni_client) {
|
||||
g_return_val_if_fail (NI_IS_CLIENT (ni_client), NULL);
|
||||
|
||||
return ni_client->priv->routes_v4;
|
||||
}
|
||||
|
||||
GList *ni_client_get_routes_v6 (NIClient *ni_client) {
|
||||
g_return_val_if_fail (NI_IS_CLIENT (ni_client), NULL);
|
||||
|
||||
return ni_client->priv->routes_v6;
|
||||
}
|
||||
|
||||
gboolean ni_client_connect (NIClient *ni_client) {
|
||||
int s, ret;
|
||||
struct sockaddr_un path_dest;
|
||||
|
@ -749,6 +978,9 @@ gboolean ni_client_connect (NIClient *ni_client) {
|
|||
|
||||
/* Pedir un listado de interfaces */
|
||||
ni_client_ask_interfaces (ni_client);
|
||||
|
||||
/* Pedir un listado de rutas */
|
||||
ni_client_ask_routes (ni_client);
|
||||
}
|
||||
|
||||
void ni_client_disconnect (NIClient *ni_client) {
|
||||
|
|
|
@ -60,6 +60,8 @@ struct _NIClientClass {
|
|||
/*gboolean (* data_response_error) (NiClient *ni_client, gpointer data, guint size);*/
|
||||
void (*new_interface) (NIClient *ni_client, gpointer ni_interface);
|
||||
void (*delete_interface) (NIClient *ni_client, gpointer ni_interface);
|
||||
void (*new_route) (NIClient *ni_client, gpointer ni_route);
|
||||
void (*delete_route) (NIClient *ni_client, gpointer ni_route);
|
||||
};
|
||||
|
||||
struct _NIClient {
|
||||
|
@ -75,7 +77,9 @@ typedef struct _NIInterface NIInterface;
|
|||
*/
|
||||
NIClient *ni_client_new (void);
|
||||
NIClient *ni_client_new_with_path (const char *path);
|
||||
|
||||
gboolean ni_client_connect (NIClient *ni_client);
|
||||
|
||||
void ni_client_ask_ip_interface (NIClient *ni_client, NIInterface *ni_interface, int family);
|
||||
void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr, uint32_t *cacheinfo);
|
||||
void ni_client_ask_ip_delete (NIClient *ni_client, NIInterface *ni_interface, NIIP *ni_ip);
|
||||
|
@ -83,9 +87,13 @@ void ni_client_ask_change_iface_name (NIClient *ni_client, NIInterface *ni_inter
|
|||
void ni_client_ask_change_iface_mtu (NIClient *ni_client, NIInterface *ni_interface, guint new_mtu);
|
||||
void ni_client_ask_up_down_interface (NIClient *ni_client, NIInterface *ni_interface, gboolean is_up);
|
||||
void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name);
|
||||
|
||||
GList *ni_client_get_list_interfaces (NIClient *ni_client);
|
||||
NIInterface *ni_client_get_interface_by_index (NIClient *ni_client, guint index);
|
||||
|
||||
GList *ni_client_get_routes_v4 (NIClient *ni_client);
|
||||
GList *ni_client_get_routes_v6 (NIClient *ni_client);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ni-interface.h
|
||||
* ni-ip.h
|
||||
* This file is part of NetworkInador
|
||||
*
|
||||
* Copyright (C) 2021 - Gatuno
|
||||
|
|
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* ni-route.c
|
||||
* This file is part of NetworkInador
|
||||
*
|
||||
* Copyright (C) 2021 - Félix Arreola Rodríguez
|
||||
*
|
||||
* NetworkInador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NetworkInador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NetworkInador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ni-client.h"
|
||||
#include "ni-route.h"
|
||||
#include "ni-ip.h"
|
||||
|
||||
#include "../src/network-inador-manager.h"
|
||||
|
||||
struct _NIRoutePrivate {
|
||||
NIClient *ni_client;
|
||||
|
||||
guint family;
|
||||
gint family_size;
|
||||
guint type;
|
||||
uint32_t table;
|
||||
struct_addr dest;
|
||||
guint prefix;
|
||||
|
||||
guint protocol, tos, scope;
|
||||
|
||||
gboolean has_prefsrc;
|
||||
struct_addr prefsrc;
|
||||
guint priority;
|
||||
|
||||
/* Múltiples GW */
|
||||
guint nh;
|
||||
NIRouteNH *nexthops;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_NI_CLIENT = 1,
|
||||
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (NIRoute, ni_route, G_TYPE_OBJECT)
|
||||
|
||||
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
enum {
|
||||
ROUTE_UPDATED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static gboolean ni_route_process_route_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer data);
|
||||
|
||||
static void ni_route_constructed (GObject *obj) {
|
||||
NIRoute *ni_route;
|
||||
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
||||
|
||||
parent_class->constructed (obj);
|
||||
|
||||
ni_route = NI_ROUTE (obj);
|
||||
|
||||
if (ni_route->priv->ni_client != NULL) {
|
||||
/* Conectar la señal de datos */
|
||||
g_signal_connect (ni_route->priv->ni_client, "packet-read", G_CALLBACK (ni_route_process_route_response), ni_route);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_route_dispose (GObject *obj) {
|
||||
NIRoute *ni_route;
|
||||
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
||||
|
||||
ni_route = NI_ROUTE (obj);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (ni_route->priv->ni_client, G_CALLBACK (ni_route_process_route_response), ni_route);
|
||||
|
||||
parent_class->dispose (obj);
|
||||
}
|
||||
|
||||
static void ni_route_finalize (GObject *obj) {
|
||||
NIRoute *ni_route;
|
||||
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
||||
|
||||
ni_route = NI_ROUTE (obj);
|
||||
|
||||
/* Nada que hacer, por el momento */
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static void ni_route_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
||||
NIRoute *ni_route = NI_ROUTE (object);
|
||||
g_return_if_fail (NI_IS_ROUTE (object));
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NI_CLIENT:
|
||||
ni_route->priv->ni_client = NI_CLIENT (g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_route_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
||||
NIRoute *ni_route = NI_ROUTE (object);
|
||||
g_return_if_fail (NI_IS_ROUTE (object));
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NI_CLIENT:
|
||||
g_value_set_object (value, ni_route->priv->ni_client);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_route_class_init (NIRouteClass *klass) {
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = ni_route_set_property;
|
||||
object_class->get_property = ni_route_get_property;
|
||||
object_class->constructed = ni_route_constructed;
|
||||
object_class->dispose = ni_route_dispose;
|
||||
object_class->finalize = ni_route_finalize;
|
||||
|
||||
obj_properties[PROP_NI_CLIENT] = g_param_spec_object (
|
||||
"ni-client",
|
||||
"Network Inador Client",
|
||||
"The client object",
|
||||
NI_TYPE_CLIENT,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
|
||||
|
||||
signals[ROUTE_UPDATED] = g_signal_new ("updated",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void ni_route_init (NIRoute *ni_route) {
|
||||
NIRoutePrivate *priv = ni_route_get_instance_private (ni_route);
|
||||
ni_route->priv = priv;
|
||||
|
||||
/* initialize all public and private members to reasonable default values.
|
||||
* They are all automatically initialized to 0 to begin with. */
|
||||
priv->ni_client = NULL;
|
||||
priv->family = AF_UNSPEC;
|
||||
priv->type = 0;
|
||||
priv->table = 0;
|
||||
priv->prefix = 0;
|
||||
|
||||
priv->protocol = 0;
|
||||
priv->tos = 0;
|
||||
priv->scope = 0;
|
||||
|
||||
priv->priority = 0;
|
||||
|
||||
priv->has_prefsrc = FALSE;
|
||||
priv->nh = 0;
|
||||
priv->nexthops = NULL;
|
||||
|
||||
memset (&priv->dest, 0, sizeof (priv->dest));
|
||||
memset (&priv->prefsrc, 0, sizeof (priv->prefsrc));
|
||||
}
|
||||
|
||||
static gboolean ni_route_process_route_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer user_data) {
|
||||
/* Tengo que revisar si los datos son de mi interés, para absorber el evento yo */
|
||||
NIRoute *ni_route = (NIRoute *) user_data;
|
||||
uint8_t family, family_size;
|
||||
uint8_t type, protocol, tos, scope, prefix;
|
||||
uint32_t tabla, prioridad;
|
||||
uint8_t num_nexthops;
|
||||
gboolean has_prefsrc;
|
||||
int pos, g;
|
||||
NIRouteNH nexthops[16];
|
||||
struct_addr dest, prefsrc;
|
||||
int was_update = 0;
|
||||
|
||||
memset (nexthops, 0, sizeof (nexthops));
|
||||
family = buffer[2];
|
||||
|
||||
if (buffer[0] != NET_INADOR_TYPE_EVENT && buffer[1] != NET_INADOR_EVENT_ROUTE_ADDED) {
|
||||
return FALSE; /* No es para mí */
|
||||
}
|
||||
|
||||
if (family == AF_INET) {
|
||||
family_size = sizeof (struct in_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
family_size = sizeof (struct in6_addr);
|
||||
}
|
||||
|
||||
type = buffer[3];
|
||||
|
||||
memcpy (&tabla, &buffer[4], 4);
|
||||
prefix = buffer[8];
|
||||
protocol = buffer[9];
|
||||
tos = buffer[10];
|
||||
scope = buffer[11];
|
||||
|
||||
has_prefsrc = FALSE;
|
||||
if (buffer[12] & 0x01) {
|
||||
has_prefsrc = TRUE;
|
||||
}
|
||||
|
||||
num_nexthops = buffer[13];
|
||||
|
||||
memcpy (&prioridad, &buffer[14], 4);
|
||||
|
||||
memcpy (&dest, &buffer[18], family_size);
|
||||
|
||||
pos = 18 + family_size;
|
||||
if (has_prefsrc) {
|
||||
memcpy (&prefsrc, &buffer[pos], family_size);
|
||||
pos += family_size;
|
||||
}
|
||||
|
||||
/* Tengo suficientes datos, revisar si es mi ruta */
|
||||
if (ni_route->priv->family != family) return FALSE;
|
||||
if (ni_route->priv->type != type) return FALSE;
|
||||
if (ni_route->priv->table != tabla) return FALSE;
|
||||
if (ni_route->priv->priority != prioridad) return FALSE;
|
||||
|
||||
if (memcmp (&ni_route->priv->dest, &dest, family_size) != 0 || ni_route->priv->prefix != prefix) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Terminar de leer los otros datos */
|
||||
if (num_nexthops > 16) {
|
||||
num_nexthops = 16;
|
||||
}
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
nexthops[g].has_gw = FALSE;
|
||||
if (buffer[pos] & 0x01) {
|
||||
/* Tiene GW */
|
||||
nexthops[g].has_gw = TRUE;
|
||||
}
|
||||
pos++;
|
||||
|
||||
nexthops[g].flags = buffer[pos];
|
||||
pos++;
|
||||
|
||||
nexthops[g].weight = buffer[pos];
|
||||
pos++;
|
||||
|
||||
pos++; /* El byte ignorado */
|
||||
|
||||
memcpy (&nexthops[g].out_index, &buffer[pos], 4);
|
||||
pos +=4;
|
||||
|
||||
if (nexthops[g].has_gw) {
|
||||
memcpy (&nexthops[g].gw, &buffer[pos], family_size);
|
||||
pos += family_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Es mi ruta, procesar como actualización */
|
||||
if (ni_route->priv->protocol != protocol) {
|
||||
was_update = 1;
|
||||
ni_route->priv->protocol = protocol;
|
||||
}
|
||||
|
||||
if (ni_route->priv->tos != tos) {
|
||||
was_update = 1;
|
||||
ni_route->priv->tos = tos;
|
||||
}
|
||||
|
||||
if (ni_route->priv->scope != scope) {
|
||||
was_update = 1;
|
||||
ni_route->priv->scope = scope;
|
||||
}
|
||||
|
||||
if (ni_route->priv->has_prefsrc != has_prefsrc) {
|
||||
ni_route->priv->has_prefsrc = has_prefsrc;
|
||||
was_update = 1;
|
||||
if (has_prefsrc == FALSE) {
|
||||
memset (&ni_route->priv->prefsrc, 0, family_size);
|
||||
} else {
|
||||
memcpy (&ni_route->priv->prefsrc, &prefsrc, ni_route->priv->family_size);
|
||||
}
|
||||
} else if (ni_route->priv->has_prefsrc) {
|
||||
was_update = 1;
|
||||
memcpy (&ni_route->priv->prefsrc, &prefsrc, ni_route->priv->family_size);
|
||||
}
|
||||
|
||||
if (ni_route->priv->nh != num_nexthops) {
|
||||
/* Liberar los next-hops anteriores y re-crear los nuevos */
|
||||
ni_route->priv->nh = num_nexthops;
|
||||
|
||||
free (ni_route->priv->nexthops);
|
||||
|
||||
ni_route->priv->nexthops = (NIRouteNH *) malloc (sizeof (NIRouteNH) * num_nexthops);
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
/* Copiar cada next-hop */
|
||||
memcpy (&ni_route->priv->nexthops[g], &nexthops[g], sizeof (NIRouteNH));
|
||||
}
|
||||
was_update = 1;
|
||||
} else {
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
/* Comparar brincos */
|
||||
if (memcmp (&ni_route->priv->nexthops[g], &nexthops[g], sizeof (NIRouteNH)) != 0) {
|
||||
was_update = 1;
|
||||
memcpy (&ni_route->priv->nexthops[g], &nexthops[g], sizeof (NIRouteNH));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Emitir mi señal de update */
|
||||
if (was_update) {
|
||||
g_signal_emit (ni_route, signals[ROUTE_UPDATED], 0);
|
||||
}
|
||||
|
||||
/* Mi evento, ya lo procesé */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Los métodos getters */
|
||||
NIClient *ni_route_get_client (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), NULL);
|
||||
|
||||
return ni_route->priv->ni_client;
|
||||
}
|
||||
|
||||
guint ni_route_get_route_type (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->type;
|
||||
}
|
||||
|
||||
guint ni_route_get_family (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->family;
|
||||
}
|
||||
|
||||
const struct_addr *ni_route_get_dest (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), NULL);
|
||||
|
||||
return &ni_route->priv->dest;
|
||||
}
|
||||
|
||||
guint ni_route_get_prefix (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->prefix;
|
||||
}
|
||||
|
||||
uint32_t ni_route_get_table (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->table;
|
||||
}
|
||||
|
||||
guint ni_route_get_num_nexthops (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->nh;
|
||||
}
|
||||
|
||||
const NIRouteNH *ni_route_get_nexthops (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), NULL);
|
||||
|
||||
return ni_route->priv->nexthops;
|
||||
}
|
||||
|
||||
gboolean ni_route_has_prefsrc (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), FALSE);
|
||||
|
||||
return ni_route->priv->has_prefsrc;
|
||||
}
|
||||
|
||||
const struct_addr *ni_route_get_prefsrc (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), NULL);
|
||||
|
||||
return &ni_route->priv->prefsrc;
|
||||
}
|
||||
|
||||
guint ni_route_get_priority (NIRoute *ni_route) {
|
||||
g_return_val_if_fail (NI_IS_ROUTE (ni_route), 0);
|
||||
|
||||
return ni_route->priv->priority;
|
||||
}
|
||||
|
||||
/*
|
||||
guint family;
|
||||
guint type;
|
||||
guint table;
|
||||
struct_addr dest;
|
||||
guint prefix;
|
||||
|
||||
guint protocol, tos, scope;
|
||||
|
||||
gboolean has_prefsrc;
|
||||
struct_addr prefsrc;
|
||||
guint priority;
|
||||
*/
|
||||
NIRoute *ni_route_new (NIClient *ni_client, int family, int type, uint32_t table, struct_addr *dest, int prefix, unsigned char protocol, unsigned char tos, unsigned char scope, struct_addr *prefsrc, int priority, int num_nexthops, NIRouteNH *nexthops) {
|
||||
NIRoute *ni_route;
|
||||
int g;
|
||||
|
||||
g_return_val_if_fail (NI_IS_CLIENT (ni_client), NULL);
|
||||
g_return_val_if_fail (dest != NULL, NULL);
|
||||
g_return_val_if_fail (num_nexthops > 0, NULL);
|
||||
|
||||
ni_route = g_object_new (NI_TYPE_ROUTE, "ni-client", ni_client, NULL);
|
||||
|
||||
if (family == AF_INET) {
|
||||
ni_route->priv->family_size = sizeof (struct in_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
ni_route->priv->family_size = sizeof (struct in6_addr);
|
||||
}
|
||||
|
||||
/* Establecer y copiar los valores */
|
||||
ni_route->priv->family = family;
|
||||
ni_route->priv->type = type;
|
||||
ni_route->priv->table = table;
|
||||
ni_route->priv->prefix = prefix;
|
||||
|
||||
memcpy (&ni_route->priv->dest, dest, ni_route->priv->family_size);
|
||||
|
||||
ni_route->priv->protocol = protocol;
|
||||
ni_route->priv->tos = tos;
|
||||
ni_route->priv->scope = scope;
|
||||
ni_route->priv->priority = priority;
|
||||
|
||||
if (prefsrc != NULL) {
|
||||
ni_route->priv->has_prefsrc = TRUE;
|
||||
|
||||
memcpy (&ni_route->priv->prefsrc, prefsrc, ni_route->priv->family_size);
|
||||
}
|
||||
|
||||
ni_route->priv->nh = num_nexthops;
|
||||
ni_route->priv->nexthops = (NIRouteNH *) malloc (sizeof (NIRouteNH) * num_nexthops);
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
/* Copiar cada next-hop */
|
||||
memcpy (&ni_route->priv->nexthops[g], &nexthops[g], sizeof (NIRouteNH));
|
||||
}
|
||||
|
||||
|
||||
return ni_route;
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* ni-route.h
|
||||
* This file is part of NetworkInador
|
||||
*
|
||||
* Copyright (C) 2021 - Gatuno
|
||||
*
|
||||
* NetworkInador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NetworkInador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NetworkInador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* inclusion guard */
|
||||
#ifndef __NI_ROUTE_H__
|
||||
#define __NI_ROUTE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _NIRouteClass NIRouteClass;
|
||||
typedef struct _NIRoute NIRoute;
|
||||
typedef struct _NIRoutePrivate NIRoutePrivate;
|
||||
|
||||
/*
|
||||
* Type declaration.
|
||||
*/
|
||||
#define NI_TYPE_ROUTE (ni_route_get_type ())
|
||||
#define NI_ROUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NI_TYPE_ROUTE, NIRoute))
|
||||
#define NI_ROUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NI_TYPE_ROUTE, NIRouteClass))
|
||||
#define NI_IS_ROUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NI_TYPE_ROUTE))
|
||||
#define NI_IS_ROUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NI_TYPE_ROUTE))
|
||||
#define NI_ROUTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NI_TYPE_ROUTE, NIRouteClass))
|
||||
|
||||
GType ni_route_get_type (void);
|
||||
|
||||
struct _NIRouteClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
struct _NIRoute {
|
||||
GObject parent_instance;
|
||||
|
||||
NIRoutePrivate *priv;
|
||||
};
|
||||
|
||||
typedef struct _NIRouteNH {
|
||||
gboolean has_gw;
|
||||
struct_addr gw;
|
||||
guint out_index;
|
||||
guint weight;
|
||||
guint flags;
|
||||
} NIRouteNH;
|
||||
|
||||
/*
|
||||
* Method definitions.
|
||||
*/
|
||||
|
||||
NIRoute *ni_route_new (NIClient *ni_client, int family, int type, uint32_t table, struct_addr *dest, int prefix, unsigned char protocol, unsigned char tos, unsigned char scope, struct_addr *prefsrc, int priority, int num_nexthops, NIRouteNH *nexthops);
|
||||
|
||||
NIClient *ni_route_get_client (NIRoute *ni_route);
|
||||
guint ni_route_get_family (NIRoute *ni_route);
|
||||
guint ni_route_get_route_type (NIRoute *ni_route);
|
||||
const struct_addr *ni_route_get_dest (NIRoute *ni_route);
|
||||
guint ni_route_get_prefix (NIRoute *ni_route);
|
||||
uint32_t ni_route_get_table (NIRoute *ni_route);
|
||||
guint ni_route_get_num_nexthops (NIRoute *ni_route);
|
||||
const NIRouteNH *ni_route_get_nexthops (NIRoute *ni_route);
|
||||
gboolean ni_route_has_prefsrc (NIRoute *ni_route);
|
||||
const struct_addr *ni_route_get_prefsrc (NIRoute *ni_route);
|
||||
guint ni_route_get_priority (NIRoute *ni_route);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NI_ROUTE_H__ */
|
|
@ -482,7 +482,6 @@ static void ni_window_interface_clear_slave_click_cb (GtkWidget *widget, gpointe
|
|||
|
||||
/* Eventos que vienen del network-inador */
|
||||
static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface, NIIP *ni_ip) {
|
||||
GtkTreeIter iter;
|
||||
char buffer[256], ip[128], local[128];
|
||||
guint prefix, family, family_size;
|
||||
|
||||
|
@ -506,11 +505,9 @@ static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface,
|
|||
}
|
||||
|
||||
if (family == AF_INET) {
|
||||
gtk_list_store_insert (window_iface->priv->ipv4_store, &iter, -1);
|
||||
gtk_list_store_set (window_iface->priv->ipv4_store, &iter, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
|
||||
gtk_list_store_insert_with_values (window_iface->priv->ipv4_store, NULL, -1, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
|
||||
} else if (family == AF_INET6) {
|
||||
gtk_list_store_insert (window_iface->priv->ipv6_store, &iter, -1);
|
||||
gtk_list_store_set (window_iface->priv->ipv6_store, &iter, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
|
||||
gtk_list_store_insert_with_values (window_iface->priv->ipv6_store, NULL, -1, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,14 +686,12 @@ static void ni_window_interface_removed_from_bridge_cb (NIInterface *ni_interfac
|
|||
|
||||
static void ni_window_interface_added_to_bridge_cb (NIInterface *ni_interface, guint new_master, gpointer data) {
|
||||
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
|
||||
GtkTreeIter iter;
|
||||
guint our_index;
|
||||
|
||||
our_index = ni_interface_get_index (window_iface->priv->ni_interface);
|
||||
if (new_master == our_index) {
|
||||
/* Esta interfaz acaba de ser esclavizada a nuestra interfaz */
|
||||
gtk_list_store_insert (window_iface->priv->bridge_ports_store, &iter, -1);
|
||||
gtk_list_store_set (window_iface->priv->bridge_ports_store, &iter, BRIDGE_PORT_STORE_COL_IFACE_NAME, ni_interface_get_name (ni_interface), BRIDGE_PORT_STORE_COL_OBJECT, ni_interface, -1);
|
||||
gtk_list_store_insert_with_values (window_iface->priv->bridge_ports_store, NULL, -1, BRIDGE_PORT_STORE_COL_IFACE_NAME, ni_interface_get_name (ni_interface), BRIDGE_PORT_STORE_COL_OBJECT, ni_interface, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,7 +709,6 @@ static void ni_window_interface_removed_from_bridge_cb (NIInterface *ni_interfac
|
|||
static void ni_window_interface_new_interface_cb (NIClient *ni_client, NIInterface *ni_interface, gpointer data) {
|
||||
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
|
||||
guint our_index, master_other;
|
||||
GtkTreeIter iter;
|
||||
|
||||
our_index = ni_interface_get_index (window_iface->priv->ni_interface);
|
||||
|
||||
|
@ -725,8 +719,7 @@ static void ni_window_interface_new_interface_cb (NIClient *ni_client, NIInterfa
|
|||
master_other = ni_interface_get_master (ni_interface);
|
||||
if (master_other == our_index) {
|
||||
/* Esta interfaz está esclavizada a nuestra interfaz */
|
||||
gtk_list_store_insert (window_iface->priv->bridge_ports_store, &iter, -1);
|
||||
gtk_list_store_set (window_iface->priv->bridge_ports_store, &iter, BRIDGE_PORT_STORE_COL_IFACE_NAME, ni_interface_get_name (ni_interface), BRIDGE_PORT_STORE_COL_OBJECT, ni_interface, -1);
|
||||
gtk_list_store_insert_with_values (window_iface->priv->bridge_ports_store, NULL, -1, BRIDGE_PORT_STORE_COL_IFACE_NAME, ni_interface_get_name (ni_interface), BRIDGE_PORT_STORE_COL_OBJECT, ni_interface, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,12 +896,21 @@ static void ni_window_interface_constructed (GObject *obj) {
|
|||
static void ni_window_interface_dispose (GObject *obj) {
|
||||
NIWindowInterface *window_iface;
|
||||
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
|
||||
NIClient *ni_client;
|
||||
|
||||
window_iface = NI_WINDOW_INTERFACE (obj);
|
||||
|
||||
g_object_unref (window_iface->priv->ni_interface);
|
||||
window_iface->priv->ni_interface = NULL;
|
||||
|
||||
/* Desconectar todos los manejadores de señal del ni_client */
|
||||
if (window_iface->priv->ni_interface != NULL) {
|
||||
ni_client = ni_interface_get_client (window_iface->priv->ni_interface);
|
||||
|
||||
g_signal_handlers_disconnect_by_data (window_iface->priv->ni_interface, window_iface);
|
||||
g_signal_handlers_disconnect_by_data (ni_client, window_iface);
|
||||
}
|
||||
|
||||
parent_class->dispose (obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* ni-window-route.c
|
||||
* This file is part of Network Inador
|
||||
*
|
||||
* Copyright (C) 2022 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network Inador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network Inador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Network Inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "ni-window-route.h"
|
||||
|
||||
#include "ni-client.h"
|
||||
#include "ni-route.h"
|
||||
#include "ni-interface.h"
|
||||
|
||||
struct _NIWindowRoutePrivate {
|
||||
NIClient *ni_client;
|
||||
|
||||
int family;
|
||||
|
||||
uint32_t table_filter;
|
||||
GtkWidget *vbox, *tree_routes;
|
||||
GtkListStore *routes_store;
|
||||
GtkTreeModel *routes_filtered;
|
||||
GtkListStore *tables_store;
|
||||
|
||||
GtkWidget *del_route_button;
|
||||
GtkWidget *combo_tables;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_NI_CLIENT = 1,
|
||||
|
||||
PROP_NI_FAMILY,
|
||||
|
||||
PROP_NI_TABLE_FILTER,
|
||||
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
enum {
|
||||
ROUTE_STORE_TABLE,
|
||||
ROUTE_STORE_COL_DST_GW,
|
||||
|
||||
ROUTE_STORE_COL_METRIC,
|
||||
|
||||
ROUTE_STORE_COL_PREFSRC,
|
||||
|
||||
// TODO: Agregar tipo de protocolo, tos, scope
|
||||
ROUTE_STORE_COL_OBJECT,
|
||||
|
||||
NUM_ROUTE_STORE_COLS
|
||||
};
|
||||
|
||||
enum {
|
||||
TABLE_STORE_TABLE,
|
||||
TABLE_STORE_NAME,
|
||||
|
||||
TABLE_STORE_IS_NEW,
|
||||
|
||||
NUM_TABLE_STORE_COLS
|
||||
};
|
||||
|
||||
struct _NIWindowRouteSearchTable {
|
||||
gboolean found;
|
||||
uint32_t tabla;
|
||||
GtkTreeIter iter;
|
||||
};
|
||||
|
||||
struct _NIWindowRouteSearchRoute {
|
||||
gboolean found;
|
||||
void *obj;
|
||||
GtkTreeIter iter;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (NIWindowRoute, ni_window_route, GTK_TYPE_WINDOW)
|
||||
|
||||
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
static gboolean ni_window_route_foreach_tables_search_id (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
|
||||
static gboolean ni_window_route_foreach_routes_search_route (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
|
||||
static void ni_window_interface_new_ip_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data);
|
||||
static void ni_window_interface_delete_ip_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data);
|
||||
|
||||
static void ni_window_route_updated_route_cb (NIRoute *ni_route, gpointer data) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||
struct _NIWindowRouteSearchRoute for_search;
|
||||
char buffer_ip[256];
|
||||
guint priority;
|
||||
const struct_addr *dest;
|
||||
int family;
|
||||
|
||||
family = ni_route_get_family (ni_route);
|
||||
|
||||
/* Preparar el pref-src, si lo tiene */
|
||||
buffer_ip[0] = 0;
|
||||
if (ni_route_has_prefsrc (ni_route)) {
|
||||
dest = ni_route_get_prefsrc (ni_route);
|
||||
|
||||
inet_ntop (family, dest, buffer_ip, sizeof (buffer_ip));
|
||||
}
|
||||
|
||||
priority = ni_route_get_priority (ni_route);
|
||||
|
||||
for_search.found = FALSE;
|
||||
for_search.obj = ni_route;
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (window_route->priv->routes_store), ni_window_route_foreach_routes_search_route, &for_search);
|
||||
|
||||
if (for_search.found == TRUE) {
|
||||
/* Tengo fila, actualizar los valores */
|
||||
gtk_list_store_set (window_route->priv->routes_store, &for_search.iter, ROUTE_STORE_COL_METRIC, priority, ROUTE_STORE_COL_PREFSRC, buffer_ip, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_window_route_route_added_cb (NIWindowRoute *window_route, NIRoute *ni_route) {
|
||||
int family, prefix;
|
||||
char buffer_ip[256], buffer[512];
|
||||
const struct_addr *dest;
|
||||
uint32_t table;
|
||||
guint priority;
|
||||
struct _NIWindowRouteSearchTable for_search;
|
||||
|
||||
family = ni_route_get_family (ni_route);
|
||||
dest = ni_route_get_dest (ni_route);
|
||||
prefix = ni_route_get_prefix (ni_route);
|
||||
table = ni_route_get_table (ni_route);
|
||||
priority = ni_route_get_priority (ni_route);
|
||||
|
||||
/* Preparar el dest-gw */
|
||||
inet_ntop (family, dest, buffer_ip, sizeof (buffer_ip));
|
||||
if (family == AF_INET && prefix == 32) {
|
||||
snprintf (buffer, sizeof (buffer), "%s", buffer_ip);
|
||||
} else if (family == AF_INET6 && prefix == 128) {
|
||||
snprintf (buffer, sizeof (buffer), "%s", buffer_ip);
|
||||
} else {
|
||||
snprintf (buffer, sizeof (buffer), "%s/%i", buffer_ip, prefix);
|
||||
}
|
||||
|
||||
/* Preparar el pref-src, si lo tiene */
|
||||
buffer_ip[0] = 0;
|
||||
if (ni_route_has_prefsrc (ni_route)) {
|
||||
dest = ni_route_get_prefsrc (ni_route);
|
||||
|
||||
inet_ntop (family, dest, buffer_ip, sizeof (buffer_ip));
|
||||
}
|
||||
|
||||
/* Revisar que la tabla exista, si la tabla no existe, la creamos en el menú de la lista de tablas */
|
||||
for_search.found = FALSE;
|
||||
for_search.tabla = table;
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (window_route->priv->tables_store), ni_window_route_foreach_tables_search_id, &for_search);
|
||||
|
||||
if (for_search.found == FALSE) {
|
||||
/* Insertar el valor en el list store de las tablas */
|
||||
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, 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);
|
||||
}
|
||||
|
||||
/* Función para renderizar la tabla y el nombre con guion separado */
|
||||
void ni_window_route_cell_renderer_table_id (GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) {
|
||||
uint32_t tabla;
|
||||
const gchar *name;
|
||||
gboolean new;
|
||||
char buffer[1024];
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, TABLE_STORE_TABLE, &tabla, TABLE_STORE_NAME, &name, TABLE_STORE_IS_NEW, &new, -1);
|
||||
|
||||
if (new == FALSE) {
|
||||
if (name == NULL) {
|
||||
g_snprintf (buffer, sizeof (buffer), "%i - (Sin nombre)", tabla);
|
||||
} else {
|
||||
g_snprintf (buffer, sizeof (buffer), "%i - %s", tabla, name);
|
||||
}
|
||||
g_object_set (cell, "text", buffer, NULL);
|
||||
} else {
|
||||
g_object_set (cell, "text", "Nueva tabla...", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Función para renderizar la gateway */
|
||||
void ni_window_route_cell_renderer_gw_oiface (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) {
|
||||
NIRoute *ni_route;
|
||||
NIClient *ni_client;
|
||||
NIInterface *ni_interface;
|
||||
int family;
|
||||
char buffer_ip[256], buffer[8192];
|
||||
int buffer_len;
|
||||
int g, num_nexthops;
|
||||
const NIRouteNH *nexthops;
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, ROUTE_STORE_COL_OBJECT, &ni_route, -1);
|
||||
|
||||
family = ni_route_get_family (ni_route);
|
||||
|
||||
ni_client = ni_route_get_client (ni_route);
|
||||
num_nexthops = ni_route_get_num_nexthops (ni_route);
|
||||
nexthops = ni_route_get_nexthops (ni_route);
|
||||
buffer_len = 0;
|
||||
for (g = 0; g < num_nexthops; g++) {
|
||||
if (g != 0) {
|
||||
/* Anexar la coma, */
|
||||
buffer_len += g_snprintf (&buffer[buffer_len], sizeof (buffer) - buffer_len, ", ");
|
||||
}
|
||||
|
||||
if (nexthops[g].has_gw) {
|
||||
inet_ntop (family, &nexthops[g].gw, buffer_ip, sizeof (buffer_ip));
|
||||
|
||||
buffer_len += g_snprintf (&buffer[buffer_len], sizeof (buffer) - buffer_len, "%s ", buffer_ip);
|
||||
}
|
||||
|
||||
ni_interface = ni_client_get_interface_by_index (ni_client, nexthops[g].out_index);
|
||||
if (ni_interface == NULL) {
|
||||
buffer_len += g_snprintf (&buffer[buffer_len], sizeof (buffer) - buffer_len, "[¿?]");
|
||||
} else {
|
||||
buffer_len += g_snprintf (&buffer[buffer_len], sizeof (buffer) - buffer_len, "[%s]", ni_interface_get_name (ni_interface));
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set (cell, "text", buffer, NULL);
|
||||
}
|
||||
|
||||
static gboolean ni_window_route_delete_event (GtkWidget *widget, GdkEventAny *event) {
|
||||
return gtk_widget_hide_on_delete (widget);
|
||||
}
|
||||
|
||||
static void ni_window_route_constructed (GObject *obj) {
|
||||
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (obj);
|
||||
const GList *route_list = NULL, *g;
|
||||
NIRoute *ni_route;
|
||||
|
||||
parent_class->constructed (obj);
|
||||
|
||||
if (window_route->priv->ni_client == NULL) return;
|
||||
|
||||
/* Cambiar el título
|
||||
name = g_strdup_printf ("Interfaz %s", ni_interface_get_name (window_iface->priv->ni_interface));
|
||||
gtk_window_set_title (GTK_WINDOW (obj), name);
|
||||
g_free (name);*/
|
||||
|
||||
/* Conectar la señal de ruta agregada y ruta eliminada */
|
||||
g_signal_connect (window_route->priv->ni_client, "new-route", G_CALLBACK (ni_window_interface_new_ip_cb), window_route);
|
||||
g_signal_connect (window_route->priv->ni_client, "delete-route", G_CALLBACK (ni_window_interface_delete_ip_cb), window_route);
|
||||
|
||||
/* Recorrer las rutas, y procesar la información */
|
||||
if (window_route->priv->family == AF_INET) {
|
||||
route_list = ni_client_get_routes_v4 (window_route->priv->ni_client);
|
||||
} else if (window_route->priv->family == AF_INET6) {
|
||||
route_list = ni_client_get_routes_v6 (window_route->priv->ni_client);
|
||||
}
|
||||
|
||||
for (g = route_list; g != NULL; g = g->next) {
|
||||
ni_route = (NIRoute *) g->data;
|
||||
|
||||
ni_window_route_route_added_cb (window_route, ni_route);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_window_route_dispose (GObject *obj) {
|
||||
NIWindowRoute *window_route;
|
||||
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
|
||||
|
||||
window_route = NI_WINDOW_ROUTE (obj);
|
||||
|
||||
g_object_unref (window_route->priv->ni_client);
|
||||
window_route->priv->ni_client = NULL;
|
||||
|
||||
parent_class->dispose (obj);
|
||||
}
|
||||
|
||||
static void ni_window_route_change_filter_table_id (NIWindowRoute *window_route, uint32_t new_table) {
|
||||
/* Primero, guardar el valor nuevo */
|
||||
window_route->priv->table_filter = new_table;
|
||||
|
||||
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (window_route->priv->routes_filtered));
|
||||
|
||||
/* Notificar el cambio de propiedad */
|
||||
g_object_notify_by_pspec (G_OBJECT (window_route), obj_properties[PROP_NI_TABLE_FILTER]);
|
||||
}
|
||||
|
||||
static gboolean ni_window_route_foreach_tables_search_id (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
|
||||
struct _NIWindowRouteSearchTable *for_search = (struct _NIWindowRouteSearchTable *) data;
|
||||
uint32_t tabla;
|
||||
gboolean is_new;
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, TABLE_STORE_TABLE, &tabla, TABLE_STORE_IS_NEW, &is_new, -1);
|
||||
if (is_new) return FALSE;
|
||||
|
||||
if (tabla == for_search->tabla) {
|
||||
for_search->found = TRUE;
|
||||
for_search->iter = *iter;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean ni_window_route_foreach_routes_search_route (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
|
||||
struct _NIWindowRouteSearchRoute *for_search = (struct _NIWindowRouteSearchRoute *) data;
|
||||
void *route;
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, ROUTE_STORE_COL_OBJECT, &route, -1);
|
||||
|
||||
if (route == for_search->obj) {
|
||||
for_search->found = TRUE;
|
||||
for_search->iter = *iter;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint ni_window_route_sort_tables_func (GtkTreeModel *tree_model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) {
|
||||
uint32_t tabla_a, tabla_b;
|
||||
gboolean is_new_a, is_new_b;
|
||||
|
||||
gtk_tree_model_get (tree_model, a, TABLE_STORE_TABLE, &tabla_a, TABLE_STORE_IS_NEW, &is_new_a, -1);
|
||||
gtk_tree_model_get (tree_model, b, TABLE_STORE_TABLE, &tabla_b, TABLE_STORE_IS_NEW, &is_new_b, -1);
|
||||
|
||||
if (is_new_a) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_new_b) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tabla_a - tabla_b;
|
||||
}
|
||||
|
||||
static void ni_window_route_changed_combo_table_cb (GtkWidget *combo, gpointer data) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||
GtkTreeIter iter;
|
||||
uint32_t tabla;
|
||||
gboolean is_new;
|
||||
struct _NIWindowRouteSearchTable for_search;
|
||||
|
||||
gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (window_route->priv->tables_store), &iter, TABLE_STORE_TABLE, &tabla, TABLE_STORE_IS_NEW, &is_new, -1);
|
||||
|
||||
if (is_new) {
|
||||
/* TODO: Presentar el cuadro de dialogo de creación de nueva tabla */
|
||||
|
||||
/* Localizar el valor previo de la tabla, para regresar el combo */
|
||||
for_search.found = FALSE;
|
||||
for_search.tabla = window_route->priv->table_filter;
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (window_route->priv->tables_store), ni_window_route_foreach_tables_search_id, &for_search);
|
||||
if (for_search.found) {
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &for_search.iter);
|
||||
} else {
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), NULL);
|
||||
}
|
||||
} else {
|
||||
/* Aplicar el nuevo filtro */
|
||||
ni_window_route_change_filter_table_id (window_route, tabla);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean ni_window_route_tree_filter_routes_func (GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||
uint32_t tabla;
|
||||
|
||||
if (window_route->priv->table_filter == 0) return TRUE;
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, ROUTE_STORE_TABLE, &tabla, -1);
|
||||
if (tabla == window_route->priv->table_filter) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ni_window_interface_new_ip_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||
|
||||
ni_window_route_route_added_cb (window_route, ni_route);
|
||||
}
|
||||
|
||||
static void ni_window_interface_delete_ip_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||
struct _NIWindowRouteSearchRoute for_search;
|
||||
|
||||
for_search.found = FALSE;
|
||||
for_search.obj = ni_route;
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (window_route->priv->routes_store), ni_window_route_foreach_routes_search_route, &for_search);
|
||||
|
||||
if (for_search.found == TRUE) {
|
||||
/* Tengo fila, actualizar los valores */
|
||||
gtk_list_store_remove (window_route->priv->routes_store, &for_search.iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_window_route_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (object);
|
||||
g_return_if_fail (NI_IS_WINDOW_ROUTE (object));
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NI_CLIENT:
|
||||
window_route->priv->ni_client = NI_CLIENT (g_value_get_object (value));
|
||||
g_object_ref (window_route->priv->ni_client);
|
||||
break;
|
||||
case PROP_NI_FAMILY:
|
||||
window_route->priv->family = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_NI_TABLE_FILTER:
|
||||
ni_window_route_change_filter_table_id (window_route, g_value_get_uint (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_window_route_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (object);
|
||||
g_return_if_fail (NI_IS_WINDOW_ROUTE (object));
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NI_CLIENT:
|
||||
g_value_set_object (value, window_route->priv->ni_client);
|
||||
break;
|
||||
case PROP_NI_FAMILY:
|
||||
g_value_set_uint (value, window_route->priv->family);
|
||||
break;
|
||||
case PROP_NI_TABLE_FILTER:
|
||||
g_value_set_uint (value, window_route->priv->table_filter);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void ni_window_route_class_init (NIWindowRouteClass *klass) {
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->set_property = ni_window_route_set_property;
|
||||
object_class->get_property = ni_window_route_get_property;
|
||||
object_class->constructed = ni_window_route_constructed;
|
||||
object_class->dispose = ni_window_route_dispose;
|
||||
|
||||
widget_class->delete_event = ni_window_route_delete_event;
|
||||
|
||||
obj_properties[PROP_NI_CLIENT] = g_param_spec_object (
|
||||
"ni-client",
|
||||
"Network Inador Client",
|
||||
"The client object",
|
||||
NI_TYPE_CLIENT,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
|
||||
obj_properties[PROP_NI_FAMILY] = g_param_spec_uint (
|
||||
"family",
|
||||
"Family",
|
||||
"The routing family.",
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
|
||||
obj_properties[PROP_NI_TABLE_FILTER] = g_param_spec_uint (
|
||||
"table-filter",
|
||||
"Tabla filtrada",
|
||||
"Tabla filtrada.",
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
|
||||
}
|
||||
|
||||
GtkWidget *ni_window_route_create_tree_for_routes (GtkTreeModel *store, GtkWidget **tree) {
|
||||
GtkWidget *scrolled;
|
||||
GtkAdjustment *h, *v;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
*tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
|
||||
|
||||
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (*tree), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
|
||||
h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree));
|
||||
v = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree));
|
||||
|
||||
scrolled = gtk_scrolled_window_new (h, v);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Destino", renderer, "text", ROUTE_STORE_COL_DST_GW, NULL);
|
||||
gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||
gtk_tree_view_column_set_title (GTK_TREE_VIEW_COLUMN (column), "Puerta de enlace");
|
||||
gtk_tree_view_column_pack_start (GTK_TREE_VIEW_COLUMN (column), renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (column), renderer, ni_window_route_cell_renderer_gw_oiface, NULL, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Métrica", renderer, "text", ROUTE_STORE_COL_METRIC, NULL);
|
||||
gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Dir. Origen", renderer, "text", ROUTE_STORE_COL_PREFSRC, 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);
|
||||
|
||||
return scrolled;
|
||||
}
|
||||
|
||||
static void ni_window_route_init (NIWindowRoute *window_route) {
|
||||
NIWindowRoutePrivate *priv = ni_window_route_get_instance_private (window_route);
|
||||
window_route->priv = priv;
|
||||
GtkWindow *window = GTK_WINDOW (window_route);
|
||||
GtkWidget *hbox, *label, *button, *image;
|
||||
GtkWidget *vbox, *scrolled, *vbox2;
|
||||
GtkTreeSelection *selection;
|
||||
GtkSizeGroup *size_l;
|
||||
GtkTreeIter iter;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
/* initialize all public and private members to reasonable default values.
|
||||
* They are all automatically initialized to 0 to begin with. */
|
||||
priv->ni_client = NULL;
|
||||
priv->family = 0;
|
||||
gtk_window_set_title (window, "Tabla de ruteo");
|
||||
|
||||
priv->vbox = vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_container_add (GTK_CONTAINER (window), priv->vbox);
|
||||
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 5);
|
||||
|
||||
label = gtk_label_new ("Seleccione tabla de ruteo:");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
|
||||
|
||||
priv->tables_store = gtk_list_store_new (NUM_TABLE_STORE_COLS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
||||
gtk_list_store_insert_with_values (priv->tables_store, &iter, -1, TABLE_STORE_TABLE, 0, TABLE_STORE_NAME, "Todas", TABLE_STORE_IS_NEW, FALSE, -1);
|
||||
gtk_list_store_insert_with_values (priv->tables_store, NULL, -1, TABLE_STORE_TABLE, 254, TABLE_STORE_NAME, "Main", TABLE_STORE_IS_NEW, FALSE, -1);
|
||||
gtk_list_store_insert_with_values (priv->tables_store, NULL, -1, TABLE_STORE_TABLE, 255, TABLE_STORE_NAME, "Local", TABLE_STORE_IS_NEW, FALSE, -1);
|
||||
gtk_list_store_insert_with_values (priv->tables_store, NULL, -1, TABLE_STORE_TABLE, 0, TABLE_STORE_NAME, NULL, TABLE_STORE_IS_NEW, TRUE, -1);
|
||||
|
||||
/* Mantener ordenadas las tablas */
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (priv->tables_store), ni_window_route_sort_tables_func, NULL, NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->tables_store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
|
||||
|
||||
priv->combo_tables = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->tables_store));
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo_tables), renderer, TRUE);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->combo_tables), renderer, ni_window_route_cell_renderer_table_id, NULL, NULL);
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_tables), &iter);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), priv->combo_tables, FALSE, FALSE, 0);
|
||||
g_signal_connect (priv->combo_tables, "changed", G_CALLBACK (ni_window_route_changed_combo_table_cb), window_route);
|
||||
|
||||
/* Preparar el list store */
|
||||
priv->routes_store = gtk_list_store_new (NUM_ROUTE_STORE_COLS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_POINTER);
|
||||
priv->routes_filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->routes_store), NULL);
|
||||
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->routes_filtered), ni_window_route_tree_filter_routes_func, window_route, NULL);
|
||||
|
||||
label = gtk_label_new ("Rutas:");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
|
||||
|
||||
scrolled = ni_window_route_create_tree_for_routes (priv->routes_filtered, &priv->tree_routes);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0);
|
||||
|
||||
/* Botonera del tree view */
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_LARGE_TOOLBAR);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
|
||||
//g_signal_connect (button, "clicked", G_CALLBACK (ni_window_interface_addr_v6_button_add_cb), window_iface);
|
||||
|
||||
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);
|
||||
//g_signal_connect (priv->del_route_button, "clicked", G_CALLBACK (ni_window_interface_addr_v6_button_del_cb), window_iface);
|
||||
gtk_widget_set_sensitive (priv->del_route_button, FALSE);
|
||||
|
||||
/* Conectar la señal de cambio de selección del tree view */
|
||||
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);
|
||||
|
||||
/* La botonera inferior */
|
||||
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
|
||||
gtk_box_pack_start (GTK_BOX (priv->vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* El boton de cerrar */
|
||||
button = gtk_button_new_with_label ("Cerrar");
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_hide_on_delete), window);
|
||||
image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_BUTTON);
|
||||
gtk_button_set_image (GTK_BUTTON (button), image);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
||||
|
||||
gtk_widget_show_all (priv->vbox);
|
||||
}
|
||||
|
||||
GtkWidget* ni_window_route_new (NIClient *ni_client, int family) {
|
||||
NIWindowRoute *window_route;
|
||||
|
||||
window_route = g_object_new (NI_TYPE_WINDOW_ROUTE, "type", GTK_WINDOW_TOPLEVEL, "ni-client", ni_client, "family", family, NULL);
|
||||
|
||||
return GTK_WIDGET (window_route);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* ni-window-route.h
|
||||
* This file is part of NetworkInador
|
||||
*
|
||||
* Copyright (C) 2021 - Gatuno
|
||||
*
|
||||
* NetworkInador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NetworkInador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NetworkInador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* inclusion guard */
|
||||
#ifndef __NI_WINDOW_ROUTE_H__
|
||||
#define __NI_WINDOW_ROUTE_H__
|
||||
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "ni-client.h"
|
||||
#include "ni-route.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _NIWindowRouteClass NIWindowRouteClass;
|
||||
typedef struct _NIWindowRoute NIWindowRoute;
|
||||
typedef struct _NIWindowRoutePrivate NIWindowRoutePrivate;
|
||||
|
||||
/*
|
||||
* Type declaration.
|
||||
*/
|
||||
#define NI_TYPE_WINDOW_ROUTE (ni_window_route_get_type ())
|
||||
#define NI_WINDOW_ROUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NI_TYPE_WINDOW_ROUTE, NIWindowRoute))
|
||||
#define NI_WINDOW_ROUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NI_TYPE_WINDOW_ROUTE, NIWindowRouteClass))
|
||||
#define NI_IS_WINDOW_ROUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NI_TYPE_WINDOW_ROUTE))
|
||||
#define NI_IS_WINDOW_ROUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NI_TYPE_WINDOW_ROUTE))
|
||||
#define NI_WINDOW_ROUTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NI_TYPE_WINDOW_ROUTE, NIWindowRouteClass))
|
||||
|
||||
GType ni_window_route_get_type (void);
|
||||
|
||||
struct _NIWindowRouteClass {
|
||||
GtkWindowClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
struct _NIWindowRoute {
|
||||
GtkWindow parent_instance;
|
||||
|
||||
NIWindowRoutePrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Method definitions.
|
||||
*/
|
||||
GtkWidget* ni_window_route_new (NIClient *ni_client, int family);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NI_WINDOW_ROUTE_H__ */
|
Loading…
Reference in New Issue