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 HAVE_NETINET_IN_H
37 # include <netinet/in.h> /* needed for <arpa/inet.h> on some platforms */
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
48 #ifdef HAVE_WINSOCK2_H
49 #include <winsock2.h> /* needed to define AF_ values on Windows */
52 #ifdef NEED_INET_V6DEFS_H
53 # include "inet_v6defs.h"
57 #include "value_string.h"
58 #include "addr_resolv.h"
60 #include "atalk-utils.h"
61 #include "sna-utils.h"
62 #include "osi-utils.h"
63 #include <epan/dissectors/packet-mtp3.h>
68 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
69 * digits at at a time, with a specified punctuation character between
72 * If punct is '\0', no punctuation is applied (and thus
73 * the resulting string is (len-1) bytes shorter)
76 bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
79 int i = (int) len - 1;
82 /* At least one version of Apple's C compiler/linker is buggy, causing
83 a complaint from the linker about the "literal C string section"
84 not ending with '\0' if we initialize a 16-element "char" array with
85 a 16-character string, the fact that initializing such an array with
86 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
87 '\0' byte in the string nonwithstanding. */
88 static const gchar hex_digits[16] =
89 { '0', '1', '2', '3', '4', '5', '6', '7',
90 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
97 if (buflen < 3 || i < 0) {
101 buf=ep_alloc(buflen);
102 p = &buf[buflen - 1];
106 *--p = hex_digits[octet&0xF];
108 *--p = hex_digits[octet&0xF];
118 /* Wrapper for the most common case of asking
119 * for a string using a colon as the hex-digit separator.
122 remove this one later when every call has been converted to address_to_str()
125 ether_to_str(const guint8 *ad)
127 return bytestring_to_str(ad, 6, ':');
131 This function is very fast and this function is called a lot.
132 XXX update the address_to_str stuff to use this function.
135 ip_to_str(const guint8 *ad) {
139 ip_to_str_buf(ad, buf);
144 This function is very fast and this function is called a lot.
145 XXX update the address_to_str stuff to use this function.
147 static const char * const fast_strings[] = {
148 "0", "1", "2", "3", "4", "5", "6", "7",
149 "8", "9", "10", "11", "12", "13", "14", "15",
150 "16", "17", "18", "19", "20", "21", "22", "23",
151 "24", "25", "26", "27", "28", "29", "30", "31",
152 "32", "33", "34", "35", "36", "37", "38", "39",
153 "40", "41", "42", "43", "44", "45", "46", "47",
154 "48", "49", "50", "51", "52", "53", "54", "55",
155 "56", "57", "58", "59", "60", "61", "62", "63",
156 "64", "65", "66", "67", "68", "69", "70", "71",
157 "72", "73", "74", "75", "76", "77", "78", "79",
158 "80", "81", "82", "83", "84", "85", "86", "87",
159 "88", "89", "90", "91", "92", "93", "94", "95",
160 "96", "97", "98", "99", "100", "101", "102", "103",
161 "104", "105", "106", "107", "108", "109", "110", "111",
162 "112", "113", "114", "115", "116", "117", "118", "119",
163 "120", "121", "122", "123", "124", "125", "126", "127",
164 "128", "129", "130", "131", "132", "133", "134", "135",
165 "136", "137", "138", "139", "140", "141", "142", "143",
166 "144", "145", "146", "147", "148", "149", "150", "151",
167 "152", "153", "154", "155", "156", "157", "158", "159",
168 "160", "161", "162", "163", "164", "165", "166", "167",
169 "168", "169", "170", "171", "172", "173", "174", "175",
170 "176", "177", "178", "179", "180", "181", "182", "183",
171 "184", "185", "186", "187", "188", "189", "190", "191",
172 "192", "193", "194", "195", "196", "197", "198", "199",
173 "200", "201", "202", "203", "204", "205", "206", "207",
174 "208", "209", "210", "211", "212", "213", "214", "215",
175 "216", "217", "218", "219", "220", "221", "222", "223",
176 "224", "225", "226", "227", "228", "229", "230", "231",
177 "232", "233", "234", "235", "236", "237", "238", "239",
178 "240", "241", "242", "243", "244", "245", "246", "247",
179 "248", "249", "250", "251", "252", "253", "254", "255"
182 ip_to_str_buf(const guint8 *ad, gchar *buf)
184 register gchar const *p;
185 register gchar *b=buf;
187 p=fast_strings[*ad++];
194 p=fast_strings[*ad++];
201 p=fast_strings[*ad++];
218 remove this one later when every call has been converted to address_to_str()
221 ip6_to_str(const struct e_in6_addr *ad) {
222 #ifndef INET6_ADDRSTRLEN
223 #define INET6_ADDRSTRLEN 46
227 str=ep_alloc(INET6_ADDRSTRLEN+1);
229 ip6_to_str_buf(ad, str);
234 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
236 inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
240 ipx_addr_to_str(guint32 net, const guint8 *ad)
245 buf=ep_alloc(8+1+MAXNAMELEN+1); /* 8 digits, 1 period, NAME, 1 null */
246 name = get_ether_name_if_known(ad);
249 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net), name);
252 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net),
253 bytestring_to_str(ad, 6, '\0'));
259 ipxnet_to_string(const guint8 *ad)
261 guint32 addr = pntohl(ad);
262 return ipxnet_to_str_punct(addr, ' ');
266 ipxnet_to_str_punct(const guint32 ad, char punct)
272 /* At least one version of Apple's C compiler/linker is buggy, causing
273 a complaint from the linker about the "literal C string section"
274 not ending with '\0' if we initialize a 16-element "char" array with
275 a 16-character string, the fact that initializing such an array with
276 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
277 '\0' byte in the string nonwithstanding. */
278 static const gchar hex_digits[16] =
279 { '0', '1', '2', '3', '4', '5', '6', '7',
280 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
281 static const guint32 octet_mask[4] =
282 { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
289 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
290 *--p = hex_digits[octet&0xF];
292 *--p = hex_digits[octet&0xF];
303 vines_addr_to_str(const guint8 *addrp)
309 vines_addr_to_str_buf(addrp, buf, 214);
314 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
316 g_snprintf(buf, buf_len, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
319 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
320 #define COMMA(do_it) ((do_it) ? ", " : "")
323 * Maximum length of a string showing days/hours/minutes/seconds.
324 * (Does not include the terminating '\0'.)
325 * Includes space for a '-' sign for any negative compunents.
327 #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
330 * Convert a value in seconds and fractions of a second to a string,
331 * giving time in days, hours, minutes, and seconds, and put the result
333 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
335 * If time is negative, add a '-' to all non-null components.
338 time_secs_to_str_buf(gint32 time, guint32 frac, gboolean is_nsecs,
339 gchar *buf, int buf_len)
342 int hours, mins, secs;
343 const gchar *msign = "";
344 gboolean do_comma = FALSE;
351 if(time<0){ /* We've overflowed. */
352 g_snprintf(buf, buf_len, "Unable to cope with time value %d", time);
363 /* This would probably be cleaner if we used GStrings instead. */
366 p += g_snprintf(p, buf_len, "%s%u day%s", time?msign:"", time, PLURALIZE(time));
370 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u hour%s", COMMA(do_comma), hours?msign:"", hours, PLURALIZE(hours));
374 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u minute%s", COMMA(do_comma), mins?msign:"", mins, PLURALIZE(mins));
377 if (secs != 0 || frac != 0) {
380 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
382 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
384 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
389 time_secs_to_str(gint32 time)
393 buf=ep_alloc(TIME_SECS_LEN+1);
396 g_snprintf(buf, TIME_SECS_LEN+1, "0 time");
400 time_secs_to_str_buf(time, 0, FALSE, buf, TIME_SECS_LEN+1);
405 time_msecs_to_str(gint32 time)
410 buf=ep_alloc(TIME_SECS_LEN+1+3+1);
413 g_snprintf(buf, TIME_SECS_LEN+1+3+1, "0 time");
418 /* oops we got passed a negative time */
428 time_secs_to_str_buf(time, msecs, FALSE, buf, TIME_SECS_LEN+1+3+1);
432 static const char *mon_names[12] = {
448 abs_time_to_str(nstime_t *abs_time)
453 buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1+9+1);
455 tmp = localtime(&abs_time->secs);
457 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1+9+1,
458 "%s %2d, %d %02d:%02d:%02d.%09ld",
459 mon_names[tmp->tm_mon],
465 (long)abs_time->nsecs);
467 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1+9+1);
472 abs_time_secs_to_str(time_t abs_time)
477 buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1);
479 tmp = localtime(&abs_time);
481 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1,
482 "%s %2d, %d %02d:%02d:%02d",
483 mon_names[tmp->tm_mon],
490 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1);
495 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
500 /* If the fractional part of the time stamp is negative,
501 print its absolute value and, if the seconds part isn't
502 (the seconds part should be zero in that case), stick
503 a "-" in front of the entire time stamp. */
513 g_snprintf(buf, buflen, "%s%d", sign, sec);
517 g_snprintf(buf, buflen, "%s%d.%01d", sign, sec, frac);
521 g_snprintf(buf, buflen, "%s%d.%02d", sign, sec, frac);
525 g_snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
529 g_snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
533 g_snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
539 * Display a relative time as days/hours/minutes/seconds.
542 rel_time_to_str(nstime_t *rel_time)
550 buf=ep_alloc(1+TIME_SECS_LEN+1+6+1);
553 /* If the nanoseconds part of the time stamp is negative,
554 print its absolute value and, if the seconds part isn't
555 (the seconds part should be zero in that case), stick
556 a "-" in front of the entire time stamp. */
558 time = rel_time->secs;
559 nsec = rel_time->nsecs;
560 if (time == 0 && nsec == 0) {
561 g_snprintf(buf, 1+TIME_SECS_LEN+1+6+1, "0.000000000 seconds");
569 * We assume here that "rel_time->secs" is negative
570 * or zero; if it's not, the time stamp is bogus,
571 * with a positive seconds and negative microseconds.
573 time = -rel_time->secs;
576 time_secs_to_str_buf(time, nsec, TRUE, p, 1+TIME_SECS_LEN+1+6+1);
580 #define REL_TIME_SECS_LEN (1+10+1+9+1)
583 * Display a relative time as seconds.
586 rel_time_to_secs_str(nstime_t *rel_time)
590 buf=ep_alloc(REL_TIME_SECS_LEN);
592 display_signed_time(buf, REL_TIME_SECS_LEN, rel_time->secs,
593 rel_time->nsecs, NSECS);
599 remove this one later when every call has been converted to address_to_str()
602 fc_to_str(const guint8 *ad)
604 return bytestring_to_str (ad, 3, '.');
607 /* FC Network Header Network Address Authority Identifiers */
609 #define FC_NH_NAA_IEEE 1 /* IEEE 802.1a */
610 #define FC_NH_NAA_IEEE_E 2 /* IEEE Exteneded */
611 #define FC_NH_NAA_LOCAL 3
612 #define FC_NH_NAA_IP 4 /* 32-bit IP address */
613 #define FC_NH_NAA_IEEE_R 5 /* IEEE Registered */
614 #define FC_NH_NAA_IEEE_R_E 6 /* IEEE Registered Exteneded */
615 /* according to FC-PH 3 draft these are now reclaimed and reserved */
616 #define FC_NH_NAA_CCITT_INDV 12 /* CCITT 60 bit individual address */
617 #define FC_NH_NAA_CCITT_GRP 14 /* CCITT 60 bit group address */
620 fcwwn_to_str (const guint8 *ad)
626 if (ad == NULL) return NULL;
628 ethstr=ep_alloc(512);
630 fmt = (ad[0] & 0xF0) >> 4;
635 case FC_NH_NAA_IEEE_E:
636 memcpy (oui, &ad[2], 6);
637 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
638 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
639 get_manuf_name (oui));
642 case FC_NH_NAA_IEEE_R:
643 oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
644 oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
645 oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
646 oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
647 oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
648 oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
650 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
651 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
652 get_manuf_name (oui));
656 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
657 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
663 /* Generate, into "buf", a string showing the bits of a bitfield.
664 Return a pointer to the character after that string. */
665 /*XXX this needs a buf_len check */
667 other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
675 bit = 1 << (width - 1);
678 /* This bit is part of the field. Show its value. */
684 /* This bit is not part of the field. */
699 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
703 p = other_decode_bitfield_value(buf, val, mask, width);
709 /* Generate a string describing a Boolean bitfield (a one-bit field that
710 says something is either true of false). */
712 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
713 const char *truedesc, const char *falsedesc)
718 buf=ep_alloc(1025); /* is this a bit overkill? */
719 p = decode_bitfield_value(buf, val, mask, width);
723 strcpy(p, falsedesc);
727 /* Generate a string describing a numeric bitfield (an N-bit field whose
728 value is just a number). */
730 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
737 buf=ep_alloc(1025); /* isnt this a bit overkill? */
738 /* Compute the number of bits we have to shift the bitfield right
739 to extract its value. */
740 while ((mask & (1<<shift)) == 0)
743 p = decode_bitfield_value(buf, val, mask, width);
744 g_snprintf(p, 1025-(p-buf), fmt, (val & mask) >> shift);
749 /*XXX FIXME the code below may be called very very frequently in the future.
750 optimize it for speed and get rid of the slow sprintfs */
751 /* XXX - perhaps we should have individual address types register
752 a table of routines to do operations such as address-to-name translation,
753 address-to-string translation, and the like, and have this call them,
754 and also have an address-to-string-with-a-name routine */
755 /* XXX - use this, and that future address-to-string-with-a-name routine,
756 in "col_set_addr()"; it might also be useful to have address types
757 export the names of the source and destination address fields, so
758 that "col_set_addr()" need know nothing whatsoever about particular
760 /* convert an address struct into a printable string */
762 address_to_str(const address *addr)
767 address_to_str_buf(addr, str, 256);
772 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
774 struct atalk_ddp_addr ddp_addr;
778 g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", addr->data[0], addr->data[1], addr->data[2], addr->data[3], addr->data[4], addr->data[5]);
781 ip_to_str_buf(addr->data, buf);
784 inet_ntop(AF_INET6, addr->data, buf, INET6_ADDRSTRLEN);
787 g_snprintf(buf, buf_len, "%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]);
790 sna_fid_to_str_buf(addr, buf, buf_len);
793 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
794 atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
797 vines_addr_to_str_buf(addr->data, buf, buf_len);
800 print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
803 g_snprintf(buf, buf_len, "0x%02X", addr->data[0]);
806 g_snprintf(buf, buf_len, "%02x.%02x.%02x", addr->data[0], addr->data[1], addr->data[2]);
809 mtp3_addr_to_str_buf(addr->data, buf, buf_len);
812 g_snprintf(buf, buf_len, "%s", addr->data);
815 g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
816 addr->data[0], addr->data[1], addr->data[2], addr->data[3],
817 addr->data[4], addr->data[5], addr->data[6], addr->data[7]);
820 int copy_len = addr->len < buf_len ? addr->len : buf_len;
821 memmove(buf, addr->data, copy_len );
822 buf[copy_len] = '\0';
826 g_assert_not_reached();
830 gchar* oid_to_str(const guint8 *oid, gint oid_len) {
833 buf=ep_alloc(MAX_OID_STR_LEN);
834 return oid_to_str_buf(oid, oid_len, buf, MAX_OID_STR_LEN);
837 gchar* oid_to_str_buf(const guint8 *oid, gint oid_len, gchar *buf, int buf_len) {
844 for (i=0; i<oid_len; i++){
846 if ((bufp - buf) > (MAX_OID_STR_LEN - 16)) { /* "4294967295" + ".>>>" + '\0' + 1 */
847 bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".>>>");
851 bufp += g_snprintf(bufp, buf_len-(bufp-buf), "%u.%u", byte/40, byte%40);
854 value = (value << 7) | (byte & 0x7F);
858 bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".%u", value);
866 gchar* guid_to_str(const guint8 *guid) {
869 buf=ep_alloc(GUID_STR_LEN);
870 return guid_to_str_buf(guid, buf, GUID_STR_LEN);
873 gchar* guid_to_str_buf(const guint8 *guid, gchar *buf, int buf_len) {
874 g_snprintf(buf, buf_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
875 guid[0], guid[1], guid[2], guid[3],
879 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);