From 53dbe5d84a9c3624804a2b9259433f4d525425f8 Mon Sep 17 00:00:00 2001 From: davidcsi Date: Fri, 11 Nov 2016 01:55:38 +0000 Subject: [PATCH] FS-9490: [mod_sofia] add filter to SIP messages that match a regexp. --- src/mod/endpoints/mod_sofia/mod_sofia.c | 29 ++++++++++++- src/mod/endpoints/mod_sofia/mod_sofia.h | 9 ++++ src/mod/endpoints/mod_sofia/sofia.c | 57 ++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 5586631152..e66f99240c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4179,6 +4179,10 @@ SWITCH_STANDARD_API(sofia_function) switch_status_t status = SWITCH_STATUS_SUCCESS; sofia_command_t func = NULL; int lead = 1; + const char *errorptr; + int erroffset; + const unsigned char *tables = 0; + uint32_t flags = 0; static const char usage_string[] = "USAGE:\n" "--------------------------------------------------------------------------------\n" "sofia global siptrace \n" @@ -4221,6 +4225,29 @@ SWITCH_STANDARD_API(sofia_function) func = cmd_status; } else if (!strcasecmp(argv[0], "xmlstatus")) { func = cmd_xml_status; + } else if (!strcasecmp(argv[0], "filter")) { + if (argc > 1) { + if (!strcasecmp(argv[1],"off")) { + mod_sofia_globals.filtering = SWITCH_FALSE; + switch_regex_free(mod_sofia_globals.filter_re); + } else { + mod_sofia_globals.filtering = SWITCH_TRUE; + strncpy( mod_sofia_globals.filter_expression, argv[1], sizeof(mod_sofia_globals.filter_expression) ); + mod_sofia_globals.filter_re = switch_regex_compile( argv[1], flags, &errorptr, &erroffset, tables ); + if (errorptr) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s][%s]\n", erroffset, errorptr, argv[1]); + stream->write_function(stream, "Couldn't compile that regex: %s\n", argv[1]); + switch_regex_free(mod_sofia_globals.filter_re); + goto done; + } + + } + stream->write_function(stream, "+OK %s filtering sofia log for %s\n", mod_sofia_globals.filtering ? "enabled" : "disabled", mod_sofia_globals.filter_expression ); + } else { + stream->write_function(stream, "%s%s", "sofia filter is ", mod_sofia_globals.filtering ? "enabled. " : "disabled. ", mod_sofia_globals.filter_expression); + stream->write_function(stream, "%s", " (sofia filter ) - Enable, disable filtering, set 'filter-regex' to use as filter. Set 'filter-expression' to 'off' to stop filtering\n"); + } + goto done; } else if (!strcasecmp(argv[0], "tracelevel")) { if (argv[1]) { mod_sofia_globals.tracelevel = switch_log_str2level(argv[1]); @@ -6109,7 +6136,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_console_set_complete("add sofia ::[help:status"); switch_console_set_complete("add sofia status profile ::sofia::list_profiles reg"); switch_console_set_complete("add sofia status gateway ::sofia::list_gateways"); - + switch_console_set_complete("add sofia filter"); switch_console_set_complete("add sofia loglevel ::[all:default:tport:iptsec:nea:nta:nth_client:nth_server:nua:soa:sresolv:stun ::[0:1:2:3:4:5:6:7:8:9"); switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug"); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 5ed675dd20..5f3b8f53a9 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -155,6 +155,12 @@ typedef enum { SOFIA_CONFIG_RESPAWN } sofia_config_t; +typedef enum { + FILTER_UNKOWN = 0, + FILTER_BEGIN = 1, + FILTER_END = 2 +} filter_packet_state_t; + typedef struct sofia_dispatch_event_s { nua_saved_event_t event[1]; nua_handle_t *nh; @@ -396,6 +402,9 @@ struct mod_sofia_globals { uint32_t max_reg_threads; time_t presence_epoch; int presence_year; + char filter_expression[100]; + switch_regex_t *filter_re; + switch_bool_t filtering; }; extern struct mod_sofia_globals mod_sofia_globals; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 1e28be82a5..2757460fbf 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -35,6 +35,7 @@ * Emmanuel Schmidbauer * William King * David Knell + * David Villasmil * * sofia.c -- SOFIA SIP Endpoint (sofia code) * @@ -3450,13 +3451,65 @@ void launch_sofia_profile_thread(sofia_profile_t *profile) switch_thread_create(&profile->thread, thd_attr, sofia_profile_thread_run, profile, profile->pool); } +static int is_packet_begin_or_end(char *mybuf) +{ + if (!strncasecmp( mybuf, "recv ", 3) || !strncasecmp( mybuf, "send ", 3) ) { + // Buffer starts with "recv" or "send", this means it's a new packet + if (strstr(mybuf, "------------------------------------------------------------------------") != NULL) { + // Buffer also contains the dahsed line, this is good, the complete "header" so to speak + return 1; + } + } else if (!strcmp(mybuf, " ------------------------------------------------------------------------\n")) { + // Buffer only has the dashed line, this means it is the end of a packet + return 2; + } + return 0; +} + static void logger(void *logarg, char const *fmt, va_list ap) { - if (!fmt) return; + filter_packet_state_t filter_packet_state; + char buf[1024]; + static switch_stream_handle_t packetstream = { 0 }; + static switch_bool_t print_this_packet = SWITCH_FALSE; + static int ovector[30]; - switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap); + va_list temp_ap; + va_copy(temp_ap,ap); + + if (!fmt) return; + + vsnprintf( buf, 1024, fmt, temp_ap); + buf[sizeof(buf)-1] = '\0'; + + if (mod_sofia_globals.filtering) { + if (switch_regex_perform( buf, mod_sofia_globals.filter_expression, &mod_sofia_globals.filter_re, ovector, sizeof(ovector) / sizeof(ovector[0]) ) > 0) { + print_this_packet = SWITCH_TRUE; + } + + filter_packet_state = is_packet_begin_or_end(buf); + + if ( filter_packet_state == FILTER_BEGIN ) { + print_this_packet = SWITCH_FALSE; + SWITCH_STANDARD_STREAM(packetstream); + packetstream.write_function(&packetstream, "%s", buf); + + } else if ( filter_packet_state == FILTER_END ) { + if ( print_this_packet == SWITCH_TRUE ) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "\nFILTER REGEX (%s) FOUND IN: \n <<<%s>>>\n", mod_sofia_globals.filter_expression, (char *)packetstream.data ); + } + switch_safe_free(packetstream.data); + + } else { + packetstream.write_function(&packetstream, "%s", buf); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "%s", buf ); + } + buf[0] = '\0'; } + static su_log_t *sofia_get_logger(const char *name) { if (!strcasecmp(name, "tport")) {