2 * Routines for utilities to convert addresses 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 "wsutil/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>
67 /* private to_str.c API, don't export to .h! */
68 char *word_to_hex(char *out, guint16 word);
69 char *word_to_hex_npad(char *out, guint16 word);
70 char *dword_to_hex_punct(char *out, guint32 dword, char punct);
71 char *dword_to_hex(char *out, guint32 dword);
72 char *bytes_to_hexstr(char *out, const guint8 *ad, guint32 len);
73 char *bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct);
76 * If a user _does_ pass in a too-small buffer, this is probably
77 * going to be too long to fit. However, even a partial string
78 * starting with "[Buf" should provide enough of a clue to be
81 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
83 /* Wrapper for the most common case of asking
84 * for a string using a colon as the hex-digit separator.
87 remove this one later when every call has been converted to ep_address_to_str()
90 ether_to_str(const guint8 *ad)
92 return bytestring_to_str(ad, 6, ':');
96 tvb_ether_to_str(tvbuff_t *tvb, const gint offset)
98 return bytestring_to_str(tvb_get_ptr(tvb, offset, 6), 6, ':');
102 This function is very fast and this function is called a lot.
103 XXX update the ep_address_to_str stuff to use this function.
106 ip_to_str(const guint8 *ad) {
109 buf=ep_alloc(MAX_IP_STR_LEN);
110 ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
114 #define IPV4_LENGTH 4
116 tvb_ip_to_str(tvbuff_t *tvb, const gint offset)
120 buf=ep_alloc(MAX_IP_STR_LEN);
121 ip_to_str_buf(tvb_get_ptr(tvb, offset, IPV4_LENGTH), buf, MAX_IP_STR_LEN);
126 remove this one later when every call has been converted to ep_address_to_str()
129 ip6_to_str(const struct e_in6_addr *ad) {
132 str=ep_alloc(MAX_IP6_STR_LEN);
133 ip6_to_str_buf(ad, str);
137 #define IPV6_LENGTH 16
139 tvb_ip6_to_str(tvbuff_t *tvb, const gint offset)
143 buf=ep_alloc(MAX_IP6_STR_LEN);
144 ip6_to_str_buf((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, IPV6_LENGTH), buf);
149 * inet_ntop6(src, dst, size)
150 * convert IPv6 binary address into presentation (printable) format
155 ip6_to_str_buf_len(const guchar* src, char *buf, size_t buf_len)
157 struct { int base, len; } best, cur;
161 if (buf_len < MAX_IP6_STR_LEN) { /* buf_len < 40 */
162 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
168 * Copy the input (bytewise) array into a wordwise array.
169 * Find the longest run of 0x00's in src[] for :: shorthanding.
171 for (i = 0; i < 16; i += 2) {
172 words[i / 2] = (src[i+1] << 0);
173 words[i / 2] |= (src[i] << 8);
177 for (i = 0; i < 8; i++) {
180 cur.base = i, cur.len = 1;
184 if (cur.base != -1) {
185 if (best.base == -1 || cur.len > best.len)
191 if (cur.base != -1) {
192 if (best.base == -1 || cur.len > best.len)
195 if (best.base != -1 && best.len < 2)
198 /* Is this address an encapsulated IPv4? */
199 if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
201 /* best.len == 6 -> ::IPv4; 5 -> ::ffff:IPv4 */
202 buf = g_stpcpy(buf, "::");
204 buf = g_stpcpy(buf, "ffff:");
205 ip_to_str_buf(src + 12, buf, MAX_IP_STR_LEN);
206 /* max: 2 + 5 + 16 == 23 bytes */
213 for (i = 0; i < 8; i++) {
214 /* Are we inside the best run of 0x00's? */
215 if (i == best.base) {
219 /* Was it a trailing run of 0x00's? */
225 /* Are we following an initial run of 0x00s or any real hex? */
229 buf = word_to_hex_npad(buf, words[i]); /* max: 4B */
230 /* max: 8 * 4 + 7 == 39 bytes */
232 *buf = '\0'; /* 40 byte */
236 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
238 ip6_to_str_buf_len((const guchar*)ad, buf, MAX_IP6_STR_LEN);
242 ipx_addr_to_str(const guint32 net, const guint8 *ad)
247 name = get_ether_name_if_known(ad);
250 buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net), name);
253 buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net),
254 bytestring_to_str(ad, 6, '\0'));
260 ipxnet_to_string(const guint8 *ad)
262 guint32 addr = pntohl(ad);
263 return ipxnet_to_str_punct(addr, ' ');
267 ipxnet_to_str_punct(const guint32 ad, const char punct)
269 gchar *buf = ep_alloc(12);
271 *dword_to_hex_punct(buf, ad, punct) = '\0';
276 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
279 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
283 buf = dword_to_hex(buf, pntohl(&addrp[0])); /* 8 bytes */
284 *buf++ = '.'; /* 1 byte */
285 buf = word_to_hex(buf, pntohs(&addrp[4])); /* 4 bytes */
286 *buf = '\0'; /* 1 byte */
290 tvb_vines_addr_to_str(tvbuff_t *tvb, const gint offset)
294 buf=ep_alloc(214); /* XXX, 14 here? */
296 vines_addr_to_str_buf(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN), buf, 214);
301 usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
303 if(pletohl(&addrp[0])==0xffffffff){
304 g_snprintf(buf, buf_len, "host");
306 g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
311 tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
315 guint32 tipc_address;
317 tipc_address = data[0];
318 tipc_address = (tipc_address << 8) ^ data[1];
319 tipc_address = (tipc_address << 8) ^ data[2];
320 tipc_address = (tipc_address << 8) ^ data[3];
322 processor = tipc_address & 0x0fff;
324 tipc_address = tipc_address >> 12;
325 subnetwork = tipc_address & 0x0fff;
327 tipc_address = tipc_address >> 12;
328 zone = tipc_address & 0xff;
330 g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);
334 ib_addr_to_str_buf( const address *addr, gchar *buf, int buf_len){
335 if (addr->len >= 16) { /* GID is 128bits */
336 #define PREAMBLE_STR_LEN (sizeof("GID: ") - 1)
337 g_snprintf(buf,buf_len,"GID: ");
338 if (buf_len < (int)PREAMBLE_STR_LEN ||
339 inet_ntop(AF_INET6, addr->data, buf + PREAMBLE_STR_LEN,
340 buf_len - PREAMBLE_STR_LEN) == NULL ) /* Returns NULL if no space and does not touch buf */
341 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
342 } else { /* this is a LID (16 bits) */
343 guint16 lid_number = *((guint16*) addr->data);
344 g_snprintf(buf,buf_len,"LID: %u",lid_number);
349 remove this one later when every call has been converted to ep_address_to_str()
352 fc_to_str(const guint8 *ad)
354 return bytestring_to_str (ad, 3, '.');
358 tvb_fc_to_str(tvbuff_t *tvb, const gint offset)
360 return bytestring_to_str (tvb_get_ptr(tvb, offset, 3), 3, '.');
363 /* FC Network Header Network Address Authority Identifiers */
365 #define FC_NH_NAA_IEEE 1 /* IEEE 802.1a */
366 #define FC_NH_NAA_IEEE_E 2 /* IEEE Exteneded */
367 #define FC_NH_NAA_LOCAL 3
368 #define FC_NH_NAA_IP 4 /* 32-bit IP address */
369 #define FC_NH_NAA_IEEE_R 5 /* IEEE Registered */
370 #define FC_NH_NAA_IEEE_R_E 6 /* IEEE Registered Exteneded */
371 /* according to FC-PH 3 draft these are now reclaimed and reserved */
372 #define FC_NH_NAA_CCITT_INDV 12 /* CCITT 60 bit individual address */
373 #define FC_NH_NAA_CCITT_GRP 14 /* CCITT 60 bit group address */
376 fcwwn_to_str (const guint8 *ad)
383 if (ad == NULL) return NULL;
385 ethstr=ep_alloc(512);
386 ethptr = bytes_to_hexstr_punct(ethstr, ad, 8, ':'); /* 23 bytes */
388 fmt = (ad[0] & 0xF0) >> 4;
393 case FC_NH_NAA_IEEE_E:
394 memcpy (oui, &ad[2], 6);
396 g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
399 case FC_NH_NAA_IEEE_R:
400 oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
401 oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
402 oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
403 oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
404 oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
405 oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
407 g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
418 tvb_fcwwn_to_str(tvbuff_t *tvb, const gint offset)
420 return fcwwn_to_str (tvb_get_ptr(tvb, offset, 8));
423 /*XXX FIXME the code below may be called very very frequently in the future.
424 optimize it for speed and get rid of the slow sprintfs */
425 /* XXX - perhaps we should have individual address types register
426 a table of routines to do operations such as address-to-name translation,
427 address-to-string translation, and the like, and have this call them,
428 and also have an address-to-string-with-a-name routine */
429 /* XXX - use this, and that future address-to-string-with-a-name routine,
430 in "col_set_addr()"; it might also be useful to have address types
431 export the names of the source and destination address fields, so
432 that "col_set_addr()" need know nothing whatsoever about particular
434 /* convert an address struct into a printable string */
437 ep_address_to_str(const address *addr)
441 str=ep_alloc(MAX_ADDR_STR_LEN);
442 address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
446 /* The called routines use se_alloc'ed memory */
448 se_address_to_str(const address *addr)
452 str=se_alloc(MAX_ADDR_STR_LEN);
453 address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
458 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
460 const guint8 *addrdata;
461 struct atalk_ddp_addr ddp_addr;
464 char *tempptr = temp;
466 if (!buf || !buf_len)
473 case AT_ETHER: /* 18 bytes */
474 tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 6, ':'); /* 17 bytes */
477 ip_to_str_buf(addr->data, buf, buf_len);
480 ip6_to_str_buf_len(addr->data, buf, buf_len);
482 case AT_IPX: /* 22 bytes */
483 addrdata = addr->data;
484 tempptr = bytes_to_hexstr(tempptr, &addrdata[0], 4); /* 8 bytes */
485 *tempptr++ = '.'; /* 1 byte */
486 tempptr = bytes_to_hexstr(tempptr, &addrdata[4], 6); /* 12 bytes */
489 sna_fid_to_str_buf(addr, buf, buf_len);
492 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
493 atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
496 vines_addr_to_str_buf(addr->data, buf, buf_len);
499 usb_addr_to_str_buf(addr->data, buf, buf_len);
502 print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
504 case AT_ARCNET: /* 5 bytes */
505 tempptr = g_stpcpy(tempptr, "0x"); /* 2 bytes */
506 tempptr = bytes_to_hexstr(tempptr, addr->data, 1); /* 2 bytes */
508 case AT_FC: /* 9 bytes */
509 tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 3, '.'); /* 8 bytes */
512 mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
515 g_strlcpy(buf, addr->data, buf_len);
517 case AT_EUI64: /* 24 bytes */
518 tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 8, ':'); /* 23 bytes */
521 int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
522 memcpy(buf, addr->data, copy_len );
523 buf[copy_len] = '\0';
527 tipc_addr_to_str_buf(addr->data, buf, buf_len);
530 ib_addr_to_str_buf(addr, buf, buf_len);
533 g_assert_not_reached();
536 /* copy to output buffer */
537 if (tempptr != temp) {
538 size_t temp_len = (size_t) (tempptr - temp);
540 if (temp_len < (size_t) buf_len) {
541 memcpy(buf, temp, temp_len);
542 buf[temp_len] = '\0';
544 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */