4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 2001 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <ftypes-int.h>
28 #include <epan/ipv6-utils.h>
29 #include <epan/addr_resolv.h>
30 #include <epan/emem.h>
33 ipv6_fvalue_set(fvalue_t
*fv
, gpointer value
, gboolean already_copied
)
35 g_assert(!already_copied
);
37 memcpy(fv
->value
.ipv6
.addr
.bytes
, value
, FT_IPv6_LEN
);
38 fv
->value
.ipv6
.prefix
= 128;
42 ipv6_from_unparsed(fvalue_t
*fv
, char *s
, gboolean allow_partial_value _U_
, LogFunc logfunc
)
44 char *has_slash
, *addr_str
;
45 unsigned int nmask_bits
;
46 fvalue_t
*nmask_fvalue
;
48 /* Look for prefix: Is there a single slash in the string? */
49 if ((has_slash
= strchr(s
, '/')))
50 addr_str
= ep_strndup(s
, has_slash
-s
);
54 if (!get_host_ipaddr6(addr_str
, &(fv
->value
.ipv6
.addr
))) {
55 logfunc("\"%s\" is not a valid hostname or IPv6 address.", s
);
61 /* XXX - this is inefficient */
62 nmask_fvalue
= fvalue_from_unparsed(FT_UINT32
, has_slash
+1, FALSE
, logfunc
);
66 nmask_bits
= fvalue_get_uinteger(nmask_fvalue
);
67 FVALUE_FREE(nmask_fvalue
);
69 if (nmask_bits
> 128) {
70 logfunc("Prefix in a IPv6 address should be <= 128, not %u",
74 fv
->value
.ipv6
.prefix
= nmask_bits
;
76 /* Not CIDR; mask covers entire address. */
77 fv
->value
.ipv6
.prefix
= 128;
84 ipv6_repr_len(fvalue_t
*fv _U_
, ftrepr_t rtype _U_
)
87 * 39 characters for "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX".
93 ipv6_to_repr(fvalue_t
*fv
, ftrepr_t rtype _U_
, char *buf
)
95 ip6_to_str_buf(&(fv
->value
.ipv6
.addr
), buf
);
99 value_get(fvalue_t
*fv
)
101 return fv
->value
.ipv6
.addr
.bytes
;
104 static const guint8 bitmasks
[9] =
105 { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
108 cmp_compare(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
110 const ipv6_addr
*a
= &(fv_a
->value
.ipv6
);
111 const ipv6_addr
*b
= &(fv_b
->value
.ipv6
);
115 prefix
= MIN(a
->prefix
, b
->prefix
); /* MIN() like IPv4 */
116 prefix
= MIN(prefix
, 128); /* sanitize, max prefix is 128 */
118 while (prefix
>= 8) {
119 gint byte_a
= (gint
) (a
->addr
.bytes
[pos
]);
120 gint byte_b
= (gint
) (b
->addr
.bytes
[pos
]);
122 if (byte_a
!= byte_b
)
123 return byte_a
- byte_b
;
130 gint byte_a
= (gint
) (a
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
131 gint byte_b
= (gint
) (b
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
133 if (byte_a
!= byte_b
)
134 return byte_a
- byte_b
;
140 cmp_eq(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
142 return (cmp_compare(fv_a
, fv_b
) == 0);
146 cmp_ne(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
148 return (cmp_compare(fv_a
, fv_b
) != 0);
152 cmp_gt(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
154 return (cmp_compare(fv_a
, fv_b
) > 0);
158 cmp_ge(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
160 return (cmp_compare(fv_a
, fv_b
) >= 0);
164 cmp_lt(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
166 return (cmp_compare(fv_a
, fv_b
) < 0);
170 cmp_le(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
172 return (cmp_compare(fv_a
, fv_b
) <= 0);
176 cmp_bitwise_and(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
178 const ipv6_addr
*a
= &(fv_a
->value
.ipv6
);
179 const ipv6_addr
*b
= &(fv_b
->value
.ipv6
);
183 prefix
= MIN(a
->prefix
, b
->prefix
); /* MIN() like in IPv4 */
184 prefix
= MIN(prefix
, 128); /* sanitize, max prefix is 128 */
186 while (prefix
>= 8) {
187 if (a
->addr
.bytes
[pos
] & b
->addr
.bytes
[pos
])
195 guint8 byte_a
= (a
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
196 guint8 byte_b
= (b
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
205 slice(fvalue_t
*fv
, GByteArray
*bytes
, guint offset
, guint length
)
207 /* XXX needed? ipv4 doesn't support slice() */
210 data
= fv
->value
.ipv6
.addr
.bytes
+ offset
;
212 g_byte_array_append(bytes
, data
, length
);
216 ftype_register_ipv6(void)
218 static ftype_t ipv6_type
= {
220 "FT_IPv6", /* name */
221 "IPv6 address", /* pretty_name */
222 FT_IPv6_LEN
, /* wire_size */
223 NULL
, /* new_value */
224 NULL
, /* free_value */
225 ipv6_from_unparsed
, /* val_from_unparsed */
226 NULL
, /* val_from_string */
227 ipv6_to_repr
, /* val_to_string_repr */
228 ipv6_repr_len
, /* len_string_repr */
230 ipv6_fvalue_set
, /* set_value */
231 NULL
, /* set_value_uinteger */
232 NULL
, /* set_value_sinteger */
233 NULL
, /* set_value_integer64 */
234 NULL
, /* set_value_floating */
236 value_get
, /* get_value */
237 NULL
, /* get_value_uinteger */
238 NULL
, /* get_value_sinteger */
239 NULL
, /* get_value_integer64 */
240 NULL
, /* get_value_floating */
249 NULL
, /* XXX, cmp_contains, needed? ipv4 doesn't support it */
250 NULL
, /* cmp_matches */
256 ftype_register(FT_IPv6
, &ipv6_type
);