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