2 * Routines for column utilities.
4 * $Id: column-utils.c,v 1.28 2002/12/08 02:32:35 gerald 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 NEED_SNPRINTF_H
33 # include "snprintf.h"
36 #include "column-utils.h"
37 #include "timestamp.h"
38 #include "sna-utils.h"
39 #include "atalk-utils.h"
41 #include "packet_info.h"
44 #include "ipv6-utils.h"
45 #include "osi-utils.h"
47 /* Allocate all the data structures for constructing column data, given
48 the number of columns. */
50 col_init(column_info *col_info, gint num_cols)
52 col_info->num_cols = num_cols;
53 col_info->col_fmt = (gint *) g_malloc(sizeof(gint) * num_cols);
54 col_info->fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * num_cols);
55 col_info->col_width = (gint *) g_malloc(sizeof(gint) * num_cols);
56 col_info->col_title = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
57 col_info->col_data = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
58 col_info->col_buf = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
59 col_info->col_expr = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
60 col_info->col_expr_val = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
64 col_get_writable(column_info *cinfo)
66 return (cinfo ? cinfo->writable : FALSE);
70 col_set_writable(column_info *cinfo, gboolean writable)
73 cinfo->writable = writable;
76 /* Checks to see if a particular packet information element is needed for
79 check_col(column_info *cinfo, gint el) {
82 if (cinfo && cinfo->writable) {
83 for (i = 0; i < cinfo->num_cols; i++) {
84 if (cinfo->fmt_matx[i][el])
93 /* Use this to clear out a column, especially if you're going to be
94 appending to it later; at least on some platforms, it's more
95 efficient than using "col_add_str()" with a null string, and
96 more efficient than "col_set_str()" with a null string if you
97 later append to it, as the later append will cause a string
100 col_clear(column_info *cinfo, gint el) {
103 for (i = 0; i < cinfo->num_cols; i++) {
104 if (cinfo->fmt_matx[i][el]) {
105 cinfo->col_buf[i][0] = 0;
106 cinfo->col_data[i] = cinfo->col_buf[i];
107 cinfo->col_expr[i][0] = '\0';
108 cinfo->col_expr_val[i][0] = '\0';
113 /* Use this if "str" points to something that will stay around (and thus
114 needn't be copied). */
116 col_set_str(column_info *cinfo, gint el, gchar* str) {
119 for (i = 0; i < cinfo->num_cols; i++) {
120 if (cinfo->fmt_matx[i][el])
121 cinfo->col_data[i] = str;
125 /* Adds a vararg list to a packet info string. */
127 col_add_fstr(column_info *cinfo, gint el, const gchar *format, ...) {
133 max_len = COL_MAX_INFO_LEN;
135 max_len = COL_MAX_LEN;
137 va_start(ap, format);
138 for (i = 0; i < cinfo->num_cols; i++) {
139 if (cinfo->fmt_matx[i][el]) {
140 vsnprintf(cinfo->col_buf[i], max_len, format, ap);
141 cinfo->col_data[i] = cinfo->col_buf[i];
147 /* Appends a vararg list to a packet info string. */
149 col_append_fstr(column_info *cinfo, gint el, const 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 < cinfo->num_cols; i++) {
161 if (cinfo->fmt_matx[i][el]) {
162 if (cinfo->col_data[i] != cinfo->col_buf[i]) {
163 /* This was set with "col_set_str()"; copy the string they
164 set it to into the buffer, so we can append to it. */
165 strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);
166 cinfo->col_buf[i][max_len - 1] = '\0';
168 len = strlen(cinfo->col_buf[i]);
169 vsnprintf(&cinfo->col_buf[i][len], max_len - len, format, ap);
170 cinfo->col_data[i] = cinfo->col_buf[i];
176 /* Prepends a vararg list to a packet info string. */
177 #define COL_BUF_MAX_LEN (((COL_MAX_INFO_LEN) > (COL_MAX_LEN)) ? \
178 (COL_MAX_INFO_LEN) : (COL_MAX_LEN))
180 col_prepend_fstr(column_info *cinfo, gint el, const gchar *format, ...)
184 char orig_buf[COL_BUF_MAX_LEN];
189 max_len = COL_MAX_INFO_LEN;
191 max_len = COL_MAX_LEN;
193 va_start(ap, format);
194 for (i = 0; i < cinfo->num_cols; i++) {
195 if (cinfo->fmt_matx[i][el]) {
196 if (cinfo->col_data[i] != cinfo->col_buf[i]) {
197 /* This was set with "col_set_str()"; which is effectively const */
198 orig = cinfo->col_data[i];
201 strncpy(orig, cinfo->col_buf[i], max_len);
202 orig[max_len - 1] = '\0';
204 vsnprintf(cinfo->col_buf[i], max_len, format, ap);
205 strncat(cinfo->col_buf[i], orig, max_len);
206 cinfo->col_buf[i][max_len - 1] = '\0';
207 cinfo->col_data[i] = cinfo->col_buf[i];
213 /* Use this if "str" points to something that won't stay around (and
214 must thus be copied). */
216 col_add_str(column_info *cinfo, gint el, const gchar* str) {
221 max_len = COL_MAX_INFO_LEN;
223 max_len = COL_MAX_LEN;
225 for (i = 0; i < cinfo->num_cols; i++) {
226 if (cinfo->fmt_matx[i][el]) {
227 strncpy(cinfo->col_buf[i], str, max_len);
228 cinfo->col_buf[i][max_len - 1] = 0;
229 cinfo->col_data[i] = cinfo->col_buf[i];
235 col_append_str(column_info *cinfo, gint el, const gchar* str) {
240 max_len = COL_MAX_INFO_LEN;
242 max_len = COL_MAX_LEN;
244 for (i = 0; i < cinfo->num_cols; i++) {
245 if (cinfo->fmt_matx[i][el]) {
246 if (cinfo->col_data[i] != cinfo->col_buf[i]) {
247 /* This was set with "col_set_str()"; copy the string they
248 set it to into the buffer, so we can append to it. */
249 strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);
250 cinfo->col_buf[i][max_len - 1] = '\0';
252 len = strlen(cinfo->col_buf[i]);
253 strncat(cinfo->col_buf[i], str, max_len - len);
254 cinfo->col_buf[i][max_len - 1] = 0;
255 cinfo->col_data[i] = cinfo->col_buf[i];
261 col_set_abs_date_time(frame_data *fd, column_info *cinfo, int col)
267 tmp = localtime(&then);
269 snprintf(cinfo->col_buf[col], COL_MAX_LEN,
270 "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
277 (long)fd->abs_usecs);
279 cinfo->col_buf[col][0] = '\0';
281 cinfo->col_data[col] = cinfo->col_buf[col];
282 strcpy(cinfo->col_expr[col],"frame.time");
283 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
287 col_set_rel_time(frame_data *fd, column_info *cinfo, int col)
289 display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
290 fd->rel_secs, fd->rel_usecs, USECS);
291 cinfo->col_data[col] = cinfo->col_buf[col];
292 strcpy(cinfo->col_expr[col],"frame.time_relative");
293 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
297 col_set_delta_time(frame_data *fd, column_info *cinfo, int col)
299 display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
300 fd->del_secs, fd->del_usecs, USECS);
301 cinfo->col_data[col] = cinfo->col_buf[col];
302 strcpy(cinfo->col_expr[col],"frame.time_delta");
303 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
306 /* To do: Add check_col checks to the col_add* routines */
309 col_set_abs_time(frame_data *fd, column_info *cinfo, int col)
315 tmp = localtime(&then);
317 snprintf(cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%06ld",
321 (long)fd->abs_usecs);
323 cinfo->col_buf[col][0] = '\0';
325 cinfo->col_data[col] = cinfo->col_buf[col];
326 strcpy(cinfo->col_expr[col],"frame.time");
327 strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
330 /* Add "command-line-specified" time.
331 XXX - this is called from "file.c" when the user changes the time
332 format they want for "command-line-specified" time; it's a bit ugly
333 that we have to export it, but if we go to a CList-like widget that
334 invokes callbacks to get the text for the columns rather than
335 requiring us to stuff the text into the widget from outside, we
336 might be able to clean this up. */
338 col_set_cls_time(frame_data *fd, column_info *cinfo, int col)
340 switch (timestamp_type) {
342 col_set_abs_time(fd, cinfo, col);
345 case ABSOLUTE_WITH_DATE:
346 col_set_abs_date_time(fd, cinfo, col);
350 col_set_rel_time(fd, cinfo, col);
354 col_set_delta_time(fd, cinfo, col);
360 col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res,
364 struct e_in6_addr ipv6_addr;
365 struct atalk_ddp_addr ddp_addr;
366 struct sna_fid_type_4_addr sna_fid_type_4_addr;
370 pinfo->cinfo->col_expr[col][0] = '\0';
371 pinfo->cinfo->col_expr_val[col][0] = '\0';
372 switch (addr->type) {
376 strncpy(pinfo->cinfo->col_buf[col], get_ether_name(addr->data), COL_MAX_LEN);
378 strncpy(pinfo->cinfo->col_buf[col], ether_to_str(addr->data), COL_MAX_LEN);
379 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
380 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
382 strcpy(pinfo->cinfo->col_expr[col], "eth.src");
384 strcpy(pinfo->cinfo->col_expr[col], "eth.dst");
385 strncpy(pinfo->cinfo->col_expr_val[col], ether_to_str(addr->data), COL_MAX_LEN);
386 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
390 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
392 strncpy(pinfo->cinfo->col_buf[col], get_hostname(ipv4_addr), COL_MAX_LEN);
394 strncpy(pinfo->cinfo->col_buf[col], ip_to_str(addr->data), COL_MAX_LEN);
395 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
396 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
398 strcpy(pinfo->cinfo->col_expr[col], "ip.src");
400 strcpy(pinfo->cinfo->col_expr[col], "ip.dst");
401 strncpy(pinfo->cinfo->col_expr_val[col], ip_to_str(addr->data), COL_MAX_LEN);
402 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
406 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
408 strncpy(pinfo->cinfo->col_buf[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
410 strncpy(pinfo->cinfo->col_buf[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
411 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
412 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
414 strcpy(pinfo->cinfo->col_expr[col], "ipv6.src");
416 strcpy(pinfo->cinfo->col_expr[col], "ipv6.dst");
417 strncpy(pinfo->cinfo->col_expr_val[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
418 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
422 strncpy(pinfo->cinfo->col_buf[col],
423 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
424 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
425 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
432 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%04X", addr->data[0]);
436 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%04X",
437 pntohs(&addr->data[0]));
440 case SNA_FID_TYPE_4_ADDR_LEN:
441 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
442 strncpy(pinfo->cinfo->col_buf[col],
443 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
446 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
447 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
451 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
452 strncpy(pinfo->cinfo->col_buf[col], atalk_addr_to_str(&ddp_addr),
454 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
456 strcpy(pinfo->cinfo->col_expr[col], "ddp.src");
458 strcpy(pinfo->cinfo->col_expr[col], "ddp.dst");
459 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
460 strcpy(pinfo->cinfo->col_expr_val[col],pinfo->cinfo->col_buf[col]);
464 strncpy(pinfo->cinfo->col_buf[col], vines_addr_to_str(&addr->data[0]),
466 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
467 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
471 strncpy(pinfo->cinfo->col_buf[col], print_nsap_net(addr->data, addr->len),
473 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
474 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
478 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "0x%02X",
480 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
482 strcpy(pinfo->cinfo->col_expr[col], "arcnet.src");
484 strcpy(pinfo->cinfo->col_expr[col], "arcnet.dst");
485 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
486 strcpy(pinfo->cinfo->col_expr_val[col],pinfo->cinfo->col_buf[col]);
490 tmpfc = *((guint32 *)addr->data);
491 fcid = fc_to_str ((const guint8 *)&tmpfc);
493 strncpy (pinfo->cinfo->col_buf[col], fcid, COL_MAX_LEN);
494 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
495 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
504 col_set_port(packet_info *pinfo, int col, port_type ptype, guint32 port,
505 gboolean is_res, gboolean is_src)
507 pinfo->cinfo->col_expr[col][0] = '\0';
508 pinfo->cinfo->col_expr_val[col][0] = '\0';
513 strncpy(pinfo->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
515 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
520 strncpy(pinfo->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
522 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
524 strcpy(pinfo->cinfo->col_expr[col], "tcp.srcport");
526 strcpy(pinfo->cinfo->col_expr[col], "tcp.dstport");
527 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
528 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
533 strncpy(pinfo->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
535 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
537 strcpy(pinfo->cinfo->col_expr[col], "udp.srcport");
539 strcpy(pinfo->cinfo->col_expr[col], "udp.dstport");
540 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
541 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
546 strcpy(pinfo->cinfo->col_expr[col], "ddp.src_socket");
548 strcpy(pinfo->cinfo->col_expr[col], "ddp.dst_socket");
549 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
550 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
551 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
555 /* XXX - resolve IPX socket numbers */
556 snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "0x%04x", port);
558 strcpy(pinfo->cinfo->col_expr[col], "ipx.src.socket");
560 strcpy(pinfo->cinfo->col_expr[col], "ipx.dst.socket");
561 snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "0x%04x", port);
562 pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
568 pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
569 pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
573 fill_in_columns(packet_info *pinfo)
577 for (i = 0; i < pinfo->cinfo->num_cols; i++) {
578 switch (pinfo->cinfo->col_fmt[i]) {
581 snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->num);
582 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
583 strcpy(pinfo->cinfo->col_expr[i], "frame.number");
584 strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
588 col_set_cls_time(pinfo->fd, pinfo->cinfo, i);
592 col_set_abs_time(pinfo->fd, pinfo->cinfo, i);
595 case COL_ABS_DATE_TIME:
596 col_set_abs_date_time(pinfo->fd, pinfo->cinfo, i);
600 col_set_rel_time(pinfo->fd, pinfo->cinfo, i);
604 col_set_delta_time(pinfo->fd, pinfo->cinfo, i);
608 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
609 col_set_addr(pinfo, i, &pinfo->src, TRUE, TRUE);
613 col_set_addr(pinfo, i, &pinfo->src, FALSE, TRUE);
618 col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, TRUE);
621 case COL_UNRES_DL_SRC:
622 col_set_addr(pinfo, i, &pinfo->dl_src, FALSE, TRUE);
625 case COL_DEF_NET_SRC:
626 case COL_RES_NET_SRC:
627 col_set_addr(pinfo, i, &pinfo->net_src, TRUE, TRUE);
630 case COL_UNRES_NET_SRC:
631 col_set_addr(pinfo, i, &pinfo->net_src, FALSE, TRUE);
635 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
636 col_set_addr(pinfo, i, &pinfo->dst, TRUE, FALSE);
640 col_set_addr(pinfo, i, &pinfo->dst, FALSE, FALSE);
645 col_set_addr(pinfo, i, &pinfo->dl_dst, TRUE, FALSE);
648 case COL_UNRES_DL_DST:
649 col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, FALSE);
652 case COL_DEF_NET_DST:
653 case COL_RES_NET_DST:
654 col_set_addr(pinfo, i, &pinfo->net_dst, TRUE, FALSE);
657 case COL_UNRES_NET_DST:
658 col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, FALSE);
661 case COL_DEF_SRC_PORT:
662 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
663 col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, TRUE, TRUE);
666 case COL_UNRES_SRC_PORT:
667 col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, FALSE, TRUE);
670 case COL_DEF_DST_PORT:
671 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
672 col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, TRUE, FALSE);
675 case COL_UNRES_DST_PORT:
676 col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, FALSE, FALSE);
679 case COL_PROTOCOL: /* currently done by dissectors */
680 case COL_INFO: /* currently done by dissectors */
683 case COL_PACKET_LENGTH:
684 snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->pkt_len);
685 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
686 strcpy(pinfo->cinfo->col_expr[i], "frame.pkt_len");
687 strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
691 snprintf (pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->oxid);
692 pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
693 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
697 snprintf (pinfo->cinfo->col_buf[i], COL_MAX_LEN, "0x%x", pinfo->rxid);
698 pinfo->cinfo->col_buf[i][COL_MAX_LEN - 1] = '\0';
699 pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
702 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
703 g_assert_not_reached();