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>
This commit is contained in:
Uli Heilmeier 2016-03-13 23:16:20 +01:00 committed by Alexis La Goutte
parent eb6abe3a75
commit e1d54cfc3e
5 changed files with 230 additions and 2 deletions

View File

@ -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)
{
@ -3433,6 +3622,12 @@ get_ipxnet_hash_table(void)
return ipxnet_hash_table;
}
GHashTable *
get_vlan_hash_table(void)
{
return vlan_hash_table;
}
GHashTable *
get_ipv4_hash_table(void)
{
@ -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();*/
}

View File

@ -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);
@ -338,6 +347,9 @@ GHashTable *get_serv_port_hashtable(void);
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);

View File

@ -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,

View File

@ -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.

View File

@ -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) {