timestamp display precision:
[obnox/wireshark/wip.git] / epan / column-utils.c
1 /* column-utils.c
2  * Routines for column utilities.
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <time.h>
31
32 #include "column-utils.h"
33 #include "timestamp.h"
34 #include "sna-utils.h"
35 #include "atalk-utils.h"
36 #include "to_str.h"
37 #include "packet_info.h"
38 #include "pint.h"
39 #include "addr_resolv.h"
40 #include "ipv6-utils.h"
41 #include "osi-utils.h"
42 #include "value_string.h"
43
44 /* Allocate all the data structures for constructing column data, given
45    the number of columns. */
46 void
47 col_setup(column_info *col_info, gint num_cols)
48 {
49   int i;
50
51   col_info->num_cols    = num_cols;
52   col_info->col_fmt     = (gint *) g_malloc(sizeof(gint) * num_cols);
53   col_info->fmt_matx    = (gboolean **) g_malloc(sizeof(gboolean *) * num_cols);
54   col_info->col_first   = (int *) g_malloc(sizeof(int) * (NUM_COL_FMTS));
55   col_info->col_last    = (int *) g_malloc(sizeof(int) * (NUM_COL_FMTS));
56   col_info->col_title   = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
57   col_info->col_data    = (const gchar **) g_malloc(sizeof(gchar *) * num_cols);
58   col_info->col_buf     = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
59   col_info->col_fence   = (int *) g_malloc(sizeof(int) * num_cols);
60   col_info->col_expr    = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
61   col_info->col_expr_val = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
62
63   for (i = 0; i < NUM_COL_FMTS; i++) {
64     col_info->col_first[i] = -1;
65     col_info->col_last[i] = -1;
66   }
67 }
68
69 /* Initialize the data structures for constructing column data. */
70 void
71 col_init(column_info *cinfo)
72 {
73   int i;
74
75   for (i = 0; i < cinfo->num_cols; i++) {
76     cinfo->col_buf[i][0] = '\0';
77     cinfo->col_data[i] = cinfo->col_buf[i];
78     cinfo->col_fence[i] = 0;
79     cinfo->col_expr[i][0] = '\0';
80     cinfo->col_expr_val[i][0] = '\0';
81   }
82   cinfo->writable = TRUE;
83 }
84
85 gboolean
86 col_get_writable(column_info *cinfo)
87 {
88         return (cinfo ? cinfo->writable : FALSE);
89 }
90
91 void
92 col_set_writable(column_info *cinfo, gboolean writable)
93 {
94         if (cinfo)
95                 cinfo->writable = writable;
96 }
97
98 /* Checks to see if a particular packet information element is needed for
99    the packet list */
100 gint
101 check_col(column_info *cinfo, gint el) {
102
103   if (cinfo && cinfo->writable) {
104     /* We are constructing columns, and they're writable */
105     if (cinfo->col_first[el] >= 0) {
106       /* There is at least one column in that format */
107       return TRUE;
108     }
109   }
110   return FALSE;
111 }
112
113 /* Sets the fence for a column to be at the end of the column. */
114 void
115 col_set_fence(column_info *cinfo, gint el)
116 {
117   int i;
118
119   if (cinfo && cinfo->writable) {
120     /* We are constructing columns, and they're writable */
121     if (cinfo->col_first[el] >= 0) {
122       /* There is at least one column in that format */
123       for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
124         if (cinfo->fmt_matx[i][el]) {
125           cinfo->col_fence[i] = strlen(cinfo->col_data[i]);
126         }
127       }
128     }
129   }
130 }
131
132 /* Use this to clear out a column, especially if you're going to be
133    appending to it later; at least on some platforms, it's more
134    efficient than using "col_add_str()" with a null string, and
135    more efficient than "col_set_str()" with a null string if you
136    later append to it, as the later append will cause a string
137    copy to be done. */
138 void
139 col_clear(column_info *cinfo, gint el)
140 {
141   int    i;
142   int    fence;
143
144   g_assert(cinfo->col_first[el] >= 0);
145   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
146     if (cinfo->fmt_matx[i][el]) {
147       /*
148        * At this point, either
149        *
150        *   1) col_data[i] is equal to col_buf[i], in which case we
151        *      don't have to worry about copying col_data[i] to
152        *      col_buf[i];
153        *
154        *   2) col_data[i] isn't equal to col_buf[i], in which case
155        *      the only thing that's been done to the column is
156        *      "col_set_str()" calls and possibly "col_set_fence()"
157        *      calls, in which case the fence is either unset and
158        *      at the beginning of the string or set and at the end
159        *      of the string - if it's at the beginning, we're just
160        *      going to clear the column, and if it's at the end,
161        *      we don't do anything.
162        */
163       fence = cinfo->col_fence[i];
164       if (fence == 0 || cinfo->col_buf[i] == cinfo->col_data[i]) {
165         /*
166          * The fence isn't at the end of the column, or the column wasn't
167          * last set with "col_set_str()", so clear the column out.
168          */
169         cinfo->col_buf[i][fence] = '\0';
170         cinfo->col_data[i] = cinfo->col_buf[i];
171       }
172       cinfo->col_expr[i][0] = '\0';
173       cinfo->col_expr_val[i][0] = '\0';
174     }
175   }
176 }
177
178 #define COL_CHECK_APPEND(cinfo, i, max_len) \
179   if (cinfo->col_data[i] != cinfo->col_buf[i]) {                \
180     /* This was set with "col_set_str()"; copy the string they  \
181        set it to into the buffer, so we can append to it. */    \
182     strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);    \
183     cinfo->col_buf[i][max_len - 1] = '\0';                      \
184     cinfo->col_data[i] = cinfo->col_buf[i];                     \
185   }
186
187 /* Use this if "str" points to something that will stay around (and thus
188    needn't be copied). */
189 void
190 col_set_str(column_info *cinfo, gint el, const gchar* str)
191 {
192   int i;
193   int fence;
194   size_t max_len;
195
196   if (el == COL_INFO)
197         max_len = COL_MAX_INFO_LEN;
198   else
199         max_len = COL_MAX_LEN;
200
201   g_assert(cinfo->col_first[el] >= 0);
202   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
203     if (cinfo->fmt_matx[i][el]) {
204       fence = cinfo->col_fence[i];
205       if (fence != 0) {
206         /*
207          * We will append the string after the fence.
208          * First arrange that we can append, if necessary.
209          */
210         COL_CHECK_APPEND(cinfo, i, max_len);
211
212         strncpy(&cinfo->col_buf[i][fence], str, max_len - fence);
213         cinfo->col_buf[i][max_len - 1] = 0;
214       } else {
215         /*
216          * There's no fence, so we can just set the column to point
217          * to the string.
218          */
219         cinfo->col_data[i] = str;
220       }
221     }
222   }
223 }
224
225 /* Adds a vararg list to a packet info string. */
226 void
227 col_add_fstr(column_info *cinfo, gint el, const gchar *format, ...) {
228   va_list ap;
229   int     i;
230   int     fence;
231   size_t  max_len;
232
233   g_assert(cinfo->col_first[el] >= 0);
234   if (el == COL_INFO)
235         max_len = COL_MAX_INFO_LEN;
236   else
237         max_len = COL_MAX_LEN;
238
239   va_start(ap, format);
240   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
241     if (cinfo->fmt_matx[i][el]) {
242       fence = cinfo->col_fence[i];
243       if (fence != 0) {
244         /*
245          * We will append the string after the fence.
246          * First arrange that we can append, if necessary.
247          */
248         COL_CHECK_APPEND(cinfo, i, max_len);
249       } else {
250         /*
251          * There's no fence, so we can just write to the string.
252          */
253         cinfo->col_data[i] = cinfo->col_buf[i];
254       }
255       g_vsnprintf(&cinfo->col_buf[i][fence], max_len - fence, format, ap);
256       cinfo->col_buf[i][max_len - 1] = '\0';
257     }
258   }
259   va_end(ap);
260 }
261
262 static void
263 col_do_append_sep_va_fstr(column_info *cinfo, gint el, const gchar *separator,
264                           const gchar *format, va_list ap)
265 {
266   int     i;
267   size_t  len, max_len, sep_len;
268
269   g_assert(cinfo->col_first[el] >= 0);
270   if (el == COL_INFO)
271         max_len = COL_MAX_INFO_LEN;
272   else
273         max_len = COL_MAX_LEN;
274
275   if (separator == NULL)
276     sep_len = 0;
277   else
278     sep_len = strlen(separator);
279   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
280     if (cinfo->fmt_matx[i][el]) {
281       /*
282        * First arrange that we can append, if necessary.
283        */
284       COL_CHECK_APPEND(cinfo, i, max_len);
285
286       len = strlen(cinfo->col_buf[i]);
287
288       /*
289        * If we have a separator, append it if the column isn't empty.
290        */
291       if (separator != NULL) {
292         if (len != 0) {
293           strncat(cinfo->col_buf[i], separator, max_len - len);
294           len += sep_len;
295         }
296       }
297       g_vsnprintf(&cinfo->col_buf[i][len], max_len - len, format, ap);
298       cinfo->col_buf[i][max_len-1] = 0;
299     }
300   }
301 }
302
303 /* Appends a vararg list to a packet info string. */
304 void
305 col_append_fstr(column_info *cinfo, gint el, const gchar *format, ...)
306 {
307   va_list ap;
308
309   va_start(ap, format);
310   col_do_append_sep_va_fstr(cinfo, el, NULL, format, ap);
311   va_end(ap);
312 }
313
314 /* Appends a vararg list to a packet info string.
315  * Prefixes it with the given separator if the column is not empty. */
316 void
317 col_append_sep_fstr(column_info *cinfo, gint el, const gchar *separator,
318                 const gchar *format, ...)
319 {
320   va_list ap;
321
322   if (separator == NULL)
323     separator = ", ";    /* default */
324   va_start(ap, format);
325   col_do_append_sep_va_fstr(cinfo, el, separator, format, ap);
326   va_end(ap);
327 }
328
329
330
331 /* Prepends a vararg list to a packet info string. */
332 #define COL_BUF_MAX_LEN (((COL_MAX_INFO_LEN) > (COL_MAX_LEN)) ? \
333         (COL_MAX_INFO_LEN) : (COL_MAX_LEN))
334 void
335 col_prepend_fstr(column_info *cinfo, gint el, const gchar *format, ...)
336 {
337   va_list     ap;
338   int         i;
339   char        orig_buf[COL_BUF_MAX_LEN];
340   const char *orig;
341   size_t      max_len;
342
343   g_assert(cinfo->col_first[el] >= 0);
344   if (el == COL_INFO)
345         max_len = COL_MAX_INFO_LEN;
346   else
347         max_len = COL_MAX_LEN;
348
349   va_start(ap, format);
350   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
351     if (cinfo->fmt_matx[i][el]) {
352       if (cinfo->col_data[i] != cinfo->col_buf[i]) {
353         /* This was set with "col_set_str()"; which is effectively const */
354         orig = cinfo->col_data[i];
355       } else {
356         strncpy(orig_buf, cinfo->col_buf[i], max_len);
357         orig_buf[max_len - 1] = '\0';
358         orig = orig_buf;
359       }
360       g_vsnprintf(cinfo->col_buf[i], max_len, format, ap);
361       cinfo->col_buf[i][max_len - 1] = '\0';
362
363       /*
364        * Move the fence, unless it's at the beginning of the string.
365        */
366       if (cinfo->col_fence[i] > 0)
367         cinfo->col_fence[i] += strlen(cinfo->col_buf[i]);
368
369       strncat(cinfo->col_buf[i], orig, max_len);
370       cinfo->col_buf[i][max_len - 1] = '\0';
371       cinfo->col_data[i] = cinfo->col_buf[i];
372     }
373   }
374   va_end(ap);
375 }
376
377 /* Use this if "str" points to something that won't stay around (and
378    must thus be copied). */
379 void
380 col_add_str(column_info *cinfo, gint el, const gchar* str)
381 {
382   int    i;
383   int    fence;
384   size_t max_len;
385
386   g_assert(cinfo->col_first[el] >= 0);
387   if (el == COL_INFO)
388         max_len = COL_MAX_INFO_LEN;
389   else
390         max_len = COL_MAX_LEN;
391
392   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
393     if (cinfo->fmt_matx[i][el]) {
394       fence = cinfo->col_fence[i];
395       if (fence != 0) {
396         /*
397          * We will append the string after the fence.
398          * First arrange that we can append, if necessary.
399          */
400         COL_CHECK_APPEND(cinfo, i, max_len);
401       } else {
402         /*
403          * There's no fence, so we can just write to the string.
404          */
405         cinfo->col_data[i] = cinfo->col_buf[i];
406       }
407       strncpy(&cinfo->col_buf[i][fence], str, max_len - fence);
408       cinfo->col_buf[i][max_len - 1] = 0;
409     }
410   }
411 }
412
413 static void
414 col_do_append_str(column_info *cinfo, gint el, const gchar* separator,
415     const gchar* str)
416 {
417   int    i;
418   size_t len, max_len, sep_len;
419
420   g_assert(cinfo->col_first[el] >= 0);
421   if (el == COL_INFO)
422         max_len = COL_MAX_INFO_LEN;
423   else
424         max_len = COL_MAX_LEN;
425
426   if (separator == NULL)
427     sep_len = 0;
428   else
429     sep_len = strlen(separator);
430
431   for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) {
432     if (cinfo->fmt_matx[i][el]) {
433       /*
434        * First arrange that we can append, if necessary.
435        */
436       COL_CHECK_APPEND(cinfo, i, max_len);
437
438       len = strlen(cinfo->col_buf[i]);
439
440       /*
441        * If we have a separator, append it if the column isn't empty.
442        */
443       if (separator != NULL) {
444         if (len != 0) {
445           strncat(cinfo->col_buf[i], separator, max_len - len);
446           len += sep_len;
447         }
448       }
449       strncat(cinfo->col_buf[i], str, max_len - len);
450       cinfo->col_buf[i][max_len - 1] = 0;
451     }
452   }
453 }
454
455 void
456 col_append_str(column_info *cinfo, gint el, const gchar* str)
457 {
458   col_do_append_str(cinfo, el, NULL, str);
459 }
460
461 void
462 col_append_sep_str(column_info *cinfo, gint el, const gchar* separator,
463     const gchar* str)
464 {
465   if (separator == NULL)
466     separator = ", ";    /* default */
467   col_do_append_str(cinfo, el, separator, str);
468 }
469
470 static void
471 col_set_abs_date_time(frame_data *fd, column_info *cinfo, int col)
472 {
473   struct tm *tmp;
474   time_t then;
475
476   then = fd->abs_ts.secs;
477   tmp = localtime(&then);
478   if (tmp != NULL) {
479           switch(timestamp_get_precision()) {
480           case(TS_PREC_FIXED_SEC):
481           case(TS_PREC_AUTO_SEC):
482                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
483              "%04d-%02d-%02d %02d:%02d:%02d",
484              tmp->tm_year + 1900,
485              tmp->tm_mon + 1,
486              tmp->tm_mday,
487              tmp->tm_hour,
488              tmp->tm_min,
489              tmp->tm_sec);
490                   break;
491           case(TS_PREC_FIXED_DSEC):
492           case(TS_PREC_AUTO_DSEC):
493                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
494              "%04d-%02d-%02d %02d:%02d:%02d.%01ld",
495              tmp->tm_year + 1900,
496              tmp->tm_mon + 1,
497              tmp->tm_mday,
498              tmp->tm_hour,
499              tmp->tm_min,
500              tmp->tm_sec,
501              (long)fd->abs_ts.nsecs / 100000000);
502                   break;
503           case(TS_PREC_FIXED_CSEC):
504           case(TS_PREC_AUTO_CSEC):
505                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
506              "%04d-%02d-%02d %02d:%02d:%02d.%02ld",
507              tmp->tm_year + 1900,
508              tmp->tm_mon + 1,
509              tmp->tm_mday,
510              tmp->tm_hour,
511              tmp->tm_min,
512              tmp->tm_sec,
513              (long)fd->abs_ts.nsecs / 10000000);
514                   break;
515           case(TS_PREC_FIXED_MSEC):
516           case(TS_PREC_AUTO_MSEC):
517                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
518              "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
519              tmp->tm_year + 1900,
520              tmp->tm_mon + 1,
521              tmp->tm_mday,
522              tmp->tm_hour,
523              tmp->tm_min,
524              tmp->tm_sec,
525              (long)fd->abs_ts.nsecs / 1000000);
526                   break;
527           case(TS_PREC_FIXED_USEC):
528           case(TS_PREC_AUTO_USEC):
529                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
530              "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
531              tmp->tm_year + 1900,
532              tmp->tm_mon + 1,
533              tmp->tm_mday,
534              tmp->tm_hour,
535              tmp->tm_min,
536              tmp->tm_sec,
537              (long)fd->abs_ts.nsecs / 1000);
538                   break;
539           case(TS_PREC_FIXED_NSEC):
540           case(TS_PREC_AUTO_NSEC):
541                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
542              "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
543              tmp->tm_year + 1900,
544              tmp->tm_mon + 1,
545              tmp->tm_mday,
546              tmp->tm_hour,
547              tmp->tm_min,
548              tmp->tm_sec,
549              (long)fd->abs_ts.nsecs);
550                   break;
551           default:
552                   g_assert_not_reached();
553           }
554   } else {
555     cinfo->col_buf[col][0] = '\0';
556   }
557   cinfo->col_data[col] = cinfo->col_buf[col];
558   strcpy(cinfo->col_expr[col],"frame.time");
559   strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
560 }
561
562 static void
563 col_set_rel_time(frame_data *fd, column_info *cinfo, int col)
564 {
565   switch(timestamp_get_precision()) {
566           case(TS_PREC_FIXED_SEC):
567           case(TS_PREC_AUTO_SEC):
568                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
569                         fd->rel_ts.secs, fd->rel_ts.nsecs / 1000000000, SECS);
570                   break;
571           case(TS_PREC_FIXED_DSEC):
572           case(TS_PREC_AUTO_DSEC):
573                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
574                         fd->rel_ts.secs, fd->rel_ts.nsecs / 100000000, DSECS);
575                   break;
576           case(TS_PREC_FIXED_CSEC):
577           case(TS_PREC_AUTO_CSEC):
578                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
579                         fd->rel_ts.secs, fd->rel_ts.nsecs / 10000000, CSECS);
580                   break;
581           case(TS_PREC_FIXED_MSEC):
582           case(TS_PREC_AUTO_MSEC):
583                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
584                         fd->rel_ts.secs, fd->rel_ts.nsecs / 1000000, MSECS);
585                   break;
586           case(TS_PREC_FIXED_USEC):
587           case(TS_PREC_AUTO_USEC):
588                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
589                         fd->rel_ts.secs, fd->rel_ts.nsecs / 1000, USECS);
590                   break;
591           case(TS_PREC_FIXED_NSEC):
592           case(TS_PREC_AUTO_NSEC):
593                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
594                         fd->rel_ts.secs, fd->rel_ts.nsecs, NSECS);
595                   break;
596           default:
597                   g_assert_not_reached();
598   }
599   cinfo->col_data[col] = cinfo->col_buf[col];
600   strcpy(cinfo->col_expr[col],"frame.time_relative");
601   strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
602 }
603
604 static void
605 col_set_delta_time(frame_data *fd, column_info *cinfo, int col)
606 {
607   switch(timestamp_get_precision()) {
608           case(TS_PREC_FIXED_SEC):
609           case(TS_PREC_AUTO_SEC):
610                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
611                         fd->del_ts.secs, fd->del_ts.nsecs / 1000000000, SECS);
612                   break;
613           case(TS_PREC_FIXED_DSEC):
614           case(TS_PREC_AUTO_DSEC):
615                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
616                         fd->del_ts.secs, fd->del_ts.nsecs / 100000000, DSECS);
617                   break;
618           case(TS_PREC_FIXED_CSEC):
619           case(TS_PREC_AUTO_CSEC):
620                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
621                         fd->del_ts.secs, fd->del_ts.nsecs / 10000000, CSECS);
622                   break;
623           case(TS_PREC_FIXED_MSEC):
624           case(TS_PREC_AUTO_MSEC):
625                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
626                         fd->del_ts.secs, fd->del_ts.nsecs / 1000000, MSECS);
627                   break;
628           case(TS_PREC_FIXED_USEC):
629           case(TS_PREC_AUTO_USEC):
630                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
631                         fd->del_ts.secs, fd->del_ts.nsecs / 1000, USECS);
632                   break;
633           case(TS_PREC_FIXED_NSEC):
634           case(TS_PREC_AUTO_NSEC):
635                   display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
636                         fd->del_ts.secs, fd->del_ts.nsecs, NSECS);
637                   break;
638           default:
639                   g_assert_not_reached();
640   }
641   cinfo->col_data[col] = cinfo->col_buf[col];
642   strcpy(cinfo->col_expr[col],"frame.time_delta");
643   strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
644 }
645
646 /* To do: Add check_col checks to the col_add* routines */
647
648 static void
649 col_set_abs_time(frame_data *fd, column_info *cinfo, int col)
650 {
651   struct tm *tmp;
652   time_t then;
653
654   then = fd->abs_ts.secs;
655   tmp = localtime(&then);
656   if (tmp != NULL) {
657           switch(timestamp_get_precision()) {
658           case(TS_PREC_FIXED_SEC):
659           case(TS_PREC_AUTO_SEC):
660                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
661              "%02d:%02d:%02d",
662              tmp->tm_hour,
663              tmp->tm_min,
664              tmp->tm_sec);
665                   break;
666           case(TS_PREC_FIXED_DSEC):
667           case(TS_PREC_AUTO_DSEC):
668                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
669              "%02d:%02d:%02d.%01ld",
670              tmp->tm_hour,
671              tmp->tm_min,
672              tmp->tm_sec,
673              (long)fd->abs_ts.nsecs / 100000000);
674                   break;
675           case(TS_PREC_FIXED_CSEC):
676           case(TS_PREC_AUTO_CSEC):
677                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
678              "%02d:%02d:%02d.%02ld",
679              tmp->tm_hour,
680              tmp->tm_min,
681              tmp->tm_sec,
682              (long)fd->abs_ts.nsecs / 10000000);
683                   break;
684           case(TS_PREC_FIXED_MSEC):
685           case(TS_PREC_AUTO_MSEC):
686                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
687              "%02d:%02d:%02d.%03ld",
688              tmp->tm_hour,
689              tmp->tm_min,
690              tmp->tm_sec,
691              (long)fd->abs_ts.nsecs / 1000000);
692                   break;
693           case(TS_PREC_FIXED_USEC):
694           case(TS_PREC_AUTO_USEC):
695                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
696              "%02d:%02d:%02d.%06ld",
697              tmp->tm_hour,
698              tmp->tm_min,
699              tmp->tm_sec,
700              (long)fd->abs_ts.nsecs / 1000);
701                   break;
702           case(TS_PREC_FIXED_NSEC):
703           case(TS_PREC_AUTO_NSEC):
704                   g_snprintf(cinfo->col_buf[col], COL_MAX_LEN,
705              "%02d:%02d:%02d.%09ld",
706              tmp->tm_hour,
707              tmp->tm_min,
708              tmp->tm_sec,
709              (long)fd->abs_ts.nsecs);
710                   break;
711           default:
712                   g_assert_not_reached();
713           }
714   } else {
715     cinfo->col_buf[col][0] = '\0';
716   }
717   cinfo->col_data[col] = cinfo->col_buf[col];
718   strcpy(cinfo->col_expr[col],"frame.time");
719   strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
720 }
721
722 /* Add "command-line-specified" time.
723    XXX - this is called from "file.c" when the user changes the time
724    format they want for "command-line-specified" time; it's a bit ugly
725    that we have to export it, but if we go to a CList-like widget that
726    invokes callbacks to get the text for the columns rather than
727    requiring us to stuff the text into the widget from outside, we
728    might be able to clean this up. */
729 void
730 col_set_cls_time(frame_data *fd, column_info *cinfo, int col)
731 {
732   switch (timestamp_get_type()) {
733     case TS_ABSOLUTE:
734       col_set_abs_time(fd, cinfo, col);
735       break;
736
737     case TS_ABSOLUTE_WITH_DATE:
738       col_set_abs_date_time(fd, cinfo, col);
739       break;
740
741     case TS_RELATIVE:
742       col_set_rel_time(fd, cinfo, col);
743       break;
744
745     case TS_DELTA:
746       col_set_delta_time(fd, cinfo, col);
747       break;
748   }
749 }
750
751 static void
752 col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res,
753              gboolean is_src)
754 {
755   struct e_in6_addr ipv6_addr;
756
757   pinfo->cinfo->col_expr[col][0] = '\0';
758   pinfo->cinfo->col_expr_val[col][0] = '\0';
759   
760   if (addr->type == AT_NONE)
761     return;     /* no address, nothing to do */
762   
763   if (is_res) {
764     get_addr_name_buf(addr, pinfo->cinfo->col_buf[col],COL_MAX_LEN-1);
765   } else {
766     switch (addr->type) {
767
768     case AT_STRINGZ:
769       /* XXX - should be done in "address_to_str_buf()", but that routine
770          doesn't know COL_MAX_LEN; it should be changed to take the
771          maximum length as an argument. */
772       strncpy(pinfo->cinfo->col_buf[col], addr->data, COL_MAX_LEN);
773       pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
774       break;
775
776     default:
777       address_to_str_buf(addr, pinfo->cinfo->col_buf[col], COL_MAX_LEN);
778       break;
779     }
780   }
781   pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
782
783   switch (addr->type) {
784
785   case AT_ETHER:
786     if (is_src)
787       strcpy(pinfo->cinfo->col_expr[col], "eth.src");
788     else
789       strcpy(pinfo->cinfo->col_expr[col], "eth.dst");
790     strncpy(pinfo->cinfo->col_expr_val[col], ether_to_str(addr->data), COL_MAX_LEN);
791     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
792     break;
793
794   case AT_IPv4:
795     if (is_src)
796       strcpy(pinfo->cinfo->col_expr[col], "ip.src");
797     else
798       strcpy(pinfo->cinfo->col_expr[col], "ip.dst");
799     strncpy(pinfo->cinfo->col_expr_val[col], ip_to_str(addr->data), COL_MAX_LEN);
800     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
801     break;
802
803   case AT_IPv6:
804     if (is_src)
805       strcpy(pinfo->cinfo->col_expr[col], "ipv6.src");
806     else
807       strcpy(pinfo->cinfo->col_expr[col], "ipv6.dst");
808     strncpy(pinfo->cinfo->col_expr_val[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
809     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
810     break;
811
812   case AT_ATALK:
813     if (is_src)
814       strcpy(pinfo->cinfo->col_expr[col], "ddp.src");
815     else
816       strcpy(pinfo->cinfo->col_expr[col], "ddp.dst");
817     strcpy(pinfo->cinfo->col_expr_val[col], pinfo->cinfo->col_buf[col]);
818     break;
819
820   case AT_ARCNET:
821     if (is_src)
822       strcpy(pinfo->cinfo->col_expr[col], "arcnet.src");
823     else
824       strcpy(pinfo->cinfo->col_expr[col], "arcnet.dst");
825     strcpy(pinfo->cinfo->col_expr_val[col], pinfo->cinfo->col_buf[col]);
826     break;
827
828   default:
829     break;
830   }
831 }
832
833 static void
834 col_set_port(packet_info *pinfo, int col, gboolean is_res, gboolean is_src)
835 {
836   guint32 port;
837
838   if (is_src)
839     port = pinfo->srcport;
840   else
841     port = pinfo->destport;
842   pinfo->cinfo->col_expr[col][0] = '\0';
843   pinfo->cinfo->col_expr_val[col][0] = '\0';
844   switch (pinfo->ptype) {
845
846   case PT_SCTP:
847     if (is_res)
848       strncpy(pinfo->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
849     else
850       g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
851     break;
852
853   case PT_TCP:
854     if (is_res)
855       strncpy(pinfo->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
856     else
857       g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
858     if (is_src)
859       strcpy(pinfo->cinfo->col_expr[col], "tcp.srcport");
860     else
861       strcpy(pinfo->cinfo->col_expr[col], "tcp.dstport");
862     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
863     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
864     break;
865
866   case PT_UDP:
867     if (is_res)
868       strncpy(pinfo->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
869     else
870       g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
871     if (is_src)
872       strcpy(pinfo->cinfo->col_expr[col], "udp.srcport");
873     else
874       strcpy(pinfo->cinfo->col_expr[col], "udp.dstport");
875     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
876     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
877     break;
878
879   case PT_DDP:
880     if (is_src)
881       strcpy(pinfo->cinfo->col_expr[col], "ddp.src_socket");
882     else
883       strcpy(pinfo->cinfo->col_expr[col], "ddp.dst_socket");
884     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
885     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
886     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
887     break;
888
889   case PT_IPX:
890     /* XXX - resolve IPX socket numbers */
891     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "0x%04x", port);
892     if (is_src)
893       strcpy(pinfo->cinfo->col_expr[col], "ipx.src.socket");
894     else
895       strcpy(pinfo->cinfo->col_expr[col], "ipx.dst.socket");
896     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "0x%04x", port);
897     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
898     break;
899
900   case PT_IDP:
901     /* XXX - resolve IDP socket numbers */
902     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "0x%04x", port);
903     if (is_src)
904       strcpy(pinfo->cinfo->col_expr[col], "idp.src.socket");
905     else
906       strcpy(pinfo->cinfo->col_expr[col], "idp.dst.socket");
907     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "0x%04x", port);
908     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
909     break;
910
911   default:
912     break;
913   }
914   pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
915   pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
916 }
917
918 /*
919  * XXX - this should be in some common code in the epan directory, shared
920  * by this code and packet-isdn.c.
921  */
922 static const value_string channel_vals[] = {
923         { 0,    "D" },
924         { 1,    "B1" },
925         { 2,    "B2" },
926         { 3,    "B3" },
927         { 4,    "B4" },
928         { 5,    "B5" },
929         { 6,    "B6" },
930         { 7,    "B7" },
931         { 8,    "B8" },
932         { 9,    "B9" },
933         { 10,   "B10" },
934         { 11,   "B11" },
935         { 12,   "B12" },
936         { 13,   "B13" },
937         { 14,   "B14" },
938         { 15,   "B15" },
939         { 16,   "B16" },
940         { 17,   "B17" },
941         { 18,   "B19" },
942         { 19,   "B19" },
943         { 20,   "B20" },
944         { 21,   "B21" },
945         { 22,   "B22" },
946         { 23,   "B23" },
947         { 24,   "B24" },
948         { 25,   "B25" },
949         { 26,   "B26" },
950         { 27,   "B27" },
951         { 28,   "B29" },
952         { 29,   "B29" },
953         { 30,   "B30" },
954         { 0,    NULL }
955 };
956
957 static void
958 col_set_circuit_id(packet_info *pinfo, int col)
959 {
960   pinfo->cinfo->col_expr[col][0] = '\0';
961   pinfo->cinfo->col_expr_val[col][0] = '\0';
962   switch (pinfo->ctype) {
963
964   case CT_DLCI:
965     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
966     strcpy(pinfo->cinfo->col_expr[col], "fr.dlci");
967     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
968     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
969     break;
970
971   case CT_ISDN:
972     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%s",
973              val_to_str(pinfo->circuit_id, channel_vals, "Unknown (%u)"));
974     strcpy(pinfo->cinfo->col_expr[col], "isdn.channel");
975     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
976     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
977     break;
978
979   case CT_X25:
980     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
981     break;
982
983   case CT_ISUP:
984     g_snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
985     strcpy(pinfo->cinfo->col_expr[col], "isup.cic");
986     g_snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", pinfo->circuit_id);
987     pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
988     break;
989
990   default:
991     break;
992   }
993   pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
994   pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
995 }
996
997 void
998 fill_in_columns(packet_info *pinfo)
999 {
1000   int i;
1001
1002   for (i = 0; i < pinfo->cinfo->num_cols; i++) {
1003     switch (pinfo->cinfo->col_fmt[i]) {
1004
1005     case COL_NUMBER:
1006       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->num);
1007       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1008       strcpy(pinfo->cinfo->col_expr[i], "frame.number");
1009       strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
1010       break;
1011
1012     case COL_CLS_TIME:
1013       if(pinfo->fd->flags.ref_time){
1014          g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "*REF*");
1015          pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1016       } else {
1017          col_set_cls_time(pinfo->fd, pinfo->cinfo, i);
1018       }
1019       break;
1020
1021     case COL_ABS_TIME:
1022       if(pinfo->fd->flags.ref_time){
1023          g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "*REF*");
1024          pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1025       } else {
1026          col_set_abs_time(pinfo->fd, pinfo->cinfo, i);
1027       }
1028       break;
1029
1030     case COL_ABS_DATE_TIME:
1031       if(pinfo->fd->flags.ref_time){
1032          g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "*REF*");
1033          pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1034       } else {
1035          col_set_abs_date_time(pinfo->fd, pinfo->cinfo, i);
1036       }
1037       break;
1038
1039     case COL_REL_TIME:
1040       if(pinfo->fd->flags.ref_time){
1041          g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "*REF*");
1042          pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1043       } else {
1044          col_set_rel_time(pinfo->fd, pinfo->cinfo, i);
1045       }
1046       break;
1047
1048     case COL_DELTA_TIME:
1049       if(pinfo->fd->flags.ref_time){
1050          g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "*REF*");
1051          pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1052       } else {
1053          col_set_delta_time(pinfo->fd, pinfo->cinfo, i);
1054       }
1055       break;
1056
1057     case COL_DEF_SRC:
1058     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
1059       col_set_addr(pinfo, i, &pinfo->src, TRUE, TRUE);
1060       break;
1061
1062     case COL_UNRES_SRC:
1063       col_set_addr(pinfo, i, &pinfo->src, FALSE, TRUE);
1064       break;
1065
1066     case COL_DEF_DL_SRC:
1067     case COL_RES_DL_SRC:
1068       col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, TRUE);
1069       break;
1070
1071     case COL_UNRES_DL_SRC:
1072       col_set_addr(pinfo, i, &pinfo->dl_src, FALSE, TRUE);
1073       break;
1074
1075     case COL_DEF_NET_SRC:
1076     case COL_RES_NET_SRC:
1077       col_set_addr(pinfo, i, &pinfo->net_src, TRUE, TRUE);
1078       break;
1079
1080     case COL_UNRES_NET_SRC:
1081       col_set_addr(pinfo, i, &pinfo->net_src, FALSE, TRUE);
1082       break;
1083
1084     case COL_DEF_DST:
1085     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
1086       col_set_addr(pinfo, i, &pinfo->dst, TRUE, FALSE);
1087       break;
1088
1089     case COL_UNRES_DST:
1090       col_set_addr(pinfo, i, &pinfo->dst, FALSE, FALSE);
1091       break;
1092
1093     case COL_DEF_DL_DST:
1094     case COL_RES_DL_DST:
1095       col_set_addr(pinfo, i, &pinfo->dl_dst, TRUE, FALSE);
1096       break;
1097
1098     case COL_UNRES_DL_DST:
1099       col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, FALSE);
1100       break;
1101
1102     case COL_DEF_NET_DST:
1103     case COL_RES_NET_DST:
1104       col_set_addr(pinfo, i, &pinfo->net_dst, TRUE, FALSE);
1105       break;
1106
1107     case COL_UNRES_NET_DST:
1108       col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, FALSE);
1109       break;
1110
1111     case COL_DEF_SRC_PORT:
1112     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
1113       col_set_port(pinfo, i, TRUE, TRUE);
1114       break;
1115
1116     case COL_UNRES_SRC_PORT:
1117       col_set_port(pinfo, i, FALSE, TRUE);
1118       break;
1119
1120     case COL_DEF_DST_PORT:
1121     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1122       col_set_port(pinfo, i, TRUE, FALSE);
1123       break;
1124
1125     case COL_UNRES_DST_PORT:
1126       col_set_port(pinfo, i, FALSE, FALSE);
1127       break;
1128
1129     case COL_PROTOCOL:  /* currently done by dissectors */
1130     case COL_INFO:      /* currently done by dissectors */
1131       break;
1132
1133     case COL_PACKET_LENGTH:
1134       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->pkt_len);
1135       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1136       strcpy(pinfo->cinfo->col_expr[i], "frame.pkt_len");
1137       strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
1138       break;
1139
1140     case COL_CUMULATIVE_BYTES:
1141       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->cum_bytes);
1142       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1143       break;
1144
1145     case COL_OXID:
1146       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->oxid);
1147       pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
1148       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1149       break;
1150
1151     case COL_RXID:
1152       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->rxid);
1153       pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
1154       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1155       break;
1156
1157     case COL_IF_DIR:    /* currently done by dissectors */
1158       break;
1159
1160     case COL_CIRCUIT_ID:
1161       col_set_circuit_id(pinfo, i);
1162       break;
1163
1164     case COL_SRCIDX:
1165       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->src_idx);
1166       pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
1167       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1168       break;
1169
1170     case COL_DSTIDX:
1171       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->dst_idx);
1172       pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
1173       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1174       break;
1175
1176     case COL_VSAN:
1177       g_snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->vsan);
1178       pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
1179       pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
1180       break;
1181         
1182     case COL_HPUX_SUBSYS: /* done by nettl disector */
1183     case COL_HPUX_DEVID:  /* done by nettl disector */
1184       break;
1185         
1186     case COL_DCE_CALL:  /* done by dcerpc */
1187       break;
1188
1189     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
1190       g_assert_not_reached();
1191       break;
1192     }
1193   }
1194 }