2 * Routines for column utilities.
4 * $Id: column-utils.c,v 1.10 2002/01/11 08:21:00 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
36 #ifdef NEED_SNPRINTF_H
37 # include "snprintf.h"
40 #ifdef NEED_INET_V6DEFS_H
41 # include "inet_v6defs.h"
44 #include "column-utils.h"
45 #include "timestamp.h"
46 #include "sna-utils.h"
47 #include "atalk-utils.h"
49 #include "packet_info.h"
52 #include "ipv6-utils.h"
53 #include "osi-utils.h"
55 /* Allocate all the data structures for constructing column data, given
56 the number of columns. */
58 col_init(column_info *col_info, gint num_cols)
60 col_info->num_cols = num_cols;
61 col_info->col_fmt = (gint *) g_malloc(sizeof(gint) * num_cols);
62 col_info->fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * num_cols);
63 col_info->col_width = (gint *) g_malloc(sizeof(gint) * num_cols);
64 col_info->col_title = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
65 col_info->col_data = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
66 col_info->col_buf = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
67 col_info->col_expr = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
68 col_info->col_expr_val = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
73 * This function does not appear to be used anywhere...
76 col_get_writable(column_info *cinfo)
78 return (cinfo ? cinfo->writable : FALSE);
83 col_set_writable(column_info *cinfo, gboolean writable)
86 cinfo->writable = writable;
89 /* Checks to see if a particular packet information element is needed for
92 check_col(column_info *cinfo, gint el) {
95 if (cinfo && cinfo->writable) {
96 for (i = 0; i < cinfo->num_cols; i++) {
97 if (cinfo->fmt_matx[i][el])
106 /* Use this to clear out a column, especially if you're going to be
107 appending to it later; at least on some platforms, it's more
108 efficient than using "col_add_str()" with a null string, and
109 more efficient than "col_set_str()" with a null string if you
110 later append to it, as the later append will cause a string
113 col_clear(column_info *cinfo, gint el) {
116 for (i = 0; i < cinfo->num_cols; i++) {
117 if (cinfo->fmt_matx[i][el]) {
118 cinfo->col_buf[i][0] = 0;
119 cinfo->col_data[i] = cinfo->col_buf[i];
120 cinfo->col_expr[i][0] = '\0';
121 cinfo->col_expr_val[i][0] = '\0';
126 /* Use this if "str" points to something that will stay around (and thus
127 needn't be copied). */
129 col_set_str(column_info *cinfo, gint el, gchar* str) {
132 for (i = 0; i < cinfo->num_cols; i++) {
133 if (cinfo->fmt_matx[i][el])
134 cinfo->col_data[i] = str;
138 /* Adds a vararg list to a packet info string. */
140 col_add_fstr(column_info *cinfo, gint el, gchar *format, ...) {
146 max_len = COL_MAX_INFO_LEN;
148 max_len = COL_MAX_LEN;
150 va_start(ap, format);
151 for (i = 0; i < cinfo->num_cols; i++) {
152 if (cinfo->fmt_matx[i][el]) {
153 vsnprintf(cinfo->col_buf[i], max_len, format, ap);
154 cinfo->col_data[i] = cinfo->col_buf[i];
159 /* Appends a vararg list to a packet info string. */
161 col_append_fstr(column_info *cinfo, gint el, gchar *format, ...) {
167 max_len = COL_MAX_INFO_LEN;
169 max_len = COL_MAX_LEN;
171 va_start(ap, format);
172 for (i = 0; i < cinfo->num_cols; i++) {
173 if (cinfo->fmt_matx[i][el]) {
174 if (cinfo->col_data[i] != cinfo->col_buf[i]) {
175 /* This was set with "col_set_str()"; copy the string they
176 set it to into the buffer, so we can append to it. */
177 strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);
178 cinfo->col_buf[i][max_len - 1] = '\0';
180 len = strlen(cinfo->col_buf[i]);
181 vsnprintf(&cinfo->col_buf[i][len], max_len - len, format, ap);
182 cinfo->col_data[i] = cinfo->col_buf[i];
187 /* Use this if "str" points to something that won't stay around (and
188 must thus be copied). */
190 col_add_str(column_info *cinfo, gint el, const gchar* str) {
195 max_len = COL_MAX_INFO_LEN;
197 max_len = COL_MAX_LEN;
199 for (i = 0; i < cinfo->num_cols; i++) {
200 if (cinfo->fmt_matx[i][el]) {
201 strncpy(cinfo->col_buf[i], str, max_len);
202 cinfo->col_buf[i][max_len - 1] = 0;
203 cinfo->col_data[i] = cinfo->col_buf[i];
209 col_append_str(column_info *cinfo, gint el, gchar* str) {
214 max_len = COL_MAX_INFO_LEN;
216 max_len = COL_MAX_LEN;
218 for (i = 0; i < cinfo->num_cols; i++) {
219 if (cinfo->fmt_matx[i][el]) {
220 if (cinfo->col_data[i] != cinfo->col_buf[i]) {
221 /* This was set with "col_set_str()"; copy the string they
222 set it to into the buffer, so we can append to it. */
223 strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);
224 cinfo->col_buf[i][max_len - 1] = '\0';
226 len = strlen(cinfo->col_buf[i]);
227 strncat(cinfo->col_buf[i], str, max_len - len);
228 cinfo->col_buf[i][max_len - 1] = 0;
229 cinfo->col_data[i] = cinfo->col_buf[i];
235 col_set_abs_date_time(frame_data *fd, column_info *cinfo, int col)
241 tmp = localtime(&then);
243 snprintf(cinfo->col_buf[col], COL_MAX_LEN,
244 "%04d-%02d-%02d %02d:%02d:%02d.%04ld",
251 (long)fd->abs_usecs/100);
253 cinfo->col_buf[col][0] = '\0';
255 cinfo->col_data[col] = cinfo->col_buf[col];
256 strcpy(cinfo->col_expr[col],"frame.time");
257 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
261 col_set_rel_time(frame_data *fd, column_info *cinfo, int col)
263 display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
264 fd->rel_secs, fd->rel_usecs, USECS);
265 cinfo->col_data[col] = cinfo->col_buf[col];
266 strcpy(cinfo->col_expr[col],"frame.time_relative");
267 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
271 col_set_delta_time(frame_data *fd, column_info *cinfo, int col)
273 display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
274 fd->del_secs, fd->del_usecs, USECS);
275 cinfo->col_data[col] = cinfo->col_buf[col];
276 strcpy(cinfo->col_expr[col],"frame.time_delta");
277 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
280 /* To do: Add check_col checks to the col_add* routines */
283 col_set_abs_time(frame_data *fd, column_info *cinfo, int col)
289 tmp = localtime(&then);
291 snprintf(cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
295 (long)fd->abs_usecs/100);
297 cinfo->col_buf[col][0] = '\0';
299 cinfo->col_data[col] = cinfo->col_buf[col];
300 strcpy(cinfo->col_expr[col],"frame.time");
301 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
304 /* Add "command-line-specified" time.
305 XXX - this is called from "file.c" when the user changes the time
306 format they want for "command-line-specified" time; it's a bit ugly
307 that we have to export it, but if we go to a CList-like widget that
308 invokes callbacks to get the text for the columns rather than
309 requiring us to stuff the text into the widget from outside, we
310 might be able to clean this up. */
312 col_set_cls_time(frame_data *fd, column_info *cinfo, int col)
314 switch (timestamp_type) {
316 col_set_abs_time(fd, cinfo, col);
319 case ABSOLUTE_WITH_DATE:
320 col_set_abs_date_time(fd, cinfo, col);
324 col_set_rel_time(fd, cinfo, col);
328 col_set_delta_time(fd, cinfo, col);
334 col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res,
338 struct e_in6_addr ipv6_addr;
339 struct atalk_ddp_addr ddp_addr;
340 struct sna_fid_type_4_addr sna_fid_type_4_addr;
342 pinfo->cinfo->col_expr[col][0] = '\0';
343 pinfo->cinfo->col_expr_val[col][0] = '\0';
344 switch (addr->type) {
348 strncpy(pinfo->cinfo->col_buf[col], get_ether_name(addr->data), COL_MAX_LEN);
350 strncpy(pinfo->cinfo->col_buf[col], ether_to_str(addr->data), COL_MAX_LEN);
351 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
352 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
354 strcpy(pinfo->cinfo->col_expr[col], "eth.src");
356 strcpy(pinfo->cinfo->col_expr[col], "eth.dst");
357 strncpy(pinfo->cinfo->col_expr_val[col], ether_to_str(addr->data), COL_MAX_LEN);
358 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
362 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
364 strncpy(pinfo->cinfo->col_buf[col], get_hostname(ipv4_addr), COL_MAX_LEN);
366 strncpy(pinfo->cinfo->col_buf[col], ip_to_str(addr->data), COL_MAX_LEN);
367 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
368 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
370 strcpy(pinfo->cinfo->col_expr[col], "ip.src");
372 strcpy(pinfo->cinfo->col_expr[col], "ip.dst");
373 strncpy(pinfo->cinfo->col_expr_val[col], ip_to_str(addr->data), COL_MAX_LEN);
374 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
378 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
380 strncpy(pinfo->cinfo->col_buf[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
382 strncpy(pinfo->cinfo->col_buf[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
383 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
384 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
386 strcpy(pinfo->cinfo->col_expr[col], "ipv6.src");
388 strcpy(pinfo->cinfo->col_expr[col], "ipv6.dst");
389 strncpy(pinfo->cinfo->col_expr_val[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
390 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
394 strncpy(pinfo->cinfo->col_buf[col],
395 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
396 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
397 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
399 strcpy(pinfo->cinfo->col_expr[col], "ipx.src");
401 strcpy(pinfo->cinfo->col_expr[col], "ipx.dst");
402 strcpy(pinfo->cinfo->col_expr_val[col],pinfo->cinfo->col_buf[col]);
409 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%04X", addr->data[0]);
413 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%04X",
414 pntohs(&addr->data[0]));
417 case SNA_FID_TYPE_4_ADDR_LEN:
418 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
419 strncpy(pinfo->cinfo->col_buf[col],
420 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
423 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
424 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
428 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
429 strncpy(pinfo->cinfo->col_buf[col], atalk_addr_to_str(&ddp_addr),
431 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
432 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
436 strncpy(pinfo->cinfo->col_buf[col], vines_addr_to_str(&addr->data[0]),
438 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
439 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
443 strncpy(pinfo->cinfo->col_buf[col], print_nsap_net(addr->data, addr->len),
445 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
446 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
455 col_set_port(packet_info *pinfo, int col, port_type ptype, guint32 port,
456 gboolean is_res, gboolean is_src)
458 pinfo->cinfo->col_expr[col][0] = '\0';
459 pinfo->cinfo->col_expr_val[col][0] = '\0';
464 strncpy(pinfo->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
466 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
471 strncpy(pinfo->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
473 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
475 strcpy(pinfo->cinfo->col_expr[col], "tcp.srcport");
477 strcpy(pinfo->cinfo->col_expr[col], "tcp.dstport");
478 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
479 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
484 strncpy(pinfo->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
486 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
488 strcpy(pinfo->cinfo->col_expr[col], "udp.srcport");
490 strcpy(pinfo->cinfo->col_expr[col], "udp.dstport");
491 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
492 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
498 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
499 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
503 fill_in_columns(packet_info *pinfo)
507 for (i = 0; i < pinfo->cinfo->num_cols; i++) {
508 switch (pinfo->cinfo->col_fmt[i]) {
511 snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->num);
512 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
513 strcpy(pinfo->cinfo->col_expr[i], "frame.number");
514 strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
518 col_set_cls_time(pinfo->fd, pinfo->cinfo, i);
522 col_set_abs_time(pinfo->fd, pinfo->cinfo, i);
525 case COL_ABS_DATE_TIME:
526 col_set_abs_date_time(pinfo->fd, pinfo->cinfo, i);
530 col_set_rel_time(pinfo->fd, pinfo->cinfo, i);
534 col_set_delta_time(pinfo->fd, pinfo->cinfo, i);
538 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
539 col_set_addr(pinfo, i, &pinfo->src, TRUE, TRUE);
543 col_set_addr(pinfo, i, &pinfo->src, FALSE, TRUE);
548 col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, TRUE);
551 case COL_UNRES_DL_SRC:
552 col_set_addr(pinfo, i, &pinfo->dl_src, FALSE, TRUE);
555 case COL_DEF_NET_SRC:
556 case COL_RES_NET_SRC:
557 col_set_addr(pinfo, i, &pinfo->net_src, TRUE, TRUE);
560 case COL_UNRES_NET_SRC:
561 col_set_addr(pinfo, i, &pinfo->net_src, FALSE, TRUE);
565 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
566 col_set_addr(pinfo, i, &pinfo->dst, TRUE, FALSE);
570 col_set_addr(pinfo, i, &pinfo->dst, FALSE, FALSE);
575 col_set_addr(pinfo, i, &pinfo->dl_dst, TRUE, FALSE);
578 case COL_UNRES_DL_DST:
579 col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, FALSE);
582 case COL_DEF_NET_DST:
583 case COL_RES_NET_DST:
584 col_set_addr(pinfo, i, &pinfo->net_dst, TRUE, FALSE);
587 case COL_UNRES_NET_DST:
588 col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, FALSE);
591 case COL_DEF_SRC_PORT:
592 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
593 col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, TRUE, TRUE);
596 case COL_UNRES_SRC_PORT:
597 col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, FALSE, TRUE);
600 case COL_DEF_DST_PORT:
601 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
602 col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, TRUE, FALSE);
605 case COL_UNRES_DST_PORT:
606 col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, FALSE, FALSE);
609 case COL_PROTOCOL: /* currently done by dissectors */
610 case COL_INFO: /* currently done by dissectors */
613 case COL_PACKET_LENGTH:
614 snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->pkt_len);
615 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
616 strcpy(pinfo->cinfo->col_expr[i], "frame.pkt_len");
617 strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
620 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
621 g_assert_not_reached();