From 437c8215f3f68bf180b1f6f233e36f2a375c3dce Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Sun, 30 Aug 2015 06:55:34 +0000 Subject: [PATCH] plugin_fix_DTAG --- doc/siproxd.conf.example | 11 +++ src/Makefile.am | 5 ++ src/plugin_fix_DTAG.c | 170 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 src/plugin_fix_DTAG.c diff --git a/doc/siproxd.conf.example b/doc/siproxd.conf.example index 445864e..f52ccd2 100644 --- a/doc/siproxd.conf.example +++ b/doc/siproxd.conf.example @@ -331,6 +331,7 @@ plugindir=/usr/lib/siproxd/ load_plugin=plugin_logcall.la #load_plugin=plugin_defaulttarget.la #load_plugin=plugin_fix_bogus_via.la +#load_plugin=plugin_fix_DTAG.la #load_plugin=plugin_stun.la #load_plugin=plugin_prefix.la #load_plugin=plugin_regex.la @@ -384,6 +385,16 @@ plugin_defaulttarget_target = sip:internal@dddd:port # SIP message has been received from. plugin_fix_bogus_via_networks = 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 +###################################################################### +# Plugin_fix_DTAG +# +# This plugin attempts to work-around some SIP issues with +# T-ONLINE SIP (as of 2015). T-Online.de sends broken Via headers in +# responses, causing the received SIP response to be discarded by +# any SIP client that properly checks the Via chain. +# DTAG_networks: Network where DTAG messages are received from. +plugin_fix_DTAG_networks = 217.0.23.100/24 + ###################################################################### # Plugin_stun # diff --git a/src/Makefile.am b/src/Makefile.am index d23bb10..1ec9566 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,6 +34,7 @@ pkglib_LTLIBRARIES = plugin_demo.la \ plugin_logcall.la \ plugin_defaulttarget.la \ plugin_fix_bogus_via.la \ + plugin_fix_DTAG.la \ plugin_stun.la \ plugin_prefix.la \ plugin_regex.la \ @@ -44,6 +45,7 @@ DLOPENPLUGINS = -dlopen plugin_demo.la \ -dlopen plugin_logcall.la \ -dlopen plugin_defaulttarget.la \ -dlopen plugin_fix_bogus_via.la \ + -dlopen plugin_fix_DTAG.la \ -dlopen plugin_stun.la \ -dlopen plugin_prefix.la \ -dlopen plugin_regex.la \ @@ -65,6 +67,9 @@ plugin_defaulttarget_la_LDFLAGS = -module -avoid-version -shrext '.so' plugin_fix_bogus_via_la_SOURCES = plugin_fix_bogus_via.c plugin_fix_bogus_via_la_LDFLAGS = -module -avoid-version -shrext '.so' # +plugin_fix_DTAG_la_SOURCES = plugin_fix_DTAG.c +plugin_fix_DTAG_la_LDFLAGS = -module -avoid-version -shrext '.so' +# plugin_stun_la_SOURCES = plugin_stun.c plugin_stun_la_LDFLAGS = -module -avoid-version -shrext '.so' # diff --git a/src/plugin_fix_DTAG.c b/src/plugin_fix_DTAG.c new file mode 100644 index 0000000..a6fdc2e --- /dev/null +++ b/src/plugin_fix_DTAG.c @@ -0,0 +1,170 @@ +/* + Copyright (C) 2015 Thomas Ries + + This file is part of Siproxd. + + Siproxd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Siproxd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warrantry of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Siproxd; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* must be defined before including */ +#define PLUGIN_NAME plugin_fix_DTAG + +#include "config.h" + +#include + +#include +#include +#include + +#include + +#include "siproxd.h" +#include "plugins.h" +#include "log.h" + +static char const ident[]="$Id: plugin_DTAG.c 439 2010-01-07 11:29:00Z hb9xar $"; + +/* Plug-in identification */ +static char name[]="plugin_fix_DTAG"; +static char desc[]="Fixes issues with DTAG (t-online.de) broken SIP headers"; + +/* global configuration storage - required for config file location */ +extern struct siproxd_config configuration; + +/* plugin configuration storage */ +static struct plugin_config { + char *networks; +} plugin_cfg; + +/* Instructions for config parser */ +static cfgopts_t plugin_cfg_opts[] = { + { "plugin_fix_DTAG_networks", TYP_STRING, &plugin_cfg.networks, {0, NULL} }, + {0, 0, 0} +}; + +/* Prototypes */ +static int sip_patch_topvia(sip_ticket_t *ticket); + + +/* + * Initialization. + * Called once suring siproxd startup. + */ +int PLUGIN_INIT(plugin_def_t *plugin_def) { + /* API version number of siproxd that this plugin is built against. + * This constant will change whenever changes to the API are made + * that require adaptions in the plugin. */ + plugin_def->api_version=SIPROXD_API_VERSION; + + /* Name and descriptive text of the plugin */ + plugin_def->name=name; + plugin_def->desc=desc; + + /* Execution mask - during what stages of SIP processing shall + * the plugin be called. */ + plugin_def->exe_mask=PLUGIN_PRE_PROXY; + + /* read the config file */ + if (read_config(configuration.configfile, + configuration.config_search, + plugin_cfg_opts, name) == STS_FAILURE) { + ERROR("Plugin '%s': could not load config file", name); + return STS_FAILURE; + } + + INFO("plugin_fix_DTAG is initialized"); + return STS_SUCCESS; +} + +/* + * Processing. + * + */ +int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ + /* stage contains the PLUGIN_* value - the stage of SIP processing. */ + int type; + osip_via_t *via; + struct sockaddr_in from; + + type = ticket->direction; + + /* Incoming SIP response? */ +DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: type=%i", type); + if (type == RESTYP_INCOMING) { + + if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) == NULL) { + WARN("no Via header found in incoming SIP message"); + return STS_SUCCESS; + } + + get_ip_by_host(via->host, &(from.sin_addr)); + + /* check for Via IP in configured range */ + if ((plugin_cfg.networks != NULL) && + (strcmp(plugin_cfg.networks, "") !=0) && + (process_aclist(plugin_cfg.networks, from) == STS_SUCCESS)) { + /* is in list, patch Via header */ + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: replacing a bogus via"); + if (sip_patch_topvia(ticket) == STS_FAILURE) { + ERROR("patching inbound Via failed!"); + } + } + } + return STS_SUCCESS; +} + +/* + * De-Initialization. + * Called during shutdown of siproxd. Gives the plugin the chance + * to clean up its mess (e.g. dynamic memory allocation, database + * connections, whatever the plugin messes around with) + */ +int PLUGIN_END(plugin_def_t *plugin_def){ + INFO("plugin_fix_DTAG ends here"); + return STS_SUCCESS; +} + +/*--------------------------------------------------------------------*/ +static int sip_patch_topvia(sip_ticket_t *ticket) { + osip_via_t *via; + int sts; + + if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) != NULL) { + // 1) check that via header matches criteria (is not local) + if (! is_via_local(via)) { + // 2) remove broken via header + sts = osip_list_remove(&(ticket->sipmsg->vias), 0); + osip_via_free (via); + via = NULL; + + // 3) add my via header + if (ticket->direction == RESTYP_INCOMING) { + sts = sip_add_myvia(ticket, IF_OUTBOUND); + if (sts == STS_FAILURE) { + ERROR("adding my outbound via failed!"); + } + } else { + sts = sip_add_myvia(ticket, IF_INBOUND); + if (sts == STS_FAILURE) { + ERROR("adding my inbound via failed!"); + } + } + } + } + + return STS_SUCCESS; +} +