2 * Routines for utilities to convert various other types to strings.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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>
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
74 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
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
80 * If punct is '\0', no punctuation is applied (and thus
81 * the resulting string is (len-1) bytes shorter)
84 bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
87 int i = (int) len - 1;
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' };
105 if (buflen < 3 || i < 0) {
109 buf=ep_alloc(buflen);
110 p = &buf[buflen - 1];
114 *--p = hex_digits[octet&0xF];
116 *--p = hex_digits[octet&0xF];
126 /* Wrapper for the most common case of asking
127 * for a string using a colon as the hex-digit separator.
130 remove this one later when every call has been converted to address_to_str()
133 ether_to_str(const guint8 *ad)
135 return bytestring_to_str(ad, 6, ':');
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.
143 ip_to_str(const guint8 *ad) {
146 buf=ep_alloc(MAX_IP_STR_LEN);
147 ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
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.
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"
190 ip_to_str_buf(const guint8 *ad, gchar *buf, int buf_len)
192 register gchar const *p;
193 register gchar *b=buf;
195 if (buf_len < MAX_IP_STR_LEN) {
196 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
200 p=fast_strings[*ad++];
207 p=fast_strings[*ad++];
214 p=fast_strings[*ad++];
231 remove this one later when every call has been converted to address_to_str()
234 ip6_to_str(const struct e_in6_addr *ad) {
235 #ifndef INET6_ADDRSTRLEN
236 #define INET6_ADDRSTRLEN 46
240 str=ep_alloc(INET6_ADDRSTRLEN+1);
242 ip6_to_str_buf(ad, str);
247 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
249 inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
253 ipx_addr_to_str(guint32 net, const guint8 *ad)
258 buf=ep_alloc(8+1+MAXNAMELEN+1); /* 8 digits, 1 period, NAME, 1 null */
259 name = get_ether_name_if_known(ad);
262 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net), name);
265 g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net),
266 bytestring_to_str(ad, 6, '\0'));
272 ipxnet_to_string(const guint8 *ad)
274 guint32 addr = pntohl(ad);
275 return ipxnet_to_str_punct(addr, ' ');
279 ipxnet_to_str_punct(const guint32 ad, char punct)
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 };
302 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
303 *--p = hex_digits[octet&0xF];
305 *--p = hex_digits[octet&0xF];
316 vines_addr_to_str(const guint8 *addrp)
322 vines_addr_to_str_buf(addrp, buf, 214);
327 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
329 g_snprintf(buf, buf_len, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
334 usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
336 if(pletohl(&addrp[0])==0xffffffff){
337 g_snprintf(buf, buf_len, "host");
339 g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
343 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
344 #define COMMA(do_it) ((do_it) ? ", " : "")
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 compunents.
351 #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
354 * Convert a value in seconds and fractions of a second to a string,
355 * giving time in days, hours, minutes, and seconds, and put the result
357 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
359 * If time is negative, add a '-' to all non-null components.
362 time_secs_to_str_buf(gint32 time, guint32 frac, gboolean is_nsecs,
363 gchar *buf, int buf_len)
366 int hours, mins, secs;
367 const gchar *msign = "";
368 gboolean do_comma = FALSE;
375 if(time<0){ /* We've overflowed. */
376 g_snprintf(buf, buf_len, "Unable to cope with time value %d", time);
387 /* This would probably be cleaner if we used GStrings instead. */
390 p += g_snprintf(p, buf_len, "%s%u day%s", time?msign:"", time, PLURALIZE(time));
394 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u hour%s", COMMA(do_comma), hours?msign:"", hours, PLURALIZE(hours));
398 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u minute%s", COMMA(do_comma), mins?msign:"", mins, PLURALIZE(mins));
401 if (secs != 0 || frac != 0) {
404 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
406 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
408 p += g_snprintf(p, buf_len-(p-buf), "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
413 time_secs_to_str(gint32 time)
417 buf=ep_alloc(TIME_SECS_LEN+1);
420 g_snprintf(buf, TIME_SECS_LEN+1, "0 time");
424 time_secs_to_str_buf(time, 0, FALSE, buf, TIME_SECS_LEN+1);
429 time_msecs_to_str(gint32 time)
434 buf=ep_alloc(TIME_SECS_LEN+1+3+1);
437 g_snprintf(buf, TIME_SECS_LEN+1+3+1, "0 time");
442 /* oops we got passed a negative time */
452 time_secs_to_str_buf(time, msecs, FALSE, buf, TIME_SECS_LEN+1+3+1);
456 static const char *mon_names[12] = {
472 abs_time_to_str(nstime_t *abs_time)
477 buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1+9+1);
481 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
482 /* XXX - find the exact value that still does work */
483 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
484 if(abs_time->secs > 2000000000) {
488 tmp = localtime(&abs_time->secs);
490 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1+9+1,
491 "%s %2d, %d %02d:%02d:%02d.%09ld",
492 mon_names[tmp->tm_mon],
498 (long)abs_time->nsecs);
500 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1+9+1);
505 abs_time_secs_to_str(time_t abs_time)
510 buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1);
512 tmp = localtime(&abs_time);
514 g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1,
515 "%s %2d, %d %02d:%02d:%02d",
516 mon_names[tmp->tm_mon],
523 strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1);
528 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
533 /* If the fractional part of the time stamp is negative,
534 print its absolute value and, if the seconds part isn't
535 (the seconds part should be zero in that case), stick
536 a "-" in front of the entire time stamp. */
546 g_snprintf(buf, buflen, "%s%d", sign, sec);
550 g_snprintf(buf, buflen, "%s%d.%01d", sign, sec, frac);
554 g_snprintf(buf, buflen, "%s%d.%02d", sign, sec, frac);
558 g_snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
562 g_snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
566 g_snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
573 display_epoch_time(gchar *buf, int buflen, time_t sec, gint32 frac,
579 elapsed_secs = difftime(sec,(time_t)0);
581 /* This code copied from display_signed_time; keep it in case anyone
582 is looking at captures from before 1970 (???).
583 If the fractional part of the time stamp is negative,
584 print its absolute value and, if the seconds part isn't
585 (the seconds part should be zero in that case), stick
586 a "-" in front of the entire time stamp. */
590 if (elapsed_secs >= 0)
596 g_snprintf(buf, buflen, "%s%0.0f", sign, elapsed_secs);
600 g_snprintf(buf, buflen, "%s%0.0f.%01d", sign, elapsed_secs, frac);
604 g_snprintf(buf, buflen, "%s%0.0f.%02d", sign, elapsed_secs, frac);
608 g_snprintf(buf, buflen, "%s%0.0f.%03d", sign, elapsed_secs, frac);
612 g_snprintf(buf, buflen, "%s%0.0f.%06d", sign, elapsed_secs, frac);
616 g_snprintf(buf, buflen, "%s%0.0f.%09d", sign, elapsed_secs, frac);
622 * Display a relative time as days/hours/minutes/seconds.
625 rel_time_to_str(nstime_t *rel_time)
633 buf=ep_alloc(1+TIME_SECS_LEN+1+6+1);
636 /* If the nanoseconds part of the time stamp is negative,
637 print its absolute value and, if the seconds part isn't
638 (the seconds part should be zero in that case), stick
639 a "-" in front of the entire time stamp. */
641 time = (gint) rel_time->secs;
642 nsec = rel_time->nsecs;
643 if (time == 0 && nsec == 0) {
644 g_snprintf(buf, 1+TIME_SECS_LEN+1+6+1, "0.000000000 seconds");
652 * We assume here that "rel_time->secs" is negative
653 * or zero; if it's not, the time stamp is bogus,
654 * with a positive seconds and negative microseconds.
656 time = (gint) -rel_time->secs;
659 time_secs_to_str_buf(time, nsec, TRUE, p, 1+TIME_SECS_LEN+1+6+1);
663 #define REL_TIME_SECS_LEN (1+10+1+9+1)
666 * Display a relative time as seconds.
669 rel_time_to_secs_str(nstime_t *rel_time)
673 buf=ep_alloc(REL_TIME_SECS_LEN);
675 display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
676 rel_time->nsecs, NSECS);
682 remove this one later when every call has been converted to address_to_str()
685 fc_to_str(const guint8 *ad)
687 return bytestring_to_str (ad, 3, '.');
690 /* FC Network Header Network Address Authority Identifiers */
692 #define FC_NH_NAA_IEEE 1 /* IEEE 802.1a */
693 #define FC_NH_NAA_IEEE_E 2 /* IEEE Exteneded */
694 #define FC_NH_NAA_LOCAL 3
695 #define FC_NH_NAA_IP 4 /* 32-bit IP address */
696 #define FC_NH_NAA_IEEE_R 5 /* IEEE Registered */
697 #define FC_NH_NAA_IEEE_R_E 6 /* IEEE Registered Exteneded */
698 /* according to FC-PH 3 draft these are now reclaimed and reserved */
699 #define FC_NH_NAA_CCITT_INDV 12 /* CCITT 60 bit individual address */
700 #define FC_NH_NAA_CCITT_GRP 14 /* CCITT 60 bit group address */
703 fcwwn_to_str (const guint8 *ad)
709 if (ad == NULL) return NULL;
711 ethstr=ep_alloc(512);
713 fmt = (ad[0] & 0xF0) >> 4;
718 case FC_NH_NAA_IEEE_E:
719 memcpy (oui, &ad[2], 6);
720 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
721 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
722 get_manuf_name (oui));
725 case FC_NH_NAA_IEEE_R:
726 oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
727 oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
728 oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
729 oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
730 oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
731 oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
733 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
734 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
735 get_manuf_name (oui));
739 g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
740 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
746 /* Generate, into "buf", a string showing the bits of a bitfield.
747 Return a pointer to the character after that string. */
748 /*XXX this needs a buf_len check */
750 other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
758 bit = 1 << (width - 1);
761 /* This bit is part of the field. Show its value. */
767 /* This bit is not part of the field. */
782 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
786 p = other_decode_bitfield_value(buf, val, mask, width);
792 /* Generate a string describing a Boolean bitfield (a one-bit field that
793 says something is either true of false). */
795 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
796 const char *truedesc, const char *falsedesc)
801 buf=ep_alloc(1025); /* is this a bit overkill? */
802 p = decode_bitfield_value(buf, val, mask, width);
806 strcpy(p, falsedesc);
810 /* Generate a string describing a numeric bitfield (an N-bit field whose
811 value is just a number). */
813 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
820 buf=ep_alloc(1025); /* isnt this a bit overkill? */
821 /* Compute the number of bits we have to shift the bitfield right
822 to extract its value. */
823 while ((mask & (1<<shift)) == 0)
826 p = decode_bitfield_value(buf, val, mask, width);
827 g_snprintf(p, 1025-(p-buf), fmt, (val & mask) >> shift);
832 /*XXX FIXME the code below may be called very very frequently in the future.
833 optimize it for speed and get rid of the slow sprintfs */
834 /* XXX - perhaps we should have individual address types register
835 a table of routines to do operations such as address-to-name translation,
836 address-to-string translation, and the like, and have this call them,
837 and also have an address-to-string-with-a-name routine */
838 /* XXX - use this, and that future address-to-string-with-a-name routine,
839 in "col_set_addr()"; it might also be useful to have address types
840 export the names of the source and destination address fields, so
841 that "col_set_addr()" need know nothing whatsoever about particular
843 /* convert an address struct into a printable string */
845 address_to_str(const address *addr)
849 str=ep_alloc(MAX_ADDR_STR_LEN);
850 address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
855 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
857 const guint8 *addrdata;
859 struct atalk_ddp_addr ddp_addr;
866 g_snprintf(buf, buf_len, "%s", "");
869 addrdata = addr->data;
870 g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", addrdata[0], addrdata[1], addrdata[2], addrdata[3], addrdata[4], addrdata[5]);
873 ip_to_str_buf(addr->data, buf, buf_len);
876 if ( inet_ntop(AF_INET6, addr->data, buf, buf_len) == NULL ) /* Returns NULL if no space and does not touch buf */
877 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
880 addrdata = addr->data;
881 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]);
884 sna_fid_to_str_buf(addr, buf, buf_len);
887 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
888 atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
891 vines_addr_to_str_buf(addr->data, buf, buf_len);
894 usb_addr_to_str_buf(addr->data, buf, buf_len);
897 print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
900 addrdata = addr->data;
901 g_snprintf(buf, buf_len, "0x%02X", addrdata[0]);
904 addrdata = addr->data;
905 g_snprintf(buf, buf_len, "%02x.%02x.%02x", addrdata[0], addrdata[1], addrdata[2]);
908 mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
911 addrstr = addr->data;
912 g_snprintf(buf, buf_len, "%s", addrstr);
915 addrdata = addr->data;
916 g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
917 addrdata[0], addrdata[1], addrdata[2], addrdata[3],
918 addrdata[4], addrdata[5], addrdata[6], addrdata[7]);
921 int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
922 memcpy(buf, addr->data, copy_len );
923 buf[copy_len] = '\0';
927 tipc_addr_to_str_buf(addr->data, buf, buf_len);
930 g_assert_not_reached();
934 gchar* guid_to_str(const e_guid_t *guid) {
937 buf=ep_alloc(GUID_STR_LEN);
938 return guid_to_str_buf(guid, buf, GUID_STR_LEN);
941 gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
942 g_snprintf(buf, buf_len, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
943 guid->data1, guid->data2, guid->data3,
944 guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3], guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
949 tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
953 guint32 tipc_address;
955 tipc_address = data[0];
956 tipc_address = (tipc_address << 8) ^ data[1];
957 tipc_address = (tipc_address << 8) ^ data[2];
958 tipc_address = (tipc_address << 8) ^ data[3];
960 processor = tipc_address & 0x0fff;
962 tipc_address = tipc_address >> 12;
963 subnetwork = tipc_address & 0x0fff;
965 tipc_address = tipc_address >> 12;
966 zone = tipc_address & 0xff;
968 g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);