SABP: add support for messages >= 16KB

Because of the way PER specification encodes length determinant >= 16K,
we cannot get the PDU length from a fixed position at the beginning of
the message. So drop tcp_dissect_pdus() (that cannot work for this use
case) and manually request extra chunks until the full PDU is available.

Bug: 8221
Change-Id: I91e32160fc2180f74b3edb9699ba510798b46983
Reviewed-on: https://code.wireshark.org/review/18808
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Pascal Quantin 2016-11-13 22:52:06 +01:00 committed by Anders Broman
parent c88b8ad55b
commit 271ee471dd
2 changed files with 74 additions and 76 deletions

View File

@ -75,9 +75,6 @@ static guint8 sms_encoding;
#define SABP_PORT 3452
/* desegmentation of sabp over TCP */
static gboolean gbl_sabp_desegment = TRUE;
/* Dissector tables */
static dissector_table_t sabp_ies_dissector_table;
static dissector_table_t sabp_extension_dissector_table;
@ -171,34 +168,6 @@ dissect_sabp_cb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
static guint
get_sabp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
guint32 type_length;
int bit_offset;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
/* Length should be in the 3:d octet */
offset = offset + 3;
bit_offset = offset<<3;
/* Get the length of the sabp packet. offset in bits */
dissect_per_length_determinant(tvb, bit_offset, &asn1_ctx, NULL, -1, &type_length, NULL);
/*
* Return the length of the PDU
* which is 3 + the length of the length, we only care about length up to 16K
* ("n" less than 128) a single octet containing "n" with bit 8 set to zero;
* ("n" less than 16K) two octets containing "n" with bit 8 of the first octet set to 1 and bit 7 set to zero;
*/
if (type_length < 128)
return type_length+4;
return type_length+5;
}
static int
dissect_sabp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
@ -212,17 +181,47 @@ dissect_sabp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
sabp_item = proto_tree_add_item(tree, proto_sabp, tvb, 0, -1, ENC_NA);
sabp_tree = proto_item_add_subtree(sabp_item, ett_sabp);
dissect_SABP_PDU_PDU(tvb, pinfo, sabp_tree, NULL);
return tvb_captured_length(tvb);
return dissect_SABP_PDU_PDU(tvb, pinfo, sabp_tree, NULL);
}
/* Note a little bit of a hack assumes length max takes two bytes and that the length starts at byte 4 */
static int
dissect_sabp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
tcp_dissect_pdus(tvb, pinfo, tree, gbl_sabp_desegment, 5,
get_sabp_pdu_len, dissect_sabp, data);
return tvb_captured_length(tvb);
guint32 type_length, msg_len;
guint tvb_length;
int bit_offset;
gboolean is_fragmented;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
tvb_length = tvb_reported_length(tvb);
if (tvb_length < 5) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return tvb_captured_length(tvb);
}
/* Length should be in the 3:d octet */
bit_offset = 24;
/* Get the length of the sabp packet. Offset in bits */
do {
bit_offset = dissect_per_length_determinant(tvb, bit_offset, &asn1_ctx, NULL, -1, &type_length, &is_fragmented);
bit_offset += 8*type_length;
msg_len = (bit_offset + 7) >> 3;
if (is_fragmented) {
/* Next length field will take 1 or 2 bytes; let's ask for the maximum */
msg_len += 2;
}
if (msg_len > tvb_length) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = msg_len - tvb_length;
return tvb_captured_length(tvb);
}
} while (is_fragmented);
return dissect_sabp(tvb, pinfo, tree, data);
}
/*--- proto_register_sabp -------------------------------------------*/

View File

