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