aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-tplink-smarthome.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-tplink-smarthome.c')
-rw-r--r--epan/dissectors/packet-tplink-smarthome.c93
1 files changed, 65 insertions, 28 deletions
diff --git a/epan/dissectors/packet-tplink-smarthome.c b/epan/dissectors/packet-tplink-smarthome.c
index e8e0a7f45d..e2f7e133b4 100644
--- a/epan/dissectors/packet-tplink-smarthome.c
+++ b/epan/dissectors/packet-tplink-smarthome.c
@@ -32,10 +32,12 @@
#include <config.h>
#include <epan/packet.h>
#include <epan/address.h>
+#include <epan/conversation.h>
#include <epan/wmem_scopes.h>
#include "packet-tcp.h"
-#define TPLINK_SMARTHOME_PORT 9999 /* TP-Link Smart Home devices use this port on both TCP and UDP */
+#define TPLINK_SMARTHOME_PORT 9999 /* Not IANA registered */
+/* TP-Link Smart Home devices use this port on both TCP and UDP */
#define FRAME_HEADER_LEN 4 /* 4 bytes of TCP frame length header info */
/* Prototypes */
@@ -44,13 +46,41 @@
void proto_reg_handoff_tplink_smarthome(void);
void proto_register_tplink_smarthome(void);
+static dissector_handle_t tplink_smarthome_handle;
+static dissector_handle_t tplink_smarthome_message_handle;
+
/* Initialize the protocol and registered fields */
-static int proto_tplink_smarthome = -1;
-static gint ett_tplink_smarthome = -1; /* Initialize the subtree pointers */
+static int proto_tplink_smarthome;
+static gint ett_tplink_smarthome; /* Initialize the subtree pointers */
+
+static int hf_tplink_smarthome_Len;
+static int hf_tplink_smarthome_Msg;
+
+static gboolean
+test_tplink_smarthome(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
+{
+ guint8 key = 171;
+ guint8 c, d;
+ if (tvb_captured_length_remaining(tvb, offset) < 2) {
+ return FALSE;
+ }
+
+ /* The message is always JSON, so test the first two characters.
+ * They must be {" or {}, as the protocol doesn't appear to
+ * have whitespace.). */
+ c = tvb_get_guint8(tvb, offset);
+ d = c ^ key;
+ if (d != '{') {
+ return FALSE;
+ }
+ d = c ^ tvb_get_guint8(tvb, offset+1);
+ if (d != '"' && d != '}') {
+ return FALSE;
+ }
-static int hf_tplink_smarthome_Len = -1;
-static int hf_tplink_smarthome_Msg = -1;
+ return TRUE;
+}
static int
dissect_tplink_smarthome_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
@@ -58,20 +88,24 @@ dissect_tplink_smarthome_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
{
proto_item *ti;
proto_tree *tplink_smarthome_tree;
- gint8 start;
+ gint8 start = 0;
+ guint8 c, d;
+ guint8 key = 171;
gint32 len = tvb_captured_length(tvb);
- switch (pinfo->ptype) { /* look at the IP port type */
- case PT_UDP: /* UDP */
- if (len < 2) return 0; /* don't dissect unless it contains enough to hold minimum valid JSON i.e. '{}' */
- start = 0; /* and the JSON message starts immediately */
- break;
- case PT_TCP: /* TCP */
- if (len < (4 + 2)) return 0; /* don't dissect unless it has the msg length plus minimal JSON */
- start = 4; /* and the JSON message starts after that */
- break;
- default:
- return 0;
+ switch (pinfo->ptype) { /* look at the IP port type */
+ case PT_UDP:
+ start = 0;
+ break;
+ case PT_TCP:
+ start = 4;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!test_tplink_smarthome(pinfo, tvb, start, data)) {
+ return 0;
}
col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPLINK-SMARTHOME"); /* show the protocol name of what we're dissecting */
@@ -82,10 +116,8 @@ dissect_tplink_smarthome_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
if (pinfo->ptype == PT_TCP) {
proto_tree_add_item(tplink_smarthome_tree, hf_tplink_smarthome_Len,
- tvb, 0, FRAME_HEADER_LEN, ENC_BIG_ENDIAN); /* decode the the 4 byte message length field pre-pended in a TCP message, */
+ tvb, 0, FRAME_HEADER_LEN, ENC_BIG_ENDIAN); /* decode the 4 byte message length field pre-pended in a TCP message, */
}
- guint8 c, d;
- guint8 key = 171;
gint i_offset = start;
gint o_offset = 0;
gint decode_len = len - start;
@@ -127,12 +159,15 @@ get_tplink_smarthome_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offs
static int
dissect_tplink_smarthome(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
- if (pinfo->ptype == PT_UDP) {
- dissect_tplink_smarthome_message(tvb, pinfo, tree, data);
- } else {
- tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
- get_tplink_smarthome_message_len, dissect_tplink_smarthome_message, data);
+ conversation_t *conv = find_or_create_conversation(pinfo);
+ if (!conversation_get_proto_data(conv, proto_tplink_smarthome)) {
+ if (!test_tplink_smarthome(pinfo, tvb, FRAME_HEADER_LEN, data)) {
+ return 0;
+ }
+ conversation_add_proto_data(conv, proto_tplink_smarthome, GUINT_TO_POINTER(1));
}
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
+ get_tplink_smarthome_message_len, dissect_tplink_smarthome_message, data);
return tvb_captured_length(tvb);
}
@@ -160,6 +195,10 @@ proto_register_tplink_smarthome(void)
proto_tplink_smarthome = proto_register_protocol("TP-Link Smart Home Protocol", /* register the protocol name and description */
"TPLINK-SMARTHOME", "tplink-smarthome");
+ tplink_smarthome_handle = register_dissector("tplink-smarthome",
+ dissect_tplink_smarthome, proto_tplink_smarthome);
+ tplink_smarthome_message_handle = register_dissector("tplink-smarthome-message",
+ dissect_tplink_smarthome_message, proto_tplink_smarthome);
proto_register_field_array(proto_tplink_smarthome, hf, array_length(hf)); /* register the header fields */
proto_register_subtree_array(ett, array_length(ett)); /* and subtrees */
@@ -168,11 +207,9 @@ proto_register_tplink_smarthome(void)
void
proto_reg_handoff_tplink_smarthome(void)
{
- dissector_handle_t tplink_smarthome_handle;
- tplink_smarthome_handle = create_dissector_handle(dissect_tplink_smarthome, proto_tplink_smarthome);
dissector_add_uint_with_preference("tcp.port", TPLINK_SMARTHOME_PORT, tplink_smarthome_handle);
- dissector_add_uint_with_preference("udp.port", TPLINK_SMARTHOME_PORT, tplink_smarthome_handle);
+ dissector_add_uint_with_preference("udp.port", TPLINK_SMARTHOME_PORT, tplink_smarthome_message_handle);
}
/*