Note that capture filters don't work on Linux loopback devices with the
[obnox/wireshark/wip.git] / column.c
1 /* column.c
2  * Routines for handling column preferences
3  *
4  * $Id: column.c,v 1.27 2000/01/10 01:43:47 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <errno.h>
37
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include <sys/stat.h>
43
44 #include "timestamp.h"
45 #include "prefs.h"
46 #include "column.h"
47 #include "packet.h"
48
49 /* Given a format number (as defined in packet.h), returns its equivalent
50    string */
51 gchar *
52 col_format_to_string(gint fmt) {
53   gchar *slist[] = { "%m", "%t", "%Rt", "%At", "%Tt", "%s", "%rs", "%us",
54                      "%hs", "%rhs", "%uhs", "%ns", "%rns", "%uns", "%d",
55                      "%rd", "%ud", "%hd", "%rhd", "%uhd", "%nd", "%rnd",
56                      "%und", "%S", "%rS", "%uS", "%D", "%rD", "%uD", "%p",
57                      "%i", "%L" };
58   
59   if (fmt < 0 || fmt > NUM_COL_FMTS)
60     return NULL;
61   
62   return(slist[fmt]);
63 }
64
65 /* Given a format number (as defined in packet.h), returns its
66   description */
67 gchar *
68 col_format_desc(gint fmt) {
69   gchar *dlist[] = { "Number", "Time (command line specified)",
70                      "Relative time", "Absolute time", "Delta time",
71                      "Source address", "Src addr (resolved)",
72                      "Src addr (unresolved)", "Hardware src addr",
73                      "Hw src addr (resolved)", "Hw src addr (unresolved)",
74                      "Network src addr", "Net src addr (resolved)",
75                      "Net src addr (unresolved)", "Destination address",
76                      "Dest addr (resolved)", "Dest addr (unresolved)",
77                      "Hardware dest addr", "Hw dest addr (resolved)",
78                      "Hw dest addr (unresolved)", "Network dest addr",
79                      "Net dest addr (resolved)", "Net dest addr (unresolved)",
80                      "Source port", "Src port (resolved)",
81                      "Src port (unresolved)", "Destination port",
82                      "Dest port (resolved)", "Dest port (unresolved)",
83                      "Protocol", "Information", "Packet length (bytes)" };
84   
85   if (fmt < 0 || fmt > NUM_COL_FMTS)
86     return NULL;
87   
88   return(dlist[fmt]);
89 }
90
91 /* Marks each array element true if it can be substituted for the given
92    column format */
93 void
94 get_column_format_matches(gboolean *fmt_list, gint format) {
95   int i;
96   
97   for (i = 0; i < NUM_COL_FMTS; i++) {
98     /* Get the obvious: the format itself */
99     if (i == format)
100       fmt_list[i] = TRUE;
101     /* Get any formats lower down on the chain */
102     switch (format) {
103       case COL_DEF_SRC:
104         fmt_list[COL_RES_DL_SRC] = TRUE;
105         fmt_list[COL_RES_NET_SRC] = TRUE;
106         break;
107       case COL_RES_SRC:
108         fmt_list[COL_RES_DL_SRC] = TRUE;
109         fmt_list[COL_RES_NET_SRC] = TRUE;
110         break;
111       case COL_UNRES_SRC:
112         fmt_list[COL_UNRES_DL_SRC] = TRUE;
113         fmt_list[COL_UNRES_NET_SRC] = TRUE;
114         break;
115       case COL_DEF_DST:
116         fmt_list[COL_RES_DL_DST] = TRUE;
117         fmt_list[COL_RES_NET_DST] = TRUE;
118         break;
119       case COL_RES_DST:
120         fmt_list[COL_RES_DL_DST] = TRUE;
121         fmt_list[COL_RES_NET_DST] = TRUE;
122         break;
123       case COL_UNRES_DST:
124         fmt_list[COL_UNRES_DL_DST] = TRUE;
125         fmt_list[COL_UNRES_NET_DST] = TRUE;
126         break;
127       case COL_DEF_DL_SRC:
128         fmt_list[COL_RES_DL_SRC] = TRUE;
129         break;
130       case COL_DEF_DL_DST:
131         fmt_list[COL_RES_DL_DST] = TRUE;
132         break;
133       case COL_DEF_NET_SRC:
134         fmt_list[COL_RES_NET_SRC] = TRUE;
135         break;
136       case COL_DEF_NET_DST:
137         fmt_list[COL_RES_NET_DST] = TRUE;
138         break;
139       case COL_DEF_SRC_PORT:
140         fmt_list[COL_RES_SRC_PORT] = TRUE;
141         break;
142       case COL_DEF_DST_PORT:
143         fmt_list[COL_RES_DST_PORT] = TRUE;
144         break;
145       default:
146         break;
147     }
148   }
149 }
150
151 /* Returns a string representing the longest possible value for a
152    particular column type.
153
154    Except for the COL...SRC and COL...DST columns, these are used
155    only when a capture is being displayed while it's taking place;
156    they are arguably somewhat fragile, as changes to the code that
157    generates them don't cause these widths to change, but that's
158    probably not too big a problem, given that the sizes are
159    recomputed based on the actual data in the columns when the capture
160    is done, and given that the width for COL...SRC and COL...DST columns
161    is somewhat arbitrary in any case.  We should probably clean
162    that up eventually, though. */
163 char *
164 get_column_longest_string(gint format)
165 {
166   switch (format) {
167     case COL_NUMBER:
168       return "0000000";
169       break;
170     case COL_CLS_TIME:
171       if (timestamp_type == ABSOLUTE)
172         return "00:00:00.000000";
173       else
174         return "0000.000000";
175       break;
176     case COL_ABS_TIME:
177       return "00:00:00.000000";
178       break;
179     case COL_REL_TIME:
180     case COL_DELTA_TIME:
181       return "0000.000000";
182       break;
183     case COL_DEF_SRC:
184     case COL_RES_SRC:
185     case COL_UNRES_SRC:
186     case COL_DEF_DL_SRC:
187     case COL_RES_DL_SRC:
188     case COL_UNRES_DL_SRC:
189     case COL_DEF_NET_SRC:
190     case COL_RES_NET_SRC:
191     case COL_UNRES_NET_SRC:
192     case COL_DEF_DST:
193     case COL_RES_DST:
194     case COL_UNRES_DST:
195     case COL_DEF_DL_DST:
196     case COL_RES_DL_DST:
197     case COL_UNRES_DL_DST:
198     case COL_DEF_NET_DST:
199     case COL_RES_NET_DST:
200     case COL_UNRES_NET_DST:
201       return "00000000.000000000000"; /* IPX-style */
202       break;
203     case COL_DEF_SRC_PORT:
204     case COL_RES_SRC_PORT:
205     case COL_UNRES_SRC_PORT:
206     case COL_DEF_DST_PORT:
207     case COL_RES_DST_PORT:
208     case COL_UNRES_DST_PORT:
209       return "000000";
210       break;
211     case COL_PROTOCOL:
212       return "NetBIOS"; /* not the longest, but the longest is too long */
213       break;
214     case COL_PACKET_LENGTH:
215       return "000000";
216       break;
217     default: /* COL_INFO */
218       return "Source port: kerberos-master  Destination port: kerberos-master";
219       break;
220   }
221 }
222
223 /* Returns the longest possible width, in characters, for a particular
224    column type. */
225 gint
226 get_column_char_width(gint format)
227 {
228   return strlen(get_column_longest_string(format));
229 }
230
231 enum col_resize_type
232 get_column_resize_type(gint format) {
233   switch (format) {
234     case COL_NUMBER:
235     case COL_CLS_TIME:
236     case COL_ABS_TIME:
237     case COL_REL_TIME:
238     case COL_DELTA_TIME:
239     case COL_DEF_SRC_PORT:
240     case COL_RES_SRC_PORT:
241     case COL_UNRES_SRC_PORT:
242     case COL_DEF_DST_PORT:
243     case COL_RES_DST_PORT:
244     case COL_UNRES_DST_PORT:
245     case COL_PROTOCOL:
246     case COL_PACKET_LENGTH:
247       /* We don't want these to resize during a live capture, as that
248          gets in the way of trying to look at the data while it's being
249          captured. */
250       return (RESIZE_AUTO);
251       break;
252     case COL_DEF_SRC:
253     case COL_RES_SRC:
254     case COL_UNRES_SRC:
255     case COL_DEF_DL_SRC:
256     case COL_RES_DL_SRC:
257     case COL_UNRES_DL_SRC:
258     case COL_DEF_NET_SRC:
259     case COL_RES_NET_SRC:
260     case COL_UNRES_NET_SRC:
261     case COL_DEF_DST:
262     case COL_RES_DST:
263     case COL_UNRES_DST:
264     case COL_DEF_DL_DST:
265     case COL_RES_DL_DST:
266     case COL_UNRES_DL_DST:
267     case COL_DEF_NET_DST:
268     case COL_RES_NET_DST:
269     case COL_UNRES_NET_DST:
270       /* We don't want these to resize dynamically; if they get resolved
271          to names, those names could be very long, and auto-resizing
272          columns showing those names may leave too little room for
273          other columns such as the "Info" column. */
274       return (RESIZE_MANUAL);
275       break;
276     default: /* COL_INFO */
277       /* We want this to resize dynamically, even during a live capture,
278          because otherewise you won't be able to see all that's in
279          it. */
280       return (RESIZE_LIVE);
281       break;
282   }
283 }
284
285 #define TIME_DEF 0
286 #define TIME_REL 1
287 #define TIME_ABS 2
288 #define TIME_DEL 3
289
290 #define RES_DEF  0
291 #define RES_DO   1
292 #define RES_DONT 2
293
294 #define ADDR_DEF 0
295 #define ADDR_DL  3
296 #define ADDR_NET 6
297
298 gint
299 get_column_format(gint col) {
300   GList    *clp = g_list_nth(prefs.col_list, col);
301   fmt_data *cfmt;
302   
303   cfmt = (fmt_data *) clp->data;
304   
305   return(get_column_format_from_str(cfmt->fmt));
306 }
307
308 gint
309 get_column_format_from_str(gchar *str) {
310   gchar *cptr = str;
311   gint      res_off = RES_DEF, addr_off = ADDR_DEF, time_off = TIME_DEF;
312
313   /* To do: Make this parse %-formatted strings "for real" */
314   while (*cptr != '\0') {
315     switch (*cptr) {
316       case 't':  /* To do: fix for absolute and delta */
317         return COL_CLS_TIME + time_off;
318         break;
319       case 'm':
320         return COL_NUMBER;
321         break;
322       case 's':
323         return COL_DEF_SRC + res_off + addr_off;
324         break;
325       case 'd':
326         return COL_DEF_DST + res_off + addr_off;
327         break;
328       case 'S':
329         return COL_DEF_SRC_PORT + res_off;
330         break;
331       case 'D':
332         return COL_DEF_DST_PORT + res_off;
333         break;
334       case 'p':
335         return COL_PROTOCOL;
336         break;
337       case 'i':
338         return COL_INFO;
339         break;
340       case 'r':
341         res_off = RES_DO;
342         break;
343       case 'u':
344         res_off = RES_DONT;
345         break;
346       case 'h':
347         addr_off = ADDR_DL;
348         break;
349       case 'n':
350         addr_off = ADDR_NET;
351         break;
352       case 'R':
353         time_off = TIME_REL;
354         break;
355       case 'A':
356         time_off = TIME_ABS;
357         break;
358       case 'T':
359         time_off = TIME_DEL;
360         break;
361       case 'L':
362         return COL_PACKET_LENGTH;
363         break;
364     }
365     cptr++;
366   }
367   return COL_NUMBER;
368 }
369
370 gchar *
371 get_column_title(gint col) {
372   GList    *clp = g_list_nth(prefs.col_list, col);
373   fmt_data *cfmt;
374   
375   cfmt = (fmt_data *) clp->data;
376
377   return(cfmt->title);  
378 }
379
380 #define MAX_FMT_PREF_LEN      1024
381 #define MAX_FMT_PREF_LINE_LEN   60
382 gchar *
383 col_format_to_pref_str() {
384   static gchar  pref_str[MAX_FMT_PREF_LEN] = "";
385   GList        *clp = g_list_first(prefs.col_list);
386   fmt_data     *cfmt;
387   int           cur_pos = 0, cur_len = 0, fmt_len;
388   
389   while (clp) {
390     cfmt = (fmt_data *) clp->data;
391     
392     fmt_len = strlen(cfmt->title) + 4;
393     if ((fmt_len + cur_len) < (MAX_FMT_PREF_LEN - 1)) {
394       if ((fmt_len + cur_pos) > MAX_FMT_PREF_LINE_LEN) {
395         cur_len--;
396         cur_pos = 0;
397                 pref_str[cur_len] = '\n'; cur_len++;
398         pref_str[cur_len] = '\t'; cur_len++;
399       }
400       sprintf(&pref_str[cur_len], "\"%s\", ", cfmt->title);
401       cur_len += fmt_len;
402       cur_pos += fmt_len;
403     }
404
405     fmt_len = strlen(cfmt->fmt) + 4;
406     if ((fmt_len + cur_len) < (MAX_FMT_PREF_LEN - 1)) {
407       if ((fmt_len + cur_pos) > MAX_FMT_PREF_LINE_LEN) {
408         cur_len--;
409         cur_pos = 0;
410         pref_str[cur_len] = '\n'; cur_len++;
411         pref_str[cur_len] = '\t'; cur_len++;
412       }
413       sprintf(&pref_str[cur_len], "\"%s\", ", cfmt->fmt);
414       cur_len += fmt_len;
415       cur_pos += fmt_len;
416     }
417     
418     clp = clp->next;
419   }
420   
421   if (cur_len > 2)
422     pref_str[cur_len - 2] = '\0';
423
424   return(pref_str);
425 }