diff options
-rw-r--r-- | epan/dissectors/packet-ppp.c | 341 |
1 files changed, 202 insertions, 139 deletions
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c index 0e654ffbed..e2a87cf461 100644 --- a/epan/dissectors/packet-ppp.c +++ b/epan/dissectors/packet-ppp.c @@ -55,6 +55,10 @@ static int hf_ppp_protocol = -1; 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; @@ -3107,6 +3111,90 @@ dissect_ppp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti, 0); } +static void +dissect_ppp_hdlc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti = NULL; + proto_tree *fh_tree = NULL; + guint8 byte0; + int proto_offset; + tvbuff_t *next_tvb; + + byte0 = tvb_get_guint8(tvb, 0); + + /* PPP HDLC encapsulation */ + if (byte0 == 0xff) + proto_offset = 2; + else { + /* address and control are compressed (NULL) */ + proto_offset = 0; + } + + /* 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); + } + } + + 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: + if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE"); + if(check_col(pinfo->cinfo, COL_RES_DL_DST)) + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE"); + break; + + case P2P_DIR_RECV: + if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE"); + if(check_col(pinfo->cinfo, COL_RES_DL_DST)) + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE"); + break; + + default: + if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A"); + if(check_col(pinfo->cinfo, COL_RES_DL_DST)) + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A"); + break; + } + + dissect_ppp_hdlc_common(tvb, pinfo, tree); +} + static tvbuff_t* remove_escape_chars(tvbuff_t *tvb, int offset, int length) { @@ -3123,6 +3211,8 @@ remove_escape_chars(tvbuff_t *tvb, int offset, int length) if (octet == 0x7d){ offset++; scanned_len++; + if (scanned_len >= length) + break; octet = tvb_get_guint8(tvb,offset); buff[i] = octet ^ 0x20; }else{ @@ -3132,6 +3222,8 @@ remove_escape_chars(tvbuff_t *tvb, int offset, int length) scanned_len++; i++; } + if (i == 0) + return NULL; next_tvb = tvb_new_real_data(buff,i,i); /* Arrange that the allocated packet data copy be freed when the @@ -3143,163 +3235,136 @@ remove_escape_chars(tvbuff_t *tvb, int offset, int length) return next_tvb; } + /* - * Handles link-layer encapsulations 0x8881 where the frame might be - * a PPP in HDLC-like Framing frame . + * 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_8881( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) +dissect_ppp_raw_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { - proto_item *ti = NULL; - proto_tree *fh_tree = NULL; - guint8 byte0; - int proto_offset; - tvbuff_t *next_tvb,*ppp_tvb; - gint end_offset; - int offset = 0; - int length; - int tvb_length = tvb_length_remaining(tvb,offset); + proto_item *ti; + proto_tree *bs_tree = NULL; + gint offset, end_offset; + int length; + tvbuff_t *ppp_tvb; + gboolean first = TRUE; if(check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" ); - while ( offset < tvb_length ){ + 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); + } - - byte0 = tvb_get_guint8(tvb, 0); + /* + * 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++; - if (byte0 != 0x7e ){ - /* PPP Fragment */ - if(check_col(pinfo->cinfo, COL_INFO)){ - col_add_str(pinfo->cinfo, COL_INFO,"PPP Fragment"); - } - proto_tree_add_text(tree, tvb, 0, -1, "PPP Fragment"); - length = tvb_length_remaining(tvb,offset); - ppp_tvb = remove_escape_chars(tvb, offset,length); + 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; } - - end_offset = tvb_find_guint8(tvb, offset,-1, 0x7e); - if ( end_offset == -1){ - if(check_col(pinfo->cinfo, COL_INFO)){ - col_add_str(pinfo->cinfo, COL_INFO,"PPP Fragment"); + 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); } - - proto_tree_add_text(tree, tvb, 0, -1, "PPP Fragment"); - length = tvb_length_remaining(tvb,offset); + } + } + 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); - add_new_data_source(pinfo, ppp_tvb, "PPP Fragment"); - call_dissector(data_handle, ppp_tvb, pinfo, tree); + if (ppp_tvb != NULL) { + add_new_data_source(pinfo, ppp_tvb, "PPP Fragment"); + call_dissector(data_handle, ppp_tvb, pinfo, tree); + } return; } - length = end_offset - offset+1; - g_warning("length(%u) = end_offset(%u) - offset(%u)+1",length,end_offset,offset); - ppp_tvb = remove_escape_chars(tvb, offset,length); - add_new_data_source(pinfo, ppp_tvb, "PPP Message"); - - byte0 = tvb_get_guint8(ppp_tvb, 0); - - /* PPP HDLC encapsulation */ - if (byte0 == 0xff){ - proto_offset = 2; - }else { - /* address and control are compressed (NULL) */ - proto_offset = 0; - } - - if(tree) { - ti = proto_tree_add_item(tree, proto_ppp, 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, ppp_tvb, 0, 1, FALSE); - proto_tree_add_item(fh_tree, hf_ppp_control, ppp_tvb, 1, 1, FALSE); - } + 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, offset + 1, length - 1); + if (ppp_tvb != NULL) { + add_new_data_source(pinfo, ppp_tvb, "PPP Message"); + dissect_ppp_hdlc_common(ppp_tvb, pinfo, tree); + first = FALSE; + } } - next_tvb = decode_fcs(ppp_tvb, fh_tree, ppp_fcs_decode, proto_offset); - - dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset); - offset = end_offset + 1; - + offset = end_offset; } /* end while */ } -/* - * 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 ) +void +proto_register_ppp_raw_hdlc(void) { - proto_item *ti = NULL; - proto_tree *fh_tree = NULL; - guint8 byte0; - int proto_offset; - 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) - proto_offset = 2; - else { - /* address and control are compressed (NULL) */ - proto_offset = 0; - } - - /* load the top pane info. This should be overwritten by - the next protocol in the stack */ - - if(check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" ); - - switch (pinfo->p2p_dir) { - - case P2P_DIR_SENT: - if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE"); - if(check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE"); - break; - - case P2P_DIR_RECV: - if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE"); - if(check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE"); - break; - - default: - if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A"); - if(check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A"); - break; - } + static gint *ett[] = { + &ett_ppp_hdlc_data + }; - 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); - } - } + proto_ppp_hdlc = proto_register_protocol("PPP In HDLC-Like Framing", "PPP-HDLC", "ppp_hdlc"); + proto_register_subtree_array(ett, array_length(ett)); +} - next_tvb = decode_fcs(tvb, fh_tree, ppp_fcs_decode, proto_offset); +void +proto_reg_handoff_ppp_raw_hdlc(void) +{ + dissector_handle_t ppp_raw_hdlc_handle; - dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset); + 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); } /* @@ -3543,7 +3608,7 @@ proto_register_ppp(void) VALS(ppp_vals), 0x0, "", HFILL }}, }; static gint *ett[] = { - &ett_ppp, + &ett_ppp }; module_t *ppp_module; @@ -3556,7 +3621,6 @@ proto_register_ppp(void) ppp_subdissector_table = register_dissector_table("ppp.protocol", "PPP protocol", FT_UINT16, BASE_HEX); - register_dissector("ppp_8881", dissect_ppp_8881, proto_ppp); register_dissector("ppp_hdlc", dissect_ppp_hdlc, proto_ppp); register_dissector("ppp_lcp_options", dissect_lcp_options, proto_ppp); register_dissector("ppp", dissect_ppp, proto_ppp); @@ -3585,7 +3649,7 @@ proto_register_ppp(void) void proto_reg_handoff_ppp(void) { - dissector_handle_t ppp_8881_handle, ppp_hdlc_handle, ppp_handle; + dissector_handle_t ppp_hdlc_handle, ppp_handle; /* * Get a handle for the CHDLC dissector. @@ -3593,14 +3657,13 @@ proto_reg_handoff_ppp(void) chdlc_handle = find_dissector("chdlc"); data_handle = find_dissector("data"); - ppp_8881_handle = find_dissector("ppp_8881"); - 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("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle); - dissector_add("gre.proto", ETHERTYPE_CDMA2000_A10_UBS, ppp_8881_handle); } void |