@ -257,9 +257,6 @@ static guint8 sms_encoding;
#define SABP_PORT 3452
/* desegmentation of sabp over TCP */
static gboolean gbl_sabp_desegment = TRUE;
/* Dissector tables */
static dissector_table_t sabp_ies_dissector_table;
static dissector_table_t sabp_extension_dissector_table;
@ -1732,7 +1729,7 @@ static int dissect_SABP_PDU_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto
/*--- End of included file: packet-sabp-fn.c ---*/
#line 99 "./asn1/sabp/packet-sabp-template.c"
#line 96 "./asn1/sabp/packet-sabp-template.c"
static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
@ -1808,34 +1805,6 @@ dissect_sabp_cb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
static guint
get_sabp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
guint32 type_length;
int bit_offset;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
/* Length should be in the 3:d octet */
offset = offset + 3;
bit_offset = offset<<3;
/* Get the length of the sabp packet. offset in bits */
dissect_per_length_determinant(tvb, bit_offset, &asn1_ctx, NULL, -1, &type_length, NULL);
/*
* Return the length of the PDU
* which is 3 + the length of the length, we only care about length up to 16K
* ("n" less than 128) a single octet containing "n" with bit 8 set to zero;
* ("n" less than 16K) two octets containing "n" with bit 8 of the first octet set to 1 and bit 7 set to zero;
*/
if (type_length < 128)
return type_length+4;
return type_length+5;
}
static int
dissect_sabp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
@ -1849,17 +1818,47 @@ dissect_sabp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
sabp_item = proto_tree_add_item(tree, proto_sabp, tvb, 0, -1, ENC_NA);
sabp_tree = proto_item_add_subtree(sabp_item, ett_sabp);
dissect_SABP_PDU_PDU(tvb, pinfo, sabp_tree, NULL);
return tvb_captured_length(tvb);
return dissect_SABP_PDU_PDU(tvb, pinfo, sabp_tree, NULL);
}
/* Note a little bit of a hack assumes length max takes two bytes and that the length starts at byte 4 */
static int
dissect_sabp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
tcp_dissect_pdus(tvb, pinfo, tree, gbl_sabp_desegment, 5,
get_sabp_pdu_len, dissect_sabp, data);
return tvb_captured_length(tvb);
guint32 type_length, msg_len;
guint tvb_length;
int bit_offset;
gboolean is_fragmented;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
tvb_length = tvb_reported_length(tvb);
if (tvb_length < 5) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return tvb_captured_length(tvb);
}
/* Length should be in the 3:d octet */
bit_offset = 24;
/* Get the length of the sabp packet. Offset in bits */
do {
bit_offset = dissect_per_length_determinant(tvb, bit_offset, &asn1_ctx, NULL, -1, &type_length, &is_fragmented);
bit_offset += 8*type_length;
msg_len = (bit_offset + 7) >> 3;
if (is_fragmented) {
/* Next length field will take 1 or 2 bytes; let's ask for the maximum */
msg_len += 2;
}
if (msg_len > tvb_length) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = msg_len - tvb_length;
return tvb_captured_length(tvb);
}
} while (is_fragmented);
return dissect_sabp(tvb, pinfo, tree, data);
}
/*--- proto_register_sabp -------------------------------------------*/
@ -2206,7 +2205,7 @@ void proto_register_sabp(void) {
"UnsuccessfulOutcome_value", HFILL }},
/*--- End of included file: packet-sabp-hfarr.c ---*/
#line 252 "./asn1/sabp/packet-sabp-template.c"
#line 251 "./asn1/sabp/packet-sabp-template.c"
};
/* List of subtrees */
@ -2263,7 +2262,7 @@ void proto_register_sabp(void) {
&ett_sabp_UnsuccessfulOutcome,
/*--- End of included file: packet-sabp-ettarr.c ---*/
#line 265 "./asn1/sabp/packet-sabp-template.c"
#line 264 "./asn1/sabp/packet-sabp-template.c"
};
@ -2340,7 +2339,7 @@ proto_reg_handoff_sabp(void)
/*--- End of included file: packet-sabp-dis-tab.c ---*/
#line 296 "./asn1/sabp/packet-sabp-template.c"
#line 295 "./asn1/sabp/packet-sabp-template.c"
}