1 /* column-utils.c
2 * Routines for column utilities.
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "config.h"
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <time.h>
16 #include <locale.h>
17
18 #include "column-utils.h"
19 #include "timestamp.h"
20 #include "to_str.h"
21 #include "packet_info.h"
22 #include "wsutil/pint.h"
23 #include "addr_resolv.h"
24 #include "address_types.h"
25 #include "ipv6.h"
26 #include "osi-utils.h"
27 #include "value_string.h"
28 #include "column-info.h"
29 #include "proto.h"
30
31 #include <epan/strutil.h>
32 #include <epan/epan.h>
33 #include <epan/dfilter/dfilter.h>
34
35 #include <wsutil/utf8_entities.h>
36 #include <wsutil/ws_assert.h>
37
38 #ifdef HAVE_LUA
39 #include <epan/wslua/wslua.h>
40 #endif
41
42 /* Used for locale decimal point */
43 static char *col_decimal_point;
44
45 /* Used to indicate updated column information, e.g. a new request/response. */
46 static gboolean col_data_changed_;
47
48 /* Allocate all the data structures for constructing column data, given
49 the number of columns. */
50 void
col_setup(column_info * cinfo,const gint num_cols)51 col_setup(column_info *cinfo, const gint num_cols)
52 {
53 int i;
54
55 col_decimal_point = localeconv()->decimal_point;
56 cinfo->num_cols = num_cols;
57 cinfo->columns = g_new(col_item_t, num_cols);
58 cinfo->col_first = g_new(int, NUM_COL_FMTS);
59 cinfo->col_last = g_new(int, NUM_COL_FMTS);
60 for (i = 0; i < num_cols; i++) {
61 cinfo->columns[i].col_custom_fields_ids = NULL;
62 }
63 cinfo->col_expr.col_expr = g_new(const gchar*, num_cols + 1);
64 cinfo->col_expr.col_expr_val = g_new(gchar*, num_cols + 1);
65
66 for (i = 0; i < NUM_COL_FMTS; i++) {
67 cinfo->col_first[i] = -1;
68 cinfo->col_last[i] = -1;
69 }
70 cinfo->prime_regex = g_regex_new(COL_CUSTOM_PRIME_REGEX,
71 (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW),
72 G_REGEX_MATCH_ANCHORED, NULL);
73 }
74
75 static void
col_custom_fields_ids_free(GSList ** custom_fields_id)76 col_custom_fields_ids_free(GSList** custom_fields_id)
77 {
78 if (*custom_fields_id != NULL) {
79 g_slist_free_full(*custom_fields_id, g_free);
80 }
81 *custom_fields_id = NULL;
82 }
83
84 /* Cleanup all the data structures for constructing column data; undoes
85 the allocations that col_setup() does. */
86 void
col_cleanup(column_info * cinfo)87 col_cleanup(column_info *cinfo)
88 {
89 int i;
90 col_item_t* col_item;
91
92 if (!cinfo)
93 return;
94
95 for (i = 0; i < cinfo->num_cols; i++) {
96 col_item = &cinfo->columns[i];
97 g_free(col_item->fmt_matx);
98 g_free(col_item->col_title);
99 g_free(col_item->col_custom_fields);
100 dfilter_free(col_item->col_custom_dfilter);
101 /* col_item->col_data points to col_buf or static memory */
102 g_free(col_item->col_buf);
103 g_free(cinfo->col_expr.col_expr_val[i]);
104 col_custom_fields_ids_free(&col_item->col_custom_fields_ids);
105 }
106
107 g_free(cinfo->columns);
108 g_free(cinfo->col_first);
109 g_free(cinfo->col_last);
110 /*
111 * XXX - MSVC doesn't correctly handle the "const" qualifier; it thinks
112 * "const XXX **" means "pointer to const pointer to XXX", i.e. that
113 * it's a pointer to something that's "const"ant, not "pointer to
114 * pointer to const XXX", i.e. that it's a pointer to a pointer to
115 * something that's "const"ant. Cast its bogus complaints away.
116 */
117 g_free((gchar **)cinfo->col_expr.col_expr);
118 g_free(cinfo->col_expr.col_expr_val);
119 if (cinfo->prime_regex)
120 g_regex_unref(cinfo->prime_regex);
121 }
122
123 /* Initialize the data structures for constructing column data. */
124 void
col_init(column_info * cinfo,const struct epan_session * epan)125 col_init(column_info *cinfo, const struct epan_session *epan)
126 {
127 int i;
128 col_item_t* col_item;
129
130 if (!cinfo)
131 return;
132
133 for (i = 0; i < cinfo->num_cols; i++) {
134 col_item = &cinfo->columns[i];
135 col_item->col_buf[0] = '\0';
136 col_item->col_data = col_item->col_buf;
137 col_item->col_fence = 0;
138 col_item->writable = TRUE;
139 cinfo->col_expr.col_expr[i] = "";
140 cinfo->col_expr.col_expr_val[i][0] = '\0';
141 }
142 cinfo->writable = TRUE;
143 cinfo->epan = epan;
144 }
145
146 gboolean
col_get_writable(column_info * cinfo,const gint col)147 col_get_writable(column_info *cinfo, const gint col)
148 {
149 int i;
150 col_item_t* col_item;
151
152 if (cinfo == NULL)
153 return FALSE;
154
155 /* "global" (not) writeability will always override
156 an individual column */
157 if ((col == -1) || (cinfo->writable == FALSE))
158 return cinfo->writable;
159
160 if (cinfo->col_first[col] >= 0) {
161 for (i = cinfo->col_first[col]; i <= cinfo->col_last[col]; i++) {
162 col_item = &cinfo->columns[i];
163 if (col_item->fmt_matx[col]) {
164 return col_item->writable;
165 }
166 }
167 }
168 return FALSE;
169 }
170
171 void
col_set_writable(column_info * cinfo,const gint col,const gboolean writable)172 col_set_writable(column_info *cinfo, const gint col, const gboolean writable)
173 {
174 int i;
175 col_item_t* col_item;
176
177 if (cinfo) {
178 if (col == -1) {
179 cinfo->writable = writable;
180 } else if (cinfo->col_first[col] >= 0) {
181 for (i = cinfo->col_first[col]; i <= cinfo->col_last[col]; i++) {
182 col_item = &cinfo->columns[i];
183 if (col_item->fmt_matx[col]) {
184 col_item->writable = writable;
185 }
186 }
187 }
188 }
189 }
190
191 /* Checks to see if a particular packet information element is needed for the packet list */
192 #define CHECK_COL(cinfo, el) \
193 /* We are constructing columns, and they're writable */ \
194 (col_get_writable(cinfo, el) && \
195 /* There is at least one column in that format */ \
196 ((cinfo)->col_first[el] >= 0))
197
198 /* Sets the fence for a column to be at the end of the column. */
199 void
col_set_fence(column_info * cinfo,const gint el)200 col_set_fence(column_info *cinfo, const gint el)
201 {
202 int i;
203 col_item_t* col_item;
204
205 if (!CHECK_COL(cinfo, el))
206 return;
207
208 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
209 col_item = &cinfo->columns[i];
210 if (col_item->fmt_matx[el]) {
211 col_item->col_fence = (int)strlen(col_item->col_data);
212 }
213 }
214 }
215
216 /* Clear the fence for a column. */
217 void
col_clear_fence(column_info * cinfo,const gint el)218 col_clear_fence(column_info *cinfo, const gint el)
219 {
220 int i;
221 col_item_t* col_item;
222
223 if (!CHECK_COL(cinfo, el))
224 return;
225
226 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
227 col_item = &cinfo->columns[i];
228 if (col_item->fmt_matx[el]) {
229 col_item->col_fence = 0;
230 }
231 }
232 }
233
234 /* Gets the text of a column */
235 const gchar *
col_get_text(column_info * cinfo,const gint el)236 col_get_text(column_info *cinfo, const gint el)
237 {
238 int i;
239 const gchar* text = NULL;
240 col_item_t* col_item;
241
242 if (!(cinfo && (cinfo)->col_first[el] >= 0)) {
243 return NULL;
244 }
245
246 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
247 col_item = &cinfo->columns[i];
248 if (col_item->fmt_matx[el]) {
249 text = (col_item->col_data);
250 }
251 }
252 return text;
253 }
254
255
256 /* Use this to clear out a column, especially if you're going to be
257 appending to it later; at least on some platforms, it's more
258 efficient than using "col_add_str()" with a null string, and
259 more efficient than "col_set_str()" with a null string if you
260 later append to it, as the later append will cause a string
261 copy to be done. */
262 void
col_clear(column_info * cinfo,const gint el)263 col_clear(column_info *cinfo, const gint el)
264 {
265 int i;
266 col_item_t* col_item;
267
268 if (!CHECK_COL(cinfo, el))
269 return;
270
271 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
272 col_item = &cinfo->columns[i];
273 if (col_item->fmt_matx[el]) {
274 /*
275 * At this point, either
276 *
277 * 1) col_data[i] is equal to col_buf[i], in which case we
278 * don't have to worry about copying col_data[i] to
279 * col_buf[i];
280 *
281 * 2) col_data[i] isn't equal to col_buf[i], in which case
282 * the only thing that's been done to the column is
283 * "col_set_str()" calls and possibly "col_set_fence()"
284 * calls, in which case the fence is either unset and
285 * at the beginning of the string or set and at the end
286 * of the string - if it's at the beginning, we're just
287 * going to clear the column, and if it's at the end,
288 * we don't do anything.
289 */
290 if (col_item->col_buf == col_item->col_data || col_item->col_fence == 0) {
291 /*
292 * The fence isn't at the end of the column, or the column wasn't
293 * last set with "col_set_str()", so clear the column out.
294 */
295 col_item->col_buf[col_item->col_fence] = '\0';
296 col_item->col_data = col_item->col_buf;
297 }
298 cinfo->col_expr.col_expr[i] = "";
299 cinfo->col_expr.col_expr_val[i][0] = '\0';
300 }
301 }
302 }
303
304 #define COL_CHECK_APPEND(col_item, max_len) \
305 if (col_item->col_data != col_item->col_buf) { \
306 /* This was set with "col_set_str()"; copy the string they \
307 set it to into the buffer, so we can append to it. */ \
308 (void) g_strlcpy(col_item->col_buf, col_item->col_data, max_len); \
309 col_item->col_data = col_item->col_buf; \
310 }
311
312 #define COL_CHECK_REF_TIME(fd, buf) \
313 if (fd->ref_time) { \
314 (void) g_strlcpy(buf, "*REF*", COL_MAX_LEN ); \
315 return; \
316 }
317
318 /* The same as CHECK_COL(), but without the check to see if the column is writable. */
319 #define HAVE_CUSTOM_COLS(cinfo) ((cinfo) && (cinfo)->col_first[COL_CUSTOM] >= 0)
320
321 gboolean
have_custom_cols(column_info * cinfo)322 have_custom_cols(column_info *cinfo)
323 {
324 return HAVE_CUSTOM_COLS(cinfo);
325 }
326
327 gboolean
have_field_extractors(void)328 have_field_extractors(void)
329 {
330 #ifdef HAVE_LUA
331 return wslua_has_field_extractors();
332 #else
333 return FALSE;
334 #endif
335 }
336
337 /* search in edt tree custom fields */
col_custom_set_edt(epan_dissect_t * edt,column_info * cinfo)338 void col_custom_set_edt(epan_dissect_t *edt, column_info *cinfo)
339 {
340 int i;
341 col_item_t* col_item;
342
343 if (!HAVE_CUSTOM_COLS(cinfo))
344 return;
345
346 for (i = cinfo->col_first[COL_CUSTOM];
347 i <= cinfo->col_last[COL_CUSTOM]; i++) {
348 col_item = &cinfo->columns[i];
349 if (col_item->fmt_matx[COL_CUSTOM] &&
350 col_item->col_custom_fields &&
351 col_item->col_custom_fields_ids) {
352 col_item->col_data = col_item->col_buf;
353 cinfo->col_expr.col_expr[i] = epan_custom_set(edt, col_item->col_custom_fields_ids,
354 col_item->col_custom_occurrence,
355 col_item->col_buf,
356 cinfo->col_expr.col_expr_val[i],
357 COL_MAX_LEN);
358 }
359 }
360 }
361
362 void
col_custom_prime_edt(epan_dissect_t * edt,column_info * cinfo)363 col_custom_prime_edt(epan_dissect_t *edt, column_info *cinfo)
364 {
365 int i;
366 col_item_t* col_item;
367
368 if (!HAVE_CUSTOM_COLS(cinfo))
369 return;
370
371 for (i = cinfo->col_first[COL_CUSTOM];
372 i <= cinfo->col_last[COL_CUSTOM]; i++) {
373 col_item = &cinfo->columns[i];
374
375 if (col_item->fmt_matx[COL_CUSTOM] &&
376 col_item->col_custom_dfilter) {
377 epan_dissect_prime_with_dfilter(edt, col_item->col_custom_dfilter);
378 }
379 }
380 }
381
382 void
col_append_lstr(column_info * cinfo,const gint el,const gchar * str1,...)383 col_append_lstr(column_info *cinfo, const gint el, const gchar *str1, ...)
384 {
385 va_list ap;
386 size_t pos, max_len;
387 int i;
388 const gchar *str;
389 col_item_t* col_item;
390
391 if (!CHECK_COL(cinfo, el))
392 return;
393
394 if (el == COL_INFO)
395 max_len = COL_MAX_INFO_LEN;
396 else
397 max_len = COL_MAX_LEN;
398
399 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
400 col_item = &cinfo->columns[i];
401 if (col_item->fmt_matx[el]) {
402 /*
403 * First arrange that we can append, if necessary.
404 */
405 COL_CHECK_APPEND(col_item, max_len);
406
407 pos = strlen(col_item->col_buf);
408 if (pos >= max_len)
409 return;
410
411 va_start(ap, str1);
412 str = str1;
413 do {
414 if (G_UNLIKELY(str == NULL))
415 str = "(null)";
416
417 pos += g_strlcpy(&col_item->col_buf[pos], str, max_len - pos);
418
419 } while (pos < max_len && (str = va_arg(ap, const char *)) != COL_ADD_LSTR_TERMINATOR);
420 va_end(ap);
421 }
422 }
423 }
424
425 void
col_append_str_uint(column_info * cinfo,const gint col,const gchar * abbrev,guint32 val,const gchar * sep)426 col_append_str_uint(column_info *cinfo, const gint col, const gchar *abbrev, guint32 val, const gchar *sep)
427 {
428 char buf[16];
429
430 guint32_to_str_buf(val, buf, sizeof(buf));
431 col_append_lstr(cinfo, col, sep ? sep : "", abbrev, "=", buf, COL_ADD_LSTR_TERMINATOR);
432 }
433
434 static inline void
col_snprint_port(gchar * buf,size_t buf_siz,port_type typ,guint16 val)435 col_snprint_port(gchar *buf, size_t buf_siz, port_type typ, guint16 val)
436 {
437 const char *str;
438
439 if (gbl_resolv_flags.transport_name &&
440 (str = try_serv_name_lookup(typ, val)) != NULL) {
441 snprintf(buf, buf_siz, "%s(%"G_GUINT16_FORMAT")", str, val);
442 } else {
443 snprintf(buf, buf_siz, "%"G_GUINT16_FORMAT, val);
444 }
445 }
446
447 void
col_append_ports(column_info * cinfo,const gint col,port_type typ,guint16 src,guint16 dst)448 col_append_ports(column_info *cinfo, const gint col, port_type typ, guint16 src, guint16 dst)
449 {
450 char buf_src[32], buf_dst[32];
451
452 col_snprint_port(buf_src, 32, typ, src);
453 col_snprint_port(buf_dst, 32, typ, dst);
454 col_append_lstr(cinfo, col, buf_src, " " UTF8_RIGHTWARDS_ARROW " ", buf_dst, COL_ADD_LSTR_TERMINATOR);
455 }
456
457 void
col_append_frame_number(packet_info * pinfo,const gint col,const gchar * fmt_str,guint frame_num)458 col_append_frame_number(packet_info *pinfo, const gint col, const gchar *fmt_str, guint frame_num)
459 {
460 col_append_fstr(pinfo->cinfo, col, fmt_str, frame_num);
461 if (!pinfo->fd->visited) {
462 col_data_changed_ = TRUE;
463 }
464 }
465
466 static void
col_do_append_fstr(column_info * cinfo,const int el,const char * separator,const char * format,va_list ap)467 col_do_append_fstr(column_info *cinfo, const int el, const char *separator, const char *format, va_list ap)
468 {
469 size_t len, max_len, sep_len;
470 int i;
471 col_item_t* col_item;
472
473 sep_len = (separator) ? strlen(separator) : 0;
474
475 if (el == COL_INFO)
476 max_len = COL_MAX_INFO_LEN;
477 else
478 max_len = COL_MAX_LEN;
479
480 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
481 col_item = &cinfo->columns[i];
482 if (col_item->fmt_matx[el]) {
483 /*
484 * First arrange that we can append, if necessary.
485 */
486 COL_CHECK_APPEND(col_item, max_len);
487
488 len = strlen(col_item->col_buf);
489
490 /*
491 * If we have a separator, append it if the column isn't empty.
492 */
493 if (sep_len != 0 && len != 0) {
494 (void) g_strlcat(col_item->col_buf, separator, max_len);
495 len += sep_len;
496 }
497
498 if (len < max_len) {
499 va_list ap2;
500
501 va_copy(ap2, ap);
502 vsnprintf(&col_item->col_buf[len], max_len - len, format, ap2);
503 va_end(ap2);
504 }
505 }
506 }
507 }
508
509 /* Appends a vararg list to a packet info string. */
510 void
col_append_fstr(column_info * cinfo,const gint el,const gchar * format,...)511 col_append_fstr(column_info *cinfo, const gint el, const gchar *format, ...)
512 {
513 va_list ap;
514
515 if (!CHECK_COL(cinfo, el))
516 return;
517
518 va_start(ap, format);
519 col_do_append_fstr(cinfo, el, NULL, format, ap);
520 va_end(ap);
521 }
522
523 /* Appends a vararg list to a packet info string.
524 * Prefixes it with the given separator if the column is not empty.
525 */
526 void
col_append_sep_fstr(column_info * cinfo,const gint el,const gchar * separator,const gchar * format,...)527 col_append_sep_fstr(column_info *cinfo, const gint el, const gchar *separator,
528 const gchar *format, ...)
529 {
530 va_list ap;
531
532 if (!CHECK_COL(cinfo, el))
533 return;
534
535 if (separator == NULL)
536 separator = ", "; /* default */
537
538 va_start(ap, format);
539 col_do_append_fstr(cinfo, el, separator, format, ap);
540 va_end(ap);
541 }
542
543 /* Prepends a vararg list to a packet info string. */
544 #define COL_BUF_MAX_LEN (((COL_MAX_INFO_LEN) > (COL_MAX_LEN)) ? \
545 (COL_MAX_INFO_LEN) : (COL_MAX_LEN))
546 void
col_prepend_fstr(column_info * cinfo,const gint el,const gchar * format,...)547 col_prepend_fstr(column_info *cinfo, const gint el, const gchar *format, ...)
548 {
549 va_list ap;
550 int i;
551 char orig_buf[COL_BUF_MAX_LEN];
552 const char *orig;
553 int max_len;
554 col_item_t* col_item;
555
556 if (!CHECK_COL(cinfo, el))
557 return;
558
559 if (el == COL_INFO)
560 max_len = COL_MAX_INFO_LEN;
561 else
562 max_len = COL_MAX_LEN;
563
564 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
565 col_item = &cinfo->columns[i];
566 if (col_item->fmt_matx[el]) {
567 if (col_item->col_data != col_item->col_buf) {
568 /* This was set with "col_set_str()"; which is effectively const */
569 orig = col_item->col_data;
570 } else {
571 (void) g_strlcpy(orig_buf, col_item->col_buf, max_len);
572 orig = orig_buf;
573 }
574 va_start(ap, format);
575 vsnprintf(col_item->col_buf, max_len, format, ap);
576 va_end(ap);
577
578 /*
579 * Move the fence, unless it's at the beginning of the string.
580 */
581 if (col_item->col_fence > 0)
582 col_item->col_fence += (int) strlen(col_item->col_buf);
583
584 (void) g_strlcat(col_item->col_buf, orig, max_len);
585 col_item->col_data = col_item->col_buf;
586 }
587 }
588 }
589 void
col_prepend_fence_fstr(column_info * cinfo,const gint el,const gchar * format,...)590 col_prepend_fence_fstr(column_info *cinfo, const gint el, const gchar *format, ...)
591 {
592 va_list ap;
593 int i;
594 char orig_buf[COL_BUF_MAX_LEN];
595 const char *orig;
596 int max_len;
597 col_item_t* col_item;
598
599 if (!CHECK_COL(cinfo, el))
600 return;
601
602 if (el == COL_INFO)
603 max_len = COL_MAX_INFO_LEN;
604 else
605 max_len = COL_MAX_LEN;
606
607 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
608 col_item = &cinfo->columns[i];
609 if (col_item->fmt_matx[el]) {
610 if (col_item->col_data != col_item->col_buf) {
611 /* This was set with "col_set_str()"; which is effectively const */
612 orig = col_item->col_data;
613 } else {
614 (void) g_strlcpy(orig_buf, col_item->col_buf, max_len);
615 orig = orig_buf;
616 }
617 va_start(ap, format);
618 vsnprintf(col_item->col_buf, max_len, format, ap);
619 va_end(ap);
620
621 /*
622 * Move the fence if it exists, else create a new fence at the
623 * end of the prepended data.
624 */
625 if (col_item->col_fence > 0) {
626 col_item->col_fence += (int) strlen(col_item->col_buf);
627 } else {
628 col_item->col_fence = (int) strlen(col_item->col_buf);
629 }
630 (void) g_strlcat(col_item->col_buf, orig, max_len);
631 col_item->col_data = col_item->col_buf;
632 }
633 }
634 }
635
636 /* Use this if "str" points to something that won't stay around (and
637 must thus be copied). */
638 void
col_add_str(column_info * cinfo,const gint el,const gchar * str)639 col_add_str(column_info *cinfo, const gint el, const gchar* str)
640 {
641 int i;
642 size_t max_len;
643 col_item_t* col_item;
644
645 if (!CHECK_COL(cinfo, el))
646 return;
647
648 if (el == COL_INFO)
649 max_len = COL_MAX_INFO_LEN;
650 else
651 max_len = COL_MAX_LEN;
652
653 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
654 col_item = &cinfo->columns[i];
655 if (col_item->fmt_matx[el]) {
656 if (col_item->col_fence != 0) {
657 /*
658 * We will append the string after the fence.
659 * First arrange that we can append, if necessary.
660 */
661 COL_CHECK_APPEND(col_item, max_len);
662 } else {
663 /*
664 * There's no fence, so we can just write to the string.
665 */
666 col_item->col_data = col_item->col_buf;
667 }
668 (void) g_strlcpy(&col_item->col_buf[col_item->col_fence], str, max_len - col_item->col_fence);
669 }
670 }
671 }
672
673 /* Use this if "str" points to something that will stay around (and thus
674 needn't be copied). */
675 void
col_set_str(column_info * cinfo,const gint el,const gchar * str)676 col_set_str(column_info *cinfo, const gint el, const gchar* str)
677 {
678 int i;
679 size_t max_len;
680 col_item_t* col_item;
681
682 DISSECTOR_ASSERT(str);
683
684 if (!CHECK_COL(cinfo, el))
685 return;
686
687 if (el == COL_INFO)
688 max_len = COL_MAX_INFO_LEN;
689 else
690 max_len = COL_MAX_LEN;
691
692 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
693 col_item = &cinfo->columns[i];
694 if (col_item->fmt_matx[el]) {
695 if (col_item->col_fence != 0) {
696 /*
697 * We will append the string after the fence.
698 * First arrange that we can append, if necessary.
699 */
700 COL_CHECK_APPEND(col_item, max_len);
701
702 (void) g_strlcpy(&col_item->col_buf[col_item->col_fence], str, max_len - col_item->col_fence);
703 } else {
704 /*
705 * There's no fence, so we can just set the column to point
706 * to the string.
707 */
708 col_item->col_data = str;
709 }
710 }
711 }
712 }
713
714 void
col_add_lstr(column_info * cinfo,const gint el,const gchar * str1,...)715 col_add_lstr(column_info *cinfo, const gint el, const gchar *str1, ...)
716 {
717 va_list ap;
718 int i;
719 gsize pos;
720 gsize max_len;
721 const gchar *str;
722 col_item_t* col_item;
723
724 if (!CHECK_COL(cinfo, el))
725 return;
726
727 if (el == COL_INFO)
728 max_len = COL_MAX_INFO_LEN;
729 else
730 max_len = COL_MAX_LEN;
731
732 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
733 col_item = &cinfo->columns[i];
734 if (col_item->fmt_matx[el]) {
735 pos = col_item->col_fence;
736 if (pos != 0) {
737 /*
738 * We will append the string after the fence.
739 * First arrange that we can append, if necessary.
740 */
741 COL_CHECK_APPEND(col_item, max_len);
742 } else {
743 /*
744 * There's no fence, so we can just write to the string.
745 */
746 col_item->col_data = col_item->col_buf;
747 }
748
749 va_start(ap, str1);
750 str = str1;
751 do {
752 if (G_UNLIKELY(str == NULL))
753 str = "(null)";
754
755 pos += g_strlcpy(&col_item->col_buf[pos], str, max_len - pos);
756
757 } while (pos < max_len && (str = va_arg(ap, const char *)) != COL_ADD_LSTR_TERMINATOR);
758 va_end(ap);
759 }
760 }
761 }
762
763 /* Adds a vararg list to a packet info string. */
764 void
col_add_fstr(column_info * cinfo,const gint el,const gchar * format,...)765 col_add_fstr(column_info *cinfo, const gint el, const gchar *format, ...)
766 {
767 va_list ap;
768 int i;
769 int max_len;
770 col_item_t* col_item;
771
772 if (!CHECK_COL(cinfo, el))
773 return;
774
775 if (el == COL_INFO)
776 max_len = COL_MAX_INFO_LEN;
777 else
778 max_len = COL_MAX_LEN;
779
780 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
781 col_item = &cinfo->columns[i];
782 if (col_item->fmt_matx[el]) {
783 if (col_item->col_fence != 0) {
784 /*
785 * We will append the string after the fence.
786 * First arrange that we can append, if necessary.
787 */
788 COL_CHECK_APPEND(col_item, max_len);
789 } else {
790 /*
791 * There's no fence, so we can just write to the string.
792 */
793 col_item->col_data = col_item->col_buf;
794 }
795 va_start(ap, format);
796 vsnprintf(&col_item->col_buf[col_item->col_fence], max_len - col_item->col_fence, format, ap);
797 va_end(ap);
798 }
799 }
800 }
801
802 static void
col_do_append_str(column_info * cinfo,const gint el,const gchar * separator,const gchar * str)803 col_do_append_str(column_info *cinfo, const gint el, const gchar* separator,
804 const gchar* str)
805 {
806 int i;
807 size_t len, max_len;
808 col_item_t* col_item;
809
810 if (el == COL_INFO)
811 max_len = COL_MAX_INFO_LEN;
812 else
813 max_len = COL_MAX_LEN;
814
815 for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
816 col_item = &cinfo->columns[i];
817 if (col_item->fmt_matx[el]) {
818 /*
819 * First arrange that we can append, if necessary.
820 */
821 COL_CHECK_APPEND(col_item, max_len);
822
823 len = col_item->col_buf[0];
824
825 /*
826 * If we have a separator, append it if the column isn't empty.
827 */
828 if (separator != NULL) {
829 if (len != 0) {
830 (void) g_strlcat(col_item->col_buf, separator, max_len);
831 }
832 }
833 (void) g_strlcat(col_item->col_buf, str, max_len);
834 }
835 }
836 }
837
838 void
col_append_str(column_info * cinfo,const gint el,const gchar * str)839 col_append_str(column_info *cinfo, const gint el, const gchar* str)
840 {
841 if (!CHECK_COL(cinfo, el))
842 return;
843
844 col_do_append_str(cinfo, el, NULL, str);
845 }
846
847 void
col_append_sep_str(column_info * cinfo,const gint el,const gchar * separator,const gchar * str)848 col_append_sep_str(column_info *cinfo, const gint el, const gchar* separator,
849 const gchar* str)
850 {
851 if (!CHECK_COL(cinfo, el))
852 return;
853
854 if (separator == NULL)
855 separator = ", "; /* default */
856
857 col_do_append_str(cinfo, el, separator, str);
858 }
859
860 /* --------------------------------- */
861 gboolean
col_has_time_fmt(column_info * cinfo,const gint col)862 col_has_time_fmt(column_info *cinfo, const gint col)
863 {
864 col_item_t* col_item = &cinfo->columns[col];
865 return ((col_item->fmt_matx[COL_CLS_TIME]) ||
866 (col_item->fmt_matx[COL_ABS_TIME]) ||
867 (col_item->fmt_matx[COL_ABS_YMD_TIME]) ||
868 (col_item->fmt_matx[COL_ABS_YDOY_TIME]) ||
869 (col_item->fmt_matx[COL_UTC_TIME]) ||
870 (col_item->fmt_matx[COL_UTC_YMD_TIME]) ||
871 (col_item->fmt_matx[COL_UTC_YDOY_TIME]) ||
872 (col_item->fmt_matx[COL_REL_TIME]) ||
873 (col_item->fmt_matx[COL_DELTA_TIME]) ||
874 (col_item->fmt_matx[COL_DELTA_TIME_DIS]));
875 }
876
877 static void
set_abs_ymd_time(const frame_data * fd,gchar * buf,char * decimal_point,gboolean local)878 set_abs_ymd_time(const frame_data *fd, gchar *buf, char *decimal_point, gboolean local)
879 {
880 struct tm *tmp;
881 time_t then;
882 int tsprecision;
883
884 if (fd->has_ts) {
885 then = fd->abs_ts.secs;
886 if (local)
887 tmp = localtime(&then);
888 else
889 tmp = gmtime(&then);
890 } else
891 tmp = NULL;
892 if (tmp != NULL) {
893 switch (timestamp_get_precision()) {
894 case TS_PREC_FIXED_SEC:
895 tsprecision = WTAP_TSPREC_SEC;
896 break;
897 case TS_PREC_FIXED_DSEC:
898 tsprecision = WTAP_TSPREC_DSEC;
899 break;
900 case TS_PREC_FIXED_CSEC:
901 tsprecision = WTAP_TSPREC_CSEC;
902 break;
903 case TS_PREC_FIXED_MSEC:
904 tsprecision = WTAP_TSPREC_MSEC;
905 break;
906 case TS_PREC_FIXED_USEC:
907 tsprecision = WTAP_TSPREC_USEC;
908 break;
909 case TS_PREC_FIXED_NSEC:
910 tsprecision = WTAP_TSPREC_NSEC;
911 break;
912 case TS_PREC_AUTO:
913 tsprecision = fd->tsprec;
914 break;
915 default:
916 ws_assert_not_reached();
917 }
918 switch (tsprecision) {
919 case WTAP_TSPREC_SEC:
920 snprintf(buf, COL_MAX_LEN,"%04d-%02d-%02d %02d:%02d:%02d",
921 tmp->tm_year + 1900,
922 tmp->tm_mon + 1,
923 tmp->tm_mday,
924 tmp->tm_hour,
925 tmp->tm_min,
926 tmp->tm_sec);
927 break;
928 case WTAP_TSPREC_DSEC:
929 snprintf(buf, COL_MAX_LEN,"%04d-%02d-%02d %02d:%02d:%02d%s%01d",
930 tmp->tm_year + 1900,
931 tmp->tm_mon + 1,
932 tmp->tm_mday,
933 tmp->tm_hour,
934 tmp->tm_min,
935 tmp->tm_sec,
936 decimal_point,
937 fd->abs_ts.nsecs / 100000000);
938 break;
939 case WTAP_TSPREC_CSEC:
940 snprintf(buf, COL_MAX_LEN,"%04d-%02d-%02d %02d:%02d:%02d%s%02d",
941 tmp->tm_year + 1900,
942 tmp->tm_mon + 1,
943 tmp->tm_mday,
944 tmp->tm_hour,
945 tmp->tm_min,
946 tmp->tm_sec,
947 decimal_point,
948 fd->abs_ts.nsecs / 10000000);
949 break;
950 case WTAP_TSPREC_MSEC:
951 snprintf(buf, COL_MAX_LEN, "%04d-%02d-%02d %02d:%02d:%02d%s%03d",
952 tmp->tm_year + 1900,
953 tmp->tm_mon + 1,
954 tmp->tm_mday,
955 tmp->tm_hour,
956 tmp->tm_min,
957 tmp->tm_sec,
958 decimal_point,
959 fd->abs_ts.nsecs / 1000000);
960 break;
961 case WTAP_TSPREC_USEC:
962 snprintf(buf, COL_MAX_LEN, "%04d-%02d-%02d %02d:%02d:%02d%s%06d",
963 tmp->tm_year + 1900,
964 tmp->tm_mon + 1,
965 tmp->tm_mday,
966 tmp->tm_hour,
967 tmp->tm_min,
968 tmp->tm_sec,
969 decimal_point,
970 fd->abs_ts.nsecs / 1000);
971 break;
972 case WTAP_TSPREC_NSEC:
973 snprintf(buf, COL_MAX_LEN, "%04d-%02d-%02d %02d:%02d:%02d%s%09d",
974 tmp->tm_year + 1900,
975 tmp->tm_mon + 1,
976 tmp->tm_mday,
977 tmp->tm_hour,
978 tmp->tm_min,
979 tmp->tm_sec,
980 decimal_point,
981 fd->abs_ts.nsecs);
982 break;
983 default:
984 ws_assert_not_reached();
985 }
986 } else {
987 buf[0] = '\0';
988 }
989 }
990
991 static void
col_set_abs_ymd_time(const frame_data * fd,column_info * cinfo,const int col)992 col_set_abs_ymd_time(const frame_data *fd, column_info *cinfo, const int col)
993 {
994 set_abs_ymd_time(fd, cinfo->columns[col].col_buf, col_decimal_point, TRUE);
995 cinfo->col_expr.col_expr[col] = "frame.time";
996 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
997
998 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
999 }
1000
1001 static void
col_set_utc_ymd_time(const frame_data * fd,column_info * cinfo,const int col)1002 col_set_utc_ymd_time(const frame_data *fd, column_info *cinfo, const int col)
1003 {
1004 set_abs_ymd_time(fd, cinfo->columns[col].col_buf, col_decimal_point, FALSE);
1005 cinfo->col_expr.col_expr[col] = "frame.time";
1006 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1007
1008 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1009 }
1010
1011 static void
set_abs_ydoy_time(const frame_data * fd,gchar * buf,char * decimal_point,gboolean local)1012 set_abs_ydoy_time(const frame_data *fd, gchar *buf, char *decimal_point, gboolean local)
1013 {
1014 struct tm *tmp;
1015 time_t then;
1016 int tsprecision;
1017
1018 if (fd->has_ts) {
1019 then = fd->abs_ts.secs;
1020 if (local)
1021 tmp = localtime(&then);
1022 else
1023 tmp = gmtime(&then);
1024 } else
1025 tmp = NULL;
1026 if (tmp != NULL) {
1027 switch (timestamp_get_precision()) {
1028 case TS_PREC_FIXED_SEC:
1029 tsprecision = WTAP_TSPREC_SEC;
1030 break;
1031 case TS_PREC_FIXED_DSEC:
1032 tsprecision = WTAP_TSPREC_DSEC;
1033 break;
1034 case TS_PREC_FIXED_CSEC:
1035 tsprecision = WTAP_TSPREC_CSEC;
1036 break;
1037 case TS_PREC_FIXED_MSEC:
1038 tsprecision = WTAP_TSPREC_MSEC;
1039 break;
1040 case TS_PREC_FIXED_USEC:
1041 tsprecision = WTAP_TSPREC_USEC;
1042 break;
1043 case TS_PREC_FIXED_NSEC:
1044 tsprecision = WTAP_TSPREC_NSEC;
1045 break;
1046 case TS_PREC_AUTO:
1047 tsprecision = fd->tsprec;
1048 break;
1049 default:
1050 ws_assert_not_reached();
1051 }
1052 switch (tsprecision) {
1053 case WTAP_TSPREC_SEC:
1054 snprintf(buf, COL_MAX_LEN,"%04d/%03d %02d:%02d:%02d",
1055 tmp->tm_year + 1900,
1056 tmp->tm_yday + 1,
1057 tmp->tm_hour,
1058 tmp->tm_min,
1059 tmp->tm_sec);
1060 break;
1061 case WTAP_TSPREC_DSEC:
1062 snprintf(buf, COL_MAX_LEN,"%04d/%03d %02d:%02d:%02d%s%01d",
1063 tmp->tm_year + 1900,
1064 tmp->tm_yday + 1,
1065 tmp->tm_hour,
1066 tmp->tm_min,
1067 tmp->tm_sec,
1068 decimal_point,
1069 fd->abs_ts.nsecs / 100000000);
1070 break;
1071 case WTAP_TSPREC_CSEC:
1072 snprintf(buf, COL_MAX_LEN,"%04d/%03d %02d:%02d:%02d%s%02d",
1073 tmp->tm_year + 1900,
1074 tmp->tm_yday + 1,
1075 tmp->tm_hour,
1076 tmp->tm_min,
1077 tmp->tm_sec,
1078 decimal_point,
1079 fd->abs_ts.nsecs / 10000000);
1080 break;
1081 case WTAP_TSPREC_MSEC:
1082 snprintf(buf, COL_MAX_LEN, "%04d/%03d %02d:%02d:%02d%s%03d",
1083 tmp->tm_year + 1900,
1084 tmp->tm_yday + 1,
1085 tmp->tm_hour,
1086 tmp->tm_min,
1087 tmp->tm_sec,
1088 decimal_point,
1089 fd->abs_ts.nsecs / 1000000);
1090 break;
1091 case WTAP_TSPREC_USEC:
1092 snprintf(buf, COL_MAX_LEN, "%04d/%03d %02d:%02d:%02d%s%06d",
1093 tmp->tm_year + 1900,
1094 tmp->tm_yday + 1,
1095 tmp->tm_hour,
1096 tmp->tm_min,
1097 tmp->tm_sec,
1098 decimal_point,
1099 fd->abs_ts.nsecs / 1000);
1100 break;
1101 case WTAP_TSPREC_NSEC:
1102 snprintf(buf, COL_MAX_LEN, "%04d/%03d %02d:%02d:%02d%s%09d",
1103 tmp->tm_year + 1900,
1104 tmp->tm_yday + 1,
1105 tmp->tm_hour,
1106 tmp->tm_min,
1107 tmp->tm_sec,
1108 decimal_point,
1109 fd->abs_ts.nsecs);
1110 break;
1111 default:
1112 ws_assert_not_reached();
1113 }
1114 } else {
1115 buf[0] = '\0';
1116 }
1117 }
1118
1119 static void
col_set_abs_ydoy_time(const frame_data * fd,column_info * cinfo,const int col)1120 col_set_abs_ydoy_time(const frame_data *fd, column_info *cinfo, const int col)
1121 {
1122 set_abs_ydoy_time(fd, cinfo->columns[col].col_buf, col_decimal_point, TRUE);
1123 cinfo->col_expr.col_expr[col] = "frame.time";
1124 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1125
1126 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1127 }
1128
1129 static void
col_set_utc_ydoy_time(const frame_data * fd,column_info * cinfo,const int col)1130 col_set_utc_ydoy_time(const frame_data *fd, column_info *cinfo, const int col)
1131 {
1132 set_abs_ydoy_time(fd, cinfo->columns[col].col_buf, col_decimal_point, FALSE);
1133 cinfo->col_expr.col_expr[col] = "frame.time";
1134 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1135
1136 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1137 }
1138
1139 static void
set_time_seconds(const frame_data * fd,const nstime_t * ts,gchar * buf)1140 set_time_seconds(const frame_data *fd, const nstime_t *ts, gchar *buf)
1141 {
1142 int tsprecision;
1143
1144 switch (timestamp_get_precision()) {
1145 case TS_PREC_FIXED_SEC:
1146 tsprecision = WTAP_TSPREC_SEC;
1147 break;
1148 case TS_PREC_FIXED_DSEC:
1149 tsprecision = WTAP_TSPREC_DSEC;
1150 break;
1151 case TS_PREC_FIXED_CSEC:
1152 tsprecision = WTAP_TSPREC_CSEC;
1153 break;
1154 case TS_PREC_FIXED_MSEC:
1155 tsprecision = WTAP_TSPREC_MSEC;
1156 break;
1157 case TS_PREC_FIXED_USEC:
1158 tsprecision = WTAP_TSPREC_USEC;
1159 break;
1160 case TS_PREC_FIXED_NSEC:
1161 tsprecision = WTAP_TSPREC_NSEC;
1162 break;
1163 case TS_PREC_AUTO:
1164 tsprecision = fd->tsprec;
1165 break;
1166 default:
1167 ws_assert_not_reached();
1168 }
1169 switch (tsprecision) {
1170 case WTAP_TSPREC_SEC:
1171 display_signed_time(buf, COL_MAX_LEN,
1172 (gint64) ts->secs, ts->nsecs / 1000000000, TO_STR_TIME_RES_T_SECS);
1173 break;
1174 case WTAP_TSPREC_DSEC:
1175 display_signed_time(buf, COL_MAX_LEN,
1176 (gint64) ts->secs, ts->nsecs / 100000000, TO_STR_TIME_RES_T_DSECS);
1177 break;
1178 case WTAP_TSPREC_CSEC:
1179 display_signed_time(buf, COL_MAX_LEN,
1180 (gint64) ts->secs, ts->nsecs / 10000000, TO_STR_TIME_RES_T_CSECS);
1181 break;
1182 case WTAP_TSPREC_MSEC:
1183 display_signed_time(buf, COL_MAX_LEN,
1184 (gint64) ts->secs, ts->nsecs / 1000000, TO_STR_TIME_RES_T_MSECS);
1185 break;
1186 case WTAP_TSPREC_USEC:
1187 display_signed_time(buf, COL_MAX_LEN,
1188 (gint64) ts->secs, ts->nsecs / 1000, TO_STR_TIME_RES_T_USECS);
1189 break;
1190 case WTAP_TSPREC_NSEC:
1191 display_signed_time(buf, COL_MAX_LEN,
1192 (gint64) ts->secs, ts->nsecs, TO_STR_TIME_RES_T_NSECS);
1193 break;
1194 default:
1195 ws_assert_not_reached();
1196 }
1197 }
1198
1199 static void
set_time_hour_min_sec(const frame_data * fd,const nstime_t * ts,gchar * buf,char * decimal_point)1200 set_time_hour_min_sec(const frame_data *fd, const nstime_t *ts, gchar *buf, char *decimal_point)
1201 {
1202 time_t secs = ts->secs;
1203 long nsecs = (long) ts->nsecs;
1204 gboolean negative = FALSE;
1205 int tsprecision;
1206
1207 if (secs < 0) {
1208 secs = -secs;
1209 negative = TRUE;
1210 }
1211 if (nsecs < 0) {
1212 nsecs = -nsecs;
1213 negative = TRUE;
1214 }
1215
1216 switch (timestamp_get_precision()) {
1217 case TS_PREC_FIXED_SEC:
1218 tsprecision = WTAP_TSPREC_SEC;
1219 break;
1220 case TS_PREC_FIXED_DSEC:
1221 tsprecision = WTAP_TSPREC_DSEC;
1222 break;
1223 case TS_PREC_FIXED_CSEC:
1224 tsprecision = WTAP_TSPREC_CSEC;
1225 break;
1226 case TS_PREC_FIXED_MSEC:
1227 tsprecision = WTAP_TSPREC_MSEC;
1228 break;
1229 case TS_PREC_FIXED_USEC:
1230 tsprecision = WTAP_TSPREC_USEC;
1231 break;
1232 case TS_PREC_FIXED_NSEC:
1233 tsprecision = WTAP_TSPREC_NSEC;
1234 break;
1235 case TS_PREC_AUTO:
1236 tsprecision = fd->tsprec;
1237 break;
1238 default:
1239 ws_assert_not_reached();
1240 }
1241 switch (tsprecision) {
1242 case WTAP_TSPREC_SEC:
1243 if (secs >= (60*60)) {
1244 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2ds",
1245 negative ? "- " : "",
1246 (gint32) secs / (60 * 60),
1247 (gint32) (secs / 60) % 60,
1248 (gint32) secs % 60);
1249 } else if (secs >= 60) {
1250 snprintf(buf, COL_MAX_LEN, "%s%dm %2ds",
1251 negative ? "- " : "",
1252 (gint32) secs / 60,
1253 (gint32) secs % 60);
1254 } else {
1255 snprintf(buf, COL_MAX_LEN, "%s%ds",
1256 negative ? "- " : "",
1257 (gint32) secs);
1258 }
1259 break;
1260 case WTAP_TSPREC_DSEC:
1261 if (secs >= (60*60)) {
1262 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2d%s%01lds",
1263 negative ? "- " : "",
1264 (gint32) secs / (60 * 60),
1265 (gint32) (secs / 60) % 60,
1266 (gint32) secs % 60,
1267 decimal_point,
1268 nsecs / 100000000);
1269 } else if (secs >= 60) {
1270 snprintf(buf, COL_MAX_LEN, "%s%dm %2d%s%01lds",
1271 negative ? "- " : "",
1272 (gint32) secs / 60,
1273 (gint32) secs % 60,
1274 decimal_point,
1275 nsecs / 100000000);
1276 } else {
1277 snprintf(buf, COL_MAX_LEN, "%s%d%s%01lds",
1278 negative ? "- " : "",
1279 (gint32) secs,
1280 decimal_point,
1281 nsecs / 100000000);
1282 }
1283 break;
1284 case WTAP_TSPREC_CSEC:
1285 if (secs >= (60*60)) {
1286 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2d%s%02lds",
1287 negative ? "- " : "",
1288 (gint32) secs / (60 * 60),
1289 (gint32) (secs / 60) % 60,
1290 (gint32) secs % 60,
1291 decimal_point,
1292 nsecs / 10000000);
1293 } else if (secs >= 60) {
1294 snprintf(buf, COL_MAX_LEN, "%s%dm %2d%s%02lds",
1295 negative ? "- " : "",
1296 (gint32) secs / 60,
1297 (gint32) secs % 60,
1298 decimal_point,
1299 nsecs / 10000000);
1300 } else {
1301 snprintf(buf, COL_MAX_LEN, "%s%d%s%02lds",
1302 negative ? "- " : "",
1303 (gint32) secs,
1304 decimal_point,
1305 nsecs / 10000000);
1306 }
1307 break;
1308 case WTAP_TSPREC_MSEC:
1309 if (secs >= (60*60)) {
1310 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2d%s%03lds",
1311 negative ? "- " : "",
1312 (gint32) secs / (60 * 60),
1313 (gint32) (secs / 60) % 60,
1314 (gint32) secs % 60,
1315 decimal_point,
1316 nsecs / 1000000);
1317 } else if (secs >= 60) {
1318 snprintf(buf, COL_MAX_LEN, "%s%dm %2d%s%03lds",
1319 negative ? "- " : "",
1320 (gint32) secs / 60,
1321 (gint32) secs % 60,
1322 decimal_point,
1323 nsecs / 1000000);
1324 } else {
1325 snprintf(buf, COL_MAX_LEN, "%s%d%s%03lds",
1326 negative ? "- " : "",
1327 (gint32) secs,
1328 decimal_point,
1329 nsecs / 1000000);
1330 }
1331 break;
1332 case WTAP_TSPREC_USEC:
1333 if (secs >= (60*60)) {
1334 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2d%s%06lds",
1335 negative ? "- " : "",
1336 (gint32) secs / (60 * 60),
1337 (gint32) (secs / 60) % 60,
1338 (gint32) secs % 60,
1339 decimal_point,
1340 nsecs / 1000);
1341 } else if (secs >= 60) {
1342 snprintf(buf, COL_MAX_LEN, "%s%dm %2d%s%06lds",
1343 negative ? "- " : "",
1344 (gint32) secs / 60,
1345 (gint32) secs % 60,
1346 decimal_point,
1347 nsecs / 1000);
1348 } else {
1349 snprintf(buf, COL_MAX_LEN, "%s%d%s%06lds",
1350 negative ? "- " : "",
1351 (gint32) secs,
1352 decimal_point,
1353 nsecs / 1000);
1354 }
1355 break;
1356 case WTAP_TSPREC_NSEC:
1357 if (secs >= (60*60)) {
1358 snprintf(buf, COL_MAX_LEN, "%s%dh %2dm %2d%s%09lds",
1359 negative ? "- " : "",
1360 (gint32) secs / (60 * 60),
1361 (gint32) (secs / 60) % 60,
1362 (gint32) secs % 60,
1363 decimal_point,
1364 nsecs);
1365 } else if (secs >= 60) {
1366 snprintf(buf, COL_MAX_LEN, "%s%dm %2d%s%09lds",
1367 negative ? "- " : "",
1368 (gint32) secs / 60,
1369 (gint32) secs % 60,
1370 decimal_point,
1371 nsecs);
1372 } else {
1373 snprintf(buf, COL_MAX_LEN, "%s%d%s%09lds",
1374 negative ? "- " : "",
1375 (gint32) secs,
1376 decimal_point,
1377 nsecs);
1378 }
1379 break;
1380 default:
1381 ws_assert_not_reached();
1382 }
1383 }
1384
1385 static void
col_set_rel_time(const frame_data * fd,column_info * cinfo,const int col)1386 col_set_rel_time(const frame_data *fd, column_info *cinfo, const int col)
1387 {
1388 nstime_t del_rel_ts;
1389
1390 if (!fd->has_ts) {
1391 cinfo->columns[col].col_buf[0] = '\0';
1392 return;
1393 }
1394
1395 frame_delta_abs_time(cinfo->epan, fd, fd->frame_ref_num, &del_rel_ts);
1396
1397 switch (timestamp_get_seconds_type()) {
1398 case TS_SECONDS_DEFAULT:
1399 set_time_seconds(fd, &del_rel_ts, cinfo->columns[col].col_buf);
1400 cinfo->col_expr.col_expr[col] = "frame.time_relative";
1401 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1402 break;
1403 case TS_SECONDS_HOUR_MIN_SEC:
1404 set_time_hour_min_sec(fd, &del_rel_ts, cinfo->columns[col].col_buf, col_decimal_point);
1405 cinfo->col_expr.col_expr[col] = "frame.time_relative";
1406 set_time_seconds(fd, &del_rel_ts, cinfo->col_expr.col_expr_val[col]);
1407 break;
1408 default:
1409 ws_assert_not_reached();
1410 }
1411 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1412 }
1413
1414 static void
col_set_delta_time(const frame_data * fd,column_info * cinfo,const int col)1415 col_set_delta_time(const frame_data *fd, column_info *cinfo, const int col)
1416 {
1417 nstime_t del_cap_ts;
1418
1419 frame_delta_abs_time(cinfo->epan, fd, fd->num - 1, &del_cap_ts);
1420
1421 switch (timestamp_get_seconds_type()) {
1422 case TS_SECONDS_DEFAULT:
1423 set_time_seconds(fd, &del_cap_ts, cinfo->columns[col].col_buf);
1424 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1425 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1426 break;
1427 case TS_SECONDS_HOUR_MIN_SEC:
1428 set_time_hour_min_sec(fd, &del_cap_ts, cinfo->columns[col].col_buf, col_decimal_point);
1429 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1430 set_time_seconds(fd, &del_cap_ts, cinfo->col_expr.col_expr_val[col]);
1431 break;
1432 default:
1433 ws_assert_not_reached();
1434 }
1435
1436 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1437 }
1438
1439 static void
col_set_delta_time_dis(const frame_data * fd,column_info * cinfo,const int col)1440 col_set_delta_time_dis(const frame_data *fd, column_info *cinfo, const int col)
1441 {
1442 nstime_t del_dis_ts;
1443
1444 if (!fd->has_ts) {
1445 cinfo->columns[col].col_buf[0] = '\0';
1446 return;
1447 }
1448
1449 frame_delta_abs_time(cinfo->epan, fd, fd->prev_dis_num, &del_dis_ts);
1450
1451 switch (timestamp_get_seconds_type()) {
1452 case TS_SECONDS_DEFAULT:
1453 set_time_seconds(fd, &del_dis_ts, cinfo->columns[col].col_buf);
1454 cinfo->col_expr.col_expr[col] = "frame.time_delta_displayed";
1455 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1456 break;
1457 case TS_SECONDS_HOUR_MIN_SEC:
1458 set_time_hour_min_sec(fd, &del_dis_ts, cinfo->columns[col].col_buf, col_decimal_point);
1459 cinfo->col_expr.col_expr[col] = "frame.time_delta_displayed";
1460 set_time_seconds(fd, &del_dis_ts, cinfo->col_expr.col_expr_val[col]);
1461 break;
1462 default:
1463 ws_assert_not_reached();
1464 }
1465
1466 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1467 }
1468
1469 static void
set_abs_time(const frame_data * fd,gchar * buf,char * decimal_point,gboolean local)1470 set_abs_time(const frame_data *fd, gchar *buf, char *decimal_point, gboolean local)
1471 {
1472 struct tm *tmp;
1473 time_t then;
1474 int tsprecision;
1475
1476 if (fd->has_ts) {
1477 then = fd->abs_ts.secs;
1478 if (local)
1479 tmp = localtime(&then);
1480 else
1481 tmp = gmtime(&then);
1482 } else
1483 tmp = NULL;
1484 if (tmp != NULL) {
1485 switch (timestamp_get_precision()) {
1486 case TS_PREC_FIXED_SEC:
1487 tsprecision = WTAP_TSPREC_SEC;
1488 break;
1489 case TS_PREC_FIXED_DSEC:
1490 tsprecision = WTAP_TSPREC_DSEC;
1491 break;
1492 case TS_PREC_FIXED_CSEC:
1493 tsprecision = WTAP_TSPREC_CSEC;
1494 break;
1495 case TS_PREC_FIXED_MSEC:
1496 tsprecision = WTAP_TSPREC_MSEC;
1497 break;
1498 case TS_PREC_FIXED_USEC:
1499 tsprecision = WTAP_TSPREC_USEC;
1500 break;
1501 case TS_PREC_FIXED_NSEC:
1502 tsprecision = WTAP_TSPREC_NSEC;
1503 break;
1504 case TS_PREC_AUTO:
1505 tsprecision = fd->tsprec;
1506 break;
1507 default:
1508 ws_assert_not_reached();
1509 }
1510 switch (tsprecision) {
1511 case WTAP_TSPREC_SEC:
1512 snprintf(buf, COL_MAX_LEN,"%02d:%02d:%02d",
1513 tmp->tm_hour,
1514 tmp->tm_min,
1515 tmp->tm_sec);
1516 break;
1517 case WTAP_TSPREC_DSEC:
1518 snprintf(buf, COL_MAX_LEN,"%02d:%02d:%02d%s%01d",
1519 tmp->tm_hour,
1520 tmp->tm_min,
1521 tmp->tm_sec,
1522 decimal_point,
1523 fd->abs_ts.nsecs / 100000000);
1524 break;
1525 case WTAP_TSPREC_CSEC:
1526 snprintf(buf, COL_MAX_LEN,"%02d:%02d:%02d%s%02d",
1527 tmp->tm_hour,
1528 tmp->tm_min,
1529 tmp->tm_sec,
1530 decimal_point,
1531 fd->abs_ts.nsecs / 10000000);
1532 break;
1533 case WTAP_TSPREC_MSEC:
1534 snprintf(buf, COL_MAX_LEN,"%02d:%02d:%02d%s%03d",
1535 tmp->tm_hour,
1536 tmp->tm_min,
1537 tmp->tm_sec,
1538 decimal_point,
1539 fd->abs_ts.nsecs / 1000000);
1540 break;
1541 case WTAP_TSPREC_USEC:
1542 snprintf(buf, COL_MAX_LEN,"%02d:%02d:%02d%s%06d",
1543 tmp->tm_hour,
1544 tmp->tm_min,
1545 tmp->tm_sec,
1546 decimal_point,
1547 fd->abs_ts.nsecs / 1000);
1548 break;
1549 case WTAP_TSPREC_NSEC:
1550 snprintf(buf, COL_MAX_LEN, "%02d:%02d:%02d%s%09d",
1551 tmp->tm_hour,
1552 tmp->tm_min,
1553 tmp->tm_sec,
1554 decimal_point,
1555 fd->abs_ts.nsecs);
1556 break;
1557 default:
1558 ws_assert_not_reached();
1559 }
1560
1561 } else {
1562 *buf = '\0';
1563 }
1564 }
1565
1566 static void
col_set_abs_time(const frame_data * fd,column_info * cinfo,const int col)1567 col_set_abs_time(const frame_data *fd, column_info *cinfo, const int col)
1568 {
1569 set_abs_time(fd, cinfo->columns[col].col_buf, col_decimal_point, TRUE);
1570 cinfo->col_expr.col_expr[col] = "frame.time";
1571 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1572
1573 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1574 }
1575
1576 static void
col_set_utc_time(const frame_data * fd,column_info * cinfo,const int col)1577 col_set_utc_time(const frame_data *fd, column_info *cinfo, const int col)
1578 {
1579 set_abs_time(fd, cinfo->columns[col].col_buf, col_decimal_point, FALSE);
1580 cinfo->col_expr.col_expr[col] = "frame.time";
1581 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1582
1583 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1584 }
1585
1586 static gboolean
set_epoch_time(const frame_data * fd,gchar * buf)1587 set_epoch_time(const frame_data *fd, gchar *buf)
1588 {
1589 int tsprecision;
1590
1591 if (!fd->has_ts) {
1592 buf[0] = '\0';
1593 return FALSE;
1594 }
1595 switch (timestamp_get_precision()) {
1596 case TS_PREC_FIXED_SEC:
1597 tsprecision = WTAP_TSPREC_SEC;
1598 break;
1599 case TS_PREC_FIXED_DSEC:
1600 tsprecision = WTAP_TSPREC_DSEC;
1601 break;
1602 case TS_PREC_FIXED_CSEC:
1603 tsprecision = WTAP_TSPREC_CSEC;
1604 break;
1605 case TS_PREC_FIXED_MSEC:
1606 tsprecision = WTAP_TSPREC_MSEC;
1607 break;
1608 case TS_PREC_FIXED_USEC:
1609 tsprecision = WTAP_TSPREC_USEC;
1610 break;
1611 case TS_PREC_FIXED_NSEC:
1612 tsprecision = WTAP_TSPREC_NSEC;
1613 break;
1614 case TS_PREC_AUTO:
1615 tsprecision = fd->tsprec;
1616 break;
1617 default:
1618 ws_assert_not_reached();
1619 }
1620 switch (tsprecision) {
1621 case WTAP_TSPREC_SEC:
1622 display_epoch_time(buf, COL_MAX_LEN,
1623 fd->abs_ts.secs, fd->abs_ts.nsecs / 1000000000, TO_STR_TIME_RES_T_SECS);
1624 break;
1625 case WTAP_TSPREC_DSEC:
1626 display_epoch_time(buf, COL_MAX_LEN,
1627 fd->abs_ts.secs, fd->abs_ts.nsecs / 100000000, TO_STR_TIME_RES_T_DSECS);
1628 break;
1629 case WTAP_TSPREC_CSEC:
1630 display_epoch_time(buf, COL_MAX_LEN,
1631 fd->abs_ts.secs, fd->abs_ts.nsecs / 10000000, TO_STR_TIME_RES_T_CSECS);
1632 break;
1633 case WTAP_TSPREC_MSEC:
1634 display_epoch_time(buf, COL_MAX_LEN,
1635 fd->abs_ts.secs, fd->abs_ts.nsecs / 1000000, TO_STR_TIME_RES_T_MSECS);
1636 break;
1637 case WTAP_TSPREC_USEC:
1638 display_epoch_time(buf, COL_MAX_LEN,
1639 fd->abs_ts.secs, fd->abs_ts.nsecs / 1000, TO_STR_TIME_RES_T_USECS);
1640 break;
1641 case WTAP_TSPREC_NSEC:
1642 display_epoch_time(buf, COL_MAX_LEN,
1643 fd->abs_ts.secs, fd->abs_ts.nsecs, TO_STR_TIME_RES_T_NSECS);
1644 break;
1645 default:
1646 ws_assert_not_reached();
1647 }
1648 return TRUE;
1649 }
1650
1651 static void
col_set_epoch_time(const frame_data * fd,column_info * cinfo,const int col)1652 col_set_epoch_time(const frame_data *fd, column_info *cinfo, const int col)
1653 {
1654 if (set_epoch_time(fd, cinfo->columns[col].col_buf)) {
1655 cinfo->col_expr.col_expr[col] = "frame.time_delta";
1656 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],cinfo->columns[col].col_buf,COL_MAX_LEN);
1657 }
1658 cinfo->columns[col].col_data = cinfo->columns[col].col_buf;
1659 }
1660
1661 void
set_fd_time(const epan_t * epan,frame_data * fd,gchar * buf)1662 set_fd_time(const epan_t *epan, frame_data *fd, gchar *buf)
1663 {
1664
1665 switch (timestamp_get_type()) {
1666 case TS_ABSOLUTE:
1667 set_abs_time(fd, buf, col_decimal_point, TRUE);
1668 break;
1669
1670 case TS_ABSOLUTE_WITH_YMD:
1671 set_abs_ymd_time(fd, buf, col_decimal_point, TRUE);
1672 break;
1673
1674 case TS_ABSOLUTE_WITH_YDOY:
1675 set_abs_ydoy_time(fd, buf, col_decimal_point, TRUE);
1676 break;
1677
1678 case TS_RELATIVE:
1679 if (fd->has_ts) {
1680 nstime_t del_rel_ts;
1681
1682 frame_delta_abs_time(epan, fd, fd->frame_ref_num, &del_rel_ts);
1683
1684 switch (timestamp_get_seconds_type()) {
1685 case TS_SECONDS_DEFAULT:
1686 set_time_seconds(fd, &del_rel_ts, buf);
1687 break;
1688 case TS_SECONDS_HOUR_MIN_SEC:
1689 set_time_seconds(fd, &del_rel_ts, buf);
1690 break;
1691 default:
1692 ws_assert_not_reached();
1693 }
1694 } else {
1695 buf[0] = '\0';
1696 }
1697 break;
1698
1699 case TS_DELTA:
1700 if (fd->has_ts) {
1701 nstime_t del_cap_ts;
1702
1703 frame_delta_abs_time(epan, fd, fd->num - 1, &del_cap_ts);
1704
1705 switch (timestamp_get_seconds_type()) {
1706 case TS_SECONDS_DEFAULT:
1707 set_time_seconds(fd, &del_cap_ts, buf);
1708 break;
1709 case TS_SECONDS_HOUR_MIN_SEC:
1710 set_time_hour_min_sec(fd, &del_cap_ts, buf, col_decimal_point);
1711 break;
1712 default:
1713 ws_assert_not_reached();
1714 }
1715 } else {
1716 buf[0] = '\0';
1717 }
1718 break;
1719
1720 case TS_DELTA_DIS:
1721 if (fd->has_ts) {
1722 nstime_t del_dis_ts;
1723
1724 frame_delta_abs_time(epan, fd, fd->prev_dis_num, &del_dis_ts);
1725
1726 switch (timestamp_get_seconds_type()) {
1727 case TS_SECONDS_DEFAULT:
1728 set_time_seconds(fd, &del_dis_ts, buf);
1729 break;
1730 case TS_SECONDS_HOUR_MIN_SEC:
1731 set_time_hour_min_sec(fd, &del_dis_ts, buf, col_decimal_point);
1732 break;
1733 default:
1734 ws_assert_not_reached();
1735 }
1736 } else {
1737 buf[0] = '\0';
1738 }
1739 break;
1740
1741 case TS_EPOCH:
1742 set_epoch_time(fd, buf);
1743 break;
1744
1745 case TS_UTC:
1746 set_abs_time(fd, buf, col_decimal_point, FALSE);
1747 break;
1748
1749 case TS_UTC_WITH_YMD:
1750 set_abs_ymd_time(fd, buf, col_decimal_point, FALSE);
1751 break;
1752
1753 case TS_UTC_WITH_YDOY:
1754 set_abs_ydoy_time(fd, buf, col_decimal_point, FALSE);
1755 break;
1756
1757 case TS_NOT_SET:
1758 /* code is missing for this case, but I don't know which [jmayer20051219] */
1759 ws_assert_not_reached();
1760 break;
1761 }
1762 }
1763
1764 static void
col_set_cls_time(const frame_data * fd,column_info * cinfo,const gint col)1765 col_set_cls_time(const frame_data *fd, column_info *cinfo, const gint col)
1766 {
1767 switch (timestamp_get_type()) {
1768 case TS_ABSOLUTE:
1769 col_set_abs_time(fd, cinfo, col);
1770 break;
1771
1772 case TS_ABSOLUTE_WITH_YMD:
1773 col_set_abs_ymd_time(fd, cinfo, col);
1774 break;
1775
1776 case TS_ABSOLUTE_WITH_YDOY:
1777 col_set_abs_ydoy_time(fd, cinfo, col);
1778 break;
1779
1780 case TS_RELATIVE:
1781 col_set_rel_time(fd, cinfo, col);
1782 break;
1783
1784 case TS_DELTA:
1785 col_set_delta_time(fd, cinfo, col);
1786 break;
1787
1788 case TS_DELTA_DIS:
1789 col_set_delta_time_dis(fd, cinfo, col);
1790 break;
1791
1792 case TS_EPOCH:
1793 col_set_epoch_time(fd, cinfo, col);
1794 break;
1795
1796 case TS_UTC:
1797 col_set_utc_time(fd, cinfo, col);
1798 break;
1799
1800 case TS_UTC_WITH_YMD:
1801 col_set_utc_ymd_time(fd, cinfo, col);
1802 break;
1803
1804 case TS_UTC_WITH_YDOY:
1805 col_set_utc_ydoy_time(fd, cinfo, col);
1806 break;
1807
1808 case TS_NOT_SET:
1809 /* code is missing for this case, but I don't know which [jmayer20051219] */
1810 ws_assert_not_reached();
1811 break;
1812 }
1813 }
1814
1815 /* Set the format of the variable time format. */
1816 static void
col_set_fmt_time(const frame_data * fd,column_info * cinfo,const gint fmt,const gint col)1817 col_set_fmt_time(const frame_data *fd, column_info *cinfo, const gint fmt, const gint col)
1818 {
1819 COL_CHECK_REF_TIME(fd, cinfo->columns[col].col_buf);
1820
1821 switch (fmt) {
1822 case COL_CLS_TIME:
1823 col_set_cls_time(fd, cinfo, col);
1824 break;
1825
1826 case COL_ABS_TIME:
1827 col_set_abs_time(fd, cinfo, col);
1828 break;
1829
1830 case COL_ABS_YMD_TIME:
1831 col_set_abs_ymd_time(fd, cinfo, col);
1832 break;
1833
1834 case COL_ABS_YDOY_TIME:
1835 col_set_abs_ydoy_time(fd, cinfo, col);
1836 break;
1837
1838 case COL_REL_TIME:
1839 col_set_rel_time(fd, cinfo, col);
1840 break;
1841
1842 case COL_DELTA_TIME:
1843 col_set_delta_time(fd, cinfo, col);
1844 break;
1845
1846 case COL_DELTA_TIME_DIS:
1847 col_set_delta_time_dis(fd, cinfo, col);
1848 break;
1849
1850 case COL_UTC_TIME:
1851 col_set_utc_time(fd, cinfo, col);
1852 break;
1853
1854 case COL_UTC_YMD_TIME:
1855 col_set_utc_ymd_time(fd, cinfo, col);
1856 break;
1857
1858 case COL_UTC_YDOY_TIME:
1859 col_set_utc_ydoy_time(fd, cinfo, col);
1860 break;
1861
1862 default:
1863 ws_assert_not_reached();
1864 break;
1865 }
1866 }
1867
1868 /* --------------------------- */
1869 /* Set the given (relative) time to a column element.
1870 *
1871 * Used by dissectors to set the time in a column
1872 *
1873 * @param cinfo the current packet row
1874 * @param el the column to use, e.g. COL_INFO
1875 * @param ts the time to set in the column
1876 * @param fieldname the fieldname to use for creating a filter (when
1877 * applying/preparing/copying as filter)
1878 */
1879 void
col_set_time(column_info * cinfo,const gint el,const nstime_t * ts,const char * fieldname)1880 col_set_time(column_info *cinfo, const gint el, const nstime_t *ts, const char *fieldname)
1881 {
1882 int col;
1883 col_item_t* col_item;
1884
1885 if (!CHECK_COL(cinfo, el))
1886 return;
1887
1888 /** @todo TODO: We don't respect fd->ref_time (no way to access 'fd')
1889 COL_CHECK_REF_TIME(fd, buf);
1890 */
1891
1892 for (col = cinfo->col_first[el]; col <= cinfo->col_last[el]; col++) {
1893 col_item = &cinfo->columns[col];
1894 if (col_item->fmt_matx[el]) {
1895 switch (timestamp_get_precision()) {
1896 case TS_PREC_FIXED_SEC:
1897 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1898 (gint64) ts->secs, ts->nsecs / 1000000000, TO_STR_TIME_RES_T_SECS);
1899 break;
1900 case TS_PREC_FIXED_DSEC:
1901 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1902 (gint64) ts->secs, ts->nsecs / 100000000, TO_STR_TIME_RES_T_DSECS);
1903 break;
1904 case TS_PREC_FIXED_CSEC:
1905 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1906 (gint64) ts->secs, ts->nsecs / 10000000, TO_STR_TIME_RES_T_CSECS);
1907 break;
1908 case TS_PREC_FIXED_MSEC:
1909 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1910 (gint64) ts->secs, ts->nsecs / 1000000, TO_STR_TIME_RES_T_MSECS);
1911 break;
1912 case TS_PREC_FIXED_USEC:
1913 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1914 (gint64) ts->secs, ts->nsecs / 1000, TO_STR_TIME_RES_T_USECS);
1915 break;
1916 case TS_PREC_FIXED_NSEC:
1917 case TS_PREC_AUTO: /* default to maximum */
1918 display_signed_time(col_item->col_buf, COL_MAX_LEN,
1919 (gint64) ts->secs, ts->nsecs, TO_STR_TIME_RES_T_NSECS);
1920 break;
1921 default:
1922 ws_assert_not_reached();
1923 }
1924 col_item->col_data = col_item->col_buf;
1925 cinfo->col_expr.col_expr[col] = fieldname;
1926 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col],col_item->col_buf,COL_MAX_LEN);
1927 }
1928 }
1929 }
1930
1931 static void
col_set_addr(packet_info * pinfo,const int col,const address * addr,const gboolean is_src,const gboolean fill_col_exprs,const gboolean res)1932 col_set_addr(packet_info *pinfo, const int col, const address *addr, const gboolean is_src,
1933 const gboolean fill_col_exprs, const gboolean res)
1934 {
1935 const char *name;
1936 col_item_t* col_item = &pinfo->cinfo->columns[col];
1937
1938 if (addr->type == AT_NONE) {
1939 /* No address, nothing to do */
1940 return;
1941 }
1942
1943 if (res && (name = address_to_name(addr)) != NULL)
1944 col_item->col_data = name;
1945 else {
1946 col_item->col_data = col_item->col_buf;
1947 address_to_str_buf(addr, col_item->col_buf, COL_MAX_LEN);
1948 }
1949
1950 if (!fill_col_exprs)
1951 return;
1952
1953 pinfo->cinfo->col_expr.col_expr[col] = address_type_column_filter_string(addr, is_src);
1954 /* For address types that have a filter, create a string */
1955 if (strlen(pinfo->cinfo->col_expr.col_expr[col]) > 0)
1956 address_to_str_buf(addr, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1957 }
1958
1959 /* ------------------------ */
1960 static void
col_set_port(packet_info * pinfo,const int col,const gboolean is_res,const gboolean is_src,const gboolean fill_col_exprs _U_)1961 col_set_port(packet_info *pinfo, const int col, const gboolean is_res, const gboolean is_src, const gboolean fill_col_exprs _U_)
1962 {
1963 guint32 port;
1964 col_item_t* col_item = &pinfo->cinfo->columns[col];
1965
1966 if (is_src)
1967 port = pinfo->srcport;
1968 else
1969 port = pinfo->destport;
1970
1971 /* TODO: Use fill_col_exprs */
1972
1973 switch (pinfo->ptype) {
1974 case PT_SCTP:
1975 if (is_res)
1976 (void) g_strlcpy(col_item->col_buf, sctp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1977 else
1978 guint32_to_str_buf(port, col_item->col_buf, COL_MAX_LEN);
1979 break;
1980
1981 case PT_TCP:
1982 guint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1983 if (is_res)
1984 (void) g_strlcpy(col_item->col_buf, tcp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1985 else
1986 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1987 if (is_src)
1988 pinfo->cinfo->col_expr.col_expr[col] = "tcp.srcport";
1989 else
1990 pinfo->cinfo->col_expr.col_expr[col] = "tcp.dstport";
1991 break;
1992
1993 case PT_UDP:
1994 guint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1995 if (is_res)
1996 (void) g_strlcpy(col_item->col_buf, udp_port_to_display(pinfo->pool, port), COL_MAX_LEN);
1997 else
1998 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
1999 if (is_src)
2000 pinfo->cinfo->col_expr.col_expr[col] = "udp.srcport";
2001 else
2002 pinfo->cinfo->col_expr.col_expr[col] = "udp.dstport";
2003 break;
2004
2005 case PT_DDP:
2006 if (is_src)
2007 pinfo->cinfo->col_expr.col_expr[col] = "ddp.src_socket";
2008 else
2009 pinfo->cinfo->col_expr.col_expr[col] = "ddp.dst_socket";
2010 guint32_to_str_buf(port, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
2011 (void) g_strlcpy(col_item->col_buf, pinfo->cinfo->col_expr.col_expr_val[col], COL_MAX_LEN);
2012 break;
2013
2014 case PT_IPX:
2015 /* XXX - resolve IPX socket numbers */
2016 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%04x", port);
2017 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
2018 if (is_src)
2019 pinfo->cinfo->col_expr.col_expr[col] = "ipx.src.socket";
2020 else
2021 pinfo->cinfo->col_expr.col_expr[col] = "ipx.dst.socket";
2022 break;
2023
2024 case PT_IDP:
2025 /* XXX - resolve IDP socket numbers */
2026 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%04x", port);
2027 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
2028 if (is_src)
2029 pinfo->cinfo->col_expr.col_expr[col] = "idp.src.socket";
2030 else
2031 pinfo->cinfo->col_expr.col_expr[col] = "idp.dst.socket";
2032 break;
2033
2034 case PT_USB:
2035 /* XXX - resolve USB endpoint numbers */
2036 snprintf(col_item->col_buf, COL_MAX_LEN, "0x%08x", port);
2037 (void) g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], col_item->col_buf,COL_MAX_LEN);
2038 if (is_src)
2039 pinfo->cinfo->col_expr.col_expr[col] = "usb.src.endpoint";
2040 else
2041 pinfo->cinfo->col_expr.col_expr[col] = "usb.dst.endpoint";
2042 break;
2043
2044 default:
2045 break;
2046 }
2047 col_item->col_data = col_item->col_buf;
2048 }
2049
2050 gboolean
col_based_on_frame_data(column_info * cinfo,const gint col)2051 col_based_on_frame_data(column_info *cinfo, const gint col)
2052 {
2053 ws_assert(cinfo);
2054 ws_assert(col < cinfo->num_cols);
2055
2056 switch (cinfo->columns[col].col_fmt) {
2057 case COL_NUMBER:
2058 case COL_CLS_TIME:
2059 case COL_ABS_TIME:
2060 case COL_ABS_YMD_TIME:
2061 case COL_ABS_YDOY_TIME:
2062 case COL_UTC_TIME:
2063 case COL_UTC_YMD_TIME:
2064 case COL_UTC_YDOY_TIME:
2065 case COL_REL_TIME:
2066 case COL_DELTA_TIME:
2067 case COL_DELTA_TIME_DIS:
2068 case COL_PACKET_LENGTH:
2069 case COL_CUMULATIVE_BYTES:
2070 return TRUE;
2071
2072 default:
2073 return FALSE;
2074 }
2075 }
2076
2077 void
col_fill_in_frame_data(const frame_data * fd,column_info * cinfo,const gint col,const gboolean fill_col_exprs)2078 col_fill_in_frame_data(const frame_data *fd, column_info *cinfo, const gint col, const gboolean fill_col_exprs)
2079 {
2080 col_item_t* col_item = &cinfo->columns[col];
2081
2082 switch (col_item->col_fmt) {
2083 case COL_NUMBER:
2084 guint32_to_str_buf(fd->num, col_item->col_buf, COL_MAX_LEN);
2085 col_item->col_data = col_item->col_buf;
2086 break;
2087
2088 case COL_CLS_TIME:
2089 case COL_ABS_TIME:
2090 case COL_ABS_YMD_TIME:
2091 case COL_ABS_YDOY_TIME:
2092 case COL_UTC_TIME:
2093 case COL_UTC_YMD_TIME:
2094 case COL_UTC_YDOY_TIME:
2095 case COL_REL_TIME:
2096 case COL_DELTA_TIME:
2097 case COL_DELTA_TIME_DIS:
2098 /* TODO: Pass on fill_col_exprs */
2099 col_set_fmt_time(fd, cinfo, col_item->col_fmt, col);
2100 break;
2101
2102 case COL_PACKET_LENGTH:
2103 guint32_to_str_buf(fd->pkt_len, col_item->col_buf, COL_MAX_LEN);
2104 col_item->col_data = col_item->col_buf;
2105 break;
2106
2107 case COL_CUMULATIVE_BYTES:
2108 guint32_to_str_buf(fd->cum_bytes, col_item->col_buf, COL_MAX_LEN);
2109 col_item->col_data = col_item->col_buf;
2110 break;
2111
2112 default:
2113 break;
2114 }
2115
2116 if (!fill_col_exprs)
2117 return;
2118
2119 switch (col_item->col_fmt) {
2120 case COL_NUMBER:
2121 cinfo->col_expr.col_expr[col] = "frame.number";
2122 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col], col_item->col_buf, COL_MAX_LEN);
2123 break;
2124
2125 case COL_CLS_TIME:
2126 case COL_ABS_TIME:
2127 case COL_ABS_YMD_TIME:
2128 case COL_ABS_YDOY_TIME:
2129 case COL_UTC_TIME:
2130 case COL_UTC_YMD_TIME:
2131 case COL_UTC_YDOY_TIME:
2132 case COL_REL_TIME:
2133 case COL_DELTA_TIME:
2134 case COL_DELTA_TIME_DIS:
2135 /* Already handled above */
2136 break;
2137
2138 case COL_PACKET_LENGTH:
2139 cinfo->col_expr.col_expr[col] = "frame.len";
2140 (void) g_strlcpy(cinfo->col_expr.col_expr_val[col], col_item->col_buf, COL_MAX_LEN);
2141 break;
2142
2143 case COL_CUMULATIVE_BYTES:
2144 break;
2145
2146 default:
2147 break;
2148 }
2149 }
2150
2151 void
col_fill_in(packet_info * pinfo,const gboolean fill_col_exprs,const gboolean fill_fd_colums)2152 col_fill_in(packet_info *pinfo, const gboolean fill_col_exprs, const gboolean fill_fd_colums)
2153 {
2154 int i;
2155 col_item_t* col_item;
2156
2157 if (!pinfo->cinfo)
2158 return;
2159
2160 for (i = 0; i < pinfo->cinfo->num_cols; i++) {
2161 col_item = &pinfo->cinfo->columns[i];
2162 if (col_based_on_frame_data(pinfo->cinfo, i)) {
2163 if (fill_fd_colums)
2164 col_fill_in_frame_data(pinfo->fd, pinfo->cinfo, i, fill_col_exprs);
2165 } else {
2166 switch (col_item->col_fmt) {
2167 case COL_DEF_SRC:
2168 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
2169 col_set_addr(pinfo, i, &pinfo->src, TRUE, fill_col_exprs, TRUE);
2170 break;
2171
2172 case COL_UNRES_SRC:
2173 col_set_addr(pinfo, i, &pinfo->src, TRUE, fill_col_exprs, FALSE);
2174 break;
2175
2176 case COL_DEF_DL_SRC:
2177 case COL_RES_DL_SRC:
2178 col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, fill_col_exprs, TRUE);
2179 break;
2180
2181 case COL_UNRES_DL_SRC:
2182 col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, fill_col_exprs, FALSE);
2183 break;
2184
2185 case COL_DEF_NET_SRC:
2186 case COL_RES_NET_SRC:
2187 col_set_addr(pinfo, i, &pinfo->net_src, TRUE, fill_col_exprs, TRUE);
2188 break;
2189
2190 case COL_UNRES_NET_SRC:
2191 col_set_addr(pinfo, i, &pinfo->net_src, TRUE, fill_col_exprs, FALSE);
2192 break;
2193
2194 case COL_DEF_DST:
2195 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
2196 col_set_addr(pinfo, i, &pinfo->dst, FALSE, fill_col_exprs, TRUE);
2197 break;
2198
2199 case COL_UNRES_DST:
2200 col_set_addr(pinfo, i, &pinfo->dst, FALSE, fill_col_exprs, FALSE);
2201 break;
2202
2203 case COL_DEF_DL_DST:
2204 case COL_RES_DL_DST:
2205 col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, fill_col_exprs, TRUE);
2206 break;
2207
2208 case COL_UNRES_DL_DST:
2209 col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, fill_col_exprs, FALSE);
2210 break;
2211
2212 case COL_DEF_NET_DST:
2213 case COL_RES_NET_DST:
2214 col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, fill_col_exprs, TRUE);
2215 break;
2216
2217 case COL_UNRES_NET_DST:
2218 col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, fill_col_exprs, FALSE);
2219 break;
2220
2221 case COL_DEF_SRC_PORT:
2222 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
2223 col_set_port(pinfo, i, TRUE, TRUE, fill_col_exprs);
2224 break;
2225
2226 case COL_UNRES_SRC_PORT:
2227 col_set_port(pinfo, i, FALSE, TRUE, fill_col_exprs);
2228 break;
2229
2230 case COL_DEF_DST_PORT:
2231 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
2232 col_set_port(pinfo, i, TRUE, FALSE, fill_col_exprs);
2233 break;
2234
2235 case COL_UNRES_DST_PORT:
2236 col_set_port(pinfo, i, FALSE, FALSE, fill_col_exprs);
2237 break;
2238
2239 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
2240 ws_assert_not_reached();
2241 break;
2242 default:
2243 if (col_item->col_fmt >= NUM_COL_FMTS) {
2244 ws_assert_not_reached();
2245 }
2246 /*
2247 * Formatting handled by col_custom_set_edt() (COL_CUSTOM), expert.c
2248 * (COL_EXPERT), or individual dissectors.
2249 */
2250 break;
2251 }
2252 }
2253 }
2254 }
2255
2256 /*
2257 * Fill in columns if we got an error reading the packet.
2258 * We set most columns to "???", fill in columns that don't need data read
2259 * from the file, and set the Info column to an error message.
2260 */
2261 void
col_fill_in_error(column_info * cinfo,frame_data * fdata,const gboolean fill_col_exprs,const gboolean fill_fd_colums)2262 col_fill_in_error(column_info *cinfo, frame_data *fdata, const gboolean fill_col_exprs, const gboolean fill_fd_colums)
2263 {
2264 int i;
2265 col_item_t* col_item;
2266
2267 if (!cinfo)
2268 return;
2269
2270 for (i = 0; i < cinfo->num_cols; i++) {
2271 col_item = &cinfo->columns[i];
2272 if (col_based_on_frame_data(cinfo, i)) {
2273 if (fill_fd_colums)
2274 col_fill_in_frame_data(fdata, cinfo, i, fill_col_exprs);
2275 } else if (col_item->col_fmt == COL_INFO) {
2276 /* XXX - say more than this */
2277 col_item->col_data = "Read error";
2278 } else {
2279 if (col_item->col_fmt >= NUM_COL_FMTS) {
2280 ws_assert_not_reached();
2281 }
2282 /*
2283 * No dissection was done, and these columns are set as the
2284 * result of the dissection, so....
2285 */
2286 col_item->col_data = "???";
2287 break;
2288 }
2289 }
2290 }
2291
col_data_changed(void)2292 gboolean col_data_changed(void) {
2293 gboolean cur_cdc = col_data_changed_;
2294 col_data_changed_ = FALSE;
2295 return cur_cdc;
2296 }
2297 /*
2298 * Editor modelines
2299 *
2300 * Local Variables:
2301 * c-basic-offset: 2
2302 * tab-width: 8
2303 * indent-tabs-mode: nil
2304 * End:
2305 *
2306 * ex: set shiftwidth=2 tabstop=8 expandtab:
2307 * :indentSize=2:tabSize=8:noTabs=true:
2308 */
2309