aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rpcrdma.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2016-11-09 10:06:45 -0500
committerMichael Mann <mmann78@netscape.net>2016-12-02 22:45:27 +0000
commit2462f9e8103b23c2728cc5aa84995e0b2f363f12 (patch)
tree71e96e7d9a89e4188a160157d8e89572e934e62f /epan/dissectors/packet-rpcrdma.c
parent54f48c8b92475523a49c15cd549fb5408e96ea8d (diff)
packet-rpcrdma: Fix protocol frame pre-detection
The current mechanism of detecting RPC-over-RDMA is broken because it treats the Read list as a counted array (it's a list); and treats the Write list and Reply chunk identically (one is a list, one is always a single chunk). While we're here, refactor pre-detection helper functions so they can be used during frame dissection as well. Bug: 13196 Change-Id: I76e210c8d2a9464fed00e7199072d37f4ebbebf2 Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-on: https://code.wireshark.org/review/19025 Petri-Dish: Michael Mann <mmann78@netscape.net> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-rpcrdma.c')
-rw-r--r--epan/dissectors/packet-rpcrdma.c127
1 files changed, 90 insertions, 37 deletions
diff --git a/epan/dissectors/packet-rpcrdma.c b/epan/dissectors/packet-rpcrdma.c
index f825800d86..2e6854574d 100644
--- a/epan/dissectors/packet-rpcrdma.c
+++ b/epan/dissectors/packet-rpcrdma.c
@@ -130,6 +130,72 @@ static const value_string rpcordma_err[] = {
{0, NULL}
};
+static guint get_read_list_size(tvbuff_t *tvb, guint max_offset, guint offset)
+{
+ guint32 value_follows;
+ guint start = offset;
+
+ while (1) {
+ value_follows = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ if (offset > max_offset)
+ return 0;
+ if (!value_follows)
+ break;
+
+ offset += 20;
+ if (offset > max_offset)
+ return 0;
+ }
+
+ return offset - start;
+}
+
+static guint get_write_list_size(tvbuff_t *tvb, guint max_offset, guint offset)
+{
+ guint32 value_follows, segment_count;
+ guint start = offset;
+
+ while (1) {
+ value_follows = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ if (offset > max_offset)
+ return 0;
+ if (!value_follows)
+ break;
+
+ segment_count = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ if (offset > max_offset)
+ return 0;
+ offset += (segment_count * 16);
+ if (offset > max_offset)
+ return 0;
+ }
+
+ return offset - start;
+}
+
+static guint get_reply_chunk_size(tvbuff_t *tvb, guint max_offset, guint offset)
+{
+ guint32 value_follows, segment_count;
+ guint start = offset;
+
+ value_follows = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ if (offset > max_offset)
+ return 0;
+
+ if (value_follows) {
+ segment_count = tvb_get_ntohl(tvb, offset);
+ offset += segment_count * 16 + 4;
+ if (offset > max_offset)
+ return 0;
+ }
+
+ return offset - start;
+}
+
static guint parse_list(tvbuff_t *tvb, guint offset, proto_tree *tree,
int hf_item, const char* msg, gboolean have_position)
{
@@ -178,45 +244,26 @@ static guint parse_rdma_header(tvbuff_t *tvb, guint offset, proto_tree *tree)
return offset;
}
-static gboolean
-get_chunk_len(tvbuff_t *tvb, guint offset, guint len, guint num_position_bytes, guint *res)
+static guint get_chunk_lists_size(tvbuff_t *tvb, guint max_offset, guint offset)
{
- guint32 arr_len, i, val, temp;
-
- if (offset + 4 > len)
- return FALSE;
-
- arr_len = tvb_get_ntohl(tvb, offset);
- offset += 4;
-
- for (i = 0; i < arr_len; i++) {
- if (offset + 4 > len)
- return FALSE;
- val = tvb_get_ntohl(tvb, offset);
- offset += 4;
+ guint size, start = offset;
- /* xdr_rdma_segment(s) */
- temp = offset + val * (16 + num_position_bytes);
- if ((temp > len) || (temp < offset))
- return FALSE;
- offset = temp;
- }
- DISSECTOR_ASSERT(offset <= len);
-
- *res = offset;
- return TRUE;
-}
+ size = get_read_list_size(tvb, max_offset, offset);
+ if (!size)
+ return 0;
+ offset += size;
-static gboolean
-get_chunks_len(tvbuff_t *tvb, guint offset, guint len, guint *res)
-{
- if (!get_chunk_len(tvb, offset, len, 4, res))
- return FALSE;
+ size = get_write_list_size(tvb, max_offset, offset);
+ if (!size)
+ return 0;
+ offset += size;
- if (!get_chunk_len(tvb, *res, len, 0, res))
- return FALSE;
+ size = get_reply_chunk_size(tvb, max_offset, offset);
+ if (!size)
+ return 0;
+ offset += size;
- return get_chunk_len(tvb, *res, len, 0, res);
+ return offset - start;
}
/*
@@ -229,7 +276,7 @@ get_chunks_len(tvbuff_t *tvb, guint offset, guint len, guint *res)
static gboolean
packet_is_rpcordma(tvbuff_t *tvb)
{
- guint len = tvb_reported_length(tvb);
+ guint size, len = tvb_reported_length(tvb);
guint32 xid_rpc;
guint32 xid = tvb_get_ntohl(tvb, 0);
guint32 msg_type = tvb_get_ntohl(tvb, 12);
@@ -239,8 +286,11 @@ packet_is_rpcordma(tvbuff_t *tvb)
case RDMA_MSG:
if (len < MIN_RPCRDMA_MSG_SZ)
return FALSE;
- if (!get_chunks_len(tvb, MIN_RPCRDMA_HDR_SZ, len, &offset))
+ offset = MIN_RPCRDMA_HDR_SZ;
+ size = get_chunk_lists_size(tvb, len, offset);
+ if (!size)
return FALSE;
+ offset += size;
if (offset + 4 > len)
return FALSE;
@@ -252,8 +302,11 @@ packet_is_rpcordma(tvbuff_t *tvb)
case RDMA_MSGP:
if (len < MIN_RPCRDMA_MSGP_SZ)
return FALSE;
- if (!get_chunks_len(tvb, MIN_RPCRDMA_HDR_SZ + 8, len, &offset))
+ offset = MIN_RPCRDMA_HDR_SZ + 8;
+ size = get_chunk_lists_size(tvb, len, offset);
+ if (!size)
return FALSE;
+ offset += size;
if (offset + 4 > len)
return FALSE;