diff --git a/src/Makefile.am b/src/Makefile.am index 1ec9566..05e7472 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,7 +39,8 @@ pkglib_LTLIBRARIES = plugin_demo.la \ plugin_prefix.la \ plugin_regex.la \ plugin_codecfilter.la \ - plugin_stripheader.la + plugin_stripheader.la \ + plugin_siptrunk.la DLOPENPLUGINS = -dlopen plugin_demo.la \ -dlopen plugin_shortdial.la \ -dlopen plugin_logcall.la \ @@ -50,7 +51,8 @@ DLOPENPLUGINS = -dlopen plugin_demo.la \ -dlopen plugin_prefix.la \ -dlopen plugin_regex.la \ -dlopen plugin_codecfilter.la \ - -dlopen plugin_stripheader.la + -dlopen plugin_stripheader.la \ + -dlopen plugin_siptrunk.la # plugin_demo_la_SOURCES = plugin_demo.c plugin_demo_la_LDFLAGS = -module -avoid-version -shrext '.so' @@ -84,6 +86,9 @@ plugin_codecfilter_la_LDFLAGS = -module -avoid-version -shrext '.so' # plugin_stripheader_la_SOURCES = plugin_stripheader.c plugin_stripheader_la_LDFLAGS = -module -avoid-version -shrext '.so' +# +plugin_siptrunk_la_SOURCES = plugin_siptrunk.c +plugin_siptrunk_la_LDFLAGS = -module -avoid-version -shrext '.so' # diff --git a/src/plugin_fix_DTAG.c b/src/plugin_fix_DTAG.c index c378f38..712f58c 100644 --- a/src/plugin_fix_DTAG.c +++ b/src/plugin_fix_DTAG.c @@ -35,7 +35,7 @@ #include "plugins.h" #include "log.h" -static char const ident[]="$Id: plugin_DTAG.c 439 2010-01-07 11:29:00Z hb9xar $"; +static char const ident[]="$Id$"; /* Plug-in identification */ static char name[]="plugin_fix_DTAG"; diff --git a/src/plugin_siptrunk.c b/src/plugin_siptrunk.c new file mode 100644 index 0000000..7943cc0 --- /dev/null +++ b/src/plugin_siptrunk.c @@ -0,0 +1,213 @@ +/* + 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_siptrunk + +#include "config.h" + +#include + +#include +#include +#include + +#include + +#include "siproxd.h" +#include "plugins.h" +#include "log.h" + +static char const ident[]="$Id$"; + +/* Plug-in identification */ +static char name[]="plugin_siptrunk"; +static char desc[]="Handles SIP trunks with multiple numbers on same SIP account"; + +/* global configuration storage - required for config file location */ +extern struct siproxd_config configuration; + +/* plugin configuration storage */ +static struct plugin_config { + stringa_t trunk_name; + stringa_t trunk_account; + stringa_t trunk_numbers; +} plugin_cfg; + +/* Instructions for config parser */ +static cfgopts_t plugin_cfg_opts[] = { + { "plugin_siptrunk_name", TYP_STRINGA,&plugin_cfg.trunk_name, {0, NULL} }, + { "plugin_siptrunk_account", TYP_STRINGA,&plugin_cfg.trunk_account, {0, NULL} }, + { "plugin_siptrunk_numbers", TYP_STRINGA,&plugin_cfg.trunk_numbers, {0, NULL} }, + {0, 0, 0} +}; + +/* Prototypes */ +static int sip_fix_topvia(sip_ticket_t *ticket); + +/*&&&+++ +1) register + - nothing to to +2) outgoing calls + - nothing to do. Should be able to figure out direction by + Contact header, via header +3) incoming call + * need matching of incoming DID number to trunk account + - SIP URI + - To: Header + How do I pass on that matched information? + ? rewriting To: header? + ? rewriting SIP URI? + ? new metadata in ticket structure? +Need to provide info for sip_find_direction() -nope, this has been processed +(and failed) before the plugin. I need to provide the correct drection value in +the ticket. +Then with an Route header I may set the next Hop (to the internal UA). I need to +access the registration database to get the associated IP address with the +account... +Unfortunately, the route header processing is only done for OUTGOING requests. + +Probably should try with rewritung the SIP URI to the account name. However this +is bad bcoz if destroys the DID number information in the request URI. + +I may need some next hop override that a plugin can use to force the next hop, +no matter what... + + +&&&---*/ + +/* + * 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_siptrunk 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; + +DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: type=%i", type); + + /* Incoming SIP response? */ + if (type == RESTYP_INCOMING) { + /* a Via header needs to be present in response */ + if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) == NULL) { + WARN("no Via header found in incoming SIP message"); + return STS_SUCCESS; + } + + /* check for Via IP in configured range */ + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: processing VIA host [%s]", + via->host); + get_ip_by_host(via->host, &(from.sin_addr)); + if ((plugin_cfg.networks != NULL) && + (strcmp(plugin_cfg.networks, "") !=0) && + (process_aclist(plugin_cfg.networks, ticket->from) == STS_SUCCESS) && + (process_aclist(plugin_cfg.networks, from) == STS_SUCCESS)) { + + /* VIA & Sender IP are in list, fix Via header */ + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: replacing a bogus via"); + + if (sip_fix_topvia(ticket) == STS_FAILURE) { + ERROR("patching inbound Via failed!"); + } + } else { + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: not match, returning."); + } + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: done"); + } + 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_siptrunk ends here"); + return STS_SUCCESS; +} + +/*--------------------------------------------------------------------*/ +static int sip_fix_topvia(sip_ticket_t *ticket) { + osip_via_t *via; + int sts; + + if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) != NULL) { + /* 1) IP of Via has been checked beforehand. */ + + /* 2) remove broken via header */ + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: removing topmost via"); + sts = osip_list_remove(&(ticket->sipmsg->vias), 0); + osip_via_free (via); + via = NULL; + + /* 3) add my via header */ + DEBUGC(DBCLASS_PLUGIN, "plugin_siptrunk: adding new via"); + 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; +} + diff --git a/src/redirect_cache.c b/src/redirect_cache.c index 31c7d66..537af9e 100644 --- a/src/redirect_cache.c +++ b/src/redirect_cache.c @@ -35,7 +35,7 @@ #include "redirect_cache.h" #include "log.h" -static char const ident[]="$Id: plugin_prefix.c 484 2011-06-17 16:15:41Z hb9xar $"; +static char const ident[]="$Id$"; #define CACHE_TIMEOUT 20 diff --git a/src/sip_utils.c b/src/sip_utils.c index 16014ea..417f31b 100644 --- a/src/sip_utils.c +++ b/src/sip_utils.c @@ -967,7 +967,7 @@ int sip_find_outbound_proxy(sip_ticket_t *ticket, struct in_addr *addr, /* - * SIP_IS_OUTGOING + * SIP_FIND_DIRECTION * * Figures out if this is an outgoing or incoming request/response. * The direction is stored in the ticket->direction property. @@ -992,14 +992,19 @@ int sip_find_direction(sip_ticket_t *ticket, int *urlidx) { ticket->direction = DIRTYP_UNKNOWN; /* Search order is as follows: - * - "from" IP address one of our registered local UAs - * - "To:" SIP header (Request) directed to internal UA + * - "from" IP address is one of our registered local UAs + * => OUTGOING + * - "Req: To:" SIP header (Request) directed to internal UA * or - * "From:" SIP header (Response) coming from internal UA - * - SIP URI matches one of the registered local UAs - * - for Responses: check for bottommost "Via:" header to be + * Resp: "From:" SIP header (Response) coming from internal UA + * => INCOMING + * - Req: SIP URI matches one of the registered local UAs + * => INCOMING + * - Resp: check for bottommost "Via:" header to be * one of our registered local UA IPs - * - "from" IP == 127.0.0.1 || inbound_IP || outbound IP + * => INCOMING + * - "from" IP == (127.0.0.1 | inbound_IP | outbound IP) + * => OUTGOING * * The first successful match is taken. */