Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / ftypes / ftype-string.c
blob5f1c2300c52aca2a34b0ca687a285a3e7f981754
1 /*
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
7 */
9 #include "config.h"
11 #include <ftypes-int.h>
12 #include <string.h>
14 #include <strutil.h>
15 #include <wsutil/ws_assert.h>
16 #include <wsutil/array.h>
17 #include <wsutil/strtoi.h>
20 static void
21 string_fvalue_new(fvalue_t *fv)
23 fv->value.strbuf = NULL;
26 static void
27 string_fvalue_copy(fvalue_t *dst, const fvalue_t *src)
29 dst->value.strbuf = wmem_strbuf_dup(NULL, src->value.strbuf);
32 static void
33 string_fvalue_free(fvalue_t *fv)
35 wmem_strbuf_destroy(fv->value.strbuf);
38 static void
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;
49 static char *
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;
71 static bool
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);
77 if (len > 0)
78 fv->value.strbuf = wmem_strbuf_new_len(NULL, s, len);
79 else
80 fv->value.strbuf = wmem_strbuf_new(NULL, s);
82 return true;
85 static bool
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);
95 static bool
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) {
105 if (err_msg) {
106 *err_msg = ws_strdup_printf("%lu is too large for a byte value", num);
108 return false;
111 char c = (char)num;
112 fv->value.strbuf = wmem_strbuf_new(NULL, NULL);
113 wmem_strbuf_append_c(fv->value.strbuf, c);
115 return true;
118 static unsigned
119 string_hash(const fvalue_t *fv)
121 return g_str_hash(wmem_strbuf_get_str(fv->value.strbuf));
124 static bool
125 string_is_zero(const fvalue_t *fv)
127 return fv->value.strbuf == NULL || fv->value.strbuf->len == 0;
130 static unsigned
131 len(fvalue_t *fv)
133 /* g_utf8_strlen returns long for no apparent reason*/
134 long len = g_utf8_strlen(fv->value.strbuf->str, -1);
135 if (len < 0)
136 return 0;
137 return (unsigned)len;
140 static void
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);
147 const char *n;
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);
153 p = n;
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);
161 return FT_OK;
164 static enum ft_result
165 cmp_contains(const fvalue_t *fv_a, const fvalue_t *fv_b, bool *contains)
167 /* According to
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) {
172 *contains = false;
173 return FT_OK;
176 if (wmem_strbuf_strstr(fv_a->value.strbuf, fv_b->value.strbuf)) {
177 *contains = true;
179 else {
180 *contains = false;
183 return FT_OK;
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;
191 if (regex == NULL) {
192 return FT_BADARG;
195 *matches = ws_regex_matches_length(regex, buf->str, buf->len);
196 return FT_OK;
199 static bool
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
203 * spec and
205 * http://www.itu.int/ITU-R/terrestrial/docs/fixedmobile/fxm-art19-sec3.pdf
208 if (len == 0)
209 len = strlen(s);
211 const char *end = s + len;
212 const char *hyphen = strchr(s, '-');
213 if (hyphen == NULL) {
214 hyphen = end;
217 if (s == hyphen || (hyphen - s) > 6) {
218 if (err_msg != NULL)
219 *err_msg = ws_strdup_printf("\"%s\" is not a valid AX.25 address, the callsign must be 1-6 alphanumeric ASCII characters.", s);
220 return false;
222 const char *p;
223 for (p = s; p != hyphen; p++) {
224 if (!g_ascii_isalnum(*p)) {
225 if (err_msg != NULL)
226 *err_msg = ws_strdup_printf("\"%s\" is not a valid AX.25 address, the callsign must be alphanumeric ASCII characters.", s);
227 return false;
230 uint8_t ssid = 0;
231 if (hyphen != end) {
232 if (!ws_strtou8(hyphen + 1, NULL, &ssid)) {
233 if (err_msg != NULL)
234 *err_msg = ws_strdup_printf("\"%s\" is not a valid AX.25 SSID (must be a number between 0 and 15).", hyphen + 1);
235 return false;
237 if (ssid > 15) {
238 if (err_msg != NULL)
239 *err_msg = ws_strdup_printf("%u is too large to be an AX.25 SSID (must be between 0 and 15)", ssid);
240 return false;
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);
247 g_free(str);
248 return ret;
251 static bool
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);
257 void
258 ftype_register_string(void)
261 static const ftype_t string_type = {
262 FT_STRING, /* ftype */
263 0, /* wire_size */
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 */
282 cmp_order,
283 cmp_contains,
284 cmp_matches,
286 string_hash, /* hash */
287 string_is_zero, /* is_zero */
288 NULL, /* is_negative */
289 len,
290 (FvalueSlice)slice,
291 NULL, /* bitwise_and */
292 NULL, /* unary_minus */
293 NULL, /* add */
294 NULL, /* subtract */
295 NULL, /* multiply */
296 NULL, /* divide */
297 NULL, /* modulo */
299 static const ftype_t stringz_type = {
300 FT_STRINGZ, /* ftype */
301 0, /* wire_size */
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 */
320 cmp_order,
321 cmp_contains, /* cmp_contains */
322 cmp_matches,
324 string_hash, /* hash */
325 string_is_zero, /* is_zero */
326 NULL, /* is_negative */
327 len,
328 (FvalueSlice)slice,
329 NULL, /* bitwise_and */
330 NULL, /* unary_minus */
331 NULL, /* add */
332 NULL, /* subtract */
333 NULL, /* multiply */
334 NULL, /* divide */
335 NULL, /* modulo */
337 static const ftype_t uint_string_type = {
338 FT_UINT_STRING, /* ftype */
339 0, /* wire_size */
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 */
358 cmp_order,
359 cmp_contains, /* cmp_contains */
360 cmp_matches,
362 string_hash, /* hash */
363 string_is_zero, /* is_zero */
364 NULL, /* is_negative */
365 len,
366 (FvalueSlice)slice,
367 NULL, /* bitwise_and */
368 NULL, /* unary_minus */
369 NULL, /* add */
370 NULL, /* subtract */
371 NULL, /* multiply */
372 NULL, /* divide */
373 NULL, /* modulo */
375 static const ftype_t stringzpad_type = {
376 FT_STRINGZPAD, /* ftype */
377 0, /* wire_size */
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 */
396 cmp_order,
397 cmp_contains, /* cmp_contains */
398 cmp_matches,
400 string_hash, /* hash */
401 string_is_zero, /* is_zero */
402 NULL, /* is_negative */
403 len,
404 (FvalueSlice)slice,
405 NULL, /* bitwise_and */
406 NULL, /* unary_minus */
407 NULL, /* add */
408 NULL, /* subtract */
409 NULL, /* multiply */
410 NULL, /* divide */
411 NULL, /* modulo */
413 static const ftype_t stringztrunc_type = {
414 FT_STRINGZTRUNC, /* ftype */
415 0, /* wire_size */
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 */
434 cmp_order,
435 cmp_contains, /* cmp_contains */
436 cmp_matches,
438 string_hash, /* hash */
439 string_is_zero, /* is_zero */
440 NULL, /* is_negative */
441 len,
442 (FvalueSlice)slice,
443 NULL, /* bitwise_and */
444 NULL, /* unary_minus */
445 NULL, /* add */
446 NULL, /* subtract */
447 NULL, /* multiply */
448 NULL, /* divide */
449 NULL, /* modulo */
451 static const ftype_t ax25_type = {
452 FT_AX25, /* ftype */
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 */
472 cmp_order,
473 cmp_contains,
474 cmp_matches,
476 string_hash, /* hash */
477 string_is_zero, /* is_zero */
478 NULL, /* is_negative */
479 len,
480 (FvalueSlice)slice,
481 NULL, /* bitwise_and */
482 NULL, /* unary_minus */
483 NULL, /* add */
484 NULL, /* subtract */
485 NULL, /* multiply */
486 NULL, /* divide */
487 NULL, /* modulo */
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);
499 void
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[] = {
510 { &hf_ft_string,
511 { "FT_STRING", "_ws.ftypes.string",
512 FT_STRING, BASE_NONE, NULL, 0x00,
513 NULL, HFILL }
515 { &hf_ft_stringz,
516 { "FT_STRINGZ", "_ws.ftypes.stringz",
517 FT_STRINGZ, BASE_NONE, NULL, 0x00,
518 NULL, HFILL }
520 { &hf_ft_uint_string,
521 { "FT_UINT_STRING", "_ws.ftypes.uint_string",
522 FT_UINT_STRING, BASE_NONE, NULL, 0x00,
523 NULL, HFILL }
525 { &hf_ft_stringzpad,
526 { "FT_STRINGZPAD", "_ws.ftypes.stringzpad",
527 FT_STRINGZPAD, BASE_NONE, NULL, 0x00,
528 NULL, HFILL }
530 { &hf_ft_stringztrunc,
531 { "FT_STRINGZTRUNC", "_ws.ftypes.stringztrunc",
532 FT_STRINGZTRUNC, BASE_NONE, NULL, 0x00,
533 NULL, HFILL }
535 { &hf_ft_ax25,
536 { "FT_AX25", "_ws.ftypes.ax25",
537 FT_AX25, BASE_NONE, NULL, 0x00,
538 NULL, HFILL }
542 proto_register_field_array(proto, hf_ftypes, array_length(hf_ftypes));
546 * Editor modelines - https://www.wireshark.org/tools/modelines.html
548 * Local variables:
549 * c-basic-offset: 8
550 * tab-width: 8
551 * indent-tabs-mode: t
552 * End:
554 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
555 * :indentSize=8:tabSize=8:noTabs=false: