wireshark/epan/dissectors/packet-isis.c
Guy Harris a4c8ebc18b Don't do any Decode As stuff for dissector tables not used with Decode As.
Have all dissector tables have a "supports Decode As" flag, which
defaults to FALSE, and which is set to TRUE if a register_decode_as()
refers to it.

When adding a dissector to a dissector table with a given key, only add
it for Decode As if the dissector table supports it.

For non-FT_STRING dissector tables, always check for multiple entries
for the same protocol with different dissectors, and report an error if
we found them.

This means there's no need for the creator of a dissector table to
specify whether duplicates of that sort should be allowed - we always do
the check when registering something for "Decode As" (in a non-FT_STRING
dissector table), and just don't bother registering anything for "Decode
As" if the dissector table doesn't support "Decode As", so there's no
check done for those dissector tables.

Change-Id: I4a1fdea3bddc2af27a65cfbca23edc99b26c0eed
Reviewed-on: https://code.wireshark.org/review/17402
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-08-31 00:08:01 +00:00

237 lines
7.8 KiB
C

/* packet-isis.c
* Routines for ISO/OSI network and transport protocol packet disassembly, core
* bits.
*
* Stuart Stanley <stuarts@mxmail.net>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/nlpid.h>
#include <epan/etypes.h>
#include "packet-osi.h"
#include "packet-isis.h"
void proto_register_isis(void);
void proto_reg_handoff_isis(void);
static dissector_table_t isis_dissector_table;
/* isis base header */
static int proto_isis = -1;
static int hf_isis_irpd = -1;
static int hf_isis_header_length = -1;
static int hf_isis_version = -1;
static int hf_isis_system_id_length = -1;
static int hf_isis_type = -1;
static int hf_isis_type_reserved = -1;
static int hf_isis_version2 = -1;
static int hf_isis_reserved = -1;
static int hf_isis_max_area_adr = -1;
static gint ett_isis = -1;
static expert_field ei_isis_version = EI_INIT;
static expert_field ei_isis_type = EI_INIT;
static dissector_handle_t isis_handle;
static const value_string isis_vals[] = {
{ ISIS_TYPE_L1_HELLO, "L1 HELLO"},
{ ISIS_TYPE_L2_HELLO, "L2 HELLO"},
{ ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
{ ISIS_TYPE_L1_LSP, "L1 LSP"},
{ ISIS_TYPE_L2_LSP, "L2 LSP"},
{ ISIS_TYPE_L1_CSNP, "L1 CSNP"},
{ ISIS_TYPE_L2_CSNP, "L2 CSNP"},
{ ISIS_TYPE_L1_PSNP, "L1 PSNP"},
{ ISIS_TYPE_L2_PSNP, "L2 PSNP"},
{ 0, NULL}
};
static int
dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ti, *version_item;
proto_tree *isis_tree = NULL;
int offset = 0;
guint8 isis_version;
guint8 isis_type;
tvbuff_t *next_tvb;
isis_data_t subdissector_data;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS");
col_clear(pinfo->cinfo, COL_INFO);
ti = proto_tree_add_item(tree, proto_isis, tvb, 0, -1, ENC_NA);
isis_tree = proto_item_add_subtree(ti, ett_isis);
proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1, ENC_BIG_ENDIAN );
offset += 1;
subdissector_data.header_length = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
offset, 1, subdissector_data.header_length );
offset += 1;
isis_version = tvb_get_guint8(tvb, offset);
version_item = proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
offset, 1, isis_version );
if (isis_version != ISIS_REQUIRED_VERSION){
col_add_fstr(pinfo->cinfo, COL_INFO,
"Unknown ISIS version (%u vs %u)",
isis_version, ISIS_REQUIRED_VERSION );
expert_add_info(pinfo, version_item, &ei_isis_version);
}
offset += 1;
subdissector_data.system_id_len = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
offset, 1, subdissector_data.system_id_len );
offset += 1;
isis_type = tvb_get_guint8(tvb, offset) & ISIS_TYPE_MASK;
col_add_str(pinfo->cinfo, COL_INFO,
val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );
proto_tree_add_item(isis_tree, hf_isis_type, tvb, offset, 1, ENC_BIG_ENDIAN );
proto_tree_add_item(isis_tree, hf_isis_type_reserved, tvb, offset, 1, ENC_BIG_ENDIAN );
offset += 1;
proto_tree_add_item(isis_tree, hf_isis_version2, tvb, offset, 1, ENC_BIG_ENDIAN );
offset += 1;
proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, offset, 1, ENC_BIG_ENDIAN );
offset += 1;
proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, offset, 1, ENC_BIG_ENDIAN );
offset += 1;
/*
* Interpret the system ID length.
*/
if (subdissector_data.system_id_len == 0)
subdissector_data.system_id_len = 6; /* zero means 6-octet ID field length */
else if (subdissector_data.system_id_len == 255) {
subdissector_data.system_id_len = 0; /* 255 means null ID field */
/* XXX - what about the LAN ID? */
}
/* XXX - otherwise, must be in the range 1 through 8 */
next_tvb = tvb_new_subset_remaining(tvb, offset);
if (!dissector_try_uint_new(isis_dissector_table, isis_type, next_tvb,
pinfo, tree, TRUE, &subdissector_data))
{
proto_tree_add_expert(tree, pinfo, &ei_isis_type, tvb, offset, -1);
}
return tvb_captured_length(tvb);
} /* dissect_isis */
void
proto_register_isis(void)
{
static hf_register_info hf[] = {
{ &hf_isis_irpd,
{ "Intra Domain Routing Protocol Discriminator", "isis.irpd",
FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, NULL, HFILL }},
{ &hf_isis_header_length,
{ "PDU Header Length", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_isis_version,
{ "Version", "isis.version", FT_UINT8,
BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_isis_system_id_length,
{ "System ID Length", "isis.sysid_len",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_isis_type,
{ "PDU Type", "isis.type", FT_UINT8, BASE_DEC,
VALS(isis_vals), ISIS_TYPE_MASK, NULL, HFILL }},
{ &hf_isis_type_reserved,
{ "Reserved", "isis.reserved", FT_UINT8, BASE_HEX,
NULL, ISIS_TYPE_RESERVED_MASK, NULL, HFILL }},
{ &hf_isis_version2,
{ "Version2 (==1)", "isis.version2", FT_UINT8, BASE_DEC, NULL,
0x0, NULL, HFILL }},
{ &hf_isis_reserved,
{ "Reserved (==0)", "isis.reserved", FT_UINT8, BASE_DEC, NULL,
0x0, NULL, HFILL }},
{ &hf_isis_max_area_adr,
{ "Max.AREAs: (0==3)", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL,
0x0, NULL, HFILL }},
};
/*
* Note, we pull in the unknown CLV handler here, since it
* is used by all ISIS packet types.
*/
static gint *ett[] = {
&ett_isis,
};
static ei_register_info ei[] = {
{ &ei_isis_version, { "isis.version.unknown", PI_PROTOCOL, PI_WARN, "Unknown ISIS version", EXPFILL }},
{ &ei_isis_type, { "isis.type.unknown", PI_PROTOCOL, PI_WARN, "Unknown ISIS packet type", EXPFILL }},
};
expert_module_t* expert_isis;
proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "ISIS", "isis");
proto_register_field_array(proto_isis, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_isis = expert_register_protocol(proto_isis);
expert_register_field_array(expert_isis, ei, array_length(ei));
isis_handle = register_dissector("isis", dissect_isis, proto_isis);
isis_dissector_table = register_dissector_table("isis.type",
"ISIS Type", proto_isis, FT_UINT8, BASE_DEC);
}
void
proto_reg_handoff_isis(void)
{
dissector_add_uint("osinl.incl", NLPID_ISO10589_ISIS, isis_handle);
dissector_add_uint("ethertype", ETHERTYPE_L2ISIS, isis_handle);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/