/* * ni-add-route-dialog.c * This file is part of Network Inador * * Copyright (C) 2021 - Gatuno * * 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 #include #include #include #include #include "ni-add-route-dialog.h" #include "ni-route.h" struct _NIAddRouteGW { NIAddRouteDialog *dialog; GtkWidget *hbox; GtkWidget *hbox_weight; GtkWidget *label_weight; GtkWidget *gw, *weight; GtkWidget *button; int pos; }; struct _NIAddRouteDialogPrivate { int family; GtkWidget *destination; GtkWidget *button_add; GtkWidget *metric; GList *gws; GtkWidget *add_gw_button; GtkSizeGroup *weight_sizer; int gw_count; GtkListStore *tables_store; GtkWidget *entry_tabla; GtkWidget *entry_protocol; GtkWidget *check_prefsrc, *entry_prefsrc; gboolean valid_main_ip, valid_gw; gboolean valid_metric; gboolean valid_route_table, valid_route_protocol; gboolean valid_prefsrc; }; enum { PROP_ROUTE_FAMILY = 1, N_PROPERTIES }; enum { COL_TABLE_ID, COL_TABLE_ID_STR, COL_TABLE_NAME, NUM_TABLE_STORE_COLS }; enum { COL_ROUTE_PROTOCOL_STR, COL_ROUTE_PROTOCOL_DESC, NUM_ROUTE_PROTOCOL_COLS }; G_DEFINE_TYPE_WITH_PRIVATE (NIAddRouteDialog, ni_add_route_dialog, GTK_TYPE_DIALOG) static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; static void ni_add_route_dialog_add_more_gw_cb (GtkWidget *button, gpointer data); static void ni_add_route_dialog_remove_gw_row_cb (GtkWidget *button, gpointer data); static gboolean ni_add_route_dialog_get_ip (NIAddRouteDialog *dialog, struct_addr *addr); static void split_ip_mask (const char *texto, gchar *ip, int ip_size, gchar *mask, int mask_size) { gchar *dup; int g, has_slash = -1; mask[0] = 0; dup = g_strdup (texto); for (g = 0; g < strlen (texto); g++) { if (texto[g] == '/' && texto[g + 1] != 0) { has_slash = g; break; } } if (has_slash >= 0) { strncpy (mask, &texto[has_slash + 1], mask_size); strncpy (ip, texto, ip_size); ip[has_slash] = 0; } else { strncpy (ip, texto, ip_size); } } static gboolean ip_valid_ipv4 (const char *ip) { struct in_addr addr; if (inet_pton (AF_INET, ip, &addr) == 0) { return FALSE; } return TRUE; } static gboolean ip_valid_ipv6 (const char *ip) { struct in6_addr addr; if (inet_pton (AF_INET6, ip, &addr) == 0) { return FALSE; } return TRUE; } static void ni_add_route_dialog_update_response (NIAddRouteDialog *dialog) { /*if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_p2p)) && dialog->priv->valid_p2p_ip == FALSE) { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); return; }*/ gboolean res; res = dialog->priv->valid_main_ip && dialog->priv->valid_gw && dialog->priv->valid_metric && dialog->priv->valid_route_table && dialog->priv->valid_route_protocol && dialog->priv->valid_prefsrc; if (res == FALSE) { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); return; } gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE); } static void ni_add_route_dialog_validate_main_ip (GtkEditable *editable, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); struct_addr addr; int prefix; dialog->priv->valid_main_ip = ni_add_route_dialog_get_destination (dialog, &addr, &prefix); if (dialog->priv->valid_main_ip == FALSE) { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (editable), GTK_ENTRY_ICON_SECONDARY, "dialog-warning"); } else { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (editable), GTK_ENTRY_ICON_SECONDARY, NULL); } ni_add_route_dialog_update_response (dialog); } static void ni_add_route_dialog_validate_gws (GtkWidget *widget, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); struct _NIAddRouteGW *gw_row; GList *g; const gchar *texto; gboolean valid; dialog->priv->valid_gw = TRUE; /* Recorrer cada caja de gateways */ g = dialog->priv->gws; while (g != NULL) { gw_row = (struct _NIAddRouteGW *) g->data; valid = FALSE; texto = gtk_entry_get_text (GTK_ENTRY (gw_row->gw)); if (dialog->priv->family == AF_INET || dialog->priv->family == AF_UNSPEC) { valid |= ip_valid_ipv4 (texto); } if (dialog->priv->family == AF_INET6 || dialog->priv->family == AF_UNSPEC) { valid |= ip_valid_ipv6 (texto); } dialog->priv->valid_gw = dialog->priv->valid_gw && valid; if (valid == FALSE) { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (gw_row->gw), GTK_ENTRY_ICON_SECONDARY, "dialog-warning"); } else { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (gw_row->gw), GTK_ENTRY_ICON_SECONDARY, NULL); } g = g->next; } ni_add_route_dialog_update_response (dialog); } static void ni_add_route_dialog_validate_metric (GtkSpinButton *spin_button, GtkScrollType scroll, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); gdouble value; value = gtk_spin_button_get_value (spin_button); if (value >= 0.0) { dialog->priv->valid_metric = TRUE; } else { dialog->priv->valid_metric = FALSE; } ni_add_route_dialog_update_response (dialog); } static void ni_add_route_dialog_validate_route_table (GtkComboBox *combo, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); const char *texto; int n, g; char endptr; GtkWidget *entry; entry = gtk_bin_get_child (GTK_BIN (combo)); texto = gtk_entry_get_text (GTK_ENTRY (entry)); n = sscanf (texto, "%i%c", &g, &endptr); if (n != 1) { dialog->priv->valid_route_table = FALSE; gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, "dialog-warning"); } else { dialog->priv->valid_route_table = TRUE; gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL); } ni_add_route_dialog_update_response (dialog); } static void ni_add_route_dialog_validate_route_protocol (GtkComboBox *combo, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); const char *texto; int n, g; char endptr; GtkWidget *entry; entry = gtk_bin_get_child (GTK_BIN (combo)); texto = gtk_entry_get_text (GTK_ENTRY (entry)); n = sscanf (texto, "%i%c", &g, &endptr); if (n != 1 || g > 255) { dialog->priv->valid_route_protocol = FALSE; gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, "dialog-warning"); } else { dialog->priv->valid_route_protocol = TRUE; gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL); } ni_add_route_dialog_update_response (dialog); } static void ni_add_route_dialog_validate_prefsrc_ip (GtkEditable *editable, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); const gchar *texto; int prefix; texto = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_prefsrc)); dialog->priv->valid_prefsrc = FALSE; if (dialog->priv->family == AF_INET || dialog->priv->family == AF_UNSPEC) { dialog->priv->valid_prefsrc = ip_valid_ipv4 (texto); if (dialog->priv->valid_prefsrc) { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (dialog->priv->entry_prefsrc), GTK_ENTRY_ICON_SECONDARY, NULL); ni_add_route_dialog_update_response (dialog); return; } } if (dialog->priv->family == AF_INET6 || dialog->priv->family == AF_UNSPEC) { dialog->priv->valid_prefsrc = ip_valid_ipv6 (texto); } if (dialog->priv->valid_prefsrc) { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (dialog->priv->entry_prefsrc), GTK_ENTRY_ICON_SECONDARY, NULL); } else { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (dialog->priv->entry_prefsrc), GTK_ENTRY_ICON_SECONDARY, "dialog-warning"); } ni_add_route_dialog_update_response (dialog); } void ni_add_route_dialog_toggle_prefsrc_cb (GtkWidget *widget, gpointer data) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { gtk_widget_set_sensitive (dialog->priv->entry_prefsrc, TRUE); ni_add_route_dialog_validate_prefsrc_ip (NULL, dialog); } else { gtk_widget_set_sensitive (dialog->priv->entry_prefsrc, FALSE); dialog->priv->valid_prefsrc = TRUE; } ni_add_route_dialog_update_response (dialog); } /* Función para renderizar la tabla y el nombre con guion separado */ void ni_add_route_dialog_cell_renderer_table_id (GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { const gchar *name; gtk_tree_model_get (tree_model, iter, COL_TABLE_NAME, &name, -1); if (name == NULL) { g_object_set (cell, "text", "(Sin nombre)", NULL); } else { g_object_set (cell, "text", name, NULL); } } static void ni_add_route_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (object); g_return_if_fail (NI_IS_ADD_ROUTE_DIALOG (object)); switch (prop_id) { case PROP_ROUTE_FAMILY: dialog->priv->family = g_value_get_uint (value); if (dialog->priv->family == AF_UNSPEC) { gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->priv->destination), "192.0.2.1/24 or 2001:db8::1/64"); } else if (dialog->priv->family == AF_INET) { gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->priv->destination), "192.0.2.1/24"); } else if (dialog->priv->family == AF_INET6) { gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->priv->destination), "2001:db8::1/64"); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ni_add_route_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (object); g_return_if_fail (NI_IS_ADD_ROUTE_DIALOG (object)); switch (prop_id) { case PROP_ROUTE_FAMILY: g_value_set_uint (value, dialog->priv->family); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ni_add_route_dialog_class_init (NIAddRouteDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass); object_class->set_property = ni_add_route_dialog_set_property; object_class->get_property = ni_add_route_dialog_get_property; obj_properties[PROP_ROUTE_FAMILY] = g_param_spec_uint ( "family", "Network family", "Network family to allow", 0, 10, AF_UNSPEC, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties); } static struct _NIAddRouteGW *ni_add_route_dialog_create_gw_row (NIAddRouteDialog *dialog) { struct _NIAddRouteGW *gw_row; GtkWidget *label, *button; gw_row = (struct _NIAddRouteGW *) malloc (sizeof (struct _NIAddRouteGW)); if (gw_row == NULL) return NULL; gw_row->dialog = dialog; gw_row->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); //gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); if (dialog->priv->gw_count > 0) { button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_BUTTON); g_signal_connect (button, "clicked", G_CALLBACK (ni_add_route_dialog_remove_gw_row_cb), gw_row); gtk_box_pack_start (GTK_BOX (gw_row->hbox), button, FALSE, FALSE, 0); } label = gtk_label_new ("Puerta de enlace:"); gtk_box_pack_start (GTK_BOX (gw_row->hbox), label, FALSE, FALSE, 0); gw_row->gw = gtk_entry_new (); g_signal_connect (gw_row->gw, "changed", G_CALLBACK (ni_add_route_dialog_validate_gws), dialog); gtk_box_pack_start (GTK_BOX (gw_row->hbox), gw_row->gw, TRUE, TRUE, 0); gw_row->hbox_weight = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); gtk_box_pack_start (GTK_BOX (gw_row->hbox), gw_row->hbox_weight, FALSE, FALSE, 5); gtk_size_group_add_widget (dialog->priv->weight_sizer, gw_row->hbox_weight); gw_row->label_weight = gtk_label_new ("Peso:"); gtk_widget_hide (gw_row->label_weight); gtk_box_pack_start (GTK_BOX (gw_row->hbox_weight), gw_row->label_weight, FALSE, FALSE, 0); gw_row->weight = gtk_spin_button_new_with_range (0.0, 9000.0, 10.0); gtk_widget_hide (gw_row->weight); gtk_box_pack_start (GTK_BOX (gw_row->hbox_weight), gw_row->weight, TRUE, TRUE, 0); return gw_row; } static void ni_add_route_dialog_remove_gw_row_cb (GtkWidget *button, gpointer data) { struct _NIAddRouteGW *gw_row = (struct _NIAddRouteGW *) data; NIAddRouteDialog *dialog = gw_row->dialog; NIAddRouteDialogPrivate *priv = dialog->priv; gtk_size_group_remove_widget (priv->weight_sizer, gw_row->hbox_weight); priv->gws = g_list_remove (priv->gws, gw_row); priv->gw_count--; gtk_widget_destroy (gw_row->hbox); free (gw_row); if (priv->gw_count == 1) { /* Volver a ocultar la caja de peso de la única fila */ gw_row = (struct _NIAddRouteGW *) priv->gws->data; gtk_widget_hide (gw_row->hbox_weight); } } static void ni_add_route_dialog_add_more_gw_cb (GtkWidget *button, gpointer data) { struct _NIAddRouteGW *gw_row; NIAddRouteDialog *dialog = NI_ADD_ROUTE_DIALOG (data); NIAddRouteDialogPrivate *priv = ni_add_route_dialog_get_instance_private (dialog); GValue gval = G_VALUE_INIT; gint pos; GtkWidget *vbox_parent, *image; /* Si es la única fila, mostrar la caja de peso */ if (priv->gw_count == 1) { gw_row = (struct _NIAddRouteGW *) priv->gws->data; gtk_widget_show (gw_row->hbox_weight); } /* Desconectar esta señal y conectarla a eliminar */ vbox_parent = gtk_widget_get_parent (priv->add_gw_button); g_value_init (&gval, G_TYPE_INT); gtk_container_child_get_property (GTK_CONTAINER (vbox_parent), priv->add_gw_button, "position", &gval); pos = g_value_get_int (&gval); /* Ahora, crear una nueva fila */ gw_row = ni_add_route_dialog_create_gw_row (dialog); if (gw_row != NULL) { gtk_box_pack_start (GTK_BOX (vbox_parent), gw_row->hbox, FALSE, FALSE, 0); gtk_box_reorder_child (GTK_BOX (vbox_parent), gw_row->hbox, pos); gtk_widget_show_all (gw_row->hbox); priv->gws = g_list_append (priv->gws, gw_row); priv->gw_count++; gtk_window_set_focus (GTK_WINDOW (dialog), gw_row->gw); } } static void ni_add_route_dialog_init (NIAddRouteDialog *dialog) { NIAddRouteDialogPrivate *priv = ni_add_route_dialog_get_instance_private (dialog); GtkWidget *image, *entry; GtkWidget *vbox, *expander; GtkWidget *container, *label, *hbox; GtkTreeIter iter; GtkCellRenderer *renderer; struct _NIAddRouteGW *gw_row; GtkListStore *store; dialog->priv = priv; priv->family = AF_UNSPEC; gtk_window_set_title (GTK_WINDOW (dialog), "Add new Route"); gtk_dialog_add_button (GTK_DIALOG (dialog), "Cancelar", GTK_RESPONSE_CANCEL); priv->button_add = gtk_dialog_add_button (GTK_DIALOG (dialog), "Agregar", GTK_RESPONSE_OK); image = gtk_image_new_from_icon_name ("list-add", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (priv->button_add), image); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); gtk_box_pack_start (GTK_BOX (container), vbox, TRUE, TRUE, 0); label = gtk_label_new ("Ingrese los detalles sobre la ruta:"); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 5); /* La caja de la ruta */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new ("Destino:"); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); priv->destination = gtk_entry_new (); gtk_entry_set_placeholder_text (GTK_ENTRY (priv->destination), "192.0.2.1/24 or 2001:db8::1/64"); g_signal_connect (priv->destination, "changed", G_CALLBACK (ni_add_route_dialog_validate_main_ip), dialog); gtk_box_pack_start (GTK_BOX (hbox), priv->destination, TRUE, TRUE, 0); priv->weight_sizer = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* Primero crear una sola fila de gateway */ priv->gw_count = 0; priv->gws = NULL; gw_row = ni_add_route_dialog_create_gw_row (dialog); if (gw_row != NULL) { gtk_box_pack_start (GTK_BOX (vbox), gw_row->hbox, FALSE, FALSE, 0); priv->gws = g_list_append (NULL, gw_row); priv->gw_count = 1; } priv->add_gw_button = gtk_button_new_with_label ("Agregar un siguiente brinco"); g_signal_connect (priv->add_gw_button, "clicked", G_CALLBACK (ni_add_route_dialog_add_more_gw_cb), dialog); image = gtk_image_new_from_icon_name ("list-add", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (priv->add_gw_button), image); gtk_box_pack_start (GTK_BOX (vbox), priv->add_gw_button, FALSE, FALSE, 0); /* La métrica */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new ("Metrica:"); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); priv->metric = gtk_spin_button_new_with_range (0.0, 9000.0, 10.0); g_signal_connect (priv->metric, "change-value", G_CALLBACK (ni_add_route_dialog_validate_metric), dialog); gtk_spin_button_set_digits (GTK_SPIN_BUTTON (priv->metric), 0); // gtk_spin_button_get_value_as_int gtk_box_pack_start (GTK_BOX (hbox), priv->metric, TRUE, TRUE, 0); // Las opciones avanzadas expander = gtk_expander_new_with_mnemonic ("_Opciones avanzadas"); gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); gtk_container_add (GTK_CONTAINER (expander), vbox); /* La tabla de ruteo */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 3); label = gtk_label_new ("Tabla de ruteo:"); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); priv->tables_store = gtk_list_store_new (NUM_TABLE_STORE_COLS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); /* TODO: Conseguir esta información desde el NetworkInador */ gtk_list_store_insert_with_values (priv->tables_store, &iter, -1, COL_TABLE_ID, 0, COL_TABLE_ID_STR, "0", COL_TABLE_NAME, "Por defecto", -1); gtk_list_store_insert_with_values (priv->tables_store, NULL, -1, COL_TABLE_ID, 254, COL_TABLE_ID_STR, "254", COL_TABLE_NAME, "Main", -1); gtk_list_store_insert_with_values (priv->tables_store, NULL, -1, COL_TABLE_ID, 255, COL_TABLE_ID_STR, "255", COL_TABLE_NAME, "Local", -1); priv->entry_tabla = gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL (priv->tables_store)); g_signal_connect (priv->entry_tabla, "changed", G_CALLBACK (ni_add_route_dialog_validate_route_table), dialog); renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->entry_tabla), renderer, TRUE); gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->entry_tabla), renderer, ni_add_route_dialog_cell_renderer_table_id, NULL, NULL); gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->entry_tabla), COL_TABLE_ID_STR); gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->entry_tabla), &iter); g_object_unref (priv->tables_store); gtk_box_pack_start (GTK_BOX (hbox), priv->entry_tabla, TRUE, TRUE, 0); /* La opción avanzada de tipo de tipo de ruta */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 3); label = gtk_label_new ("Tipo de ruta:"); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); store = gtk_list_store_new (NUM_ROUTE_PROTOCOL_COLS, G_TYPE_STRING, G_TYPE_STRING); gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_PROTOCOL_STR, "2", COL_ROUTE_PROTOCOL_DESC, "Kernel", -1); gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_PROTOCOL_STR, "3", COL_ROUTE_PROTOCOL_DESC, "Arranque (Boot)", -1); gtk_list_store_insert_with_values (store, &iter, -1, COL_ROUTE_PROTOCOL_STR, "4", COL_ROUTE_PROTOCOL_DESC, "Estática", -1); gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_PROTOCOL_STR, "16", COL_ROUTE_PROTOCOL_DESC, "Por DHCP", -1); priv->entry_protocol = gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL (store)); g_signal_connect (priv->entry_protocol, "changed", G_CALLBACK (ni_add_route_dialog_validate_route_protocol), dialog); renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->entry_protocol), renderer, TRUE); gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->entry_protocol), renderer, "text", COL_ROUTE_PROTOCOL_DESC); gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->entry_protocol), COL_ROUTE_PROTOCOL_STR); gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->entry_protocol), &iter); g_object_unref (store); gtk_box_pack_start (GTK_BOX (hbox), priv->entry_protocol, TRUE, TRUE, 0); /* Agregar pref-src en las opciones avanzadas */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 3); priv->check_prefsrc = gtk_check_button_new_with_label ("Pref src:"); g_signal_connect (priv->check_prefsrc, "toggled", G_CALLBACK (ni_add_route_dialog_toggle_prefsrc_cb), dialog); gtk_box_pack_start (GTK_BOX (hbox), priv->check_prefsrc, FALSE, FALSE, 0); priv->entry_prefsrc = gtk_entry_new (); g_signal_connect (priv->entry_prefsrc, "changed", G_CALLBACK (ni_add_route_dialog_validate_prefsrc_ip), dialog); gtk_box_pack_start (GTK_BOX (hbox), priv->entry_prefsrc, TRUE, TRUE, 0); gtk_widget_set_sensitive (priv->entry_prefsrc, FALSE); dialog->priv->valid_main_ip = FALSE; dialog->priv->valid_gw = FALSE; dialog->priv->valid_metric = TRUE; dialog->priv->valid_route_table = TRUE; dialog->priv->valid_route_protocol = TRUE; dialog->priv->valid_prefsrc = TRUE; gtk_widget_show_all (container); if (gw_row != NULL) { gtk_widget_hide (gw_row->hbox_weight); } } gboolean ni_add_route_dialog_get_destination (NIAddRouteDialog *dialog, struct_addr *addr, int *prefix) { const gchar *texto; gchar *rest, ip[128], mask[32]; int lprefix; gboolean valid; texto = gtk_entry_get_text (GTK_ENTRY (dialog->priv->destination)); split_ip_mask (texto, ip, sizeof (ip), mask, sizeof (mask)); if (mask[0] != 0) { lprefix = g_ascii_strtoll (mask, &rest, 10); if (rest[0] != 0) { return FALSE; } } if (dialog->priv->family == AF_INET || dialog->priv->family == AF_UNSPEC) { valid = ip_valid_ipv4 (ip); if (valid == FALSE || (mask[0] != 0 && (lprefix <= 0 || lprefix > 32))) { if (dialog->priv->family == AF_INET) { return FALSE; } } else { *prefix = 32; if (mask[0] != 0) { *prefix = lprefix; } inet_pton (AF_INET, ip, addr); return TRUE; } } if (dialog->priv->family == AF_INET6 || dialog->priv->family == AF_UNSPEC) { valid = ip_valid_ipv6 (ip); if (valid == FALSE || (mask[0] != 0 && (lprefix <= 0 || lprefix > 128))) { return FALSE; } else { *prefix = 128; if (mask[0] != 0) { *prefix = lprefix; } inet_pton (AF_INET6, ip, addr); } } return FALSE; } GList *ni_add_route_dialog_get_gateways (NIAddRouteDialog *dialog) { GList *result = NULL, *h; int g, ret; struct NIAddRouteDialogGW *gw; struct _NIAddRouteGW *gw_row; const char *gw_texto; for (g = 0; g < dialog->priv->gw_count; g++) { gw = (struct NIAddRouteDialogGW *) g_malloc (sizeof (struct NIAddRouteDialogGW)); h = g_list_nth (dialog->priv->gws, g); gw_row = (struct _NIAddRouteGW *) h->data; gw_texto = gtk_entry_get_text (GTK_ENTRY (gw_row->gw)); if (dialog->priv->family == AF_INET) { inet_pton (AF_INET, gw_texto, &gw->addr); } else if (dialog->priv->family == AF_INET6) { inet_pton (AF_INET6, gw_texto, &gw->addr); } else { /* UNSPEC */ ret = inet_pton (AF_INET, gw_texto, &gw->addr); if (ret == 0) { inet_pton (AF_INET6, gw_texto, &gw->addr); } } gw_texto = gtk_entry_get_text (GTK_ENTRY (gw_row->weight)); gw->metric = g_ascii_strtoll (gw_texto, NULL, 10); result = g_list_append (result, gw); } return result; } int ni_add_route_dialog_get_metric (NIAddRouteDialog *dialog) { gdouble val; val = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->priv->metric)); return (int) val; } int ni_add_route_dialog_get_route_table (NIAddRouteDialog *dialog) { const char *texto; texto = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (dialog->priv->entry_tabla)))); return g_ascii_strtoll (texto, NULL, 10); } int ni_add_route_dialog_get_route_protocol (NIAddRouteDialog *dialog) { const char *texto; texto = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (dialog->priv->entry_protocol)))); return g_ascii_strtoll (texto, NULL, 10); } gboolean ni_add_route_dialog_has_prefsrc_address (NIAddRouteDialog *dialog) { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_prefsrc)); } gboolean ni_add_route_dialog_get_prefsrc_address (NIAddRouteDialog *dialog, struct_addr *addr) { gboolean valid; const gchar *texto; if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_prefsrc)) == FALSE) { return FALSE; } texto = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_prefsrc)); if (dialog->priv->family == AF_INET || dialog->priv->family == AF_UNSPEC) { valid = ip_valid_ipv4 (texto); if (valid) { inet_pton (AF_INET, texto, addr); return TRUE; } } if (dialog->priv->family == AF_INET6 || dialog->priv->family == AF_UNSPEC) { valid = ip_valid_ipv6 (texto); if (valid) { inet_pton (AF_INET6, texto, addr); return TRUE; } } return FALSE; } GtkWidget* ni_add_route_dialog_new (int family) { NIAddRouteDialog *dialog; dialog = g_object_new (NI_TYPE_ADD_ROUTE_DIALOG, "family", family, NULL); return GTK_WIDGET (dialog); }