2 * Routines for column utilities.
4 * $Id: column-utils.c,v 1.3 2001/04/02 10:38:26 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
45 #ifdef NEED_INET_V6DEFS_H
46 # include "inet_v6defs.h"
49 #include "column-utils.h"
50 #include "timestamp.h"
51 #include "sna-utils.h"
52 #include "atalk-utils.h"
54 #include "packet_info.h"
57 #include "ipv6-utils.h"
58 #include "osi-utils.h"
60 /* Allocate all the data structures for constructing column data, given
61 the number of columns. */
63 col_init(column_info *col_info, gint num_cols)
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);
75 * This function does not appear to be used anywhere...
78 col_get_writable(frame_data *fd)
82 return (fd->cinfo ? fd->cinfo->writable : FALSE);
93 col_set_writable(frame_data *fd, gboolean writable)
96 fd->cinfo->writable = writable;
100 /* Checks to see if a particular packet information element is needed for
103 check_col(frame_data *fd, gint el) {
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])
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
124 col_clear(frame_data *fd, gint el) {
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];
135 /* Use this if "str" points to something that will stay around (and thus
136 needn't be copied). */
138 col_set_str(frame_data *fd, gint el, gchar* str) {
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;
147 /* Adds a vararg list to a packet info string. */
149 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
155 max_len = COL_MAX_INFO_LEN;
157 max_len = COL_MAX_LEN;
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];
168 /* Appends a vararg list to a packet info string. */
170 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
176 max_len = COL_MAX_INFO_LEN;
178 max_len = COL_MAX_LEN;
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';
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];
196 /* Use this if "str" points to something that won't stay around (and
197 must thus be copied). */
199 col_add_str(frame_data *fd, gint el, const gchar* str) {
204 max_len = COL_MAX_INFO_LEN;
206 max_len = COL_MAX_LEN;
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];
218 col_append_str(frame_data *fd, gint el, gchar* str) {
223 max_len = COL_MAX_INFO_LEN;
225 max_len = COL_MAX_LEN;
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';
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];
244 col_set_abs_date_time(frame_data *fd, int col)
250 tmp = localtime(&then);
251 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN,
252 "%04d-%02d-%02d %02d:%02d:%02d.%04ld",
259 (long)fd->abs_usecs/100);
260 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
264 col_set_rel_time(frame_data *fd, int col)
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];
272 col_set_delta_time(frame_data *fd, int col)
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];
279 /* To do: Add check_col checks to the col_add* routines */
282 col_set_abs_time(frame_data *fd, int col)
288 tmp = localtime(&then);
289 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
293 (long)fd->abs_usecs/100);
294 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
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. */
305 col_set_cls_time(frame_data *fd, int col)
307 switch (timestamp_type) {
309 col_set_abs_time(fd, col);
312 case ABSOLUTE_WITH_DATE:
313 col_set_abs_date_time(fd, col);
317 col_set_rel_time(fd, col);
321 col_set_delta_time(fd, col);
327 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
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;
334 switch (addr->type) {
338 strncpy(fd->cinfo->col_buf[col], get_ether_name(addr->data), COL_MAX_LEN);
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];
346 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
348 strncpy(fd->cinfo->col_buf[col], get_hostname(ipv4_addr), COL_MAX_LEN);
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];
356 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
358 strncpy(fd->cinfo->col_buf[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
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];
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];
376 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X", addr->data[0]);
380 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X",
381 pntohs(&addr->data[0]));
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);
390 fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
391 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
395 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
396 strncpy(fd->cinfo->col_buf[col], atalk_addr_to_str(&ddp_addr),
398 fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
399 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
403 strncpy(fd->cinfo->col_buf[col], vines_addr_to_str(&addr->data[0]),
405 fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
406 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
410 strncpy(fd->cinfo->col_buf[col], print_nsap_net(addr->data, addr->len),
412 fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
413 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
422 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
429 strncpy(fd->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
431 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
436 strncpy(fd->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
438 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
443 strncpy(fd->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
445 snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
451 fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
452 fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
456 fill_in_columns(frame_data *fd)
460 for (i = 0; i < fd->cinfo->num_cols; i++) {
461 switch (fd->cinfo->col_fmt[i]) {
464 snprintf(fd->cinfo->col_buf[i], COL_MAX_LEN, "%u", fd->num);
465 fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
469 col_set_cls_time(fd, i);
473 col_set_abs_time(fd, i);
476 case COL_ABS_DATE_TIME:
477 col_set_abs_date_time(fd, i);
481 col_set_rel_time(fd, i);
485 col_set_delta_time(fd, i);
489 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
490 col_set_addr(fd, i, &pi.src, TRUE);
494 col_set_addr(fd, i, &pi.src, FALSE);
499 col_set_addr(fd, i, &pi.dl_src, TRUE);
502 case COL_UNRES_DL_SRC:
503 col_set_addr(fd, i, &pi.dl_src, FALSE);
506 case COL_DEF_NET_SRC:
507 case COL_RES_NET_SRC:
508 col_set_addr(fd, i, &pi.net_src, TRUE);
511 case COL_UNRES_NET_SRC:
512 col_set_addr(fd, i, &pi.net_src, FALSE);
516 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
517 col_set_addr(fd, i, &pi.dst, TRUE);
521 col_set_addr(fd, i, &pi.dst, FALSE);
526 col_set_addr(fd, i, &pi.dl_dst, TRUE);
529 case COL_UNRES_DL_DST:
530 col_set_addr(fd, i, &pi.dl_dst, FALSE);
533 case COL_DEF_NET_DST:
534 case COL_RES_NET_DST:
535 col_set_addr(fd, i, &pi.net_dst, TRUE);
538 case COL_UNRES_NET_DST:
539 col_set_addr(fd, i, &pi.net_dst, FALSE);
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);
547 case COL_UNRES_SRC_PORT:
548 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
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);
556 case COL_UNRES_DST_PORT:
557 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
560 case COL_PROTOCOL: /* currently done by dissectors */
561 case COL_INFO: /* currently done by dissectors */
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];
569 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */