Agrego rutas en el cliente gtk.

master
Félix Arreola Rodríguez 2022-02-06 23:28:26 -06:00
parent d1a75017b6
commit 88bec9eb0d
10 changed files with 1577 additions and 16 deletions

View File

@ -13,6 +13,8 @@ inador_gtk_client_SOURCES = main.c \
ni-ip-add-dialog.c ni-ip-add-dialog.h \ ni-ip-add-dialog.c ni-ip-add-dialog.h \
ni-interface-filter.c ni-interface-filter.h \ ni-interface-filter.c ni-interface-filter.h \
ni-interface-chooser-dialog.c ni-interface-chooser-dialog.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) $(BUILT_SOURCES)
#inador_gtk_client_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) #inador_gtk_client_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)

View File

@ -5,6 +5,8 @@
#include "ni-client.h" #include "ni-client.h"
#include "ni-interface.h" #include "ni-interface.h"
#include "ni-window-interface.h" #include "ni-window-interface.h"
#include "ni-window-route.h"
#include "../src/link-types.h" #include "../src/link-types.h"
enum { enum {
@ -54,6 +56,8 @@ GtkWidget *main_vbox, *network_vbox;
GtkWidget *empty_label = NULL; GtkWidget *empty_label = NULL;
GHashTable *network_blocks_list; GHashTable *network_blocks_list;
GtkWidget *create_bridge_menu; 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) { static void click_interface_cb (GtkIconView *iconview, GtkTreePath *path, gpointer data) {
UINetworkType *network_block = (UINetworkType *) data; UINetworkType *network_block = (UINetworkType *) data;
@ -74,6 +78,22 @@ static void click_interface_cb (GtkIconView *iconview, GtkTreePath *path, gpoint
gtk_widget_show (ventana); 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) { int guess_interface_type (NIInterface *ni_interface) {
guint type; guint type;
@ -321,6 +341,32 @@ int main (int argc, char *argv[]) {
gtk_widget_show_all (menu); 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); scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);

View File

@ -34,6 +34,8 @@
#include "ni-client.h" #include "ni-client.h"
#include "ni-interface.h" #include "ni-interface.h"
#include "ni-marshal.h" #include "ni-marshal.h"
#include "ni-route.h"
#include "../src/network-inador-manager.h" #include "../src/network-inador-manager.h"
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" #define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
@ -50,6 +52,8 @@ struct _NIClientPrivate {
gchar *socket_path; gchar *socket_path;
GHashTable *interfaces; GHashTable *interfaces;
GList *routes_v4, *routes_v6;
guint source; guint source;
guint events; guint events;
}; };
@ -66,9 +70,11 @@ enum {
DATA_READ, DATA_READ,
NEW_INTERFACE, NEW_INTERFACE,
DELETE_INTERFACE, DELETE_INTERFACE,
NEW_ROUTE,
DELETE_ROUTE,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -158,13 +164,36 @@ static void ni_client_class_init (NIClientClass *klass) {
1, 1,
NI_TYPE_INTERFACE); 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->data_response = ni_client_data_read;
klass->new_interface = NULL; klass->new_interface = NULL;
klass->delete_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) { static void ni_client_process_interface_response (NIClient *ni_client, gpointer data, guint size) {
printf ("Interface response\n");
NIInterface *ni_interface; NIInterface *ni_interface;
unsigned char *buffer = (unsigned char *) data; 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); 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) { static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint size) {
unsigned char *buffer = (unsigned char *) data; unsigned char *buffer = (unsigned char *) data;
uint32_t index; 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 */ /* Dejar pasar el evento para que la propia interfaz lo procese */
return FALSE; return FALSE;
break; 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) { } else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) {
switch (buffer[1]) { 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: case NET_INADOR_RESPONSE_DHCP_STATUS:
memcpy (&index, &buffer[2], 4); 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)); ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index));
if (ni_interface == NULL) { if (ni_interface == NULL) {
/* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */ /* 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 */ /* Dejar pasar el evento para que la propia interfaz lo procese */
return FALSE; return FALSE;
break; 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->client_socket = -1;
priv->socket_path = NULL; priv->socket_path = NULL;
priv->routes_v4 = NULL;
priv->routes_v6 = NULL;
priv->source = 0; 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); 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); 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) { 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]; unsigned char buffer[80];
uint32_t index; 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)); 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) { gboolean ni_client_connect (NIClient *ni_client) {
int s, ret; int s, ret;
struct sockaddr_un path_dest; struct sockaddr_un path_dest;
@ -749,6 +978,9 @@ gboolean ni_client_connect (NIClient *ni_client) {
/* Pedir un listado de interfaces */ /* Pedir un listado de interfaces */
ni_client_ask_interfaces (ni_client); ni_client_ask_interfaces (ni_client);
/* Pedir un listado de rutas */
ni_client_ask_routes (ni_client);
} }
void ni_client_disconnect (NIClient *ni_client) { void ni_client_disconnect (NIClient *ni_client) {

View File

@ -60,6 +60,8 @@ struct _NIClientClass {
/*gboolean (* data_response_error) (NiClient *ni_client, gpointer data, guint size);*/ /*gboolean (* data_response_error) (NiClient *ni_client, gpointer data, guint size);*/
void (*new_interface) (NIClient *ni_client, gpointer ni_interface); void (*new_interface) (NIClient *ni_client, gpointer ni_interface);
void (*delete_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 { struct _NIClient {
@ -75,7 +77,9 @@ typedef struct _NIInterface NIInterface;
*/ */
NIClient *ni_client_new (void); NIClient *ni_client_new (void);
NIClient *ni_client_new_with_path (const char *path); NIClient *ni_client_new_with_path (const char *path);
gboolean ni_client_connect (NIClient *ni_client); 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_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_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); 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_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_up_down_interface (NIClient *ni_client, NIInterface *ni_interface, gboolean is_up);
void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name); void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name);
GList *ni_client_get_list_interfaces (NIClient *ni_client); GList *ni_client_get_list_interfaces (NIClient *ni_client);
NIInterface *ni_client_get_interface_by_index (NIClient *ni_client, guint index); 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_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

@ -1,5 +1,5 @@
/* /*
* ni-interface.h * ni-ip.h
* This file is part of NetworkInador * This file is part of NetworkInador
* *
* Copyright (C) 2021 - Gatuno * Copyright (C) 2021 - Gatuno

View File

@ -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;
}

View File

@ -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__ */

View File

@ -482,7 +482,6 @@ static void ni_window_interface_clear_slave_click_cb (GtkWidget *widget, gpointe
/* Eventos que vienen del network-inador */ /* Eventos que vienen del network-inador */
static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface, NIIP *ni_ip) { static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface, NIIP *ni_ip) {
GtkTreeIter iter;
char buffer[256], ip[128], local[128]; char buffer[256], ip[128], local[128];
guint prefix, family, family_size; guint prefix, family, family_size;
@ -506,11 +505,9 @@ static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface,
} }
if (family == AF_INET) { if (family == AF_INET) {
gtk_list_store_insert (window_iface->priv->ipv4_store, &iter, -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);
gtk_list_store_set (window_iface->priv->ipv4_store, &iter, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
} else if (family == AF_INET6) { } else if (family == AF_INET6) {
gtk_list_store_insert (window_iface->priv->ipv6_store, &iter, -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);
gtk_list_store_set (window_iface->priv->ipv6_store, &iter, 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) { static void ni_window_interface_added_to_bridge_cb (NIInterface *ni_interface, guint new_master, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
GtkTreeIter iter;
guint our_index; guint our_index;
our_index = ni_interface_get_index (window_iface->priv->ni_interface); our_index = ni_interface_get_index (window_iface->priv->ni_interface);
if (new_master == our_index) { if (new_master == our_index) {
/* Esta interfaz acaba de ser esclavizada a nuestra interfaz */ /* Esta interfaz acaba de ser esclavizada a nuestra interfaz */
gtk_list_store_insert (window_iface->priv->bridge_ports_store, &iter, -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);
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);
} }
} }
@ -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) { static void ni_window_interface_new_interface_cb (NIClient *ni_client, NIInterface *ni_interface, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
guint our_index, master_other; guint our_index, master_other;
GtkTreeIter iter;
our_index = ni_interface_get_index (window_iface->priv->ni_interface); 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); master_other = ni_interface_get_master (ni_interface);
if (master_other == our_index) { if (master_other == our_index) {
/* Esta interfaz está esclavizada a nuestra interfaz */ /* Esta interfaz está esclavizada a nuestra interfaz */
gtk_list_store_insert (window_iface->priv->bridge_ports_store, &iter, -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);
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);
} }
} }
@ -903,12 +896,21 @@ static void ni_window_interface_constructed (GObject *obj) {
static void ni_window_interface_dispose (GObject *obj) { static void ni_window_interface_dispose (GObject *obj) {
NIWindowInterface *window_iface; NIWindowInterface *window_iface;
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW)); GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
NIClient *ni_client;
window_iface = NI_WINDOW_INTERFACE (obj); window_iface = NI_WINDOW_INTERFACE (obj);
g_object_unref (window_iface->priv->ni_interface); g_object_unref (window_iface->priv->ni_interface);
window_iface->priv->ni_interface = NULL; 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); parent_class->dispose (obj);
} }

View File

@ -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);
}

View File

@ -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__ */