/* packet-docsis.c
* Routines for docsis dissection
- * Copyright 2002, Anand V. Narwani <anarwani@cisco.com>
+ * Copyright 2002, Anand V. Narwani <anand[AT]narwani.org>
*
- * $Id: packet-docsis.c,v 1.4 2002/07/21 00:22:17 guy Exp $
+ * $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * 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
/* This code is based on the DOCSIS 1.1 specification available at:
- * http://www.cablemodem.com/specifications.html
- *
- * DOCSIS Captures can be facilitated using the Cable Monitor Feature
+ * http://www.cablemodem.com/specifications/specifications11.html
+ *
+ * DOCSIS Captures can be facilitated using the Cable Monitor Feature
* available on Cisco Cable Modem Termination Systems :
* http://www.cisco.com/univercd/cc/td/doc/product/cable/cab_rout/cmtsfg/ufg_cmon.htm
*
* This dissector depends on the presence of a DOCSIS enapsulation type.
* There is no simple way to distinguish DOCSIS Frames from Ethernet frames,
- * since the frames are copied from the RF interface on the CMTS to
- * a Fast Ethernet interface; Thus a preference was needed to enable
+ * since the frames are copied from the RF interface on the CMTS to
+ * a Fast Ethernet interface; thus a preference was needed to enable
* the DOCSIS encapsulation type.
+ *
+ * The current CVS version of libpcap allows a link-layer header type to
+ * be specified for some interfaces on some platforms; for Ethernet
+ * interfaces, it allows DOCSIS to be specified. If an Ethernet capture
+ * is done with a link-layer type of DOCSIS, the file will have a link-
+ * layer type of DLT_DOCSIS; Wireshark will treat the frames in that capture
+ * as DOCSIS frames.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include "plugins/plugin_api.h"
-#include "plugins/plugin_api_defs.h"
-#include "moduleinfo.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#include <gmodule.h>
-
#include <epan/packet.h>
-
-#ifndef __ETHEREAL_STATIC__
-G_MODULE_EXPORT const gchar version[] = VERSION;
-#endif
-
-
#include "packet-docsis.h"
#define FCTYPE_PACKET 0x00
static int hf_docsis_eh_type = -1;
static int hf_docsis_eh_len = -1;
static int hf_docsis_eh_val = -1;
+static int hf_docsis_frag_rsvd = -1;
+static int hf_docsis_frag_first = -1;
+static int hf_docsis_frag_last = -1;
+static int hf_docsis_frag_seq = -1;
static int hf_docsis_sid = -1;
static int hf_docsis_mini_slots = -1;
static int hf_docsis_hcs = -1;
static int hf_docsis_key_seq = -1;
static int hf_docsis_ehdr_ver = -1;
static int hf_docsis_said = -1;
+static int hf_docsis_ehdr_phsi = -1;
+static int hf_docsis_ehdr_qind = -1;
+static int hf_docsis_ehdr_grants = -1;
static int hf_docsis_reserved = -1;
static dissector_handle_t docsis_handle;
-static dissector_handle_t eth_handle;
+static dissector_handle_t eth_withoutfcs_handle;
static dissector_handle_t data_handle;
static dissector_handle_t docsis_mgmt_handle;
static dissector_table_t docsis_dissector_table;
{0x1C, "Concatenation Header"},
{0, NULL}
};
-static const value_string ehdron_vals[] = {
- {0x00, "Extended Header Absent"},
- {0x01, "Extended Header Present"},
- {0, NULL}
+
+static const true_false_string ehdron_tfs = {
+ "Extended Header Present",
+ "Extended Header Absent"
};
static const true_false_string ena_dis_tfs = {
"Disabled"
};
-static const value_string ena_dis_vals[] = {
- {0, "Disabled"},
- {1, "Enabled"},
- {0, NULL}
+static const true_false_string qind_tfs = {
+ "Rate overrun",
+ "Rate non-overrun"
};
-static const value_string odd_even_vals[] = {
- {1, "Odd Key"},
- {0, "Even Key"},
- {0, NULL}
+static const true_false_string odd_even_tfs = {
+ "Odd Key",
+ "Even Key",
};
+
/* Code to actually dissect the packets */
/* Code to Dissect the extended header */
static void
-dissect_ehdr (tvbuff_t * tvb, proto_tree * tree)
+dissect_ehdr (tvbuff_t * tvb, proto_tree * tree, gboolean isfrag)
{
proto_tree *ehdr_tree;
proto_item *it;
- guint8 ehdrlen;
+ gint ehdrlen;
int pos;
guint8 type;
guint8 len;
+ guint8 val;
guint8 mini_slots;
guint16 sid;
it = proto_tree_add_text (tree, tvb, pos, ehdrlen, "Extended Header");
ehdr_tree = proto_item_add_subtree (it, ett_ehdr);
- while (pos < (int)(ehdrlen + 4))
+ while (pos < ehdrlen + 4)
{
- proto_tree_add_item (ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, FALSE);
- proto_tree_add_item (ehdr_tree, hf_docsis_eh_len, tvb, pos, 1, FALSE);
type = (tvb_get_guint8 (tvb, pos) & 0xF0);
len = (tvb_get_guint8 (tvb, pos) & 0x0F);
+ if ((((type >> 4) & 0x0F)== 6) && (len == 2))
+ {
+ proto_tree_add_item_hidden (ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, FALSE);
+ proto_tree_add_text(ehdr_tree, tvb, pos, 1, "0110 .... = Unsolicited Grant Sync EHDR Sub-Element" );
+ }
+ else
+ proto_tree_add_item (ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, FALSE);
+ proto_tree_add_item (ehdr_tree, hf_docsis_eh_len, tvb, pos, 1, FALSE);
switch ((type >> 4) & 0x0F)
{
case EH_REQUEST:
FALSE);
proto_tree_add_item (ehdr_tree, hf_docsis_mini_slots, tvb, pos + 4,
1, FALSE);
+ if (isfrag)
+ {
+ proto_tree_add_item (ehdr_tree, hf_docsis_frag_rsvd, tvb, pos+5,
+ 1, FALSE);
+ proto_tree_add_item (ehdr_tree, hf_docsis_frag_first, tvb, pos+5,
+ 1, FALSE);
+ proto_tree_add_item (ehdr_tree, hf_docsis_frag_last, tvb, pos+5,
+ 1, FALSE);
+ proto_tree_add_item (ehdr_tree, hf_docsis_frag_seq, tvb, pos+5,
+ 1, FALSE);
+ }
break;
case EH_BP_DOWN:
proto_tree_add_item (ehdr_tree, hf_docsis_key_seq, tvb, pos + 1, 1,
proto_tree_add_item (ehdr_tree, hf_docsis_reserved, tvb, pos + 4, 1,
FALSE);
break;
+ case EH_SFLOW_HDR_DOWN:
+ case EH_SFLOW_HDR_UP:
+ val = tvb_get_guint8 (tvb, pos+1);
+ if (val == 0)
+ {
+ proto_tree_add_item_hidden (ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, FALSE);
+ proto_tree_add_text (ehdr_tree, tvb, pos+1, 1, "0000 0000 = No PHS on current packet" );
+ }
+ else
+ proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, FALSE);
+
+ if (len == 2)
+ {
+ proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_qind, tvb, pos+2, 1, FALSE);
+ proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_grants, tvb, pos+2, 1, FALSE);
+ }
+ break;
default:
if (len > 0)
proto_tree_add_item (ehdr_tree, hf_docsis_eh_val, tvb, pos + 1,
guint8 fctype;
guint8 fcparm;
guint8 ehdron;
- guint8 mac_parm;
- guint8 hdrlen;
+ gint mac_parm;
+ gint hdrlen;
guint16 len_sid;
tvbuff_t *next_tvb, *mgt_tvb;
- guint16 pdulen, captured_length, framelen;
+ gint pdulen, captured_length;
+ gint framelen;
+ gboolean isfrag = FALSE;
+ gint oldconcatlen;
+
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *ti;
proto_tree *docsis_tree;
/* concatlen and concatpos are declared static to allow for recursive calls to
* the dissect_docsis routine when dissecting Concatenated frames
*/
- static guint16 concatlen;
- static guint16 concatpos;
+ static gint concatlen;
+ static gint concatpos;
/* Extract important fields */
fc = tvb_get_guint8 (tvb, 0); /* Frame Control Byte */
else
{
framelen = 6 + len_sid;
- pdulen = len_sid - ((guint16) (mac_parm & 0xFF));
+ pdulen = len_sid - (mac_parm + 2);
}
/* if this is a concatenated frame setup the length of the concatenated
"Request Frame SID = %u Mini Slots = %u", len_sid,
mac_parm);
else if (fcparm == 0x03)
- col_set_str (pinfo->cinfo, COL_INFO, "Mac Specific");
- else
col_set_str (pinfo->cinfo, COL_INFO, "Fragmented Frame");
+ else
+ col_set_str (pinfo->cinfo, COL_INFO, "Mac Specific");
break;
} /* switch */
} /* if */
FALSE);
proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
FALSE);
- dissect_ehdr (tvb, docsis_tree);
+ dissect_ehdr (tvb, docsis_tree, isfrag);
proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
4 + mac_parm, 2, FALSE);
}
FALSE);
break;
}
+ /* Check if this is a fragmentation header */
+ if (fcparm == 0x03)
+ {
+ isfrag = TRUE;
+ }
/* Decode for a Concatenated Header. No Extended Header */
if (fcparm == 0x1c)
{
FALSE);
proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
FALSE);
- dissect_ehdr (tvb, docsis_tree);
+ dissect_ehdr (tvb, docsis_tree, isfrag);
proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
4 + mac_parm, 2, FALSE);
break;
}
/* If this protocol has a sub-dissector call it here, see section 1.8 */
- if ((fctype == FCTYPE_PACKET) && (len_sid > mac_parm))
+ switch (fctype)
{
- next_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
- call_dissector (eth_handle, next_tvb, pinfo, tree);
- if (concatlen > 0)
+ case FCTYPE_PACKET:
+ if (pdulen >= 0)
{
- concatlen = concatlen - framelen;
- concatpos += framelen;
+ if (pdulen > 0)
+ {
+ next_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
+ call_dissector (eth_withoutfcs_handle, next_tvb, pinfo, tree);
+ }
+ if (concatlen > 0)
+ {
+ concatlen = concatlen - framelen;
+ concatpos += framelen;
+ }
}
- }
- if (fctype == FCTYPE_MACSPC)
- {
+ break;
+ case FCTYPE_MACSPC:
switch (fcparm)
{
case 0x00:
case 0x01:
- mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
- call_dissector (docsis_mgmt_handle, mgt_tvb, pinfo, tree);
+ if (pdulen > 0)
+ {
+ mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
+ call_dissector (docsis_mgmt_handle, mgt_tvb, pinfo, tree);
+ }
if (concatlen > 0)
{
concatlen = concatlen - framelen;
/* Don't do anything for a Request Frame */
break;
case 0x03:
- /* For Fragmentation Frames simply dissect using the data
+ /* For Fragmentation Frames simply dissect using the data
* dissector as we don't handle them yet
*/
- mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
- call_dissector (data_handle, mgt_tvb, pinfo, tree);
+ if (pdulen > 0)
+ {
+ mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
+ call_dissector (data_handle, mgt_tvb, pinfo, tree);
+ }
if (concatlen > 0)
{
concatlen = concatlen - framelen;
}
break;
case 0x1c:
- /* call the docsis dissector on the same frame
+ /* call the docsis dissector on the same frame
* to dissect DOCSIS frames within the concatenated
- * frame. concatpos and concatlen are declared
- * static and are decremented and incremented
+ * frame. concatpos and concatlen are declared
+ * static and are decremented and incremented
* respectively when the inner
* docsis frames are dissected. */
while (concatlen > 0)
{
+ oldconcatlen = concatlen;
next_tvb = tvb_new_subset (tvb, concatpos, -1, concatlen);
call_dissector (docsis_handle, next_tvb, pinfo, tree);
+ if (oldconcatlen <= concatlen)
+ THROW(ReportedBoundsError);
}
concatlen = 0;
concatpos = 0;
col_set_str (pinfo->cinfo, COL_INFO, "Concatenated Frame");
break;
}
+ break;
}
}
-/* Register the protocol with Ethereal */
+/* Register the protocol with Wireshark */
/* this format is require because a script is used to build the C function
that calls all the protocol registration.
static hf_register_info hf[] = {
{&hf_docsis_fctype,
{"FCType", "docsis.fctype",
- FT_UINT8, BASE_BIN, VALS (fctype_vals), 0xC0,
+ FT_UINT8, BASE_HEX, VALS (fctype_vals), 0xC0,
"Frame Control Type", HFILL}
},
{&hf_docsis_fcparm,
{"FCParm", "docsis.fcparm",
- FT_UINT8, BASE_BIN, NULL, 0x3E,
+ FT_UINT8, BASE_DEC, NULL, 0x3E,
"Parameter Field", HFILL}
},
{&hf_docsis_machdr_fcparm,
{"FCParm", "docsis.fcparm",
- FT_UINT8, BASE_BIN, VALS (fcparm_vals), 0x3E,
+ FT_UINT8, BASE_HEX, VALS (fcparm_vals), 0x3E,
"Parameter Field", HFILL}
},
{&hf_docsis_ehdron,
{"EHDRON", "docsis.ehdron",
- FT_UINT8, BASE_BIN, VALS (ehdron_vals), 0x01,
+ FT_BOOLEAN, 8, TFS (&ehdron_tfs), 0x01,
"Extended Header Presence", HFILL}
},
{&hf_docsis_macparm,
FT_BYTES, BASE_HEX, NULL, 0x0,
"TLV Value", HFILL}
},
+ {&hf_docsis_frag_rsvd,
+ {"Reserved", "docsis.frag_rsvd",
+ FT_UINT8, BASE_DEC, NULL, 0xC0,
+ "Reserved", HFILL}
+ },
+ {&hf_docsis_frag_first,
+ {"First Frame", "docsis.frag_first",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "First Frame", HFILL}
+ },
+ {&hf_docsis_frag_last,
+ {"Last Frame", "docsis.frag_last",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ "Last Frame", HFILL}
+ },
+ {&hf_docsis_frag_seq,
+ {"Fragmentation Sequence #", "docsis.frag_seq",
+ FT_UINT8, BASE_DEC, NULL, 0x0F,
+ "Fragmentation Sequence Number", HFILL}
+ },
{&hf_docsis_sid,
{"SID", "docsis.ehdr.sid",
FT_UINT16, BASE_DEC, NULL, 0x3FFF,
"Key Sequence", HFILL}
},
{&hf_docsis_ehdr_ver,
- {"Version", "docsis.ehdr.",
+ {"Version", "docsis.ehdr.ver",
FT_UINT8, BASE_DEC, NULL, 0x0F,
"Version", HFILL}
},
+ {&hf_docsis_ehdr_phsi,
+ {"Payload Header Suppression Index", "docsis.ehdr.phsi",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Payload Header Suppression Index", HFILL}
+ },
+ {&hf_docsis_ehdr_qind,
+ {"Queue Indicator", "docsis.ehdr.qind",
+ FT_BOOLEAN, 8, TFS(&qind_tfs), 0x80,
+ "Queue Indicator", HFILL}
+ },
+ {&hf_docsis_ehdr_grants,
+ {"Active Grants", "docsis.ehdr.act_grants",
+ FT_UINT8, BASE_DEC, NULL, 0x7F,
+ "Active Grants", HFILL}
+ },
{&hf_docsis_hcs,
{"Header check sequence", "docsis.hcs",
FT_UINT16, BASE_HEX, NULL, 0x0,
},
{&hf_docsis_bpi_en,
{"Encryption", "docsis.bpi_en",
- FT_UINT8, BASE_HEX, VALS (ena_dis_vals), 0x80,
+ FT_BOOLEAN, 8, TFS (&ena_dis_tfs), 0x80,
"BPI Enable", HFILL},
},
{&hf_docsis_toggle_bit,
{"Toggle", "docsis.toggle_bit",
- FT_UINT8, BASE_HEX, VALS (odd_even_vals), 0x40,
+ FT_BOOLEAN, 8, TFS (&odd_even_tfs), 0x40,
"Toggle", HFILL},
},
dissector_add ("wtap_encap", WTAP_ENCAP_DOCSIS, docsis_handle);
docsis_mgmt_handle = find_dissector ("docsis_mgmt");
- eth_handle = find_dissector ("eth");
-}
-
-/* Start the functions we need for the plugin stuff */
-
-#ifndef __ETHEREAL_STATIC__
-
-G_MODULE_EXPORT void
-plugin_reg_handoff (void)
-{
- proto_reg_handoff_docsis ();
- proto_reg_handoff_docsis_bpkmattr ();
- proto_reg_handoff_docsis_dsarsp ();
- proto_reg_handoff_docsis_mgmt ();
- proto_reg_handoff_docsis_rngreq ();
- proto_reg_handoff_docsis_rngrsp ();
- proto_reg_handoff_docsis_bpkmreq ();
- proto_reg_handoff_docsis_dscack ();
- proto_reg_handoff_docsis_map ();
- proto_reg_handoff_docsis_tlv ();
- proto_reg_handoff_docsis_bpkmrsp ();
- proto_reg_handoff_docsis_dscreq ();
- proto_reg_handoff_docsis_regack ();
- proto_reg_handoff_docsis_uccreq ();
- proto_reg_handoff_docsis_dscrsp ();
- proto_reg_handoff_docsis_regreq ();
- proto_reg_handoff_docsis_uccrsp ();
- proto_reg_handoff_docsis_dsaack ();
- proto_reg_handoff_docsis_dsdreq ();
- proto_reg_handoff_docsis_regrsp ();
- proto_reg_handoff_docsis_ucd ();
- proto_reg_handoff_docsis_dsareq ();
- proto_reg_handoff_docsis_dsdrsp ();
+ eth_withoutfcs_handle = find_dissector ("eth_withoutfcs");
}
-
-G_MODULE_EXPORT void
-plugin_init (plugin_address_table_t * pat
-#ifndef PLUGINS_NEED_ADDRESS_TABLE
- _U_
-#endif
- )
-{
- /* initialise the table of pointers needed in Win32 DLLs */
- plugin_address_table_init (pat);
- /* register the new protocol, protocol fields, and subtrees */
- if (proto_docsis == -1)
- { /* execute protocol initialization only once */
- proto_register_docsis ();
- proto_register_docsis_bpkmattr ();
- proto_register_docsis_dsarsp ();
- proto_register_docsis_mgmt ();
- proto_register_docsis_rngrsp ();
- proto_register_docsis_bpkmreq ();
- proto_register_docsis_dscack ();
- proto_register_docsis_map ();
- proto_register_docsis_tlv ();
- proto_register_docsis_bpkmrsp ();
- proto_register_docsis_dscreq ();
- proto_register_docsis_regack ();
- proto_register_docsis_uccreq ();
- proto_register_docsis_dscrsp ();
- proto_register_docsis_regreq ();
- proto_register_docsis_uccrsp ();
- proto_register_docsis_dsaack ();
- proto_register_docsis_dsdreq ();
- proto_register_docsis_regrsp ();
- proto_register_docsis_ucd ();
- proto_register_docsis_dsareq ();
- proto_register_docsis_dsdrsp ();
- proto_register_docsis_rngreq ();
-
- }
-}
-
-#endif