add a new column DCE/RPC context ID
[obnox/wireshark/wip.git] / epan / column.c
1 /* column.c
2  * Routines for handling column preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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 <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <epan/timestamp.h>
39 #include <epan/prefs.h>
40 #include <epan/column.h>
41 #include <epan/packet.h>
42
43 /* Given a format number (as defined in packet.h), returns its equivalent
44    string */
45 const gchar *
46 col_format_to_string(gint fmt) {
47   const gchar *slist[] = {
48         "%m", 
49         "%t",
50         "%Rt",
51         "%At",
52         "%Yt",
53         "%Tt",
54         "%s",
55         "%rs",
56         "%us",
57         "%hs",
58         "%rhs",
59         "%uhs",
60         "%ns",
61         "%rns",
62         "%uns",
63         "%d",
64         "%rd",
65         "%ud",
66         "%hd",
67         "%rhd",
68     "%uhd",
69     "%nd", 
70     "%rnd",
71         "%und", 
72     "%S", 
73     "%rS", 
74     "%uS", 
75     "%D", 
76     "%rD", 
77     "%uD", 
78     "%p",
79         "%i", 
80     "%L", 
81     "%B", 
82     "%XO", 
83     "%XR", 
84     "%I", 
85     "%c", 
86     "%Xs", 
87         "%Xd", 
88     "%V", 
89     "%x", 
90     "%e", 
91     "%H", 
92     "%P", 
93     "%y", 
94     "%z", 
95     "%v", 
96     "%E"
97 };
98                      
99   if (fmt < 0 || fmt >= NUM_COL_FMTS)
100     return NULL;
101
102   return(slist[fmt]);
103 }
104
105 /* Given a format number (as defined in packet.h), returns its
106   description */
107 static const gchar *dlist[NUM_COL_FMTS] = {
108         "Number",                                   /* COL_NUMBER */
109         "Time (format as specified)",               /* COL_CLS_TIME */
110         "Relative time",                            /* COL_REL_TIME */
111         "Absolute time",                            /* COL_ABS_TIME */
112         "Absolute date and time",                   /* COL_ABS_DATE_TIME */
113         "Delta time",                               /* COL_DELTA_TIME */
114         "Source address",                           /* COL_DEF_SRC */
115         "Src addr (resolved)",                      /* COL_RES_SRC */
116         "Src addr (unresolved)",                    /* COL_UNRES_SRC */
117         "Hardware src addr",                        /* COL_DEF_DL_SRC */
118         "Hw src addr (resolved)",                   /* COL_RES_DL_SRC*/
119         "Hw src addr (unresolved)",                 /* COL_UNRES_DL_SRC */
120         "Network src addr",                         /* COL_DEF_NET_SRC */
121         "Net src addr (resolved)",                  /* COL_RES_NET_SRC */
122         "Net src addr (unresolved)",                /* COL_UNRES_NET_SRC */
123         "Destination address",                      /* COL_DEF_DST */
124         "Dest addr (resolved)",                     /* COL_RES_DST */
125         "Dest addr (unresolved)",                   /* COL_UNRES_DST */
126         "Hardware dest addr",                       /* COL_DEF_DL_DST */
127         "Hw dest addr (resolved)",                  /* COL_RES_DL_DST */
128         "Hw dest addr (unresolved)",                /* COL_UNRES_DL_DST */
129         "Network dest addr",                        /* COL_DEF_NET_DST */
130         "Net dest addr (resolved)",                 /* COL_RES_NET_DST */
131         "Net dest addr (unresolved)",               /* COL_UNRES_NET_DST */
132         "Source port",                              /* COL_DEF_SRC_PORT */
133         "Src port (resolved)",                      /* COL_RES_SRC_PORT */
134         "Src port (unresolved)",                    /* COL_UNRES_SRC_PORT */
135         "Destination port",                         /* COL_DEF_DST_PORT */
136         "Dest port (resolved)",                     /* COL_RES_DST_PORT */
137         "Dest port (unresolved)",                   /* COL_UNRES_DST_PORT */
138         "Protocol",                                 /* COL_PROTOCOL */
139         "Information",                              /* COL_INFO */
140         "Packet length (bytes)" ,                   /* COL_PACKET_LENGTH */
141         "Cumulative Bytes" ,                        /* COL_CUMULATIVE_BYTES */
142         "Fibre Channel OXID",                       /* COL_OXID */
143         "Fibre Channel RXID",                       /* COL_RXID */
144         "FW-1 monitor if/direction",                /* COL_IF_DIR */
145         "Circuit ID",                               /* COL_CIRCUIT_ID */
146         "Cisco Src PortIdx",                        /* COL_SRCIDX */
147         "Cisco Dst PortIdx",                        /* COL_DSTIDX */
148         "Cisco VSAN",                               /* COL_VSAN */
149         "IEEE 802.11 TX rate",                      /* COL_TX_RATE */
150         "IEEE 802.11 RSSI",                         /* COL_RSSI */
151         "HP-UX Subsystem",                          /* COL_HPUX_SUBSYS */
152         "HP-UX Device ID",                          /* COL_HPUX_DEVID */
153         "DCE/RPC call (cn_call_id / dg_seqnum)",    /* COL_DCE_CALL */
154         "DCE/RPC context ID (cn_ctx_id)",           /* COL_DCE_CTX */
155         "802.1Q VLAN id",                           /* COL_8021Q_VLAN_ID */
156         "TEI",                                      /* XXX - why is it missing in column_utils.c and elsewhere? */
157 };
158
159 const gchar *
160 col_format_desc(gint fmt) {
161   g_assert((fmt >= 0) && (fmt < NUM_COL_FMTS));
162   return(dlist[fmt]);
163 }
164
165 /* Marks each array element true if it can be substituted for the given
166    column format */
167 void
168 get_column_format_matches(gboolean *fmt_list, gint format) {
169
170   /* Get the obvious: the format itself */
171   if ((format >= 0) && (format < NUM_COL_FMTS))
172     fmt_list[format] = TRUE;
173
174   /* Get any formats lower down on the chain */
175   switch (format) {
176     case COL_DEF_SRC:
177       fmt_list[COL_RES_DL_SRC] = TRUE;
178       fmt_list[COL_RES_NET_SRC] = TRUE;
179       break;
180     case COL_RES_SRC:
181       fmt_list[COL_RES_DL_SRC] = TRUE;
182       fmt_list[COL_RES_NET_SRC] = TRUE;
183       break;
184     case COL_UNRES_SRC:
185       fmt_list[COL_UNRES_DL_SRC] = TRUE;
186       fmt_list[COL_UNRES_NET_SRC] = TRUE;
187       break;
188     case COL_DEF_DST:
189       fmt_list[COL_RES_DL_DST] = TRUE;
190       fmt_list[COL_RES_NET_DST] = TRUE;
191       break;
192     case COL_RES_DST:
193       fmt_list[COL_RES_DL_DST] = TRUE;
194       fmt_list[COL_RES_NET_DST] = TRUE;
195       break;
196     case COL_UNRES_DST:
197       fmt_list[COL_UNRES_DL_DST] = TRUE;
198       fmt_list[COL_UNRES_NET_DST] = TRUE;
199       break;
200     case COL_DEF_DL_SRC:
201       fmt_list[COL_RES_DL_SRC] = TRUE;
202       break;
203     case COL_DEF_DL_DST:
204       fmt_list[COL_RES_DL_DST] = TRUE;
205       break;
206     case COL_DEF_NET_SRC:
207       fmt_list[COL_RES_NET_SRC] = TRUE;
208       break;
209     case COL_DEF_NET_DST:
210       fmt_list[COL_RES_NET_DST] = TRUE;
211       break;
212     case COL_DEF_SRC_PORT:
213       fmt_list[COL_RES_SRC_PORT] = TRUE;
214       break;
215     case COL_DEF_DST_PORT:
216       fmt_list[COL_RES_DST_PORT] = TRUE;
217       break;
218     case COL_OXID:
219       fmt_list[COL_OXID] = TRUE;
220       break;
221     case COL_RXID:
222       fmt_list[COL_RXID] = TRUE;
223       break;
224     case COL_IF_DIR:
225       fmt_list[COL_IF_DIR] = TRUE;
226       break;
227     case COL_CIRCUIT_ID:
228       fmt_list[COL_CIRCUIT_ID] = TRUE;
229       break;
230     case COL_SRCIDX:
231       fmt_list[COL_SRCIDX] = TRUE;
232       break;
233     case COL_DSTIDX:
234       fmt_list[COL_DSTIDX] = TRUE;
235       break;
236     case COL_VSAN:
237       fmt_list[COL_VSAN] = TRUE;
238       break;
239     case COL_TX_RATE:
240       fmt_list[COL_TX_RATE] = TRUE;
241       break;
242     case COL_RSSI:
243       fmt_list[COL_RSSI] = TRUE;
244       break;
245     case COL_HPUX_SUBSYS:
246       fmt_list[COL_HPUX_SUBSYS] = TRUE;
247       break;
248     case COL_HPUX_DEVID:
249       fmt_list[COL_HPUX_DEVID] = TRUE;
250       break;
251     case COL_DCE_CALL:
252       fmt_list[COL_DCE_CALL] = TRUE;
253       break;
254     case COL_DCE_CTX:
255       fmt_list[COL_DCE_CTX] = TRUE;
256       break;
257     case COL_8021Q_VLAN_ID:
258       fmt_list[COL_8021Q_VLAN_ID] = TRUE;
259       break;
260     case COL_TEI:
261       fmt_list[COL_TEI] = TRUE;
262       break;
263     default:
264       break;
265   }
266 }
267
268 /* Returns a string representing the longest possible value for 
269    a timestamp column type. */
270 static const char *
271 get_timestamp_column_longest_string(gint type, gint precision)
272 {
273
274         switch(type) {
275         case(TS_ABSOLUTE_WITH_DATE):
276                 switch(precision) {
277                         case(TS_PREC_AUTO_SEC):
278                         case(TS_PREC_FIXED_SEC):
279                                 return "0000-00-00 00:00:00";
280                                 break;
281                         case(TS_PREC_AUTO_DSEC):
282                         case(TS_PREC_FIXED_DSEC):
283                                 return "0000-00-00 00:00:00.0";
284                                 break;
285                         case(TS_PREC_AUTO_CSEC):
286                         case(TS_PREC_FIXED_CSEC):
287                                 return "0000-00-00 00:00:00.00";
288                                 break;
289                         case(TS_PREC_AUTO_MSEC):
290                         case(TS_PREC_FIXED_MSEC):
291                                 return "0000-00-00 00:00:00.000";
292                                 break;
293                         case(TS_PREC_AUTO_USEC):
294                         case(TS_PREC_FIXED_USEC):
295                                 return "0000-00-00 00:00:00.000000";
296                                 break;
297                         case(TS_PREC_AUTO_NSEC):
298                         case(TS_PREC_FIXED_NSEC):
299                                 return "0000-00-00 00:00:00.000000000";
300                                 break;
301                         default:
302                                 g_assert_not_reached();
303                 }
304                         break;
305         case(TS_ABSOLUTE):
306                 switch(precision) {
307                         case(TS_PREC_AUTO_SEC):
308                         case(TS_PREC_FIXED_SEC):
309                                 return "00:00:00";
310                                 break;
311                         case(TS_PREC_AUTO_DSEC):
312                         case(TS_PREC_FIXED_DSEC):
313                                 return "00:00:00.0";
314                                 break;
315                         case(TS_PREC_AUTO_CSEC):
316                         case(TS_PREC_FIXED_CSEC):
317                                 return "00:00:00.00";
318                                 break;
319                         case(TS_PREC_AUTO_MSEC):
320                         case(TS_PREC_FIXED_MSEC):
321                                 return "00:00:00.000";
322                                 break;
323                         case(TS_PREC_AUTO_USEC):
324                         case(TS_PREC_FIXED_USEC):
325                                 return "00:00:00.000000";
326                                 break;
327                         case(TS_PREC_AUTO_NSEC):
328                         case(TS_PREC_FIXED_NSEC):
329                                 return "00:00:00.000000000";
330                                 break;
331                         default:
332                                 g_assert_not_reached();
333                 }
334                 break;
335         case(TS_RELATIVE):      /* fallthrough */
336         case(TS_DELTA):
337                 switch(precision) {
338                         case(TS_PREC_AUTO_SEC):
339                         case(TS_PREC_FIXED_SEC):
340                                 return "0000";
341                                 break;
342                         case(TS_PREC_AUTO_DSEC):
343                         case(TS_PREC_FIXED_DSEC):
344                                 return "0000.0";
345                                 break;
346                         case(TS_PREC_AUTO_CSEC):
347                         case(TS_PREC_FIXED_CSEC):
348                                 return "0000.00";
349                                 break;
350                         case(TS_PREC_AUTO_MSEC):
351                         case(TS_PREC_FIXED_MSEC):
352                                 return "0000.000";
353                                 break;
354                         case(TS_PREC_AUTO_USEC):
355                         case(TS_PREC_FIXED_USEC):
356                                 return "0000.000000";
357                                 break;
358                         case(TS_PREC_AUTO_NSEC):
359                         case(TS_PREC_FIXED_NSEC):
360                                 return "0000.000000000";
361                                 break;
362                         default:
363                                 g_assert_not_reached();
364                 }
365                 break;
366         case(TS_NOT_SET):
367                 return "0000.000000";
368                 break;
369         default:
370                 g_assert_not_reached();
371         }
372
373         /* never reached, satisfy compiler */
374         return "";
375 }
376
377 /* Returns a string representing the longest possible value for a
378    particular column type.
379
380    Except for the COL...SRC and COL...DST columns, these are used
381    only when a capture is being displayed while it's taking place;
382    they are arguably somewhat fragile, as changes to the code that
383    generates them don't cause these widths to change, but that's
384    probably not too big a problem, given that the sizes are
385    recomputed based on the actual data in the columns when the capture
386    is done, and given that the width for COL...SRC and COL...DST columns
387    is somewhat arbitrary in any case.  We should probably clean
388    that up eventually, though. */
389 const char *
390 get_column_longest_string(gint format)
391 {
392   switch (format) {
393     case COL_NUMBER:
394       return "0000000";
395       break;
396     case COL_CLS_TIME:
397       return get_timestamp_column_longest_string(timestamp_get_type(), timestamp_get_precision());
398       break;
399     case COL_ABS_DATE_TIME:
400       return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_DATE, timestamp_get_precision());
401       break;
402     case COL_ABS_TIME:
403       return get_timestamp_column_longest_string(TS_ABSOLUTE, timestamp_get_precision());
404       break;
405     case COL_REL_TIME:
406       return get_timestamp_column_longest_string(TS_RELATIVE, timestamp_get_precision());
407       break;
408     case COL_DELTA_TIME:
409       return get_timestamp_column_longest_string(TS_DELTA, timestamp_get_precision());
410       break;
411     case COL_DEF_SRC:
412     case COL_RES_SRC:
413     case COL_UNRES_SRC:
414     case COL_DEF_DL_SRC:
415     case COL_RES_DL_SRC:
416     case COL_UNRES_DL_SRC:
417     case COL_DEF_NET_SRC:
418     case COL_RES_NET_SRC:
419     case COL_UNRES_NET_SRC:
420     case COL_DEF_DST:
421     case COL_RES_DST:
422     case COL_UNRES_DST:
423     case COL_DEF_DL_DST:
424     case COL_RES_DL_DST:
425     case COL_UNRES_DL_DST:
426     case COL_DEF_NET_DST:
427     case COL_RES_NET_DST:
428     case COL_UNRES_NET_DST:
429       return "00000000.000000000000"; /* IPX-style */
430       break;
431     case COL_DEF_SRC_PORT:
432     case COL_RES_SRC_PORT:
433     case COL_UNRES_SRC_PORT:
434     case COL_DEF_DST_PORT:
435     case COL_RES_DST_PORT:
436     case COL_UNRES_DST_PORT:
437       return "000000";
438       break;
439     case COL_PROTOCOL:
440       return "Protocol";        /* not the longest, but the longest is too long */
441       break;
442     case COL_PACKET_LENGTH:
443       return "00000";
444       break;
445     case COL_CUMULATIVE_BYTES:
446       return "00000000";
447       break;
448     case COL_RXID:
449     case COL_OXID:
450       return "000000";
451       break;
452     case COL_IF_DIR:
453       return "i 00000000 I";
454       break;
455     case COL_CIRCUIT_ID:
456       return "000000";
457       break;
458     case COL_SRCIDX:
459     case COL_DSTIDX:
460       return "0000000";
461       break;
462     case COL_VSAN:
463       return "000000";
464       break;
465     case COL_TX_RATE:
466       return "108.0";
467       break;
468     case COL_RSSI:
469       return "100";
470       break;
471     case COL_HPUX_SUBSYS:
472       return "OTS9000-TRANSPORT";
473       break;
474     case COL_HPUX_DEVID:
475       return "0000";
476       break;
477     case COL_DCE_CALL:
478       return "0000";
479       break;
480     case COL_DCE_CTX:
481       return "0000";
482       break;
483     case COL_8021Q_VLAN_ID:
484       return "0000";
485       break;
486     case COL_TEI:
487       return "127";
488       break;
489     default: /* COL_INFO */
490       return "Source port: kerberos-master  Destination port: kerberos-master";
491       break;
492   }
493 }
494
495 /* Returns the longest possible width, in characters, for a particular
496    column type. */
497 gint
498 get_column_char_width(gint format)
499 {
500   return strlen(get_column_longest_string(format));
501 }
502
503 #define TIME_DEF      0
504 #define TIME_REL      1
505 #define TIME_ABS      2
506 #define DATE_TIME_ABS 3
507 #define TIME_DEL      4
508
509 #define RES_DEF  0
510 #define RES_DO   1
511 #define RES_DONT 2
512
513 #define ADDR_DEF 0
514 #define ADDR_DL  3
515 #define ADDR_NET 6
516
517 gint
518 get_column_format(gint col) {
519   GList    *clp = g_list_nth(prefs.col_list, col);
520   fmt_data *cfmt;
521
522   cfmt = (fmt_data *) clp->data;
523
524   return(get_column_format_from_str(cfmt->fmt));
525 }
526
527 gint
528 get_column_format_from_str(gchar *str) {
529   gchar *cptr = str;
530   gint      res_off = RES_DEF, addr_off = ADDR_DEF, time_off = TIME_DEF;
531   gint      prev_code = -1;
532
533   /* To do: Make this parse %-formatted strings "for real" */
534   while (*cptr != '\0') {
535     switch (*cptr) {
536       case 't':  /* To do: fix for absolute and delta */
537         return COL_CLS_TIME + time_off;
538         break;
539       case 'm':
540         return COL_NUMBER;
541         break;
542       case 's':
543         if (prev_code == COL_OXID) {
544           return COL_SRCIDX;
545         }
546         else {
547           return COL_DEF_SRC + res_off + addr_off;
548         }
549         break;
550       case 'd':
551         if (prev_code == COL_OXID) {
552           return COL_DSTIDX;
553         }
554         else {
555           return COL_DEF_DST + res_off + addr_off;
556         }
557         break;
558       case 'S':
559         return COL_DEF_SRC_PORT + res_off;
560         break;
561       case 'D':
562         return COL_DEF_DST_PORT + res_off;
563         break;
564       case 'p':
565         return COL_PROTOCOL;
566         break;
567       case 'i':
568         return COL_INFO;
569         break;
570       case 'r':
571         res_off = RES_DO;
572         break;
573       case 'u':
574         res_off = RES_DONT;
575         break;
576       case 'h':
577         addr_off = ADDR_DL;
578         break;
579       case 'n':
580         addr_off = ADDR_NET;
581         break;
582       case 'R':
583         if (prev_code == COL_OXID) {
584             return COL_RXID;
585         }
586         else {
587             time_off = TIME_REL;
588         }
589         break;
590       case 'A':
591         time_off = TIME_ABS;
592         break;
593       case 'Y':
594         time_off = DATE_TIME_ABS;
595         break;
596       case 'T':
597         time_off = TIME_DEL;
598         break;
599       case 'L':
600         return COL_PACKET_LENGTH;
601         break;
602       case 'B':
603         return COL_CUMULATIVE_BYTES;
604         break;
605       case 'X':
606         prev_code = COL_OXID;
607         break;
608       case 'O':
609         return COL_OXID;
610         break;
611       case 'I':
612         return COL_IF_DIR;
613         break;
614       case 'c':
615         return COL_CIRCUIT_ID;
616         break;
617       case 'V':
618         return COL_VSAN;
619         break;
620       case 'x':
621         return COL_TX_RATE;
622         break;
623       case 'e':
624         return COL_RSSI;
625         break;
626       case 'H':
627         return COL_HPUX_SUBSYS;
628         break;
629       case 'P':
630         return COL_HPUX_DEVID;
631         break;
632       case 'y':
633         return COL_DCE_CALL;
634         break;
635       case 'z':
636         return COL_DCE_CTX;
637         break;
638       case 'v':
639         return COL_8021Q_VLAN_ID;
640         break;
641       case 'E':
642         return COL_TEI;
643         break;
644     }
645     cptr++;
646   }
647   return -1;    /* illegal */
648 }
649
650 gchar *
651 get_column_title(gint col) {
652   GList    *clp = g_list_nth(prefs.col_list, col);
653   fmt_data *cfmt;
654
655   cfmt = (fmt_data *) clp->data;
656
657   return(cfmt->title);
658 }