2 * Routines for utilities to convert various other types to strings.
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> /* needed for <netinet/in.h> */
36 #ifdef NEED_SNPRINTF_H
37 # include "snprintf.h"
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h> /* needed for <arpa/inet.h> on some platforms */
44 #ifdef HAVE_ARPA_INET_H
45 #include <arpa/inet.h>
48 #ifdef HAVE_SYS_SOCKET_H
49 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
52 #ifdef HAVE_WINSOCK2_H
53 #include <winsock2.h> /* needed to define AF_ values on Windows */
56 #ifdef NEED_INET_V6DEFS_H
57 # include "inet_v6defs.h"
61 #include "value_string.h"
62 #include "addr_resolv.h"
64 #include "atalk-utils.h"
65 #include "sna-utils.h"
66 #include "osi-utils.h"
67 #include <epan/dissectors/packet-mtp3.h>
71 #define MAX_BYTESTRING_LEN 6
73 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
74 * digits at at a time, with a specified punctuation character between
75 * the bytes. The sequence of bytes must be no longer than
78 * If punct is '\0', no punctuation is applied (and thus
79 * the resulting string is (len-1) bytes shorter)
82 bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
83 static gchar str[3][MAX_BYTESTRING_LEN*3];
88 /* At least one version of Apple's C compiler/linker is buggy, causing
89 a complaint from the linker about the "literal C string section"
90 not ending with '\0' if we initialize a 16-element "char" array with
91 a 16-character string, the fact that initializing such an array with
92 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
93 '\0' byte in the string nonwithstanding. */
94 static const gchar hex_digits[16] =
95 { '0', '1', '2', '3', '4', '5', '6', '7',
96 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
98 g_assert(len > 0 && len <= MAX_BYTESTRING_LEN);
101 if (cur == &str[0][0]) {
103 } else if (cur == &str[1][0]) {
113 *--p = hex_digits[octet&0xF];
115 *--p = hex_digits[octet&0xF];
125 /* Wrapper for the most common case of asking
126 * for a string using a colon as the hex-digit separator.
129 remove this one later when every call has been converted to address_to_str()
132 ether_to_str(const guint8 *ad)
134 return bytestring_to_str(ad, 6, ':');
138 This function is very fast and this function is called a lot.
139 XXX update the address_to_str stuff to use this function.
142 ip_to_str(const guint8 *ad) {
143 static gchar str[4][16];
144 static int cur_idx=0;
151 cur=&str[cur_idx][0];
153 ip_to_str_buf(ad, cur);
158 This function is very fast and this function is called a lot.
159 XXX update the address_to_str stuff to use this function.
161 static const char * const fast_strings[] = {
162 "0", "1", "2", "3", "4", "5", "6", "7",
163 "8", "9", "10", "11", "12", "13", "14", "15",
164 "16", "17", "18", "19", "20", "21", "22", "23",
165 "24", "25", "26", "27", "28", "29", "30", "31",
166 "32", "33", "34", "35", "36", "37", "38", "39",
167 "40", "41", "42", "43", "44", "45", "46", "47",
168 "48", "49", "50", "51", "52", "53", "54", "55",
169 "56", "57", "58", "59", "60", "61", "62", "63",
170 "64", "65", "66", "67", "68", "69", "70", "71",
171 "72", "73", "74", "75", "76", "77", "78", "79",
172 "80", "81", "82", "83", "84", "85", "86", "87",
173 "88", "89", "90", "91", "92", "93", "94", "95",
174 "96", "97", "98", "99", "100", "101", "102", "103",
175 "104", "105", "106", "107", "108", "109", "110", "111",
176 "112", "113", "114", "115", "116", "117", "118", "119",
177 "120", "121", "122", "123", "124", "125", "126", "127",
178 "128", "129", "130", "131", "132", "133", "134", "135",
179 "136", "137", "138", "139", "140", "141", "142", "143",
180 "144", "145", "146", "147", "148", "149", "150", "151",
181 "152", "153", "154", "155", "156", "157", "158", "159",
182 "160", "161", "162", "163", "164", "165", "166", "167",
183 "168", "169", "170", "171", "172", "173", "174", "175",
184 "176", "177", "178", "179", "180", "181", "182", "183",
185 "184", "185", "186", "187", "188", "189", "190", "191",
186 "192", "193", "194", "195", "196", "197", "198", "199",
187 "200", "201", "202", "203", "204", "205", "206", "207",
188 "208", "209", "210", "211", "212", "213", "214", "215",
189 "216", "217", "218", "219", "220", "221", "222", "223",
190 "224", "225", "226", "227", "228", "229", "230", "231",
191 "232", "233", "234", "235", "236", "237", "238", "239",
192 "240", "241", "242", "243", "244", "245", "246", "247",
193 "248", "249", "250", "251", "252", "253", "254", "255"
196 ip_to_str_buf(const guint8 *ad, gchar *buf)
198 register gchar const *p;
199 register gchar *b=buf;
202 p=fast_strings[*ad++];
209 p=fast_strings[*ad++];
216 p=fast_strings[*ad++];
223 p=fast_strings[*ad++];
233 remove this one later when every call has been converted to address_to_str()
236 ip6_to_str(const struct e_in6_addr *ad) {
237 #ifndef INET6_ADDRSTRLEN
238 #define INET6_ADDRSTRLEN 46
241 static gchar *strp, str[4][INET6_ADDRSTRLEN];
249 ip6_to_str_buf(ad, strp);
254 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
256 inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
260 ipx_addr_to_str(guint32 net, const guint8 *ad)
262 static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
266 if (cur == &str[0][0]) {
268 } else if (cur == &str[1][0]) {
274 name = get_ether_name_if_known(ad);
277 sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
280 sprintf(cur, "%s.%s", get_ipxnet_name(net),
281 bytestring_to_str(ad, 6, '\0'));
287 ipxnet_to_string(const guint8 *ad)
289 guint32 addr = pntohl(ad);
290 return ipxnet_to_str_punct(addr, ' ');
294 ipxnet_to_str_punct(const guint32 ad, char punct)
296 static gchar str[3][12];
301 /* At least one version of Apple's C compiler/linker is buggy, causing
302 a complaint from the linker about the "literal C string section"
303 not ending with '\0' if we initialize a 16-element "char" array with
304 a 16-character string, the fact that initializing such an array with
305 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
306 '\0' byte in the string nonwithstanding. */
307 static const gchar hex_digits[16] =
308 { '0', '1', '2', '3', '4', '5', '6', '7',
309 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
310 static const guint32 octet_mask[4] =
311 { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
313 if (cur == &str[0][0]) {
315 } else if (cur == &str[1][0]) {
324 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
325 *--p = hex_digits[octet&0xF];
327 *--p = hex_digits[octet&0xF];
338 vines_addr_to_str(const guint8 *addrp)
340 static gchar str[3][214];
343 if (cur == &str[0][0]) {
345 } else if (cur == &str[1][0]) {
350 vines_addr_to_str_buf(addrp, cur);
355 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf)
357 sprintf(buf, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
360 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
361 #define COMMA(do_it) ((do_it) ? ", " : "")
364 * Maximum length of a string showing days/hours/minutes/seconds.
365 * (Does not include the terminating '\0'.)
367 #define TIME_SECS_LEN (8+1+4+2+2+5+2+2+7+2+2+7)
370 * Convert a value in seconds and fractions of a second to a string,
371 * giving time in days, hours, minutes, and seconds, and put the result
373 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
377 time_secs_to_str_buf(guint32 time, guint32 frac, gboolean is_nsecs,
381 int hours, mins, secs;
382 gboolean do_comma = FALSE;
393 sprintf(p, "%u day%s", time, PLURALIZE(time));
398 sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
403 sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
407 if (secs != 0 || frac != 0) {
410 sprintf(p, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
412 sprintf(p, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
414 sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
419 time_secs_to_str(guint32 time)
421 static gchar str[3][TIME_SECS_LEN+1];
424 if (cur == &str[0][0]) {
426 } else if (cur == &str[1][0]) {
433 sprintf(cur, "0 time");
437 time_secs_to_str_buf(time, 0, FALSE, cur);
442 time_msecs_to_str(guint32 time)
444 static gchar str[3][TIME_SECS_LEN+1+3+1];
448 if (cur == &str[0][0]) {
450 } else if (cur == &str[1][0]) {
457 sprintf(cur, "0 time");
464 time_secs_to_str_buf(time, msecs, FALSE, cur);
468 static const char *mon_names[12] = {
484 abs_time_to_str(nstime_t *abs_time)
488 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+9+1];
490 if (cur == &str[0][0]) {
492 } else if (cur == &str[1][0]) {
498 tmp = localtime(&abs_time->secs);
500 sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%09ld",
501 mon_names[tmp->tm_mon],
507 (long)abs_time->nsecs);
509 strncpy(cur, "Not representable", sizeof(str[0]));
514 abs_time_secs_to_str(time_t abs_time)
518 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1];
520 if (cur == &str[0][0]) {
522 } else if (cur == &str[1][0]) {
528 tmp = localtime(&abs_time);
530 sprintf(cur, "%s %2d, %d %02d:%02d:%02d",
531 mon_names[tmp->tm_mon],
538 strncpy(cur, "Not representable", sizeof(str[0]));
543 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
548 /* If the fractional part of the time stamp is negative,
549 print its absolute value and, if the seconds part isn't
550 (the seconds part should be zero in that case), stick
551 a "-" in front of the entire time stamp. */
561 snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
565 snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
569 snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
575 * Display a relative time as days/hours/minutes/seconds.
578 rel_time_to_str(nstime_t *rel_time)
581 static char str[3][1+TIME_SECS_LEN+1+6+1];
587 if (cur == &str[0][0]) {
589 } else if (cur == &str[1][0]) {
596 /* If the nanoseconds part of the time stamp is negative,
597 print its absolute value and, if the seconds part isn't
598 (the seconds part should be zero in that case), stick
599 a "-" in front of the entire time stamp. */
601 time = rel_time->secs;
602 nsec = rel_time->nsecs;
603 if (time == 0 && nsec == 0) {
604 sprintf(cur, "0.000000000 seconds");
612 * We assume here that "rel_time->secs" is negative
613 * or zero; if it's not, the time stamp is bogus,
614 * with a positive seconds and negative microseconds.
616 time = -rel_time->secs;
619 time_secs_to_str_buf(time, nsec, TRUE, p);
623 #define REL_TIME_SECS_LEN (1+10+1+9+1)
626 * Display a relative time as seconds.
629 rel_time_to_secs_str(nstime_t *rel_time)
632 static char str[3][REL_TIME_SECS_LEN];
634 if (cur == &str[0][0]) {
636 } else if (cur == &str[1][0]) {
642 display_signed_time(cur, REL_TIME_SECS_LEN, rel_time->secs,
643 rel_time->nsecs, NSECS);
649 remove this one later when every call has been converted to address_to_str()
652 fc_to_str(const guint8 *ad)
654 return bytestring_to_str (ad, 3, '.');
657 /* FC Network Header Network Address Authority Identifiers */
659 #define FC_NH_NAA_IEEE 1 /* IEEE 802.1a */
660 #define FC_NH_NAA_IEEE_E 2 /* IEEE Exteneded */
661 #define FC_NH_NAA_LOCAL 3
662 #define FC_NH_NAA_IP 4 /* 32-bit IP address */
663 #define FC_NH_NAA_IEEE_R 5 /* IEEE Registered */
664 #define FC_NH_NAA_IEEE_R_E 6 /* IEEE Registered Exteneded */
665 /* according to FC-PH 3 draft these are now reclaimed and reserved */
666 #define FC_NH_NAA_CCITT_INDV 12 /* CCITT 60 bit individual address */
667 #define FC_NH_NAA_CCITT_GRP 14 /* CCITT 60 bit group address */
670 fcwwn_to_str (const guint8 *ad)
674 static gchar ethstr[512];
676 if (ad == NULL) return NULL;
678 fmt = (ad[0] & 0xF0) >> 4;
683 case FC_NH_NAA_IEEE_E:
684 memcpy (oui, &ad[2], 6);
685 sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
686 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
687 get_manuf_name (oui));
690 case FC_NH_NAA_IEEE_R:
691 oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
692 oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
693 oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
694 oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
695 oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
696 oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
698 sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
699 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
700 get_manuf_name (oui));
704 sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
705 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
711 /* Generate, into "buf", a string showing the bits of a bitfield.
712 Return a pointer to the character after that string. */
714 other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
722 bit = 1 << (width - 1);
725 /* This bit is part of the field. Show its value. */
731 /* This bit is not part of the field. */
746 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
750 p = other_decode_bitfield_value(buf, val, mask, width);
756 /* Generate a string describing a Boolean bitfield (a one-bit field that
757 says something is either true of false). */
759 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
760 const char *truedesc, const char *falsedesc)
762 static char buf[1025];
765 p = decode_bitfield_value(buf, val, mask, width);
769 strcpy(p, falsedesc);
773 /* Generate a string describing a numeric bitfield (an N-bit field whose
774 value is just a number). */
776 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
779 static char buf[1025];
783 /* Compute the number of bits we have to shift the bitfield right
784 to extract its value. */
785 while ((mask & (1<<shift)) == 0)
788 p = decode_bitfield_value(buf, val, mask, width);
789 sprintf(p, fmt, (val & mask) >> shift);
794 /*XXX FIXME the code below may be called very very frequently in the future.
795 optimize it for speed and get rid of the slow sprintfs */
796 /* XXX - perhaps we should have individual address types register
797 a table of routines to do operations such as address-to-name translation,
798 address-to-string translation, and the like, and have this call them,
799 and also have an address-to-string-with-a-name routine */
800 /* XXX - use this, and that future address-to-string-with-a-name routine,
801 in "col_set_addr()"; it might also be useful to have address types
802 export the names of the source and destination address fields, so
803 that "col_set_addr()" need know nothing whatsoever about particular
805 /* convert an address struct into a printable string */
807 address_to_str(address *addr)
809 #ifndef INET6_ADDRSTRLEN
810 #define INET6_ADDRSTRLEN 46
813 static gchar *strp, str[16][INET6_ADDRSTRLEN];/* IPv6 is the largest one */
821 address_to_str_buf(addr, strp);
826 address_to_str_buf(address *addr, gchar *buf)
828 struct atalk_ddp_addr ddp_addr;
832 sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", addr->data[0], addr->data[1], addr->data[2], addr->data[3], addr->data[4], addr->data[5]);
835 ip_to_str_buf(addr->data, buf);
838 inet_ntop(AF_INET6, addr->data, buf, INET6_ADDRSTRLEN);
841 sprintf(buf, "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x", addr->data[0], addr->data[1], addr->data[2], addr->data[3], addr->data[4], addr->data[5], addr->data[6], addr->data[7], addr->data[8], addr->data[9]);
844 sna_fid_to_str_buf(addr, buf);
847 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
848 atalk_addr_to_str_buf(&ddp_addr, buf);
851 vines_addr_to_str_buf(addr->data, buf);
854 print_nsap_net_buf(addr->data, addr->len, buf);
857 sprintf(buf, "0x%02X", addr->data[0]);
860 sprintf(buf, "%02x.%02x.%02x", addr->data[0], addr->data[1], addr->data[2]);
863 mtp3_addr_to_str_buf(addr->data, buf);
866 sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
867 addr->data[0], addr->data[1], addr->data[2], addr->data[3],
868 addr->data[4], addr->data[5], addr->data[6], addr->data[7]);
871 g_assert_not_reached();