diff options
-rw-r--r-- | epan/dissectors/packet-rlc-lte.c | 137 | ||||
-rw-r--r-- | epan/dissectors/packet-rlc-lte.h | 58 |
2 files changed, 195 insertions, 0 deletions
diff --git a/epan/dissectors/packet-rlc-lte.c b/epan/dissectors/packet-rlc-lte.c index 2fdc11d83b..b59e5584e0 100644 --- a/epan/dissectors/packet-rlc-lte.c +++ b/epan/dissectors/packet-rlc-lte.c @@ -1144,6 +1144,128 @@ static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo, } +/* Forwad declarations */ +void proto_reg_handoff_rlc_lte(void); +void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +/* Heuristic dissection */ +static gboolean global_rlc_lte_heur = FALSE; + +/* Heuristic dissector looks for supported framing protocol (see wiki page) */ +static gboolean dissect_rlc_lte_heur(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *tree) +{ + gint offset = 0; + struct rlc_lte_info *p_rlc_lte_info; + tvbuff_t *rlc_tvb; + guint8 tag = 0; + gboolean infoAlreadySet = FALSE; + gboolean umSeqNumLengthTagPresent = FALSE; + + /* This is a heuristic dissector, which means we get all the UDP + * traffic not sent to a known dissector and not claimed by + * a heuristic dissector called before us! + */ + + if (!global_rlc_lte_heur) { + return FALSE; + } + + /* If redissecting, use previous info struct (if available) */ + p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte); + if (p_rlc_lte_info == NULL) { + /* Allocate new info struct for this frame */ + p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info)); + if (p_rlc_lte_info == NULL) { + return FALSE; + } + infoAlreadySet = FALSE; + } + else { + infoAlreadySet = TRUE; + } + + /* Do this again on re-dissection to re-discover offset of actual PDU */ + + /* Needs to be at least as long as: + - the signature string + - fixed header bytes + - tag for data + - at least one byte of RLC PDU payload */ + if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(RLC_LTE_START_STRING)+1+2)) { + return FALSE; + } + + /* OK, compare with signature string */ + if (tvb_strneql(tvb, offset, RLC_LTE_START_STRING, (gint)strlen(RLC_LTE_START_STRING)) != 0) { + return FALSE; + } + offset += (gint)strlen(RLC_LTE_START_STRING); + + /* Read fixed fields */ + p_rlc_lte_info->rlcMode = tvb_get_guint8(tvb, offset++); + + /* Read optional fields */ + while (tag != RLC_LTE_PAYLOAD_TAG) { + /* Process next tag */ + tag = tvb_get_guint8(tvb, offset++); + switch (tag) { + case RLC_LTE_UM_SN_LENGTH_TAG: + p_rlc_lte_info->UMSequenceNumberLength = tvb_get_guint8(tvb, offset); + offset++; + umSeqNumLengthTagPresent = TRUE; + break; + case RLC_LTE_DIRECTION_TAG: + p_rlc_lte_info->direction = tvb_get_guint8(tvb, offset); + offset++; + break; + case RLC_LTE_PRIORITY_TAG: + p_rlc_lte_info->priority = tvb_get_guint8(tvb, offset); + offset++; + break; + case RLC_LTE_UEID_TAG: + p_rlc_lte_info->ueid = tvb_get_ntohs(tvb, offset); + offset += 2; + break; + case RLC_LTE_CHANNEL_TYPE_TAG: + p_rlc_lte_info->channelType = tvb_get_ntohs(tvb, offset); + offset += 2; + break; + case RLC_LTE_CHANNEL_ID_TAG: + p_rlc_lte_info->channelId = tvb_get_ntohs(tvb, offset); + offset += 2; + break; + + case RLC_LTE_PAYLOAD_TAG: + /* Have reached data, so set payload length and get out of loop */ + p_rlc_lte_info->pduLength= tvb_length_remaining(tvb, offset); + continue; + + default: + /* It must be a recognised tag */ + return FALSE; + } + } + + if ((p_rlc_lte_info->rlcMode == RLC_UM_MODE) && (umSeqNumLengthTagPresent == FALSE)) { + /* Conditional field is not present */ + return FALSE; + } + + if (!infoAlreadySet) { + /* Store info in packet */ + p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info); + } + + /**************************************/ + /* OK, now dissect as RLC LTE */ + + /* Create tvb that starts at actual RLC PDU */ + rlc_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset); + dissect_rlc_lte(rlc_tvb, pinfo, tree); + return TRUE; +} + /*****************************/ /* Main dissection function. */ @@ -1618,8 +1740,23 @@ void proto_register_rlc_lte(void) "Call RRC dissector for CCCH PDUs", &global_rlc_lte_call_rrc); + prefs_register_bool_preference(rlc_lte_module, "heuristic_rlc_lte_over_udp", + "Try Heuristic LTE-RLC over UDP framing", + "When enabled, use heuristic dissector to find RLC-LTE frames sent with " + "UDP framing", + &global_rlc_lte_heur); register_init_routine(&rlc_lte_init_protocol); } +void +proto_reg_handoff_rlc_lte(void) +{ + static dissector_handle_t rlc_lte_handle; + if (!rlc_lte_handle) { + rlc_lte_handle = find_dissector("rlc-lte"); + /* Add as a heuristic UDP dissector */ + heur_dissector_add("udp", dissect_rlc_lte_heur, proto_rlc_lte); + } +} diff --git a/epan/dissectors/packet-rlc-lte.h b/epan/dissectors/packet-rlc-lte.h index 6ece90b57d..191be962bf 100644 --- a/epan/dissectors/packet-rlc-lte.h +++ b/epan/dissectors/packet-rlc-lte.h @@ -58,3 +58,61 @@ typedef struct rlc_lte_info guint8 UMSequenceNumberLength; } rlc_lte_info; + + +/*****************************************************************/ +/* UDP framing format */ +/* ----------------------- */ +/* Several people have asked about dissecting RLC by framing */ +/* PDUs over IP. A suggested format over UDP has been defined */ +/* and implemented by this dissector, using the definitions */ +/* below. */ +/* */ +/* A heuristic dissecter (enabled by a preference) will */ +/* recognise a signature at the beginning of these frames. */ +/* Until someone is using this format, suggestions for changes */ +/* are welcome. */ +/*****************************************************************/ + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define RLC_LTE_START_STRING "rlc-lte" + +/* Fixed field. This is followed by the following 1 mandatory field: + - rlcMode (1 byte) + (where the allowed values are defined above */ + +/* Conditional field. This field is mandatory in case of RLC Unacknowledged mode. + The format is to have the tag, followed by the value (there is no length field, + its implicit from the tag). The allowed values are defined above. */ + +#define RLC_LTE_UM_SN_LENGTH_TAG 0x02 +/* 1 byte */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + its implicit from the tag) */ + +#define RLC_LTE_DIRECTION_TAG 0x03 +/* 1 byte */ + +#define RLC_LTE_PRIORITY_TAG 0x04 +/* 1 byte */ + +#define RLC_LTE_UEID_TAG 0x05 +/* 2 bytes, network order */ + +#define RLC_LTE_CHANNEL_TYPE_TAG 0x06 +/* 2 bytes, network order */ + +#define RLC_LTE_CHANNEL_ID_TAG 0x07 +/* 2 bytes, network order */ + + +/* RLC PDU. Following this tag comes the actual RLC PDU (there is no length, the PDU + continues until the end of the frame) */ +#define RLC_LTE_PAYLOAD_TAG 0x01 |