2022-02-06 23:28:26 -06:00
/*
* 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>
2022-12-22 02:27:06 -06:00
# include <linux/rtnetlink.h>
2022-02-06 23:28:26 -06:00
# include "ni-window-route.h"
# include "ni-client.h"
# include "ni-route.h"
# include "ni-interface.h"
2022-12-21 23:15:56 -06:00
# include "ni-add-route-dialog.h"
2022-02-06 23:28:26 -06:00
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 ) ;
2022-12-21 23:15:56 -06:00
static void ni_window_interface_new_route_cb ( NIClient * ni_client , NIRoute * ni_route , gpointer data ) ;
static void ni_window_interface_delete_route_cb ( NIClient * ni_client , NIRoute * ni_route , gpointer data ) ;
2022-02-06 23:28:26 -06:00
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 ;
2022-12-22 02:27:06 -06:00
char buffer_ip [ 256 ] , buffer [ 512 ] , buffer2 [ 512 ] ;
2022-02-06 23:28:26 -06:00
const struct_addr * dest ;
uint32_t table ;
guint priority ;
struct _NIWindowRouteSearchTable for_search ;
2022-12-22 02:27:06 -06:00
int route_type ;
char * route_type_desc ;
2022-12-24 18:39:46 -06:00
int tos ;
char * route_tos_desc ;
2022-02-06 23:28:26 -06:00
family = ni_route_get_family ( ni_route ) ;
dest = ni_route_get_dest ( ni_route ) ;
2022-12-22 02:27:06 -06:00
route_type = ni_route_get_route_type ( ni_route ) ;
2022-02-06 23:28:26 -06:00
prefix = ni_route_get_prefix ( ni_route ) ;
table = ni_route_get_table ( ni_route ) ;
priority = ni_route_get_priority ( ni_route ) ;
2022-12-24 18:39:46 -06:00
tos = ni_route_get_route_tos ( ni_route ) ;
2022-02-06 23:28:26 -06:00
2022-04-20 00:55:55 -05:00
if ( family ! = window_route - > priv - > family ) {
return ;
}
2022-12-22 02:27:06 -06:00
route_type_desc = NULL ;
/* Preparar el tipo de ruta */
switch ( route_type ) {
case RTN_UNICAST :
//route_type_desc = "";
break ;
case RTN_BROADCAST :
route_type_desc = " [Broadcast] " ;
break ;
case RTN_LOCAL :
route_type_desc = " [Local] " ;
break ;
case RTN_BLACKHOLE :
route_type_desc = " [Blackhole] " ;
break ;
case RTN_MULTICAST :
route_type_desc = " [Multicast] " ;
break ;
default :
route_type_desc = " [Other...] " ;
}
2022-02-06 23:28:26 -06:00
/* 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 ) ;
}
2022-12-24 18:39:46 -06:00
2022-12-22 02:27:06 -06:00
if ( route_type_desc ! = NULL ) {
snprintf ( buffer2 , sizeof ( buffer2 ) , " %s %s " , buffer , route_type_desc ) ;
} else {
strncpy ( buffer2 , buffer , sizeof ( buffer2 ) ) ;
}
2022-02-06 23:28:26 -06:00
2022-12-24 18:39:46 -06:00
route_tos_desc = NULL ;
if ( tos ! = 0 ) {
snprintf ( buffer , sizeof ( buffer ) , " %s [TOS 0x%02x] " , buffer2 , tos ) ;
} else {
strncpy ( buffer , buffer2 , sizeof ( buffer ) ) ;
}
2022-02-06 23:28:26 -06:00
/* 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 ) ;
}
2022-12-24 18:39:46 -06:00
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 ) ;
2022-02-06 23:28:26 -06:00
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 */
2022-12-21 23:15:56 -06:00
g_signal_connect ( window_route - > priv - > ni_client , " new-route " , G_CALLBACK ( ni_window_interface_new_route_cb ) , window_route ) ;
g_signal_connect ( window_route - > priv - > ni_client , " delete-route " , G_CALLBACK ( ni_window_interface_delete_route_cb ) , window_route ) ;
2022-02-06 23:28:26 -06:00
/* 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 ;
}
2022-12-21 23:15:56 -06:00
static void ni_window_interface_new_route_cb ( NIClient * ni_client , NIRoute * ni_route , gpointer data ) {
2022-02-06 23:28:26 -06:00
NIWindowRoute * window_route = NI_WINDOW_ROUTE ( data ) ;
ni_window_route_route_added_cb ( window_route , ni_route ) ;
}
2022-12-21 23:15:56 -06:00
static void ni_window_interface_delete_route_cb ( NIClient * ni_client , NIRoute * ni_route , gpointer data ) {
2022-02-06 23:28:26 -06:00
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 ) ;
}
}
2022-12-24 18:39:46 -06:00
static void has_route_selected_cb ( GtkTreeSelection * selection , gpointer data ) {
NIWindowRoute * window_route = NI_WINDOW_ROUTE ( data ) ;
if ( gtk_tree_selection_count_selected_rows ( selection ) > 0 ) {
gtk_widget_set_sensitive ( window_route - > priv - > del_route_button , TRUE ) ;
} else {
gtk_widget_set_sensitive ( window_route - > priv - > del_route_button , FALSE ) ;
}
}
static void ni_window_route_del_route_button_add_cb ( GtkWidget * button , gpointer data ) {
NIWindowRoute * window_route = NI_WINDOW_ROUTE ( data ) ;
GtkTreeIter iter ;
GtkTreeModel * model ;
GtkTreeSelection * selection ;
NIRoute * ni_route ;
selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( window_route - > priv - > tree_routes ) ) ;
gtk_tree_selection_get_selected ( selection , & model , & iter ) ;
gtk_tree_model_get ( model , & iter , ROUTE_STORE_COL_OBJECT , & ni_route , - 1 ) ;
ni_client_ask_route_del ( window_route - > priv - > ni_client , ni_route ) ;
}
2022-12-21 23:15:56 -06:00
static void ni_window_route_add_route_button_add_cb ( GtkWidget * button , gpointer data ) {
NIWindowRoute * window_route = NI_WINDOW_ROUTE ( data ) ;
GtkWidget * dialog ;
gint response ;
NIClient * ni_client ;
GList * gws ;
2022-12-22 02:27:06 -06:00
int metrica , tabla , protocol ;
2022-12-21 23:15:56 -06:00
struct_addr destino ;
2022-12-22 02:27:06 -06:00
int prefix ;
gboolean good ;
NIRouteNH * next_hop ;
struct NIAddRouteDialogGW * next_hop_dialog ;
GList * new_list , * g ;
gboolean has_prefsrc ;
struct_addr prefsrc ;
2022-12-21 23:15:56 -06:00
dialog = ni_add_route_dialog_new ( window_route - > priv - > family ) ;
gtk_window_set_transient_for ( GTK_WINDOW ( dialog ) , GTK_WINDOW ( window_route ) ) ;
gtk_window_set_modal ( GTK_WINDOW ( dialog ) , TRUE ) ;
response = gtk_dialog_run ( GTK_DIALOG ( dialog ) ) ;
if ( response = = GTK_RESPONSE_OK ) {
/* Mandar la ip al network-inador */
2022-12-22 02:27:06 -06:00
ni_client = window_route - > priv - > ni_client ;
2022-12-21 23:15:56 -06:00
2022-12-22 02:27:06 -06:00
good = ni_add_route_dialog_get_destination ( NI_ADD_ROUTE_DIALOG ( dialog ) , & destino , & prefix ) ;
tabla = ni_add_route_dialog_get_route_table ( NI_ADD_ROUTE_DIALOG ( dialog ) ) ;
metrica = ni_add_route_dialog_get_metric ( NI_ADD_ROUTE_DIALOG ( dialog ) ) ;
protocol = ni_add_route_dialog_get_route_protocol ( NI_ADD_ROUTE_DIALOG ( dialog ) ) ;
2022-12-21 23:15:56 -06:00
2022-12-22 02:27:06 -06:00
has_prefsrc = ni_add_route_dialog_has_prefsrc_address ( NI_ADD_ROUTE_DIALOG ( dialog ) ) ;
if ( has_prefsrc ) {
ni_add_route_dialog_get_prefsrc_address ( NI_ADD_ROUTE_DIALOG ( dialog ) , & prefsrc ) ;
2022-12-21 23:15:56 -06:00
}
2022-12-22 02:27:06 -06:00
gws = ni_add_route_dialog_get_gateways ( NI_ADD_ROUTE_DIALOG ( dialog ) ) ;
2022-12-21 23:15:56 -06:00
2022-12-22 02:27:06 -06:00
/* Reacomodar los next-hop del cuadro de dialogo en las otras estructuras */
new_list = NULL ;
g = gws ;
while ( g ! = NULL ) {
next_hop_dialog = ( struct NIAddRouteDialogGW * ) g - > data ;
next_hop = ( NIRouteNH * ) g_malloc ( sizeof ( NIRouteNH ) ) ;
memset ( next_hop , 0 , sizeof ( NIRouteNH ) ) ;
next_hop - > has_gw = 1 ;
memcpy ( & next_hop - > gw , & next_hop_dialog - > addr , sizeof ( next_hop - > gw ) ) ;
next_hop - > weight = next_hop_dialog - > metric ;
new_list = g_list_append ( new_list , next_hop ) ;
g = g - > next ;
2022-12-21 23:15:56 -06:00
}
2022-12-22 02:27:06 -06:00
//void ni_client_ask_route_new (NIClient *ni_client, int family, int prefix, struct_addr *dest, int type, uint32_t tabla, int protocol, int tos, int scope, int has_prefsrc, struct_addr prefsrc, uint32_t priority, GList *gws)
ni_client_ask_route_new ( ni_client , window_route - > priv - > family , prefix , & destino , RTN_UNICAST , tabla , protocol , 0 , 0 , has_prefsrc , & prefsrc , metrica , new_list ) ;
2022-12-21 23:15:56 -06:00
2022-12-22 02:27:06 -06:00
g_list_free_full ( gws , g_free ) ;
g_list_free_full ( new_list , g_free ) ;
2022-12-21 23:15:56 -06:00
}
gtk_widget_destroy ( dialog ) ;
}
2022-02-06 23:28:26 -06:00
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 ) ) ;
2022-04-20 00:55:55 -05:00
v = gtk_scrollable_get_vadjustment ( GTK_SCROLLABLE ( * tree ) ) ;
2022-02-06 23:28:26 -06:00
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 ) ;
2022-04-20 00:55:55 -05:00
renderer = gtk_cell_renderer_text_new ( ) ;
column = gtk_tree_view_column_new_with_attributes ( " Tabla " , renderer , " text " , ROUTE_STORE_TABLE , NULL ) ;
gtk_tree_view_column_set_resizable ( GTK_TREE_VIEW_COLUMN ( column ) , TRUE ) ;
gtk_tree_view_append_column ( GTK_TREE_VIEW ( * tree ) , column ) ;
2022-02-06 23:28:26 -06:00
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 ) ;
2022-12-21 23:15:56 -06:00
/* TODO: Recuperar esta informacion de las tablas de ruteo desde el NetworkInador */
2022-02-06 23:28:26 -06:00
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 ) ;
2022-12-21 23:15:56 -06:00
g_signal_connect ( button , " clicked " , G_CALLBACK ( ni_window_route_add_route_button_add_cb ) , window_route ) ;
2022-02-06 23:28:26 -06:00
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 ) ;
2022-12-24 18:39:46 -06:00
g_signal_connect ( priv - > del_route_button , " clicked " , G_CALLBACK ( ni_window_route_del_route_button_add_cb ) , window_route ) ;
2022-02-06 23:28:26 -06:00
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 ) ) ;
2022-12-24 18:39:46 -06:00
g_signal_connect ( selection , " changed " , G_CALLBACK ( has_route_selected_cb ) , window_route ) ;
2022-02-06 23:28:26 -06:00
/* 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 ) ;
}