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.
26 #include <ftypes-int.h>
29 #include <epan/exceptions.h>
31 #define CMP_MATCHES cmp_matches
33 #define tvb_is_private fvalue_gboolean1
36 value_new(fvalue_t
*fv
)
39 fv
->tvb_is_private
= FALSE
;
43 value_free(fvalue_t
*fv
)
45 if (fv
->value
.tvb
&& fv
->tvb_is_private
) {
46 tvb_free_chain(fv
->value
.tvb
);
51 value_set(fvalue_t
*fv
, gpointer value
, gboolean already_copied
)
53 g_assert(already_copied
);
55 /* Free up the old value, if we have one */
58 fv
->value
.tvb
= (tvbuff_t
*)value
;
62 free_tvb_data(void *data
)
68 val_from_string(fvalue_t
*fv
, char *s
, LogFunc logfunc _U_
)
73 /* Free up the old value, if we have one */
76 /* Make a tvbuff from the string. We can drop the
78 private_data
= (guint8
*)g_memdup(s
, (guint
)strlen(s
));
79 new_tvb
= tvb_new_real_data(private_data
,
80 (guint
)strlen(s
), (gint
)strlen(s
));
82 /* Let the tvbuff know how to delete the data. */
83 tvb_set_free_cb(new_tvb
, free_tvb_data
);
85 /* And let us know that we need to free the tvbuff */
86 fv
->tvb_is_private
= TRUE
;
87 fv
->value
.tvb
= new_tvb
;
92 val_from_unparsed(fvalue_t
*fv
, char *s
, gboolean allow_partial_value _U_
, LogFunc logfunc
)
98 /* Free up the old value, if we have one */
101 /* Does this look like a byte string? */
102 fv_bytes
= fvalue_from_unparsed(FT_BYTES
, s
, TRUE
, NULL
);
104 /* Make a tvbuff from the bytes */
105 private_data
= (guint8
*)g_memdup(fv_bytes
->value
.bytes
->data
,
106 fv_bytes
->value
.bytes
->len
);
107 new_tvb
= tvb_new_real_data(private_data
,
108 fv_bytes
->value
.bytes
->len
,
109 fv_bytes
->value
.bytes
->len
);
111 /* Let the tvbuff know how to delete the data. */
112 tvb_set_free_cb(new_tvb
, free_tvb_data
);
114 /* And let us know that we need to free the tvbuff */
115 fv
->tvb_is_private
= TRUE
;
116 fv
->value
.tvb
= new_tvb
;
120 /* Treat it as a string. */
121 return val_from_string(fv
, s
, logfunc
);
125 val_repr_len(fvalue_t
*fv
, ftrepr_t rtype
)
127 volatile guint length
= 0;
129 if (rtype
!= FTREPR_DFILTER
) return -1;
132 /* 3 bytes for each byte of the byte "NN:" minus 1 byte
133 * as there's no trailing ":". */
134 length
= tvb_length(fv
->value
.tvb
) * 3 - 1;
145 val_to_repr(fvalue_t
*fv
, ftrepr_t rtype
, char * volatile buf
)
151 g_assert(rtype
== FTREPR_DFILTER
);
154 length
= tvb_length(fv
->value
.tvb
);
155 c
= tvb_get_ptr(fv
->value
.tvb
, 0, length
);
157 for (i
= 0; i
< length
; i
++) {
159 sprintf((char *)buf
, "%02x", *c
++);
163 sprintf((char *)buf
, ":%02x", *c
++);
175 value_get(fvalue_t
*fv
)
177 return fv
->value
.tvb
;
183 volatile guint length
= 0;
187 length
= tvb_length(fv
->value
.tvb
);
198 slice(fvalue_t
*fv
, GByteArray
*bytes
, guint offset
, guint length
)
204 data
= tvb_get_ptr(fv
->value
.tvb
, offset
, length
);
205 g_byte_array_append(bytes
, data
, length
);
216 cmp_eq(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
218 tvbuff_t
*a
= fv_a
->value
.tvb
;
219 tvbuff_t
*b
= fv_b
->value
.tvb
;
220 volatile gboolean eq
= FALSE
;
223 guint a_len
= tvb_length(a
);
225 if (a_len
== tvb_length(b
))
226 eq
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) == 0);
237 cmp_ne(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
239 tvbuff_t
*a
= fv_a
->value
.tvb
;
240 tvbuff_t
*b
= fv_b
->value
.tvb
;
241 volatile gboolean ne
= TRUE
;
244 guint a_len
= tvb_length(a
);
246 if (a_len
== tvb_length(b
)) {
247 ne
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) != 0);
259 cmp_gt(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
261 tvbuff_t
*a
= fv_a
->value
.tvb
;
262 tvbuff_t
*b
= fv_b
->value
.tvb
;
263 volatile gboolean gt
= FALSE
;
266 guint a_len
= tvb_length(a
);
267 guint b_len
= tvb_length(b
);
271 } else if (a_len
== b_len
) {
272 gt
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) > 0);
284 cmp_ge(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
286 tvbuff_t
*a
= fv_a
->value
.tvb
;
287 tvbuff_t
*b
= fv_b
->value
.tvb
;
288 volatile gboolean ge
= FALSE
;
291 guint a_len
= tvb_length(a
);
292 guint b_len
= tvb_length(b
);
296 } else if (a_len
== b_len
) {
297 ge
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) >= 0);
309 cmp_lt(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
311 tvbuff_t
*a
= fv_a
->value
.tvb
;
312 tvbuff_t
*b
= fv_b
->value
.tvb
;
313 volatile gboolean lt
= FALSE
;
316 guint a_len
= tvb_length(a
);
317 guint b_len
= tvb_length(b
);
321 } else if (a_len
== b_len
) {
322 lt
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) < 0);
334 cmp_le(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
336 tvbuff_t
*a
= fv_a
->value
.tvb
;
337 tvbuff_t
*b
= fv_b
->value
.tvb
;
338 volatile gboolean le
= FALSE
;
341 guint a_len
= tvb_length(a
);
342 guint b_len
= tvb_length(b
);
346 } else if (a_len
== b_len
) {
347 le
= (memcmp(tvb_get_ptr(a
, 0, a_len
), tvb_get_ptr(b
, 0, a_len
), a_len
) <= 0);
359 cmp_contains(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
361 volatile gboolean contains
= FALSE
;
364 if (tvb_find_tvb(fv_a
->value
.tvb
, fv_b
->value
.tvb
, 0) > -1) {
377 cmp_matches(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
)
379 tvbuff_t
*tvb
= fv_a
->value
.tvb
;
380 GRegex
*regex
= fv_b
->value
.re
;
381 volatile gboolean rc
= FALSE
;
382 const char *data
= NULL
; /* tvb data */
383 guint32 tvb_len
; /* tvb length */
385 /* fv_b is always a FT_PCRE, otherwise the dfilter semcheck() would have
386 * warned us. For the same reason (and because we're using g_malloc()),
387 * fv_b->value.re is not NULL.
389 if (strcmp(fv_b
->ftype
->name
, "FT_PCRE") != 0) {
396 tvb_len
= tvb_length(tvb
);
397 data
= (const char *)tvb_get_ptr(tvb
, 0, tvb_len
);
398 rc
= g_regex_match_full(
399 regex
, /* Compiled PCRE */
400 data
, /* The data to check for the pattern... */
401 tvb_len
, /* ... and its length */
402 0, /* Start offset within data */
403 (GRegexMatchFlags
)0, /* GRegexMatchFlags */
404 NULL
, /* We are not interested in the match information */
405 NULL
/* We don't want error information */
407 /* NOTE - DO NOT g_free(data) */
417 ftype_register_tvbuff(void)
420 static ftype_t protocol_type
= {
421 FT_PROTOCOL
, /* ftype */
422 "FT_PROTOCOL", /* name */
423 "Protocol", /* pretty_name */
425 value_new
, /* new_value */
426 value_free
, /* free_value */
427 val_from_unparsed
, /* val_from_unparsed */
428 val_from_string
, /* val_from_string */
429 val_to_repr
, /* val_to_string_repr */
430 val_repr_len
, /* len_string_repr */
432 value_set
, /* set_value */
433 NULL
, /* set_value_uinteger */
434 NULL
, /* set_value_sinteger */
435 NULL
, /* set_value_integer64 */
436 NULL
, /* set_value_floating */
438 value_get
, /* get_value */
439 NULL
, /* get_value_uinteger */
440 NULL
, /* get_value_sinteger */
441 NULL
, /* get_value_integer64 */
442 NULL
, /* get_value_floating */
450 NULL
, /* cmp_bitwise_and */
460 ftype_register(FT_PROTOCOL
, &protocol_type
);