#include "packet-ipx.h"
#include "packet-vines.h"
#include "nlpid.h"
-#include "crc16.h"
-#include "crc32.h"
+#include <epan/crc16.h>
+#include <epan/crc32.h>
#define ppp_min(a, b) ((a<b) ? a : b)
static gint ett_ppp = -1;
+static int proto_ppp_hdlc = -1;
+
+static gint ett_ppp_hdlc_data = -1;
+
static int proto_lcp = -1;
static gint ett_lcp = -1;
static gint ett_ipcp = -1;
static gint ett_ipcp_options = -1;
static gint ett_ipcp_ipaddrs_opt = -1;
-static gint ett_ipcp_compressprot_opt = -1;
+static gint ett_ipcp_compress_opt = -1;
+static gint ett_ipcp_iphc_disableprot_opt = -1;
static int proto_osicp = -1;
static gint ett_ipv6cp = -1;
static gint ett_ipv6cp_options = -1;
static gint ett_ipv6cp_if_id_opt = -1;
-static gint ett_ipv6cp_compressprot_opt = -1;
+static gint ett_ipv6cp_compress_opt = -1;
static dissector_table_t ppp_subdissector_table;
static dissector_handle_t chdlc_handle;
{PPP_NTCITS_IPI,"NTCITS IPI" },
{PPP_ML_SLCOMP, "single link compression in multilink" },
{PPP_COMP, "compressed packet" },
- {PPP_STP_HELLO, "802.1d Hello Packet" },
+ {PPP_STP_HELLO, "802.1D Hello Packet" },
{PPP_IBM_SR, "IBM Source Routing BPDU" },
{PPP_DEC_LB, "DEC LANBridge100 Spanning Tree"},
{PPP_CDP, "Cisco Discovery Protocol" },
static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint length, packet_info *pinfo,
proto_tree *tree);
+static void dissect_ipcp_compress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_ipcp_iphc_disableprot_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
static const ip_tcp_opt ipcp_opts[] = {
{
},
{
CI_COMPRESSTYPE,
- "IP compression protocol",
- &ett_ipcp_compressprot_opt,
+ "IP compression",
+ &ett_ipcp_compress_opt,
VARIABLE_LENGTH,
4,
- dissect_lcp_protocol_opt
+ dissect_ipcp_compress_opt
},
{
CI_ADDR,
#define N_IPCP_OPTS (sizeof ipcp_opts / sizeof ipcp_opts[0])
+
+/*
+ * IP Compression options
+ */
+#define IPCP_COMPRESS_VJ_1172 0x37 /* value defined in RFC1172 (typo) */
+#define IPCP_COMPRESS_VJ 0x2d /* value defined in RFC1332 (correct) */
+#define IPCP_COMPRESS_IPHC 0x61
+
+const value_string ipcp_compress_proto_vals[] = {
+ { IPCP_COMPRESS_VJ_1172, "VJ compression (RFC1172-typo)" },
+ { IPCP_COMPRESS_VJ, "VJ compression" },
+ { IPCP_COMPRESS_IPHC, "IPHC compression" },
+ { 0, NULL }
+};
+
+/* IPHC suboptions (RFC2508, 3544) */
+#define IPCP_IPHC_CRTP 1
+#define IPCP_IPHC_ECRTP 2
+#define IPCP_IPHC_DISABLE_PROTO 3 /* Disable compression for protocol */
+
+const value_string ipcp_iphc_disable_proto_vals[] = {
+ { 1, "TCP" },
+ { 2, "Non-TCP" },
+ { 0, NULL }
+};
+
+static const ip_tcp_opt ipcp_iphc_subopts[] = {
+ {
+ IPCP_IPHC_CRTP,
+ "RTP compression (RFC2508)",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ IPCP_IPHC_CRTP,
+ "Enhanced RTP compression (RFC3545)",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ IPCP_IPHC_DISABLE_PROTO,
+ "Enhanced RTP compression (RFC3545)",
+ &ett_ipcp_iphc_disableprot_opt,
+ FIXED_LENGTH,
+ 3,
+ dissect_ipcp_iphc_disableprot_opt
+ },
+};
+
+#define N_IPCP_IPHC_SUBOPTS (sizeof ipcp_iphc_subopts / sizeof ipcp_iphc_subopts[0])
+
+
/*
* Options. (OSICP)
*/
},
{
CI_COMPRESSTYPE,
- "IPv6 compression protocol",
- &ett_ipcp_compressprot_opt,
+ "IPv6 compression",
+ &ett_ipcp_compress_opt,
VARIABLE_LENGTH,
4,
- dissect_lcp_protocol_opt
+ dissect_ipcp_compress_opt
},
};
rx_fcs_got = tvb_get_letohs(tvb, rx_fcs_offset);
if (rx_fcs_got != rx_fcs_exp) {
proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2,
- "FCS 16: 0x%04x (incorrect, should be 0x%04x)",
+ "FCS 16: 0x%04x [incorrect, should be 0x%04x]",
rx_fcs_got, rx_fcs_exp);
} else {
proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2,
- "FCS 16: 0x%04x (correct)",
+ "FCS 16: 0x%04x [correct]",
rx_fcs_got);
}
}
rx_fcs_got = tvb_get_letohl(tvb, rx_fcs_offset);
if (rx_fcs_got != rx_fcs_exp) {
proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4,
- "FCS 32: 0x%08x (incorrect, should be 0x%08x)",
+ "FCS 32: 0x%08x [incorrect, should be 0x%08x]",
rx_fcs_got, rx_fcs_exp);
} else {
proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4,
- "FCS 32: 0x%08x (correct)",
+ "FCS 32: 0x%08x [correct]",
rx_fcs_got);
}
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
next_tvb = NULL;
}
ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)));
}
+static void dissect_ipcp_compress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 ub;
+ guint16 us;
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2; /* Skip option type + length */
+ length -= 2;
+
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2, "IP compression protocol: %s (0x%04x)",
+ val_to_str( us, ipcp_compress_proto_vals, "Unknown protocol" ),
+ us );
+ offset += 2; /* skip protocol */
+ length -= 2;
+
+ if (length > 0) {
+ switch ( us ) {
+ case IPCP_COMPRESS_VJ_1172:
+ case IPCP_COMPRESS_VJ:
+ /* First byte is max slot id */
+ ub = tvb_get_guint8( tvb, offset );
+ proto_tree_add_text( field_tree, tvb, offset, 1,
+ "Max slot id: %u (0x%02x)",
+ ub, ub );
+ offset++;
+ length--;
+
+ if ( length > 0 ) {
+ /* second byte is "compress slot id" */
+ ub = tvb_get_guint8( tvb, offset );
+ proto_tree_add_text( field_tree, tvb, offset, 1,
+ "Compress slot id: %s (0x%02x)",
+ ub ? "yes" : "no", ub );
+ offset++;
+ length--;
+ }
+ break;
+
+
+ case IPCP_COMPRESS_IPHC:
+ if ( length < 2 ) {
+ break;
+ }
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2,
+ "TCP space: %u (0x%04x)",
+ us, us );
+ offset += 2;
+ length -= 2;
+
+
+ if ( length < 2 ) {
+ break;
+ }
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2,
+ "Non-TCP space: %u (0x%04x)",
+ us, us );
+ offset += 2;
+ length -= 2;
+
+
+ if ( length < 2 ) {
+ break;
+ }
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2,
+ "Max period: %u (0x%04x) compressed packets",
+ us, us );
+ offset += 2;
+ length -= 2;
+
+
+ if ( length < 2 ) {
+ break;
+ }
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2,
+ "Max time: %u (0x%04x) seconds",
+ us, us );
+ offset += 2;
+ length -= 2;
+
+
+ if ( length < 2 ) {
+ break;
+ }
+ us = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text( field_tree, tvb, offset, 2,
+ "Max header: %u (0x%04x) bytes",
+ us, us );
+ offset += 2;
+ length -= 2;
+
+ if ( length > 0 ) {
+ /* suboptions */
+ tf = proto_tree_add_text(field_tree, tvb, offset, length,
+ "Suboptions: (%u byte%s)",
+ length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ dissect_ip_tcp_options(tvb, offset, length,
+ ipcp_iphc_subopts, N_IPCP_IPHC_SUBOPTS, -1,
+ pinfo, field_tree);
+ }
+ return;
+ }
+
+ if (length > 0) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ }
+ }
+}
+
+static void dissect_ipcp_iphc_disableprot_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb,
+ int offset, guint length,
+ packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 param;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ param = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Protocol: %s (0x%02x)",
+ val_to_str( param, ipcp_iphc_disable_proto_vals, "Unknown" ),
+ param );
+}
+
+
static void dissect_osicp_align_npdu_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint length, packet_info *pinfo _U_,
proto_tree *tree)
offset++;
length--;
addr_len = tvb_strsize(tvb, offset);
+ if (addr_len > length) {
+ proto_tree_add_text(addr_tree, tvb, offset, length,
+ "Address: (runs past end of option)");
+ break;
+ }
proto_tree_add_text(addr_tree, tvb, offset, addr_len,
"Address: %s",
tvb_format_text(tvb, offset, addr_len - 1));
- offset += (addr_len + 1);
- length -= (addr_len + 1);
+ offset += addr_len;
+ length -= addr_len;
}
}
subopt_type = tvb_get_guint8(tvb, offset);
subopt_len = tvb_get_guint8(tvb, offset + 1);
ti = proto_tree_add_text(field_tree, tvb, offset, subopt_len,
- "Sub-Option (%d byte%s)",
+ "Sub-Option (%u byte%s)",
subopt_len, plurality(subopt_len, "", "s"));
suboption_tree = proto_item_add_subtree(ti, ett_bap_phone_delta_subopt);
val_to_str(subopt_type, bap_phone_delta_subopt_vals, "Unknown"),
subopt_type);
+ if (subopt_len < 2) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Sub-Option Length: %u (invalid, must be >= 2)", subopt_len);
+ return;
+ }
+ if (subopt_len > length) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Sub-Option Length: %u (invalid, must be <= length remaining in option %u)", subopt_len, length);
+ return;
+ }
+
proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
"Sub-Option Length: %u", subopt_len);
switch (subopt_type) {
case BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT:
- proto_tree_add_text(suboption_tree, tvb, offset + 2, 1, "Uniq Digit: %u",
- tvb_get_guint8(tvb, offset + 2));
+ if (subopt_len == 3) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, 1, "Unique Digit: %u",
+ tvb_get_guint8(tvb, offset + 2));
+ } else {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Invalid suboption length: %u (must be == 3)",
+ subopt_len);
+ }
break;
case BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM:
if (subopt_len > 2) {
tvb_format_text(tvb, offset + 2, subopt_len - 2));
} else {
proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
- "Invalid suboption length: %u", subopt_len);
+ "Invalid suboption length: %u (must be > 2)",
+ subopt_len);
}
break;
case BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR:
proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
"Phone Number Sub Address: %s",
tvb_format_text(tvb, offset + 2, subopt_len - 2));
+ } else {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Invalid suboption length: %u (must be > 2)",
+ subopt_len);
}
break;
default:
- proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
+ if (subopt_len > 2) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
"Unknown");
+ } else {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Invalid suboption length: %u (must be > 2)",
+ subopt_len);
+ }
break;
}
offset += subopt_len;
case ECHOREQ:
case ECHOREP:
case DISCREQ:
- case IDENT:
if(tree) {
proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
tvb_get_ntohl(tvb, offset));
}
break;
+ case IDENT:
+ if(tree) {
+ proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ length -= 4;
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Message: %s",
+ tvb_format_text(tvb, offset, length));
+ }
+ break;
+
case TIMEREMAIN:
if(tree) {
proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
static void
dissect_ppp_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- proto_tree *fh_tree, proto_item *ti )
+ proto_tree *fh_tree, proto_item *ti, int proto_offset )
{
guint16 ppp_prot;
int proto_len;
}
/* If "ti" is not null, it refers to the top-level "proto_ppp" item
- for PPP, and was given a length equal to the length of any
- stuff in the header preceding the protocol type, e.g. an HDLC
- header; add the length of the protocol type field to it. */
+ for PPP, and proto_offset is the length of any stuff in the header
+ preceding the protocol type, e.g. an HDLC header; add the length
+ of the protocol type field to it, and set the length of that item
+ to the result. */
if (ti != NULL)
- proto_item_set_len(ti, proto_item_get_len(ti) + proto_len);
+ proto_item_set_len(ti, proto_offset + proto_len);
if (tree)
proto_tree_add_uint(fh_tree, hf_ppp_protocol, tvb, 0, proto_len, ppp_prot);
length_remaining -= hdr_length;
length -= pid_field;
+ tvb_ensure_bytes_exist (tvb,offset,length);
sub_ti = proto_tree_add_text(sub_tree,tvb,offset,length,"Information Field");
info_tree = proto_item_add_subtree(sub_ti,ett_pppmux_subframe_info);
fh_tree = proto_item_add_subtree(ti, ett_ppp);
}
- dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti);
+ dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti, 0);
}
-/*
- * Handles link-layer encapsulations where the frame might be
- * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
- */
static void
-dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+dissect_ppp_hdlc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *ti = NULL;
proto_tree *fh_tree = NULL;
tvbuff_t *next_tvb;
byte0 = tvb_get_guint8(tvb, 0);
- if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
- /* Cisco HDLC encapsulation */
- call_dissector(chdlc_handle, tvb, pinfo, tree);
- return;
- }
-
- /*
- * XXX - should we have a routine that always dissects PPP, for use
- * when we know the packets are PPP, not CHDLC?
- */
/* PPP HDLC encapsulation */
if (byte0 == 0xff)
/* load the top pane info. This should be overwritten by
the next protocol in the stack */
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_ppp);
+ if (byte0 == 0xff) {
+ proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1, FALSE);
+ proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1, FALSE);
+ }
+ }
- if(check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" );
+ next_tvb = decode_fcs(tvb, fh_tree, ppp_fcs_decode, proto_offset);
+
+ dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset);
+}
+
+/*
+ * Handles link-layer encapsulations where the frame might be
+ * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
+ */
+static void
+dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ guint8 byte0;
+ byte0 = tvb_get_guint8(tvb, 0);
+ if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
+ /* Cisco HDLC encapsulation */
+ call_dissector(chdlc_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ /*
+ * XXX - should we have an exported dissector that always dissects PPP,
+ * for use when we know the packets are PPP, not CHDLC?
+ */
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
switch (pinfo->p2p_dir) {
case P2P_DIR_SENT:
break;
}
- if(tree) {
- ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, proto_offset, FALSE);
- fh_tree = proto_item_add_subtree(ti, ett_ppp);
- if (byte0 == 0xff) {
- proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1, FALSE);
- proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1, FALSE);
- }
+ dissect_ppp_hdlc_common(tvb, pinfo, tree);
+}
+
+static tvbuff_t*
+remove_escape_chars(tvbuff_t *tvb, int offset, int length)
+{
+ guint8 *buff;
+ int i;
+ int scanned_len = 0;
+ guint8 octet;
+ tvbuff_t *next_tvb;
+
+ buff = g_malloc(length);
+ i = 0;
+ while ( scanned_len < length ){
+ octet = tvb_get_guint8(tvb,offset);
+ if (octet == 0x7d){
+ offset++;
+ scanned_len++;
+ if (scanned_len >= length)
+ break;
+ octet = tvb_get_guint8(tvb,offset);
+ buff[i] = octet ^ 0x20;
+ }else{
+ buff[i]= octet;
+ }
+ offset++;
+ scanned_len++;
+ i++;
}
+ if (i == 0)
+ return NULL;
+ next_tvb = tvb_new_real_data(buff,i,i);
- next_tvb = decode_fcs(tvb, fh_tree, ppp_fcs_decode, proto_offset);
+ /* Arrange that the allocated packet data copy be freed when the
+ * tvbuff is freed.
+ */
+ tvb_set_free_cb( next_tvb, g_free );
+
+ tvb_set_child_real_data_tvbuff(tvb,next_tvb);
+ return next_tvb;
- dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti);
+}
+
+/*
+ * Handles link-layer encapsulations where we have a raw RFC 1662
+ * HDLC-like asynchronous framing byte stream, and have to
+ * break the byte stream into frames and remove escapes.
+ */
+static void
+dissect_ppp_raw_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti;
+ proto_tree *bs_tree = NULL;
+ gint offset, end_offset, data_offset;
+ int length, data_length;
+ tvbuff_t *ppp_tvb;
+ gboolean first = TRUE;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" );
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ppp_hdlc, tvb, 0, -1, FALSE);
+ bs_tree = proto_item_add_subtree(ti, ett_ppp_hdlc_data);
+ }
+
+ /*
+ * XXX - this needs to handle a PPP frame split over multiple higher-level
+ * packets.
+ */
+
+ /*
+ * Look for a frame delimiter.
+ */
+ offset = tvb_find_guint8(tvb, 0, -1, 0x7e);
+ if (offset == -1) {
+ /*
+ * None found - this is presumably continued from an earlier
+ * packet and continued in a later packet.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_add_str(pinfo->cinfo, COL_INFO,"PPP Fragment");
+ }
+ if (tree)
+ proto_tree_add_text(bs_tree, tvb, offset, -1, "PPP Fragment");
+ offset++;
+ length = tvb_length_remaining(tvb,offset);
+ ppp_tvb = remove_escape_chars(tvb, offset,length);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_dissector(data_handle, ppp_tvb, pinfo, tree);
+ }
+ return;
+ }
+ if (offset != 0) {
+ /*
+ * We have some data preceding the first PPP packet;
+ * mark it as a PPP fragment.
+ */
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_add_str(pinfo->cinfo, COL_INFO,"PPP Fragment");
+ }
+ length = offset;
+ if (tree)
+ proto_tree_add_text(bs_tree, tvb, 0, length, "PPP Fragment");
+ if (length != 0) {
+ ppp_tvb = remove_escape_chars(tvb, 0, length - 1);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_dissector(data_handle, ppp_tvb, pinfo, tree);
+ }
+ }
+ }
+ while ( tvb_reported_length_remaining(tvb, offset) > 0 ){
+ /*
+ * Look for the next frame delimiter.
+ */
+ end_offset = tvb_find_guint8(tvb, offset+1, -1, 0x7e);
+ if ( end_offset == -1 ){
+ /*
+ * We didn't find one. This is probably continued in
+ * a later packet.
+ */
+ if (first) {
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_add_str(pinfo->cinfo, COL_INFO,"PPP Fragment");
+ }
+ }
+ if (tree)
+ proto_tree_add_text(bs_tree, tvb, offset, -1, "PPP Fragment");
+ offset++;
+ length = tvb_length_remaining(tvb, offset);
+ ppp_tvb = remove_escape_chars(tvb, offset,length);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_dissector(data_handle, ppp_tvb, pinfo, tree);
+ }
+ return;
+ }
+
+ data_offset = offset+1; /* skip starting frame delimiter */
+ data_length = end_offset - data_offset;
+
+ /*
+ * Is that frame delimiter immediately followed by another one?
+ * Some PPP implementations put a frame delimiter at the
+ * beginning and the end of each frame, although RFC 1662
+ * appears only to require that there be one frame delimiter
+ * between adjacent frames:
+ *
+ * Each frame begins and ends with a Flag Sequence, which is the
+ * binary sequence 01111110 (hexadecimal 0x7e). All implementations
+ * continuously check for this flag, which is used for frame
+ * synchronization.
+ *
+ * Only one Flag Sequence is required between two frames. Two
+ * consecutive Flag Sequences constitute an empty frame, which is
+ * silently discarded, and not counted as a FCS error.
+ *
+ * If the delimiter at the end of this frame is followed by
+ * another delimiter, we consider the first delimiter part
+ * of this frame.
+ */
+ if (tvb_offset_exists(tvb, end_offset+1) &&
+ tvb_get_guint8(tvb, end_offset+1) == 0x7e)
+ end_offset++;
+ length = end_offset - offset;
+ if (tree)
+ proto_tree_add_text(bs_tree, tvb, offset, length, "PPP Data");
+ if (length > 1) {
+ ppp_tvb = remove_escape_chars(tvb, data_offset, data_length);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Message");
+ dissect_ppp_hdlc_common(ppp_tvb, pinfo, tree);
+ first = FALSE;
+ }
+ }
+ offset = end_offset;
+ } /* end while */
+}
+
+void
+proto_register_ppp_raw_hdlc(void)
+{
+ static gint *ett[] = {
+ &ett_ppp_hdlc_data
+ };
+
+ proto_ppp_hdlc = proto_register_protocol("PPP In HDLC-Like Framing", "PPP-HDLC", "ppp_hdlc");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ppp_raw_hdlc(void)
+{
+ dissector_handle_t ppp_raw_hdlc_handle;
+
+ ppp_raw_hdlc_handle = create_dissector_handle(dissect_ppp_raw_hdlc, proto_ppp);
+ dissector_add("gre.proto", ETHERTYPE_CDMA2000_A10_UBS, ppp_raw_hdlc_handle);
}
/*
proto_tree *value_tree;
guint8 code, id, value_size;
- guint16 length;
+ gint32 length;
int offset;
- int name_length;
code = tvb_get_guint8(tvb, 0);
id = tvb_get_guint8(tvb, 1);
val_to_str(code, chap_vals, "Unknown"), code);
proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
id);
+ }
+ if(length < 4) {
+ if(tree) {
+ proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u (invalid, must be >= 4)",
+ length);
+ return;
+ }
+ }
+ if(tree) {
proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
length);
}
plurality(length, "", "s"));
field_tree = proto_item_add_subtree(tf, ett_chap_data);
value_size = tvb_get_guint8(tvb, offset);
- name_length = length - value_size - 1;
+ length--;
+ if (value_size > length) {
+ proto_tree_add_text(field_tree, tvb, offset, 1,
+ "Value Size: %d byte%s (invalid, must be <= %u)",
+ value_size, plurality(value_size, "", "s"),
+ length);
+ return;
+ }
tv = proto_tree_add_text(field_tree, tvb, offset, 1,
- "Value Size: %d byte%s",
- value_size, plurality(value_size, "", "s"));
- if (--length > 0) {
+ "Value Size: %u byte%s",
+ value_size, plurality(value_size, "", "s"));
+ offset++;
+ if (length > 0) {
value_tree = proto_item_add_subtree(tv, ett_chap_value);
- proto_tree_add_text(value_tree, tvb, ++offset,
- ppp_min(value_size, length),
- "Value (%d byte%s)",
+ proto_tree_add_text(value_tree, tvb, offset, value_size,
+ "Value (%u byte%s)",
value_size, plurality(value_size, "", "s"));
offset+=value_size;
length-=value_size;
if (length > 0) {
- proto_tree_add_text(field_tree, tvb, offset,
- ppp_min(name_length, length),
- "Name (%d byte%s)", name_length,
- plurality(name_length, "", "s"));
+ tvb_ensure_bytes_exist(tvb, offset, length);
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Name (%u byte%s)", length,
+ plurality(length, "", "s"));
}
}
}
if(tree) {
if (length > 0) {
tf = proto_tree_add_text(fh_tree, tvb, offset, length,
- "Data (%d byte%s)", length,
+ "Data (%u byte%s)", length,
plurality(length, "", "s"));
field_tree = proto_item_add_subtree(tf, ett_chap_data);
tv = proto_tree_add_text(field_tree, tvb, offset, length,
- "Message: %d byte%s",
+ "Message: %u byte%s",
length, plurality(length, "", "s"));
}
}
break;
default:
if (length > 0)
- proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%u byte%s)",
length, plurality(length, "", "s"));
break;
}
VALS(ppp_vals), 0x0, "", HFILL }},
};
static gint *ett[] = {
- &ett_ppp,
+ &ett_ppp
};
module_t *ppp_module;
chdlc_handle = find_dissector("chdlc");
data_handle = find_dissector("data");
- ppp_hdlc_handle = find_dissector("ppp_hdlc");
ppp_handle = find_dissector("ppp");
+ dissector_add("fr.ietf", NLPID_PPP, ppp_handle);
+
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
dissector_add("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_handle);
dissector_add("wtap_encap", WTAP_ENCAP_PPP_WITH_PHDR, ppp_hdlc_handle);
- dissector_add("fr.ietf", NLPID_PPP, ppp_handle);
+ dissector_add("osinl.excl", NLPID_PPP, ppp_handle);
dissector_add("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle);
}
* table.
*/
dissector_add("ethertype", PPP_LCP, lcp_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add("sm_pco.protocol", PPP_LCP, lcp_handle);
+
}
void
&ett_ipcp,
&ett_ipcp_options,
&ett_ipcp_ipaddrs_opt,
- &ett_ipcp_compressprot_opt,
+ &ett_ipcp_compress_opt,
};
proto_ipcp = proto_register_protocol("PPP IP Control Protocol", "PPP IPCP",
* registering with the "ethertype" dissector table.
*/
dissector_add("ethertype", PPP_IPCP, ipcp_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add("sm_pco.protocol", PPP_IPCP, ipcp_handle);
+
}
void
* registering with the "ethertype" dissector table.
*/
dissector_add("ethertype", PPP_PAP, pap_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add("sm_pco.protocol", PPP_PAP, pap_handle);
}
void
* registering with the "ethertype" dissector table.
*/
dissector_add("ethertype", PPP_CHAP, chap_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add("sm_pco.protocol", PPP_CHAP, chap_handle);
}
void
&ett_ipv6cp,
&ett_ipv6cp_options,
&ett_ipv6cp_if_id_opt,
- &ett_ipv6cp_compressprot_opt,
+ &ett_ipv6cp_compress_opt,
};
proto_ipv6cp = proto_register_protocol("PPP IPv6 Control Protocol",