Add a protocol layer for the raw byte stream for PPP in HDLC-like
framing, and put the raw packet and fragment data at that layer. Add a common routine to dissect un-escaped PPP data that might have 0xff 0x03, and use it both for the raw PPP in HDLC-like framing and for processing un-escaped data. Check for an escape byte not followed by another byte (e.g., because the packet is too short). Handle the case where a chunk of that raw byte data doesn't begin with 0x7e, but starts with cruft from a previous PPP packet split across lower-level packets. svn path=/trunk/; revision=12741
This commit is contained in:
parent
8afae320de
commit
3f0412a729
1 changed files with 214 additions and 151 deletions
|
@ -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,130 +3111,8 @@ dissect_ppp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
|
|||
dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti, 0);
|
||||
}
|
||||
|
||||
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++;
|
||||
octet = tvb_get_guint8(tvb,offset);
|
||||
buff[i] = octet ^ 0x20;
|
||||
}else{
|
||||
buff[i]= octet;
|
||||
}
|
||||
offset++;
|
||||
scanned_len++;
|
||||
i++;
|
||||
}
|
||||
next_tvb = tvb_new_real_data(buff,i,i);
|
||||
|
||||
/* 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;
|
||||
|
||||
}
|
||||
/*
|
||||
* Handles link-layer encapsulations 0x8881 where the frame might be
|
||||
* a PPP in HDLC-like Framing frame .
|
||||
*/
|
||||
static void
|
||||
dissect_ppp_8881( 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);
|
||||
|
||||
if(check_col(pinfo->cinfo, COL_PROTOCOL))
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" );
|
||||
|
||||
while ( offset < tvb_length ){
|
||||
|
||||
|
||||
byte0 = tvb_get_guint8(tvb, 0);
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
proto_tree_add_text(tree, tvb, 0, -1, "PPP Fragment");
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
} /* 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 )
|
||||
dissect_ppp_hdlc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
proto_item *ti = NULL;
|
||||
proto_tree *fh_tree = NULL;
|
||||
|
@ -3239,16 +3121,6 @@ dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
|
|||
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)
|
||||
|
@ -3260,10 +3132,42 @@ dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
|
|||
|
||||
/* 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" );
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
|
||||
switch (pinfo->p2p_dir) {
|
||||
|
||||
case P2P_DIR_SENT:
|
||||
|
@ -3288,18 +3192,179 @@ dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
|
|||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
int 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);
|
||||
}
|
||||
|
||||
next_tvb = decode_fcs(tvb, fh_tree, ppp_fcs_decode, proto_offset);
|
||||
/*
|
||||
* XXX - this needs to handle a PPP frame split over multiple higher-level
|
||||
* packets.
|
||||
*/
|
||||
|
||||
dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue