Introduce se_address_to_str()
[metze/wireshark/wip.git] / epan / to_str.c
1 /* to_str.c
2  * Routines for utilities to convert various other types to strings.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>         /* needed for <netinet/in.h> */
34 #endif
35
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>        /* needed for <arpa/inet.h> on some platforms */
38 #endif
39
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>         /* needed to define AF_ values on UNIX */
46 #endif
47
48 #ifdef HAVE_WINSOCK2_H
49 #include <winsock2.h>           /* needed to define AF_ values on Windows */
50 #endif
51
52 #ifdef NEED_INET_V6DEFS_H
53 # include "inet_v6defs.h"
54 #endif
55
56 #include "to_str.h"
57 #include "value_string.h"
58 #include "addr_resolv.h"
59 #include "pint.h"
60 #include "atalk-utils.h"
61 #include "sna-utils.h"
62 #include "osi-utils.h"
63 #include <epan/dissectors/packet-mtp3.h>
64 #include <stdio.h>
65 #include <time.h>
66 #include "emem.h"
67
68 /*
69  * If a user _does_ pass in a too-small buffer, this is probably
70  * going to be too long to fit.  However, even a partial string
71  * starting with "[Buf" should provide enough of a clue to be
72  * useful.
73  */
74 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
75
76 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
77  * digits at at a time, with a specified punctuation character between
78  * the bytes.
79  *
80  * If punct is '\0', no punctuation is applied (and thus
81  * the resulting string is (len-1) bytes shorter)
82  */
83 gchar *
84 bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
85   gchar *buf;
86   gchar        *p;
87   int          i = (int) len - 1;
88   guint32      octet;
89   size_t       buflen;
90   /* At least one version of Apple's C compiler/linker is buggy, causing
91      a complaint from the linker about the "literal C string section"
92      not ending with '\0' if we initialize a 16-element "char" array with
93      a 16-character string, the fact that initializing such an array with
94      such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
95      '\0' byte in the string nonwithstanding. */
96   static const gchar hex_digits[16] =
97       { '0', '1', '2', '3', '4', '5', '6', '7',
98         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
99
100   if (punct)
101     buflen=len*3;
102   else
103     buflen=len*2 + 1;
104
105   if (buflen < 3 || i < 0) {
106     return "";
107   }
108
109   buf=ep_alloc(buflen);
110   p = &buf[buflen - 1];
111   *p = '\0';
112   for (;;) {
113     octet = ad[i];
114     *--p = hex_digits[octet&0xF];
115     octet >>= 4;
116     *--p = hex_digits[octet&0xF];
117     if (i <= 0)
118       break;
119     if (punct)
120       *--p = punct;
121     i--;
122   }
123   return p;
124 }
125
126 /* Wrapper for the most common case of asking
127  * for a string using a colon as the hex-digit separator.
128  */
129 /* XXX FIXME
130 remove this one later when every call has been converted to address_to_str()
131 */
132 gchar *
133 ether_to_str(const guint8 *ad)
134 {
135         return bytestring_to_str(ad, 6, ':');
136 }
137
138 /*
139  This function is very fast and this function is called a lot.
140  XXX update the address_to_str stuff to use this function.
141 */
142 const gchar *
143 ip_to_str(const guint8 *ad) {
144   gchar *buf;
145
146   buf=ep_alloc(MAX_IP_STR_LEN);
147   ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
148   return buf;
149 }
150
151 /*
152  This function is very fast and this function is called a lot.
153  XXX update the address_to_str stuff to use this function.
154 */
155 static const char * const fast_strings[] = {
156 "0", "1", "2", "3", "4", "5", "6", "7",
157 "8", "9", "10", "11", "12", "13", "14", "15",
158 "16", "17", "18", "19", "20", "21", "22", "23",
159 "24", "25", "26", "27", "28", "29", "30", "31",
160 "32", "33", "34", "35", "36", "37", "38", "39",
161 "40", "41", "42", "43", "44", "45", "46", "47",
162 "48", "49", "50", "51", "52", "53", "54", "55",
163 "56", "57", "58", "59", "60", "61", "62", "63",
164 "64", "65", "66", "67", "68", "69", "70", "71",
165 "72", "73", "74", "75", "76", "77", "78", "79",
166 "80", "81", "82", "83", "84", "85", "86", "87",
167 "88", "89", "90", "91", "92", "93", "94", "95",
168 "96", "97", "98", "99", "100", "101", "102", "103",
169 "104", "105", "106", "107", "108", "109", "110", "111",
170 "112", "113", "114", "115", "116", "117", "118", "119",
171 "120", "121", "122", "123", "124", "125", "126", "127",
172 "128", "129", "130", "131", "132", "133", "134", "135",
173 "136", "137", "138", "139", "140", "141", "142", "143",
174 "144", "145", "146", "147", "148", "149", "150", "151",
175 "152", "153", "154", "155", "156", "157", "158", "159",
176 "160", "161", "162", "163", "164", "165", "166", "167",
177 "168", "169", "170", "171", "172", "173", "174", "175",
178 "176", "177", "178", "179", "180", "181", "182", "183",
179 "184", "185", "186", "187", "188", "189", "190", "191",
180 "192", "193", "194", "195", "196", "197", "198", "199",
181 "200", "201", "202", "203", "204", "205", "206", "207",
182 "208", "209", "210", "211", "212", "213", "214", "215",
183 "216", "217", "218", "219", "220", "221", "222", "223",
184 "224", "225", "226", "227", "228", "229", "230", "231",
185 "232", "233", "234", "235", "236", "237", "238", "239",
186 "240", "241", "242", "243", "244", "245", "246", "247",
187 "248", "249", "250", "251", "252", "253", "254", "255"
188 };
189 void
190 ip_to_str_buf(const guint8 *ad, gchar *buf, int buf_len)
191 {
192         register gchar const *p;
193         register gchar *b=buf;
194
195         if (buf_len < MAX_IP_STR_LEN) {
196                 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
197                 return;
198         }
199
200         p=fast_strings[*ad++];
201         do {
202                 *b++=*p;
203                 p++;
204         } while(*p);
205         *b++='.';
206
207         p=fast_strings[*ad++];
208         do {
209                 *b++=*p;
210                 p++;
211         } while(*p);
212         *b++='.';
213
214         p=fast_strings[*ad++];
215         do {
216                 *b++=*p;
217                 p++;
218         } while(*p);
219         *b++='.';
220
221         p=fast_strings[*ad];
222         do {
223                 *b++=*p;
224                 p++;
225         } while(*p);
226         *b=0;
227 }
228
229
230 /* XXX FIXME
231 remove this one later when every call has been converted to address_to_str()
232 */
233 gchar *
234 ip6_to_str(const struct e_in6_addr *ad) {
235 #ifndef INET6_ADDRSTRLEN
236 #define INET6_ADDRSTRLEN 46
237 #endif
238   static gchar *str;
239
240   str=ep_alloc(INET6_ADDRSTRLEN+1);
241
242   ip6_to_str_buf(ad, str);
243   return str;
244 }
245
246 void
247 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
248 {
249   inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
250 }
251
252 gchar*
253 ipx_addr_to_str(guint32 net, const guint8 *ad)
254 {
255         gchar   *buf;
256         char    *name;
257
258         buf=ep_alloc(8+1+MAXNAMELEN+1); /* 8 digits, 1 period, NAME, 1 null */
259         name = get_ether_name_if_known(ad);
260
261         if (name) {
262                 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net), name);
263         }
264         else {
265                 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net),
266                     bytestring_to_str(ad, 6, '\0'));
267         }
268         return buf;
269 }
270
271 gchar*
272 ipxnet_to_string(const guint8 *ad)
273 {
274         guint32 addr = pntohl(ad);
275         return ipxnet_to_str_punct(addr, ' ');
276 }
277
278 gchar *
279 ipxnet_to_str_punct(const guint32 ad, char punct)
280 {
281   gchar        *buf;
282   gchar        *p;
283   int          i;
284   guint32      octet;
285   /* At least one version of Apple's C compiler/linker is buggy, causing
286      a complaint from the linker about the "literal C string section"
287      not ending with '\0' if we initialize a 16-element "char" array with
288      a 16-character string, the fact that initializing such an array with
289      such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
290      '\0' byte in the string nonwithstanding. */
291   static const gchar hex_digits[16] =
292       { '0', '1', '2', '3', '4', '5', '6', '7',
293         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
294   static const guint32  octet_mask[4] =
295           { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
296
297   buf=ep_alloc(12);
298   p = &buf[12];
299   *--p = '\0';
300   i = 3;
301   for (;;) {
302     octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
303     *--p = hex_digits[octet&0xF];
304     octet >>= 4;
305     *--p = hex_digits[octet&0xF];
306     if (i == 0)
307       break;
308     if (punct)
309       *--p = punct;
310     i--;
311   }
312   return p;
313 }
314
315 gchar *
316 vines_addr_to_str(const guint8 *addrp)
317 {
318   gchar *buf;
319
320   buf=ep_alloc(214);
321
322   vines_addr_to_str_buf(addrp, buf, 214);
323   return buf;
324 }
325
326 void
327 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
328 {
329   g_snprintf(buf, buf_len, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
330 }
331
332
333 void
334 usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
335 {
336   if(pletohl(&addrp[0])==0xffffffff){
337     g_snprintf(buf, buf_len, "host");
338   } else {
339     g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
340   }
341 }
342
343 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
344 #define COMMA(do_it)    ((do_it) ? ", " : "")
345
346 /*
347  * Maximum length of a string showing days/hours/minutes/seconds.
348  * (Does not include the terminating '\0'.)
349  * Includes space for a '-' sign for any negative components.
350  * -12345 days, 12 hours, 12 minutes, 12.123 seconds
351  */
352 #define TIME_SECS_LEN   (10+1+4+2+2+5+2+2+7+2+2+7+4)
353
354 /*
355  * Convert a value in seconds and fractions of a second to a string,
356  * giving time in days, hours, minutes, and seconds, and put the result
357  * into a buffer.
358  * "is_nsecs" says that "frac" is microseconds if true and milliseconds
359  * if false.
360  * If time is negative, add a '-' to all non-null components.
361  */
362 static void
363 time_secs_to_str_buf(gint32 time, guint32 frac, gboolean is_nsecs,
364                            emem_strbuf_t *buf)
365 {
366   int hours, mins, secs;
367   const gchar *msign = "";
368   gboolean do_comma = FALSE;
369
370   if(time == G_MININT32) {      /* That Which Shall Not Be Negated */
371     ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time);
372     return;
373   }
374
375   if(time < 0){
376     time = -time;
377     msign = "-";
378   }
379
380   secs = time % 60;
381   time /= 60;
382   mins = time % 60;
383   time /= 60;
384   hours = time % 24;
385   time /= 24;
386
387   if (time != 0) {
388     ep_strbuf_append_printf(buf, "%s%u day%s", msign, time, PLURALIZE(time));
389     do_comma = TRUE;
390     msign="";
391   }
392   if (hours != 0) {
393     ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
394     do_comma = TRUE;
395     msign="";
396   }
397   if (mins != 0) {
398     ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
399     do_comma = TRUE;
400     msign="";
401   }
402   if (secs != 0 || frac != 0) {
403     if (frac != 0) {
404       if (is_nsecs)
405         ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
406       else
407         ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
408     } else
409       ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
410   }
411 }
412
413 gchar *
414 time_secs_to_str(gint32 time)
415 {
416   emem_strbuf_t *buf;
417
418   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
419
420   if (time == 0) {
421     ep_strbuf_append(buf, "0 time");
422     return buf->str;
423   }
424
425   time_secs_to_str_buf(time, 0, FALSE, buf);
426   return buf->str;
427 }
428
429 static void
430 time_secs_to_str_buf_unsigned(guint32 time, guint32 frac, gboolean is_nsecs,
431                          emem_strbuf_t *buf)
432 {
433   int hours, mins, secs;
434   gboolean do_comma = FALSE;
435
436   secs = time % 60;
437   time /= 60;
438   mins = time % 60;
439   time /= 60;
440   hours = time % 24;
441   time /= 24;
442
443   if (time != 0) {
444     ep_strbuf_append_printf(buf, "%u day%s", time, PLURALIZE(time));
445     do_comma = TRUE;
446   }
447   if (hours != 0) {
448     ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
449     do_comma = TRUE;
450   }
451   if (mins != 0) {
452     ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
453     do_comma = TRUE;
454   }
455   if (secs != 0 || frac != 0) {
456     if (frac != 0) {
457       if (is_nsecs)
458         ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
459       else
460         ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
461     } else
462       ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
463   }
464 }
465
466 gchar *
467 time_secs_to_str_unsigned(guint32 time)
468 {
469   emem_strbuf_t *buf;
470
471   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
472
473   if (time == 0) {
474     ep_strbuf_append(buf, "0 time");
475     return buf->str;
476   }
477
478   time_secs_to_str_buf_unsigned(time, 0, FALSE, buf);
479   return buf->str;
480 }
481
482
483 gchar *
484 time_msecs_to_str(gint32 time)
485 {
486   emem_strbuf_t *buf;
487   int msecs;
488
489   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
490
491   if (time == 0) {
492     ep_strbuf_append(buf, "0 time");
493     return buf->str;
494   }
495
496   if(time<0){
497     /* oops we got passed a negative time */
498     time= -time;
499     msecs = time % 1000;
500     time /= 1000;
501     time= -time;
502   } else {
503     msecs = time % 1000;
504     time /= 1000;
505   }
506
507   time_secs_to_str_buf(time, msecs, FALSE, buf);
508   return buf->str;
509 }
510
511 static const char *mon_names[12] = {
512         "Jan",
513         "Feb",
514         "Mar",
515         "Apr",
516         "May",
517         "Jun",
518         "Jul",
519         "Aug",
520         "Sep",
521         "Oct",
522         "Nov",
523         "Dec"
524 };
525
526 gchar *
527 abs_time_to_str(nstime_t *abs_time)
528 {
529         struct tm *tmp;
530         gchar *buf;
531
532         buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1+9+1);
533
534
535 #ifdef _MSC_VER
536         /* calling localtime() on MSVC 2005 with huge values causes it to crash */
537         /* XXX - find the exact value that still does work */
538         /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
539         if(abs_time->secs > 2000000000) {
540             tmp = NULL;
541         } else
542 #endif
543         tmp = localtime(&abs_time->secs);
544         if (tmp) {
545                 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1+9+1,
546                     "%s %2d, %d %02d:%02d:%02d.%09ld",
547                     mon_names[tmp->tm_mon],
548                     tmp->tm_mday,
549                     tmp->tm_year + 1900,
550                     tmp->tm_hour,
551                     tmp->tm_min,
552                     tmp->tm_sec,
553                     (long)abs_time->nsecs);
554         } else
555                 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1+9+1);
556         return buf;
557 }
558
559 gchar *
560 abs_time_secs_to_str(time_t abs_time)
561 {
562         struct tm *tmp;
563         gchar *buf;
564
565         buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1);
566
567         tmp = localtime(&abs_time);
568         if (tmp) {
569                 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1,
570                     "%s %2d, %d %02d:%02d:%02d",
571                     mon_names[tmp->tm_mon],
572                     tmp->tm_mday,
573                     tmp->tm_year + 1900,
574                     tmp->tm_hour,
575                     tmp->tm_min,
576                     tmp->tm_sec);
577         } else
578                 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1);
579         return buf;
580 }
581
582 void
583 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
584     time_res_t units)
585 {
586         const char *sign;
587
588         /* If the fractional part of the time stamp is negative,
589            print its absolute value and, if the seconds part isn't
590            (the seconds part should be zero in that case), stick
591            a "-" in front of the entire time stamp. */
592         sign = "";
593         if (frac < 0) {
594                 frac = -frac;
595                 if (sec >= 0)
596                         sign = "-";
597         }
598         switch (units) {
599
600         case SECS:
601                 g_snprintf(buf, buflen, "%s%d", sign, sec);
602                 break;
603
604         case DSECS:
605                 g_snprintf(buf, buflen, "%s%d.%01d", sign, sec, frac);
606                 break;
607
608         case CSECS:
609                 g_snprintf(buf, buflen, "%s%d.%02d", sign, sec, frac);
610                 break;
611
612         case MSECS:
613                 g_snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
614                 break;
615
616         case USECS:
617                 g_snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
618                 break;
619
620         case NSECS:
621                 g_snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
622                 break;
623         }
624 }
625
626
627 void
628 display_epoch_time(gchar *buf, int buflen, time_t sec, gint32 frac,
629     time_res_t units)
630 {
631         const char *sign;
632         double elapsed_secs;
633
634         elapsed_secs = difftime(sec,(time_t)0);
635
636         /* This code copied from display_signed_time; keep it in case anyone
637            is looking at captures from before 1970 (???).
638            If the fractional part of the time stamp is negative,
639            print its absolute value and, if the seconds part isn't
640            (the seconds part should be zero in that case), stick
641            a "-" in front of the entire time stamp. */
642         sign = "";
643         if (frac < 0) {
644                 frac = -frac;
645                 if (elapsed_secs >= 0)
646                         sign = "-";
647         }
648         switch (units) {
649
650         case SECS:
651                 g_snprintf(buf, buflen, "%s%0.0f", sign, elapsed_secs);
652                 break;
653
654         case DSECS:
655                 g_snprintf(buf, buflen, "%s%0.0f.%01d", sign, elapsed_secs, frac);
656                 break;
657
658         case CSECS:
659                 g_snprintf(buf, buflen, "%s%0.0f.%02d", sign, elapsed_secs, frac);
660                 break;
661
662         case MSECS:
663                 g_snprintf(buf, buflen, "%s%0.0f.%03d", sign, elapsed_secs, frac);
664                 break;
665
666         case USECS:
667                 g_snprintf(buf, buflen, "%s%0.0f.%06d", sign, elapsed_secs, frac);
668                 break;
669
670         case NSECS:
671                 g_snprintf(buf, buflen, "%s%0.0f.%09d", sign, elapsed_secs, frac);
672                 break;
673         }
674 }
675
676 /*
677  * Display a relative time as days/hours/minutes/seconds.
678  */
679 gchar *
680 rel_time_to_str(nstime_t *rel_time)
681 {
682         emem_strbuf_t *buf;
683         const char *sign;
684         gint32 time;
685         gint32 nsec;
686
687         buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
688
689         /* If the nanoseconds part of the time stamp is negative,
690            print its absolute value and, if the seconds part isn't
691            (the seconds part should be zero in that case), stick
692            a "-" in front of the entire time stamp. */
693         sign = "";
694         time = (gint) rel_time->secs;
695         nsec = rel_time->nsecs;
696         if (time == 0 && nsec == 0) {
697                 ep_strbuf_append(buf, "0.000000000 seconds");
698                 return buf->str;
699         }
700         if (nsec < 0) {
701                 nsec = -nsec;
702                 ep_strbuf_append_c(buf, '-');
703
704                 /*
705                  * We assume here that "rel_time->secs" is negative
706                  * or zero; if it's not, the time stamp is bogus,
707                  * with a positive seconds and negative microseconds.
708                  */
709                 time = (gint) -rel_time->secs;
710         }
711
712         time_secs_to_str_buf(time, nsec, TRUE, buf);
713         return buf->str;
714 }
715
716 #define REL_TIME_SECS_LEN       (1+10+1+9+1)
717
718 /*
719  * Display a relative time as seconds.
720  */
721 gchar *
722 rel_time_to_secs_str(nstime_t *rel_time)
723 {
724         gchar *buf;
725
726         buf=ep_alloc(REL_TIME_SECS_LEN);
727
728         display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
729             rel_time->nsecs, NSECS);
730         return buf;
731 }
732
733
734 /* XXX FIXME
735 remove this one later when every call has been converted to address_to_str()
736 */
737 gchar *
738 fc_to_str(const guint8 *ad)
739 {
740     return bytestring_to_str (ad, 3, '.');
741 }
742
743 /* FC Network Header Network Address Authority Identifiers */
744
745 #define FC_NH_NAA_IEEE          1       /* IEEE 802.1a */
746 #define FC_NH_NAA_IEEE_E        2       /* IEEE Exteneded */
747 #define FC_NH_NAA_LOCAL         3
748 #define FC_NH_NAA_IP            4       /* 32-bit IP address */
749 #define FC_NH_NAA_IEEE_R        5       /* IEEE Registered */
750 #define FC_NH_NAA_IEEE_R_E      6       /* IEEE Registered Exteneded */
751 /* according to FC-PH 3 draft these are now reclaimed and reserved */
752 #define FC_NH_NAA_CCITT_INDV    12      /* CCITT 60 bit individual address */
753 #define FC_NH_NAA_CCITT_GRP     14      /* CCITT 60 bit group address */
754
755 gchar *
756 fcwwn_to_str (const guint8 *ad)
757 {
758     int fmt;
759     guint8 oui[6];
760     gchar *ethstr;
761
762     if (ad == NULL) return NULL;
763
764     ethstr=ep_alloc(512);
765
766     fmt = (ad[0] & 0xF0) >> 4;
767
768     switch (fmt) {
769
770     case FC_NH_NAA_IEEE:
771     case FC_NH_NAA_IEEE_E:
772         memcpy (oui, &ad[2], 6);
773         g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
774                  ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
775                  get_manuf_name (oui));
776         break;
777
778     case FC_NH_NAA_IEEE_R:
779         oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
780         oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
781         oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
782         oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
783         oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
784         oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
785
786         g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
787                  ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
788                  get_manuf_name (oui));
789         break;
790
791     default:
792         g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
793                  ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
794         break;
795     }
796     return (ethstr);
797 }
798 /*
799  * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
800  * with the length in bits of no_of_bits based on value.
801  * Ex: ..xx x...
802  */
803
804 char *
805 decode_bits_in_field(gint bit_offset, gint no_of_bits, guint64 value)
806 {
807         guint64 mask = 0,tmp;
808         char *str;
809         int bit;
810         int i;
811
812         mask = 1;
813         mask = mask << (no_of_bits-1);
814
815         /* prepare the string */
816         str=ep_alloc(256);
817         str[0]='\0';
818         for(bit=0;bit<((int)(bit_offset&0x07));bit++){
819                 if(bit&&(!(bit%4))){
820                         strcat(str, " ");
821                 }
822                 strcat(str,".");
823         }
824
825         /* read the bits for the int */
826         for(i=0;i<no_of_bits;i++){
827                 if(bit&&(!(bit%4))){
828                         strcat(str, " ");
829                 }
830                 if(bit&&(!(bit%8))){
831                         strcat(str, " ");
832                 }
833                 bit++;
834                 tmp = value & mask;
835                 if(tmp != 0){
836                         strcat(str, "1");
837                 } else {
838                         strcat(str, "0");
839                 }
840                 mask = mask>>1;
841         }
842
843         for(;bit%8;bit++){
844                 if(bit&&(!(bit%4))){
845                         strcat(str, " ");
846                 }
847                 strcat(str,".");
848         }
849         return str;
850 }
851
852 /* Generate, into "buf", a string showing the bits of a bitfield.
853    Return a pointer to the character after that string. */
854 /*XXX this needs a buf_len check */
855 char *
856 other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
857 {
858   int i;
859   guint32 bit;
860   char *p;
861
862   i = 0;
863   p = buf;
864   bit = 1 << (width - 1);
865   for (;;) {
866     if (mask & bit) {
867       /* This bit is part of the field.  Show its value. */
868       if (val & bit)
869         *p++ = '1';
870       else
871         *p++ = '0';
872     } else {
873       /* This bit is not part of the field. */
874       *p++ = '.';
875     }
876     bit >>= 1;
877     i++;
878     if (i >= width)
879       break;
880     if (i % 4 == 0)
881       *p++ = ' ';
882   }
883   *p = '\0';
884   return p;
885 }
886
887 char *
888 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
889 {
890   char *p;
891
892   p = other_decode_bitfield_value(buf, val, mask, width);
893   strcpy(p, " = ");
894   p += 3;
895   return p;
896 }
897
898 /* Generate a string describing a Boolean bitfield (a one-bit field that
899    says something is either true of false). */
900 const char *
901 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
902     const char *truedesc, const char *falsedesc)
903 {
904   char *buf;
905   char *p;
906
907   buf=ep_alloc(1025); /* is this a bit overkill? */
908   p = decode_bitfield_value(buf, val, mask, width);
909   if (val & mask)
910     strcpy(p, truedesc);
911   else
912     strcpy(p, falsedesc);
913   return buf;
914 }
915
916 /* Generate a string describing a numeric bitfield (an N-bit field whose
917    value is just a number). */
918 const char *
919 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
920     const char *fmt)
921 {
922   char *buf;
923   char *p;
924   int shift = 0;
925
926   buf=ep_alloc(1025); /* isnt this a bit overkill? */
927   /* Compute the number of bits we have to shift the bitfield right
928      to extract its value. */
929   while ((mask & (1<<shift)) == 0)
930     shift++;
931
932   p = decode_bitfield_value(buf, val, mask, width);
933   g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
934   return buf;
935 }
936
937
938 /*XXX FIXME the code below may be called very very frequently in the future.
939   optimize it for speed and get rid of the slow sprintfs */
940 /* XXX - perhaps we should have individual address types register
941    a table of routines to do operations such as address-to-name translation,
942    address-to-string translation, and the like, and have this call them,
943    and also have an address-to-string-with-a-name routine */
944 /* XXX - use this, and that future address-to-string-with-a-name routine,
945    in "col_set_addr()"; it might also be useful to have address types
946    export the names of the source and destination address fields, so
947    that "col_set_addr()" need know nothing whatsoever about particular
948    address types */
949 /* convert an address struct into a printable string */
950
951 gchar*
952 address_to_str(const address *addr)
953 {
954   gchar *str;
955
956   str=ep_alloc(MAX_ADDR_STR_LEN);
957   address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
958   return str;
959 }
960
961 /* The called routines use ep_alloc:ed memory */
962 gchar*
963 se_address_to_str(const address *addr)
964 {
965   gchar *str;
966
967   str = address_to_str(addr);
968   return se_strdup(str);
969 }
970
971 void
972 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
973 {
974   const guint8 *addrdata;
975   const char *addrstr;
976   struct atalk_ddp_addr ddp_addr;
977
978   if (!buf)
979     return;
980
981   switch(addr->type){
982   case AT_NONE:
983     g_snprintf(buf, buf_len, "%s", "");
984     break;
985   case AT_ETHER:
986     addrdata = addr->data;
987     g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", addrdata[0], addrdata[1], addrdata[2], addrdata[3], addrdata[4], addrdata[5]);
988     break;
989   case AT_IPv4:
990     ip_to_str_buf(addr->data, buf, buf_len);
991     break;
992   case AT_IPv6:
993     if ( inet_ntop(AF_INET6, addr->data, buf, buf_len) == NULL ) /* Returns NULL if no space and does not touch buf */
994         g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
995     break;
996   case AT_IPX:
997     addrdata = addr->data;
998     g_snprintf(buf, buf_len, "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x", addrdata[0], addrdata[1], addrdata[2], addrdata[3], addrdata[4], addrdata[5], addrdata[6], addrdata[7], addrdata[8], addrdata[9]);
999     break;
1000   case AT_SNA:
1001     sna_fid_to_str_buf(addr, buf, buf_len);
1002     break;
1003   case AT_ATALK:
1004     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
1005     atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
1006     break;
1007   case AT_VINES:
1008     vines_addr_to_str_buf(addr->data, buf, buf_len);
1009     break;
1010   case AT_USB:
1011     usb_addr_to_str_buf(addr->data, buf, buf_len);
1012     break;
1013   case AT_OSI:
1014     print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
1015     break;
1016   case AT_ARCNET:
1017     addrdata = addr->data;
1018     g_snprintf(buf, buf_len, "0x%02X", addrdata[0]);
1019     break;
1020   case AT_FC:
1021     addrdata = addr->data;
1022     g_snprintf(buf, buf_len, "%02x.%02x.%02x", addrdata[0], addrdata[1], addrdata[2]);
1023     break;
1024   case AT_SS7PC:
1025     mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
1026     break;
1027   case AT_STRINGZ:
1028     addrstr = addr->data;
1029     g_snprintf(buf, buf_len, "%s", addrstr);
1030     break;
1031   case AT_EUI64:
1032     addrdata = addr->data;
1033     g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1034             addrdata[0], addrdata[1], addrdata[2], addrdata[3],
1035             addrdata[4], addrdata[5], addrdata[6], addrdata[7]);
1036     break;
1037   case AT_URI: {
1038     int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
1039     memcpy(buf, addr->data, copy_len );
1040     buf[copy_len] = '\0';
1041     }
1042     break;
1043   case AT_TIPC:
1044     tipc_addr_to_str_buf(addr->data, buf, buf_len);
1045     break;
1046   default:
1047     g_assert_not_reached();
1048   }
1049 }
1050
1051 gchar* guid_to_str(const e_guid_t *guid) {
1052   gchar *buf;
1053
1054   buf=ep_alloc(GUID_STR_LEN);
1055   return guid_to_str_buf(guid, buf, GUID_STR_LEN);
1056 }
1057
1058 gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
1059   g_snprintf(buf, buf_len, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1060           guid->data1, guid->data2, guid->data3,
1061           guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3], guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
1062   return buf;
1063 }
1064
1065 void
1066 tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
1067         guint8 zone;
1068         guint16 subnetwork;
1069         guint16 processor;
1070         guint32 tipc_address;
1071
1072         tipc_address = data[0];
1073         tipc_address = (tipc_address << 8) ^ data[1];
1074         tipc_address = (tipc_address << 8) ^ data[2];
1075         tipc_address = (tipc_address << 8) ^ data[3];
1076
1077         processor = tipc_address & 0x0fff;
1078
1079         tipc_address = tipc_address >> 12;
1080         subnetwork = tipc_address & 0x0fff;
1081
1082         tipc_address = tipc_address >> 12;
1083         zone = tipc_address & 0xff;
1084
1085         g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);
1086
1087
1088 }
1089