1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2020 Canonical Ltd.
4  *
5  * Licensed under the GNU General Public License Version 2
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 #include <arpa/inet.h>
23 #include <NetworkManager.h>
24 
25 #include "ce-netmask-entry.h"
26 
27 struct _CENetmaskEntry
28 {
29   GtkEntry parent_instance;
30 };
31 
32 static void ce_netmask_entry_editable_init (GtkEditableInterface *iface);
33 
G_DEFINE_TYPE_WITH_CODE(CENetmaskEntry,ce_netmask_entry,GTK_TYPE_ENTRY,G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,ce_netmask_entry_editable_init))34 G_DEFINE_TYPE_WITH_CODE (CENetmaskEntry, ce_netmask_entry, GTK_TYPE_ENTRY,
35                          G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
36                                                 ce_netmask_entry_editable_init))
37 
38 static gboolean
39 parse_netmask (const char *str, guint32 *prefix)
40 {
41   struct in_addr tmp_addr;
42   glong tmp_prefix;
43 
44   /* Is it a prefix? */
45   errno = 0;
46   if (!strchr (str, '.'))
47     {
48       tmp_prefix = strtol (str, NULL, 10);
49       if (!errno && tmp_prefix >= 0 && tmp_prefix <= 32)
50         {
51           if (prefix != NULL)
52             *prefix = tmp_prefix;
53           return TRUE;
54         }
55     }
56 
57   /* Is it a netmask? */
58   if (inet_pton (AF_INET, str, &tmp_addr) > 0)
59     {
60       if (prefix != NULL)
61         *prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr);
62       return TRUE;
63     }
64 
65   return FALSE;
66 }
67 
68 static void
ce_netmask_entry_changed(GtkEditable * editable)69 ce_netmask_entry_changed (GtkEditable *editable)
70 {
71   CENetmaskEntry *self = CE_NETMASK_ENTRY (editable);
72   GtkStyleContext *context;
73 
74   context = gtk_widget_get_style_context (GTK_WIDGET (self));
75   if (ce_netmask_entry_is_valid (self))
76     gtk_style_context_remove_class (context, "error");
77   else
78     gtk_style_context_add_class (context, "error");
79 }
80 
81 static void
ce_netmask_entry_init(CENetmaskEntry * self)82 ce_netmask_entry_init (CENetmaskEntry *self)
83 {
84 }
85 
86 static void
ce_netmask_entry_editable_init(GtkEditableInterface * iface)87 ce_netmask_entry_editable_init (GtkEditableInterface *iface)
88 {
89   iface->changed = ce_netmask_entry_changed;
90 }
91 
92 static void
ce_netmask_entry_class_init(CENetmaskEntryClass * klass)93 ce_netmask_entry_class_init (CENetmaskEntryClass *klass)
94 {
95 }
96 
97 CENetmaskEntry *
ce_netmask_entry_new(void)98 ce_netmask_entry_new (void)
99 {
100   return CE_NETMASK_ENTRY (g_object_new (ce_netmask_entry_get_type (), NULL));
101 }
102 
103 gboolean
ce_netmask_entry_is_empty(CENetmaskEntry * self)104 ce_netmask_entry_is_empty (CENetmaskEntry *self)
105 {
106   const gchar *text;
107 
108   g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), FALSE);
109 
110   text = gtk_entry_get_text (GTK_ENTRY (self));
111   return text[0] == '\0';
112 }
113 
114 gboolean
ce_netmask_entry_is_valid(CENetmaskEntry * self)115 ce_netmask_entry_is_valid (CENetmaskEntry *self)
116 {
117   const gchar *text;
118 
119   g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), FALSE);
120 
121   text = gtk_entry_get_text (GTK_ENTRY (self));
122   return text[0] == '\0' || parse_netmask (text, NULL);
123 }
124 
125 guint32
ce_netmask_entry_get_prefix(CENetmaskEntry * self)126 ce_netmask_entry_get_prefix (CENetmaskEntry *self)
127 {
128   const gchar *text;
129   guint32 prefix = 0;
130 
131   g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), 0);
132 
133   text = gtk_entry_get_text (GTK_ENTRY (self));
134   parse_netmask (text, &prefix);
135 
136   return prefix;
137 }
138