2 * Wireshark - Network traffic analyzer
3 * By Gerald Combs <gerald@wireshark.org>
4 * Copyright 2001 Gerald Combs
6 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include <ftypes-int.h>
12 #include <epan/addr_resolv.h>
13 #include <epan/to_str.h>
14 #include <wsutil/inet_cidr.h>
15 #include <wsutil/strtoi.h>
16 #include <wsutil/array.h>
19 ipv6_from_literal(fvalue_t
*fv
, const char *s
, bool allow_partial_value _U_
, char **err_msg
)
23 char *addr_str_to_free
= NULL
;
27 /* Look for prefix: Is there a single slash in the string? */
28 slash
= strchr(s
, '/');
30 /* Make a copy of the string up to but not including the
31 * slash; that's the address portion. */
32 addr_str_to_free
= wmem_strndup(NULL
, s
, slash
-s
);
33 addr_str
= addr_str_to_free
;
38 if (!get_host_ipaddr6(addr_str
, &(fv
->value
.ipv6
.addr
))) {
40 *err_msg
= ws_strdup_printf("\"%s\" is not a valid hostname or IPv6 address.", s
);
42 wmem_free(NULL
, addr_str_to_free
);
47 wmem_free(NULL
, addr_str_to_free
);
51 if(!ws_strtou32(slash
+1, &endptr
, &nmask_bits
) || *endptr
!= '\0') {
52 if (err_msg
!= NULL
) {
53 *err_msg
= ws_strdup_printf("%s in not a valid mask", slash
+1);
57 if (nmask_bits
> 128) {
58 if (err_msg
!= NULL
) {
59 *err_msg
= ws_strdup_printf("Prefix in a IPv6 address should be <= 128, not %u",
64 fv
->value
.ipv6
.prefix
= nmask_bits
;
66 /* Not CIDR; mask covers entire address. */
67 fv
->value
.ipv6
.prefix
= 128;
74 ipv6_to_repr(wmem_allocator_t
*scope
, const fvalue_t
*fv
, ftrepr_t rtype _U_
, int field_display _U_
)
76 char buf
[WS_INET6_ADDRSTRLEN
];
79 ip6_to_str_buf(&fv
->value
.ipv6
.addr
, buf
, sizeof(buf
));
81 if (fv
->value
.ipv6
.prefix
!= 0 && fv
->value
.ipv6
.prefix
!= 128)
82 repr
= wmem_strdup_printf(scope
, "%s/%"PRIu32
, buf
, fv
->value
.ipv6
.prefix
);
84 repr
= wmem_strdup(scope
, buf
);
90 ipv6_set(fvalue_t
*fv
, const ipv6_addr_and_prefix
*value
)
92 fv
->value
.ipv6
= *value
;
95 static const ipv6_addr_and_prefix
*
96 ipv6_get(fvalue_t
*fv
)
98 return &fv
->value
.ipv6
;
101 static const uint8_t bitmasks
[9] =
102 { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
104 static enum ft_result
105 cmp_order(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
, int *cmp
)
107 const ipv6_addr_and_prefix
*a
= &(fv_a
->value
.ipv6
);
108 const ipv6_addr_and_prefix
*b
= &(fv_b
->value
.ipv6
);
112 prefix
= MIN(a
->prefix
, b
->prefix
); /* MIN() like IPv4 */
113 prefix
= MIN(prefix
, 128); /* sanitize, max prefix is 128 */
115 while (prefix
>= 8) {
116 int byte_a
= (int) (a
->addr
.bytes
[pos
]);
117 int byte_b
= (int) (b
->addr
.bytes
[pos
]);
119 if (byte_a
!= byte_b
) {
120 *cmp
= byte_a
- byte_b
;
129 int byte_a
= (int) (a
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
130 int byte_b
= (int) (b
->addr
.bytes
[pos
] & (bitmasks
[prefix
]));
132 if (byte_a
!= byte_b
) {
133 *cmp
= byte_a
- byte_b
;
141 static enum ft_result
142 bitwise_and(fvalue_t
*dst
, const fvalue_t
*fv_a
, const fvalue_t
*fv_b
, char **err_ptr _U_
)
144 const ipv6_addr_and_prefix
*a
= &(fv_a
->value
.ipv6
);
145 const ipv6_addr_and_prefix
*b
= &(fv_b
->value
.ipv6
);
149 prefix
= MIN(a
->prefix
, b
->prefix
); /* MIN() like in IPv4 */
150 prefix
= MIN(prefix
, 128); /* sanitize, max prefix is 128 */
152 while (prefix
>= 8) {
153 dst
->value
.ipv6
.addr
.bytes
[pos
] =
154 a
->addr
.bytes
[pos
] & b
->addr
.bytes
[pos
];
161 dst
->value
.ipv6
.addr
.bytes
[pos
] =
162 a
->addr
.bytes
[pos
] & b
->addr
.bytes
[pos
] & bitmasks
[prefix
];
168 len(fvalue_t
*fv _U_
)
174 slice(fvalue_t
*fv
, GByteArray
*bytes
, unsigned offset
, unsigned length
)
178 data
= fv
->value
.ipv6
.addr
.bytes
+ offset
;
180 g_byte_array_append(bytes
, data
, length
);
184 ipv6_hash(const fvalue_t
*fv
)
188 } *addr
= (struct _ipv6
*)&fv
->value
.ipv6
.addr
;
189 int64_t mask
= fv
->value
.ipv6
.prefix
;
191 return g_int64_hash(&addr
->val
[0]) ^ g_int64_hash(&addr
->val
[1]) ^ g_int64_hash(&mask
);
195 is_zero(const fvalue_t
*fv_a
)
197 ws_in6_addr zero
= { 0 };
198 return memcmp(&fv_a
->value
.ipv6
.addr
, &zero
, sizeof(ws_in6_addr
)) == 0;
202 ftype_register_ipv6(void)
204 static const ftype_t ipv6_type
= {
206 FT_IPv6_LEN
, /* wire_size */
207 NULL
, /* new_value */
208 NULL
, /* copy_value */
209 NULL
, /* free_value */
210 ipv6_from_literal
, /* val_from_literal */
211 NULL
, /* val_from_string */
212 NULL
, /* val_from_charconst */
213 NULL
, /* val_from_uinteger64 */
214 NULL
, /* val_from_sinteger64 */
215 NULL
, /* val_from_double */
216 ipv6_to_repr
, /* val_to_string_repr */
218 NULL
, /* val_to_uinteger64 */
219 NULL
, /* val_to_sinteger64 */
220 NULL
, /* val_to_double */
222 { .set_value_ipv6
= ipv6_set
}, /* union set_value */
223 { .get_value_ipv6
= ipv6_get
}, /* union get_value */
226 NULL
, /* XXX, cmp_contains, needed? ipv4 doesn't support it */
227 NULL
, /* cmp_matches */
235 NULL
, /* unary_minus */
243 ftype_register(FT_IPv6
, &ipv6_type
);
247 ftype_register_pseudofields_ipv6(int proto
)
249 static int hf_ft_ipv6
;
251 static hf_register_info hf_ftypes
[] = {
253 { "FT_IPv6", "_ws.ftypes.ipv6",
254 FT_IPv6
, BASE_NONE
, NULL
, 0x00,
259 proto_register_field_array(proto
, hf_ftypes
, array_length(hf_ftypes
));
263 * Editor modelines - https://www.wireshark.org/tools/modelines.html
268 * indent-tabs-mode: t
271 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
272 * :indentSize=8:tabSize=8:noTabs=false: