|
|
dbc6ab |
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
|
|
|
dbc6ab |
index 225a7eb..e3e81f7 100644
|
|
|
dbc6ab |
--- a/epan/dissectors/packet-http.c
|
|
|
dbc6ab |
+++ b/epan/dissectors/packet-http.c
|
|
|
dbc6ab |
@@ -2625,6 +2625,10 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
dbc6ab |
} else {
|
|
|
dbc6ab |
while (tvb_reported_length_remaining(tvb, offset) != 0) {
|
|
|
dbc6ab |
if (conv_data->upgrade == UPGRADE_WEBSOCKET && pinfo->fd->num >= conv_data->startframe) {
|
|
|
dbc6ab |
+ /* Websockets is a stream of data, preserve
|
|
|
dbc6ab |
+ * desegmentation functionality. */
|
|
|
dbc6ab |
+ if (pinfo->can_desegment > 0)
|
|
|
dbc6ab |
+ pinfo->can_desegment++;
|
|
|
dbc6ab |
call_dissector_only(websocket_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree, NULL);
|
|
|
dbc6ab |
break;
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
diff --git a/epan/dissectors/packet-websocket.c b/epan/dissectors/packet-websocket.c
|
|
|
dbc6ab |
index e02825d..561e206 100644
|
|
|
dbc6ab |
--- a/epan/dissectors/packet-websocket.c
|
|
|
dbc6ab |
+++ b/epan/dissectors/packet-websocket.c
|
|
|
dbc6ab |
@@ -31,6 +31,7 @@
|
|
|
dbc6ab |
#include <epan/expert.h>
|
|
|
dbc6ab |
#include <epan/prefs.h>
|
|
|
dbc6ab |
|
|
|
dbc6ab |
+#include "packet-tcp.h"
|
|
|
dbc6ab |
|
|
|
dbc6ab |
/*
|
|
|
dbc6ab |
* The information used comes from:
|
|
|
dbc6ab |
@@ -152,7 +153,7 @@ tvb_unmasked(tvbuff_t *tvb, const guint offset, guint payload_length, const guin
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
|
|
|
dbc6ab |
static int
|
|
|
dbc6ab |
-dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, guint8 mask, const guint8* masking_key)
|
|
|
dbc6ab |
+dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, gboolean mask, const guint8* masking_key)
|
|
|
dbc6ab |
{
|
|
|
dbc6ab |
guint offset = 0;
|
|
|
dbc6ab |
proto_item *ti_unmask, *ti;
|
|
|
dbc6ab |
@@ -301,65 +302,35 @@ dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, p
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
|
|
|
dbc6ab |
|
|
|
dbc6ab |
-static int
|
|
|
dbc6ab |
-dissect_websocket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|
|
dbc6ab |
+static void
|
|
|
dbc6ab |
+dissect_websocket_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
dbc6ab |
{
|
|
|
dbc6ab |
proto_item *ti, *ti_len;
|
|
|
dbc6ab |
- guint8 fin, opcode, mask;
|
|
|
dbc6ab |
- guint length, short_length, payload_length, recurse_length;
|
|
|
dbc6ab |
- guint payload_offset, mask_offset, recurse_offset;
|
|
|
dbc6ab |
+ guint8 fin, opcode;
|
|
|
dbc6ab |
+ gboolean mask;
|
|
|
dbc6ab |
+ guint short_length, payload_length;
|
|
|
dbc6ab |
+ guint payload_offset, mask_offset;
|
|
|
dbc6ab |
proto_tree *ws_tree = NULL;
|
|
|
dbc6ab |
const guint8 *masking_key = NULL;
|
|
|
dbc6ab |
tvbuff_t *tvb_payload = NULL;
|
|
|
dbc6ab |
|
|
|
dbc6ab |
- length = tvb_length(tvb);
|
|
|
dbc6ab |
- if(length<2){
|
|
|
dbc6ab |
- pinfo->desegment_len = 2;
|
|
|
dbc6ab |
- return 0;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
-
|
|
|
dbc6ab |
short_length = tvb_get_guint8(tvb, 1) & MASK_WS_PAYLOAD_LEN;
|
|
|
dbc6ab |
+ mask_offset = 2;
|
|
|
dbc6ab |
if(short_length==126){
|
|
|
dbc6ab |
- if(length < 2+2){
|
|
|
dbc6ab |
- pinfo->desegment_len = 2+2;
|
|
|
dbc6ab |
- return 0;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
payload_length = tvb_get_ntohs(tvb, 2);
|
|
|
dbc6ab |
- mask_offset = 2+2;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
- else if(short_length==127){
|
|
|
dbc6ab |
- if(length < 2+8){
|
|
|
dbc6ab |
- pinfo->desegment_len = 2+8;
|
|
|
dbc6ab |
- return 0;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
- /* warning C4244: '=' : conversion from 'guint64' to 'guint ', possible loss of data */
|
|
|
dbc6ab |
+ mask_offset += 2;
|
|
|
dbc6ab |
+ } else if (short_length==127) {
|
|
|
dbc6ab |
+ /* warning C4244: '=' : conversion from 'guint64' to 'guint ', possible loss of data */
|
|
|
dbc6ab |
payload_length = (guint)tvb_get_ntoh64(tvb, 2);
|
|
|
dbc6ab |
- mask_offset = 2+8;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
- else{
|
|
|
dbc6ab |
+ mask_offset += 8;
|
|
|
dbc6ab |
+ } else {
|
|
|
dbc6ab |
payload_length = short_length;
|
|
|
dbc6ab |
- mask_offset = 2;
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
|
|
|
dbc6ab |
/* Mask */
|
|
|
dbc6ab |
- mask = (tvb_get_guint8(tvb, 1) & MASK_WS_MASK) >> 4;
|
|
|
dbc6ab |
+ mask = (tvb_get_guint8(tvb, 1) & MASK_WS_MASK) != 0;
|
|
|
dbc6ab |
payload_offset = mask_offset + (mask ? 4 : 0);
|
|
|
dbc6ab |
|
|
|
dbc6ab |
- if (payload_offset + payload_length < payload_length) {
|
|
|
dbc6ab |
- /* Integer overflow, which means the packet contains a ridiculous
|
|
|
dbc6ab |
- * payload length. Just take what we've got available.
|
|
|
dbc6ab |
- * See bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8448 */
|
|
|
dbc6ab |
- payload_length = tvb_reported_length_remaining(tvb, payload_offset);
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
-
|
|
|
dbc6ab |
- if(length < payload_offset + payload_length){
|
|
|
dbc6ab |
- /* XXXX Warning desegment_len is 32 bits */
|
|
|
dbc6ab |
- pinfo->desegment_len = payload_offset + payload_length - length;
|
|
|
dbc6ab |
- return 0;
|
|
|
dbc6ab |
- }
|
|
|
dbc6ab |
-
|
|
|
dbc6ab |
- /* We've got the entire message! */
|
|
|
dbc6ab |
-
|
|
|
dbc6ab |
col_set_str(pinfo->cinfo, COL_PROTOCOL, "WebSocket");
|
|
|
dbc6ab |
col_set_str(pinfo->cinfo, COL_INFO, "WebSocket");
|
|
|
dbc6ab |
|
|
|
dbc6ab |
@@ -402,18 +373,49 @@ dissect_websocket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
|
|
|
dbc6ab |
|
|
|
dbc6ab |
tvb_payload = tvb_new_subset_remaining(tvb, payload_offset);
|
|
|
dbc6ab |
dissect_websocket_payload(tvb_payload, pinfo, tree, ws_tree, opcode, payload_length, mask, masking_key);
|
|
|
dbc6ab |
+}
|
|
|
dbc6ab |
+
|
|
|
dbc6ab |
+static guint
|
|
|
dbc6ab |
+get_websocket_frame_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
|
|
|
dbc6ab |
+{
|
|
|
dbc6ab |
+ guint frame_length, payload_length;
|
|
|
dbc6ab |
+ gboolean mask;
|
|
|
dbc6ab |
+
|
|
|
dbc6ab |
+ frame_length = 2; /* flags, opcode and Payload length */
|
|
|
dbc6ab |
+ mask = tvb_get_guint8(tvb, offset + 1) & MASK_WS_MASK;
|
|
|
dbc6ab |
+
|
|
|
dbc6ab |
+ payload_length = tvb_get_guint8(tvb, offset + 1) & MASK_WS_PAYLOAD_LEN;
|
|
|
dbc6ab |
+ offset += 2; /* Skip flags, opcode and Payload length */
|
|
|
dbc6ab |
|
|
|
dbc6ab |
- /* Call this function recursively, to see if we have enough data to parse another websocket message */
|
|
|
dbc6ab |
+ /* Check for Extended Payload Length. */
|
|
|
dbc6ab |
+ if (payload_length == 126) {
|
|
|
dbc6ab |
+ if (tvb_reported_length_remaining(tvb, offset) < 2)
|
|
|
dbc6ab |
+ return 0; /* Need more data. */
|
|
|
dbc6ab |
|
|
|
dbc6ab |
- recurse_offset = payload_offset + payload_length;
|
|
|
dbc6ab |
- if(length > recurse_offset){
|
|
|
dbc6ab |
- recurse_length = dissect_websocket(tvb_new_subset_remaining(tvb, payload_offset+payload_length), pinfo, tree, data);
|
|
|
dbc6ab |
- if(pinfo->desegment_len) pinfo->desegment_offset += recurse_offset;
|
|
|
dbc6ab |
- return recurse_offset + recurse_length;
|
|
|
dbc6ab |
+ payload_length = tvb_get_ntohs(tvb, offset);
|
|
|
dbc6ab |
+ frame_length += 2; /* Extended payload length */
|
|
|
dbc6ab |
+ } else if (payload_length == 127) {
|
|
|
dbc6ab |
+ if (tvb_reported_length_remaining(tvb, offset) < 8)
|
|
|
dbc6ab |
+ return 0; /* Need more data. */
|
|
|
dbc6ab |
+
|
|
|
dbc6ab |
+ payload_length = (guint)tvb_get_ntoh64(tvb, offset);
|
|
|
dbc6ab |
+ frame_length += 8; /* Extended payload length */
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
- return recurse_offset;
|
|
|
dbc6ab |
+
|
|
|
dbc6ab |
+ if (mask)
|
|
|
dbc6ab |
+ frame_length += 4; /* Masking-key */
|
|
|
dbc6ab |
+ frame_length += payload_length; /* Payload data */
|
|
|
dbc6ab |
+ return frame_length;
|
|
|
dbc6ab |
}
|
|
|
dbc6ab |
|
|
|
dbc6ab |
+static int
|
|
|
dbc6ab |
+dissect_websocket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|
|
dbc6ab |
+{
|
|
|
dbc6ab |
+ /* Need at least two bytes for flags, opcode and Payload length. */
|
|
|
dbc6ab |
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 2,
|
|
|
dbc6ab |
+ get_websocket_frame_length, dissect_websocket_frame);
|
|
|
dbc6ab |
+ return tvb_length(tvb);
|
|
|
dbc6ab |
+}
|
|
|
dbc6ab |
|
|
|
dbc6ab |
void
|
|
|
dbc6ab |
proto_register_websocket(void)
|