*
* $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h> /* needed for <netinet/in.h> */
-#endif
-
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h> /* needed for <arpa/inet.h> on some platforms */
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
+#include "config.h"
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h> /* needed to define AF_ values on UNIX */
-#endif
-
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h> /* needed to define AF_ values on Windows */
-#endif
-
-#ifdef NEED_INET_V6DEFS_H
-# include "inet_v6defs.h"
-#endif
-
-#include "to_str.h"
-#include "value_string.h"
-#include "addr_resolv.h"
-#include "pint.h"
-#include "atalk-utils.h"
-#include "sna-utils.h"
-#include "osi-utils.h"
-#include <epan/dissectors/packet-mtp3.h>
#include <stdio.h>
+#include <string.h>
#include <time.h>
+#include <glib.h>
-#define MAX_BYTESTRING_LEN 6
+#include "emem.h"
+#include "proto.h"
+#include "to_str.h"
+#include "strutil.h"
-/* Routine to convert a sequence of bytes to a hex string, one byte/two hex
- * digits at at a time, with a specified punctuation character between
- * the bytes. The sequence of bytes must be no longer than
- * MAX_BYTESTRING_LEN.
- *
- * If punct is '\0', no punctuation is applied (and thus
- * the resulting string is (len-1) bytes shorter)
+/*
+ * If a user _does_ pass in a too-small buffer, this is probably
+ * going to be too long to fit. However, even a partial string
+ * starting with "[Buf" should provide enough of a clue to be
+ * useful.
*/
-static gchar *
-bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
- static gchar str[3][MAX_BYTESTRING_LEN*3];
- static gchar *cur;
- gchar *p;
- int i;
- guint32 octet;
+#define BUF_TOO_SMALL_ERR "[Buffer too small]"
+
+static inline char
+octet_to_hex(guint8 oct)
+{
/* At least one version of Apple's C compiler/linker is buggy, causing
a complaint from the linker about the "literal C string section"
not ending with '\0' if we initialize a 16-element "char" array with
{ '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- g_assert(len > 0 && len <= MAX_BYTESTRING_LEN);
- len--;
+ return hex_digits[oct & 0xF];
+}
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
- p = &cur[18];
- *--p = '\0';
- i = len;
- for (;;) {
- octet = ad[i];
- *--p = hex_digits[octet&0xF];
- octet >>= 4;
- *--p = hex_digits[octet&0xF];
- if (i == 0)
- break;
- if (punct)
- *--p = punct;
- i--;
- }
- return p;
+static inline char *
+byte_to_hex(char *out, guint32 dword) {
+ *out++ = octet_to_hex(dword >> 4);
+ *out++ = octet_to_hex(dword);
+ return out;
}
-/* Wrapper for the most common case of asking
- * for a string using a colon as the hex-digit separator.
- */
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
-gchar *
-ether_to_str(const guint8 *ad)
-{
- return bytestring_to_str(ad, 6, ':');
+char *
+word_to_hex(char *out, guint16 word) {
+ out = byte_to_hex(out, word >> 8);
+ out = byte_to_hex(out, word);
+ return out;
}
-/*
- This function is very fast and this function is called a lot.
- XXX update the address_to_str stuff to use this function.
-*/
-gchar *
-ip_to_str(const guint8 *ad) {
- static gchar str[4][16];
- static guint32 cur_idx=0;
- gchar *cur;
+char *
+word_to_hex_npad(char *out, guint16 word) {
+ if (word >= 0x1000)
+ *out++ = octet_to_hex(word >> 12);
+ if (word >= 0x0100)
+ *out++ = octet_to_hex(word >> 8);
+ if (word >= 0x0010)
+ *out++ = octet_to_hex(word >> 4);
+ *out++ = octet_to_hex(word);
+ return out;
+}
- cur_idx++;
- if(cur_idx>3){
- cur_idx=0;
- }
- cur=&str[cur_idx][0];
+char *
+dword_to_hex(char *out, guint32 dword) {
+ out = byte_to_hex(out, dword >> 24);
+ out = byte_to_hex(out, dword >> 16);
+ out = byte_to_hex(out, dword >> 8);
+ out = byte_to_hex(out, dword);
+ return out;
+}
- ip_to_str_buf(ad, cur);
- return cur;
+char *
+dword_to_hex_punct(char *out, guint32 dword, char punct) {
+ out = byte_to_hex(out, dword >> 24);
+ *out++ = punct;
+ out = byte_to_hex(out, dword >> 16);
+ *out++ = punct;
+ out = byte_to_hex(out, dword >> 8);
+ *out++ = punct;
+ out = byte_to_hex(out, dword);
+ return out;
}
-/*
- This function is very fast and this function is called a lot.
- XXX update the address_to_str stuff to use this function.
-*/
-static const char * const fast_strings[] = {
-"0", "1", "2", "3", "4", "5", "6", "7",
-"8", "9", "10", "11", "12", "13", "14", "15",
-"16", "17", "18", "19", "20", "21", "22", "23",
-"24", "25", "26", "27", "28", "29", "30", "31",
-"32", "33", "34", "35", "36", "37", "38", "39",
-"40", "41", "42", "43", "44", "45", "46", "47",
-"48", "49", "50", "51", "52", "53", "54", "55",
-"56", "57", "58", "59", "60", "61", "62", "63",
-"64", "65", "66", "67", "68", "69", "70", "71",
-"72", "73", "74", "75", "76", "77", "78", "79",
-"80", "81", "82", "83", "84", "85", "86", "87",
-"88", "89", "90", "91", "92", "93", "94", "95",
-"96", "97", "98", "99", "100", "101", "102", "103",
-"104", "105", "106", "107", "108", "109", "110", "111",
-"112", "113", "114", "115", "116", "117", "118", "119",
-"120", "121", "122", "123", "124", "125", "126", "127",
-"128", "129", "130", "131", "132", "133", "134", "135",
-"136", "137", "138", "139", "140", "141", "142", "143",
-"144", "145", "146", "147", "148", "149", "150", "151",
-"152", "153", "154", "155", "156", "157", "158", "159",
-"160", "161", "162", "163", "164", "165", "166", "167",
-"168", "169", "170", "171", "172", "173", "174", "175",
-"176", "177", "178", "179", "180", "181", "182", "183",
-"184", "185", "186", "187", "188", "189", "190", "191",
-"192", "193", "194", "195", "196", "197", "198", "199",
-"200", "201", "202", "203", "204", "205", "206", "207",
-"208", "209", "210", "211", "212", "213", "214", "215",
-"216", "217", "218", "219", "220", "221", "222", "223",
-"224", "225", "226", "227", "228", "229", "230", "231",
-"232", "233", "234", "235", "236", "237", "238", "239",
-"240", "241", "242", "243", "244", "245", "246", "247",
-"248", "249", "250", "251", "252", "253", "254", "255"
-};
-void
-ip_to_str_buf(const guint8 *ad, gchar *buf)
-{
- register gchar const *p;
- register gchar *b=buf;
+/*
+ * This does *not* null-terminate the string. It returns a pointer
+ * to the position in the string following the last character it
+ * puts there, so that the caller can either put the null terminator
+ * in or can append more stuff to the buffer.
+ *
+ * There needs to be at least len * 2 bytes left in the buffer.
+ */
+char *
+bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
+ guint32 i;
- p=fast_strings[*ad++];
- do {
- *b++=*p;
- p++;
- } while(*p);
- *b++='.';
+ if (!ad)
+ REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
- p=fast_strings[*ad++];
- do {
- *b++=*p;
- p++;
- } while(*p);
- *b++='.';
+ for (i = 0; i < len; i++)
+ out = byte_to_hex(out, ad[i]);
+ return out;
+}
- p=fast_strings[*ad++];
- do {
- *b++=*p;
- p++;
- } while(*p);
- *b++='.';
+/*
+ * This does *not* null-terminate the string. It returns a pointer
+ * to the position in the string following the last character it
+ * puts there, so that the caller can either put the null terminator
+ * in or can append more stuff to the buffer.
+ *
+ * There needs to be at least len * 3 - 1 bytes left in the buffer.
+ */
+char *
+bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
+ guint32 i;
- p=fast_strings[*ad];
- do {
- *b++=*p;
- p++;
- } while(*p);
- *b=0;
+ if (!ad)
+ REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
+
+ out = byte_to_hex(out, ad[0]);
+ for (i = 1; i < len; i++) {
+ *out++ = punct;
+ out = byte_to_hex(out, ad[i]);
+ }
+ return out;
}
+/* Routine to convert a sequence of bytes to a hex string, one byte/two hex
+ * digits at at a time, with a specified punctuation character between
+ * the bytes.
+ *
+ * If punct is '\0', no punctuation is applied (and thus
+ * the resulting string is (len-1) bytes shorter)
+ */
+const gchar *
+bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
+ gchar *buf;
+ size_t buflen;
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
-gchar *
-ip6_to_str(const struct e_in6_addr *ad) {
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
- static int i=0;
- static gchar *strp, str[4][INET6_ADDRSTRLEN];
+ if (!ad)
+ REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
- i++;
- if(i>=4){
- i=0;
- }
- strp=str[i];
+ /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
+ if ( ((int) len) < 0)
+ return "";
- ip6_to_str_buf(ad, strp);
- return strp;
-}
+ if (!len)
+ return "";
-void
-ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
-{
- inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
-}
+ if (punct)
+ buflen=len*3;
+ else
+ buflen=len*2 + 1;
-gchar*
-ipx_addr_to_str(guint32 net, const guint8 *ad)
-{
- static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
- static gchar *cur;
- char *name;
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
+ buf=(gchar *)ep_alloc(buflen);
- name = get_ether_name_if_known(ad);
+ if (punct)
+ bytes_to_hexstr_punct(buf, ad, len, punct);
+ else
+ bytes_to_hexstr(buf, ad, len);
- if (name) {
- sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
- }
- else {
- sprintf(cur, "%s.%s", get_ipxnet_name(net),
- bytestring_to_str(ad, 6, '\0'));
- }
- return cur;
+ buf[buflen-1] = '\0';
+ return buf;
}
-gchar*
-ipxnet_to_string(const guint8 *ad)
-{
- guint32 addr = pntohl(ad);
- return ipxnet_to_str_punct(addr, ' ');
-}
+/* Max string length for displaying byte string. */
+#define MAX_BYTE_STR_LEN 48
gchar *
-ipxnet_to_str_punct(const guint32 ad, char punct)
-{
- static gchar str[3][12];
- static gchar *cur;
- gchar *p;
- int i;
- guint32 octet;
- /* At least one version of Apple's C compiler/linker is buggy, causing
- a complaint from the linker about the "literal C string section"
- not ending with '\0' if we initialize a 16-element "char" array with
- a 16-character string, the fact that initializing such an array with
- such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
- '\0' byte in the string nonwithstanding. */
- static const gchar hex_digits[16] =
- { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- static const guint32 octet_mask[4] =
- { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
- p = &cur[12];
- *--p = '\0';
- i = 3;
- for (;;) {
- octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
- *--p = hex_digits[octet&0xF];
- octet >>= 4;
- *--p = hex_digits[octet&0xF];
- if (i == 0)
- break;
- if (punct)
- *--p = punct;
- i--;
+bytes_to_str(const guint8 *bd, int bd_len) {
+ gchar *cur;
+ gchar *cur_ptr;
+ int truncated = 0;
+
+ if (!bd)
+ REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
+
+ cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
+ if (bd_len <= 0) { cur[0] = '\0'; return cur; }
+
+ if (bd_len > MAX_BYTE_STR_LEN/2) { /* bd_len > 24 */
+ truncated = 1;
+ bd_len = MAX_BYTE_STR_LEN/2;
}
- return p;
+
+ cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */
+
+ if (truncated)
+ cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
+
+ *cur_ptr = '\0'; /* 1 byte */
+ return cur;
}
+/* Turn an array of bytes into a string showing the bytes in hex with
+ * punct as a bytes separator.
+ */
gchar *
-vines_addr_to_str(const guint8 *addrp)
-{
- static gchar str[3][214];
- static gchar *cur;
+bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
+ gchar *cur;
+ gchar *cur_ptr;
+ int truncated = 0;
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
+ if (!punct)
+ return bytes_to_str(bd, bd_len);
+
+ cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
+ if (bd_len <= 0) { cur[0] = '\0'; return cur; }
+
+ if (bd_len > MAX_BYTE_STR_LEN/3) { /* bd_len > 16 */
+ truncated = 1;
+ bd_len = MAX_BYTE_STR_LEN/3;
}
- vines_addr_to_str_buf(addrp, cur);
+
+ cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
+
+ if (truncated) {
+ *cur_ptr++ = punct; /* 1 byte */
+ cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
+ }
+
+ *cur_ptr = '\0';
return cur;
}
+static int
+guint32_to_str_buf_len(const guint32 u) {
+ if (u >= 1000000000)return 10;
+ if (u >= 100000000) return 9;
+ if (u >= 10000000) return 8;
+ if (u >= 1000000) return 7;
+ if (u >= 100000) return 6;
+ if (u >= 10000) return 5;
+ if (u >= 1000) return 4;
+ if (u >= 100) return 3;
+ if (u >= 10) return 2;
+
+ return 1;
+}
+
+static const char fast_strings[][4] = {
+"0", "1", "2", "3", "4", "5", "6", "7",
+"8", "9", "10", "11", "12", "13", "14", "15",
+"16", "17", "18", "19", "20", "21", "22", "23",
+"24", "25", "26", "27", "28", "29", "30", "31",
+"32", "33", "34", "35", "36", "37", "38", "39",
+"40", "41", "42", "43", "44", "45", "46", "47",
+"48", "49", "50", "51", "52", "53", "54", "55",
+"56", "57", "58", "59", "60", "61", "62", "63",
+"64", "65", "66", "67", "68", "69", "70", "71",
+"72", "73", "74", "75", "76", "77", "78", "79",
+"80", "81", "82", "83", "84", "85", "86", "87",
+"88", "89", "90", "91", "92", "93", "94", "95",
+"96", "97", "98", "99", "100", "101", "102", "103",
+"104", "105", "106", "107", "108", "109", "110", "111",
+"112", "113", "114", "115", "116", "117", "118", "119",
+"120", "121", "122", "123", "124", "125", "126", "127",
+"128", "129", "130", "131", "132", "133", "134", "135",
+"136", "137", "138", "139", "140", "141", "142", "143",
+"144", "145", "146", "147", "148", "149", "150", "151",
+"152", "153", "154", "155", "156", "157", "158", "159",
+"160", "161", "162", "163", "164", "165", "166", "167",
+"168", "169", "170", "171", "172", "173", "174", "175",
+"176", "177", "178", "179", "180", "181", "182", "183",
+"184", "185", "186", "187", "188", "189", "190", "191",
+"192", "193", "194", "195", "196", "197", "198", "199",
+"200", "201", "202", "203", "204", "205", "206", "207",
+"208", "209", "210", "211", "212", "213", "214", "215",
+"216", "217", "218", "219", "220", "221", "222", "223",
+"224", "225", "226", "227", "228", "229", "230", "231",
+"232", "233", "234", "235", "236", "237", "238", "239",
+"240", "241", "242", "243", "244", "245", "246", "247",
+"248", "249", "250", "251", "252", "253", "254", "255"
+};
+
+char *uint_to_str_back(char *ptr, guint32 value);
+
void
-vines_addr_to_str_buf(const guint8 *addrp, gchar *buf)
-{
- sprintf(buf, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
+guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
+ int str_len = guint32_to_str_buf_len(u)+1;
+
+ gchar *bp = &buf[str_len];
+
+ if (buf_len < str_len) {
+ g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
+ return;
+ }
+
+ *--bp = '\0';
+
+ uint_to_str_back(bp, u);
+}
+
+gchar *
+guint32_to_str(const guint32 u) {
+ int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
+
+ gchar *bp = (gchar *)ep_alloc(str_len);
+ guint32_to_str_buf(u, bp, str_len);
+
+ return bp;
}
#define PLURALIZE(n) (((n) > 1) ? "s" : "")
/*
* Maximum length of a string showing days/hours/minutes/seconds.
* (Does not include the terminating '\0'.)
- * Includes space for a '-' sign for any negative compunents.
+ * Includes space for a '-' sign for any negative components.
+ * -12345 days, 12 hours, 12 minutes, 12.123 seconds
*/
#define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
* If time is negative, add a '-' to all non-null components.
*/
static void
-time_secs_to_str_buf(gint32 time, guint32 frac, gboolean is_nsecs,
- gchar *buf)
+time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
+ emem_strbuf_t *buf)
{
- static gchar *p;
int hours, mins, secs;
- gchar *msign = "";
+ const gchar *msign = "";
gboolean do_comma = FALSE;
- if(time<0){
- time= -time;
- msign="-";
+ if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
+ ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
+ return;
}
- if(time<0){ /* We've overflowed. */
- sprintf(buf, "Unable to cope with time value %d", time);
- return;
+ if(time_val < 0){
+ time_val = -time_val;
+ msign = "-";
}
- secs = time % 60;
- time /= 60;
- mins = time % 60;
- time /= 60;
- hours = time % 24;
- time /= 24;
+ secs = time_val % 60;
+ time_val /= 60;
+ mins = time_val % 60;
+ time_val /= 60;
+ hours = time_val % 24;
+ time_val /= 24;
- /* This would probably be cleaner if we used GStrings instead. */
- p = buf;
- if (time != 0) {
- sprintf(p, "%s%u day%s", time?msign:"", time, PLURALIZE(time));
- p += strlen(p);
+ if (time_val != 0) {
+ ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
do_comma = TRUE;
+ msign="";
}
if (hours != 0) {
- sprintf(p, "%s%s%u hour%s", COMMA(do_comma), hours?msign:"", hours, PLURALIZE(hours));
- p += strlen(p);
+ ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
do_comma = TRUE;
+ msign="";
}
if (mins != 0) {
- sprintf(p, "%s%s%u minute%s", COMMA(do_comma), mins?msign:"", mins, PLURALIZE(mins));
- p += strlen(p);
+ ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
do_comma = TRUE;
+ msign="";
}
if (secs != 0 || frac != 0) {
if (frac != 0) {
if (is_nsecs)
- sprintf(p, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
+ ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
else
- sprintf(p, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
+ ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
} else
- sprintf(p, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
+ ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
}
}
gchar *
-time_secs_to_str(gint32 time)
+time_secs_to_str(const gint32 time_val)
{
- static gchar str[3][TIME_SECS_LEN+1];
- static gchar *cur;
+ emem_strbuf_t *buf;
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
+ buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
+
+ if (time_val == 0) {
+ ep_strbuf_append(buf, "0 seconds");
+ return buf->str;
}
- if (time == 0) {
- sprintf(cur, "0 time");
- return cur;
+ time_secs_to_str_buf(time_val, 0, FALSE, buf);
+ return buf->str;
+}
+
+static void
+time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
+ emem_strbuf_t *buf)
+{
+ int hours, mins, secs;
+ gboolean do_comma = FALSE;
+
+ secs = time_val % 60;
+ time_val /= 60;
+ mins = time_val % 60;
+ time_val /= 60;
+ hours = time_val % 24;
+ time_val /= 24;
+
+ if (time_val != 0) {
+ ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
+ do_comma = TRUE;
}
+ if (hours != 0) {
+ ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
+ do_comma = TRUE;
+ }
+ if (mins != 0) {
+ ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
+ do_comma = TRUE;
+ }
+ if (secs != 0 || frac != 0) {
+ if (frac != 0) {
+ if (is_nsecs)
+ ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
+ else
+ ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
+ } else
+ ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
+ }
+}
- time_secs_to_str_buf(time, 0, FALSE, cur);
- return cur;
+gchar *
+time_secs_to_str_unsigned(const guint32 time_val)
+{
+ emem_strbuf_t *buf;
+
+ buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
+
+ if (time_val == 0) {
+ ep_strbuf_append(buf, "0 seconds");
+ return buf->str;
+ }
+
+ time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
+ return buf->str;
}
+
gchar *
-time_msecs_to_str(gint32 time)
+time_msecs_to_str(gint32 time_val)
{
- static gchar str[3][TIME_SECS_LEN+1+3+1];
- static gchar *cur;
+ emem_strbuf_t *buf;
int msecs;
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
+ buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
- if (time == 0) {
- sprintf(cur, "0 time");
- return cur;
+ if (time_val == 0) {
+ ep_strbuf_append(buf, "0 seconds");
+ return buf->str;
}
- if(time<0){
+ if(time_val<0){
/* oops we got passed a negative time */
- time= -time;
- msecs = time % 1000;
- time /= 1000;
- time= -time;
+ time_val= -time_val;
+ msecs = time_val % 1000;
+ time_val /= 1000;
+ time_val= -time_val;
} else {
- msecs = time % 1000;
- time /= 1000;
+ msecs = time_val % 1000;
+ time_val /= 1000;
}
- time_secs_to_str_buf(time, msecs, FALSE, cur);
- return cur;
+ time_secs_to_str_buf(time_val, msecs, FALSE, buf);
+ return buf->str;
}
-static const char *mon_names[12] = {
+static const char mon_names[12][4] = {
"Jan",
"Feb",
"Mar",
"Dec"
};
+static const gchar *get_zonename(struct tm *tmp) {
+#if defined(HAVE_TM_ZONE)
+ return tmp->tm_zone;
+#else
+ if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
+ return "???";
+ }
+# if defined(HAVE_TZNAME)
+ return tzname[tmp->tm_isdst];
+
+# elif defined(_WIN32)
+ /* Windows C Runtime: */
+ /* _tzname is encoded using the "system default ansi code page" */
+ /* ("which is not necessarily the same as the C library locale"). */
+ /* So: _tzname must be converted to UTF8 before use. */
+ /* Alternative: use Windows GetTimeZoneInformation() to get the */
+ /* timezone name in UTF16 and convert same to UTF8. */
+ /* XXX: the result is that the timezone name will be based upon the */
+ /* system code page (iow: the charset of the system). */
+ /* Since Wireshark is not internationalized, it would seem more */
+ /* correct to show the timezone name in English, no matter what */
+ /* the system code page, but I don't how to do that (or if it's */
+ /* really even possible). */
+ /* In any case converting to UTF8 presumably at least keeps GTK */
+ /* happy. (A bug was reported wherein Wireshark crashed in GDK */
+ /* on a "Japanese version of Windows XP" when trying to copy */
+ /* the date/time string (containing a copy of _tz_name) to the */
+ /* clipboard). */
+
+ {
+ static char *ws_tzname[2] = {NULL, NULL};
+
+ /* The g_malloc'd value returned from g_locale_to_utf8() is */
+ /* cached for all further use so there's no need to ever */
+ /* g_free() that value. */
+ if (ws_tzname[tmp->tm_isdst] == NULL) {
+ ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
+ if (ws_tzname[tmp->tm_isdst] == NULL) {
+ ws_tzname[tmp->tm_isdst] = "???";
+ }
+ }
+ return ws_tzname[tmp->tm_isdst];
+ }
+# else
+ return tmp->tm_isdst ? "?DT" : "?ST";
+
+# endif
+#endif
+}
+
gchar *
-abs_time_to_str(nstime_t *abs_time)
+abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
+ gboolean show_zone)
{
- struct tm *tmp;
- static gchar *cur;
- static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+9+1];
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
+ struct tm *tmp = NULL;
+ const char *zonename = "???";
+ gchar *buf = NULL;
+
+#if (defined _WIN32) && (_MSC_VER < 1500)
+ /* calling localtime() on MSVC 2005 with huge values causes it to crash */
+ /* XXX - find the exact value that still does work */
+ /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
+ if(abs_time->secs > 2000000000) {
+ tmp = NULL;
+ } else
+#endif
+ switch (fmt) {
+
+ case ABSOLUTE_TIME_UTC:
+ case ABSOLUTE_TIME_DOY_UTC:
+ tmp = gmtime(&abs_time->secs);
+ zonename = "UTC";
+ break;
+
+ case ABSOLUTE_TIME_LOCAL:
+ tmp = localtime(&abs_time->secs);
+ if (tmp) {
+ zonename = get_zonename(tmp);
+ }
+ break;
}
-
- tmp = localtime(&abs_time->secs);
if (tmp) {
- sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%09ld",
- mon_names[tmp->tm_mon],
- tmp->tm_mday,
- tmp->tm_year + 1900,
- tmp->tm_hour,
- tmp->tm_min,
- tmp->tm_sec,
- (long)abs_time->nsecs);
+ switch (fmt) {
+
+ case ABSOLUTE_TIME_DOY_UTC:
+ if (show_zone) {
+ buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
+ tmp->tm_year + 1900,
+ tmp->tm_yday + 1,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (long)abs_time->nsecs,
+ zonename);
+ } else {
+ buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
+ tmp->tm_year + 1900,
+ tmp->tm_yday + 1,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (long)abs_time->nsecs);
+ }
+ break;
+
+ case ABSOLUTE_TIME_UTC:
+ case ABSOLUTE_TIME_LOCAL:
+ if (show_zone) {
+ buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
+ mon_names[tmp->tm_mon],
+ tmp->tm_mday,
+ tmp->tm_year + 1900,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (long)abs_time->nsecs,
+ zonename);
+ } else {
+ buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
+ mon_names[tmp->tm_mon],
+ tmp->tm_mday,
+ tmp->tm_year + 1900,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (long)abs_time->nsecs);
+ }
+ break;
+ }
} else
- strncpy(cur, "Not representable", sizeof(str[0]));
- return cur;
+ buf = ep_strdup("Not representable");
+ return buf;
}
gchar *
-abs_time_secs_to_str(time_t abs_time)
+abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
+ gboolean show_zone)
{
- struct tm *tmp;
- static gchar *cur;
- static char str[3][3+1+2+2+4+1+2+1+2+1+2+1];
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
+ struct tm *tmp = NULL;
+ const char *zonename = "???";
+ gchar *buf = NULL;
+
+#if (defined _WIN32) && (_MSC_VER < 1500)
+ /* calling localtime() on MSVC 2005 with huge values causes it to crash */
+ /* XXX - find the exact value that still does work */
+ /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
+ if(abs_time > 2000000000) {
+ tmp = NULL;
+ } else
+#endif
+ switch (fmt) {
+
+ case ABSOLUTE_TIME_UTC:
+ case ABSOLUTE_TIME_DOY_UTC:
+ tmp = gmtime(&abs_time);
+ zonename = "UTC";
+ break;
+
+ case ABSOLUTE_TIME_LOCAL:
+ tmp = localtime(&abs_time);
+ if (tmp) {
+ zonename = get_zonename(tmp);
+ }
+ break;
}
-
- tmp = localtime(&abs_time);
if (tmp) {
- sprintf(cur, "%s %2d, %d %02d:%02d:%02d",
- mon_names[tmp->tm_mon],
- tmp->tm_mday,
- tmp->tm_year + 1900,
- tmp->tm_hour,
- tmp->tm_min,
- tmp->tm_sec);
+ switch (fmt) {
+
+ case ABSOLUTE_TIME_DOY_UTC:
+ if (show_zone) {
+ buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
+ tmp->tm_year + 1900,
+ tmp->tm_yday + 1,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ zonename);
+ } else {
+ buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
+ tmp->tm_year + 1900,
+ tmp->tm_yday + 1,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec);
+ }
+ break;
+
+ case ABSOLUTE_TIME_UTC:
+ case ABSOLUTE_TIME_LOCAL:
+ if (show_zone) {
+ buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
+ mon_names[tmp->tm_mon],
+ tmp->tm_mday,
+ tmp->tm_year + 1900,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ zonename);
+ } else {
+ buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
+ mon_names[tmp->tm_mon],
+ tmp->tm_mday,
+ tmp->tm_year + 1900,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec);
+ }
+ break;
+ }
} else
- strncpy(cur, "Not representable", sizeof(str[0]));
- return cur;
+ buf = ep_strdup("Not representable");
+ return buf;
}
void
-display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
- time_res_t units)
+display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
+ const to_str_time_res_t units)
{
- char *sign;
-
/* If the fractional part of the time stamp is negative,
print its absolute value and, if the seconds part isn't
(the seconds part should be zero in that case), stick
a "-" in front of the entire time stamp. */
- sign = "";
if (frac < 0) {
frac = -frac;
- if (sec >= 0)
- sign = "-";
+ if (sec >= 0) {
+ if (buflen < 1) {
+ return;
+ }
+ buf[0] = '-';
+ buf++;
+ buflen--;
+ }
+ }
+ switch (units) {
+
+ case TO_STR_TIME_RES_T_SECS:
+ g_snprintf(buf, buflen, "%d", sec);
+ break;
+
+ case TO_STR_TIME_RES_T_DSECS:
+ g_snprintf(buf, buflen, "%d.%01d", sec, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_CSECS:
+ g_snprintf(buf, buflen, "%d.%02d", sec, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_MSECS:
+ g_snprintf(buf, buflen, "%d.%03d", sec, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_USECS:
+ g_snprintf(buf, buflen, "%d.%06d", sec, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_NSECS:
+ g_snprintf(buf, buflen, "%d.%09d", sec, frac);
+ break;
+ }
+}
+
+
+void
+display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
+ const to_str_time_res_t units)
+{
+ double elapsed_secs;
+
+ elapsed_secs = difftime(sec,(time_t)0);
+
+ /* This code copied from display_signed_time; keep it in case anyone
+ is looking at captures from before 1970 (???).
+ If the fractional part of the time stamp is negative,
+ print its absolute value and, if the seconds part isn't
+ (the seconds part should be zero in that case), stick
+ a "-" in front of the entire time stamp. */
+ if (frac < 0) {
+ frac = -frac;
+ if (elapsed_secs >= 0) {
+ if (buflen < 1) {
+ return;
+ }
+ buf[0] = '-';
+ buf++;
+ buflen--;
+ }
}
switch (units) {
- case MSECS:
- snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
+ case TO_STR_TIME_RES_T_SECS:
+ g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
break;
- case USECS:
- snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
+ case TO_STR_TIME_RES_T_DSECS:
+ g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
break;
- case NSECS:
- snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
+ case TO_STR_TIME_RES_T_CSECS:
+ g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_MSECS:
+ g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_USECS:
+ g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
+ break;
+
+ case TO_STR_TIME_RES_T_NSECS:
+ g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
break;
}
}
* Display a relative time as days/hours/minutes/seconds.
*/
gchar *
-rel_time_to_str(nstime_t *rel_time)
+rel_time_to_str(const nstime_t *rel_time)
{
- static gchar *cur;
- static char str[3][1+TIME_SECS_LEN+1+6+1];
- char *p;
- char *sign;
- gint32 time;
+ emem_strbuf_t *buf;
+ gint32 time_val;
gint32 nsec;
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
- p = cur;
+ buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
/* If the nanoseconds part of the time stamp is negative,
print its absolute value and, if the seconds part isn't
(the seconds part should be zero in that case), stick
a "-" in front of the entire time stamp. */
- sign = "";
- time = rel_time->secs;
+ time_val = (gint) rel_time->secs;
nsec = rel_time->nsecs;
- if (time == 0 && nsec == 0) {
- sprintf(cur, "0.000000000 seconds");
- return cur;
+ if (time_val == 0 && nsec == 0) {
+ ep_strbuf_append(buf, "0.000000000 seconds");
+ return buf->str;
}
if (nsec < 0) {
nsec = -nsec;
- *p++ = '-';
+ ep_strbuf_append_c(buf, '-');
/*
* We assume here that "rel_time->secs" is negative
* or zero; if it's not, the time stamp is bogus,
* with a positive seconds and negative microseconds.
*/
- time = -rel_time->secs;
+ time_val = (gint) -rel_time->secs;
}
- time_secs_to_str_buf(time, nsec, TRUE, p);
- return cur;
+ time_secs_to_str_buf(time_val, nsec, TRUE, buf);
+ return buf->str;
}
#define REL_TIME_SECS_LEN (1+10+1+9+1)
* Display a relative time as seconds.
*/
gchar *
-rel_time_to_secs_str(nstime_t *rel_time)
+rel_time_to_secs_str(const nstime_t *rel_time)
{
- static gchar *cur;
- static char str[3][REL_TIME_SECS_LEN];
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
+ gchar *buf;
- display_signed_time(cur, REL_TIME_SECS_LEN, rel_time->secs,
- rel_time->nsecs, NSECS);
- return cur;
+ buf=(gchar *)ep_alloc(REL_TIME_SECS_LEN);
+
+ display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
+ rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
+ return buf;
}
+/*
+ * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
+ * with the length in bits of no_of_bits based on value.
+ * Ex: ..xx x...
+ */
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
-gchar *
-fc_to_str(const guint8 *ad)
+char *
+decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
{
- return bytestring_to_str (ad, 3, '.');
-}
-
-/* FC Network Header Network Address Authority Identifiers */
+ guint64 mask = 0,tmp;
+ char *str;
+ int bit, str_p = 0;
+ int i;
+
+ mask = 1;
+ mask = mask << (no_of_bits-1);
+
+ /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
+ str=(char *)ep_alloc0(256+64);
+ for(bit=0;bit<((int)(bit_offset&0x07));bit++){
+ if(bit&&(!(bit%4))){
+ str[str_p] = ' ';
+ str_p++;
+ }
+ str[str_p] = '.';
+ str_p++;
+ }
-#define FC_NH_NAA_IEEE 1 /* IEEE 802.1a */
-#define FC_NH_NAA_IEEE_E 2 /* IEEE Exteneded */
-#define FC_NH_NAA_LOCAL 3
-#define FC_NH_NAA_IP 4 /* 32-bit IP address */
-#define FC_NH_NAA_IEEE_R 5 /* IEEE Registered */
-#define FC_NH_NAA_IEEE_R_E 6 /* IEEE Registered Exteneded */
-/* according to FC-PH 3 draft these are now reclaimed and reserved */
-#define FC_NH_NAA_CCITT_INDV 12 /* CCITT 60 bit individual address */
-#define FC_NH_NAA_CCITT_GRP 14 /* CCITT 60 bit group address */
+ /* read the bits for the int */
+ for(i=0;i<no_of_bits;i++){
+ if(bit&&(!(bit%4))){
+ str[str_p] = ' ';
+ str_p++;
+ }
+ if(bit&&(!(bit%8))){
+ str[str_p] = ' ';
+ str_p++;
+ }
+ bit++;
+ tmp = value & mask;
+ if(tmp != 0){
+ str[str_p] = '1';
+ str_p++;
+ } else {
+ str[str_p] = '0';
+ str_p++;
+ }
+ mask = mask>>1;
+ }
-gchar *
-fcwwn_to_str (const guint8 *ad)
-{
- int fmt;
- guint8 oui[6];
- static gchar ethstr[512];
-
- if (ad == NULL) return NULL;
-
- fmt = (ad[0] & 0xF0) >> 4;
-
- switch (fmt) {
-
- case FC_NH_NAA_IEEE:
- case FC_NH_NAA_IEEE_E:
- memcpy (oui, &ad[2], 6);
- sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
- ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
- get_manuf_name (oui));
- break;
-
- case FC_NH_NAA_IEEE_R:
- oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
- oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
- oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
- oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
- oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
- oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
-
- sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
- ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
- get_manuf_name (oui));
- break;
-
- default:
- sprintf (ethstr, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
- ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
- break;
- }
- return (ethstr);
+ for(;bit%8;bit++){
+ if(bit&&(!(bit%4))){
+ str[str_p] = ' ';
+ str_p++;
+ }
+ str[str_p] = '.';
+ str_p++;
+ }
+ return str;
}
/* Generate, into "buf", a string showing the bits of a bitfield.
Return a pointer to the character after that string. */
+/*XXX this needs a buf_len check */
char *
-other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
{
int i;
guint32 bit;
}
char *
-decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
{
char *p;
}
/* Generate a string describing a Boolean bitfield (a one-bit field that
- says something is either true of false). */
+ says something is either true or false). */
const char *
-decode_boolean_bitfield(guint32 val, guint32 mask, int width,
+decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
const char *truedesc, const char *falsedesc)
{
- static char buf[1025];
+ char *buf;
char *p;
+ buf=(char *)ep_alloc(1025); /* is this a bit overkill? */
p = decode_bitfield_value(buf, val, mask, width);
if (val & mask)
strcpy(p, truedesc);
/* Generate a string describing a numeric bitfield (an N-bit field whose
value is just a number). */
const char *
-decode_numeric_bitfield(guint32 val, guint32 mask, int width,
+decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
const char *fmt)
{
- static char buf[1025];
+ char *buf;
char *p;
int shift = 0;
+ buf=(char *)ep_alloc(1025); /* isnt this a bit overkill? */
/* Compute the number of bits we have to shift the bitfield right
to extract its value. */
while ((mask & (1<<shift)) == 0)
shift++;
p = decode_bitfield_value(buf, val, mask, width);
- sprintf(p, fmt, (val & mask) >> shift);
+ g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
return buf;
}
-
-/*XXX FIXME the code below may be called very very frequently in the future.
- optimize it for speed and get rid of the slow sprintfs */
-/* XXX - perhaps we should have individual address types register
- a table of routines to do operations such as address-to-name translation,
- address-to-string translation, and the like, and have this call them,
- and also have an address-to-string-with-a-name routine */
-/* XXX - use this, and that future address-to-string-with-a-name routine,
- in "col_set_addr()"; it might also be useful to have address types
- export the names of the source and destination address fields, so
- that "col_set_addr()" need know nothing whatsoever about particular
- address types */
-/* convert an address struct into a printable string */
-gchar*
-address_to_str(const address *addr)
+/*
+ This function is very fast and this function is called a lot.
+ XXX update the ep_address_to_str stuff to use this function.
+*/
+void
+ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
{
- static int i=0;
- static gchar *strp, str[16][256];
+ register gchar const *p;
+ register gchar *b=buf;
- i++;
- if(i>=16){
- i=0;
- }
- strp=str[i];
+ if (buf_len < MAX_IP_STR_LEN) {
+ g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
+ return;
+ }
- address_to_str_buf(addr, strp);
- return strp;
-}
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
-void
-address_to_str_buf(const address *addr, gchar *buf)
-{
- struct atalk_ddp_addr ddp_addr;
-
- switch(addr->type){
- case AT_ETHER:
- 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]);
- break;
- case AT_IPv4:
- ip_to_str_buf(addr->data, buf);
- break;
- case AT_IPv6:
- inet_ntop(AF_INET6, addr->data, buf, INET6_ADDRSTRLEN);
- break;
- case AT_IPX:
- 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]);
- break;
- case AT_SNA:
- sna_fid_to_str_buf(addr, buf);
- break;
- case AT_ATALK:
- memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
- atalk_addr_to_str_buf(&ddp_addr, buf);
- break;
- case AT_VINES:
- vines_addr_to_str_buf(addr->data, buf);
- break;
- case AT_OSI:
- print_nsap_net_buf(addr->data, addr->len, buf);
- break;
- case AT_ARCNET:
- sprintf(buf, "0x%02X", addr->data[0]);
- break;
- case AT_FC:
- sprintf(buf, "%02x.%02x.%02x", addr->data[0], addr->data[1], addr->data[2]);
- break;
- case AT_SS7PC:
- mtp3_addr_to_str_buf(addr->data, buf);
- break;
- case AT_STRINGZ:
- strcpy(buf, addr->data);
- break;
- case AT_EUI64:
- sprintf(buf, "%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]);
- break;
- case AT_URI:
- memmove(buf, addr->data, addr->len);
- buf[addr->len] = '\0';
- break;
- default:
- g_assert_not_reached();
- }
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
+
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
+
+ p=fast_strings[*ad];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b=0;
}
-gchar* oid_to_str(const guint8 *oid, gint oid_len) {
- /* static buffer */
- static int cnt = 0;
- static gchar strbuf[8][MAX_OID_STR_LEN];
+gchar* guid_to_str(const e_guid_t *guid) {
+ gchar *buf;
- cnt = (cnt + 1) % 8;
- return oid_to_str_buf(oid, oid_len, strbuf[cnt]);
+ buf=(gchar *)ep_alloc(GUID_STR_LEN);
+ return guid_to_str_buf(guid, buf, GUID_STR_LEN);
}
-gchar* oid_to_str_buf(const guint8 *oid, gint oid_len, gchar *buf) {
- gint i;
- guint8 byte;
- guint32 value;
- gchar *bufp;
+gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
+ char *tempptr = buf;
- bufp = buf; value=0;
- for (i=0; i<oid_len; i++){
- byte = oid[i];
- if ((bufp - buf) > (MAX_OID_STR_LEN - 16)) { /* "4294967295" + ".>>>" + '\0' + 1 */
- bufp += sprintf(bufp, ".>>>");
- break;
- }
- if (i == 0) {
- bufp += sprintf(bufp, "%u.%u", byte/40, byte%40);
- continue;
- }
- value = (value << 7) | (byte & 0x7F);
- if (byte & 0x80) {
- continue;
- }
- bufp += sprintf(bufp, ".%u", value);
- value = 0;
+ if (buf_len < GUID_STR_LEN) {
+ g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
+ return buf;
}
- *bufp = '\0';
+ /* 37 bytes */
+ tempptr = dword_to_hex(tempptr, guid->data1); /* 8 bytes */
+ *tempptr++ = '-'; /* 1 byte */
+ tempptr = word_to_hex(tempptr, guid->data2); /* 4 bytes */
+ *tempptr++ = '-'; /* 1 byte */
+ tempptr = word_to_hex(tempptr, guid->data3); /* 4 bytes */
+ *tempptr++ = '-'; /* 1 byte */
+ tempptr = bytes_to_hexstr(tempptr, &guid->data4[0], 2); /* 4 bytes */
+ *tempptr++ = '-'; /* 1 byte */
+ tempptr = bytes_to_hexstr(tempptr, &guid->data4[2], 6); /* 12 bytes */
+
+ *tempptr = '\0';
return buf;
}
-gchar* guid_to_str(const guint8 *guid) {
- /* static buffer */
- static int cnt = 0;
- static gchar strbuf[8][GUID_STR_LEN];
+const gchar* port_type_to_str (port_type type) {
+ switch (type) {
+ case PT_NONE: return "NONE";
+ case PT_SCTP: return "SCTP";
+ case PT_TCP: return "TCP";
+ case PT_UDP: return "UDP";
+ case PT_DCCP: return "DCCP";
+ case PT_IPX: return "IPX";
+ case PT_NCP: return "NCP";
+ case PT_EXCHG: return "FC EXCHG";
+ case PT_DDP: return "DDP";
+ case PT_SBCCS: return "FICON SBCCS";
+ case PT_IDP: return "IDP";
+ case PT_TIPC: return "TIPC";
+ case PT_USB: return "USB";
+ case PT_I2C: return "I2C";
+ case PT_IBQP: return "IBQP";
+ case PT_BLUETOOTH: return "BLUETOOTH";
+ default: return "[Unknown]";
+ }
+}
+
+char *
+oct_to_str_back(char *ptr, guint32 value)
+{
+ while (value) {
+ *(--ptr) = '0' + (value & 0x7);
+ value >>= 3;
+ }
- cnt = (cnt + 1) % 8;
- return guid_to_str_buf(guid, strbuf[cnt]);
+ *(--ptr) = '0';
+ return ptr;
}
-gchar* guid_to_str_buf(const guint8 *guid, gchar *buf) {
- sprintf(buf, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- guid[0], guid[1], guid[2], guid[3],
- guid[4], guid[5],
- guid[6], guid[7],
- guid[8], guid[9],
- guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
- return buf;
+char *
+hex_to_str_back(char *ptr, int pad, guint32 value)
+{
+ do {
+ *(--ptr) = octet_to_hex(value);
+ value >>= 4;
+ pad--;
+ } while (value);
+
+ /* pad */
+ while (pad > 0) {
+ *(--ptr) = '0';
+ pad--;
+ }
+
+ *(--ptr) = 'x';
+ *(--ptr) = '0';
+
+ return ptr;
}
+
+char *
+uint_to_str_back(char *ptr, guint32 value)
+{
+ char const *p;
+
+ /* special case */
+ if (value == 0)
+ *(--ptr) = '0';
+
+ while (value >= 10) {
+ p = fast_strings[100 + (value % 100)];
+
+ value /= 100;
+
+ *(--ptr) = p[2];
+ *(--ptr) = p[1];
+ }
+
+ if (value)
+ *(--ptr) = (value) | '0';
+
+ return ptr;
+}
+
+char *
+int_to_str_back(char *ptr, gint32 value)
+{
+ if (value < 0) {
+ ptr = uint_to_str_back(ptr, -value);
+ *(--ptr) = '-';
+ } else
+ ptr = uint_to_str_back(ptr, value);
+
+ return ptr;
+}
+