2 * Wireshark - Network traffic analyzer
3 * By Gerald Combs <gerald@wireshark.org>
4 * Copyright 2001 Gerald Combs
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.
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.
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.
25 #include <ftypes-int.h>
26 #include <epan/ipv6.h>
27 #include <epan/addr_resolv.h>
28 #include <epan/to_str.h>
31 ipv6_fvalue_set(fvalue_t *fv, const guint8 *value)
33 memcpy(fv->value.ipv6.addr.bytes, value, FT_IPv6_LEN);
34 fv->value.ipv6.prefix = 128;
38 ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
42 char *addr_str_to_free = NULL;
43 unsigned int nmask_bits;
44 fvalue_t *nmask_fvalue;
46 /* Look for prefix: Is there a single slash in the string? */
47 slash = strchr(s, '/');
49 /* Make a copy of the string up to but not including the
50 * slash; that's the address portion. */
51 addr_str_to_free = wmem_strndup(NULL, s, slash-s);
52 addr_str = addr_str_to_free;
57 if (!get_host_ipaddr6(addr_str, &(fv->value.ipv6.addr))) {
59 *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or IPv6 address.", s);
61 wmem_free(NULL, addr_str_to_free);
66 wmem_free(NULL, addr_str_to_free);
70 /* XXX - this is inefficient */
71 nmask_fvalue = fvalue_from_unparsed(FT_UINT32, slash+1, FALSE, err_msg);
75 nmask_bits = fvalue_get_uinteger(nmask_fvalue);
76 FVALUE_FREE(nmask_fvalue);
78 if (nmask_bits > 128) {
79 if (err_msg != NULL) {
80 *err_msg = g_strdup_printf("Prefix in a IPv6 address should be <= 128, not %u",
85 fv->value.ipv6.prefix = nmask_bits;
87 /* Not CIDR; mask covers entire address. */
88 fv->value.ipv6.prefix = 128;
95 ipv6_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
97 return MAX_IP6_STR_LEN;
101 ipv6_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
103 ip6_to_str_buf(&(fv->value.ipv6.addr), buf, size);
107 value_get(fvalue_t *fv)
109 return fv->value.ipv6.addr.bytes;
112 static const guint8 bitmasks[9] =
113 { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
116 cmp_compare(const fvalue_t *fv_a, const fvalue_t *fv_b)
118 const ipv6_addr_and_prefix *a = &(fv_a->value.ipv6);
119 const ipv6_addr_and_prefix *b = &(fv_b->value.ipv6);
123 prefix = MIN(a->prefix, b->prefix); /* MIN() like IPv4 */
124 prefix = MIN(prefix, 128); /* sanitize, max prefix is 128 */
126 while (prefix >= 8) {
127 gint byte_a = (gint) (a->addr.bytes[pos]);
128 gint byte_b = (gint) (b->addr.bytes[pos]);
130 if (byte_a != byte_b)
131 return byte_a - byte_b;
138 gint byte_a = (gint) (a->addr.bytes[pos] & (bitmasks[prefix]));
139 gint byte_b = (gint) (b->addr.bytes[pos] & (bitmasks[prefix]));
141 if (byte_a != byte_b)
142 return byte_a - byte_b;
148 cmp_eq(const fvalue_t *fv_a, const fvalue_t *fv_b)
150 return (cmp_compare(fv_a, fv_b) == 0);
154 cmp_ne(const fvalue_t *fv_a, const fvalue_t *fv_b)
156 return (cmp_compare(fv_a, fv_b) != 0);
160 cmp_gt(const fvalue_t *fv_a, const fvalue_t *fv_b)
162 return (cmp_compare(fv_a, fv_b) > 0);
166 cmp_ge(const fvalue_t *fv_a, const fvalue_t *fv_b)
168 return (cmp_compare(fv_a, fv_b) >= 0);
172 cmp_lt(const fvalue_t *fv_a, const fvalue_t *fv_b)
174 return (cmp_compare(fv_a, fv_b) < 0);
178 cmp_le(const fvalue_t *fv_a, const fvalue_t *fv_b)
180 return (cmp_compare(fv_a, fv_b) <= 0);
184 cmp_bitwise_and(const fvalue_t *fv_a, const fvalue_t *fv_b)
186 const ipv6_addr_and_prefix *a = &(fv_a->value.ipv6);
187 const ipv6_addr_and_prefix *b = &(fv_b->value.ipv6);
191 prefix = MIN(a->prefix, b->prefix); /* MIN() like in IPv4 */
192 prefix = MIN(prefix, 128); /* sanitize, max prefix is 128 */
194 while (prefix >= 8) {
195 if (a->addr.bytes[pos] & b->addr.bytes[pos])
203 guint8 byte_a = (a->addr.bytes[pos] & (bitmasks[prefix]));
204 guint8 byte_b = (b->addr.bytes[pos] & (bitmasks[prefix]));
213 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
215 /* XXX needed? ipv4 doesn't support slice() */
218 data = fv->value.ipv6.addr.bytes + offset;
220 g_byte_array_append(bytes, data, length);
224 ftype_register_ipv6(void)
226 static ftype_t ipv6_type = {
228 "FT_IPv6", /* name */
229 "IPv6 address", /* pretty_name */
230 FT_IPv6_LEN, /* wire_size */
231 NULL, /* new_value */
232 NULL, /* free_value */
233 ipv6_from_unparsed, /* val_from_unparsed */
234 NULL, /* val_from_string */
235 ipv6_to_repr, /* val_to_string_repr */
236 ipv6_repr_len, /* len_string_repr */
238 { .set_value_bytes = ipv6_fvalue_set }, /* union set_value */
240 NULL, /* set_value_sinteger */
241 NULL, /* set_value_uinteger64 */
242 NULL, /* set_value_sinteger64 */
243 NULL, /* set_value_floating */
245 value_get, /* get_value */
246 NULL, /* get_value_uinteger */
247 NULL, /* get_value_sinteger */
248 NULL, /* get_value_uinteger64 */
249 NULL, /* get_value_sinteger64 */
250 NULL, /* get_value_floating */
259 NULL, /* XXX, cmp_contains, needed? ipv4 doesn't support it */
260 NULL, /* cmp_matches */
266 ftype_register(FT_IPv6, &ipv6_type);
270 * Editor modelines - http://www.wireshark.org/tools/modelines.html
275 * indent-tabs-mode: t
278 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
279 * :indentSize=8:tabSize=8:noTabs=false: