2021-09-04 23:32:04 -05:00
# include <gtk/gtk.h>
# include <linux/if_arp.h>
# include "ni-client.h"
# include "ni-interface.h"
# include "ni-window-interface.h"
2022-02-06 23:28:26 -06:00
# include "ni-window-route.h"
2021-09-04 23:32:04 -05:00
# include "../src/link-types.h"
enum {
COL_IFACE_OBJECT ,
COL_IFACE_INDEX ,
COL_IFACE_NAME ,
COL_IFACE_ICON ,
COL_IFACE_WINDOW ,
NUM_COLS_IFACE ,
} ;
enum {
INTERFACES_GROUP_ETHERNET ,
INTERFACES_GROUP_WIFI ,
INTERFACES_GROUP_BRIDGES ,
INTERFACES_GROUP_OTHER ,
INTERFACES_GROUP_LOOP_DUMMY ,
NUM_INTERFACES_GROUP
} ;
typedef struct {
int group_type ;
GtkWidget * vbox ;
GtkWidget * label ;
GtkWidget * iconview ;
GtkWidget * scrolled ;
GtkTreeModel * model_filter ;
} UINetworkType ;
const char * group_names [ NUM_INTERFACES_GROUP ] = {
" Redes cableadas " ,
" Redes inalámbricas " ,
" Puentes " ,
" Otros " ,
" Loopback y otros tipos "
} ;
GtkListStore * interfaces_store ;
NIClient * ni_client ;
GtkWidget * ventana ;
2021-12-28 23:16:15 -06:00
GtkWidget * main_vbox , * network_vbox ;
2021-09-04 23:32:04 -05:00
GtkWidget * empty_label = NULL ;
GHashTable * network_blocks_list ;
2021-12-28 23:16:15 -06:00
GtkWidget * create_bridge_menu ;
2022-02-06 23:28:26 -06:00
GtkWidget * route_v4_menu , * route_v6_menu ;
GtkWidget * route_v4_window = NULL , * route_v6_window = NULL ;
2021-09-04 23:32:04 -05:00
static void click_interface_cb ( GtkIconView * iconview , GtkTreePath * path , gpointer data ) {
UINetworkType * network_block = ( UINetworkType * ) data ;
GtkTreeIter iter , real_iter ;
GtkWidget * ventana ;
NIInterface * ni_interface ;
gtk_tree_model_get_iter ( GTK_TREE_MODEL ( network_block - > model_filter ) , & iter , path ) ;
gtk_tree_model_get ( GTK_TREE_MODEL ( network_block - > model_filter ) , & iter , COL_IFACE_OBJECT , & ni_interface , COL_IFACE_WINDOW , & ventana , - 1 ) ;
if ( ventana = = NULL ) {
ventana = ni_window_interface_new ( ni_interface ) ;
gtk_tree_model_filter_convert_iter_to_child_iter ( GTK_TREE_MODEL_FILTER ( network_block - > model_filter ) , & real_iter , & iter ) ;
gtk_list_store_set ( interfaces_store , & real_iter , COL_IFACE_WINDOW , ventana , - 1 ) ;
}
gtk_widget_show ( ventana ) ;
}
2022-02-06 23:28:26 -06:00
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 ) ;
}
2021-09-04 23:32:04 -05:00
int guess_interface_type ( NIInterface * ni_interface ) {
guint type ;
type = ni_interface_get_iface_type ( ni_interface ) ;
if ( type = = NI_LINK_TYPE_ETHERNET ) {
return INTERFACES_GROUP_ETHERNET ;
} else if ( type = = NI_LINK_TYPE_WIFI ) {
return INTERFACES_GROUP_WIFI ;
} else if ( type = = NI_LINK_TYPE_DUMMY | | type = = NI_LINK_TYPE_LOOPBACK ) {
return INTERFACES_GROUP_LOOP_DUMMY ;
} else if ( type = = NI_LINK_TYPE_BRIDGE ) {
return INTERFACES_GROUP_BRIDGES ;
}
return INTERFACES_GROUP_OTHER ;
}
gboolean network_block_model_filter_by_type ( GtkTreeModel * model , GtkTreeIter * iter , gpointer data ) {
NIInterface * ni_interface ;
const gchar * iface_type ;
UINetworkType * network_block = ( UINetworkType * ) data ;
gtk_tree_model_get ( model , iter , COL_IFACE_OBJECT , & ni_interface , - 1 ) ;
if ( ni_interface = = NULL ) {
return FALSE ;
}
//iface_type = ni_interface_get_iface_type (ni_interface);
if ( guess_interface_type ( ni_interface ) = = network_block - > group_type ) {
return TRUE ;
}
return FALSE ;
}
UINetworkType * create_block_list ( int type ) {
UINetworkType * network_block ;
int g , pos ;
if ( g_hash_table_size ( network_blocks_list ) = = 0 ) {
/* Eliminar la etiqueta */
gtk_widget_destroy ( empty_label ) ;
}
network_block = g_new0 ( UINetworkType , 1 ) ;
network_block - > group_type = type ;
network_block - > model_filter = gtk_tree_model_filter_new ( GTK_TREE_MODEL ( interfaces_store ) , NULL ) ;
printf ( " Para el group type: %i, el model_filter: %p \n " , type , network_block - > model_filter ) ;
gtk_tree_model_filter_set_visible_func ( GTK_TREE_MODEL_FILTER ( network_block - > model_filter ) , network_block_model_filter_by_type , network_block , NULL ) ;
network_block - > vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 5 ) ;
2021-12-28 23:16:15 -06:00
gtk_box_pack_start ( GTK_BOX ( network_vbox ) , network_block - > vbox , FALSE , FALSE , 5 ) ;
2021-09-04 23:32:04 -05:00
/* Reordenar los grupos presentes, dentro del vbox */
pos = 0 ;
for ( g = 0 ; g < NUM_INTERFACES_GROUP & & g < type ; g + + ) {
if ( g_hash_table_lookup ( network_blocks_list , GINT_TO_POINTER ( g ) ) ! = NULL ) {
pos + + ;
}
}
2021-12-28 23:16:15 -06:00
gtk_box_reorder_child ( GTK_BOX ( network_vbox ) , network_block - > vbox , pos ) ;
2021-09-04 23:32:04 -05:00
network_block - > label = gtk_label_new ( group_names [ type ] ) ;
gtk_box_pack_start ( GTK_BOX ( network_block - > vbox ) , network_block - > label , FALSE , FALSE , 0 ) ;
network_block - > iconview = gtk_icon_view_new_with_model ( network_block - > model_filter ) ;
g_signal_connect ( network_block - > iconview , " item-activated " , G_CALLBACK ( click_interface_cb ) , network_block ) ;
gtk_icon_view_set_text_column ( GTK_ICON_VIEW ( network_block - > iconview ) , COL_IFACE_NAME ) ;
gtk_icon_view_set_pixbuf_column ( GTK_ICON_VIEW ( network_block - > iconview ) , COL_IFACE_ICON ) ;
//gtk_icon_view_set_columns (GTK_ICON_VIEW (network_block->iconview), 1000);
gtk_icon_view_set_reorderable ( GTK_ICON_VIEW ( network_block - > iconview ) , FALSE ) ;
network_block - > scrolled = gtk_scrolled_window_new (
gtk_scrollable_get_hadjustment ( GTK_SCROLLABLE ( network_block - > iconview ) ) ,
gtk_scrollable_get_vadjustment ( GTK_SCROLLABLE ( network_block - > iconview ) ) ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( network_block - > scrolled ) , GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC ) ;
gtk_container_add ( GTK_CONTAINER ( network_block - > scrolled ) , network_block - > iconview ) ;
gtk_box_pack_start ( GTK_BOX ( network_block - > vbox ) , network_block - > scrolled , FALSE , FALSE , 0 ) ;
gtk_widget_show_all ( network_block - > vbox ) ;
return network_block ;
}
gboolean locate_interface_from_store ( GtkListStore * store , GtkTreeIter * iter , guint index ) {
gboolean has ;
guint index_data ;
has = gtk_tree_model_get_iter_first ( GTK_TREE_MODEL ( store ) , iter ) ;
while ( has ) {
gtk_tree_model_get ( GTK_TREE_MODEL ( interfaces_store ) , iter , COL_IFACE_INDEX , & index_data , - 1 ) ;
if ( index = = index_data ) {
return TRUE ;
}
has = gtk_tree_model_iter_next ( GTK_TREE_MODEL ( interfaces_store ) , iter ) ;
}
return FALSE ;
}
static void interface_changed_name_cb ( GObject * object , GParamSpec * sp , gpointer data ) {
NIInterface * ni_interface = NI_INTERFACE ( object ) ;
guint index ;
GtkTreeIter iter ;
index = ni_interface_get_index ( ni_interface ) ;
if ( locate_interface_from_store ( interfaces_store , & iter , index ) ) {
gtk_list_store_set ( interfaces_store , & iter , COL_IFACE_NAME , ni_interface_get_name ( ni_interface ) , - 1 ) ;
}
}
void new_interface_cb ( NIClient * ni_client , NIInterface * ni_interface , gpointer data ) {
guint index ;
UINetworkType * network_block ;
int type ;
GdkPixbuf * icon ;
GtkTreeIter iter ;
type = guess_interface_type ( ni_interface ) ;
network_block = g_hash_table_lookup ( network_blocks_list , GINT_TO_POINTER ( type ) ) ;
if ( network_block = = NULL ) {
/* El bloque está vacio, pedir crearlo */
network_block = create_block_list ( type ) ;
g_hash_table_insert ( network_blocks_list , GINT_TO_POINTER ( type ) , network_block ) ;
}
if ( type = = INTERFACES_GROUP_ETHERNET ) {
icon = gtk_icon_theme_load_icon ( gtk_icon_theme_get_default ( ) , " network-wired " , 32 , 0 , NULL ) ;
} else {
icon = gtk_icon_theme_load_icon ( gtk_icon_theme_get_default ( ) , " network-wired " , 32 , 0 , NULL ) ;
}
gtk_list_store_insert ( interfaces_store , & iter , - 1 ) ;
gtk_list_store_set ( interfaces_store , & iter , COL_IFACE_OBJECT , ni_interface , COL_IFACE_INDEX , ni_interface_get_index ( ni_interface ) , COL_IFACE_NAME , ni_interface_get_name ( ni_interface ) , COL_IFACE_ICON , icon , COL_IFACE_WINDOW , NULL , - 1 ) ;
g_signal_connect ( ni_interface , " notify::name " , G_CALLBACK ( interface_changed_name_cb ) , NULL ) ;
g_object_unref ( icon ) ;
}
void delete_interface_cb ( NIClient * ni_client , NIInterface * ni_interface , gpointer data ) {
GtkWidget * ventana ;
GtkTreeIter iter ;
if ( locate_interface_from_store ( interfaces_store , & iter , ni_interface_get_index ( ni_interface ) ) ) {
gtk_tree_model_get ( GTK_TREE_MODEL ( interfaces_store ) , & iter , COL_IFACE_WINDOW , & ventana , - 1 ) ;
/* Eliminar este objeto */
if ( ventana ! = NULL ) {
gtk_widget_destroy ( ventana ) ;
}
gtk_list_store_remove ( interfaces_store , & iter ) ;
}
}
2021-12-28 23:16:15 -06:00
void create_bridge_cb ( GtkWidget * menu_item , gpointer data ) {
static GtkWidget * dialog = NULL ;
GtkWidget * content ;
GtkWidget * label , * entry ;
guint res ;
gchar * name ;
if ( dialog ! = NULL ) {
gtk_window_present ( GTK_WINDOW ( dialog ) ) ;
return ;
}
dialog = gtk_message_dialog_new ( GTK_WINDOW ( ventana ) , GTK_DIALOG_DESTROY_WITH_PARENT , GTK_MESSAGE_QUESTION , GTK_BUTTONS_OK_CANCEL , " Nombre del nuevo bridge " ) ;
content = gtk_message_dialog_get_message_area ( GTK_MESSAGE_DIALOG ( dialog ) ) ;
entry = gtk_entry_new ( ) ;
gtk_entry_set_text ( GTK_ENTRY ( entry ) , " br0 " ) ;
gtk_box_pack_start ( GTK_BOX ( content ) , entry , FALSE , FALSE , 0 ) ;
gtk_widget_show ( entry ) ;
res = gtk_dialog_run ( GTK_DIALOG ( dialog ) ) ;
if ( res = = GTK_RESPONSE_OK ) {
name = gtk_entry_get_text ( GTK_ENTRY ( entry ) ) ;
if ( name ! = NULL & & name [ 0 ] ! = 0 ) {
ni_client_ask_create_bridge ( ni_client , name ) ;
}
}
gtk_widget_destroy ( dialog ) ;
dialog = NULL ;
}
2021-09-04 23:32:04 -05:00
void cerrar_ventana_cb ( GtkWidget * ventana , gpointer data ) {
g_object_unref ( ni_client ) ;
gtk_main_quit ( ) ;
}
int main ( int argc , char * argv [ ] ) {
gboolean connected ;
GtkWidget * label , * scrolled ;
2021-12-28 23:16:15 -06:00
GtkWidget * menu_bar , * menu , * menu_item ;
GtkWidget * icon ;
2021-09-04 23:32:04 -05:00
gtk_init ( & argc , & argv ) ;
ni_client = ni_client_new ( ) ;
connected = ni_client_connect ( ni_client ) ;
g_signal_connect ( ni_client , " new-interface " , G_CALLBACK ( new_interface_cb ) , NULL ) ;
g_signal_connect ( ni_client , " delete-interface " , G_CALLBACK ( delete_interface_cb ) , NULL ) ;
interfaces_store = gtk_list_store_new ( NUM_COLS_IFACE , G_TYPE_POINTER , G_TYPE_UINT , G_TYPE_STRING , GDK_TYPE_PIXBUF , G_TYPE_POINTER ) ;
network_blocks_list = g_hash_table_new ( g_direct_hash , g_direct_equal ) ;
ventana = gtk_window_new ( GTK_WINDOW_TOPLEVEL ) ;
gtk_window_set_title ( GTK_WINDOW ( ventana ) , " Interfaces " ) ;
gtk_window_set_default_size ( GTK_WINDOW ( ventana ) , 640 , 480 ) ;
2021-09-17 08:20:00 -05:00
g_signal_connect ( ventana , " destroy " , G_CALLBACK ( cerrar_ventana_cb ) , NULL ) ;
2021-09-04 23:32:04 -05:00
2021-12-28 23:16:15 -06:00
main_vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 5 ) ;
gtk_container_add ( GTK_CONTAINER ( ventana ) , main_vbox ) ;
menu_bar = gtk_menu_bar_new ( ) ;
gtk_box_pack_start ( GTK_BOX ( main_vbox ) , menu_bar , FALSE , FALSE , 0 ) ;
menu_item = gtk_menu_item_new_with_mnemonic ( " _Interfaces " ) ;
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 ) ;
create_bridge_menu = gtk_image_menu_item_new_with_mnemonic ( " Crear _bridge " ) ;
if ( connected = = FALSE ) {
gtk_widget_set_sensitive ( create_bridge_menu , FALSE ) ;
}
icon = gtk_image_new_from_icon_name ( " list-add " , GTK_ICON_SIZE_MENU ) ;
gtk_image_menu_item_set_image ( GTK_IMAGE_MENU_ITEM ( create_bridge_menu ) , icon ) ;
gtk_menu_shell_append ( GTK_MENU_SHELL ( menu ) , create_bridge_menu ) ;
gtk_widget_show_all ( create_bridge_menu ) ;
g_signal_connect ( create_bridge_menu , " activate " , G_CALLBACK ( create_bridge_cb ) , NULL ) ;
gtk_widget_show_all ( menu ) ;
2022-02-06 23:28:26 -06:00
/* 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 */
2021-09-04 23:32:04 -05:00
scrolled = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled ) , GTK_POLICY_AUTOMATIC , GTK_POLICY_NEVER ) ;
2021-12-28 23:16:15 -06:00
gtk_box_pack_start ( GTK_BOX ( main_vbox ) , scrolled , TRUE , TRUE , 0 ) ;
2021-09-04 23:32:04 -05:00
2021-12-28 23:16:15 -06:00
network_vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 0 ) ;
gtk_widget_set_size_request ( network_vbox , 260 , - 1 ) ;
2021-09-04 23:32:04 -05:00
2021-12-28 23:16:15 -06:00
gtk_container_add ( GTK_CONTAINER ( scrolled ) , network_vbox ) ;
2021-09-04 23:32:04 -05:00
if ( connected = = FALSE ) {
empty_label = gtk_label_new ( " El servicio del network inador no está corriendo \n " ) ;
} else {
empty_label = gtk_label_new ( " Recuperando información... \n " ) ;
}
2021-12-28 23:16:15 -06:00
gtk_box_pack_start ( GTK_BOX ( network_vbox ) , empty_label , TRUE , TRUE , 0 ) ;
2021-09-04 23:32:04 -05:00
gtk_widget_show_all ( ventana ) ;
gtk_main ( ) ;
return 0 ;
}