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/to_str.h>
14 #include <wsutil/array.h>
16 #include <epan/exceptions.h>
17 #include <wsutil/ws_assert.h>
20 value_new(fvalue_t
*fv
)
22 fv
->value
.protocol
.tvb
= NULL
;
23 fv
->value
.protocol
.proto_string
= NULL
;
24 fv
->value
.protocol
.tvb_is_private
= false;
25 fv
->value
.protocol
.length
= -1;
29 value_copy(fvalue_t
*dst
, const fvalue_t
*src
)
31 dst
->value
.protocol
.tvb
= tvb_clone(src
->value
.protocol
.tvb
);
32 dst
->value
.protocol
.proto_string
= g_strdup(src
->value
.protocol
.proto_string
);
33 dst
->value
.protocol
.tvb_is_private
= true;
34 dst
->value
.protocol
.length
= src
->value
.protocol
.length
;
38 value_free(fvalue_t
*fv
)
40 if (fv
->value
.protocol
.tvb
&& fv
->value
.protocol
.tvb_is_private
) {
41 tvb_free_chain(fv
->value
.protocol
.tvb
);
43 g_free(fv
->value
.protocol
.proto_string
);
47 value_set(fvalue_t
*fv
, tvbuff_t
*value
, const char *name
, int length
)
49 /* Free up the old value, if we have one */
52 /* Set the protocol description and an (optional, nullable) tvbuff. */
53 fv
->value
.protocol
.tvb
= value
;
54 fv
->value
.protocol
.proto_string
= g_strdup(name
);
55 fv
->value
.protocol
.length
= length
;
59 val_from_string(fvalue_t
*fv
, const char *s
, size_t len
, char **err_msg _U_
)
62 uint8_t *private_data
;
64 /* Free up the old value, if we have one */
70 /* Make a tvbuff from the string. We can drop the
72 private_data
= (uint8_t *)g_memdup2(s
, (unsigned)len
);
73 new_tvb
= tvb_new_real_data(private_data
,
74 (unsigned)len
, (int)len
);
76 /* Let the tvbuff know how to delete the data. */
77 tvb_set_free_cb(new_tvb
, g_free
);
79 /* And let us know that we need to free the tvbuff */
80 fv
->value
.protocol
.tvb_is_private
= true;
81 /* This "field" is a value, it has no protocol description, but
82 * we might compare it to a protocol with NULL tvb.
83 * (e.g., proto_expert) */
84 fv
->value
.protocol
.tvb
= new_tvb
;
85 fv
->value
.protocol
.proto_string
= g_strdup("");
86 fv
->value
.protocol
.length
= -1;
91 val_from_literal(fvalue_t
*fv
, const char *s
, bool allow_partial_value _U_
, char **err_msg
)
96 /* Free up the old value, if we have one */
98 fv
->value
.protocol
.tvb
= NULL
;
99 fv
->value
.protocol
.proto_string
= NULL
;
100 fv
->value
.protocol
.length
= -1;
102 /* Does this look like a byte string? */
103 bytes
= byte_array_from_literal(s
, err_msg
);
105 /* Make a tvbuff from the bytes */
106 new_tvb
= tvb_new_real_data(bytes
->data
, bytes
->len
, bytes
->len
);
108 /* Let the tvbuff know how to delete the data. */
109 tvb_set_free_cb(new_tvb
, g_free
);
111 /* Free GByteArray, but keep data. */
112 g_byte_array_free(bytes
, false);
114 /* And let us know that we need to free the tvbuff */
115 fv
->value
.protocol
.tvb_is_private
= true;
116 fv
->value
.protocol
.tvb
= new_tvb
;
118 /* This "field" is a value, it has no protocol description, but
119 * we might compare it to a protocol with NULL tvb.
120 * (e.g., proto_expert) */
121 fv
->value
.protocol
.proto_string
= g_strdup("");
125 /* Not a byte array, forget about it. */
130 val_from_charconst(fvalue_t
*fv
, unsigned long num
, char **err_msg
)
135 /* Free up the old value, if we have one */
137 fv
->value
.protocol
.tvb
= NULL
;
138 fv
->value
.protocol
.proto_string
= NULL
;
139 fv
->value
.protocol
.length
= -1;
141 /* Does this look like a byte string? */
142 bytes
= byte_array_from_charconst(num
, err_msg
);
144 /* Make a tvbuff from the bytes */
145 new_tvb
= tvb_new_real_data(bytes
->data
, bytes
->len
, bytes
->len
);
147 /* Let the tvbuff know how to delete the data. */
148 tvb_set_free_cb(new_tvb
, g_free
);
150 /* Free GByteArray, but keep data. */
151 g_byte_array_free(bytes
, false);
153 /* And let us know that we need to free the tvbuff */
154 fv
->value
.protocol
.tvb_is_private
= true;
155 fv
->value
.protocol
.tvb
= new_tvb
;
157 /* This "field" is a value, it has no protocol description, but
158 * we might compare it to a protocol with NULL tvb.
159 * (e.g., proto_expert) */
160 fv
->value
.protocol
.proto_string
= g_strdup("");
164 /* Not a byte array, forget about it. */
169 val_to_repr(wmem_allocator_t
*scope
, const fvalue_t
*fv
, ftrepr_t rtype
, int field_display _U_
)
172 char *volatile buf
= NULL
;
174 if (rtype
!= FTREPR_DFILTER
)
178 if (fv
->value
.protocol
.length
>= 0)
179 length
= fv
->value
.protocol
.length
;
181 length
= tvb_captured_length(fv
->value
.protocol
.tvb
);
184 if (rtype
== FTREPR_DFILTER
)
185 buf
= bytes_to_dfilter_repr(scope
, tvb_get_ptr(fv
->value
.protocol
.tvb
, 0, length
), length
);
187 buf
= bytes_to_str_punct_maxlen(scope
, tvb_get_ptr(fv
->value
.protocol
.tvb
, 0, length
), length
, ':', 0);
198 value_get(fvalue_t
*fv
)
200 if (fv
->value
.protocol
.tvb
== NULL
)
202 if (fv
->value
.protocol
.length
< 0)
203 return fv
->value
.protocol
.tvb
;
204 return tvb_new_subset_length_caplen(fv
->value
.protocol
.tvb
, 0, fv
->value
.protocol
.length
, fv
->value
.protocol
.length
);
210 volatile unsigned length
= 0;
213 if (fv
->value
.protocol
.tvb
) {
214 if (fv
->value
.protocol
.length
>= 0)
215 length
= fv
->value
.protocol
.length
;
217 length
= tvb_captured_length(fv
->value
.protocol
.tvb
);
230 slice(fvalue_t
*fv
, GByteArray
*bytes
, unsigned offset
, unsigned length
)
233 volatile unsigned len
= length
;
235 if (fv
->value
.protocol
.tvb
) {
236 if (fv
->value
.protocol
.length
>= 0 && (unsigned)fv
->value
.protocol
.length
< len
) {
237 len
= fv
->value
.protocol
.length
;
241 data
= tvb_get_ptr(fv
->value
.protocol
.tvb
, offset
, len
);
242 g_byte_array_append(bytes
, data
, len
);
253 _tvbcmp(const protocol_value_t
*a
, const protocol_value_t
*b
)
259 a_len
= tvb_captured_length(a
->tvb
);
264 b_len
= tvb_captured_length(b
->tvb
);
269 return a_len
< b_len
? -1 : 1;
270 return memcmp(tvb_get_ptr(a
->tvb
, 0, a_len
), tvb_get_ptr(b
->tvb
, 0, a_len
), a_len
);
273 static enum ft_result
274 cmp_order(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
, int *cmp
)
276 const protocol_value_t
*a
= (const protocol_value_t
*)&fv_a
->value
.protocol
;
277 const protocol_value_t
*b
= (const protocol_value_t
*)&fv_b
->value
.protocol
;
281 if ((a
->tvb
!= NULL
) && (b
->tvb
!= NULL
)) {
284 c
= strcmp(a
->proto_string
, b
->proto_string
);
296 static enum ft_result
297 cmp_contains(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
, bool *contains
)
299 volatile bool yes
= false;
302 /* First see if tvb exists for both sides */
303 if ((fv_a
->value
.protocol
.tvb
!= NULL
) && (fv_b
->value
.protocol
.tvb
!= NULL
)) {
304 if (tvb_find_tvb(fv_a
->value
.protocol
.tvb
, fv_b
->value
.protocol
.tvb
, 0) > -1) {
308 /* Otherwise just compare strings */
309 if ((strlen(fv_b
->value
.protocol
.proto_string
) != 0) &&
310 strstr(fv_a
->value
.protocol
.proto_string
, fv_b
->value
.protocol
.proto_string
)) {
324 static enum ft_result
325 cmp_matches(const fvalue_t
*fv
, const ws_regex_t
*regex
, bool *matches
)
327 const protocol_value_t
*a
= (const protocol_value_t
*)&fv
->value
.protocol
;
328 volatile bool rc
= false;
329 const char *data
= NULL
; /* tvb data */
330 uint32_t tvb_len
; /* tvb length */
336 if (a
->tvb
!= NULL
) {
337 tvb_len
= tvb_captured_length(a
->tvb
);
338 data
= (const char *)tvb_get_ptr(a
->tvb
, 0, tvb_len
);
339 rc
= ws_regex_matches_length(regex
, data
, tvb_len
);
341 rc
= ws_regex_matches(regex
, a
->proto_string
);
354 val_hash(const fvalue_t
*fv
)
356 const protocol_value_t
*value
= &fv
->value
.protocol
;
357 return g_direct_hash(value
->tvb
) ^ g_int_hash(&value
->length
) ^ g_str_hash(value
->proto_string
);
361 is_zero(const fvalue_t
*fv
)
363 const protocol_value_t
*a
= &fv
->value
.protocol
;
364 return a
->tvb
== NULL
&& a
->proto_string
== NULL
;
368 ftype_register_tvbuff(void)
371 static const ftype_t protocol_type
= {
372 FT_PROTOCOL
, /* ftype */
374 value_new
, /* new_value */
375 value_copy
, /* copy_value */
376 value_free
, /* free_value */
377 val_from_literal
, /* val_from_literal */
378 val_from_string
, /* val_from_string */
379 val_from_charconst
, /* val_from_charconst */
380 NULL
, /* val_from_uinteger64 */
381 NULL
, /* val_from_sinteger64 */
382 NULL
, /* val_from_double */
383 val_to_repr
, /* val_to_string_repr */
385 NULL
, /* val_to_uinteger64 */
386 NULL
, /* val_to_sinteger64 */
387 NULL
, /* val_to_double */
389 { .set_value_protocol
= value_set
}, /* union set_value */
390 { .get_value_protocol
= value_get
}, /* union get_value */
402 NULL
, /* unary_minus */
411 ftype_register(FT_PROTOCOL
, &protocol_type
);
415 ftype_register_pseudofields_tvbuff(int proto
)
417 static int hf_ft_protocol
;
419 static hf_register_info hf_ftypes
[] = {
421 { "FT_PROTOCOL", "_ws.ftypes.protocol",
422 FT_PROTOCOL
, BASE_NONE
, NULL
, 0x00,
427 proto_register_field_array(proto
, hf_ftypes
, array_length(hf_ftypes
));
431 * Editor modelines - https://www.wireshark.org/tools/modelines.html
436 * indent-tabs-mode: t
439 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
440 * :indentSize=8:tabSize=8:noTabs=false: