aboutsummaryrefslogtreecommitdiffstats
path: root/epan/address_types.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/address_types.c')
-rw-r--r--epan/address_types.c290
1 files changed, 263 insertions, 27 deletions
diff --git a/epan/address_types.c b/epan/address_types.c
index 48b0e26b74..61d3f52a2d 100644
--- a/epan/address_types.c
+++ b/epan/address_types.c
@@ -52,6 +52,7 @@ struct _address_type_t {
AddrValueToString addr_to_str;
AddrValueToStringLen addr_str_len;
AddrColFilterString addr_col_filter;
+ AddrFixedLen addr_fixed_len;
/* XXX - Some sort of compare functions (like ftype)? ***/
/* XXX - Include functions for name resolution? ***/
@@ -88,7 +89,7 @@ static void address_type_register(int addr_type, address_type_t *at)
int address_type_dissector_register(const char* name, const char* pretty_name,
AddrValueToString to_str_func, AddrValueToStringLen str_len_func,
- AddrColFilterString col_filter_str_func)
+ AddrColFilterString col_filter_str_func, AddrFixedLen fixed_len_func)
{
int addr_type;
@@ -108,8 +109,9 @@ int address_type_dissector_register(const char* name, const char* pretty_name,
dissector_type_addresses[num_dissector_addr_type].addr_to_str = to_str_func;
dissector_type_addresses[num_dissector_addr_type].addr_str_len = str_len_func;
dissector_type_addresses[num_dissector_addr_type].addr_col_filter = col_filter_str_func;
+ dissector_type_addresses[num_dissector_addr_type].addr_fixed_len = fixed_len_func;
- type_list[addr_type] = &dissector_type_addresses[num_dissector_addr_type];
+ type_list[addr_type] = &dissector_type_addresses[num_dissector_addr_type];
num_dissector_addr_type++;
@@ -130,6 +132,11 @@ int none_addr_str_len(const address* addr _U_)
return 1; /* NULL character for empty string */
}
+int none_addr_len(void)
+{
+ return 0;
+}
+
/******************************************************************************
* AT_ETHER
******************************************************************************/
@@ -145,7 +152,7 @@ int ether_str_len(const address* addr _U_)
return 18;
}
-const char* ether_col_filter_str(const address* addr _U_, gboolean is_src)
+static const char* ether_col_filter_str(const address* addr _U_, gboolean is_src)
{
if (is_src)
return "eth.src";
@@ -153,6 +160,11 @@ const char* ether_col_filter_str(const address* addr _U_, gboolean is_src)
return "eth.dst";
}
+int ether_len(void)
+{
+ return 6;
+}
+
/******************************************************************************
* AT_IPv4
******************************************************************************/
@@ -167,7 +179,7 @@ static int ipv4_str_len(const address* addr _U_)
return MAX_IP_STR_LEN;
}
-const char* ipv4_col_filter_str(const address* addr _U_, gboolean is_src)
+static const char* ipv4_col_filter_str(const address* addr _U_, gboolean is_src)
{
if (is_src)
return "ip.src";
@@ -175,14 +187,134 @@ const char* ipv4_col_filter_str(const address* addr _U_, gboolean is_src)
return "ip.dst";
}
+static int ipv4_len(void)
+{
+ return 4;
+}
+
/******************************************************************************
* AT_IPv6
******************************************************************************/
-static gboolean ipv6_to_str(const address* addr, gchar *buf, int buf_len _U_)
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static void
+ip6_to_str_buf_len(const guchar* src, char *buf, size_t buf_len)
+{
+ struct { int base, len; } best, cur;
+ guint words[8];
+ int i;
+
+ if (buf_len < MAX_IP6_STR_LEN) { /* buf_len < 40 */
+ g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
+ return;
+ }
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ for (i = 0; i < 16; i += 2) {
+ words[i / 2] = (src[i+1] << 0);
+ words[i / 2] |= (src[i] << 8);
+ }
+ best.base = -1; best.len = 0;
+ cur.base = -1; cur.len = 0;
+ for (i = 0; i < 8; i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1) {
+ cur.base = i;
+ cur.len = 1;
+ } else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /* Is this address an encapsulated IPv4? */
+ /* XXX,
+ * Orginal code dated 1996 uses ::/96 as a valid IPv4-compatible addresses
+ * but since Feb 2006 ::/96 is deprecated one.
+ * Quoting wikipedia [0]:
+ * > The 96-bit zero-value prefix ::/96, originally known as IPv4-compatible
+ * > addresses, was mentioned in 1995[35] but first described in 1998.[41]
+ * > This class of addresses was used to represent IPv4 addresses within
+ * > an IPv6 transition technology. Such an IPv6 address has its first
+ * > (most significant) 96 bits set to zero, while its last 32 bits are the
+ * > IPv4 address that is represented.
+ * > In February 2006 the Internet Engineering Task Force (IETF) has deprecated
+ * > the use of IPv4-compatible addresses.[1] The only remaining use of this address
+ * > format is to represent an IPv4 address in a table or database with fixed size
+ * > members that must also be able to store an IPv6 address.
+ *
+ * If needed it can be fixed by changing next line:
+ * if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
+ * to:
+ * if (best.base == 0 && best.len == 5 && words[5] == 0xffff)
+ *
+ * [0] http://en.wikipedia.org/wiki/IPv6_address#Historical_notes
+ */
+
+ if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
+ {
+ /* best.len == 6 -> ::IPv4; 5 -> ::ffff:IPv4 */
+ buf = g_stpcpy(buf, "::");
+ if (best.len == 5)
+ buf = g_stpcpy(buf, "ffff:");
+ ip_to_str_buf(src + 12, buf, MAX_IP_STR_LEN);
+ /* max: 2 + 5 + 16 == 23 bytes */
+ return;
+ }
+
+ /*
+ * Format the result.
+ */
+ for (i = 0; i < 8; i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (i == best.base) {
+ *buf++ = ':';
+ i += best.len;
+
+ /* Was it a trailing run of 0x00's? */
+ if (i == 8) {
+ *buf++ = ':';
+ break;
+ }
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *buf++ = ':';
+
+ buf = word_to_hex_npad(buf, words[i]); /* max: 4B */
+ /* max: 8 * 4 + 7 == 39 bytes */
+ }
+ *buf = '\0'; /* 40 byte */
+}
+
+void
+ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
{
- /* XXX - pull in ip6_to_str_buf_len as this should be the module for it */
+ ip6_to_str_buf_len((const guchar*)ad, buf, MAX_IP6_STR_LEN);
+}
- ip6_to_str_buf((const struct e_in6_addr*)addr->data, buf/*, buf_len*/);
+static gboolean ipv6_to_str(const address* addr, gchar *buf, int buf_len)
+{
+ ip6_to_str_buf_len((const guchar*)addr->data, buf, buf_len);
return TRUE;
}
@@ -191,7 +323,7 @@ static int ipv6_str_len(const address* addr _U_)
return MAX_IP6_STR_LEN;
}
-const char* ipv6_col_filter_str(const address* addr _U_, gboolean is_src)
+static const char* ipv6_col_filter_str(const address* addr _U_, gboolean is_src)
{
if (is_src)
return "ipv6.src";
@@ -199,6 +331,11 @@ const char* ipv6_col_filter_str(const address* addr _U_, gboolean is_src)
return "ipv6.dst";
}
+static int ipv6_len(void)
+{
+ return 16;
+}
+
/******************************************************************************
* AT_IPX
******************************************************************************/
@@ -218,6 +355,11 @@ static int ipx_str_len(const address* addr _U_)
return 22;
}
+static int ipx_len(void)
+{
+ return 10;
+}
+
/******************************************************************************
* AT_VINES
* XXX - This functionality should really be in packet-vines.c as a dissector
@@ -240,6 +382,11 @@ static int vines_str_len(const address* addr _U_)
return 14;
}
+static int vines_len(void)
+{
+ return VINES_ADDR_LEN;
+}
+
/******************************************************************************
* AT_FC
******************************************************************************/
@@ -256,6 +403,10 @@ static int fc_str_len(const address* addr _U_)
return 9;
}
+static int fc_len(void)
+{
+ return 3;
+}
/******************************************************************************
* AT_FCWWN
@@ -324,6 +475,11 @@ static int fcwwn_str_len(const address* addr _U_)
return 200;
}
+static int fcwwn_len(void)
+{
+ return FCWWN_ADDR_LEN;
+}
+
/******************************************************************************
* AT_SS7PC
* XXX - This should really be a dissector address type as its address string
@@ -366,7 +522,12 @@ static gboolean eui64_addr_to_str(const address* addr, gchar *buf, int buf_len _
static int eui64_str_len(const address* addr _U_)
{
- return 24;
+ return EUI64_STR_LEN;
+}
+
+static int eui64_len(void)
+{
+ return 8;
}
/******************************************************************************
@@ -445,7 +606,7 @@ static int ax25_addr_str_len(const address* addr _U_)
return 21; /* Leaves extra space (10 bytes) just for uint_to_str_back() */
}
-const char* ax25_col_filter_str(const address* addr _U_, gboolean is_src)
+static const char* ax25_col_filter_str(const address* addr _U_, gboolean is_src)
{
if (is_src)
return "ax25.src";
@@ -453,6 +614,11 @@ const char* ax25_col_filter_str(const address* addr _U_, gboolean is_src)
return "ax25.dst";
}
+static int ax25_len(void)
+{
+ return AX25_ADDR_LEN;
+}
+
/******************************************************************************
* END OF PROVIDED ADDRESS TYPES
******************************************************************************/
@@ -468,7 +634,8 @@ void address_types_initialize(void)
"No address", /* pretty_name */
none_addr_to_str, /* addr_to_str */
none_addr_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ none_addr_len /* addr_fixed_len */
};
static address_type_t ether_address = {
@@ -477,7 +644,8 @@ void address_types_initialize(void)
"Ethernet address", /* pretty_name */
ether_to_str, /* addr_to_str */
ether_str_len, /* addr_str_len */
- ether_col_filter_str /* addr_col_filter */
+ ether_col_filter_str, /* addr_col_filter */
+ ether_len /* addr_fixed_len */
};
static address_type_t ipv4_address = {
@@ -486,7 +654,8 @@ void address_types_initialize(void)
"IPv4 address", /* pretty_name */
ipv4_to_str, /* addr_to_str */
ipv4_str_len, /* addr_str_len */
- ipv4_col_filter_str /* addr_col_filter */
+ ipv4_col_filter_str, /* addr_col_filter */
+ ipv4_len /* addr_fixed_len */
};
static address_type_t ipv6_address = {
@@ -495,7 +664,8 @@ void address_types_initialize(void)
"IPv6 address", /* pretty_name */
ipv6_to_str, /* addr_to_str */
ipv6_str_len, /* addr_str_len */
- ipv6_col_filter_str /* addr_col_filter */
+ ipv6_col_filter_str, /* addr_col_filter */
+ ipv6_len /* addr_fixed_len */
};
static address_type_t ipx_address = {
@@ -504,7 +674,8 @@ void address_types_initialize(void)
"IPX address", /* pretty_name */
ipx_to_str, /* addr_to_str */
ipx_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ ipx_len /* addr_fixed_len */
};
static address_type_t vines_address = {
@@ -513,7 +684,8 @@ void address_types_initialize(void)
"Banyan Vines address", /* pretty_name */
vines_to_str, /* addr_to_str */
vines_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ vines_len /*addr_fixed_len */
};
static address_type_t fc_address = {
@@ -522,7 +694,8 @@ void address_types_initialize(void)
"FC address", /* pretty_name */
fc_to_str, /* addr_to_str */
fc_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ fc_len /*addr_fixed_len */
};
static address_type_t fcwwn_address = {
@@ -531,7 +704,8 @@ void address_types_initialize(void)
"Fibre Channel WWN", /* pretty_name */
fcwwn_to_str, /* addr_to_str */
fcwwn_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ fcwwn_len /* addr_fixed_len */
};
static address_type_t ss7pc_address = {
@@ -540,7 +714,8 @@ void address_types_initialize(void)
"SS7 Point Code", /* pretty_name */
ss7pc_to_str, /* addr_to_str */
ss7pc_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ NULL /* addr_fixed_len */
};
static address_type_t stringz_address = {
@@ -549,7 +724,8 @@ void address_types_initialize(void)
"String address", /* pretty_name */
stringz_addr_to_str, /* addr_to_str */
stringz_addr_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ NULL /* addr_fixed_len */
};
static address_type_t eui64_address = {
@@ -558,7 +734,8 @@ void address_types_initialize(void)
"IEEE EUI-64", /* pretty_name */
eui64_addr_to_str, /* addr_to_str */
eui64_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ eui64_len /* addr_fixed_len */
};
static address_type_t ib_address = {
@@ -567,7 +744,8 @@ void address_types_initialize(void)
"Infiniband GID/LID", /* pretty_name */
ib_addr_to_str, /* addr_to_str */
ib_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ NULL /* addr_fixed_len */
};
static address_type_t usb_address = {
@@ -576,7 +754,8 @@ void address_types_initialize(void)
"USB Address", /* pretty_name */
usb_addr_to_str, /* addr_to_str */
usb_addr_str_len, /* addr_str_len */
- NULL /* addr_col_filter */
+ NULL, /* addr_col_filter */
+ NULL /* addr_fixed_len */
};
static address_type_t ax25_address = {
@@ -585,7 +764,8 @@ void address_types_initialize(void)
"AX.25 Address", /* pretty_name */
ax25_addr_to_str, /* addr_to_str */
ax25_addr_str_len,/* addr_str_len */
- ax25_col_filter_str /* addr_col_filter */
+ ax25_col_filter_str, /* addr_col_filter */
+ ax25_len /* addr_fixed_len */
};
num_dissector_addr_type = 0;
@@ -616,8 +796,7 @@ void address_types_initialize(void)
g_assert(addr_type < MAX_ADDR_TYPE_VALUE); \
result = type_list[addr_type];
-/* XXX - Temporary? Here at least until all of the address type handling is finalized */
-int address_type_get_length(const address* addr)
+static int address_type_get_length(const address* addr)
{
address_type_t *at;
@@ -629,7 +808,29 @@ int address_type_get_length(const address* addr)
return at->addr_str_len(addr);
}
-void address_type_to_string(const address* addr, gchar *buf, int buf_len)
+/*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 */
+/* convert an address struct into a printable string */
+
+gchar*
+address_to_str(wmem_allocator_t *scope, const address *addr)
+{
+ gchar *str;
+ int len = address_type_get_length(addr);
+
+ if (len <= 0)
+ len = MAX_ADDR_STR_LEN;
+
+ str=(gchar *)wmem_alloc(scope, len);
+ address_to_str_buf(addr, str, len);
+ return str;
+}
+
+void address_to_str_buf(const address* addr, gchar *buf, int buf_len)
{
address_type_t *at;
@@ -661,6 +862,41 @@ const char* address_type_column_filter_string(const address* addr, gboolean src)
return at->addr_col_filter(addr, src);
}
+gchar*
+tvb_address_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int type, const gint offset)
+{
+ address addr;
+ address_type_t *at;
+
+ ADDR_TYPE_LOOKUP(type, at);
+
+ if (at == NULL)
+ {
+ return NULL;
+ }
+
+ /* The address type must have a fixed length to use this function */
+ /* For variable length fields, use tvb_address_var_to_str() */
+ if (at->addr_fixed_len == NULL)
+ {
+ g_assert_not_reached();
+ return NULL;
+ }
+
+ TVB_SET_ADDRESS(&addr, type, tvb, offset, at->addr_fixed_len());
+
+ return address_to_str(scope, &addr);
+}
+
+gchar* tvb_address_var_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, address_type type, const gint offset, int length)
+{
+ address addr;
+
+ TVB_SET_ADDRESS(&addr, type, tvb, offset, length);
+
+ return address_to_str(scope, &addr);
+}
+
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html