Ahora se pueden agregar rutas através del manager.
parent
0663160417
commit
64ca906dd7
|
@ -15,6 +15,7 @@ inador_gtk_client_SOURCES = main.c \
|
||||||
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-route.c ni-route.h \
|
||||||
ni-window-route.c ni-window-route.h \
|
ni-window-route.c ni-window-route.h \
|
||||||
|
ni-add-route-dialog.c ni-add-route-dialog.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)
|
||||||
|
|
|
@ -0,0 +1,687 @@
|
||||||
|
/*
|
||||||
|
* 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 <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#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_tipo;
|
||||||
|
gboolean valid_main_ip, valid_gw;
|
||||||
|
|
||||||
|
gboolean valid_metric;
|
||||||
|
gboolean valid_route_table, valid_route_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
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_TYPE_STR,
|
||||||
|
|
||||||
|
COL_ROUTE_TYPE_DESC,
|
||||||
|
|
||||||
|
NUM_ROUTE_TYPE_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_type;
|
||||||
|
|
||||||
|
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_type (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_type = FALSE;
|
||||||
|
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, "dialog-warning");
|
||||||
|
} else {
|
||||||
|
dialog->priv->valid_route_type = TRUE;
|
||||||
|
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TYPE_COLS, G_TYPE_STRING, G_TYPE_STRING);
|
||||||
|
gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_TYPE_STR, "2", COL_ROUTE_TYPE_DESC, "Kernel", -1);
|
||||||
|
gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_TYPE_STR, "3", COL_ROUTE_TYPE_DESC, "Arranque (Boot)", -1);
|
||||||
|
gtk_list_store_insert_with_values (store, &iter, -1, COL_ROUTE_TYPE_STR, "4", COL_ROUTE_TYPE_DESC, "Estática", -1);
|
||||||
|
gtk_list_store_insert_with_values (store, NULL, -1, COL_ROUTE_TYPE_STR, "16", COL_ROUTE_TYPE_DESC, "Por DHCP", -1);
|
||||||
|
|
||||||
|
priv->entry_tipo = gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL (store));
|
||||||
|
g_signal_connect (priv->entry_tipo, "changed", G_CALLBACK (ni_add_route_dialog_validate_route_type), dialog);
|
||||||
|
renderer = gtk_cell_renderer_text_new ();
|
||||||
|
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->entry_tipo), renderer, TRUE);
|
||||||
|
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->entry_tipo), renderer, "text", COL_ROUTE_TYPE_DESC);
|
||||||
|
gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->entry_tipo), COL_ROUTE_TYPE_STR);
|
||||||
|
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->entry_tipo), &iter);
|
||||||
|
|
||||||
|
g_object_unref (store);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), priv->entry_tipo, TRUE, TRUE, 0);
|
||||||
|
|
||||||
|
/* TODO: Agregar pref-src en las opciones avanzadas */
|
||||||
|
|
||||||
|
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_type = 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_type (NIAddRouteDialog *dialog) {
|
||||||
|
const char *texto;
|
||||||
|
|
||||||
|
texto = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (dialog->priv->entry_tipo))));
|
||||||
|
|
||||||
|
return g_ascii_strtoll (texto, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* ni-add-route-dialog.h
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NI_ADD_ROUTE_DIALOG_H__
|
||||||
|
#define __NI_ADD_ROUTE_DIALOG_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "ni-route.h"
|
||||||
|
#include "ni-ip.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _NIAddRouteDialogClass NIAddRouteDialogClass;
|
||||||
|
typedef struct _NIAddRouteDialog NIAddRouteDialog;
|
||||||
|
typedef struct _NIAddRouteDialogPrivate NIAddRouteDialogPrivate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type declaration.
|
||||||
|
*/
|
||||||
|
#define NI_TYPE_ADD_ROUTE_DIALOG (ni_add_route_dialog_get_type ())
|
||||||
|
#define NI_ADD_ROUTE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NI_TYPE_ADD_ROUTE_DIALOG, NIAddRouteDialog))
|
||||||
|
#define NI_ADD_ROUTE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NI_TYPE_ADD_ROUTE_DIALOG, NIAddRouteDialogClass))
|
||||||
|
#define NI_IS_ADD_ROUTE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NI_TYPE_ADD_ROUTE_DIALOG))
|
||||||
|
#define NI_IS_ADD_ROUTE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NI_TYPE_ADD_ROUTE_DIALOG))
|
||||||
|
#define NI_ADD_ROUTE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NI_TYPE_ADD_ROUTE_DIALOG, NIAddRouteDialogClass))
|
||||||
|
|
||||||
|
GType ni_add_route_dialog_get_type (void);
|
||||||
|
|
||||||
|
struct _NIAddRouteDialogClass {
|
||||||
|
GtkDialogClass parent_class;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _NIAddRouteDialog {
|
||||||
|
GtkDialog parent_instance;
|
||||||
|
|
||||||
|
NIAddRouteDialogPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NIAddRouteDialogGW {
|
||||||
|
struct_addr addr;
|
||||||
|
int metric;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Method definitions.
|
||||||
|
*/
|
||||||
|
GtkWidget* ni_add_route_dialog_new (int family);
|
||||||
|
|
||||||
|
gboolean ni_add_route_dialog_get_destination (NIAddRouteDialog *dialog, struct_addr *addr, int *prefix);
|
||||||
|
GList *ni_add_route_dialog_get_gateways (NIAddRouteDialog *dialog);
|
||||||
|
int ni_add_route_dialog_get_metric (NIAddRouteDialog *dialog);
|
||||||
|
int ni_add_route_dialog_get_route_table (NIAddRouteDialog *dialog);
|
||||||
|
int ni_add_route_dialog_get_route_type (NIAddRouteDialog *dialog);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __NI_ADD_ROUTE_DIALOG_H__ */
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "ni-ip.h"
|
||||||
|
#include "ni-client.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _NIRouteClass NIRouteClass;
|
typedef struct _NIRouteClass NIRouteClass;
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#include "ni-client.h"
|
#include "ni-client.h"
|
||||||
#include "ni-route.h"
|
#include "ni-route.h"
|
||||||
#include "ni-interface.h"
|
#include "ni-interface.h"
|
||||||
|
#include "ni-add-route-dialog.h"
|
||||||
|
|
||||||
|
|
||||||
struct _NIWindowRoutePrivate {
|
struct _NIWindowRoutePrivate {
|
||||||
NIClient *ni_client;
|
NIClient *ni_client;
|
||||||
|
@ -104,8 +106,8 @@ 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_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 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_new_route_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_interface_delete_route_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data);
|
||||||
|
|
||||||
static void ni_window_route_updated_route_cb (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);
|
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||||
|
@ -273,8 +275,8 @@ static void ni_window_route_constructed (GObject *obj) {
|
||||||
g_free (name);*/
|
g_free (name);*/
|
||||||
|
|
||||||
/* Conectar la señal de ruta agregada y ruta eliminada */
|
/* 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, "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_ip_cb), window_route);
|
g_signal_connect (window_route->priv->ni_client, "delete-route", G_CALLBACK (ni_window_interface_delete_route_cb), window_route);
|
||||||
|
|
||||||
/* Recorrer las rutas, y procesar la información */
|
/* Recorrer las rutas, y procesar la información */
|
||||||
if (window_route->priv->family == AF_INET) {
|
if (window_route->priv->family == AF_INET) {
|
||||||
|
@ -405,13 +407,13 @@ gboolean ni_window_route_tree_filter_routes_func (GtkTreeModel *tree_model, GtkT
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ni_window_interface_new_ip_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data) {
|
static void ni_window_interface_new_route_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data) {
|
||||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||||
|
|
||||||
ni_window_route_route_added_cb (window_route, ni_route);
|
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) {
|
static void ni_window_interface_delete_route_cb (NIClient *ni_client, NIRoute *ni_route, gpointer data) {
|
||||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
NIWindowRoute *window_route = NI_WINDOW_ROUTE (data);
|
||||||
struct _NIWindowRouteSearchRoute for_search;
|
struct _NIWindowRouteSearchRoute for_search;
|
||||||
|
|
||||||
|
@ -426,6 +428,59 @@ static void ni_window_interface_delete_ip_cb (NIClient *ni_client, NIRoute *ni_r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int metrica, tabla, tipo;
|
||||||
|
struct_addr destino;
|
||||||
|
gboolean has_
|
||||||
|
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 */
|
||||||
|
ni_client = ni_interface_get_client (window_route->priv->ni_interface);
|
||||||
|
|
||||||
|
gws = ni_add_route_dialog_get_gateways (NI_ADD_ROUTE_DIALOG (dialog));
|
||||||
|
|
||||||
|
if (gws != NULL) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free_full (gws, g_free);
|
||||||
|
#if 0
|
||||||
|
ni_ip_add_dialog_get_address (NI_IP_ADD_DIALOG (dialog), &addr, &prefix);
|
||||||
|
has_p2p = ni_ip_add_dialog_has_p2p_address (NI_IP_ADD_DIALOG (dialog));
|
||||||
|
if (has_p2p) {
|
||||||
|
memcpy (&p2p_addr, &addr, sizeof (p2p_addr));
|
||||||
|
ni_ip_add_dialog_get_p2p_address (NI_IP_ADD_DIALOG (dialog), &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= IFA_F_PERMANENT;
|
||||||
|
if (ni_ip_add_dialog_get_noprefix (NI_IP_ADD_DIALOG (dialog))) {
|
||||||
|
flags |= IFA_F_NOPREFIXROUTE;
|
||||||
|
}
|
||||||
|
//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) {
|
||||||
|
|
||||||
|
/* TODO: Pedir los tiempos de validez de la interfaz */
|
||||||
|
guint32 cacheinfo[2];
|
||||||
|
cacheinfo[0] = 60;
|
||||||
|
cacheinfo[1] = 60;
|
||||||
|
ni_client_ask_ip_new (ni_client, window_iface->priv->ni_interface, family, prefix, &addr, flags, 0, has_p2p, (has_p2p ? &p2p_addr : NULL), FALSE, NULL, cacheinfo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
|
}
|
||||||
|
|
||||||
static void ni_window_route_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
static void ni_window_route_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
||||||
NIWindowRoute *window_route = NI_WINDOW_ROUTE (object);
|
NIWindowRoute *window_route = NI_WINDOW_ROUTE (object);
|
||||||
g_return_if_fail (NI_IS_WINDOW_ROUTE (object));
|
g_return_if_fail (NI_IS_WINDOW_ROUTE (object));
|
||||||
|
@ -577,6 +632,7 @@ static void ni_window_route_init (NIWindowRoute *window_route) {
|
||||||
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 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);
|
priv->tables_store = gtk_list_store_new (NUM_TABLE_STORE_COLS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
||||||
|
/* TODO: Recuperar esta informacion de las tablas de ruteo desde el NetworkInador */
|
||||||
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, &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, 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, 255, TABLE_STORE_NAME, "Local", TABLE_STORE_IS_NEW, FALSE, -1);
|
||||||
|
@ -615,7 +671,7 @@ static void ni_window_route_init (NIWindowRoute *window_route) {
|
||||||
|
|
||||||
button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_LARGE_TOOLBAR);
|
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);
|
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);
|
g_signal_connect (button, "clicked", G_CALLBACK (ni_window_route_add_route_button_add_cb), window_route);
|
||||||
|
|
||||||
priv->del_route_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_LARGE_TOOLBAR);
|
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);
|
gtk_box_pack_start (GTK_BOX (vbox2), priv->del_route_button, FALSE, FALSE, 0);
|
||||||
|
|
121
src/manager.c
121
src/manager.c
|
@ -42,6 +42,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "interfaces.h"
|
#include "interfaces.h"
|
||||||
#include "ip-address.h"
|
#include "ip-address.h"
|
||||||
|
#include "routes.h"
|
||||||
#include "bridge.h"
|
#include "bridge.h"
|
||||||
#include "network-inador-manager.h"
|
#include "network-inador-manager.h"
|
||||||
#include "dhcp_client.h"
|
#include "dhcp_client.h"
|
||||||
|
@ -1160,6 +1161,120 @@ void _manager_send_list_routes (ManagerClientInfo *manager_client, unsigned char
|
||||||
_manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTES);
|
_manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _manager_execute_add_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
Route route;
|
||||||
|
int ret, has_prefsrc;
|
||||||
|
int family_size, wanted_size, family, nexthops_needed;
|
||||||
|
int g, rem, pos;
|
||||||
|
RouteNH *nh;
|
||||||
|
|
||||||
|
if (buffer_len < 18) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
family = buffer[2];
|
||||||
|
|
||||||
|
if (family != AF_INET && family != AF_INET6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (family == AF_INET) {
|
||||||
|
family_size = sizeof (struct in_addr);
|
||||||
|
} else if (family == AF_INET6) {
|
||||||
|
family_size = sizeof (struct in6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
has_prefsrc = 0;
|
||||||
|
if (buffer[12] & 0x01) {
|
||||||
|
has_prefsrc = 1;
|
||||||
|
}
|
||||||
|
/* Ya puedo revisar el resto de la longitud */
|
||||||
|
wanted_size = 18 + family_size + (family_size * has_prefsrc);
|
||||||
|
if (buffer_len < wanted_size) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Revisar los next hops */
|
||||||
|
g = buffer[13];
|
||||||
|
rem = buffer_len - wanted_size;
|
||||||
|
pos = wanted_size;
|
||||||
|
while (g > 0) {
|
||||||
|
if (rem < 8) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer[pos] & 0x01 && rem < 12) {
|
||||||
|
/* Tiene GW */
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g--;
|
||||||
|
if (buffer[pos] & 0x01) {
|
||||||
|
rem -= 12;
|
||||||
|
pos += 12;
|
||||||
|
} else {
|
||||||
|
rem -= 8;
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&route, 0, sizeof (route));
|
||||||
|
|
||||||
|
/* Ejecutar el parsing */
|
||||||
|
route.family = family;
|
||||||
|
route.type = buffer[3];
|
||||||
|
memcpy (&route.table, &buffer[4], 4);
|
||||||
|
route.prefix = buffer[8];
|
||||||
|
route.protocol = buffer[9];
|
||||||
|
route.tos = buffer[10];
|
||||||
|
route.scope = buffer[11];
|
||||||
|
memcpy (&route.priority, &buffer[14], 4);
|
||||||
|
|
||||||
|
memcpy (&route.dest, &buffer[18], family_size);
|
||||||
|
pos = 18 + family_size;
|
||||||
|
if (has_prefsrc) {
|
||||||
|
memcpy (&route.prefsrc, &buffer[pos], family_size);
|
||||||
|
pos += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recorrer cada next-hop */
|
||||||
|
g = buffer[13];
|
||||||
|
route.nexthops = NULL;
|
||||||
|
while (g > 0) {
|
||||||
|
nh = (RouteNH *) malloc (sizeof (RouteNH));
|
||||||
|
|
||||||
|
memset (nh, 0, sizeof (RouteNH));
|
||||||
|
nh->nh_flags = buffer[pos + 1];
|
||||||
|
nh->nh_weight = buffer[pos + 2];
|
||||||
|
memcpy (&nh->out_index, &buffer[pos + 4], 4);
|
||||||
|
|
||||||
|
pos += 8;
|
||||||
|
|
||||||
|
if (buffer[pos] & 0x01) {
|
||||||
|
/* Tiene GW */
|
||||||
|
memcpy (&nh->gw, &buffer[pos], family_size);
|
||||||
|
pos += family_size;
|
||||||
|
}
|
||||||
|
route.nexthops = g_list_append (route.nexthops, nh);
|
||||||
|
g--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = routes_add (manager_client->manager->handle, &route);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* OK */
|
||||||
|
_manager_send_executed (manager_client);
|
||||||
|
} else {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_ADD_ROUTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
|
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||||
ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
|
ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
|
||||||
NetworkInadorManager *manager = manager_client->manager;
|
NetworkInadorManager *manager = manager_client->manager;
|
||||||
|
@ -1260,6 +1375,12 @@ static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition
|
||||||
break;
|
break;
|
||||||
case NET_INADOR_COMMAND_LIST_ROUTES:
|
case NET_INADOR_COMMAND_LIST_ROUTES:
|
||||||
_manager_send_list_routes (manager_client, buffer, bytes);
|
_manager_send_list_routes (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_ADD_ROUTE:
|
||||||
|
_manager_execute_add_route (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_REMOVE_ROUTE:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
|
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
|
||||||
|
|
|
@ -41,6 +41,8 @@ enum {
|
||||||
NET_INADOR_COMMAND_GET_DHCP_STATUS,
|
NET_INADOR_COMMAND_GET_DHCP_STATUS,
|
||||||
|
|
||||||
NET_INADOR_COMMAND_LIST_ROUTES = 64,
|
NET_INADOR_COMMAND_LIST_ROUTES = 64,
|
||||||
|
NET_INADOR_COMMAND_ADD_ROUTE,
|
||||||
|
NET_INADOR_COMMAND_REMOVE_ROUTE,
|
||||||
|
|
||||||
NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
|
NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
|
||||||
|
|
||||||
|
|
163
src/routes.c
163
src/routes.c
|
@ -431,6 +431,169 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) {
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _route_wait_ack_or_error (struct nl_msg *msg, void *arg) {
|
||||||
|
int *ret = (int *) arg;
|
||||||
|
struct nlmsgerr *l_err;
|
||||||
|
struct nlmsghdr *reply;
|
||||||
|
|
||||||
|
reply = nlmsg_hdr (msg);
|
||||||
|
|
||||||
|
if (reply->nlmsg_type == NLMSG_ERROR) {
|
||||||
|
l_err = nlmsg_data (reply);
|
||||||
|
|
||||||
|
*ret = l_err->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _route_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, void *arg) {
|
||||||
|
int *ret = (int *) arg;
|
||||||
|
|
||||||
|
*ret = l_err->error;
|
||||||
|
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int routes_add (NetworkInadorHandle *handle, Route *route) {
|
||||||
|
struct nl_msg * msg, *msg_nh;
|
||||||
|
struct rtmsg route_hdr;
|
||||||
|
int ret, error;
|
||||||
|
int family_size = 0;
|
||||||
|
struct_addr empty;
|
||||||
|
int hop_count;
|
||||||
|
RouteNH *nh;
|
||||||
|
GList *g;
|
||||||
|
struct rtnexthop nexthop_hdr, *nhptr;
|
||||||
|
char buffer_nexthops[8192];
|
||||||
|
int size_nexthops;
|
||||||
|
|
||||||
|
route_hdr.rtm_family = route->family;
|
||||||
|
route_hdr.rtm_dst_len = route->prefix;
|
||||||
|
route_hdr.rtm_src_len = 0;
|
||||||
|
route_hdr.rtm_tos = route->tos;
|
||||||
|
route_hdr.rtm_table = route->table;
|
||||||
|
route_hdr.rtm_protocol = route->protocol;
|
||||||
|
route_hdr.rtm_scope = route->scope;
|
||||||
|
route_hdr.rtm_type = route->type;
|
||||||
|
route_hdr.rtm_flags = 0;
|
||||||
|
|
||||||
|
msg = nlmsg_alloc_simple (RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE);
|
||||||
|
ret = nlmsg_append (msg, &route_hdr, sizeof (route_hdr), NLMSG_ALIGNTO);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
nlmsg_free (msg);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route->family == AF_INET) {
|
||||||
|
family_size = sizeof (struct in_addr);
|
||||||
|
} else if (route->family == AF_INET6) {
|
||||||
|
family_size = sizeof (struct in6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nla_put (msg, RTA_DST, family_size, &route->dest);
|
||||||
|
if (route->priority != 0) {
|
||||||
|
ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&empty, 0, sizeof (empty));
|
||||||
|
if (memcmp (&empty, &route->prefsrc, family_size) != 0) {
|
||||||
|
ret |= nla_put (msg, RTA_PREFSRC, family_size, &route->prefsrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
hop_count = g_list_length (route->nexthops);
|
||||||
|
if (hop_count <= 1) {
|
||||||
|
/* Agregar por el método 1 */
|
||||||
|
nh = (RouteNH *) route->nexthops->data;
|
||||||
|
|
||||||
|
ret |= nla_put (msg, RTA_OIF, 4, &nh->out_index);
|
||||||
|
|
||||||
|
if (memcmp (&empty, &nh->gw, family_size) != 0) {
|
||||||
|
ret |= nla_put (msg, RTA_GATEWAY, family_size, &nh->gw);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Tenemos múltiples next-hops */
|
||||||
|
//nest = nla_nest_start (msg, RTA_MULTIPATH);
|
||||||
|
size_nexthops = 0;
|
||||||
|
|
||||||
|
g = route->nexthops;
|
||||||
|
while (g != NULL) {
|
||||||
|
nh = (RouteNH *) g->data;
|
||||||
|
|
||||||
|
msg_nh = nlmsg_alloc ();
|
||||||
|
if (msg_nh == NULL) break;
|
||||||
|
nexthop_hdr.rtnh_len = 0;
|
||||||
|
nexthop_hdr.rtnh_flags = nh->nh_flags;
|
||||||
|
nexthop_hdr.rtnh_hops = nh->nh_weight;
|
||||||
|
nexthop_hdr.rtnh_ifindex = nh->out_index;
|
||||||
|
|
||||||
|
nlmsg_append (msg_nh, &nexthop_hdr, sizeof (nexthop_hdr), 0);
|
||||||
|
|
||||||
|
if (memcmp (&empty, &nh->gw, family_size) != 0) {
|
||||||
|
/* Tiene un gw el next-hop */
|
||||||
|
nla_put (msg_nh, RTA_GATEWAY, family_size, &nh->gw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Corregir la longitud */
|
||||||
|
nhptr = nlmsg_data (nlmsg_hdr (msg_nh));
|
||||||
|
nhptr->rtnh_len = (nlmsg_hdr (msg_nh))->nlmsg_len - NLMSG_HDRLEN;
|
||||||
|
|
||||||
|
/* Copiar al buffer de los next-hops */
|
||||||
|
memcpy (&buffer_nexthops[size_nexthops], nhptr, nhptr->rtnh_len);
|
||||||
|
size_nexthops += nhptr->rtnh_len;
|
||||||
|
|
||||||
|
nlmsg_free (msg_nh);
|
||||||
|
g = g->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret |= nla_put (msg, RTA_MULTIPATH, size_nexthops, buffer_nexthops);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
nlmsg_free (msg);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_complete_msg (handle->nl_sock_route, msg);
|
||||||
|
|
||||||
|
ret = nl_send (handle->nl_sock_route, msg);
|
||||||
|
|
||||||
|
nlmsg_free (msg);
|
||||||
|
if (ret <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
|
||||||
|
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
|
||||||
|
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _route_wait_ack_or_error, &error);
|
||||||
|
nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _route_wait_error, &error);
|
||||||
|
|
||||||
|
ret = nl_recvmsgs_default (handle->nl_sock_route);
|
||||||
|
|
||||||
|
if (ret < 0 || error < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int routes_del (NetworkInadorHandle *handle, Route *route) {
|
||||||
|
struct nl_msg * msg;
|
||||||
|
struct rtmsg route_hdr;
|
||||||
|
int ret, error;
|
||||||
|
int family_size = 0;
|
||||||
|
struct_addr empty;
|
||||||
|
int hop_count;
|
||||||
|
RouteNH *nh;
|
||||||
|
GList *g;
|
||||||
|
|
||||||
|
/* TODO: Pendiente escribir esto */
|
||||||
|
}
|
||||||
|
|
||||||
void routes_ask (NetworkInadorHandle *handle) {
|
void routes_ask (NetworkInadorHandle *handle) {
|
||||||
struct nl_msg * msg;
|
struct nl_msg * msg;
|
||||||
struct rtmsg rtm_hdr = {
|
struct rtmsg rtm_hdr = {
|
||||||
|
|
|
@ -32,6 +32,7 @@ void routes_init (NetworkInadorHandle *handle);
|
||||||
void routes_ask (NetworkInadorHandle *handle);
|
void routes_ask (NetworkInadorHandle *handle);
|
||||||
int routes_receive_message_newroute (struct nl_msg *msg, void *arg);
|
int routes_receive_message_newroute (struct nl_msg *msg, void *arg);
|
||||||
int routes_receive_message_delroute (struct nl_msg *msg, void *arg);
|
int routes_receive_message_delroute (struct nl_msg *msg, void *arg);
|
||||||
|
int routes_add (NetworkInadorHandle *handle, Route *route);
|
||||||
|
|
||||||
void route_ask_delayed_delroute (NetworkInadorHandle *handle);
|
void route_ask_delayed_delroute (NetworkInadorHandle *handle);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue