Clean up indentation.
[obnox/wireshark/wip.git] / epan / column-utils.c
1 /* column-utils.c
2  * Routines for column utilities.
3  *
4  * $Id: column-utils.c,v 1.7 2001/11/21 23:16:23 gram 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 #include <string.h>
31 #include <time.h>
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #ifdef NEED_SNPRINTF_H
38 # include "snprintf.h"
39 #endif
40
41 #ifdef NEED_INET_V6DEFS_H
42 # include "inet_v6defs.h"
43 #endif
44
45 #include "column-utils.h"
46 #include "timestamp.h"
47 #include "sna-utils.h"
48 #include "atalk-utils.h"
49 #include "to_str.h"
50 #include "packet_info.h"
51 #include "pint.h"
52 #include "resolv.h"
53 #include "ipv6-utils.h" 
54 #include "osi-utils.h"
55
56 /* Allocate all the data structures for constructing column data, given
57    the number of columns. */
58 void
59 col_init(column_info *col_info, gint num_cols)
60 {
61   col_info->num_cols    = num_cols;
62   col_info->col_fmt     = (gint *) g_malloc(sizeof(gint) * num_cols);
63   col_info->fmt_matx    = (gboolean **) g_malloc(sizeof(gboolean *) * num_cols);
64   col_info->col_width   = (gint *) g_malloc(sizeof(gint) * num_cols);
65   col_info->col_title   = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
66   col_info->col_data    = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
67   col_info->col_buf     = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
68 }
69
70 /*
71  * This function does not appear to be used anywhere...  
72
73 gboolean
74 col_get_writable(frame_data *fd)
75 {
76   if (fd) {
77
78     return (fd->cinfo ? fd->cinfo->writable : FALSE);
79
80   }
81
82   return FALSE;
83
84 }
85
86 */
87
88 void
89 col_set_writable(frame_data *fd, gboolean writable)
90 {
91         if (fd->cinfo) {
92                 fd->cinfo->writable = writable;
93         }
94 }
95
96 /* Checks to see if a particular packet information element is needed for
97    the packet list */
98 gint
99 check_col(frame_data *fd, gint el) {
100   int i;
101
102   if (fd->cinfo && fd->cinfo->writable) {
103     for (i = 0; i < fd->cinfo->num_cols; i++) {
104       if (fd->cinfo->fmt_matx[i][el])
105         return TRUE;
106     }
107   }
108   return FALSE;
109 }
110
111
112
113 /* Use this to clear out a column, especially if you're going to be
114    appending to it later; at least on some platforms, it's more
115    efficient than using "col_add_str()" with a null string, and
116    more efficient than "col_set_str()" with a null string if you
117    later append to it, as the later append will cause a string
118    copy to be done. */
119 void
120 col_clear(frame_data *fd, gint el) {
121   int    i;
122
123   for (i = 0; i < fd->cinfo->num_cols; i++) {
124     if (fd->cinfo->fmt_matx[i][el]) {
125       fd->cinfo->col_buf[i][0] = 0;
126       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
127     }
128   }
129 }
130
131 /* Use this if "str" points to something that will stay around (and thus
132    needn't be copied). */
133 void
134 col_set_str(frame_data *fd, gint el, gchar* str) {
135   int i;
136   
137   for (i = 0; i < fd->cinfo->num_cols; i++) {
138     if (fd->cinfo->fmt_matx[i][el])
139       fd->cinfo->col_data[i] = str;
140   }
141 }
142
143 /* Adds a vararg list to a packet info string. */
144 void
145 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
146   va_list ap;
147   int     i;
148   size_t  max_len;
149
150   if (el == COL_INFO)
151         max_len = COL_MAX_INFO_LEN;
152   else
153         max_len = COL_MAX_LEN;
154   
155   va_start(ap, format);
156   for (i = 0; i < fd->cinfo->num_cols; i++) {
157     if (fd->cinfo->fmt_matx[i][el]) {
158       vsnprintf(fd->cinfo->col_buf[i], max_len, format, ap);
159       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
160     }
161   }
162 }
163
164 /* Appends a vararg list to a packet info string. */
165 void
166 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
167   va_list ap;
168   int     i;
169   size_t  len, max_len;
170   
171   if (el == COL_INFO)
172         max_len = COL_MAX_INFO_LEN;
173   else
174         max_len = COL_MAX_LEN;
175   
176   va_start(ap, format);
177   for (i = 0; i < fd->cinfo->num_cols; i++) {
178     if (fd->cinfo->fmt_matx[i][el]) {
179       if (fd->cinfo->col_data[i] != fd->cinfo->col_buf[i]) {
180         /* This was set with "col_set_str()"; copy the string they
181            set it to into the buffer, so we can append to it. */
182         strncpy(fd->cinfo->col_buf[i], fd->cinfo->col_data[i], max_len);
183         fd->cinfo->col_buf[i][max_len - 1] = '\0';
184       }
185       len = strlen(fd->cinfo->col_buf[i]);
186       vsnprintf(&fd->cinfo->col_buf[i][len], max_len - len, format, ap);
187       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
188     }
189   }
190 }
191
192 /* Use this if "str" points to something that won't stay around (and
193    must thus be copied). */
194 void
195 col_add_str(frame_data *fd, gint el, const gchar* str) {
196   int    i;
197   size_t max_len;
198
199   if (el == COL_INFO)
200         max_len = COL_MAX_INFO_LEN;
201   else
202         max_len = COL_MAX_LEN;
203   
204   for (i = 0; i < fd->cinfo->num_cols; i++) {
205     if (fd->cinfo->fmt_matx[i][el]) {
206       strncpy(fd->cinfo->col_buf[i], str, max_len);
207       fd->cinfo->col_buf[i][max_len - 1] = 0;
208       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
209     }
210   }
211 }
212
213 void
214 col_append_str(frame_data *fd, gint el, gchar* str) {
215   int    i;
216   size_t len, max_len;
217
218   if (el == COL_INFO)
219         max_len = COL_MAX_INFO_LEN;
220   else
221         max_len = COL_MAX_LEN;
222   
223   for (i = 0; i < fd->cinfo->num_cols; i++) {
224     if (fd->cinfo->fmt_matx[i][el]) {
225       if (fd->cinfo->col_data[i] != fd->cinfo->col_buf[i]) {
226         /* This was set with "col_set_str()"; copy the string they
227            set it to into the buffer, so we can append to it. */
228         strncpy(fd->cinfo->col_buf[i], fd->cinfo->col_data[i], max_len);
229         fd->cinfo->col_buf[i][max_len - 1] = '\0';
230       }
231       len = strlen(fd->cinfo->col_buf[i]);
232       strncat(fd->cinfo->col_buf[i], str, max_len - len);
233       fd->cinfo->col_buf[i][max_len - 1] = 0;
234       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
235     }
236   }
237 }
238
239 static void
240 col_set_abs_date_time(frame_data *fd, int col)
241 {
242   struct tm *tmp;
243   time_t then;
244
245   then = fd->abs_secs;
246   tmp = localtime(&then);
247   if (tmp != NULL) {
248     snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN,
249              "%04d-%02d-%02d %02d:%02d:%02d.%04ld",
250              tmp->tm_year + 1900,
251              tmp->tm_mon + 1,
252              tmp->tm_mday,
253              tmp->tm_hour,
254              tmp->tm_min,
255              tmp->tm_sec,
256              (long)fd->abs_usecs/100);
257   } else {
258     fd->cinfo->col_buf[col][0] = '\0';
259   }
260   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
261 }
262
263 static void
264 col_set_rel_time(frame_data *fd, int col)
265 {
266   display_signed_time(fd->cinfo->col_buf[col], COL_MAX_LEN,
267         fd->rel_secs, fd->rel_usecs, USECS);
268   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
269 }
270
271 static void
272 col_set_delta_time(frame_data *fd, int col)
273 {
274   display_signed_time(fd->cinfo->col_buf[col], COL_MAX_LEN,
275         fd->del_secs, fd->del_usecs, USECS);
276   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
277 }
278
279 /* To do: Add check_col checks to the col_add* routines */
280
281 static void
282 col_set_abs_time(frame_data *fd, int col)
283 {
284   struct tm *tmp;
285   time_t then;
286
287   then = fd->abs_secs;
288   tmp = localtime(&then);
289   if (tmp != NULL) {
290     snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
291              tmp->tm_hour,
292              tmp->tm_min,
293              tmp->tm_sec,
294              (long)fd->abs_usecs/100);
295   } else {
296     fd->cinfo->col_buf[col][0] = '\0';
297   }
298   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
299 }
300
301 /* Add "command-line-specified" time.
302    XXX - this is called from "file.c" when the user changes the time
303    format they want for "command-line-specified" time; it's a bit ugly
304    that we have to export it, but if we go to a CList-like widget that
305    invokes callbacks to get the text for the columns rather than
306    requiring us to stuff the text into the widget from outside, we
307    might be able to clean this up. */
308 void
309 col_set_cls_time(frame_data *fd, int col)
310 {
311   switch (timestamp_type) {
312     case ABSOLUTE:
313       col_set_abs_time(fd, col);
314       break;
315
316     case ABSOLUTE_WITH_DATE:
317       col_set_abs_date_time(fd, col);
318       break;
319
320     case RELATIVE:
321       col_set_rel_time(fd, col);
322       break;
323
324     case DELTA:
325       col_set_delta_time(fd, col);
326       break;
327   }
328 }
329
330 static void
331 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
332 {
333   guint32 ipv4_addr;
334   struct e_in6_addr ipv6_addr;
335   struct atalk_ddp_addr ddp_addr;
336   struct sna_fid_type_4_addr sna_fid_type_4_addr;
337
338   switch (addr->type) {
339
340   case AT_ETHER:
341     if (is_res)
342       strncpy(fd->cinfo->col_buf[col], get_ether_name(addr->data), COL_MAX_LEN);
343     else
344       strncpy(fd->cinfo->col_buf[col], ether_to_str(addr->data), COL_MAX_LEN);
345     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
346     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
347     break;
348
349   case AT_IPv4:
350     memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
351     if (is_res)
352       strncpy(fd->cinfo->col_buf[col], get_hostname(ipv4_addr), COL_MAX_LEN);
353     else
354       strncpy(fd->cinfo->col_buf[col], ip_to_str(addr->data), COL_MAX_LEN);
355     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
356     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
357     break;
358
359   case AT_IPv6:
360     memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
361     if (is_res)
362       strncpy(fd->cinfo->col_buf[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
363     else
364       strncpy(fd->cinfo->col_buf[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
365     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
366     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
367     break;
368
369   case AT_IPX:
370     strncpy(fd->cinfo->col_buf[col],
371       ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
372     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
373     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
374     break;
375
376   case AT_SNA:
377     switch (addr->len) {
378
379     case 1:
380       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X", addr->data[0]);
381       break;
382
383     case 2:
384       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X",
385         pntohs(&addr->data[0]));
386       break;
387
388     case SNA_FID_TYPE_4_ADDR_LEN:
389       memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
390       strncpy(fd->cinfo->col_buf[col],
391         sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
392       break;
393     }
394     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
395     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
396     break;
397
398   case AT_ATALK:
399     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
400     strncpy(fd->cinfo->col_buf[col], atalk_addr_to_str(&ddp_addr),
401       COL_MAX_LEN);
402     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
403     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
404     break;
405
406   case AT_VINES:
407     strncpy(fd->cinfo->col_buf[col], vines_addr_to_str(&addr->data[0]),
408       COL_MAX_LEN);
409     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
410     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
411     break;
412
413   case AT_OSI:
414     strncpy(fd->cinfo->col_buf[col], print_nsap_net(addr->data, addr->len),
415       COL_MAX_LEN);
416     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
417     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
418     break;
419
420   default:
421     break;
422   }
423 }
424
425 static void
426 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
427                 gboolean is_res)
428 {
429   switch (ptype) {
430
431   case PT_SCTP:
432     if (is_res)
433       strncpy(fd->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
434     else
435       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
436     break;
437     
438   case PT_TCP:
439     if (is_res)
440       strncpy(fd->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
441     else
442       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
443     break;
444
445   case PT_UDP:
446     if (is_res)
447       strncpy(fd->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
448     else
449       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
450     break;
451
452   default:
453     break;
454   }
455   fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
456   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
457 }
458
459 void
460 fill_in_columns(frame_data *fd, packet_info *pinfo)
461 {
462   int i;
463
464   for (i = 0; i < fd->cinfo->num_cols; i++) {
465     switch (fd->cinfo->col_fmt[i]) {
466
467     case COL_NUMBER:
468       snprintf(fd->cinfo->col_buf[i], COL_MAX_LEN, "%u", fd->num);
469       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
470       break;
471
472     case COL_CLS_TIME:
473       col_set_cls_time(fd, i);
474       break;
475
476     case COL_ABS_TIME:
477       col_set_abs_time(fd, i);
478       break;
479
480     case COL_ABS_DATE_TIME:
481       col_set_abs_date_time(fd, i);
482       break;
483
484     case COL_REL_TIME:
485       col_set_rel_time(fd, i);
486       break;
487
488     case COL_DELTA_TIME:
489       col_set_delta_time(fd, i);
490       break;
491
492     case COL_DEF_SRC:
493     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
494       col_set_addr(fd, i, &pinfo->src, TRUE);
495       break;
496
497     case COL_UNRES_SRC:
498       col_set_addr(fd, i, &pinfo->src, FALSE);
499       break;
500
501     case COL_DEF_DL_SRC:
502     case COL_RES_DL_SRC:
503       col_set_addr(fd, i, &pinfo->dl_src, TRUE);
504       break;
505
506     case COL_UNRES_DL_SRC:
507       col_set_addr(fd, i, &pinfo->dl_src, FALSE);
508       break;
509
510     case COL_DEF_NET_SRC:
511     case COL_RES_NET_SRC:
512       col_set_addr(fd, i, &pinfo->net_src, TRUE);
513       break;
514
515     case COL_UNRES_NET_SRC:
516       col_set_addr(fd, i, &pinfo->net_src, FALSE);
517       break;
518
519     case COL_DEF_DST:
520     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
521       col_set_addr(fd, i, &pinfo->dst, TRUE);
522       break;
523
524     case COL_UNRES_DST:
525       col_set_addr(fd, i, &pinfo->dst, FALSE);
526       break;
527
528     case COL_DEF_DL_DST:
529     case COL_RES_DL_DST:
530       col_set_addr(fd, i, &pinfo->dl_dst, TRUE);
531       break;
532
533     case COL_UNRES_DL_DST:
534       col_set_addr(fd, i, &pinfo->dl_dst, FALSE);
535       break;
536
537     case COL_DEF_NET_DST:
538     case COL_RES_NET_DST:
539       col_set_addr(fd, i, &pinfo->net_dst, TRUE);
540       break;
541
542     case COL_UNRES_NET_DST:
543       col_set_addr(fd, i, &pinfo->net_dst, FALSE);
544       break;
545
546     case COL_DEF_SRC_PORT:
547     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
548       col_set_port(fd, i, pinfo->ptype, pinfo->srcport, TRUE);
549       break;
550
551     case COL_UNRES_SRC_PORT:
552       col_set_port(fd, i, pinfo->ptype, pinfo->srcport, FALSE);
553       break;
554
555     case COL_DEF_DST_PORT:
556     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
557       col_set_port(fd, i, pinfo->ptype, pinfo->destport, TRUE);
558       break;
559
560     case COL_UNRES_DST_PORT:
561       col_set_port(fd, i, pinfo->ptype, pinfo->destport, FALSE);
562       break;
563
564     case COL_PROTOCOL:  /* currently done by dissectors */
565     case COL_INFO:      /* currently done by dissectors */
566       break;
567
568     case COL_PACKET_LENGTH:
569       snprintf(fd->cinfo->col_buf[i], COL_MAX_LEN, "%d", fd->pkt_len);
570       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
571       break;
572
573     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
574       break;
575     }
576   }
577 }
578         
579
580
581
582
583