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