From: Sipwise Development Team <support@sipwise.com>
Date: Fri, 29 Nov 2019 11:23:36 +0100
Subject: [PATCH] cfgt: don't process non-sip messages

* Skip OPTION messages internally generated
---
 src/modules/cfgt/cfgt_int.c | 103 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 95 insertions(+), 8 deletions(-)

diff --git a/src/modules/cfgt/cfgt_int.c b/src/modules/cfgt/cfgt_int.c
index 5f73a05..382d696 100644
--- a/src/modules/cfgt/cfgt_int.c
+++ b/src/modules/cfgt/cfgt_int.c
@@ -30,6 +30,11 @@
 #include "../../core/pvar.h"
 #include "../../core/rpc.h"
 #include "../../core/rpc_lookup.h"
+#include "../../core/parser/msg_parser.h"
+#include "../../core/parser/parse_uri.h"
+#include "../../core/parser/parse_to.h"
+#include "../../core/parser/parse_from.h"
+#include "../../core/parser/parse_cseq.h"
 
 #include "cfgt_int.h"
 #include "cfgt_json.h"
@@ -41,6 +46,7 @@ cfgt_hash_p _cfgt_uuid = NULL;
 str cfgt_hdr_prefix = {"NGCP%", 5};
 str cfgt_basedir = {"/tmp", 4};
 int cfgt_mask = CFGT_DP_ALL;
+int not_sip = 0;
 
 int _cfgt_get_filename(int msgid, str uuid, str *dest, int *dir);
 
@@ -258,7 +264,7 @@ int _cfgt_get_hdr_helper(struct sip_msg *msg, str *res, int mode)
 			return STR_EQ(tmp, *res);
 		}
 	}
-	return 1; /* not found */
+	return 2; /* not found */
 }
 
 int _cfgt_get_hdr(struct sip_msg *msg, str *res)
@@ -465,15 +471,21 @@ int _cfgt_set_dump(struct sip_msg *msg, cfgt_node_p node, str *flow)
 
 	if(node == NULL || flow == NULL)
 		return -1;
+
 	vars = srjson_CreateObject(&node->jdoc);
 	if(vars == NULL) {
 		LM_ERR("cannot create json object\n");
 		return -1;
 	}
+
+	/* TODO: during cfgt_get_json some errors are generated due to missing
+	values in some routes. Skip the function when node->route->s.s equals
+	'dialog:failed' partially solve the issue */
 	if(cfgt_get_json(msg, 30, &node->jdoc, vars) < 0) {
 		LM_ERR("cannot get var info\n");
 		return -1;
 	}
+
 	f = srjson_CreateObject(&node->jdoc);
 	if(f == NULL) {
 		LM_ERR("cannot create json object\n");
@@ -619,6 +631,31 @@ int _cfgt_node_get_flowname(cfgt_str_list_p route, int *indx, str *dest)
 	return 0;
 }
 
+int _cfgt_parse_msg(sip_msg_t *msg)
+{
+	if(parse_msg(msg->buf, msg->len, msg) != 0) {
+		LM_ERR("outbuf buffer parsing failed!");
+		return 1;
+	}
+
+	if(msg->first_line.type == SIP_REQUEST) {
+		if(!IS_SIP(msg)) {
+			LM_DBG("non sip request message\n");
+			return 1;
+		}
+	} else if(msg->first_line.type == SIP_REPLY) {
+		if(!IS_SIP_REPLY(msg)) {
+			LM_DBG("non sip reply message\n");
+			return 1;
+		}
+	} else {
+		LM_DBG("non sip message\n");
+		return 1;
+	}
+
+	return 0;
+}
+
 int cfgt_process_route(struct sip_msg *msg, struct action *a)
 {
 	str routename;
@@ -634,6 +671,10 @@ int cfgt_process_route(struct sip_msg *msg, struct action *a)
 		return 0;
 	}
 	LM_DBG("route from action:[%s]\n", a->rname);
