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