summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Heilmeier <uh@heilmeier.eu>2016-03-13 23:16:20 +0100
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2016-03-18 05:41:36 +0000
commite1d54cfc3e8223bb4334e5aeed019dab35528e9b (patch)
treeab97ecbc78feb49dcd60f7b0bc053ac1954dfe5f
parenteb6abe3a75f80776865332d4c28977a348b09a52 (diff)
downloadwireshark-e1d54cfc3e8223bb4334e5aeed019dab35528e9b.tar.gz
IEEE 802.1Q/VLAN: Resolve ID to a describing name
A vlans file in the personal preference directory add an option to resolve VLAN IDs to a describing name. Format of vlan file is 123\tName of VLAN To enable the resolving the preference nameres.vlan_name must be set to TRUE. Bug: 11209 Change-Id: I3f00b4897aace89c03c57b68b6c4b6c8b7d4685a Reviewed-on: https://code.wireshark.org/review/14471 Reviewed-by: Michael Mann <mmann78@netscape.net> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
-rw-r--r--epan/addr_resolv.c199
-rw-r--r--epan/addr_resolv.h12
-rw-r--r--epan/dissectors/packet-vlan.c15
-rw-r--r--epan/prefs.c3
-rw-r--r--ui/gtk/main.c3
5 files changed, 230 insertions, 2 deletions
diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index db96820a17..f1c3d79335 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -3,6 +3,9 @@
*
* Laurent Deniel <laurent.deniel@free.fr>
*
+ * Add option to resolv VLAN ID to describing name
+ * Uli Heilmeier, March 2016
+ *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
@@ -125,6 +128,7 @@
#define ENAME_IPXNETS "ipxnets"
#define ENAME_MANUF "manuf"
#define ENAME_SERVICES "services"
+#define ENAME_VLANS "vlans"
#define HASHETHSIZE 2048
#define HASHHOSTSIZE 2048
@@ -164,6 +168,12 @@ typedef struct hashipxnet {
gchar name[MAXNAMELEN];
} hashipxnet_t;
+typedef struct hashvlan {
+ guint id;
+/* struct hashvlan *next; */
+ gchar name[MAXVLANNAMELEN];
+} hashvlan_t;
+
/* hash tables used for ethernet and manufacturer lookup */
#define HASHETHER_STATUS_UNRESOLVED 1
#define HASHETHER_STATUS_RESOLVED_DUMMY 2
@@ -197,9 +207,17 @@ typedef struct _ipxnet
char name[MAXNAMELEN];
} ipxnet_t;
+/* internal vlan type */
+typedef struct _vlan
+{
+ guint id;
+ char name[MAXVLANNAMELEN];
+} vlan_t;
+
static GHashTable *ipxnet_hash_table = NULL;
static GHashTable *ipv4_hash_table = NULL;
static GHashTable *ipv6_hash_table = NULL;
+static GHashTable *vlan_hash_table = NULL;
static GSList *manually_resolved_ipv4_list = NULL;
static GSList *manually_resolved_ipv6_list = NULL;
@@ -283,7 +301,8 @@ e_addr_resolve gbl_resolv_flags = {
TRUE, /* concurrent_dns */
TRUE, /* dns_pkt_addr_resolution */
TRUE, /* use_external_net_name_resolver */
- FALSE /* load_hosts_file_from_profile_only */
+ FALSE, /* load_hosts_file_from_profile_only */
+ FALSE /* vlan_name */
};
#if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
static guint name_resolve_concurrency = 500;
@@ -301,6 +320,7 @@ gchar *g_ipxnets_path = NULL; /* global ipxnets file */
gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
gchar *g_services_path = NULL; /* global services file */
gchar *g_pservices_path = NULL; /* personal services file */
+gchar *g_pvlan_path = NULL; /* personal vlans file */
/* first resolving call */
/* c-ares */
@@ -1947,6 +1967,153 @@ ipxnet_addr_lookup(const gchar *name _U_, gboolean *success)
#endif
} /* ipxnet_addr_lookup */
+/* VLANS */
+static int
+parse_vlan_line(char *line, vlan_t *vlan)
+{
+ gchar *cp;
+ guint16 id;
+
+ if ((cp = strchr(line, '#')))
+ *cp = '\0';
+
+ if ((cp = strtok(line, " \t\n")) == NULL)
+ return -1;
+
+ if (sscanf(cp, "%" G_GUINT16_FORMAT, &id) == 1) {
+ vlan->id = id;
+ }
+ else {
+ return -1;
+ }
+
+ if ((cp = strtok(NULL, "\t\n")) == NULL)
+ return -1;
+
+ g_strlcpy(vlan->name, cp, MAXVLANNAMELEN);
+
+ return 0;
+
+} /* parse_vlan_line */
+
+static FILE *vlan_p = NULL;
+
+static void
+set_vlanent(char *path)
+{
+ if (vlan_p)
+ rewind(vlan_p);
+ else
+ vlan_p = ws_fopen(path, "r");
+}
+
+static void
+end_vlanent(void)
+{
+ if (vlan_p) {
+ fclose(vlan_p);
+ vlan_p = NULL;
+ }
+}
+
+static vlan_t *
+get_vlanent(void)
+{
+
+ static vlan_t vlan;
+ static int size = 0;
+ static char *buf = NULL;
+
+ if (vlan_p == NULL)
+ return NULL;
+
+ while (fgetline(&buf, &size, vlan_p) >= 0) {
+ if (parse_vlan_line(buf, &vlan) == 0) {
+ return &vlan;
+ }
+ }
+
+ return NULL;
+
+} /* get_vlanent */
+
+static vlan_t *
+get_vlannamebyid(guint16 id)
+{
+ vlan_t *vlan;
+
+ set_vlanent(g_pvlan_path);
+
+ while (((vlan = get_vlanent()) != NULL) && (id != vlan->id) ) ;
+
+ if (vlan == NULL) {
+ end_vlanent();
+
+ }
+
+ return vlan;
+
+} /* get_vlannamebyid */
+
+static void
+initialize_vlans(void)
+{
+ g_assert(vlan_hash_table == NULL);
+ vlan_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+
+ /* Set g_pipxnets_path here, but don't actually do anything
+ * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
+ */
+ if (g_pvlan_path == NULL)
+ g_pvlan_path = get_persconffile_path(ENAME_VLANS, FALSE);
+
+} /* initialize_vlans */
+
+static void
+vlan_name_lookup_cleanup(void)
+{
+ if (vlan_hash_table) {
+ g_hash_table_destroy(vlan_hash_table);
+ vlan_hash_table = NULL;
+ }
+
+}
+
+static const gchar *
+vlan_name_lookup(const guint id)
+{
+ hashvlan_t *tp;
+ vlan_t *vlan;
+
+ tp = (hashvlan_t *)g_hash_table_lookup(vlan_hash_table, &id);
+ if (tp == NULL) {
+ int *key;
+
+ key = (int *)g_new(int, 1);
+ *key = id;
+ tp = g_new(hashvlan_t, 1);
+ g_hash_table_insert(vlan_hash_table, key, tp);
+ } else {
+ return tp->name;
+ }
+
+ /* fill in a new entry */
+
+ tp->id = id;
+
+ if ( (vlan = get_vlannamebyid(id)) == NULL) {
+ /* unknown name */
+ g_snprintf(tp->name, MAXVLANNAMELEN, "<%u>", id);
+
+ } else {
+ g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN);
+ }
+
+ return tp->name;
+
+} /* vlan_name_lookup */
+/* VLAN END */
+
static gboolean
read_hosts_file (const char *hostspath, gboolean store_entries)
{
@@ -2374,6 +2541,15 @@ addr_resolve_pref_init(module_t *nameres)
" Checking this box only loads the \"hosts\" in the current profile.",
&gbl_resolv_flags.load_hosts_file_from_profile_only);
+ prefs_register_bool_preference(nameres, "vlan_name",
+ "Resolve VLAN IDs",
+ "Resolve VLAN IDs to describing names."
+ " To do so you need a file called vlans in your"
+ " user preference directory. Format of the file is:"
+ " \"ID<Tab>Name\""
+ " One line per VLAN.",
+ &gbl_resolv_flags.vlan_name);
+
}
void
@@ -2384,6 +2560,7 @@ disable_name_resolution(void) {
gbl_resolv_flags.concurrent_dns = FALSE;
gbl_resolv_flags.dns_pkt_addr_resolution = FALSE;
gbl_resolv_flags.use_external_net_name_resolver = FALSE;
+ gbl_resolv_flags.vlan_name = FALSE;
}
#ifdef HAVE_C_ARES
@@ -3045,6 +3222,18 @@ get_ipxnet_addr(const gchar *name, gboolean *known)
} /* get_ipxnet_addr */
+gchar *
+get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
+{
+
+ if (!gbl_resolv_flags.vlan_name) {
+ return NULL;
+ }
+
+ return wmem_strdup(allocator, vlan_name_lookup(id));
+
+} /* get_vlan_name */
+
const gchar *
get_manuf_name(const guint8 *addr)
{
@@ -3434,6 +3623,12 @@ get_ipxnet_hash_table(void)
}
GHashTable *
+get_vlan_hash_table(void)
+{
+ return vlan_hash_table;
+}
+
+GHashTable *
get_ipv4_hash_table(void)
{
return ipv4_hash_table;
@@ -3451,6 +3646,7 @@ addr_resolv_init(void)
initialize_services();
initialize_ethers();
initialize_ipxnets();
+ initialize_vlans();
/* host name initialization is done on a per-capture-file basis */
/*host_name_lookup_init();*/
}
@@ -3462,6 +3658,7 @@ addr_resolv_cleanup(void)
service_name_lookup_cleanup();
eth_name_lookup_cleanup();
ipx_name_lookup_cleanup();
+ vlan_name_lookup_cleanup();
/* host name initialization is done on a per-capture-file basis */
/*host_name_lookup_cleanup();*/
}
diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h
index f5ee82901d..876aff2bc9 100644
--- a/epan/addr_resolv.h
+++ b/epan/addr_resolv.h
@@ -47,6 +47,10 @@ extern "C" {
#define MAXNAMELEN 64 /* max name length (hostname and port name) */
#endif
+#ifndef MAXVLANNAMELEN
+#define MAXVLANNAMELEN 128 /* max vlan name length */
+#endif
+
/**
* @brief Flags to control name resolution.
*/
@@ -58,6 +62,7 @@ typedef struct _e_addr_resolve {
gboolean dns_pkt_addr_resolution; /**< Whether to resolve addresses using captured DNS packets */
gboolean use_external_net_name_resolver; /**< Whether to system's configured DNS server to resolve names */
gboolean load_hosts_file_from_profile_only; /**< Whether to only load the hosts in the current profile, not hosts files */
+ gboolean vlan_name; /**< Whether to resolve VLAN IDs to names */
} e_addr_resolve;
#define ADDR_RESOLV_MACADDR(at) \
@@ -240,6 +245,10 @@ extern gchar *eui64_to_display(wmem_allocator_t *allocator, const guint64 addr);
* or a string formatted with "%X" if not */
extern gchar *get_ipxnet_name(wmem_allocator_t *allocator, const guint32 addr);
+/* get_vlan_name returns the logical name if found in a vlans file,
+ * or the VLAN ID itself as a string if not found*/
+extern gchar *get_vlan_name(wmem_allocator_t *allocator, const guint16 id);
+
WS_DLL_PUBLIC guint get_hash_ether_status(hashether_t* ether);
WS_DLL_PUBLIC char* get_hash_ether_hexaddr(hashether_t* ether);
WS_DLL_PUBLIC char* get_hash_ether_resolved_name(hashether_t* ether);
@@ -339,6 +348,9 @@ WS_DLL_PUBLIC
GHashTable *get_ipxnet_hash_table(void);
WS_DLL_PUBLIC
+GHashTable *get_vlan_hash_table(void);
+
+WS_DLL_PUBLIC
GHashTable *get_ipv4_hash_table(void);
WS_DLL_PUBLIC
diff --git a/epan/dissectors/packet-vlan.c b/epan/dissectors/packet-vlan.c
index 05ba381dac..915129b573 100644
--- a/epan/dissectors/packet-vlan.c
+++ b/epan/dissectors/packet-vlan.c
@@ -34,6 +34,7 @@
#include <epan/etypes.h>
#include <epan/prefs.h>
#include <epan/to_str.h>
+#include <epan/addr_resolv.h>
void proto_register_vlan(void);
void proto_reg_handoff_vlan(void);
@@ -81,6 +82,10 @@ static header_field_info hfi_vlan_id VLAN_HFI_INIT = {
"ID", "vlan.id", FT_UINT16, BASE_DEC,
NULL, 0x0FFF, "VLAN ID", HFILL };
+static header_field_info hfi_vlan_id_name VLAN_HFI_INIT = {
+ "Name", "vlan.id_name", FT_STRING, STR_UNICODE,
+ NULL, 0x0, "VLAN ID Name", HFILL };
+
static header_field_info hfi_vlan_etype VLAN_HFI_INIT = {
"Type", "vlan.etype", FT_UINT16, BASE_HEX,
VALS(etype_vals), 0x0, "Ethertype", HFILL };
@@ -141,6 +146,7 @@ dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
guint16 encap_proto;
gboolean is_802_2;
proto_tree *vlan_tree;
+ proto_item *item;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "VLAN");
col_clear(pinfo->cinfo, COL_INFO);
@@ -169,6 +175,14 @@ dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
proto_tree_add_item(vlan_tree, &hfi_vlan_priority, tvb, 0, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(vlan_tree, &hfi_vlan_cfi, tvb, 0, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(vlan_tree, &hfi_vlan_id, tvb, 0, 2, ENC_BIG_ENDIAN);
+
+ if (gbl_resolv_flags.vlan_name) {
+ item = proto_tree_add_string(vlan_tree, &hfi_vlan_id_name, tvb, 0, 2,
+ get_vlan_name(wmem_packet_scope(), vlan_id));
+ PROTO_ITEM_SET_GENERATED(item);
+
+ }
+
}
encap_proto = tvb_get_ntohs(tvb, 2);
@@ -214,6 +228,7 @@ proto_register_vlan(void)
&hfi_vlan_priority,
&hfi_vlan_cfi,
&hfi_vlan_id,
+ &hfi_vlan_id_name,
&hfi_vlan_etype,
&hfi_vlan_len,
&hfi_vlan_trailer,
diff --git a/epan/prefs.c b/epan/prefs.c
index 063e9c6268..fb99675ba0 100644
--- a/epan/prefs.c
+++ b/epan/prefs.c
@@ -3914,6 +3914,9 @@ string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
case 'd':
name_resolve->dns_pkt_addr_resolution = TRUE;
break;
+ case 'v':
+ name_resolve->vlan_name = TRUE;
+ break;
default:
/*
* Unrecognized letter.
diff --git a/ui/gtk/main.c b/ui/gtk/main.c
index 42215a4afb..b2e096d483 100644
--- a/ui/gtk/main.c
+++ b/ui/gtk/main.c
@@ -936,7 +936,8 @@ void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_)
TRUE, /* concurrent_dns */
TRUE, /* dns_pkt_addr_resolution */
TRUE, /* use_external_net_name_resolver */
- FALSE /* load_hosts_file_from_profile_only */
+ FALSE, /* load_hosts_file_from_profile_only */
+ FALSE /* vlan_name */
};
if (cfile.edt->tree) {