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>
15 #include <wsutil/ws_assert.h>
16 #include <wsutil/array.h>
17 #include <wsutil/strtoi.h>
21 string_fvalue_new(fvalue_t
*fv
)
23 fv
->value
.strbuf
= NULL
;
27 string_fvalue_copy(fvalue_t
*dst
, const fvalue_t
*src
)
29 dst
->value
.strbuf
= wmem_strbuf_dup(NULL
, src
->value
.strbuf
);
33 string_fvalue_free(fvalue_t
*fv
)
35 wmem_strbuf_destroy(fv
->value
.strbuf
);
39 string_fvalue_set_strbuf(fvalue_t
*fv
, wmem_strbuf_t
*value
)
41 DISSECTOR_ASSERT(value
!= NULL
);
43 /* Free up the old value, if we have one */
44 string_fvalue_free(fv
);
46 fv
->value
.strbuf
= value
;
50 string_to_repr(wmem_allocator_t
*scope
, const fvalue_t
*fv
, ftrepr_t rtype _U_
, int field_display _U_
)
52 if (rtype
== FTREPR_DISPLAY
|| rtype
== FTREPR_JSON
|| rtype
== FTREPR_RAW
) {
53 /* XXX: This escapes NUL with "\0", but JSON (neither RFC 8259 nor
54 * ECMA-404) does not allow that, it must be "\u0000".
56 return ws_escape_null(scope
, fv
->value
.strbuf
->str
, fv
->value
.strbuf
->len
, false);
58 if (rtype
== FTREPR_DFILTER
) {
59 return ws_escape_string_len(scope
, fv
->value
.strbuf
->str
, fv
->value
.strbuf
->len
, true);
61 ws_assert_not_reached();
65 static const wmem_strbuf_t
*
66 value_get(fvalue_t
*fv
)
68 return fv
->value
.strbuf
;
72 val_from_string(fvalue_t
*fv
, const char *s
, size_t len
, char **err_msg _U_
)
74 /* Free up the old value, if we have one */
75 string_fvalue_free(fv
);
78 fv
->value
.strbuf
= wmem_strbuf_new_len(NULL
, s
, len
);
80 fv
->value
.strbuf
= wmem_strbuf_new(NULL
, s
);
86 val_from_literal(fvalue_t
*fv
, const char *s
, bool allow_partial_value _U_
, char **err_msg
)
88 /* Just turn it into a string */
89 /* XXX Should probably be a syntax error instead. It's more user-friendly to ask the
90 * user to be explicit about the meaning of an unquoted literal than them trying to figure out
91 * why a valid filter expression is giving wrong results. */
92 return val_from_string(fv
, s
, 0, err_msg
);
96 val_from_charconst(fvalue_t
*fv
, unsigned long num
, char **err_msg
)
98 /* XXX Should be a syntax error if literal is also a syntax error. */
100 /* Free up the old value, if we have one */
101 string_fvalue_free(fv
);
102 fv
->value
.strbuf
= NULL
;
104 if (num
> UINT8_MAX
) {
106 *err_msg
= ws_strdup_printf("%lu is too large for a byte value", num
);
112 fv
->value
.strbuf
= wmem_strbuf_new(NULL
, NULL
);
113 wmem_strbuf_append_c(fv
->value
.strbuf
, c
);
119 string_hash(const fvalue_t
*fv
)
121 return g_str_hash(wmem_strbuf_get_str(fv
->value
.strbuf
));
125 string_is_zero(const fvalue_t
*fv
)
127 return fv
->value
.strbuf
== NULL
|| fv
->value
.strbuf
->len
== 0;
133 /* g_utf8_strlen returns long for no apparent reason*/
134 long len
= g_utf8_strlen(fv
->value
.strbuf
->str
, -1);
137 return (unsigned)len
;
141 slice(fvalue_t
*fv
, wmem_strbuf_t
*buf
, unsigned offset
, unsigned length
)
143 const char *str
= fv
->value
.strbuf
->str
;
145 /* Go to the starting offset */
146 const char *p
= g_utf8_offset_to_pointer(str
, (long)offset
);
148 /* Copy 'length' codepoints to dst. Skip the terminating NULL */
149 while (*p
!= '\0' && length
-- > 0) {
150 n
= g_utf8_next_char(p
);
151 /* Append n - p bytes (one codepoint)*/
152 wmem_strbuf_append_len(buf
, p
, n
- p
);
157 static enum ft_result
158 cmp_order(const fvalue_t
*a
, const fvalue_t
*b
, int *cmp
)
160 *cmp
= wmem_strbuf_strcmp(a
->value
.strbuf
, b
->value
.strbuf
);
164 static enum ft_result
165 cmp_contains(const fvalue_t
*fv_a
, const fvalue_t
*fv_b
, bool *contains
)
168 * http://www.introl.com/introl-demo/Libraries/C/ANSI_C/string/strstr.html
169 * strstr() returns a non-NULL value if needle is an empty
170 * string. We don't that behavior for cmp_contains. */
171 if (fv_b
->value
.strbuf
->len
== 0) {
176 if (wmem_strbuf_strstr(fv_a
->value
.strbuf
, fv_b
->value
.strbuf
)) {
186 static enum ft_result
187 cmp_matches(const fvalue_t
*fv
, const ws_regex_t
*regex
, bool *matches
)
189 wmem_strbuf_t
*buf
= fv
->value
.strbuf
;
195 *matches
= ws_regex_matches_length(regex
, buf
->str
, buf
->len
);
200 ax25_from_string(fvalue_t
*fv
, const char *s
, size_t len
, char **err_msg _U_
)
202 /* See section 3.12 "Address-Field Encoding" of the AX.25
205 * http://www.itu.int/ITU-R/terrestrial/docs/fixedmobile/fxm-art19-sec3.pdf
211 const char *end
= s
+ len
;
212 const char *hyphen
= strchr(s
, '-');
213 if (hyphen
== NULL
) {
217 if (s
== hyphen
|| (hyphen
- s
) > 6) {
219 *err_msg
= ws_strdup_printf("\"%s\" is not a valid AX.25 address, the callsign must be 1-6 alphanumeric ASCII characters.", s
);
223 for (p
= s
; p
!= hyphen
; p
++) {
224 if (!g_ascii_isalnum(*p
)) {
226 *err_msg
= ws_strdup_printf("\"%s\" is not a valid AX.25 address, the callsign must be alphanumeric ASCII characters.", s
);
232 if (!ws_strtou8(hyphen
+ 1, NULL
, &ssid
)) {
234 *err_msg
= ws_strdup_printf("\"%s\" is not a valid AX.25 SSID (must be a number between 0 and 15).", hyphen
+ 1);
239 *err_msg
= ws_strdup_printf("%u is too large to be an AX.25 SSID (must be between 0 and 15)", ssid
);
244 /* OK, it looks valid. Allow the user to enter lower-case letters. */
245 char *str
= g_ascii_strup(s
, len
);
246 bool ret
= val_from_string(fv
, str
, len
, err_msg
);
252 ax25_from_literal(fvalue_t
*fv
, const char *s
, bool allow_partial_value _U_
, char **err_msg
)
254 return ax25_from_string(fv
, s
, 0, err_msg
);
258 ftype_register_string(void)
261 static const ftype_t string_type
= {
262 FT_STRING
, /* ftype */
264 string_fvalue_new
, /* new_value */
265 string_fvalue_copy
, /* copy_value */
266 string_fvalue_free
, /* free_value */
267 val_from_literal
, /* val_from_literal */
268 val_from_string
, /* val_from_string */
269 val_from_charconst
, /* val_from_charconst */
270 NULL
, /* val_from_uinteger64 */
271 NULL
, /* val_from_sinteger64 */
272 NULL
, /* val_from_double */
273 string_to_repr
, /* val_to_string_repr */
275 NULL
, /* val_to_uinteger64 */
276 NULL
, /* val_to_sinteger64 */
277 NULL
, /* val_to_double */
279 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
280 { .get_value_strbuf
= value_get
}, /* union get_value */
286 string_hash
, /* hash */
287 string_is_zero
, /* is_zero */
288 NULL
, /* is_negative */
291 NULL
, /* bitwise_and */
292 NULL
, /* unary_minus */
299 static const ftype_t stringz_type
= {
300 FT_STRINGZ
, /* ftype */
302 string_fvalue_new
, /* new_value */
303 string_fvalue_copy
, /* copy_value */
304 string_fvalue_free
, /* free_value */
305 val_from_literal
, /* val_from_literal */
306 val_from_string
, /* val_from_string */
307 val_from_charconst
, /* val_from_charconst */
308 NULL
, /* val_from_uinteger64 */
309 NULL
, /* val_from_sinteger64 */
310 NULL
, /* val_from_double */
311 string_to_repr
, /* val_to_string_repr */
313 NULL
, /* val_to_uinteger64 */
314 NULL
, /* val_to_sinteger64 */
315 NULL
, /* val_to_double */
317 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
318 { .get_value_strbuf
= value_get
}, /* union get_value */
321 cmp_contains
, /* cmp_contains */
324 string_hash
, /* hash */
325 string_is_zero
, /* is_zero */
326 NULL
, /* is_negative */
329 NULL
, /* bitwise_and */
330 NULL
, /* unary_minus */
337 static const ftype_t uint_string_type
= {
338 FT_UINT_STRING
, /* ftype */
340 string_fvalue_new
, /* new_value */
341 string_fvalue_copy
, /* copy_value */
342 string_fvalue_free
, /* free_value */
343 val_from_literal
, /* val_from_literal */
344 val_from_string
, /* val_from_string */
345 val_from_charconst
, /* val_from_charconst */
346 NULL
, /* val_from_uinteger64 */
347 NULL
, /* val_from_sinteger64 */
348 NULL
, /* val_from_double */
349 string_to_repr
, /* val_to_string_repr */
351 NULL
, /* val_to_uinteger64 */
352 NULL
, /* val_to_sinteger64 */
353 NULL
, /* val_to_double */
355 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
356 { .get_value_strbuf
= value_get
}, /* union get_value */
359 cmp_contains
, /* cmp_contains */
362 string_hash
, /* hash */
363 string_is_zero
, /* is_zero */
364 NULL
, /* is_negative */
367 NULL
, /* bitwise_and */
368 NULL
, /* unary_minus */
375 static const ftype_t stringzpad_type
= {
376 FT_STRINGZPAD
, /* ftype */
378 string_fvalue_new
, /* new_value */
379 string_fvalue_copy
, /* copy_value */
380 string_fvalue_free
, /* free_value */
381 val_from_literal
, /* val_from_literal */
382 val_from_string
, /* val_from_string */
383 val_from_charconst
, /* val_from_charconst */
384 NULL
, /* val_from_uinteger64 */
385 NULL
, /* val_from_sinteger64 */
386 NULL
, /* val_from_double */
387 string_to_repr
, /* val_to_string_repr */
389 NULL
, /* val_to_uinteger64 */
390 NULL
, /* val_to_sinteger64 */
391 NULL
, /* val_to_double */
393 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
394 { .get_value_strbuf
= value_get
}, /* union get_value */
397 cmp_contains
, /* cmp_contains */
400 string_hash
, /* hash */
401 string_is_zero
, /* is_zero */
402 NULL
, /* is_negative */
405 NULL
, /* bitwise_and */
406 NULL
, /* unary_minus */
413 static const ftype_t stringztrunc_type
= {
414 FT_STRINGZTRUNC
, /* ftype */
416 string_fvalue_new
, /* new_value */
417 string_fvalue_copy
, /* copy_value */
418 string_fvalue_free
, /* free_value */
419 val_from_literal
, /* val_from_literal */
420 val_from_string
, /* val_from_string */
421 val_from_charconst
, /* val_from_charconst */
422 NULL
, /* val_from_uinteger64 */
423 NULL
, /* val_from_sinteger64 */
424 NULL
, /* val_from_double */
425 string_to_repr
, /* val_to_string_repr */
427 NULL
, /* val_to_uinteger64 */
428 NULL
, /* val_to_sinteger64 */
429 NULL
, /* val_to_double */
431 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
432 { .get_value_strbuf
= value_get
}, /* union get_value */
435 cmp_contains
, /* cmp_contains */
438 string_hash
, /* hash */
439 string_is_zero
, /* is_zero */
440 NULL
, /* is_negative */
443 NULL
, /* bitwise_and */
444 NULL
, /* unary_minus */
451 static const ftype_t ax25_type
= {
453 FT_AX25_ADDR_LEN
, /* wire_size */
454 string_fvalue_new
, /* new_value */
455 string_fvalue_copy
, /* copy_value */
456 string_fvalue_free
, /* free_value */
457 ax25_from_literal
, /* val_from_literal */
458 ax25_from_string
, /* val_from_string */
459 NULL
, /* val_from_charconst */
460 NULL
, /* val_from_uinteger64 */
461 NULL
, /* val_from_sinteger64 */
462 NULL
, /* val_from_double */
463 string_to_repr
, /* val_to_string_repr */
465 NULL
, /* val_to_uinteger64 */
466 NULL
, /* val_to_sinteger64 */
467 NULL
, /* val_to_double */
469 { .set_value_strbuf
= string_fvalue_set_strbuf
}, /* union set_value */
470 { .get_value_strbuf
= value_get
}, /* union get_value */
476 string_hash
, /* hash */
477 string_is_zero
, /* is_zero */
478 NULL
, /* is_negative */
481 NULL
, /* bitwise_and */
482 NULL
, /* unary_minus */
491 ftype_register(FT_STRING
, &string_type
);
492 ftype_register(FT_STRINGZ
, &stringz_type
);
493 ftype_register(FT_UINT_STRING
, &uint_string_type
);
494 ftype_register(FT_STRINGZPAD
, &stringzpad_type
);
495 ftype_register(FT_STRINGZTRUNC
, &stringztrunc_type
);
496 ftype_register(FT_AX25
, &ax25_type
);
500 ftype_register_pseudofields_string(int proto
)
502 static int hf_ft_string
;
503 static int hf_ft_stringz
;
504 static int hf_ft_uint_string
;
505 static int hf_ft_stringzpad
;
506 static int hf_ft_stringztrunc
;
507 static int hf_ft_ax25
;
509 static hf_register_info hf_ftypes
[] = {
511 { "FT_STRING", "_ws.ftypes.string",
512 FT_STRING
, BASE_NONE
, NULL
, 0x00,
516 { "FT_STRINGZ", "_ws.ftypes.stringz",
517 FT_STRINGZ
, BASE_NONE
, NULL
, 0x00,
520 { &hf_ft_uint_string
,
521 { "FT_UINT_STRING", "_ws.ftypes.uint_string",
522 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00,
526 { "FT_STRINGZPAD", "_ws.ftypes.stringzpad",
527 FT_STRINGZPAD
, BASE_NONE
, NULL
, 0x00,
530 { &hf_ft_stringztrunc
,
531 { "FT_STRINGZTRUNC", "_ws.ftypes.stringztrunc",
532 FT_STRINGZTRUNC
, BASE_NONE
, NULL
, 0x00,
536 { "FT_AX25", "_ws.ftypes.ax25",
537 FT_AX25
, BASE_NONE
, NULL
, 0x00,
542 proto_register_field_array(proto
, hf_ftypes
, array_length(hf_ftypes
));
546 * Editor modelines - https://www.wireshark.org/tools/modelines.html
551 * indent-tabs-mode: t
554 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
555 * :indentSize=8:tabSize=8:noTabs=false: