summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2015-04-17 13:25:22 +0200
committerJiří Klimeš <jklimes@redhat.com>2015-04-27 13:13:19 +0200
commit6c50f00b60b5c887410c89fd82d2681fb0bd56aa (patch)
treeda51b9eb30948636cab45b986550e5a60a4426fb
parent7e6dcb445a608c96265e1fb8688b6bf149c6bceb (diff)
downloadnetwork-manager-applet-6c50f00b60b5c887410c89fd82d2681fb0bd56aa.tar.gz
editor: check gateway to be in the network specified by addr/prefix (rh #1167491)
If the gateway doesn't match address/prefix network, highlight it in yellow, because it may be invalid. https://bugzilla.redhat.com/show_bug.cgi?id=1167491
-rw-r--r--src/connection-editor/page-ip4.c91
-rw-r--r--src/connection-editor/page-ip6.c100
2 files changed, 163 insertions, 28 deletions
diff --git a/src/connection-editor/page-ip4.c b/src/connection-editor/page-ip4.c
index a6ec7152..b431552c 100644
--- a/src/connection-editor/page-ip4.c
+++ b/src/connection-editor/page-ip4.c
@@ -716,11 +716,50 @@ is_address_unspecified (const char *str)
}
static gboolean
+gateway_matches_address (const char *gw_str, const char *addr_str, guint32 prefix)
+{
+ struct in_addr gw, addr;
+ guint32 netmask;
+
+ if (!gw_str || inet_pton (AF_INET, gw_str, &gw) != 1)
+ return FALSE;
+ if (!addr_str || inet_pton (AF_INET, addr_str, &addr) != 1)
+ return FALSE;
+
+ netmask = nm_utils_ip4_prefix_to_netmask (prefix);
+ return ((addr.s_addr & netmask) == (gw.s_addr & netmask));
+}
+
+static gboolean
+possibly_wrong_gateway (GtkTreeModel *model, GtkTreeIter *iter, const char *gw_str)
+{
+ char *addr_str, *prefix_str;
+ gboolean addr_valid;
+ guint32 prefix;
+
+ gtk_tree_model_get (model, iter, COL_ADDRESS, &addr_str, -1);
+ gtk_tree_model_get (model, iter, COL_PREFIX, &prefix_str, -1);
+ addr_valid = addr_str && *addr_str && nm_utils_ipaddr_valid (AF_INET, addr_str) && !is_address_unspecified (addr_str)
+ && parse_netmask (prefix_str, &prefix);
+
+ if (addr_valid && !gateway_matches_address (gw_str, addr_str, prefix))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+typedef struct {
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ guint column;
+} AddressLineInfo;
+
+static gboolean
cell_changed_cb (GtkEditable *editable,
gpointer user_data)
{
+ AddressLineInfo *info = (AddressLineInfo *) user_data;
char *cell_text;
- guint column;
GdkRGBA rgba;
gboolean value_valid = FALSE;
const char *colorname = NULL;
@@ -728,8 +767,7 @@ cell_changed_cb (GtkEditable *editable,
cell_text = gtk_editable_get_chars (editable, 0, -1);
/* The COL_PREFIX can contain IP address or prefix */
- column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (user_data), "column"));
- if (column == COL_PREFIX) {
+ if (info->column == COL_PREFIX) {
guint32 tmp_prefix;
value_valid = parse_netmask (cell_text, &tmp_prefix);
@@ -740,16 +778,22 @@ cell_changed_cb (GtkEditable *editable,
value_valid = TRUE;
/* 0.0.0.0 is not accepted for address */
- if (column == COL_ADDRESS && tmp_addr.s_addr == 0)
+ if (info->column == COL_ADDRESS && tmp_addr.s_addr == 0)
value_valid = FALSE;
/* Consider empty gateway as valid */
- if (!*cell_text && column == COL_GATEWAY)
+ if (!*cell_text && info->column == COL_GATEWAY)
value_valid = TRUE;
}
/* Change cell's background color while editing */
colorname = value_valid ? "lightgreen" : "red";
+ /* Check gateway against address and prefix */
+ if ( info->column == COL_GATEWAY
+ && value_valid
+ && possibly_wrong_gateway (info->model, &info->iter, cell_text))
+ colorname = "yellow";
+
gdk_rgba_parse (&rgba, colorname);
utils_override_bg_color (GTK_WIDGET (editable), &rgba);
@@ -803,6 +847,12 @@ key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
}
static void
+address_line_info_destroy (AddressLineInfo *info)
+{
+ g_slice_free (AddressLineInfo, info);
+}
+
+static void
cell_editing_started (GtkCellRenderer *cell,
GtkCellEditable *editable,
const gchar *path,
@@ -810,6 +860,9 @@ cell_editing_started (GtkCellRenderer *cell,
{
CEPageIP4 *self = CE_PAGE_IP4 (user_data);
CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ AddressLineInfo *info;
if (!GTK_IS_ENTRY (editable)) {
g_warning ("%s: Unexpected cell editable type.", __func__);
@@ -833,9 +886,16 @@ cell_editing_started (GtkCellRenderer *cell,
user_data);
/* Set up handler for IP verifying and changing cell background */
- g_signal_connect (G_OBJECT (editable), "changed",
- (GCallback) cell_changed_cb,
- cell);
+ model = gtk_tree_view_get_model (priv->addr_list);
+ gtk_tree_model_get_iter_from_string (model, &iter, priv->last_path);
+ info = g_slice_new0 (AddressLineInfo);
+ info->model = model;
+ info->iter = iter;
+ info->column = priv->last_column;
+ g_signal_connect_data (G_OBJECT (editable), "changed",
+ (GCallback) cell_changed_cb,
+ info,
+ (GClosureNotify) address_line_info_destroy, 0);
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
@@ -946,7 +1006,7 @@ cell_error_data_func (GtkTreeViewColumn *tree_column,
{
guint32 col = GPOINTER_TO_UINT (data);
char *value = NULL;
- const char *color = "red";
+ const char *color = NULL;
guint32 prefix;
gboolean invalid = FALSE;
@@ -957,15 +1017,18 @@ cell_error_data_func (GtkTreeViewColumn *tree_column,
|| is_address_unspecified (value);
else if (col == COL_PREFIX)
invalid = !parse_netmask (value, &prefix);
- else if (col == COL_GATEWAY)
+ else if (col == COL_GATEWAY) {
invalid = value && *value && !nm_utils_ipaddr_valid (AF_INET, value);
- else
+
+ /* Check gateway against address and prefix */
+ if (!invalid && possibly_wrong_gateway (tree_model, iter, value))
+ color = "#DDC000"; /* darker than "yellow", else selected text is hard to read */
+ } else
g_warn_if_reached ();
if (invalid)
- utils_set_cell_background (cell, color, value);
- else
- utils_set_cell_background (cell, NULL, NULL);
+ color = "red";
+ utils_set_cell_background (cell, color, color ? value : NULL);
g_free (value);
}
diff --git a/src/connection-editor/page-ip6.c b/src/connection-editor/page-ip6.c
index 35ef7131..69dfd3a9 100644
--- a/src/connection-editor/page-ip6.c
+++ b/src/connection-editor/page-ip6.c
@@ -714,11 +714,59 @@ delete_text_cb (GtkEditable *editable,
}
static gboolean
+gateway_matches_address (const char *gw_str, const char *addr_str, guint32 prefix)
+{
+ struct in6_addr gw, addr;
+ guint32 x, y, mask;
+ int i;
+
+ if (!gw_str || inet_pton (AF_INET6, gw_str, &gw) != 1)
+ return FALSE;
+ if (!addr_str || inet_pton (AF_INET6, addr_str, &addr) != 1)
+ return FALSE;
+
+ x = prefix / 32;
+ y = prefix % 32;
+ mask = ~htonl (0xFFFFFFFF >> y);
+ for (i = 0; i < x; i++) {
+ if (addr.s6_addr32[i] != gw.s6_addr32[i])
+ return FALSE;
+ }
+ if ((addr.s6_addr32[i] & mask) != (gw.s6_addr32[i] & mask))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+possibly_wrong_gateway (GtkTreeModel *model, GtkTreeIter *iter, const char *gw_str)
+{
+ char *addr_str, *prefix_str;
+ gboolean addr_valid;
+ guint32 prefix;
+
+ gtk_tree_model_get (model, iter, COL_ADDRESS, &addr_str, -1);
+ gtk_tree_model_get (model, iter, COL_PREFIX, &prefix_str, -1);
+ addr_valid = addr_str && *addr_str && nm_utils_ipaddr_valid (AF_INET6, addr_str) && !is_address_unspecified (addr_str)
+ && is_prefix_valid (prefix_str, &prefix);
+
+ if (addr_valid && !gateway_matches_address (gw_str, addr_str, prefix))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+typedef struct {
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ guint column;
+} AddressLineInfo;
+
+static gboolean
cell_changed_cb (GtkEditable *editable,
gpointer user_data)
{
+ AddressLineInfo *info = (AddressLineInfo *) user_data;
char *cell_text;
- guint column;
GdkRGBA rgba;
gboolean value_valid = FALSE;
const char *colorname = NULL;
@@ -726,8 +774,7 @@ cell_changed_cb (GtkEditable *editable,
cell_text = gtk_editable_get_chars (editable, 0, -1);
/* The Prefix column is 1..128 */
- column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (user_data), "column"));
- if (column == COL_PREFIX)
+ if (info->column == COL_PREFIX)
value_valid = is_prefix_valid (cell_text, NULL);
else {
struct in6_addr tmp_addr;
@@ -736,16 +783,22 @@ cell_changed_cb (GtkEditable *editable,
value_valid = TRUE;
/* :: is not accepted for address */
- if (column == COL_ADDRESS && IN6_IS_ADDR_UNSPECIFIED (&tmp_addr))
+ if (info->column == COL_ADDRESS && IN6_IS_ADDR_UNSPECIFIED (&tmp_addr))
value_valid = FALSE;
/* Consider empty gateway as valid */
- if (!*cell_text && column == COL_GATEWAY)
+ if (!*cell_text && info->column == COL_GATEWAY)
value_valid = TRUE;
}
/* Change cell's background color while editing */
colorname = value_valid ? "lightgreen" : "red";
+ /* Check gateway against address and prefix */
+ if ( info->column == COL_GATEWAY
+ && value_valid
+ && possibly_wrong_gateway (info->model, &info->iter, cell_text))
+ colorname = "yellow";
+
gdk_rgba_parse (&rgba, colorname);
utils_override_bg_color (GTK_WIDGET (editable), &rgba);
@@ -799,6 +852,12 @@ key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
}
static void
+address_line_info_destroy (AddressLineInfo *info)
+{
+ g_slice_free (AddressLineInfo, info);
+}
+
+static void
cell_editing_started (GtkCellRenderer *cell,
GtkCellEditable *editable,
const gchar *path,
@@ -807,6 +866,9 @@ cell_editing_started (GtkCellRenderer *cell,
CEPageIP6 *self = CE_PAGE_IP6 (user_data);
CEPageIP6Private *priv = CE_PAGE_IP6_GET_PRIVATE (self);
guint column;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ AddressLineInfo *info;
if (!GTK_IS_ENTRY (editable)) {
g_warning ("%s: Unexpected cell editable type.", __func__);
@@ -834,9 +896,16 @@ cell_editing_started (GtkCellRenderer *cell,
user_data);
/* Set up handler for value verifying and changing cell background */
- g_signal_connect (G_OBJECT (editable), "changed",
- (GCallback) cell_changed_cb,
- cell);
+ model = gtk_tree_view_get_model (priv->addr_list);
+ gtk_tree_model_get_iter_from_string (model, &iter, priv->last_path);
+ info = g_slice_new0 (AddressLineInfo);
+ info->model = model;
+ info->iter = iter;
+ info->column = priv->last_column;
+ g_signal_connect_data (G_OBJECT (editable), "changed",
+ (GCallback) cell_changed_cb,
+ info,
+ (GClosureNotify) address_line_info_destroy, 0);
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
@@ -947,7 +1016,7 @@ cell_error_data_func (GtkTreeViewColumn *tree_column,
{
guint32 col = GPOINTER_TO_UINT (data);
char *value = NULL;
- const char *color = "red";
+ const char *color = NULL;
gboolean invalid = FALSE;
gtk_tree_model_get (tree_model, iter, col, &value, -1);
@@ -957,15 +1026,18 @@ cell_error_data_func (GtkTreeViewColumn *tree_column,
|| is_address_unspecified (value);
else if (col == COL_PREFIX)
invalid = !is_prefix_valid (value, NULL);
- else if (col == COL_GATEWAY)
+ else if (col == COL_GATEWAY) {
invalid = value && *value && !nm_utils_ipaddr_valid (AF_INET6, value);
- else
+
+ /* Check gateway against address and prefix */
+ if (!invalid && possibly_wrong_gateway (tree_model, iter, value))
+ color = "#DDC000"; /* darker than "yellow", else selected text is hard to read */
+ } else
g_warn_if_reached ();
if (invalid)
- utils_set_cell_background (cell, color, value);
- else
- utils_set_cell_background (cell, NULL, NULL);
+ color = "red";
+ utils_set_cell_background (cell, color, color ? value : NULL);
g_free (value);
}