aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-rlc-lte.c137
-rw-r--r--epan/dissectors/packet-rlc-lte.h58
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