+	if(not_sip) {
+		LM_DBG("not_sip flag set, not a SIP message, skip it\n");
+		return 0;
+	}
 	routename.s = a->rname;
 	routename.len = strlen(a->rname);
 	switch(_cfgt_add_routename(_cfgt_node, a, &routename)) {
@@ -679,22 +720,35 @@ int cfgt_process_route(struct sip_msg *msg, struct action *a)
 
 /*
 TODO:
-- parse first line, check if is SIP
 - parse for header cfgtest
 */
 int cfgt_msgin(sr_event_param_t *evp)
 {
 	srjson_t *jobj;
+	sip_msg_t msg;
 	str *buf = (str *)evp->data;
+
 	if(buf == NULL)
 		return 0;
+	LM_DBG("msg in:{%.*s}\n", buf->len, buf->s);
+
+	// Check if it is a SIP message
+	memset(&msg, 0, sizeof(sip_msg_t));
+	msg.buf = buf->s;
+	msg.len = buf->len;
+	if(_cfgt_parse_msg(&msg) != 0) {
+		LM_DBG("set 'not_sip' flag\n");
+		not_sip = 1;
+	} else {
+		not_sip = 0;
+	}
+
 	if(_cfgt_node) {
 		cfgt_save_node(_cfgt_node);
 		_cfgt_remove_node(_cfgt_node);
 		LM_DBG("node removed\n");
 		_cfgt_node = NULL;
 	}
-	LM_DBG("msg in:{%.*s}\n", buf->len, buf->s);
 	_cfgt_node = cfgt_create_node(NULL);
 	if(_cfgt_node) {
 		jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len);
@@ -712,14 +766,23 @@ int cfgt_msgin(sr_event_param_t *evp)
 int cfgt_pre(struct sip_msg *msg, unsigned int flags, void *bar)
 {
 	str unknown = {"unknown", 7};
+	int get_hdr_result = 0;
 
 	if(_cfgt_node) {
 		if(_cfgt_node->msgid == 0) {
 			LM_DBG("new node\n");
-			if(_cfgt_get_hdr(msg, &_cfgt_node->uuid) != 0
-					|| _cfgt_node->uuid.len == 0) {
-				LM_ERR("cannot get value of cfgtest uuid header."
-					   " Using unknown\n");
+			get_hdr_result = _cfgt_get_hdr(msg, &_cfgt_node->uuid);
+			if(get_hdr_result != 0 || _cfgt_node->uuid.len == 0) {
+				if(not_sip) {
+					LM_DBG("not_sip flag set, not a SIP message."
+						   " Using 'unknown' uuid\n");
+				} else if(get_hdr_result == 2) {
+					LM_DBG("message not related to the cfgtest scenario."
+						   " Using 'unknown' uuid\n");
+				} else {
+					LM_ERR("cannot get value of cfgtest uuid header."
+						   " Using 'unknown' uuid\n");
+				}
 				pkg_str_dup(&_cfgt_node->uuid, &unknown);
 			}
 			return _cfgt_get_uuid_id(_cfgt_node);
@@ -749,7 +812,11 @@ int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar)
 
 	if(_cfgt_node) {
 		LM_DBG("dump last flow\n");
-		if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname) < 0)
+		if(_cfgt_node->route == NULL
+				&& strncmp(_cfgt_node->uuid.s, "unknown", 7) == 0)
+			LM_DBG("route is NULL and message doesn't belong to cfgtest "
+				   "scenario\n");
+		else if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname) < 0)
 			LM_ERR("cannot create flowname\n");
 		else
 			_cfgt_set_dump(msg, _cfgt_node, &flowname);
@@ -763,11 +830,24 @@ int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar)
 int cfgt_msgout(sr_event_param_t *evp)
 {
 	srjson_t *jobj;
+	sip_msg_t msg;
 	str *buf = (str *)evp->data;
+
 	if(buf == NULL)
 		return 0;
 	LM_DBG("msg out:{%.*s}\n", buf->len, buf->s);
 
+	// Check if it is a SIP message
+	memset(&msg, 0, sizeof(sip_msg_t));
+	msg.buf = buf->s;
+	msg.len = buf->len;
+	if(_cfgt_parse_msg(&msg) != 0) {
+		LM_DBG("set 'not_sip' flag\n");
+		not_sip = 1;
+	} else {
+		not_sip = 0;
+	}
+
 	if(_cfgt_node) {
 		jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len);
 		if(jobj == NULL) {
@@ -777,6 +857,13 @@ int cfgt_msgout(sr_event_param_t *evp)
 		srjson_AddItemToArray(&_cfgt_node->jdoc, _cfgt_node->out, jobj);
 		return 0;
 	}
+
+	// Skip OPTION messages internally generated
+	if(buf->len > 7 && strcasestr(buf->s, "OPTIONS")) {
+		LM_DBG("OPTIONS message internally generated, skip it\n");
+		return 0;
+	}
+
 	LM_ERR("node empty\n");
 	return -1;
 }
