ftypes: move set_value_floating into the union
[metze/wireshark/wip.git] / epan / ftypes / ftype-ipv4.c
1 /*
2  * Wireshark - Network traffic analyzer
3  * By Gerald Combs <gerald@wireshark.org>
4  * Copyright 2001 Gerald Combs
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <ftypes-int.h>
26 #include <epan/ipv4.h>
27 #include <epan/addr_resolv.h>
28
29
30 static void
31 set_uinteger(fvalue_t *fv, guint32 value)
32 {
33         ipv4_addr_and_mask_set_net_order_addr(&(fv->value.ipv4), value);
34         ipv4_addr_and_mask_set_netmask_bits(&(fv->value.ipv4), 32);
35 }
36
37 static gpointer
38 value_get(fvalue_t *fv)
39 {
40         return &(fv->value.ipv4);
41 }
42
43 static gboolean
44 val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
45 {
46         guint32 addr;
47         unsigned int nmask_bits;
48
49         const char *slash, *net_str;
50         const char *addr_str;
51         char *addr_str_to_free = NULL;
52         fvalue_t *nmask_fvalue;
53
54         /* Look for CIDR: Is there a single slash in the string? */
55         slash = strchr(s, '/');
56         if (slash) {
57                 /* Make a copy of the string up to but not including the
58                  * slash; that's the address portion. */
59                 addr_str_to_free = wmem_strndup(NULL, s, slash - s);
60                 addr_str = addr_str_to_free;
61         }
62         else {
63                 addr_str = s;
64         }
65
66         if (!get_host_ipaddr(addr_str, &addr)) {
67                 if (err_msg != NULL) {
68                         *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or IPv4 address.",
69                             addr_str);
70                 }
71                 if (addr_str_to_free)
72                         wmem_free(NULL, addr_str_to_free);
73                 return FALSE;
74         }
75
76         if (addr_str_to_free)
77                 wmem_free(NULL, addr_str_to_free);
78         ipv4_addr_and_mask_set_net_order_addr(&(fv->value.ipv4), addr);
79
80         /* If CIDR, get netmask bits. */
81         if (slash) {
82                 /* Skip past the slash */
83                 net_str = slash + 1;
84
85                 /* XXX - this is inefficient */
86                 nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, err_msg);
87                 if (!nmask_fvalue) {
88                         return FALSE;
89                 }
90                 nmask_bits = fvalue_get_uinteger(nmask_fvalue);
91                 FVALUE_FREE(nmask_fvalue);
92
93                 if (nmask_bits > 32) {
94                         if (err_msg != NULL) {
95                                 *err_msg = g_strdup_printf("Netmask bits in a CIDR IPv4 address should be <= 32, not %u",
96                                                 nmask_bits);
97                         }
98                         return FALSE;
99                 }
100                 ipv4_addr_and_mask_set_netmask_bits(&fv->value.ipv4, nmask_bits);
101         }
102         else {
103                 /* Not CIDR; mask covers entire address. */
104                 ipv4_addr_and_mask_set_netmask_bits(&(fv->value.ipv4), 32);
105         }
106
107         return TRUE;
108 }
109
110 static int
111 val_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
112 {
113         /*
114          * 15 characters for "XXX.XXX.XXX.XXX".
115          */
116         return 15;
117 }
118
119 static void
120 val_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size _U_)
121 {
122         ipv4_addr_and_mask_str_buf(&fv->value.ipv4, buf);
123 }
124
125 static gboolean
126 cmp_eq(const fvalue_t *a, const fvalue_t *b)
127 {
128         return ipv4_addr_and_mask_eq(&a->value.ipv4, &b->value.ipv4);
129 }
130
131 static gboolean
132 cmp_ne(const fvalue_t *a, const fvalue_t *b)
133 {
134         return ipv4_addr_and_mask_ne(&a->value.ipv4, &b->value.ipv4);
135 }
136
137 static gboolean
138 cmp_gt(const fvalue_t *a, const fvalue_t *b)
139 {
140         return ipv4_addr_and_mask_gt(&a->value.ipv4, &b->value.ipv4);
141 }
142
143 static gboolean
144 cmp_ge(const fvalue_t *a, const fvalue_t *b)
145 {
146         return ipv4_addr_and_mask_ge(&a->value.ipv4, &b->value.ipv4);
147 }
148
149 static gboolean
150 cmp_lt(const fvalue_t *a, const fvalue_t *b)
151 {
152         return ipv4_addr_and_mask_lt(&a->value.ipv4, &b->value.ipv4);
153 }
154
155 static gboolean
156 cmp_le(const fvalue_t *a, const fvalue_t *b)
157 {
158         return ipv4_addr_and_mask_le(&a->value.ipv4, &b->value.ipv4);
159 }
160
161 static gboolean
162 cmp_bitwise_and(const fvalue_t *fv_a, const fvalue_t *fv_b)
163 {
164         guint32         addr_a;
165         guint32         addr_b;
166
167         addr_a = fv_a->value.ipv4.addr & fv_a->value.ipv4.nmask;
168         addr_b = fv_b->value.ipv4.addr & fv_b->value.ipv4.nmask;
169         return ((addr_a & addr_b) != 0);
170 }
171
172 void
173 ftype_register_ipv4(void)
174 {
175
176         static ftype_t ipv4_type = {
177                 FT_IPv4,                        /* ftype */
178                 "FT_IPv4",                      /* name */
179                 "IPv4 address",                 /* pretty_name */
180                 4,                              /* wire_size */
181                 NULL,                           /* new_value */
182                 NULL,                           /* free_value */
183                 val_from_unparsed,              /* val_from_unparsed */
184                 NULL,                           /* val_from_string */
185                 val_to_repr,                    /* val_to_string_repr */
186                 val_repr_len,                   /* len_string_repr */
187
188                 { .set_value_uinteger = set_uinteger }, /* union set_value */
189
190
191                 value_get,                      /* get_value */
192                 NULL,                           /* get_value_uinteger */
193                 NULL,                           /* get_value_sinteger */
194                 NULL,                           /* get_value_uinteger64 */
195                 NULL,                           /* get_value_sinteger64 */
196                 NULL,                           /* get_value_floating */
197
198                 cmp_eq,
199                 cmp_ne,
200                 cmp_gt,
201                 cmp_ge,
202                 cmp_lt,
203                 cmp_le,
204                 cmp_bitwise_and,
205                 NULL,                           /* cmp_contains */
206                 NULL,                           /* cmp_matches */
207
208                 NULL,
209                 NULL,
210         };
211
212         ftype_register(FT_IPv4, &ipv4_type);
213 }
214
215 /*
216  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
217  *
218  * Local variables:
219  * c-basic-offset: 8
220  * tab-width: 8
221  * indent-tabs-mode: t
222  * End:
223  *
224  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
225  * :indentSize=8:tabSize=8:noTabs=false:
226  */