Coverage Report

Created: 2025-02-15 06:25

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