dcerpc-netlogon: remove unused variable
[wireshark-sm.git] / epan / column-utils.c
blob2cf197e1ce9664f9b644fd14bd8fdd9f0b97e956
1 /* column-utils.c
2 * Routines for column utilities.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <time.h>
16 #include <locale.h>
17 #include <limits.h>
19 #include "column-utils.h"
20 #include "timestamp.h"
21 #include "to_str.h"
22 #include "packet_info.h"
23 #include "wsutil/pint.h"
24 #include "addr_resolv.h"
25 #include "address_types.h"
26 #include "osi-utils.h"
27 #include "value_string.h"
28 #include "column-info.h"
29 #include "column.h"
30 #include "proto.h"
32 #include <epan/strutil.h>
33 #include <epan/epan.h>
34 #include <epan/dfilter/dfilter.h>
36 #include <wsutil/inet_cidr.h>
37 #include <wsutil/utf8_entities.h>
38 #include <wsutil/ws_assert.h>
39 #include <wsutil/unicode-utils.h>
40 #include <wsutil/time_util.h>
42 #ifdef HAVE_LUA
43 #include <epan/wslua/wslua.h>
44 #endif
46 #define COL_BUF_MAX_LEN (((COL_MAX_INFO_LEN) > (COL_MAX_LEN)) ? \
47 (COL_MAX_INFO_LEN) : (COL_MAX_LEN))
49 /* Used for locale decimal point */
50 static char *col_decimal_point;
52 /* Used to indicate updated column information, e.g. a new request/response. */
53 static bool col_data_changed_;
55 static int proto_cols;
56 static int ett_cols;
58 /* Allocate all the data structures for constructing column data, given
59 the number of columns. */
60 void
61 col_setup(column_info *cinfo, const int num_cols)
63 int i;
65 col_decimal_point = localeconv()->decimal_point;
66 cinfo->num_cols = num_cols;
67 cinfo->columns = g_new(col_item_t, num_cols);
68 cinfo->col_first = g_new(int, NUM_COL_FMTS);
69 cinfo->col_last = g_new(int, NUM_COL_FMTS);
70 for (i = 0; i < num_cols; i++) {
71 cinfo->columns[i].col_custom_fields_ids = NULL;
73 cinfo->col_expr.col_expr = g_new(const char*, num_cols + 1);
74 cinfo->col_expr.col_expr_val = g_new(char*, num_cols + 1);
76 for (i = 0; i < NUM_COL_FMTS; i++) {
77 cinfo->col_first[i] = -1;
78 cinfo->col_last[i] = -1;
80 cinfo->prime_regex = g_regex_new(COL_CUSTOM_PRIME_REGEX,
81 (GRegexCompileFlags) (G_REGEX_RAW),
82 0, NULL);
85 static void
86 col_custom_free_cb(void *data)
88 col_custom_t *col_custom = (col_custom_t*)data;
89 dfilter_free(col_custom->dfilter);
90 g_free(col_custom->dftext);
91 g_free(col_custom);
94 static void
95 col_custom_fields_ids_free(GSList** custom_fields_id)
97 if (*custom_fields_id != NULL) {
98 g_slist_free_full(*custom_fields_id, col_custom_free_cb);
100 *custom_fields_id = NULL;
103 /* Cleanup all the data structures for constructing column data; undoes
104 the allocations that col_setup() does. */
105 void
106 col_cleanup(column_info *cinfo)
108 int i;
109 col_item_t* col_item;
111 if (!cinfo)
112 return;
114 for (i = 0; i < cinfo->num_cols; i++) {
115 col_item = &cinfo->columns[i];
116 g_free(col_item->fmt_matx);
117 g_free(col_item->col_title);
118 g_free(col_item->col_custom_fields);
119 dfilter_free(col_item->col_custom_dfilter);
120 /* col_item->col_data points to col_buf or static memory */
121 g_free(col_item->col_buf);
122 g_free(cinfo->col_expr.col_expr_val[i]);
123 col_custom_fields_ids_free(&col_item->col_custom_fields_ids);
126 g_free(cinfo->columns);
127 g_free(cinfo->col_first);
128 g_free(cinfo->col_last);
130 * XXX - MSVC doesn't correctly handle the "const" qualifier; it thinks
131 * "const XXX **" means "pointer to const pointer to XXX", i.e. that
132 * it's a pointer to something that's "const"ant, not "pointer to
133 * pointer to const XXX", i.e. that it's a pointer to a pointer to
134 * something that's "const"ant. Cast its bogus complaints away.
136 g_free((char **)cinfo->col_expr.col_expr);
137 g_free(cinfo->col_expr.col_expr_val);
138 if (cinfo->prime_regex)
139 g_regex_unref(cinfo->prime_regex);
142 /* Initialize the data structures for constructing column data. */
143 void
144 col_init(column_info *cinfo, const struct epan_session *epan)
146 int i;
147 col_item_t* col_item;
149 if (!cinfo)
150 return;
152 for (i = 0; i < cinfo->num_cols; i++) {
153 col_item = &cinfo->columns[i];
154 col_item->col_buf[0] = '\0';
155 col_item->col_data = col_item->col_buf;
156 col_item->col_fence = 0;
157 col_item->writable = true;
158 cinfo->col_expr.col_expr[i] = "";
159 cinfo->col_expr.col_expr_val[i][0] = '\0';
161 cinfo->writable = true;
162 cinfo->epan = epan;
165 bool
166 col_get_writable(column_info *cinfo, const int col)
168 int i;
169 col_item_t* col_item;
171 if (cinfo == NULL)
172 return false;
174 /* "global" (not) writeability will always override
175 an individual column */
176 if ((col == -1) || (cinfo->writable == false))
177 return cinfo->writable;
179 if (cinfo->col_first[col] >= 0) {
180 for (i = cinfo->col_first[col]; i <= cinfo->col_last[col]; i++) {
181 col_item = &cinfo->columns[i];
182 if (col_item->fmt_matx[col]) {
183 return col_item->writable;
187 return false;
190 void
191 col_set_writable(column_info *cinfo, const int col, const bool writable)
193 int i;
194 col_item_t* col_item;
196 if (cinfo) {
197 if (col == -1) {
198 cinfo->writable = writable;
199 } else if (cinfo->col_first[col] >= 0) {
200 for (i = cinfo->col_first[col]; i <= cinfo->col_last[col]; i++) {
201 col_item = &cinfo->columns[i];
202 if (col_item->fmt_matx[col]) {
203 col_item->writable = writable;
210 /* Checks to see if a particular packet information element is needed for the packet list */
211 #define CHECK_COL(cinfo, el) \
212 /* We are constructing columns, and they're writable */ \
213 (col_get_writable(cinfo, el) && \
214 /* There is at least one column in that format */ \
215 ((cinfo)->col_first[el] >= 0))
217 /* Sets the fence for a column to be at the end of the column. */
218 void
219 col_set_fence(column_info *cinfo, const int el)
221 int i;
222 col_item_t* col_item;
224 if (!CHECK_COL(cinfo, el))
225 return;
227 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
228 col_item = &cinfo->columns[i];
229 if (col_item->fmt_matx[el]) {
230 col_item->col_fence = (int)strlen(col_item->col_data);
235 /* Clear the fence for a column. */
236 void
237 col_clear_fence(column_info *cinfo, const int el)
239 int i;
240 col_item_t* col_item;
242 if (!CHECK_COL(cinfo, el))
243 return;
245 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
246 col_item = &cinfo->columns[i];
247 if (col_item->fmt_matx[el]) {
248 col_item->col_fence = 0;
253 /* Gets the text of a column */
254 const char *
255 col_get_text(column_info *cinfo, const int el)
257 int i;
258 const char* text = NULL;
259 col_item_t* col_item;
261 if (!(cinfo && (cinfo)->col_first[el] >= 0)) {
262 return NULL;
265 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
266 col_item = &cinfo->columns[i];
267 if (col_item->fmt_matx[el]) {
268 text = (col_item->col_data);
271 return text;
275 /* Use this to clear out a column, especially if you're going to be
276 appending to it later; at least on some platforms, it's more
277 efficient than using "col_add_str()" with a null string, and
278 more efficient than "col_set_str()" with a null string if you
279 later append to it, as the later append will cause a string
280 copy to be done. */
281 void
282 col_clear(column_info *cinfo, const int el)
284 int i;
285 col_item_t* col_item;
287 if (!CHECK_COL(cinfo, el))
288 return;
290 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
291 col_item = &cinfo->columns[i];
292 if (col_item->fmt_matx[el]) {
294 * At this point, either
296 * 1) col_data[i] is equal to col_buf[i], in which case we
297 * don't have to worry about copying col_data[i] to
298 * col_buf[i];
300 * 2) col_data[i] isn't equal to col_buf[i], in which case
301 * the only thing that's been done to the column is
302 * "col_set_str()" calls and possibly "col_set_fence()"
303 * calls, in which case the fence is either unset and
304 * at the beginning of the string or set and at the end
305 * of the string - if it's at the beginning, we're just
306 * going to clear the column, and if it's at the end,
307 * we don't do anything.
309 if (col_item->col_buf == col_item->col_data || col_item->col_fence == 0) {
311 * The fence isn't at the end of the column, or the column wasn't
312 * last set with "col_set_str()", so clear the column out.
314 col_item->col_buf[col_item->col_fence] = '\0';
315 col_item->col_data = col_item->col_buf;
317 cinfo->col_expr.col_expr[i] = "";
318 cinfo->col_expr.col_expr_val[i][0] = '\0';
323 #define COL_CHECK_APPEND(col_item, max_len) \
324 if (col_item->col_data != col_item->col_buf) { \
325 /* This was set with "col_set_str()"; copy the string they \
326 set it to into the buffer, so we can append to it. */ \
327 (void) g_strlcpy(col_item->col_buf, col_item->col_data, max_len); \
328 col_item->col_data = col_item->col_buf; \
331 #define COL_CHECK_REF_TIME(fd, buf) \
332 if (fd->ref_time) { \
333 (void) g_strlcpy(buf, "*REF*", COL_MAX_LEN ); \
334 return; \
337 /* The same as CHECK_COL(), but without the check to see if the column is writable. */
338 #define HAVE_CUSTOM_COLS(cinfo) ((cinfo) && (cinfo)->col_first[COL_CUSTOM] >= 0)
340 bool
341 have_custom_cols(column_info *cinfo)
343 return HAVE_CUSTOM_COLS(cinfo);
346 bool
347 have_field_extractors(void)
349 #ifdef HAVE_LUA
350 return wslua_has_field_extractors();
351 #else
352 return false;
353 #endif
356 /* search in edt tree custom fields */
357 void col_custom_set_edt(epan_dissect_t *edt, column_info *cinfo)
359 int i;
360 col_item_t* col_item;
362 if (!HAVE_CUSTOM_COLS(cinfo))
363 return;
365 for (i = cinfo->col_first[COL_CUSTOM];
366 i <= cinfo->col_last[COL_CUSTOM]; i++) {
367 col_item = &cinfo->columns[i];
368 if (col_item->fmt_matx[COL_CUSTOM] &&
369 col_item->col_custom_fields &&
370 col_item->col_custom_fields_ids) {
371 col_item->col_data = col_item->col_buf;
372 cinfo->col_expr.col_expr[i] = epan_custom_set(edt, col_item->col_custom_fields_ids,
373 col_item->col_custom_occurrence,
374 get_column_display_format(i) == COLUMN_DISPLAY_DETAILS,
375 col_item->col_buf,
376 cinfo->col_expr.col_expr_val[i],
377 COL_MAX_LEN);
382 #if 0
383 // Needed if we create _ws.col.custom
384 static void
385 col_custom_set(proto_tree *tree, column_info *cinfo)
387 int i;
388 col_item_t* col_item;
390 if (!HAVE_CUSTOM_COLS(cinfo))
391 return;
393 for (i = cinfo->col_first[COL_CUSTOM];
394 i <= cinfo->col_last[COL_CUSTOM]; i++) {
395 col_item = &cinfo->columns[i];
396 if (col_item->fmt_matx[COL_CUSTOM] &&
397 col_item->col_custom_fields &&
398 col_item->col_custom_fields_ids) {
399 col_item->col_data = col_item->col_buf;
400 cinfo->col_expr.col_expr[i] = proto_custom_set(tree, col_item->col_custom_fields_ids,
401 col_item->col_custom_occurrence,
402 get_column_display_format(i) == COLUMN_DISPLAY_DETAILS,
403 col_item->col_buf,
404 cinfo->col_expr.col_expr_val[i],
405 COL_MAX_LEN);
409 #endif
411 void
412 col_custom_prime_edt(epan_dissect_t *edt, column_info *cinfo)
414 int i;
415 col_item_t* col_item;
417 if (!HAVE_CUSTOM_COLS(cinfo))
418 return;
420 for (i = cinfo->col_first[COL_CUSTOM];
421 i <= cinfo->col_last[COL_CUSTOM]; i++) {
422 col_item = &cinfo->columns[i];
424 if (col_item->fmt_matx[COL_CUSTOM] &&
425 col_item->col_custom_dfilter) {
426 if (get_column_display_format(i) == COLUMN_DISPLAY_DETAILS) {
427 epan_dissect_prime_with_dfilter_print(edt, col_item->col_custom_dfilter);
428 } else {
429 epan_dissect_prime_with_dfilter(edt, col_item->col_custom_dfilter);
435 char*
436 col_custom_get_filter(epan_dissect_t *edt, column_info *cinfo, const int col)
438 col_item_t* col_item;
440 ws_assert(cinfo);
441 ws_assert(col < cinfo->num_cols);
443 col_item = &cinfo->columns[col];
444 if (col_item->fmt_matx[COL_CUSTOM] &&
445 col_item->col_custom_fields &&
446 col_item->col_custom_fields_ids) {
448 return proto_custom_get_filter(edt, col_item->col_custom_fields_ids,
449 col_item->col_custom_occurrence);
451 return NULL;
454 void
455 col_append_lstr(column_info *cinfo, const int el, const char *str1, ...)
457 va_list ap;
458 size_t pos, max_len;
459 int i;
460 const char *str;
461 col_item_t* col_item;
463 if (!CHECK_COL(cinfo, el))
464 return;
466 if (el == COL_INFO)
467 max_len = COL_MAX_INFO_LEN;
468 else
469 max_len = COL_MAX_LEN;
471 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
472 col_item = &cinfo->columns[i];
473 if (col_item->fmt_matx[el]) {
475 * First arrange that we can append, if necessary.
477 COL_CHECK_APPEND(col_item, max_len);
479 pos = strlen(col_item->col_buf);
480 if (pos >= max_len)
481 return;
483 va_start(ap, str1);
484 str = str1;
485 do {
486 if (G_UNLIKELY(str == NULL)) {
487 str = "(null)";
489 WS_UTF_8_CHECK(str, -1);
490 pos = ws_label_strcpy(col_item->col_buf, max_len, pos, str, 0);
492 } while (pos < max_len && (str = va_arg(ap, const char *)) != COL_ADD_LSTR_TERMINATOR);
493 va_end(ap);
498 void
499 col_append_str_uint(column_info *cinfo, const int col, const char *abbrev, uint32_t val, const char *sep)
501 char buf[16];
503 if (!CHECK_COL(cinfo, col))
504 return;
506 uint32_to_str_buf(val, buf, sizeof(buf));
507 col_append_lstr(cinfo, col, sep ? sep : "", abbrev, "=", buf, COL_ADD_LSTR_TERMINATOR);
510 static inline void
511 col_snprint_port(char *buf, size_t buf_siz, port_type typ, uint16_t val)
513 const char *str;
515 if (gbl_resolv_flags.transport_name &&
516 (str = try_serv_name_lookup(typ, val)) != NULL) {
517 snprintf(buf, buf_siz, "%s(%"PRIu16")", str, val);
518 } else {
519 snprintf(buf, buf_siz, "%"PRIu16, val);
523 void
524 col_append_ports(column_info *cinfo, const int col, port_type typ, uint16_t src, uint16_t dst)
526 char buf_src[32], buf_dst[32];
528 if (!CHECK_COL(cinfo, col))
529 return;
531 col_snprint_port(buf_src, 32, typ, src);
532 col_snprint_port(buf_dst, 32, typ, dst);
533 col_append_lstr(cinfo, col, buf_src, " " UTF8_RIGHTWARDS_ARROW " ", buf_dst, COL_ADD_LSTR_TERMINATOR);
536 void
537 col_append_frame_number(packet_info *pinfo, const int col, const char *fmt_str, unsigned frame_num)
539 col_append_fstr(pinfo->cinfo, col, fmt_str, frame_num);
540 if (!pinfo->fd->visited) {
541 col_data_changed_ = true;
545 static void
546 col_do_append_fstr(column_info *cinfo, const int el, const char *separator, const char *format, va_list ap)
548 size_t len, max_len, sep_len, pos;
549 int i;
550 col_item_t* col_item;
551 char tmp[COL_BUF_MAX_LEN];
553 sep_len = (separator) ? strlen(separator) : 0;
555 if (el == COL_INFO)
556 max_len = COL_MAX_INFO_LEN;
557 else
558 max_len = COL_MAX_LEN;
560 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
561 col_item = &cinfo->columns[i];
562 if (col_item->fmt_matx[el]) {
564 * First arrange that we can append, if necessary.
566 COL_CHECK_APPEND(col_item, max_len);
568 len = strlen(col_item->col_buf);
571 * If we have a separator, append it if the column isn't empty.
573 if (sep_len != 0 && len != 0) {
574 (void) ws_label_strcat(col_item->col_buf, max_len, separator, 0);
575 len += sep_len;
578 if (len < max_len) {
579 va_list ap2;
581 va_copy(ap2, ap);
582 pos = vsnprintf(tmp, sizeof(tmp), format, ap2);
583 va_end(ap2);
584 if (pos >= max_len) {
585 ws_utf8_truncate(tmp, max_len - 1);
587 WS_UTF_8_CHECK(tmp, -1);
588 ws_label_strcpy(col_item->col_buf, max_len, len, tmp, 0);
594 /* Appends a vararg list to a packet info string. */
595 void
596 col_append_fstr(column_info *cinfo, const int el, const char *format, ...)
598 va_list ap;
600 if (!CHECK_COL(cinfo, el))
601 return;
603 va_start(ap, format);
604 col_do_append_fstr(cinfo, el, NULL, format, ap);
605 va_end(ap);
608 /* Appends a vararg list to a packet info string.
609 * Prefixes it with the given separator if the column is not empty.
611 void
612 col_append_sep_fstr(column_info *cinfo, const int el, const char *separator,
613 const char *format, ...)
615 va_list ap;
617 if (!CHECK_COL(cinfo, el))
618 return;
620 if (separator == NULL)
621 separator = ", "; /* default */
623 va_start(ap, format);
624 col_do_append_fstr(cinfo, el, separator, format, ap);
625 va_end(ap);
628 /* Prepends a vararg list to a packet info string. */
629 void
630 col_prepend_fstr(column_info *cinfo, const int el, const char *format, ...)
632 va_list ap;
633 int i;
634 char orig_buf[COL_BUF_MAX_LEN];
635 const char *orig;
636 size_t max_len, pos;
637 col_item_t* col_item;
638 char tmp[COL_BUF_MAX_LEN];
640 if (!CHECK_COL(cinfo, el))
641 return;
643 if (el == COL_INFO)
644 max_len = COL_MAX_INFO_LEN;
645 else
646 max_len = COL_MAX_LEN;
648 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
649 col_item = &cinfo->columns[i];
650 if (col_item->fmt_matx[el]) {
651 if (col_item->col_data != col_item->col_buf) {
652 /* This was set with "col_set_str()"; which is effectively const */
653 orig = col_item->col_data;
654 } else {
655 (void) g_strlcpy(orig_buf, col_item->col_buf, max_len);
656 orig = orig_buf;
658 va_start(ap, format);
659 pos = vsnprintf(tmp, sizeof(tmp), format, ap);
660 va_end(ap);
661 if (pos >= max_len) {
662 ws_utf8_truncate(tmp, max_len - 1);
664 WS_UTF_8_CHECK(tmp, -1);
665 pos = ws_label_strcpy(col_item->col_buf, max_len, 0, tmp, 0);
668 * Move the fence, unless it's at the beginning of the string.
670 if (col_item->col_fence > 0)
671 col_item->col_fence += (int) strlen(col_item->col_buf);
674 * Append the original data.
676 ws_label_strcpy(col_item->col_buf, max_len, pos, orig, 0);
677 col_item->col_data = col_item->col_buf;
681 void
682 col_prepend_fence_fstr(column_info *cinfo, const int el, const char *format, ...)
684 va_list ap;
685 int i;
686 char orig_buf[COL_BUF_MAX_LEN];
687 const char *orig;
688 size_t max_len, pos;
689 col_item_t* col_item;
690 char tmp[COL_BUF_MAX_LEN];
692 if (!CHECK_COL(cinfo, el))
693 return;
695 if (el == COL_INFO)
696 max_len = COL_MAX_INFO_LEN;
697 else
698 max_len = COL_MAX_LEN;
700 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
701 col_item = &cinfo->columns[i];
702 if (col_item->fmt_matx[el]) {
703 if (col_item->col_data != col_item->col_buf) {
704 /* This was set with "col_set_str()"; which is effectively const */
705 orig = col_item->col_data;
706 } else {
707 (void) g_strlcpy(orig_buf, col_item->col_buf, max_len);
708 orig = orig_buf;
710 va_start(ap, format);
711 pos = vsnprintf(tmp, sizeof(tmp), format, ap);
712 va_end(ap);
713 if (pos >= max_len) {
714 ws_utf8_truncate(tmp, max_len - 1);
716 WS_UTF_8_CHECK(tmp, -1);
717 pos = ws_label_strcpy(col_item->col_buf, max_len, 0, tmp, 0);
720 * Move the fence if it exists, else create a new fence at the
721 * end of the prepended data.
723 if (col_item->col_fence > 0) {
724 col_item->col_fence += (int) strlen(col_item->col_buf);
725 } else {
726 col_item->col_fence = (int) strlen(col_item->col_buf);
729 * Append the original data.
731 ws_label_strcpy(col_item->col_buf, max_len, pos, orig, 0);
732 col_item->col_data = col_item->col_buf;
737 /* Use this if "str" points to something that won't stay around (and
738 must thus be copied). */
739 void
740 col_add_str(column_info *cinfo, const int el, const char* str)
742 int i;
743 size_t max_len;
744 col_item_t* col_item;
746 if (!CHECK_COL(cinfo, el))
747 return;
749 if (el == COL_INFO)
750 max_len = COL_MAX_INFO_LEN;
751 else
752 max_len = COL_MAX_LEN;
754 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
755 col_item = &cinfo->columns[i];
756 if (col_item->fmt_matx[el]) {
757 if (col_item->col_fence != 0) {
759 * We will append the string after the fence.
760 * First arrange that we can append, if necessary.
762 COL_CHECK_APPEND(col_item, max_len);
763 } else {
765 * There's no fence, so we can just write to the string.
767 col_item->col_data = col_item->col_buf;
769 WS_UTF_8_CHECK(str, -1);
770 (void) ws_label_strcpy(col_item->col_buf, max_len, col_item->col_fence, str, 0);
775 /* Use this if "str" points to something that will stay around (and thus
776 needn't be copied). */
777 void
778 col_set_str(column_info *cinfo, const int el, const char* str)
780 int i;
781 size_t max_len;
782 col_item_t* col_item;
784 DISSECTOR_ASSERT(str);
786 if (!CHECK_COL(cinfo, el))
787 return;
789 if (el == COL_INFO)
790 max_len = COL_MAX_INFO_LEN;
791 else
792 max_len = COL_MAX_LEN;
794 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
795 col_item = &cinfo->columns[i];
796 if (col_item->fmt_matx[el]) {
797 if (col_item->col_fence != 0) {
799 * We will append the string after the fence.
800 * First arrange that we can append, if necessary.
802 COL_CHECK_APPEND(col_item, max_len);
804 (void) g_strlcpy(&col_item->col_buf[col_item->col_fence], str, max_len - col_item->col_fence);
805 } else {
807 * There's no fence, so we can just set the column to point
808 * to the string.
810 col_item->col_data = str;
816 void
817 col_add_lstr(column_info *cinfo, const int el, const char *str1, ...)
819 va_list ap;
820 int i;
821 size_t pos;
822 size_t max_len;
823 const char *str;
824 col_item_t* col_item;
826 if (!CHECK_COL(cinfo, el))
827 return;
829 if (el == COL_INFO)
830 max_len = COL_MAX_INFO_LEN;
831 else
832 max_len = COL_MAX_LEN;
834 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
835 col_item = &cinfo->columns[i];
836 if (col_item->fmt_matx[el]) {
837 pos = col_item->col_fence;
838 if (pos != 0) {
840 * We will append the string after the fence.
841 * First arrange that we can append, if necessary.
843 COL_CHECK_APPEND(col_item, max_len);
844 } else {
846 * There's no fence, so we can just write to the string.
848 col_item->col_data = col_item->col_buf;
851 va_start(ap, str1);
852 str = str1;
853 do {
854 if (G_UNLIKELY(str == NULL)) {
855 str = "(null)";
857 WS_UTF_8_CHECK(str, -1);
858 pos = ws_label_strcpy(col_item->col_buf, max_len, pos, str, 0);
860 } while (pos < max_len && (str = va_arg(ap, const char *)) != COL_ADD_LSTR_TERMINATOR);
861 va_end(ap);
866 /* Adds a vararg list to a packet info string. */
867 void
868 col_add_fstr(column_info *cinfo, const int el, const char *format, ...)
870 va_list ap;
871 int i, pos;
872 int max_len;
873 col_item_t* col_item;
874 char tmp[COL_BUF_MAX_LEN];
876 if (!CHECK_COL(cinfo, el))
877 return;
879 if (el == COL_INFO)
880 max_len = COL_MAX_INFO_LEN;
881 else
882 max_len = COL_MAX_LEN;
884 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
885 col_item = &cinfo->columns[i];
886 if (col_item->fmt_matx[el]) {
887 if (col_item->col_fence != 0) {
889 * We will append the string after the fence.
890 * First arrange that we can append, if necessary.
892 COL_CHECK_APPEND(col_item, max_len);
893 } else {
895 * There's no fence, so we can just write to the string.
897 col_item->col_data = col_item->col_buf;
899 va_start(ap, format);
900 pos = vsnprintf(tmp, sizeof(tmp), format, ap);
901 va_end(ap);
902 if (pos >= max_len) {
903 ws_utf8_truncate(tmp, max_len - 1);
905 WS_UTF_8_CHECK(tmp, -1);
906 ws_label_strcpy(col_item->col_buf, max_len, col_item->col_fence, tmp, 0);
911 static void
912 col_do_append_str(column_info *cinfo, const int el, const char* separator,
913 const char* str)
915 int i;
916 size_t len, max_len;
917 col_item_t* col_item;
919 if (el == COL_INFO)
920 max_len = COL_MAX_INFO_LEN;
921 else
922 max_len = COL_MAX_LEN;
924 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
925 col_item = &cinfo->columns[i];
926 if (col_item->fmt_matx[el]) {
928 * First arrange that we can append, if necessary.
930 COL_CHECK_APPEND(col_item, max_len);
932 len = col_item->col_buf[0];
935 * If we have a separator, append it if the column isn't empty.
937 if (separator != NULL) {
938 if (len != 0) {
939 (void) ws_label_strcat(col_item->col_buf, max_len, separator, 0);
942 WS_UTF_8_CHECK(str, -1);
943 (void) ws_label_strcat(col_item->col_buf, max_len, str, 0);
948 void
949 col_append_str(column_info *cinfo, const int el, const char* str)
951 if (!CHECK_COL(cinfo, el))
952 return;
954 col_do_append_str(cinfo, el, NULL, str);
957 void
958 col_append_sep_str(column_info *cinfo, const int el, const char* separator,
959 const char* str)
961 if (!CHECK_COL(cinfo, el))
962 return;
964 if (separator == NULL)
965 separator = ", "; /* default */
967 col_do_append_str(cinfo, el, separator, str);
970 /* --------------------------------- */
971 bool
972 col_has_time_fmt(column_info *cinfo, const int col)
974 col_item_t* col_item = &cinfo->columns[col];
975 return ((col_item->fmt_matx[COL_CLS_TIME]) ||
976 (col_item->fmt_matx[COL_ABS_TIME]) ||
977 (col_item->fmt_matx[COL_ABS_YMD_TIME]) ||
978 (col_item->fmt_matx[COL_ABS_YDOY_TIME]) ||
979 (col_item->fmt_matx[COL_UTC_TIME]) ||
980 (col_item->fmt_matx[COL_UTC_YMD_TIME]) ||
981 (col_item->fmt_matx[COL_UTC_YDOY_TIME]) ||
982 (col_item->fmt_matx[COL_REL_TIME]) ||
983 (col_item->fmt_matx[COL_DELTA_TIME]) ||
984 (col_item->fmt_matx[COL_DELTA_TIME_DIS]));
987 static int
988 get_frame_timestamp_precision(const frame_data *fd)
990 int tsprecision;
992 tsprecision = timestamp_get_precision();
993 if (tsprecision == TS_PREC_AUTO)
994 tsprecision = fd->tsprec;
995 else if (tsprecision < 0)
996 ws_assert_not_reached();
999 * Time stamp precision values higher than the maximum
1000 * precision we support can't be handled. Just display
1001 * those times with the maximum precision we support.
1003 if (tsprecision > WS_TSPREC_MAX)
1004 tsprecision = WS_TSPREC_MAX;
1006 return tsprecision;
1009 static int
1010 get_default_timestamp_precision(void)
1012 int tsprecision;
1014 tsprecision = timestamp_get_precision();
1015 if (tsprecision == TS_PREC_AUTO)
1016 tsprecision = WS_TSPREC_MAX; /* default to the maximum precision we support */
1017 else if (tsprecision < 0)
1018 ws_assert_not_reached();
1021 * Time stamp precision values higher than the maximum
1022 * precision we support can't be handled. Just display
1023 * those times with the maximum precision we support.
1025 if (tsprecision > WS_TSPREC_MAX)
1026 tsprecision = WS_TSPREC_MAX;
1028 return tsprecision;
1031 static void
1032 set_abs_ymd_time(const frame_data *fd, char *buf, char *decimal_point, bool local)
1034 if (!fd->has_ts) {
1035 buf[0] = '\0';
1036 return;
1038 format_nstime_as_iso8601(buf, COL_MAX_LEN, &fd->abs_ts, decimal_point, local, get_frame_timestamp_precision(fd));
1041 static void
1042 col_set_abs_ymd_time(const frame_data *fd, column_info *cinfo, const int col)
1044 set_abs_ymd_time(fd, cinfo->columns[col].col_buf, col_decimal_point, true);
1045 cinfo->col_expr.col_expr[col] = "frame.time";
1046 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1048 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1051 static void
1052 col_set_utc_ymd_time(const frame_data *fd, column_info *cinfo, const int col)
1054 set_abs_ymd_time(fd, cinfo->columns[col].col_buf, col_decimal_point, false);
1055 cinfo->col_expr.col_expr[col] = "frame.time";
1056 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1058 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1061 static void
1062 set_abs_ydoy_time(const frame_data *fd, char *buf, char *decimal_point, bool local)
1064 struct tm tm, *tmp;
1065 char *ptr;
1066 size_t remaining;
1067 int num_bytes;
1068 int tsprecision;
1070 if (!fd->has_ts) {
1071 buf[0] = '\0';
1072 return;
1075 if (local)
1076 tmp = ws_localtime_r(&fd->abs_ts.secs, &tm);
1077 else
1078 tmp = ws_gmtime_r(&fd->abs_ts.secs, &tm);
1079 if (tmp == NULL) {
1080 snprintf(buf, COL_MAX_LEN, "Not representable");
1081 return;
1083 ptr = buf;
1084 remaining = COL_MAX_LEN;
1085 num_bytes = snprintf(ptr, remaining,"%04d/%03d %02d:%02d:%02d",
1086 tmp->tm_year + 1900,
1087 tmp->tm_yday + 1,
1088 tmp->tm_hour,
1089 tmp->tm_min,
1090 tmp->tm_sec);
1091 if (num_bytes < 0) {
1093 * That got an error.
1094 * Not much else we can do.
1096 snprintf(ptr, remaining, "snprintf() failed");
1097 return;
1099 if ((unsigned int)num_bytes >= remaining) {
1101 * That filled up or would have overflowed the buffer.
1102 * Nothing more we can do.
1104 return;
1106 ptr += num_bytes;
1107 remaining -= num_bytes;
1109 tsprecision = get_frame_timestamp_precision(fd);
1110 if (tsprecision != 0) {
1112 * Append the fractional part.
1113 * Get the nsecs as a 32-bit unsigned value, as it should never
1114 * be negative, so we treat it as unsigned.
1116 format_fractional_part_nsecs(ptr, remaining, (uint32_t)fd->abs_ts.nsecs, decimal_point, tsprecision);
1120 static void
1121 col_set_abs_ydoy_time(const frame_data *fd, column_info *cinfo, const int col)
1123 set_abs_ydoy_time(fd, cinfo->columns[col].col_buf, col_decimal_point, true);
1124 cinfo->col_expr.col_expr[col] = "frame.time";
1125 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1127 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1130 static void
1131 col_set_utc_ydoy_time(const frame_data *fd, column_info *cinfo, const int col)
1133 set_abs_ydoy_time(fd, cinfo->columns[col].col_buf, col_decimal_point, false);
1134 cinfo->col_expr.col_expr[col] = "frame.time";
1135 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1137 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1140 static void
1141 set_time_seconds(const frame_data *fd, const nstime_t *ts, char *buf)
1143 ws_assert(fd->has_ts);
1145 display_signed_time(buf, COL_MAX_LEN, ts, get_frame_timestamp_precision(fd));
1148 static void
1149 set_time_hour_min_sec(const frame_data *fd, const nstime_t *ts, char *buf, char *decimal_point)
1151 time_t secs = ts->secs;
1152 uint32_t nsecs;
1153 bool negative = false;
1154 char *ptr;
1155 size_t remaining;
1156 int num_bytes;
1157 int tsprecision;
1159 ws_assert(fd->has_ts);
1161 if (secs < 0) {
1162 secs = -secs;
1163 negative = true;
1165 if (ts->nsecs >= 0) {
1166 nsecs = ts->nsecs;
1167 } else if (G_LIKELY(ts->nsecs != INT_MIN)) {
1169 * This isn't the smallest negative number that fits in 32
1170 * bits, so we can compute its negative and store it in a
1171 * 32-bit unsigned int variable.
1173 nsecs = -ts->nsecs;
1174 negative = true;
1175 } else {
1177 * -2147483648 is the smallest number that fits in a signed
1178 * 2's complement 32-bit variable, and its negative doesn't
1179 * fit in 32 bits.
1181 * Just cast it to a 32-bit unsigned int value to set the
1182 * 32-bit unsigned int variable to 2147483648.
1184 * Note that, on platforms where both integers and long
1185 * integers are 32-bit, such as 32-bit UN*Xes and both
1186 * 32-bit *and* 64-bit Windows, making the variable in
1187 * question a long will not avoid undefined behavior.
1189 nsecs = (uint32_t)ts->nsecs;
1190 negative = true;
1192 ptr = buf;
1193 remaining = COL_MAX_LEN;
1194 if (secs >= (60*60)) {
1195 num_bytes = snprintf(ptr, remaining, "%s%dh %2dm %2d",
1196 negative ? "- " : "",
1197 (int32_t) secs / (60 * 60),
1198 (int32_t) (secs / 60) % 60,
1199 (int32_t) secs % 60);
1200 } else if (secs >= 60) {
1201 num_bytes = snprintf(ptr, remaining, "%s%dm %2d",
1202 negative ? "- " : "",
1203 (int32_t) secs / 60,
1204 (int32_t) secs % 60);
1205 } else {
1206 num_bytes = snprintf(ptr, remaining, "%s%d",
1207 negative ? "- " : "",
1208 (int32_t) secs);
1210 if (num_bytes < 0) {
1212 * That got an error.
1213 * Not much else we can do.
1215 snprintf(ptr, remaining, "snprintf() failed");
1216 return;
1218 if ((unsigned int)num_bytes >= remaining) {
1220 * That filled up or would have overflowed the buffer.
1221 * Nothing more we can do.
1223 return;
1225 ptr += num_bytes;
1226 remaining -= num_bytes;
1228 tsprecision = get_frame_timestamp_precision(fd);
1229 if (tsprecision != 0) {
1231 * Append the fractional part.
1233 num_bytes = format_fractional_part_nsecs(ptr, remaining, nsecs, decimal_point, tsprecision);
1234 if ((unsigned int)num_bytes >= remaining) {
1236 * That filled up or would have overflowed the buffer.
1237 * Nothing more we can do.
1239 return;
1241 ptr += num_bytes;
1242 remaining -= num_bytes;
1245 /* Append the "s" for seconds. */
1246 snprintf(ptr, remaining, "s");
1249 static void
1250 col_set_rel_time(const frame_data *fd, column_info *cinfo, const int col)
1252 nstime_t del_rel_ts;
1254 if (!fd->has_ts) {
1255 cinfo->columns[col].col_buf[0] = '\0';
1256 return;
1259 frame_delta_abs_time(cinfo->epan, fd, fd->frame_ref_num, &del_rel_ts);
1261 switch (timestamp_get_seconds_type()) {
1262 case TS_SECONDS_DEFAULT:
1263 set_time_seconds(fd, &del_rel_ts, cinfo->columns[col].col_buf);
1264 cinfo->col_expr.col_expr[col] = "frame.time_relative";
1265 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1266 break;
1267 case TS_SECONDS_HOUR_MIN_SEC:
1268 set_time_hour_min_sec(fd, &del_rel_ts, cinfo->columns[col].col_buf, col_decimal_point);
1269 cinfo->col_expr.col_expr[col] = "frame.time_relative";
1270 set_time_seconds(fd, &del_rel_ts, cinfo->col_expr.col_expr_val[col]);
1271 break;
1272 default:
1273 ws_assert_not_reached();
1275 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1278 static void
1279 col_set_delta_time(const frame_data *fd, column_info *cinfo, const int col)
1281 nstime_t del_cap_ts;
1283 if (!fd->has_ts) {
1284 cinfo->columns[col].col_buf[0] = '\0';
1285 return;
1288 frame_delta_abs_time(cinfo->epan, fd, fd->num - 1, &del_cap_ts);
1290 switch (timestamp_get_seconds_type()) {
1291 case TS_SECONDS_DEFAULT:
1292 set_time_seconds(fd, &del_cap_ts, cinfo->columns[col].col_buf);
1293 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1294 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1295 break;
1296 case TS_SECONDS_HOUR_MIN_SEC:
1297 set_time_hour_min_sec(fd, &del_cap_ts, cinfo->columns[col].col_buf, col_decimal_point);
1298 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1299 set_time_seconds(fd, &del_cap_ts, cinfo->col_expr.col_expr_val[col]);
1300 break;
1301 default:
1302 ws_assert_not_reached();
1305 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1308 static void
1309 col_set_delta_time_dis(const frame_data *fd, column_info *cinfo, const int col)
1311 nstime_t del_dis_ts;
1313 if (!fd->has_ts) {
1314 cinfo->columns[col].col_buf[0] = '\0';
1315 return;
1318 frame_delta_abs_time(cinfo->epan, fd, fd->prev_dis_num, &del_dis_ts);
1320 switch (timestamp_get_seconds_type()) {
1321 case TS_SECONDS_DEFAULT:
1322 set_time_seconds(fd, &del_dis_ts, cinfo->columns[col].col_buf);
1323 cinfo->col_expr.col_expr[col] = "frame.time_delta_displayed";
1324 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1325 break;
1326 case TS_SECONDS_HOUR_MIN_SEC:
1327 set_time_hour_min_sec(fd, &del_dis_ts, cinfo->columns[col].col_buf, col_decimal_point);
1328 cinfo->col_expr.col_expr[col] = "frame.time_delta_displayed";
1329 set_time_seconds(fd, &del_dis_ts, cinfo->col_expr.col_expr_val[col]);
1330 break;
1331 default:
1332 ws_assert_not_reached();
1335 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1339 * Time, without date.
1341 static void
1342 set_abs_time(const frame_data *fd, char *buf, char *decimal_point, bool local)
1344 struct tm tm, *tmp;
1345 char *ptr;
1346 size_t remaining;
1347 int num_bytes;
1348 int tsprecision;
1350 if (!fd->has_ts) {
1351 *buf = '\0';
1352 return;
1355 ptr = buf;
1356 remaining = COL_MAX_LEN;
1358 if (local)
1359 tmp = ws_localtime_r(&fd->abs_ts.secs, &tm);
1360 else
1361 tmp = ws_gmtime_r(&fd->abs_ts.secs, &tm);
1362 if (tmp == NULL) {
1363 snprintf(ptr, remaining, "Not representable");
1364 return;
1367 /* Integral part. */
1368 num_bytes = snprintf(ptr, remaining, "%02d:%02d:%02d",
1369 tmp->tm_hour,
1370 tmp->tm_min,
1371 tmp->tm_sec);
1372 if (num_bytes < 0) {
1374 * That got an error.
1375 * Not much else we can do.
1377 snprintf(ptr, remaining, "snprintf() failed");
1378 return;
1380 if ((unsigned int)num_bytes >= remaining) {
1382 * That filled up or would have overflowed the buffer.
1383 * Nothing more we can do.
1385 return;
1387 ptr += num_bytes;
1388 remaining -= num_bytes;
1390 tsprecision = get_frame_timestamp_precision(fd);
1391 if (tsprecision != 0) {
1393 * Append the fractional part.
1394 * Get the nsecs as a 32-bit unsigned value, as it should never
1395 * be negative, so we treat it as unsigned.
1397 format_fractional_part_nsecs(ptr, remaining, (uint32_t)fd->abs_ts.nsecs, decimal_point, tsprecision);
1401 static void
1402 col_set_abs_time(const frame_data *fd, column_info *cinfo, const int col)
1404 set_abs_time(fd, cinfo->columns[col].col_buf, col_decimal_point, true);
1405 cinfo->col_expr.col_expr[col] = "frame.time";
1406 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1408 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1411 static void
1412 col_set_utc_time(const frame_data *fd, column_info *cinfo, const int col)
1414 set_abs_time(fd, cinfo->columns[col].col_buf, col_decimal_point, false);
1415 cinfo->col_expr.col_expr[col] = "frame.time";
1416 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1418 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1421 static bool
1422 set_epoch_time(const frame_data *fd, char *buf)
1424 if (!fd->has_ts) {
1425 buf[0] = '\0';
1426 return false;
1428 display_epoch_time(buf, COL_MAX_LEN, &fd->abs_ts, get_frame_timestamp_precision(fd));
1429 return true;
1432 static void
1433 col_set_epoch_time(const frame_data *fd, column_info *cinfo, const int col)
1435 if (set_epoch_time(fd, cinfo->columns[col].col_buf)) {
1436 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1437 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1439 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1442 void
1443 set_fd_time(const epan_t *epan, frame_data *fd, char *buf)
1446 switch (timestamp_get_type()) {
1447 case TS_ABSOLUTE:
1448 set_abs_time(fd, buf, col_decimal_point, true);
1449 break;
1451 case TS_ABSOLUTE_WITH_YMD:
1452 set_abs_ymd_time(fd, buf, col_decimal_point, true);
1453 break;
1455 case TS_ABSOLUTE_WITH_YDOY:
1456 set_abs_ydoy_time(fd, buf, col_decimal_point, true);
1457 break;
1459 case TS_RELATIVE:
1460 if (fd->has_ts) {
1461 nstime_t del_rel_ts;
1463 frame_delta_abs_time(epan, fd, fd->frame_ref_num, &del_rel_ts);
1465 switch (timestamp_get_seconds_type()) {
1466 case TS_SECONDS_DEFAULT:
1467 set_time_seconds(fd, &del_rel_ts, buf);
1468 break;
1469 case TS_SECONDS_HOUR_MIN_SEC:
1470 set_time_seconds(fd, &del_rel_ts, buf);
1471 break;
1472 default:
1473 ws_assert_not_reached();
1475 } else {
1476 buf[0] = '\0';
1478 break;
1480 case TS_DELTA:
1481 if (fd->has_ts) {
1482 nstime_t del_cap_ts;
1484 frame_delta_abs_time(epan, fd, fd->num - 1, &del_cap_ts);
1486 switch (timestamp_get_seconds_type()) {
1487 case TS_SECONDS_DEFAULT:
1488 set_time_seconds(fd, &del_cap_ts, buf);
1489 break;
1490 case TS_SECONDS_HOUR_MIN_SEC:
1491 set_time_hour_min_sec(fd, &del_cap_ts, buf, col_decimal_point);
1492 break;
1493 default:
1494 ws_assert_not_reached();
1496 } else {
1497 buf[0] = '\0';
1499 break;
1501 case TS_DELTA_DIS:
1502 if (fd->has_ts) {
1503 nstime_t del_dis_ts;
1505 frame_delta_abs_time(epan, fd, fd->prev_dis_num, &del_dis_ts);
1507 switch (timestamp_get_seconds_type()) {
1508 case TS_SECONDS_DEFAULT:
1509 set_time_seconds(fd, &del_dis_ts, buf);
1510 break;
1511 case TS_SECONDS_HOUR_MIN_SEC:
1512 set_time_hour_min_sec(fd, &del_dis_ts, buf, col_decimal_point);
1513 break;
1514 default:
1515 ws_assert_not_reached();
1517 } else {
1518 buf[0] = '\0';
1520 break;
1522 case TS_EPOCH:
1523 set_epoch_time(fd, buf);
1524 break;
1526 case TS_UTC:
1527 set_abs_time(fd, buf, col_decimal_point, false);
1528 break;
1530 case TS_UTC_WITH_YMD:
1531 set_abs_ymd_time(fd, buf, col_decimal_point, false);
1532 break;
1534 case TS_UTC_WITH_YDOY:
1535 set_abs_ydoy_time(fd, buf, col_decimal_point, false);
1536 break;
1538 case TS_NOT_SET:
1539 /* code is missing for this case, but I don't know which [jmayer20051219] */
1540 ws_assert_not_reached();
1541 break;
1545 static void
1546 col_set_cls_time(const frame_data *fd, column_info *cinfo, const int col)
1548 switch (timestamp_get_type()) {
1549 case TS_ABSOLUTE:
1550 col_set_abs_time(fd, cinfo, col);
1551 break;
1553 case TS_ABSOLUTE_WITH_YMD:
1554 col_set_abs_ymd_time(fd, cinfo, col);
1555 break;
1557 case TS_ABSOLUTE_WITH_YDOY:
1558 col_set_abs_ydoy_time(fd, cinfo, col);
1559 break;
1561 case TS_RELATIVE:
1562 col_set_rel_time(fd, cinfo, col);
1563 break;
1565 case TS_DELTA:
1566 col_set_delta_time(fd, cinfo, col);
1567 break;
1569 case TS_DELTA_DIS:
1570 col_set_delta_time_dis(fd, cinfo, col);
1571 break;
1573 case TS_EPOCH:
1574 col_set_epoch_time(fd, cinfo, col);
1575 break;
1577 case TS_UTC:
1578 col_set_utc_time(fd, cinfo, col);
1579 break;
1581 case TS_UTC_WITH_YMD:
1582 col_set_utc_ymd_time(fd, cinfo, col);
1583 break;
1585 case TS_UTC_WITH_YDOY:
1586 col_set_utc_ydoy_time(fd, cinfo, col);
1587 break;
1589 case TS_NOT_SET:
1590 /* code is missing for this case, but I don't know which [jmayer20051219] */
1591 ws_assert_not_reached();
1592 break;
1596 /* Set the format of the variable time format. */
1597 static void
1598 col_set_fmt_time(const frame_data *fd, column_info *cinfo, const int fmt, const int col)
1600 COL_CHECK_REF_TIME(fd, cinfo->columns[col].col_buf);
1602 switch (fmt) {
1603 case COL_CLS_TIME:
1604 col_set_cls_time(fd, cinfo, col);
1605 break;
1607 case COL_ABS_TIME:
1608 col_set_abs_time(fd, cinfo, col);
1609 break;
1611 case COL_ABS_YMD_TIME:
1612 col_set_abs_ymd_time(fd, cinfo, col);
1613 break;
1615 case COL_ABS_YDOY_TIME:
1616 col_set_abs_ydoy_time(fd, cinfo, col);
1617 break;
1619 case COL_REL_TIME:
1620 col_set_rel_time(fd, cinfo, col);
1621 break;
1623 case COL_DELTA_TIME:
1624 col_set_delta_time(fd, cinfo, col);
1625 break;
1627 case COL_DELTA_TIME_DIS:
1628 col_set_delta_time_dis(fd, cinfo, col);
1629 break;
1631 case COL_UTC_TIME:
1632 col_set_utc_time(fd, cinfo, col);
1633 break;
1635 case COL_UTC_YMD_TIME:
1636 col_set_utc_ymd_time(fd, cinfo, col);
1637 break;
1639 case COL_UTC_YDOY_TIME:
1640 col_set_utc_ydoy_time(fd, cinfo, col);
1641 break;
1643 default:
1644 ws_assert_not_reached();
1645 break;
1649 /* --------------------------- */
1650 /* Set the given (relative) time to a column element.
1652 * Used by dissectors to set the time in a column
1654 * @param cinfo the current packet row
1655 * @param el the column to use, e.g. COL_INFO
1656 * @param ts the time to set in the column
1657 * @param fieldname the fieldname to use for creating a filter (when
1658 * applying/preparing/copying as filter)
1660 void
1661 col_set_time(column_info *cinfo, const int el, const nstime_t *ts, const char *fieldname)
1663 int col;
1664 col_item_t* col_item;
1666 if (!CHECK_COL(cinfo, el))
1667 return;
1669 /** @todo TODO: We don't respect fd->ref_time (no way to access 'fd')
1670 COL_CHECK_REF_TIME(fd, buf);
1673 for (col = cinfo->col_first[el]; col <= cinfo->col_last[el]; col++) {
1674 col_item = &cinfo->columns[col];
1675 if (col_item->fmt_matx[el]) {
1676 display_signed_time(col_item->col_buf, COL_MAX_LEN, ts, get_default_timestamp_precision());
1677 col_item->col_data = col_item->col_buf;
1678 cinfo->col_expr.col_expr[col] = fieldname;
1679 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],col_item->col_buf,COL_MAX_LEN);
1684 static void
1685 col_set_addr(packet_info *pinfo, const int col, const address *addr, const bool is_src,
1686 const bool fill_col_exprs, const bool res)
1688 const char *name;
1689 col_item_t* col_item = &pinfo->cinfo->columns[col];
1691 if (addr->type == AT_NONE) {
1692 /* No address, nothing to do */
1693 return;
1696 if (res && (name = address_to_name(addr)) != NULL)
1697 col_item->col_data = name;
1698 else {
1699 col_item->col_data = col_item->col_buf;
1700 address_to_str_buf(addr, col_item->col_buf, COL_MAX_LEN);
1703 if (!fill_col_exprs)
1704 return;
1706 pinfo->cinfo->col_expr.col_expr[col] = address_type_column_filter_string(addr, is_src);
1707 /* For address types that have a filter, create a string */
1708 if (strlen(pinfo->cinfo->col_expr.col_expr[col]) > 0) {
1709 address_to_str_buf(addr, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1710 } else {
1711 /* For address types that don't, use the internal column FT_STRING hfi */
1712 pinfo->cinfo->col_expr.col_expr[col] = proto_registrar_get_nth(col_item->hf_id)->abbrev;
1713 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], pinfo->cinfo->columns[col].col_data, COL_MAX_LEN);
1717 /* ------------------------ */
1718 static void
1719 col_set_port(packet_info *pinfo, const int col, const bool is_res, const bool is_src, const bool fill_col_exprs _U_)
1721 uint32_t port;
1722 col_item_t* col_item = &pinfo->cinfo->columns[col];
1724 if (is_src)
1725 port = pinfo->srcport;
1726 else
1727 port = pinfo->destport;
1729 /* TODO: Use fill_col_exprs */
1731 switch (pinfo->ptype) {
1732 case PT_SCTP:
1733 if (is_res)
1734 (void) g_strlcpy(col_item->col_buf, sctp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1735 else
1736 uint32_to_str_buf(port, col_item->col_buf, COL_MAX_LEN);
1737 break;
1739 case PT_TCP:
1740 uint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1741 if (is_res)
1742 (void) g_strlcpy(col_item->col_buf, tcp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1743 else
1744 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1745 if (is_src)
1746 pinfo->cinfo->col_expr.col_expr[col] = "tcp.srcport";
1747 else
1748 pinfo->cinfo->col_expr.col_expr[col] = "tcp.dstport";
1749 break;
1751 case PT_UDP:
1752 uint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1753 if (is_res)
1754 (void) g_strlcpy(col_item->col_buf, udp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1755 else
1756 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1757 if (is_src)
1758 pinfo->cinfo->col_expr.col_expr[col] = "udp.srcport";
1759 else
1760 pinfo->cinfo->col_expr.col_expr[col] = "udp.dstport";
1761 break;
1763 case PT_DDP:
1764 if (is_src)
1765 pinfo->cinfo->col_expr.col_expr[col] = "ddp.src_socket";
1766 else
1767 pinfo->cinfo->col_expr.col_expr[col] = "ddp.dst_socket";
1768 uint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1769 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1770 break;
1772 case PT_IPX:
1773 /* XXX - resolve IPX socket numbers */
1774 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%04x", port);
1775 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
1776 if (is_src)
1777 pinfo->cinfo->col_expr.col_expr[col] = "ipx.src.socket";
1778 else
1779 pinfo->cinfo->col_expr.col_expr[col] = "ipx.dst.socket";
1780 break;
1782 case PT_IDP:
1783 /* XXX - resolve IDP socket numbers */
1784 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%04x", port);
1785 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
1786 if (is_src)
1787 pinfo->cinfo->col_expr.col_expr[col] = "idp.src.socket";
1788 else
1789 pinfo->cinfo->col_expr.col_expr[col] = "idp.dst.socket";
1790 break;
1792 case PT_USB:
1793 /* XXX - resolve USB endpoint numbers */
1794 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%08x", port);
1795 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
1796 if (is_src)
1797 pinfo->cinfo->col_expr.col_expr[col] = "usb.src.endpoint";
1798 else
1799 pinfo->cinfo->col_expr.col_expr[col] = "usb.dst.endpoint";
1800 break;
1802 default:
1803 break;
1805 col_item->col_data = col_item->col_buf;
1808 bool
1809 col_based_on_frame_data(column_info *cinfo, const int col)
1811 ws_assert(cinfo);
1812 ws_assert(col < cinfo->num_cols);
1814 switch (cinfo->columns[col].col_fmt) {
1815 case COL_NUMBER:
1816 case COL_NUMBER_DIS:
1817 case COL_CLS_TIME:
1818 case COL_ABS_TIME:
1819 case COL_ABS_YMD_TIME:
1820 case COL_ABS_YDOY_TIME:
1821 case COL_UTC_TIME:
1822 case COL_UTC_YMD_TIME:
1823 case COL_UTC_YDOY_TIME:
1824 case COL_REL_TIME:
1825 case COL_DELTA_TIME:
1826 case COL_DELTA_TIME_DIS:
1827 case COL_PACKET_LENGTH:
1828 case COL_CUMULATIVE_BYTES:
1829 return true;
1831 default:
1832 return false;
1836 void
1837 col_fill_in_frame_data(const frame_data *fd, column_info *cinfo, const int col, const bool fill_col_exprs)
1839 col_item_t* col_item = &cinfo->columns[col];
1841 switch (col_item->col_fmt) {
1842 case COL_NUMBER:
1843 uint32_to_str_buf(fd->num, col_item->col_buf, COL_MAX_LEN);
1844 col_item->col_data = col_item->col_buf;
1845 break;
1847 case COL_NUMBER_DIS:
1848 uint32_to_str_buf(fd->dis_num, col_item->col_buf, COL_MAX_LEN);
1849 col_item->col_data = col_item->col_buf;
1850 break;
1852 case COL_CLS_TIME:
1853 case COL_ABS_TIME:
1854 case COL_ABS_YMD_TIME:
1855 case COL_ABS_YDOY_TIME:
1856 case COL_UTC_TIME:
1857 case COL_UTC_YMD_TIME:
1858 case COL_UTC_YDOY_TIME:
1859 case COL_REL_TIME:
1860 case COL_DELTA_TIME:
1861 case COL_DELTA_TIME_DIS:
1862 /* TODO: Pass on fill_col_exprs */
1863 col_set_fmt_time(fd, cinfo, col_item->col_fmt, col);
1864 break;
1866 case COL_PACKET_LENGTH:
1867 uint32_to_str_buf(fd->pkt_len, col_item->col_buf, COL_MAX_LEN);
1868 col_item->col_data = col_item->col_buf;
1869 break;
1871 case COL_CUMULATIVE_BYTES:
1872 uint32_to_str_buf(fd->cum_bytes, col_item->col_buf, COL_MAX_LEN);
1873 col_item->col_data = col_item->col_buf;
1874 break;
1876 default:
1877 break;
1880 if (!fill_col_exprs)
1881 return;
1883 switch (col_item->col_fmt) {
1884 case COL_NUMBER:
1885 cinfo->col_expr.col_expr[col] = "frame.number";
1886 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col], col_item->col_buf, COL_MAX_LEN);
1887 break;
1889 case COL_CLS_TIME:
1890 case COL_ABS_TIME:
1891 case COL_ABS_YMD_TIME:
1892 case COL_ABS_YDOY_TIME:
1893 case COL_UTC_TIME:
1894 case COL_UTC_YMD_TIME:
1895 case COL_UTC_YDOY_TIME:
1896 case COL_REL_TIME:
1897 case COL_DELTA_TIME:
1898 case COL_DELTA_TIME_DIS:
1899 /* Already handled above */
1900 break;
1902 case COL_PACKET_LENGTH:
1903 cinfo->col_expr.col_expr[col] = "frame.len";
1904 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col], col_item->col_buf, COL_MAX_LEN);
1905 break;
1907 case COL_CUMULATIVE_BYTES:
1908 case COL_NUMBER_DIS:
1909 break;
1911 default:
1912 break;
1916 void
1917 col_fill_in(packet_info *pinfo, const bool fill_col_exprs, const bool fill_fd_colums)
1919 int i;
1920 col_item_t* col_item;
1922 if (!pinfo->cinfo)
1923 return;
1925 for (i = 0; i < pinfo->cinfo->num_cols; i++) {
1926 col_item = &pinfo->cinfo->columns[i];
1927 if (col_based_on_frame_data(pinfo->cinfo, i)) {
1928 if (fill_fd_colums)
1929 col_fill_in_frame_data(pinfo->fd, pinfo->cinfo, i, fill_col_exprs);
1930 } else {
1931 switch (col_item->col_fmt) {
1932 case COL_DEF_SRC:
1933 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
1934 col_set_addr(pinfo, i, &pinfo->src, true, fill_col_exprs, true);
1935 break;
1937 case COL_UNRES_SRC:
1938 col_set_addr(pinfo, i, &pinfo->src, true, fill_col_exprs, false);
1939 break;
1941 case COL_DEF_DL_SRC:
1942 case COL_RES_DL_SRC:
1943 col_set_addr(pinfo, i, &pinfo->dl_src, true, fill_col_exprs, true);
1944 break;
1946 case COL_UNRES_DL_SRC:
1947 col_set_addr(pinfo, i, &pinfo->dl_src, true, fill_col_exprs, false);
1948 break;
1950 case COL_DEF_NET_SRC:
1951 case COL_RES_NET_SRC:
1952 col_set_addr(pinfo, i, &pinfo->net_src, true, fill_col_exprs, true);
1953 break;
1955 case COL_UNRES_NET_SRC:
1956 col_set_addr(pinfo, i, &pinfo->net_src, true, fill_col_exprs, false);
1957 break;
1959 case COL_DEF_DST:
1960 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
1961 col_set_addr(pinfo, i, &pinfo->dst, false, fill_col_exprs, true);
1962 break;
1964 case COL_UNRES_DST:
1965 col_set_addr(pinfo, i, &pinfo->dst, false, fill_col_exprs, false);
1966 break;
1968 case COL_DEF_DL_DST:
1969 case COL_RES_DL_DST:
1970 col_set_addr(pinfo, i, &pinfo->dl_dst, false, fill_col_exprs, true);
1971 break;
1973 case COL_UNRES_DL_DST:
1974 col_set_addr(pinfo, i, &pinfo->dl_dst, false, fill_col_exprs, false);
1975 break;
1977 case COL_DEF_NET_DST:
1978 case COL_RES_NET_DST:
1979 col_set_addr(pinfo, i, &pinfo->net_dst, false, fill_col_exprs, true);
1980 break;
1982 case COL_UNRES_NET_DST:
1983 col_set_addr(pinfo, i, &pinfo->net_dst, false, fill_col_exprs, false);
1984 break;
1986 case COL_DEF_SRC_PORT:
1987 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
1988 col_set_port(pinfo, i, true, true, fill_col_exprs);
1989 break;
1991 case COL_UNRES_SRC_PORT:
1992 col_set_port(pinfo, i, false, true, fill_col_exprs);
1993 break;
1995 case COL_DEF_DST_PORT:
1996 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1997 col_set_port(pinfo, i, true, false, fill_col_exprs);
1998 break;
2000 case COL_UNRES_DST_PORT:
2001 col_set_port(pinfo, i, false, false, fill_col_exprs);
2002 break;
2004 case COL_CUSTOM:
2005 /* Formatting handled by col_custom_set_edt() / col_custom_get_filter() */
2006 break;
2008 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
2009 ws_assert_not_reached();
2010 break;
2011 default:
2012 if (col_item->col_fmt >= NUM_COL_FMTS) {
2013 ws_assert_not_reached();
2016 * Formatting handled by expert.c (COL_EXPERT), or individual
2017 * dissectors. Fill in from the text using the internal hfid.
2019 if (fill_col_exprs) {
2020 pinfo->cinfo->col_expr.col_expr[i] = proto_registrar_get_nth(col_item->hf_id)->abbrev;
2021 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[i], pinfo->cinfo->columns[i].col_data, (col_item->col_fmt == COL_INFO) ? COL_MAX_INFO_LEN : COL_MAX_LEN);
2023 break;
2030 * Fill in columns if we got an error reading the packet.
2031 * We set most columns to "???", fill in columns that don't need data read
2032 * from the file, and set the Info column to an error message.
2034 void
2035 col_fill_in_error(column_info *cinfo, frame_data *fdata, const bool fill_col_exprs, const bool fill_fd_colums)
2037 int i;
2038 col_item_t* col_item;
2040 if (!cinfo)
2041 return;
2043 for (i = 0; i < cinfo->num_cols; i++) {
2044 col_item = &cinfo->columns[i];
2045 if (col_based_on_frame_data(cinfo, i)) {
2046 if (fill_fd_colums)
2047 col_fill_in_frame_data(fdata, cinfo, i, fill_col_exprs);
2048 } else if (col_item->col_fmt == COL_INFO) {
2049 /* XXX - say more than this */
2050 col_item->col_data = "Read error";
2051 } else {
2052 if (col_item->col_fmt >= NUM_COL_FMTS) {
2053 ws_assert_not_reached();
2056 * No dissection was done, and these columns are set as the
2057 * result of the dissection, so....
2059 col_item->col_data = "???";
2060 break;
2065 bool col_data_changed(void) {
2066 bool cur_cdc = col_data_changed_;
2067 col_data_changed_ = false;
2068 return cur_cdc;
2071 void
2072 col_register_protocol(void)
2074 /* This gets called by proto_init() before column_register_fields()
2075 * gets called by the preference modules actually getting registered.
2077 if (proto_cols <= 0) {
2078 proto_cols = proto_get_id_by_filter_name("_ws.col");
2080 if (proto_cols <= 0) {
2081 proto_cols = proto_register_protocol("Wireshark Columns", "Columns", "_ws.col");
2083 static int *ett[] = {
2084 &ett_cols
2086 proto_register_subtree_array(ett, G_N_ELEMENTS(ett));
2089 void
2090 col_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2092 proto_item *ti;
2093 proto_tree *col_tree;
2095 column_info *cinfo = pinfo->cinfo;
2097 if (!cinfo) {
2098 return;
2101 if (proto_field_is_referenced(tree, proto_cols)) {
2102 // XXX: Needed if we also create _ws.col.custom
2103 //col_custom_set(tree, cinfo);
2104 col_fill_in(pinfo, false, true);
2105 ti = proto_tree_add_item(tree, proto_cols, tvb, 0, 0, ENC_NA);
2106 proto_item_set_hidden(ti);
2107 col_tree = proto_item_add_subtree(ti, ett_cols);
2108 for (int i = 0; i < cinfo->num_cols; ++i) {
2109 if (cinfo->columns[i].hf_id != -1) {
2110 if (cinfo->columns[i].col_fmt == COL_CUSTOM) {
2111 ti = proto_tree_add_string_format(col_tree, cinfo->columns[i].hf_id, tvb, 0, 0, get_column_text(cinfo, i), "%s: %s", get_column_title(i), get_column_text(cinfo, i));
2112 } else {
2113 ti = proto_tree_add_string(col_tree, cinfo->columns[i].hf_id, tvb, 0, 0, get_column_text(cinfo, i));
2115 proto_item_set_hidden(ti);
2122 * Editor modelines
2124 * Local Variables:
2125 * c-basic-offset: 2
2126 * tab-width: 8
2127 * indent-tabs-mode: nil
2128 * End:
2130 * ex: set shiftwidth=2 tabstop=8 expandtab:
2131 * :indentSize=2:tabSize=8:noTabs=true: