2007-04-02 19:54:25 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2011-01-05 10:08:55 -06:00
* Copyright ( C ) 2005 - 2011 , Anthony Minessale II < anthm @ freeswitch . org >
2007-04-02 19:54:25 +00:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-04-02 19:54:25 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2008-07-30 18:50:47 +00:00
* Ken Rice , < krice at cometsig . com > ( work sponsored by Comet Signaling LLC , CopperCom , Inc and Asteria Solutions Group , Inc )
2007-04-02 19:54:25 +00:00
* Paul D . Tinsley < pdt at jackhammer . org >
* Bret McDanel < trixter AT 0xdecafbad . com >
2007-04-07 03:04:46 +00:00
* Marcel Barbulescu < marcelbarbulescu @ gmail . com >
2008-01-12 19:15:05 +00:00
* David Knell < >
2009-03-04 19:45:10 +00:00
* Eliot Gable < egable AT . AT broadvox . com >
2011-08-17 19:34:22 -05:00
* Leon de Rooij < leon @ scarlet - internet . nl >
2007-04-02 19:54:25 +00:00
*
*
2011-08-17 19:34:22 -05:00
* sofia_reg . c - - SOFIA SIP Endpoint ( registration code )
2007-04-02 19:54:25 +00:00
*
*/
2007-03-31 19:01:33 +00:00
# include "mod_sofia.h"
2009-03-22 20:04:56 +00:00
static void sofia_reg_new_handle ( sofia_gateway_t * gateway_ptr , int attach )
2008-01-29 21:56:36 +00:00
{
2009-03-22 05:15:17 +00:00
int ss_state = nua_callstate_authenticating ;
2008-05-27 04:54:52 +00:00
if ( gateway_ptr - > nh ) {
nua_handle_bind ( gateway_ptr - > nh , NULL ) ;
nua_handle_destroy ( gateway_ptr - > nh ) ;
gateway_ptr - > nh = NULL ;
2009-03-22 05:15:17 +00:00
sofia_private_free ( gateway_ptr - > sofia_private ) ;
2008-05-27 04:54:52 +00:00
}
2007-03-31 19:01:33 +00:00
2009-03-22 05:15:17 +00:00
gateway_ptr - > nh = nua_handle ( gateway_ptr - > profile - > nua , NULL ,
SIPTAG_CALL_ID_STR ( gateway_ptr - > uuid_str ) ,
SIPTAG_TO_STR ( gateway_ptr - > register_to ) ,
NUTAG_CALLSTATE_REF ( ss_state ) , SIPTAG_FROM_STR ( gateway_ptr - > register_from ) , TAG_END ( ) ) ;
2009-03-22 20:04:56 +00:00
if ( attach ) {
if ( ! gateway_ptr - > sofia_private ) {
2011-07-16 11:30:25 -05:00
gateway_ptr - > sofia_private = malloc ( sizeof ( * gateway_ptr - > sofia_private ) ) ;
2011-07-16 01:02:22 -05:00
switch_assert ( gateway_ptr - > sofia_private ) ;
2009-03-22 20:04:56 +00:00
}
memset ( gateway_ptr - > sofia_private , 0 , sizeof ( * gateway_ptr - > sofia_private ) ) ;
2010-02-06 03:38:24 +00:00
2009-03-22 20:04:56 +00:00
gateway_ptr - > sofia_private - > gateway = gateway_ptr ;
nua_handle_bind ( gateway_ptr - > nh , gateway_ptr - > sofia_private ) ;
}
2009-03-22 05:15:17 +00:00
}
2011-11-10 10:48:06 -06:00
static void sofia_reg_new_sub_handle ( sofia_gateway_t * gateway_ptr , int attach )
{
char * user_via = NULL ;
char * register_host = sofia_glue_get_register_host ( gateway_ptr - > register_proxy ) ;
int ss_state = nua_callstate_authenticating ;
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
if ( register_host & & sofia_glue_check_nat ( gateway_ptr - > profile , register_host ) ) {
user_via = sofia_glue_create_external_via ( NULL , gateway_ptr - > profile , gateway_ptr - > register_transport ) ;
}
if ( gateway_ptr - > sub_nh ) {
nua_handle_bind ( gateway_ptr - > sub_nh , NULL ) ;
nua_handle_destroy ( gateway_ptr - > sub_nh ) ;
gateway_ptr - > sub_nh = NULL ;
sofia_private_free ( gateway_ptr - > sofia_private ) ;
}
gateway_ptr - > sub_nh = nua_handle ( gateway_ptr - > profile - > nua , NULL ,
NUTAG_URL ( gateway_ptr - > register_proxy ) ,
TAG_IF ( user_via , SIPTAG_VIA_STR ( user_via ) ) ,
SIPTAG_TO_STR ( gateway_ptr - > register_to ) ,
NUTAG_CALLSTATE_REF ( ss_state ) , SIPTAG_FROM_STR ( gateway_ptr - > register_from ) , TAG_END ( ) ) ;
if ( attach ) {
if ( ! gateway_ptr - > sofia_private ) {
gateway_ptr - > sofia_private = malloc ( sizeof ( * gateway_ptr - > sofia_private ) ) ;
switch_assert ( gateway_ptr - > sofia_private ) ;
}
memset ( gateway_ptr - > sofia_private , 0 , sizeof ( * gateway_ptr - > sofia_private ) ) ;
gateway_ptr - > sofia_private - > gateway = gateway_ptr ;
nua_handle_bind ( gateway_ptr - > sub_nh , gateway_ptr - > sofia_private ) ;
}
switch_safe_free ( register_host ) ;
switch_safe_free ( user_via ) ;
}
static void sofia_reg_kill_sub ( sofia_gateway_t * gateway_ptr )
{
if ( gateway_ptr - > sub_nh ) {
nua_handle_bind ( gateway_ptr - > sub_nh , NULL ) ;
}
2011-11-10 09:46:56 -06:00
if ( gateway_ptr - > sub_state ! = SUB_STATE_SUBED & & gateway_ptr - > sub_state ! = SUB_STATE_UNSUBSCRIBE ) {
2011-11-10 10:48:06 -06:00
if ( gateway_ptr - > sub_nh ) {
nua_handle_destroy ( gateway_ptr - > sub_nh ) ;
gateway_ptr - > sub_nh = NULL ;
}
return ;
}
if ( gateway_ptr - > sub_nh ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " UN-Subbing %s \n " , gateway_ptr - > name ) ;
nua_unsubscribe ( gateway_ptr - > sub_nh , NUTAG_URL ( gateway_ptr - > register_url ) , TAG_END ( ) ) ;
}
}
2009-03-22 05:15:17 +00:00
static void sofia_reg_kill_reg ( sofia_gateway_t * gateway_ptr )
{
2011-10-04 17:46:49 -05:00
if ( gateway_ptr - > nh ) {
nua_handle_bind ( gateway_ptr - > nh , NULL ) ;
}
2011-10-05 13:55:16 -05:00
if ( gateway_ptr - > state ! = REG_STATE_REGED & & gateway_ptr - > state ! = REG_STATE_UNREGISTER ) {
2009-04-03 13:14:26 +00:00
if ( gateway_ptr - > nh ) {
nua_handle_destroy ( gateway_ptr - > nh ) ;
gateway_ptr - > nh = NULL ;
}
return ;
}
2010-02-06 03:38:24 +00:00
2009-03-22 05:15:17 +00:00
if ( gateway_ptr - > nh ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " UN-Registering %s \n " , gateway_ptr - > name ) ;
2010-02-06 03:38:24 +00:00
nua_unregister ( gateway_ptr - > nh , NUTAG_URL ( gateway_ptr - > register_url ) , NUTAG_REGISTRAR ( gateway_ptr - > register_proxy ) , TAG_END ( ) ) ;
2009-03-22 05:15:17 +00:00
}
2008-01-29 21:56:36 +00:00
}
2007-04-20 18:06:06 +00:00
2010-05-10 12:33:31 -04:00
void sofia_reg_fire_custom_gateway_state_event ( sofia_gateway_t * gateway , int status , const char * phrase )
2010-02-06 03:38:24 +00:00
{
2008-10-10 15:36:02 +00:00
switch_event_t * s_event ;
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_GATEWAY_STATE ) = = SWITCH_STATUS_SUCCESS ) {
2009-04-21 01:02:45 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " Gateway " , gateway - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " State " , sofia_state_string ( gateway - > state ) ) ;
2010-05-10 12:33:31 -04:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " Ping-Status " , sofia_gateway_status_name ( gateway - > status ) ) ;
2010-01-15 15:18:07 +00:00
if ( ! zstr ( phrase ) ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " Phrase " , phrase ) ;
}
if ( status ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " Status " , " %d " , status ) ;
}
2008-10-10 15:36:02 +00:00
switch_event_fire ( & s_event ) ;
}
}
2007-04-04 03:08:17 +00:00
void sofia_reg_unregister ( sofia_profile_t * profile )
2007-03-31 19:01:33 +00:00
{
2007-04-29 01:16:49 +00:00
sofia_gateway_t * gateway_ptr ;
2011-11-10 10:48:06 -06:00
sofia_gateway_subscription_t * gw_sub_ptr ;
2010-03-25 00:28:56 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
2009-03-22 20:04:56 +00:00
2011-10-04 17:46:49 -05:00
if ( gateway_ptr - > nh ) {
nua_handle_bind ( gateway_ptr - > nh , NULL ) ;
}
2007-03-31 19:01:33 +00:00
if ( gateway_ptr - > sofia_private ) {
2009-03-22 05:15:17 +00:00
sofia_private_free ( gateway_ptr - > sofia_private ) ;
2007-03-31 19:01:33 +00:00
}
2009-03-22 20:04:56 +00:00
2009-04-03 13:14:26 +00:00
if ( gateway_ptr - > state = = REG_STATE_REGED ) {
sofia_reg_kill_reg ( gateway_ptr ) ;
}
2009-03-22 20:04:56 +00:00
2011-11-10 10:48:06 -06:00
for ( gw_sub_ptr = gateway_ptr - > subscriptions ; gw_sub_ptr ; gw_sub_ptr = gw_sub_ptr - > next ) {
if ( gw_sub_ptr - > state = = SUB_STATE_SUBED ) {
sofia_reg_kill_sub ( gateway_ptr ) ;
}
}
2007-03-31 19:01:33 +00:00
}
2010-03-25 00:28:56 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
}
2008-11-24 15:52:55 +00:00
void sofia_sub_check_gateway ( sofia_profile_t * profile , time_t now )
{
/* NOTE: A lot of the mechanism in place here for refreshing subscriptions is
* pretty much redundant , as the sofia stack takes it upon itself to
* refresh subscriptions on its own , based on the value of the Expires
* header ( which we control in the outgoing subscription request )
*/
sofia_gateway_t * gateway_ptr ;
2010-02-06 03:38:24 +00:00
2011-06-16 14:32:08 -05:00
switch_mutex_lock ( profile - > gw_mutex ) ;
2008-11-24 15:52:55 +00:00
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
sofia_gateway_subscription_t * gw_sub_ptr ;
for ( gw_sub_ptr = gateway_ptr - > subscriptions ; gw_sub_ptr ; gw_sub_ptr = gw_sub_ptr - > next ) {
sub_state_t ostate = gw_sub_ptr - > state ;
2010-02-06 03:38:24 +00:00
2008-11-24 15:52:55 +00:00
if ( ! now ) {
gw_sub_ptr - > state = ostate = SUB_STATE_UNSUBED ;
gw_sub_ptr - > expires_str = " 0 " ;
}
2009-06-03 22:00:49 +00:00
2011-11-10 09:46:56 -06:00
gateway_ptr - > sub_state = gw_sub_ptr - > state ;
2008-11-24 15:52:55 +00:00
switch ( ostate ) {
case SUB_STATE_NOSUB :
break ;
case SUB_STATE_SUBSCRIBE :
gw_sub_ptr - > expires = now + gw_sub_ptr - > freq ;
gw_sub_ptr - > state = SUB_STATE_SUBED ;
break ;
case SUB_STATE_UNSUBSCRIBE :
gw_sub_ptr - > state = SUB_STATE_NOSUB ;
2011-11-10 10:48:06 -06:00
sofia_reg_kill_sub ( gateway_ptr ) ;
2008-11-24 15:52:55 +00:00
break ;
case SUB_STATE_UNSUBED :
2010-02-06 03:38:24 +00:00
2011-11-10 10:48:06 -06:00
sofia_reg_new_sub_handle ( gateway_ptr , 1 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " subscribing to [%s] on gateway [%s] \n " , gw_sub_ptr - > event , gateway_ptr - > name ) ;
2008-11-24 15:52:55 +00:00
if ( now ) {
2010-11-22 14:59:25 -06:00
nua_subscribe ( gateway_ptr - > sub_nh ,
NUTAG_URL ( gateway_ptr - > register_url ) ,
SIPTAG_EVENT_STR ( gw_sub_ptr - > event ) ,
SIPTAG_ACCEPT_STR ( gw_sub_ptr - > content_type ) ,
SIPTAG_TO_STR ( gateway_ptr - > register_from ) ,
SIPTAG_FROM_STR ( gateway_ptr - > register_from ) ,
SIPTAG_CONTACT_STR ( gateway_ptr - > register_contact ) ,
SIPTAG_EXPIRES_STR ( gw_sub_ptr - > expires_str ) , /* sofia stack bases its auto-refresh stuff on this */
2009-06-03 22:00:49 +00:00
TAG_NULL ( ) ) ;
2008-11-24 15:52:55 +00:00
gw_sub_ptr - > retry = now + gw_sub_ptr - > retry_seconds ;
} else {
2009-03-22 05:15:17 +00:00
nua_unsubscribe ( gateway_ptr - > sub_nh ,
2009-06-03 22:00:49 +00:00
NUTAG_URL ( gateway_ptr - > register_url ) ,
SIPTAG_EVENT_STR ( gw_sub_ptr - > event ) ,
SIPTAG_ACCEPT_STR ( gw_sub_ptr - > content_type ) ,
SIPTAG_FROM_STR ( gateway_ptr - > register_from ) ,
SIPTAG_TO_STR ( gateway_ptr - > register_from ) ,
2010-02-06 03:38:24 +00:00
SIPTAG_CONTACT_STR ( gateway_ptr - > register_contact ) , SIPTAG_EXPIRES_STR ( gw_sub_ptr - > expires_str ) , TAG_NULL ( ) ) ;
2008-11-24 15:52:55 +00:00
}
gw_sub_ptr - > state = SUB_STATE_TRYING ;
break ;
2010-02-06 03:38:24 +00:00
2008-11-24 15:52:55 +00:00
case SUB_STATE_FAILED :
case SUB_STATE_TRYING :
if ( gw_sub_ptr - > retry & & now > = gw_sub_ptr - > retry ) {
gw_sub_ptr - > state = SUB_STATE_UNSUBED ;
gw_sub_ptr - > retry = 0 ;
}
break ;
default :
if ( now > = gw_sub_ptr - > expires ) {
gw_sub_ptr - > state = SUB_STATE_UNSUBED ;
}
break ;
}
2011-11-10 10:48:06 -06:00
2008-11-24 15:52:55 +00:00
}
}
2011-06-16 14:32:08 -05:00
switch_mutex_unlock ( profile - > gw_mutex ) ;
2008-11-24 15:52:55 +00:00
}
2007-04-04 03:08:17 +00:00
void sofia_reg_check_gateway ( sofia_profile_t * profile , time_t now )
2007-03-31 19:01:33 +00:00
{
2011-09-27 08:44:29 -05:00
sofia_gateway_t * check , * gateway_ptr , * last = NULL ;
2010-01-23 19:08:44 +00:00
switch_event_t * event ;
2012-01-10 08:51:14 -06:00
int delta = 0 ;
2008-07-08 22:05:34 +00:00
2011-06-16 14:32:08 -05:00
switch_mutex_lock ( profile - > gw_mutex ) ;
2008-07-08 22:05:34 +00:00
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
2011-09-27 08:44:29 -05:00
if ( gateway_ptr - > deleted ) {
if ( ( check = switch_core_hash_find ( mod_sofia_globals . gateway_hash , gateway_ptr - > name ) ) & & check = = gateway_ptr ) {
char * pkey = switch_mprintf ( " %s::%s " , profile - > name , gateway_ptr - > name ) ;
switch_assert ( pkey ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Removing gateway %s from hash. \n " , pkey ) ;
switch_core_hash_delete ( mod_sofia_globals . gateway_hash , pkey ) ;
switch_core_hash_delete ( mod_sofia_globals . gateway_hash , gateway_ptr - > name ) ;
free ( pkey ) ;
2008-07-08 22:05:34 +00:00
}
2010-02-18 22:39:08 +00:00
2011-09-27 08:44:29 -05:00
if ( gateway_ptr - > state = = REG_STATE_NOREG ) {
2010-02-18 22:39:08 +00:00
2011-09-27 08:44:29 -05:00
if ( last ) {
last - > next = gateway_ptr - > next ;
} else {
profile - > gateways = gateway_ptr - > next ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Deleted gateway %s \n " , gateway_ptr - > name ) ;
if ( switch_event_create_subclass ( & event , SWITCH_EVENT_CUSTOM , MY_EVENT_GATEWAY_DEL ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " profile-name " , gateway_ptr - > profile - > name ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Gateway " , gateway_ptr - > name ) ;
switch_event_fire ( & event ) ;
}
if ( gateway_ptr - > ob_vars ) {
switch_event_destroy ( & gateway_ptr - > ob_vars ) ;
}
if ( gateway_ptr - > ib_vars ) {
switch_event_destroy ( & gateway_ptr - > ib_vars ) ;
}
2008-10-21 22:40:20 +00:00
}
2008-07-09 17:54:03 +00:00
} else {
last = gateway_ptr ;
2008-07-08 22:05:34 +00:00
}
}
2007-03-31 19:01:33 +00:00
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
reg_state_t ostate = gateway_ptr - > state ;
2009-06-03 22:00:49 +00:00
char * user_via = NULL ;
2010-11-22 14:59:25 -06:00
char * register_host = NULL ;
2007-03-31 19:01:33 +00:00
2007-04-29 01:16:49 +00:00
if ( ! now ) {
gateway_ptr - > state = ostate = REG_STATE_UNREGED ;
gateway_ptr - > expires_str = " 0 " ;
}
2009-07-14 19:32:42 +00:00
if ( gateway_ptr - > ping & & ! gateway_ptr - > pinging & & ( now > = gateway_ptr - > ping & & ( ostate = = REG_STATE_NOREG | | ostate = = REG_STATE_REGED ) ) & &
! gateway_ptr - > deleted ) {
2009-07-14 18:25:38 +00:00
nua_handle_t * nh = nua_handle ( profile - > nua , NULL , NUTAG_URL ( gateway_ptr - > register_url ) , TAG_END ( ) ) ;
2011-07-16 01:02:22 -05:00
sofia_private_t * pvt ;
2008-04-30 22:09:54 +00:00
2010-11-22 14:59:25 -06:00
register_host = sofia_glue_get_register_host ( gateway_ptr - > register_proxy ) ;
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
2010-11-23 09:54:50 -06:00
if ( register_host & & sofia_glue_check_nat ( gateway_ptr - > profile , register_host ) ) {
2009-07-14 23:39:57 +00:00
user_via = sofia_glue_create_external_via ( NULL , gateway_ptr - > profile , gateway_ptr - > register_transport ) ;
}
2010-11-22 14:59:25 -06:00
switch_safe_free ( register_host ) ;
2011-07-16 01:02:22 -05:00
pvt = malloc ( sizeof ( * pvt ) ) ;
switch_assert ( pvt ) ;
memset ( pvt , 0 , sizeof ( * pvt ) ) ;
pvt - > destroy_nh = 1 ;
pvt - > destroy_me = 1 ;
switch_copy_string ( pvt - > gateway_name , gateway_ptr - > name , sizeof ( pvt - > gateway_name ) ) ;
nua_handle_bind ( nh , pvt ) ;
2008-04-30 22:09:54 +00:00
gateway_ptr - > pinging = 1 ;
2010-02-06 03:38:24 +00:00
nua_options ( nh ,
2009-07-14 18:25:38 +00:00
TAG_IF ( gateway_ptr - > register_sticky_proxy , NUTAG_PROXY ( gateway_ptr - > register_sticky_proxy ) ) ,
2009-07-14 23:39:57 +00:00
TAG_IF ( user_via , SIPTAG_VIA_STR ( user_via ) ) ,
2009-07-14 18:25:38 +00:00
SIPTAG_TO_STR ( gateway_ptr - > register_from ) ,
2010-02-06 03:38:24 +00:00
SIPTAG_CONTACT_STR ( gateway_ptr - > register_contact ) , SIPTAG_FROM_STR ( gateway_ptr - > register_from ) , TAG_END ( ) ) ;
2009-07-14 23:39:57 +00:00
switch_safe_free ( user_via ) ;
user_via = NULL ;
2008-04-30 22:09:54 +00:00
}
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
switch ( ostate ) {
2007-04-07 03:04:46 +00:00
case REG_STATE_NOREG :
2008-11-24 16:56:21 +00:00
if ( ! gateway_ptr - > ping & & ! gateway_ptr - > pinging ) {
gateway_ptr - > status = SOFIA_GATEWAY_UP ;
}
2007-04-07 03:04:46 +00:00
break ;
2007-03-31 19:01:33 +00:00
case REG_STATE_REGISTER :
2008-10-12 03:56:11 +00:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Registered %s \n " , gateway_ptr - > name ) ;
}
2008-11-24 16:56:21 +00:00
gateway_ptr - > failures = 0 ;
2012-01-10 08:51:14 -06:00
if ( gateway_ptr - > freq > 30 ) {
delta = ( gateway_ptr - > freq - 15 ) ;
2008-10-07 22:15:51 +00:00
} else {
2012-01-10 08:51:14 -06:00
delta = ( gateway_ptr - > freq / 2 ) ;
2008-10-07 22:15:51 +00:00
}
2012-01-10 08:51:14 -06:00
if ( delta < 1 ) {
delta = 1 ;
}
gateway_ptr - > expires = now + delta ;
2007-03-31 19:01:33 +00:00
gateway_ptr - > state = REG_STATE_REGED ;
2008-04-30 22:09:54 +00:00
gateway_ptr - > status = SOFIA_GATEWAY_UP ;
2007-03-31 19:01:33 +00:00
break ;
2007-09-18 17:31:36 +00:00
case REG_STATE_UNREGISTER :
2009-03-22 05:15:17 +00:00
sofia_reg_kill_reg ( gateway_ptr ) ;
2007-09-18 17:31:36 +00:00
gateway_ptr - > state = REG_STATE_NOREG ;
2012-01-10 08:51:14 -06:00
gateway_ptr - > status = SOFIA_GATEWAY_DOWN ;
2007-09-18 17:31:36 +00:00
break ;
2007-03-31 19:01:33 +00:00
case REG_STATE_UNREGED :
2009-12-02 20:47:46 +00:00
gateway_ptr - > retry = 0 ;
2010-02-06 03:38:24 +00:00
2010-02-16 00:07:50 +00:00
if ( ! gateway_ptr - > nh ) {
2010-02-06 03:38:24 +00:00
sofia_reg_new_handle ( gateway_ptr , now ? 1 : 0 ) ;
2010-02-16 00:07:50 +00:00
}
2009-06-03 22:00:49 +00:00
2010-11-22 14:59:25 -06:00
register_host = sofia_glue_get_register_host ( gateway_ptr - > register_proxy ) ;
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
2010-11-23 09:54:50 -06:00
if ( register_host & & sofia_glue_check_nat ( gateway_ptr - > profile , register_host ) ) {
2009-06-04 05:43:34 +00:00
user_via = sofia_glue_create_external_via ( NULL , gateway_ptr - > profile , gateway_ptr - > register_transport ) ;
}
2009-06-03 22:00:49 +00:00
2010-11-22 14:59:25 -06:00
switch_safe_free ( register_host ) ;
2009-03-22 05:15:17 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Registering %s \n " , gateway_ptr - > name ) ;
2010-02-06 03:38:24 +00:00
2009-03-22 05:15:17 +00:00
if ( now ) {
nua_register ( gateway_ptr - > nh ,
NUTAG_URL ( gateway_ptr - > register_url ) ,
TAG_IF ( gateway_ptr - > register_sticky_proxy , NUTAG_PROXY ( gateway_ptr - > register_sticky_proxy ) ) ,
2009-06-03 22:00:49 +00:00
TAG_IF ( user_via , SIPTAG_VIA_STR ( user_via ) ) ,
2009-11-03 23:21:02 +00:00
SIPTAG_TO_STR ( gateway_ptr - > distinct_to ? gateway_ptr - > register_to : gateway_ptr - > register_from ) ,
2009-03-22 05:15:17 +00:00
SIPTAG_CONTACT_STR ( gateway_ptr - > register_contact ) ,
2010-02-06 03:38:24 +00:00
SIPTAG_FROM_STR ( gateway_ptr - > register_from ) ,
2009-03-22 05:15:17 +00:00
SIPTAG_EXPIRES_STR ( gateway_ptr - > expires_str ) ,
NUTAG_REGISTRAR ( gateway_ptr - > register_proxy ) ,
NUTAG_OUTBOUND ( " no-options-keepalive " ) , NUTAG_OUTBOUND ( " no-validate " ) , NUTAG_KEEPALIVE ( 0 ) , TAG_NULL ( ) ) ;
2008-11-24 16:56:21 +00:00
gateway_ptr - > retry = now + gateway_ptr - > retry_seconds ;
2007-03-31 19:01:33 +00:00
} else {
2012-01-10 08:51:14 -06:00
gateway_ptr - > status = SOFIA_GATEWAY_DOWN ;
2009-03-22 05:15:17 +00:00
nua_unregister ( gateway_ptr - > nh ,
NUTAG_URL ( gateway_ptr - > register_url ) ,
2009-06-03 22:00:49 +00:00
TAG_IF ( user_via , SIPTAG_VIA_STR ( user_via ) ) ,
2009-03-22 05:15:17 +00:00
SIPTAG_FROM_STR ( gateway_ptr - > register_from ) ,
2009-11-03 23:21:02 +00:00
SIPTAG_TO_STR ( gateway_ptr - > distinct_to ? gateway_ptr - > register_to : gateway_ptr - > register_from ) ,
2009-03-22 05:15:17 +00:00
SIPTAG_EXPIRES_STR ( gateway_ptr - > expires_str ) ,
NUTAG_REGISTRAR ( gateway_ptr - > register_proxy ) ,
NUTAG_OUTBOUND ( " no-options-keepalive " ) , NUTAG_OUTBOUND ( " no-validate " ) , NUTAG_KEEPALIVE ( 0 ) , TAG_NULL ( ) ) ;
2007-03-31 19:01:33 +00:00
}
2010-11-03 10:58:32 -05:00
gateway_ptr - > reg_timeout = now + gateway_ptr - > reg_timeout_seconds ;
2010-02-06 03:38:24 +00:00
gateway_ptr - > state = REG_STATE_TRYING ;
2009-07-14 23:39:57 +00:00
switch_safe_free ( user_via ) ;
user_via = NULL ;
2007-03-31 19:01:33 +00:00
break ;
2010-11-02 17:58:24 -05:00
case REG_STATE_TIMEOUT :
{
nua_handle_t * nh = gateway_ptr - > nh ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Timeout Registering %s \n " , gateway_ptr - > name ) ;
gateway_ptr - > nh = NULL ;
nua_handle_destroy ( nh ) ;
gateway_ptr - > state = REG_STATE_FAILED ;
gateway_ptr - > failures + + ;
gateway_ptr - > failure_status = 908 ;
}
break ;
2007-05-10 16:15:07 +00:00
case REG_STATE_FAILED :
2009-12-02 20:47:46 +00:00
{
2009-12-11 22:21:29 +00:00
int sec ;
2009-12-02 20:47:46 +00:00
2010-11-02 17:58:24 -05:00
if ( gateway_ptr - > failure_status = = 503 | | gateway_ptr - > failure_status = = 908 ) {
2009-12-11 22:21:29 +00:00
sec = gateway_ptr - > retry_seconds ;
2010-02-06 03:38:24 +00:00
} else {
2009-12-02 20:47:46 +00:00
sec = gateway_ptr - > retry_seconds * ( gateway_ptr - > failures + 1 ) ;
}
2010-02-06 03:38:24 +00:00
2010-01-08 17:42:56 +00:00
gateway_ptr - > retry = switch_epoch_time_now ( NULL ) + sec ;
2009-12-02 20:47:46 +00:00
gateway_ptr - > status = SOFIA_GATEWAY_DOWN ;
gateway_ptr - > state = REG_STATE_FAIL_WAIT ;
gateway_ptr - > failure_status = 0 ;
2010-11-02 17:58:24 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " %s Failed Registration [%d], setting retry to %d seconds. \n " ,
gateway_ptr - > name , gateway_ptr - > failure_status , sec ) ;
2009-12-02 20:47:46 +00:00
}
2008-11-24 16:56:21 +00:00
break ;
case REG_STATE_FAIL_WAIT :
if ( ! gateway_ptr - > retry | | now > = gateway_ptr - > retry ) {
2007-03-31 19:01:33 +00:00
gateway_ptr - > state = REG_STATE_UNREGED ;
2008-11-24 16:56:21 +00:00
}
break ;
case REG_STATE_TRYING :
2010-11-03 10:58:32 -05:00
if ( now > = gateway_ptr - > reg_timeout ) {
2010-11-02 17:58:24 -05:00
gateway_ptr - > state = REG_STATE_TIMEOUT ;
2007-03-31 19:01:33 +00:00
}
break ;
default :
if ( now > = gateway_ptr - > expires ) {
gateway_ptr - > state = REG_STATE_UNREGED ;
}
break ;
}
2008-10-10 15:36:02 +00:00
if ( ostate ! = gateway_ptr - > state ) {
2010-01-15 15:18:07 +00:00
sofia_reg_fire_custom_gateway_state_event ( gateway_ptr , 0 , NULL ) ;
2008-10-10 15:36:02 +00:00
}
2007-03-31 19:01:33 +00:00
}
2011-06-16 14:32:08 -05:00
switch_mutex_unlock ( profile - > gw_mutex ) ;
2007-03-31 19:01:33 +00:00
}
int sofia_reg_find_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
struct callback_t * cbt = ( struct callback_t * ) pArg ;
2010-08-18 14:58:14 -05:00
if ( ! cbt - > len ) {
switch_console_push_match ( & cbt - > list , argv [ 0 ] ) ;
cbt - > matches + + ;
return 0 ;
}
2007-03-31 19:01:33 +00:00
switch_copy_string ( cbt - > val , argv [ 0 ] , cbt - > len ) ;
cbt - > matches + + ;
2010-08-18 14:58:14 -05:00
return cbt - > matches = = 1 ? 0 : 1 ;
2007-03-31 19:01:33 +00:00
}
2011-08-17 19:34:22 -05:00
int sofia_reg_find_reg_with_positive_expires_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
struct callback_t * cbt = ( struct callback_t * ) pArg ;
sofia_destination_t * dst = NULL ;
long int expires ;
char * contact = NULL ;
expires = atol ( argv [ 1 ] ) - 60 - ( long ) switch_epoch_time_now ( NULL ) ;
if ( expires > 0 ) {
dst = sofia_glue_get_destination ( argv [ 0 ] ) ;
contact = switch_mprintf ( " <%s>;expires=%ld " , dst - > contact , expires ) ;
if ( ! cbt - > len ) {
switch_console_push_match ( & cbt - > list , contact ) ;
switch_safe_free ( contact ) ;
sofia_glue_free_destination ( dst ) ;
cbt - > matches + + ;
return 0 ;
}
switch_copy_string ( cbt - > val , contact , cbt - > len ) ;
switch_safe_free ( contact ) ;
sofia_glue_free_destination ( dst ) ;
cbt - > matches + + ;
return cbt - > matches = = 1 ? 0 : 1 ;
}
return 0 ;
}
2007-05-22 15:03:21 +00:00
int sofia_reg_nat_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
nua_handle_t * nh ;
char to [ 128 ] = " " ;
2009-06-19 15:48:23 +00:00
sofia_destination_t * dst = NULL ;
2007-05-22 15:03:21 +00:00
2008-04-14 16:10:18 +00:00
switch_snprintf ( to , sizeof ( to ) , " sip:%s@%s " , argv [ 1 ] , argv [ 2 ] ) ;
2009-06-19 15:48:23 +00:00
dst = sofia_glue_get_destination ( argv [ 3 ] ) ;
switch_assert ( dst ) ;
2010-09-15 15:38:25 -05:00
2010-02-06 03:38:24 +00:00
nh = nua_handle ( profile - > nua , NULL , SIPTAG_FROM_STR ( profile - > url ) , SIPTAG_TO_STR ( to ) , NUTAG_URL ( dst - > contact ) , SIPTAG_CONTACT_STR ( profile - > url ) ,
TAG_END ( ) ) ;
2008-05-07 14:22:36 +00:00
nua_handle_bind ( nh , & mod_sofia_globals . destroy_private ) ;
2010-09-15 15:38:25 -05:00
nua_options ( nh ,
NTATAG_SIP_T2 ( 5000 ) ,
NTATAG_SIP_T4 ( 10000 ) ,
TAG_IF ( dst - > route_uri , NUTAG_PROXY ( dst - > route_uri ) ) , TAG_IF ( dst - > route , SIPTAG_ROUTE_STR ( dst - > route ) ) , TAG_END ( ) ) ;
2007-10-28 16:07:23 +00:00
2009-06-19 15:48:23 +00:00
sofia_glue_free_destination ( dst ) ;
2008-05-27 04:54:52 +00:00
2007-05-22 15:03:21 +00:00
return 0 ;
}
2008-05-07 20:06:46 +00:00
2010-02-06 03:38:24 +00:00
void sofia_reg_send_reboot ( sofia_profile_t * profile , const char * user , const char * host , const char * contact , const char * user_agent ,
const char * network_ip )
2008-07-17 20:47:42 +00:00
{
const char * event = " check-sync " ;
2009-08-21 00:59:09 +00:00
const char * contenttype = " application/simple-message-summary " ;
const char * body = " " ;
2008-07-17 20:47:42 +00:00
2010-12-03 18:58:39 -05:00
if ( switch_stristr ( " snom " , user_agent ) | | switch_stristr ( " yealink " , user_agent ) ) {
2008-07-17 20:47:42 +00:00
event = " check-sync;reboot=true " ;
} else if ( switch_stristr ( " linksys " , user_agent ) ) {
event = " reboot_now " ;
2010-01-13 15:57:58 +00:00
} else if ( switch_stristr ( " spa " , user_agent ) ) {
event = " reboot " ;
2008-07-17 20:47:42 +00:00
}
2011-08-19 17:29:42 -05:00
sofia_glue_send_notify ( profile , user , host , event , contenttype , body , contact , network_ip ) ;
2008-07-17 20:47:42 +00:00
}
2009-03-22 05:15:17 +00:00
int sofia_sla_dialog_del_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
nua_handle_t * nh = NULL ;
if ( ( nh = nua_handle_by_call_id ( profile - > nua , argv [ 0 ] ) ) ) {
nua_handle_destroy ( nh ) ;
}
2010-02-06 03:38:24 +00:00
2009-03-22 05:15:17 +00:00
return 0 ;
}
2008-07-17 20:47:42 +00:00
2007-03-31 19:01:33 +00:00
int sofia_reg_del_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
switch_event_t * s_event ;
2008-07-17 20:47:42 +00:00
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
2010-02-06 03:38:24 +00:00
2009-06-03 21:08:34 +00:00
if ( argc > 12 & & atoi ( argv [ 12 ] ) = = 1 ) {
sofia_reg_send_reboot ( profile , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 7 ] , argv [ 11 ] ) ;
2008-07-17 20:47:42 +00:00
}
2007-03-31 19:01:33 +00:00
if ( argc > = 3 ) {
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_EXPIRE ) = = SWITCH_STATUS_SUCCESS ) {
2009-02-10 18:30:49 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , argv [ 10 ] ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " call-id " , argv [ 0 ] ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user " , argv [ 1 ] ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " host " , argv [ 2 ] ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " contact " , argv [ 3 ] ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " expires " , argv [ 6 ] ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user-agent " , argv [ 7 ] ) ;
2007-03-31 19:01:33 +00:00
switch_event_fire ( & s_event ) ;
}
2010-02-03 19:40:24 +00:00
2010-09-15 15:38:25 -05:00
if ( switch_event_create ( & s_event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2010-02-03 19:40:24 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , " away " ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " login " , profile - > url ) ;
if ( argv [ 4 ] ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user-agent " , argv [ 4 ] ) ;
}
if ( argv [ 1 ] & & argv [ 2 ] ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , argv [ 1 ] , argv [ 2 ] ) ;
}
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " status " , " Unregistered " ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & s_event ) ;
}
2007-03-31 19:01:33 +00:00
}
return 0 ;
}
2008-07-17 20:47:42 +00:00
void sofia_reg_expire_call_id ( sofia_profile_t * profile , const char * call_id , int reboot )
2008-03-25 22:06:48 +00:00
{
2009-08-11 01:26:51 +00:00
char * sql = NULL ;
char * sqlextra = NULL ;
2009-05-15 19:36:43 +00:00
char * dup = strdup ( call_id ) ;
char * host = NULL , * user = NULL ;
2008-07-17 20:47:42 +00:00
2009-05-15 19:36:43 +00:00
switch_assert ( dup ) ;
2008-05-27 04:54:52 +00:00
2009-05-15 19:36:43 +00:00
if ( ( host = strchr ( dup , ' @ ' ) ) ) {
2008-07-17 20:47:42 +00:00
* host + + = ' \0 ' ;
2009-05-15 19:36:43 +00:00
user = dup ;
} else {
host = dup ;
2008-07-17 20:47:42 +00:00
}
2009-05-15 19:36:43 +00:00
2008-07-17 20:47:42 +00:00
if ( ! host ) {
host = " none " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( user ) ) {
2009-08-11 01:26:51 +00:00
sqlextra = switch_mprintf ( " or (sip_host='%q') " , host ) ;
2009-05-15 19:36:43 +00:00
} else {
2009-08-11 01:26:51 +00:00
sqlextra = switch_mprintf ( " or (sip_user='%q' and sip_host='%q') " , user , host ) ;
2009-05-15 19:36:43 +00:00
}
2009-08-11 01:26:51 +00:00
sql = switch_mprintf ( " select call_id,sip_user,sip_host,contact,status,rpid,expires "
2010-02-06 03:38:24 +00:00
" ,user_agent,server_user,server_host,profile_name,network_ip "
" ,%d from sip_registrations where call_id='%q' %s " , reboot , call_id , sqlextra ) ;
2008-03-25 22:06:48 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2009-11-12 03:52:07 +00:00
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_del_callback , profile ) ;
2008-03-25 22:06:48 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2009-08-11 01:26:51 +00:00
switch_safe_free ( sql ) ;
2010-02-06 03:38:24 +00:00
2011-01-16 22:27:56 +00:00
sql = switch_mprintf ( " delete from sip_registrations where call_id='%q' %s " , call_id , sqlextra ) ;
2010-07-29 23:39:39 -05:00
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_FALSE ) ;
2008-07-17 20:47:42 +00:00
2011-01-16 22:27:56 +00:00
switch_safe_free ( sqlextra ) ;
2009-08-11 01:26:51 +00:00
switch_safe_free ( sql ) ;
2009-05-15 19:36:43 +00:00
switch_safe_free ( dup ) ;
2008-07-17 20:47:42 +00:00
2008-03-25 22:06:48 +00:00
}
2007-05-22 15:03:21 +00:00
2008-07-17 20:47:42 +00:00
void sofia_reg_check_expire ( sofia_profile_t * profile , time_t now , int reboot )
2007-03-31 19:01:33 +00:00
{
char sql [ 1024 ] ;
2008-05-07 20:06:46 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2007-04-29 01:16:49 +00:00
if ( now ) {
2009-06-03 21:08:34 +00:00
switch_snprintf ( sql , sizeof ( sql ) , " select call_id,sip_user,sip_host,contact,status,rpid,expires "
" ,user_agent,server_user,server_host,profile_name,network_ip "
2008-09-18 00:01:03 +00:00
" ,%d from sip_registrations where expires > 0 and expires <= %ld " , reboot , ( long ) now ) ;
2007-04-29 01:16:49 +00:00
} else {
2009-06-03 21:08:34 +00:00
switch_snprintf ( sql , sizeof ( sql ) , " select call_id,sip_user,sip_host,contact,status,rpid,expires "
2010-02-06 03:38:24 +00:00
" ,user_agent,server_user,server_host,profile_name,network_ip " " ,%d from sip_registrations where expires > 0 " , reboot ) ;
2007-04-29 01:16:49 +00:00
}
2007-03-31 19:01:33 +00:00
2009-11-12 03:52:07 +00:00
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_del_callback , profile ) ;
2007-04-29 01:16:49 +00:00
if ( now ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q' " ,
2008-09-18 00:01:03 +00:00
( long ) now , mod_sofia_globals . hostname ) ;
2007-04-29 01:16:49 +00:00
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_registrations where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2007-04-29 01:16:49 +00:00
}
2008-04-14 15:07:43 +00:00
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2008-05-27 04:54:52 +00:00
2008-11-22 01:34:19 +00:00
2009-03-22 05:15:17 +00:00
if ( now ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select call_id from sip_shared_appearance_dialogs where hostname='%q' "
2010-02-06 03:38:24 +00:00
" and profile_name='%s' and expires <= %ld " , mod_sofia_globals . hostname , profile - > name , ( long ) now ) ;
2009-11-12 03:52:07 +00:00
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_sla_dialog_del_callback , profile ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld " ,
2009-03-22 05:15:17 +00:00
mod_sofia_globals . hostname , ( long ) now ) ;
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2009-03-22 05:15:17 +00:00
}
2008-11-22 01:34:19 +00:00
if ( now ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q' " ,
2008-11-22 01:34:19 +00:00
( long ) now , mod_sofia_globals . hostname ) ;
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_presence where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2008-11-22 01:34:19 +00:00
}
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2008-11-22 01:34:19 +00:00
2007-04-29 01:16:49 +00:00
if ( now ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q' " ,
2008-09-18 00:01:03 +00:00
( long ) now , mod_sofia_globals . hostname ) ;
2007-04-29 01:16:49 +00:00
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_authentication where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2007-04-29 01:16:49 +00:00
}
2008-04-14 15:07:43 +00:00
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2010-09-15 15:38:25 -05:00
2011-12-15 16:30:33 -06:00
sofia_presence_check_subscriptions ( profile , now ) ;
2010-01-09 00:34:17 +00:00
if ( now ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q' " ,
2010-01-09 00:34:17 +00:00
( long ) now , mod_sofia_globals . hostname ) ;
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_dialogs where expires >= -1 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2007-04-29 01:16:49 +00:00
}
2008-04-14 15:07:43 +00:00
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
2010-09-15 15:38:25 -05:00
if ( now ) {
if ( sofia_test_pflag ( profile , PFLAG_ALL_REG_OPTIONS_PING ) ) {
switch_snprintf ( sql , sizeof ( sql ) , " select call_id,sip_user,sip_host,contact,status,rpid, "
" expires,user_agent,server_user,server_host,profile_name "
2010-10-15 17:59:00 -05:00
" from sip_registrations where hostname='%s' and "
" profile_name='%s' " , mod_sofia_globals . hostname , profile - > name ) ;
2010-09-15 15:38:25 -05:00
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_nat_callback , profile ) ;
} else if ( sofia_test_pflag ( profile , PFLAG_NAT_OPTIONS_PING ) ) {
switch_snprintf ( sql , sizeof ( sql ) , " select call_id,sip_user,sip_host,contact,status,rpid, "
" expires,user_agent,server_user,server_host,profile_name "
" from sip_registrations where (status like '%%NAT%%' "
2010-10-15 17:59:00 -05:00
" or contact like '%%fs_nat=yes%%') and hostname='%s' "
" and profile_name='%s' " , mod_sofia_globals . hostname , profile - > name ) ;
2010-09-15 15:38:25 -05:00
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_nat_callback , profile ) ;
}
2007-05-22 15:03:21 +00:00
}
2007-03-31 19:01:33 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
}
2011-06-08 11:09:03 -05:00
int sofia_reg_check_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
sofia_reg_send_reboot ( profile , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 7 ] , argv [ 11 ] ) ;
return 0 ;
}
void sofia_reg_check_call_id ( sofia_profile_t * profile , const char * call_id )
{
char * sql = NULL ;
char * sqlextra = NULL ;
char * dup = strdup ( call_id ) ;
char * host = NULL , * user = NULL ;
switch_assert ( dup ) ;
if ( ( host = strchr ( dup , ' @ ' ) ) ) {
* host + + = ' \0 ' ;
user = dup ;
} else {
host = dup ;
}
if ( ! host ) {
host = " none " ;
}
if ( zstr ( user ) ) {
sqlextra = switch_mprintf ( " or (sip_host='%q') " , host ) ;
} else {
sqlextra = switch_mprintf ( " or (sip_user='%q' and sip_host='%q') " , user , host ) ;
}
sql = switch_mprintf ( " select call_id,sip_user,sip_host,contact,status,rpid,expires "
" ,user_agent,server_user,server_host,profile_name,network_ip "
" from sip_registrations where call_id='%q' %s " , call_id , sqlextra ) ;
switch_mutex_lock ( profile - > ireg_mutex ) ;
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_check_callback , profile ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
switch_safe_free ( sqlextra ) ;
switch_safe_free ( dup ) ;
}
void sofia_reg_check_sync ( sofia_profile_t * profile )
{
char sql [ 1024 ] ;
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_snprintf ( sql , sizeof ( sql ) , " select call_id,sip_user,sip_host,contact,status,rpid,expires "
" ,user_agent,server_user,server_host,profile_name,network_ip "
" from sip_registrations where expires > 0 " ) ;
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_del_callback , profile ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_registrations where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2011-06-08 11:09:03 -05:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_presence where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2011-06-08 11:09:03 -05:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_authentication where expires > 0 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2011-06-08 11:09:03 -05:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_subscriptions where expires >= -1 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2011-06-08 11:09:03 -05:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " delete from sip_dialogs where expires >= -1 and hostname='%q' " , mod_sofia_globals . hostname ) ;
2011-06-08 11:09:03 -05:00
sofia_glue_actually_execute_sql ( profile , sql , NULL ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
}
2007-04-04 03:08:17 +00:00
char * sofia_reg_find_reg_url ( sofia_profile_t * profile , const char * user , const char * host , char * val , switch_size_t len )
2007-03-31 19:01:33 +00:00
{
struct callback_t cbt = { 0 } ;
2008-08-12 20:54:51 +00:00
char sql [ 512 ] = " " ;
2007-03-31 19:01:33 +00:00
if ( ! user ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Called with null user! \n " ) ;
return NULL ;
}
cbt . val = val ;
cbt . len = len ;
2007-04-04 03:08:17 +00:00
2007-03-31 19:01:33 +00:00
if ( host ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " ,
2010-02-06 03:38:24 +00:00
user , host , host ) ;
2007-03-31 19:01:33 +00:00
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact from sip_registrations where sip_user='%q' " , user ) ;
2007-03-31 19:01:33 +00:00
}
2009-11-12 03:52:07 +00:00
sofia_glue_execute_sql_callback ( profile , profile - > ireg_mutex , sql , sofia_reg_find_callback , & cbt ) ;
2007-03-31 19:01:33 +00:00
if ( cbt . matches ) {
return val ;
} else {
return NULL ;
}
}
2007-06-08 22:28:32 +00:00
2010-08-18 14:58:14 -05:00
switch_console_callback_match_t * sofia_reg_find_reg_url_multi ( sofia_profile_t * profile , const char * user , const char * host )
{
struct callback_t cbt = { 0 } ;
char sql [ 512 ] = " " ;
if ( ! user ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Called with null user! \n " ) ;
return NULL ;
}
if ( host ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " ,
2010-08-18 14:58:14 -05:00
user , host , host ) ;
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact from sip_registrations where sip_user='%q' " , user ) ;
2010-08-18 14:58:14 -05:00
}
sofia_glue_execute_sql_callback ( profile , profile - > ireg_mutex , sql , sofia_reg_find_callback , & cbt ) ;
return cbt . list ;
}
2011-08-17 19:34:22 -05:00
switch_console_callback_match_t * sofia_reg_find_reg_url_with_positive_expires_multi ( sofia_profile_t * profile , const char * user , const char * host )
{
struct callback_t cbt = { 0 } ;
char sql [ 512 ] = " " ;
if ( ! user ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Called with null user! \n " ) ;
return NULL ;
}
if ( host ) {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " ,
2011-08-17 19:34:22 -05:00
user , host , host ) ;
} else {
2011-09-29 08:28:12 -05:00
switch_snprintfv ( sql , sizeof ( sql ) , " select contact,expires from sip_registrations where sip_user='%q' " , user ) ;
2011-08-17 19:34:22 -05:00
}
sofia_glue_execute_sql_callback ( profile , profile - > ireg_mutex , sql , sofia_reg_find_reg_with_positive_expires_callback , & cbt ) ;
return cbt . list ;
}
2011-06-30 11:59:58 -05:00
void sofia_reg_auth_challenge ( sofia_profile_t * profile , nua_handle_t * nh , sofia_dispatch_event_t * de ,
2011-06-16 14:37:22 -05:00
sofia_regtype_t regtype , const char * realm , int stale )
2007-06-08 22:28:32 +00:00
{
switch_uuid_t uuid ;
char uuid_str [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
char * sql , * auth_str ;
2011-06-30 11:59:58 -05:00
msg_t * msg = NULL ;
if ( de & & de - > data ) {
msg = de - > data - > e_msg ;
}
2007-06-08 22:28:32 +00:00
switch_uuid_get ( & uuid ) ;
switch_uuid_format ( uuid_str , & uuid ) ;
2009-10-28 16:55:29 +00:00
sql = switch_mprintf ( " insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) "
2010-02-06 03:38:24 +00:00
" values('%q', %ld, '%q', '%q', 0) " , uuid_str ,
2011-03-28 10:27:06 -05:00
( long ) switch_epoch_time_now ( NULL ) + ( profile - > nonce_ttl ? profile - > nonce_ttl : DEFAULT_NONCE_TTL ) ,
2009-10-28 16:55:29 +00:00
profile - > name , mod_sofia_globals . hostname ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , profile - > ireg_mutex ) ;
2008-04-08 15:36:58 +00:00
switch_safe_free ( sql ) ;
2007-06-08 22:28:32 +00:00
2009-11-23 16:49:05 +00:00
auth_str = switch_mprintf ( " Digest realm= \" %q \" , nonce= \" %q \" ,%s algorithm=MD5, qop= \" auth \" " , realm , uuid_str , stale ? " stale=true, " : " " ) ;
2007-06-08 22:28:32 +00:00
if ( regtype = = REG_REGISTER ) {
2011-06-30 11:59:58 -05:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , TAG_IF ( msg , NUTAG_WITH_THIS_MSG ( msg ) ) , SIPTAG_WWW_AUTHENTICATE_STR ( auth_str ) , TAG_END ( ) ) ;
2007-06-08 22:28:32 +00:00
} else if ( regtype = = REG_INVITE ) {
2011-06-30 11:59:58 -05:00
nua_respond ( nh , SIP_407_PROXY_AUTH_REQUIRED ,
TAG_IF ( msg , NUTAG_WITH_THIS_MSG ( msg ) ) ,
SIPTAG_PROXY_AUTHENTICATE_STR ( auth_str ) , TAG_END ( ) ) ;
2007-06-08 22:28:32 +00:00
}
switch_safe_free ( auth_str ) ;
}
2011-01-03 16:40:49 -06:00
uint32_t sofia_reg_reg_count ( sofia_profile_t * profile , const char * user , const char * host )
{
char buf [ 32 ] = " " ;
char * sql ;
sql = switch_mprintf ( " select count(*) from sip_registrations where profile_name='%q' and "
" sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " , profile - > name , user , host , host ) ;
sofia_glue_execute_sql2str ( profile , profile - > ireg_mutex , sql , buf , sizeof ( buf ) ) ;
switch_safe_free ( sql ) ;
return atoi ( buf ) ;
}
2011-06-16 14:37:22 -05:00
uint8_t sofia_reg_handle_register ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sip_t const * sip ,
sofia_dispatch_event_t * de , sofia_regtype_t regtype , char * key ,
2008-05-21 21:49:27 +00:00
uint32_t keylen , switch_event_t * * v_event , const char * is_nat )
2007-03-31 19:01:33 +00:00
{
2007-06-05 17:42:15 +00:00
sip_to_t const * to = NULL ;
2008-07-16 19:42:40 +00:00
sip_from_t const * from = NULL ;
2007-03-31 19:01:33 +00:00
sip_expires_t const * expires = NULL ;
sip_authorization_t const * authorization = NULL ;
sip_contact_t const * contact = NULL ;
2009-10-27 06:14:00 +00:00
char * sql ;
2007-03-31 19:01:33 +00:00
switch_event_t * s_event ;
2007-06-05 17:42:15 +00:00
const char * to_user = NULL ;
const char * to_host = NULL ;
2009-09-25 20:07:40 +00:00
char * mwi_account = NULL ;
char * dup_mwi_account = NULL ;
char * mwi_user = NULL ;
char * mwi_host = NULL ;
2009-10-21 23:09:41 +00:00
char * var = NULL ;
2008-07-16 19:42:40 +00:00
const char * from_user = NULL ;
const char * from_host = NULL ;
2008-09-08 22:38:37 +00:00
const char * reg_host = profile - > reg_db_domain ;
2010-09-02 16:01:50 -05:00
const char * sub_host = profile - > sub_domain ;
2007-03-31 19:01:33 +00:00
char contact_str [ 1024 ] = " " ;
2008-10-22 17:40:43 +00:00
uint8_t multi_reg = 0 , multi_reg_contact = 0 , avoid_multi_reg = 0 ;
2007-04-20 18:06:06 +00:00
uint8_t stale = 0 , forbidden = 0 ;
2011-12-16 12:28:22 -06:00
auth_res_t auth_res = AUTH_OK ;
2009-04-30 00:09:41 +00:00
long exptime = 300 ;
2007-03-31 19:01:33 +00:00
switch_event_t * event ;
const char * rpid = " unknown " ;
const char * display = " \" user \" " ;
2007-04-20 18:06:06 +00:00
char network_ip [ 80 ] ;
2009-03-04 19:45:10 +00:00
char network_port_c [ 6 ] ;
2008-07-03 18:50:15 +00:00
char url_ip [ 80 ] ;
2007-05-21 19:11:37 +00:00
int network_port ;
2008-01-17 17:37:49 +00:00
const char * reg_desc = " Registered " ;
2007-10-24 23:20:47 +00:00
const char * call_id = NULL ;
2008-01-12 19:15:05 +00:00
char * force_user ;
2008-05-23 12:23:06 +00:00
char received_data [ 128 ] = " " ;
2008-06-26 20:19:09 +00:00
char * path_val = NULL ;
2009-03-25 20:14:07 +00:00
switch_event_t * auth_params = NULL ;
int r = 0 ;
2009-11-12 03:52:07 +00:00
long reg_count = 0 ;
2010-09-15 15:38:25 -05:00
const char * agent = " unknown " ;
2011-01-14 13:57:58 -06:00
const char * pres_on_reg = NULL ;
int send_pres = 0 ;
2011-02-11 23:10:12 -06:00
int is_tls = 0 , is_tcp = 0 ;
2011-01-14 13:57:58 -06:00
if ( v_event & & * v_event ) pres_on_reg = switch_event_get_header ( * v_event , " send-presence-on-register " ) ;
if ( ! ( send_pres = switch_true ( pres_on_reg ) ) ) {
if ( pres_on_reg & & ! strcasecmp ( pres_on_reg , " first-only " ) ) {
send_pres = 2 ;
}
}
2011-08-17 19:34:22 -05:00
/* all callers must confirm that sip and sip->sip_request are not NULL */
switch_assert ( sip ! = NULL & & sip - > sip_request ! = NULL ) ;
2007-03-31 19:01:33 +00:00
2011-06-16 14:37:22 -05:00
sofia_glue_get_addr ( de - > data - > e_msg , network_ip , sizeof ( network_ip ) , & network_port ) ;
2008-07-03 18:50:15 +00:00
2009-03-04 19:45:10 +00:00
snprintf ( network_port_c , sizeof ( network_port_c ) , " %d " , network_port ) ;
2011-06-16 14:37:22 -05:00
snprintf ( url_ip , sizeof ( url_ip ) , ( msg_addrinfo ( de - > data - > e_msg ) ) - > ai_addr - > sa_family = = AF_INET6 ? " [%s] " : " %s " , network_ip ) ;
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
expires = sip - > sip_expires ;
authorization = sip - > sip_authorization ;
contact = sip - > sip_contact ;
2007-06-05 17:42:15 +00:00
to = sip - > sip_to ;
2010-01-13 01:40:11 +00:00
from = sip - > sip_from ;
2007-03-31 19:01:33 +00:00
2010-09-15 15:38:25 -05:00
if ( sip - > sip_user_agent ) {
agent = sip - > sip_user_agent - > g_string ;
}
2010-01-13 01:40:11 +00:00
if ( from ) {
from_user = from - > a_url - > url_user ;
from_host = from - > a_url - > url_host ;
}
2010-02-06 03:38:24 +00:00
2007-06-05 17:42:15 +00:00
if ( to ) {
to_user = to - > a_url - > url_user ;
to_host = to - > a_url - > url_host ;
2007-03-31 19:01:33 +00:00
}
2010-02-06 03:38:24 +00:00
if ( ! to_user )
to_user = from_user ;
if ( ! to_host )
to_host = from_host ;
2010-01-13 01:40:11 +00:00
2007-06-05 17:42:15 +00:00
if ( ! to_user | | ! to_host ) {
2010-08-17 19:54:46 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can not do authorization without a complete header in REGISTER request from %s:%d \n " ,
network_ip , network_port ) ;
2011-06-16 14:37:22 -05:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , TAG_END ( ) ) ;
2009-03-25 20:14:07 +00:00
switch_goto_int ( r , 1 , end ) ;
2007-03-31 19:01:33 +00:00
}
2008-09-08 22:38:37 +00:00
if ( ! reg_host ) {
reg_host = to_host ;
}
2010-09-02 16:01:50 -05:00
if ( ! sub_host ) {
sub_host = to_host ;
}
2008-09-08 22:38:37 +00:00
2011-08-17 19:34:22 -05:00
if ( contact & & contact - > m_url ) {
2007-03-31 19:01:33 +00:00
const char * port = contact - > m_url - > url_port ;
2008-04-07 14:03:10 +00:00
char new_port [ 25 ] = " " ;
2008-05-21 21:49:27 +00:00
const char * contact_host = contact - > m_url - > url_host ;
2008-06-26 20:19:09 +00:00
char * path_encoded = NULL ;
int path_encoded_len = 0 ;
2008-06-27 21:38:59 +00:00
const char * proto = " sip " ;
2008-07-03 15:01:46 +00:00
if ( switch_stristr ( " transport=tls " , sip - > sip_contact - > m_url - > url_params ) ) {
is_tls + = 1 ;
}
2010-02-06 03:38:24 +00:00
2008-06-27 21:38:59 +00:00
if ( sip - > sip_contact - > m_url - > url_type = = url_sips ) {
proto = " sips " ;
2008-07-03 15:01:46 +00:00
is_tls + = 2 ;
2008-06-27 21:38:59 +00:00
}
2010-02-06 03:38:24 +00:00
2008-07-03 15:01:46 +00:00
if ( switch_stristr ( " transport=tcp " , sip - > sip_contact - > m_url - > url_params ) ) {
is_tcp = 1 ;
}
2010-02-06 03:38:24 +00:00
2008-05-22 01:24:13 +00:00
display = contact - > m_display ;
2010-02-06 03:38:24 +00:00
2008-05-21 21:49:27 +00:00
if ( is_nat ) {
2008-07-03 15:01:46 +00:00
if ( is_tls ) {
reg_desc = " Registered(TLS-NAT) " ;
} else if ( is_tcp ) {
reg_desc = " Registered(TCP-NAT) " ;
} else {
reg_desc = " Registered(UDP-NAT) " ;
}
2009-04-30 00:09:41 +00:00
//contact_host = url_ip;
//switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
//port = NULL;
2008-07-03 15:01:46 +00:00
} else {
if ( is_tls ) {
reg_desc = " Registered(TLS) " ;
} else if ( is_tcp ) {
reg_desc = " Registered(TCP) " ;
} else {
reg_desc = " Registered(UDP) " ;
}
2008-05-21 21:49:27 +00:00
}
2008-05-27 04:54:52 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( display ) ) {
2007-06-05 17:42:15 +00:00
if ( to ) {
display = to - > a_display ;
2009-10-23 16:03:42 +00:00
if ( zstr ( display ) ) {
2007-03-31 19:01:33 +00:00
display = " \" user \" " ;
}
}
}
2008-06-26 20:19:09 +00:00
if ( sip - > sip_path ) {
2009-03-24 17:57:00 +00:00
path_val = sip_header_as_string ( nua_handle_home ( nh ) , ( void * ) sip - > sip_path ) ;
2010-09-29 15:47:58 -05:00
path_encoded_len = ( int ) ( strlen ( path_val ) * 3 ) + 1 ;
2008-06-26 20:19:09 +00:00
switch_zmalloc ( path_encoded , path_encoded_len ) ;
2008-06-27 16:01:40 +00:00
switch_copy_string ( path_encoded , " ;fs_path= " , 10 ) ;
switch_url_encode ( path_val , path_encoded + 9 , path_encoded_len - 9 ) ;
2009-04-30 00:09:41 +00:00
} else if ( is_nat ) {
char my_contact_str [ 1024 ] ;
2009-05-04 14:36:11 +00:00
if ( sip - > sip_contact - > m_url - > url_params ) {
2010-02-06 03:38:24 +00:00
switch_snprintf ( my_contact_str , sizeof ( my_contact_str ) , " sip:%s@%s:%d;%s " ,
2009-05-04 14:36:11 +00:00
contact - > m_url - > url_user , url_ip , network_port , sip - > sip_contact - > m_url - > url_params ) ;
} else {
switch_snprintf ( my_contact_str , sizeof ( my_contact_str ) , " sip:%s@%s:%d " , contact - > m_url - > url_user , url_ip , network_port ) ;
}
2010-09-29 15:47:58 -05:00
path_encoded_len = ( int ) ( strlen ( my_contact_str ) * 3 ) + 1 ;
2009-04-30 00:09:41 +00:00
switch_zmalloc ( path_encoded , path_encoded_len ) ;
switch_copy_string ( path_encoded , " ;fs_path= " , 10 ) ;
switch_url_encode ( my_contact_str , path_encoded + 9 , path_encoded_len - 9 ) ;
exptime = 30 ;
2008-06-26 20:19:09 +00:00
}
2008-04-07 14:03:10 +00:00
if ( port ) {
switch_snprintf ( new_port , sizeof ( new_port ) , " :%s " , port ) ;
2007-03-31 19:01:33 +00:00
}
2009-02-09 17:56:38 +00:00
if ( is_nat & & sofia_test_pflag ( profile , PFLAG_RECIEVED_IN_NAT_REG_CONTACT ) ) {
2008-11-21 16:15:29 +00:00
switch_snprintf ( received_data , sizeof ( received_data ) , " ;received=%s:%d " , url_ip , network_port ) ;
2008-05-23 12:23:06 +00:00
}
2007-03-31 19:01:33 +00:00
if ( contact - > m_url - > url_params ) {
2008-06-27 21:38:59 +00:00
switch_snprintf ( contact_str , sizeof ( contact_str ) , " %s <%s:%s@%s%s;%s%s%s%s> " ,
2010-02-06 03:38:24 +00:00
display , proto , contact - > m_url - > url_user , contact_host , new_port ,
2008-06-27 16:01:40 +00:00
contact - > m_url - > url_params , received_data , is_nat ? " ;fs_nat=yes " : " " , path_encoded ? path_encoded : " " ) ;
2007-03-31 19:01:33 +00:00
} else {
2008-06-27 21:38:59 +00:00
switch_snprintf ( contact_str , sizeof ( contact_str ) , " %s <%s:%s@%s%s%s%s%s> " , display , proto , contact - > m_url - > url_user , contact_host , new_port ,
2008-06-27 16:01:40 +00:00
received_data , is_nat ? " ;fs_nat=yes " : " " , path_encoded ? path_encoded : " " ) ;
2007-03-31 19:01:33 +00:00
}
2008-06-26 20:19:09 +00:00
switch_safe_free ( path_encoded ) ;
2007-03-31 19:01:33 +00:00
}
if ( expires ) {
exptime = expires - > ex_delta ;
2011-08-17 19:34:22 -05:00
} else if ( contact & & contact - > m_expires ) {
2007-03-31 19:01:33 +00:00
exptime = atol ( contact - > m_expires ) ;
}
if ( regtype = = REG_REGISTER ) {
authorization = sip - > sip_authorization ;
} else if ( regtype = = REG_INVITE ) {
authorization = sip - > sip_proxy_authorization ;
}
2009-02-09 17:56:38 +00:00
if ( regtype = = REG_AUTO_REGISTER | | ( regtype = = REG_REGISTER & & sofia_test_pflag ( profile , PFLAG_BLIND_REG ) ) ) {
2008-05-13 23:22:21 +00:00
regtype = REG_REGISTER ;
2007-03-31 19:01:33 +00:00
goto reg ;
}
if ( authorization ) {
2011-05-29 09:46:02 -05:00
char * v_contact_str = NULL ;
2010-10-27 12:00:30 -05:00
const char * username = " unknown " ;
const char * realm = reg_host ;
2011-06-16 14:37:22 -05:00
if ( ( auth_res = sofia_reg_parse_auth ( profile , authorization , sip , de , sip - > sip_request - > rq_method_name ,
2009-11-12 03:52:07 +00:00
key , keylen , network_ip , v_event , exptime , regtype , to_user , & auth_params , & reg_count ) ) = = AUTH_STALE ) {
2007-03-31 19:01:33 +00:00
stale = 1 ;
}
2008-05-27 04:54:52 +00:00
2010-10-27 12:00:30 -05:00
if ( auth_params ) {
username = switch_event_get_header ( auth_params , " sip_auth_username " ) ;
realm = switch_event_get_header ( auth_params , " sip_auth_realm " ) ;
}
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_REGISTER_ATTEMPT ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , profile - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-user " , to_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-host " , reg_host ) ;
2011-08-17 19:34:22 -05:00
if ( contact )
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " contact " , contact_str ) ;
2010-10-27 12:00:30 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " call-id " , call_id ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " status " , reg_desc ) ;
2011-08-17 19:34:22 -05:00
if ( contact )
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %ld " , ( long ) exptime ) ;
2010-10-27 12:00:30 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-user " , from_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-host " , from_host ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-ip " , network_ip ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-port " , network_port_c ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " username " , username ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " realm " , realm ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user-agent " , agent ) ;
switch_event_fire ( & s_event ) ;
}
2011-08-17 19:34:22 -05:00
if ( contact & & exptime & & v_event & & * v_event ) {
2011-12-22 14:03:32 -06:00
uint32_t exp_var ;
uint32_t exp_max_deviation_var ;
2008-07-15 18:04:17 +00:00
char * allow_multireg = NULL ;
2011-01-06 16:01:07 -06:00
int auto_connectile = 0 ;
2008-07-15 18:04:17 +00:00
allow_multireg = switch_event_get_header ( * v_event , " sip-allow-multiple-registrations " ) ;
2010-02-06 03:38:24 +00:00
if ( allow_multireg & & switch_false ( allow_multireg ) ) {
2008-07-15 18:04:17 +00:00
avoid_multi_reg = 1 ;
}
2007-10-18 16:17:42 +00:00
2008-01-12 19:15:05 +00:00
/* Allow us to force the SIP user to be something specific - needed if
* we - for example - want to be able to ensure that the username a UA can
* be contacted at is the same one that they used for authentication .
2008-05-27 04:54:52 +00:00
*/
2008-01-12 19:15:05 +00:00
if ( ( force_user = switch_event_get_header ( * v_event , " sip-force-user " ) ) ) {
to_user = force_user ;
}
2008-05-27 04:54:52 +00:00
2011-03-28 18:31:40 -05:00
if ( profile - > server_rport_level = = 3 & & sip - > sip_user_agent & &
2010-12-21 19:32:54 -06:00
sip - > sip_user_agent - > g_string & & ! strncasecmp ( sip - > sip_user_agent - > g_string , " Polycom " , 7 ) ) {
2011-01-06 16:01:07 -06:00
if ( sip & & sip - > sip_via ) {
const char * host = sip - > sip_via - > v_host ;
const char * c_port = sip - > sip_via - > v_port ;
int port = 0 ;
if ( c_port ) port = atoi ( c_port ) ;
if ( ! port ) port = 5060 ;
if ( host & & strcmp ( network_ip , host ) ) {
auto_connectile = 1 ;
} else if ( port ! = network_port ) {
auto_connectile = 1 ;
}
} else {
auto_connectile = 1 ;
}
2010-12-21 19:32:54 -06:00
}
2011-03-19 10:14:50 -04:00
if ( auto_connectile | | ( v_contact_str = switch_event_get_header ( * v_event , " sip-force-contact " ) ) ) {
if ( auto_connectile | | ( ! strcasecmp ( v_contact_str , " NDLB-connectile-dysfunction-2.0 " ) ) ) {
2011-08-04 00:02:13 -05:00
char * path_encoded = NULL ;
2009-04-29 23:27:24 +00:00
size_t path_encoded_len ;
2009-04-29 22:04:25 +00:00
char my_contact_str [ 1024 ] ;
2009-04-29 23:27:24 +00:00
switch_snprintf ( my_contact_str , sizeof ( my_contact_str ) , " sip:%s@%s:%d " , contact - > m_url - > url_user , url_ip , network_port ) ;
path_encoded_len = ( strlen ( my_contact_str ) * 3 ) + 1 ;
2009-04-29 22:00:34 +00:00
2011-08-04 00:02:13 -05:00
if ( ! switch_stristr ( " fs_path= " , contact_str ) ) {
2009-04-29 22:00:34 +00:00
switch_zmalloc ( path_encoded , path_encoded_len ) ;
2009-04-29 23:27:24 +00:00
switch_copy_string ( path_encoded , " ;fs_nat=yes;fs_path= " , 21 ) ;
2009-04-29 22:56:19 +00:00
switch_url_encode ( my_contact_str , path_encoded + 20 , path_encoded_len - 20 ) ;
2009-04-29 22:00:34 +00:00
reg_desc = " Registered(AUTO-NAT-2.0) " ;
2009-04-30 00:09:41 +00:00
exptime = 30 ;
2011-01-19 11:35:48 -06:00
/* place fs_path (the encoded path) inside the <...> of the contact string, if possible */
if ( contact_str [ strlen ( contact_str ) - 1 ] = = ' > ' ) {
switch_snprintf ( contact_str + strlen ( contact_str ) - 1 , sizeof ( contact_str ) - strlen ( contact_str ) + 1 , " %s> " , path_encoded ) ;
} else {
switch_snprintf ( contact_str + strlen ( contact_str ) , sizeof ( contact_str ) - strlen ( contact_str ) , " %s " , path_encoded ) ;
}
2011-08-04 00:02:13 -05:00
switch_safe_free ( path_encoded ) ;
}
2009-04-29 22:00:34 +00:00
} else {
if ( * received_data & & sofia_test_pflag ( profile , PFLAG_RECIEVED_IN_NAT_REG_CONTACT ) ) {
switch_snprintf ( received_data , sizeof ( received_data ) , " ;received=%s:%d " , url_ip , network_port ) ;
2007-09-18 17:31:36 +00:00
}
2010-02-06 03:38:24 +00:00
2009-04-29 22:00:34 +00:00
if ( ! strcasecmp ( v_contact_str , " nat-connectile-dysfunction " ) | |
! strcasecmp ( v_contact_str , " NDLB-connectile-dysfunction " ) | | ! strcasecmp ( v_contact_str , " NDLB-tls-connectile-dysfunction " ) ) {
if ( contact - > m_url - > url_params ) {
switch_snprintf ( contact_str , sizeof ( contact_str ) , " %s <sip:%s@%s:%d;%s%s;fs_nat=yes> " ,
display , contact - > m_url - > url_user , url_ip , network_port , contact - > m_url - > url_params , received_data ) ;
} else {
switch_snprintf ( contact_str , sizeof ( contact_str ) , " %s <sip:%s@%s:%d%s;fs_nat=yes> " , display , contact - > m_url - > url_user , url_ip ,
network_port , received_data ) ;
}
2010-03-26 16:23:49 +00:00
if ( switch_stristr ( v_contact_str , " transport=tls " ) ) {
2009-04-29 22:00:34 +00:00
reg_desc = " Registered(TLSHACK) " ;
} else {
reg_desc = " Registered(AUTO-NAT) " ;
2009-04-30 00:09:41 +00:00
exptime = 30 ;
2009-04-29 22:00:34 +00:00
}
2008-01-17 17:37:49 +00:00
} else {
2009-04-29 22:00:34 +00:00
char * p ;
switch_copy_string ( contact_str , v_contact_str , sizeof ( contact_str ) ) ;
for ( p = contact_str ; p & & * p ; p + + ) {
if ( * p = = ' \' ' | | * p = = ' [ ' | | * p = = ' ] ' ) {
* p = ' " ' ;
}
2007-09-18 17:31:36 +00:00
}
2007-05-21 19:11:37 +00:00
}
2007-05-14 22:04:28 +00:00
}
}
2008-05-27 04:54:52 +00:00
2011-12-22 14:03:32 -06:00
if ( ( ( exp_var = atoi ( switch_event_get_header_nil ( * v_event , " sip-force-expires " ) ) ) ) | |
( ( exp_var = profile - > sip_force_expires ) ) ) {
if ( exp_var > 0 ) {
exptime = exp_var ;
2007-10-18 16:17:42 +00:00
}
}
2011-12-22 14:03:32 -06:00
if ( ( ( exp_max_deviation_var = atoi ( switch_event_get_header_nil ( * v_event , " sip-expires-max-deviation " ) ) ) ) | |
( ( exp_max_deviation_var = profile - > sip_expires_max_deviation ) ) ) {
if ( exp_max_deviation_var > 0 ) {
int exp_deviation ;
srand ( ( unsigned ) ( ( unsigned ) ( intptr_t ) switch_thread_self ( ) + switch_micro_time_now ( ) ) ) ;
/* random number between negative exp_max_deviation_var and positive exp_max_deviation_var: */
exp_deviation = ( rand ( ) % ( exp_max_deviation_var * 2 ) ) - exp_max_deviation_var ;
exptime + = exp_deviation ;
}
}
2007-05-14 21:30:31 +00:00
}
2011-12-16 14:31:15 -05:00
if ( auth_res ! = AUTH_OK & & auth_res ! = AUTH_RENEWED & & ! stale ) {
2010-12-20 08:43:13 -06:00
if ( auth_res = = AUTH_FORBIDDEN ) {
2011-06-16 14:37:22 -05:00
nua_respond ( nh , SIP_403_FORBIDDEN , NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , TAG_END ( ) ) ;
2010-12-20 08:43:13 -06:00
forbidden = 1 ;
} else {
2011-06-16 14:37:22 -05:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , TAG_END ( ) ) ;
2010-11-24 10:34:02 -06:00
}
2009-02-27 18:15:50 +00:00
if ( profile - > debug ) {
2010-11-24 10:34:02 -06:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Send %s for [%s@%s] \n " ,
forbidden ? " forbidden " : " challenge " , to_user , to_host ) ;
2009-02-27 18:15:50 +00:00
}
2010-12-20 08:43:13 -06:00
/* Log line added to support Fail2Ban */
if ( sofia_test_pflag ( profile , PFLAG_LOG_AUTH_FAIL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " SIP auth %s (%s) on sofia profile '%s' "
" for [%s@%s] from ip %s \n " , forbidden ? " failure " : " challenge " ,
( regtype = = REG_INVITE ) ? " INVITE " : " REGISTER " , profile - > name , to_user , to_host , network_ip ) ;
2007-03-31 19:01:33 +00:00
}
2010-12-20 08:43:13 -06:00
2009-03-25 20:14:07 +00:00
switch_goto_int ( r , 1 , end ) ;
2007-03-31 19:01:33 +00:00
}
}
if ( ! authorization | | stale ) {
2009-02-17 20:36:21 +00:00
const char * realm = profile - > challenge_realm ;
2010-10-27 12:00:30 -05:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_PRE_REGISTER ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , profile - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-user " , to_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-host " , reg_host ) ;
2011-08-17 19:34:22 -05:00
if ( contact )
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " contact " , contact_str ) ;
2010-10-27 12:00:30 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " call-id " , call_id ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " status " , reg_desc ) ;
2011-08-17 19:34:22 -05:00
if ( contact )
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %ld " , ( long ) exptime ) ;
2010-10-27 12:00:30 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-user " , from_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-host " , from_host ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-ip " , network_ip ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-port " , network_port_c ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user-agent " , agent ) ;
switch_event_fire ( & s_event ) ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( realm ) | | ! strcasecmp ( realm , " auto_to " ) ) {
2009-02-17 20:36:21 +00:00
realm = to_host ;
} else if ( ! strcasecmp ( realm , " auto_from " ) ) {
realm = from_host ;
}
2011-06-30 11:59:58 -05:00
sofia_reg_auth_challenge ( profile , nh , de , regtype , realm , stale ) ;
2010-12-20 08:43:13 -06:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Send challenge for [%s@%s] \n " , to_user , to_host ) ;
2007-03-31 19:01:33 +00:00
}
2010-12-20 08:43:13 -06:00
/* Log line added to support Fail2Ban */
if ( sofia_test_pflag ( profile , PFLAG_LOG_AUTH_FAIL ) ) {
2011-11-23 13:25:24 -06:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " SIP auth challenge (%s) on sofia profile '%s' "
2010-12-20 08:43:13 -06:00
" for [%s@%s] from ip %s \n " , ( regtype = = REG_INVITE ) ? " INVITE " : " REGISTER " ,
profile - > name , to_user , to_host , network_ip ) ;
}
2009-03-25 20:14:07 +00:00
switch_goto_int ( r , 1 , end ) ;
2007-03-31 19:01:33 +00:00
}
2011-08-17 19:34:22 -05:00
if ( ! contact )
goto respond_200_ok ;
2008-05-27 04:54:52 +00:00
reg :
2007-03-31 19:01:33 +00:00
2009-10-21 23:09:41 +00:00
if ( v_event & & * v_event & & ( var = switch_event_get_header ( * v_event , " sip-force-extension " ) ) ) {
to_user = var ;
}
2009-09-26 05:41:05 +00:00
if ( v_event & & * v_event & & ( mwi_account = switch_event_get_header ( * v_event , " mwi-account " ) ) ) {
2009-09-25 20:07:40 +00:00
dup_mwi_account = strdup ( mwi_account ) ;
switch_assert ( dup_mwi_account ! = NULL ) ;
2010-06-02 01:09:54 +02:00
switch_split_user_domain ( dup_mwi_account , & mwi_user , & mwi_host ) ;
2009-09-25 20:07:40 +00:00
}
if ( ! mwi_user ) {
mwi_user = ( char * ) to_user ;
}
if ( ! mwi_host ) {
mwi_host = ( char * ) reg_host ;
}
2007-08-16 17:19:27 +00:00
if ( regtype ! = REG_REGISTER ) {
2009-03-25 20:14:07 +00:00
switch_goto_int ( r , 0 , end ) ;
2007-08-16 17:19:27 +00:00
}
2007-10-18 16:17:42 +00:00
2008-10-07 22:18:40 +00:00
call_id = sip - > sip_call_id - > i_id ;
2007-12-12 23:21:45 +00:00
switch_assert ( call_id ) ;
2007-10-18 16:17:42 +00:00
2008-07-15 18:04:17 +00:00
/* Does this profile supports multiple registrations ? */
2010-02-06 03:38:24 +00:00
multi_reg = ( sofia_test_pflag ( profile , PFLAG_MULTIREG ) ) ? 1 : 0 ;
multi_reg_contact = ( sofia_test_pflag ( profile , PFLAG_MULTIREG_CONTACT ) ) ? 1 : 0 ;
2008-07-15 18:04:17 +00:00
2010-02-06 03:38:24 +00:00
if ( multi_reg & & avoid_multi_reg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Disabling multiple registrations on a per-user basis for %s@%s \n " , switch_str_nil ( to_user ) , switch_str_nil ( to_host ) ) ;
2008-07-15 18:04:17 +00:00
multi_reg = 0 ;
}
2007-03-31 19:01:33 +00:00
if ( exptime ) {
2008-07-30 18:50:47 +00:00
char guess_ip4 [ 256 ] ;
2009-03-25 20:14:07 +00:00
const char * username = " unknown " ;
const char * realm = reg_host ;
2011-02-11 23:10:12 -06:00
char * url = NULL ;
char * contact = NULL ;
2011-12-16 14:31:15 -05:00
switch_bool_t update_registration = SWITCH_FALSE ;
2009-03-25 20:14:07 +00:00
if ( auth_params ) {
username = switch_event_get_header ( auth_params , " sip_auth_username " ) ;
realm = switch_event_get_header ( auth_params , " sip_auth_realm " ) ;
}
2012-01-17 16:12:56 -05:00
if ( auth_res ! = AUTH_RENEWED | | ! multi_reg ) {
2011-12-16 14:31:15 -05:00
if ( multi_reg ) {
if ( multi_reg_contact ) {
sql =
switch_mprintf ( " delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q' " , to_user , reg_host , contact_str ) ;
} else {
sql = switch_mprintf ( " delete from sip_registrations where call_id='%q' " , call_id ) ;
}
2008-10-22 17:40:43 +00:00
} else {
2011-12-16 14:31:15 -05:00
sql = switch_mprintf ( " delete from sip_registrations where sip_user='%q' and sip_host='%q' " , to_user , reg_host ) ;
2008-10-22 17:40:43 +00:00
}
2011-12-16 14:31:15 -05:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_TRUE ) ;
2007-03-31 19:01:33 +00:00
} else {
2011-12-16 14:31:15 -05:00
char buf [ 32 ] = " " ;
sql = switch_mprintf ( " select count(*) from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q' " , to_user , reg_host , contact_str ) ;
2011-12-17 13:06:37 -05:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2011-12-16 14:31:15 -05:00
sofia_glue_execute_sql2str ( profile , profile - > ireg_mutex , sql , buf , sizeof ( buf ) ) ;
switch_safe_free ( sql ) ;
if ( atoi ( buf ) > 0 ) {
update_registration = SWITCH_TRUE ;
2010-09-15 15:38:25 -05:00
}
2007-10-18 01:02:01 +00:00
}
2009-09-25 20:07:40 +00:00
2009-06-02 16:55:10 +00:00
switch_find_local_ip ( guess_ip4 , sizeof ( guess_ip4 ) , NULL , AF_INET ) ;
2010-09-02 16:01:50 -05:00
2011-02-11 23:10:12 -06:00
contact = sofia_glue_get_url_from_contact ( contact_str , 1 ) ;
url = switch_mprintf ( " sofia/%q/sip:%q " , profile - > name , sofia_glue_strip_proto ( contact ) ) ;
2010-07-29 23:39:39 -05:00
2011-02-11 23:10:12 -06:00
switch_core_add_registration ( to_user , reg_host , call_id , url , ( long ) switch_epoch_time_now ( NULL ) + ( long ) exptime + 60 ,
network_ip , network_port_c , is_tls ? " tls " : is_tcp ? " tcp " : " udp " ) ;
switch_safe_free ( url ) ;
switch_safe_free ( contact ) ;
2011-12-16 14:31:15 -05:00
if ( ! update_registration ) {
sql = switch_mprintf ( " insert into sip_registrations "
" (call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires, "
" user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm, "
2012-01-10 17:33:40 -06:00
" mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host) "
" values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q') " ,
2011-12-16 14:31:15 -05:00
call_id , to_user , reg_host , profile - > presence_hosts ? profile - > presence_hosts : reg_host ,
contact_str , reg_desc , rpid , ( long ) switch_epoch_time_now ( NULL ) + ( long ) exptime + 60 ,
agent , from_user , guess_ip4 , profile - > name , mod_sofia_globals . hostname , network_ip , network_port_c , username , realm ,
2012-01-10 17:33:40 -06:00
mwi_user , mwi_host , guess_ip4 , mod_sofia_globals . hostname , sub_host ) ;
2011-12-16 14:31:15 -05:00
} else {
sql = switch_mprintf ( " update sip_registrations set expires = %ld where sip_user='%q' and sip_host='%q' and contact='%q' " , ( long ) switch_epoch_time_now ( NULL ) + ( long ) exptime + 60 , to_user , reg_host , contact_str ) ;
}
2007-10-18 01:02:01 +00:00
if ( sql ) {
2010-07-27 22:08:47 -05:00
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_TRUE ) ;
2007-03-31 19:01:33 +00:00
}
2008-11-25 20:54:58 +00:00
2011-12-16 14:31:15 -05:00
if ( ! update_registration & & sofia_reg_reg_count ( profile , to_user , reg_host ) = = 1 ) {
2011-01-03 16:40:49 -06:00
sql = switch_mprintf ( " delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed' " ,
to_user , reg_host , profile - > name ) ;
2011-01-05 11:32:00 -06:00
if ( mod_sofia_globals . debug_presence > 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " DELETE PRESENCE SQL: %s \n " , sql ) ;
}
2011-01-03 16:40:49 -06:00
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_TRUE ) ;
}
2010-07-29 23:39:39 -05:00
2007-10-18 01:02:01 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2007-03-31 19:01:33 +00:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_REGISTER ) = = SWITCH_STATUS_SUCCESS ) {
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , profile - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-user " , to_user ) ;
2008-09-08 22:38:37 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-host " , reg_host ) ;
2008-09-18 00:01:03 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " presence-hosts " , profile - > presence_hosts ? profile - > presence_hosts : reg_host ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " contact " , contact_str ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " call-id " , call_id ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
2009-11-09 22:26:28 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " status " , reg_desc ) ;
2007-03-31 19:01:33 +00:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %ld " , ( long ) exptime ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-user " , from_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " to-host " , from_host ) ;
2009-03-04 19:45:10 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-ip " , network_ip ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " network-port " , network_port_c ) ;
2009-03-25 20:14:07 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " username " , username ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " realm " , realm ) ;
2009-06-16 18:46:28 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " user-agent " , agent ) ;
2007-03-31 19:01:33 +00:00
switch_event_fire ( & s_event ) ;
}
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
2008-01-21 20:36:10 +00:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
2008-09-08 22:38:37 +00:00
" Register: \n From: [%s@%s] \n Contact: [%s] \n Expires: [%ld] \n " , to_user , reg_host , contact_str , ( long ) exptime ) ;
2008-01-21 20:36:10 +00:00
}
2007-03-31 19:01:33 +00:00
2008-12-10 20:54:24 +00:00
#if 0
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " login " , profile - > url ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " user-agent " ,
( sip & & sip - > sip_user_agent ) ? sip - > sip_user_agent - > g_string : " unknown " ) ;
2010-09-02 16:01:50 -05:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , sub_host ) ;
2008-12-10 20:54:24 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " status " , " Registered " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
2011-10-24 18:54:22 -05:00
2009-11-12 03:52:07 +00:00
2010-02-06 03:38:24 +00:00
if ( sofia_test_pflag ( profile , PFLAG_MESSAGE_QUERY_ON_REGISTER ) | |
2009-11-12 03:52:07 +00:00
( reg_count = = 1 & & sofia_test_pflag ( profile , PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER ) ) ) {
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_PROBE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , " sip " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " login " , profile - > url ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
2010-09-02 16:01:50 -05:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , sub_host ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " to " , " %s@%s " , to_user , sub_host ) ;
2009-11-12 03:52:07 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " status " , " Registered " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_subtype " , " probe " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
2007-03-31 19:01:33 +00:00
}
2008-12-10 20:54:24 +00:00
# endif
2008-12-11 20:20:20 +00:00
2007-03-31 19:01:33 +00:00
} else {
2011-01-03 16:40:49 -06:00
int send = 1 ;
2010-02-06 03:38:24 +00:00
2011-01-03 16:40:49 -06:00
if ( multi_reg ) {
if ( sofia_reg_reg_count ( profile , to_user , sub_host ) > 0 ) {
send = 0 ;
}
}
if ( send & & switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2008-12-11 20:20:20 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " login " , profile - > url ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " user-agent " ,
( sip & & sip - > sip_user_agent ) ? sip - > sip_user_agent - > g_string : " unknown " ) ;
2010-09-02 16:01:50 -05:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , sub_host ) ;
2009-03-22 05:15:17 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " status " , " Unregistered " ) ;
2011-10-24 18:54:22 -05:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " presence-source " , " register " ) ;
2008-12-11 20:20:20 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
#if 0
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_OUT ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , " sip " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " login " , profile - > url ) ;
2010-09-02 16:01:50 -05:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s+%s@%s " , SOFIA_CHAT_PROTO , to_user , sub_host ) ;
2008-12-11 20:20:20 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " status " , " unavailable " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
# endif
2008-07-15 18:04:17 +00:00
if ( multi_reg ) {
2007-10-18 01:02:01 +00:00
char * icontact , * p ;
icontact = sofia_glue_get_url_from_contact ( contact_str , 1 ) ;
if ( ( p = strchr ( icontact , ' ; ' ) ) ) {
* p = ' \0 ' ;
}
2007-10-18 16:17:42 +00:00
if ( ( p = strchr ( icontact + 4 , ' : ' ) ) ) {
* p = ' \0 ' ;
}
2008-10-22 17:40:43 +00:00
if ( multi_reg_contact ) {
2010-02-06 03:38:24 +00:00
sql =
switch_mprintf ( " delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q' " , to_user , reg_host , contact_str ) ;
2008-10-22 17:40:43 +00:00
} else {
sql = switch_mprintf ( " delete from sip_registrations where call_id='%q' " , call_id ) ;
2007-10-18 01:02:01 +00:00
}
2008-10-22 17:40:43 +00:00
2010-07-29 23:39:39 -05:00
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_TRUE ) ;
2008-10-22 17:40:43 +00:00
2007-10-18 01:02:01 +00:00
switch_safe_free ( icontact ) ;
} else {
2012-01-03 11:40:52 -06:00
2008-11-05 18:22:36 +00:00
if ( ( sql = switch_mprintf ( " delete from sip_registrations where sip_user='%q' and sip_host='%q' " , to_user , reg_host ) ) ) {
2010-07-29 23:39:39 -05:00
sofia_glue_execute_sql_now ( profile , & sql , SWITCH_TRUE ) ;
2007-10-18 01:02:01 +00:00
}
2007-04-23 20:38:00 +00:00
}
2007-03-31 19:01:33 +00:00
}
2011-08-17 19:34:22 -05:00
respond_200_ok :
2007-03-31 19:01:33 +00:00
if ( regtype = = REG_REGISTER ) {
2008-05-22 17:24:10 +00:00
char exp_param [ 128 ] = " " ;
2008-12-31 16:23:24 +00:00
char date [ 80 ] = " " ;
2010-08-28 23:16:00 -04:00
switch_event_t * s_mwi_event = NULL ;
2009-11-12 03:52:07 +00:00
2011-08-17 19:34:22 -05:00
switch_console_callback_match_t * contact_list = NULL ;
tagi_t * contact_tags ;
switch_console_callback_match_node_t * m ;
int i ;
2008-05-27 04:54:52 +00:00
2011-08-17 19:34:22 -05:00
s_event = NULL ;
2010-02-06 03:38:24 +00:00
2011-08-17 19:34:22 -05:00
if ( contact ) {
if ( exptime ) {
switch_snprintf ( exp_param , sizeof ( exp_param ) , " expires=%ld " , exptime ) ;
sip_contact_add_param ( nua_handle_home ( nh ) , sip - > sip_contact , exp_param ) ;
if ( sofia_test_pflag ( profile , PFLAG_MESSAGE_QUERY_ON_REGISTER ) | |
( reg_count = = 1 & & sofia_test_pflag ( profile , PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER ) ) ) {
if ( switch_event_create ( & s_mwi_event , SWITCH_EVENT_MESSAGE_QUERY ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_mwi_event , SWITCH_STACK_BOTTOM , " Message-Account " , " sip:%s@%s " , mwi_user , mwi_host ) ;
2011-11-10 10:48:06 -06:00
switch_event_add_header_string ( s_mwi_event , SWITCH_STACK_BOTTOM , " VM-Sofia-Pofile " , profile - > name ) ;
2011-08-17 19:34:22 -05:00
switch_event_add_header_string ( s_mwi_event , SWITCH_STACK_BOTTOM , " VM-Call-ID " , call_id ) ;
}
2009-04-24 14:33:54 +00:00
}
2010-07-27 22:08:47 -05:00
2011-08-17 19:34:22 -05:00
if ( sofia_test_pflag ( profile , PFLAG_PRESENCE_ON_REGISTER ) | |
( reg_count = = 1 & & sofia_test_pflag ( profile , PFLAG_PRESENCE_ON_FIRST_REGISTER ) )
| | send_pres = = 1 | | ( reg_count = = 1 & & send_pres = = 2 ) ) {
2011-01-14 13:57:58 -06:00
2011-08-17 19:34:22 -05:00
if ( sofia_test_pflag ( profile , PFLAG_PRESENCE_PROBE_ON_REGISTER ) ) {
if ( switch_event_create ( & s_event , SWITCH_EVENT_PRESENCE_PROBE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " login " , profile - > name ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , sub_host ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " to " , " %s@%s " , to_user , sub_host ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
2011-10-24 18:54:22 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " presence-source " , " register " ) ;
2011-08-17 19:34:22 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " alt_event_type " , " dialog " ) ;
switch_event_fire ( & s_event ) ;
}
} else {
if ( switch_event_create ( & s_event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " login " , profile - > name ) ;
2011-10-24 18:54:22 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " presence-source " , " register " ) ;
2011-08-17 19:34:22 -05:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , sub_host ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , " unknown " ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " status " , " Registered " ) ;
switch_event_fire ( & s_event ) ;
}
2011-01-14 13:57:58 -06:00
}
2011-08-17 19:34:22 -05:00
}
} else {
2011-09-08 17:57:07 -04:00
const char * username = " unknown " ;
if ( auth_params ) {
username = switch_event_get_header ( auth_params , " sip_auth_username " ) ;
}
2011-08-17 19:34:22 -05:00
switch_core_del_registration ( to_user , reg_host , call_id ) ;
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_UNREGISTER ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , profile - > name ) ;
2011-09-08 17:57:07 -04:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " username " , username ) ;
2011-08-17 19:34:22 -05:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-user " , to_user ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " from-host " , reg_host ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " contact " , contact_str ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " call-id " , call_id ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %ld " , ( long ) exptime ) ;
2010-11-24 21:39:08 -06:00
}
2010-09-02 16:01:50 -05:00
}
2011-08-17 19:34:22 -05:00
}
2011-02-14 11:27:55 -06:00
2011-08-17 19:34:22 -05:00
switch_rfc822_date ( date , switch_micro_time_now ( ) ) ;
/* generate and respond a 200 OK */
if ( mod_sofia_globals . reg_deny_binding_fetch_and_no_lookup ) {
/* handle backwards compatibility - contacts will not be looked up but only copied from the request into the response
remove this condition later if nobody complains about the extra select of the below new behavior
also remove the parts in mod_sofia . h , sofia . c and sofia_reg . c that refer to reg_deny_binding_fetch_and_no_lookup */
nua_respond ( nh , SIP_200_OK , TAG_IF ( contact , SIPTAG_CONTACT ( sip - > sip_contact ) ) , TAG_IF ( path_val , SIPTAG_PATH_STR ( path_val ) ) ,
NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , SIPTAG_DATE_STR ( date ) , TAG_END ( ) ) ;
} else if ( ( contact_list = sofia_reg_find_reg_url_with_positive_expires_multi ( profile , from_user , reg_host ) ) ) {
/* all + 1 tag_i elements initialized as NULL - last one implies TAG_END() */
switch_zmalloc ( contact_tags , sizeof ( * contact_tags ) * ( contact_list - > count + 1 ) ) ;
i = 0 ;
for ( m = contact_list - > head ; m ; m = m - > next ) {
contact_tags [ i ] . t_tag = siptag_contact_str ;
contact_tags [ i ] . t_value = ( tag_value_t ) m - > val ;
+ + i ;
2008-05-16 18:40:09 +00:00
}
2011-08-17 19:34:22 -05:00
nua_respond ( nh , SIP_200_OK , TAG_IF ( path_val , SIPTAG_PATH_STR ( path_val ) ) ,
NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , SIPTAG_DATE_STR ( date ) , TAG_NEXT ( contact_tags ) ) ;
switch_safe_free ( contact_tags ) ;
switch_console_free_matches ( & contact_list ) ;
} else {
/* respond without any contacts */
nua_respond ( nh , SIP_200_OK , TAG_IF ( path_val , SIPTAG_PATH_STR ( path_val ) ) ,
NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , SIPTAG_DATE_STR ( date ) , TAG_END ( ) ) ;
2007-10-18 16:17:42 +00:00
}
2010-02-06 03:38:24 +00:00
2008-05-27 04:54:52 +00:00
2008-05-29 13:25:53 +00:00
if ( s_event ) {
switch_event_fire ( & s_event ) ;
2010-08-28 23:16:00 -04:00
}
if ( s_mwi_event ) {
switch_event_fire ( & s_mwi_event ) ;
2008-05-29 13:25:53 +00:00
}
2010-02-06 03:38:24 +00:00
2009-03-25 20:14:07 +00:00
switch_goto_int ( r , 1 , end ) ;
2007-03-31 19:01:33 +00:00
}
2009-03-25 20:14:07 +00:00
2010-02-06 03:38:24 +00:00
end :
2009-09-25 20:07:40 +00:00
switch_safe_free ( dup_mwi_account ) ;
2009-03-25 20:14:07 +00:00
if ( auth_params ) {
switch_event_destroy ( & auth_params ) ;
}
2010-02-06 03:38:24 +00:00
return ( uint8_t ) r ;
2007-03-31 19:01:33 +00:00
}
2008-05-27 04:54:52 +00:00
void sofia_reg_handle_sip_i_register ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip ,
2011-06-16 14:37:22 -05:00
sofia_dispatch_event_t * de ,
2008-05-27 04:54:52 +00:00
tagi_t tags [ ] )
2007-03-31 19:01:33 +00:00
{
char key [ 128 ] = " " ;
2007-05-14 22:04:28 +00:00
switch_event_t * v_event = NULL ;
2008-03-26 22:14:09 +00:00
char network_ip [ 80 ] ;
2008-05-13 23:22:21 +00:00
sofia_regtype_t type = REG_REGISTER ;
2008-05-20 16:41:57 +00:00
int network_port = 0 ;
2008-05-21 21:49:27 +00:00
char * is_nat = NULL ;
2008-07-03 15:01:46 +00:00
2010-11-11 10:49:02 -06:00
#if 0 /* This seems to cause undesirable effects so nevermind */
2010-09-03 14:11:06 -05:00
if ( sip - > sip_to & & sip - > sip_to - > a_url & & sip - > sip_to - > a_url - > url_host ) {
const char * to_host = sip - > sip_to - > a_url - > url_host ;
if ( profile - > reg_db_domain ) {
if ( ! sofia_glue_profile_exists ( to_host ) ) {
if ( sofia_glue_add_profile ( switch_core_strdup ( profile - > pool , to_host ) , profile ) = = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Auto-Adding Alias [%s] for profile [%s] \n " , to_host , profile - > name ) ;
}
}
}
}
2010-11-11 10:49:02 -06:00
# endif
2010-09-03 14:11:06 -05:00
2011-06-16 14:37:22 -05:00
sofia_glue_get_addr ( de - > data - > e_msg , network_ip , sizeof ( network_ip ) , & network_port ) ;
2008-05-20 16:41:57 +00:00
2011-08-17 19:34:22 -05:00
/* backwards compatibility */
if ( mod_sofia_globals . reg_deny_binding_fetch_and_no_lookup & & ! ( sip - > sip_contact & & sip - > sip_contact - > m_url ) ) {
2010-06-14 14:12:14 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " NO CONTACT! ip: %s, port: %i \n " , network_ip , network_port ) ;
2008-05-20 16:41:57 +00:00
nua_respond ( nh , 400 , " Missing Contact Header " , TAG_END ( ) ) ;
goto end ;
}
if ( ! ( profile - > mflags & MFLAG_REGISTER ) ) {
2011-06-16 14:37:22 -05:00
nua_respond ( nh , SIP_403_FORBIDDEN , NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , TAG_END ( ) ) ;
2008-05-20 16:41:57 +00:00
goto end ;
}
2009-02-09 17:56:38 +00:00
if ( sofia_test_pflag ( profile , PFLAG_AGGRESSIVE_NAT_DETECTION ) ) {
2008-07-03 15:01:46 +00:00
if ( sip & & sip - > sip_via ) {
const char * port = sip - > sip_via - > v_port ;
const char * host = sip - > sip_via - > v_host ;
2010-02-06 03:38:24 +00:00
2008-07-03 15:01:46 +00:00
if ( host & & sip - > sip_via - > v_received ) {
is_nat = " via received " ;
} else if ( host & & strcmp ( network_ip , host ) ) {
is_nat = " via host " ;
} else if ( port & & atoi ( port ) ! = network_port ) {
is_nat = " via port " ;
2008-06-27 21:38:59 +00:00
}
2010-10-22 11:22:07 -05:00
if ( ! is_nat & & sip - > sip_via - > v_port & &
atoi ( sip - > sip_via - > v_port ) = = 5060 & & network_port ! = 5060 ) {
is_nat = " via port " ;
}
2008-05-21 21:49:27 +00:00
}
2008-07-03 15:01:46 +00:00
}
2008-05-21 21:49:27 +00:00
2008-07-03 15:01:46 +00:00
if ( ! is_nat & & profile - > nat_acl_count ) {
uint32_t x = 0 ;
int ok = 1 ;
char * last_acl = NULL ;
const char * contact_host = NULL ;
2008-06-27 21:38:59 +00:00
2008-07-03 15:01:46 +00:00
if ( sip & & sip - > sip_contact & & sip - > sip_contact - > m_url ) {
contact_host = sip - > sip_contact - > m_url - > url_host ;
}
2008-05-27 04:54:52 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( contact_host ) ) {
2008-07-03 15:01:46 +00:00
for ( x = 0 ; x < profile - > nat_acl_count ; x + + ) {
last_acl = profile - > nat_acl [ x ] ;
if ( ! ( ok = switch_check_network_list_ip ( contact_host , last_acl ) ) ) {
break ;
2008-06-27 21:38:59 +00:00
}
2008-07-03 15:01:46 +00:00
}
2010-02-06 03:38:24 +00:00
2008-07-03 15:01:46 +00:00
if ( ok ) {
is_nat = last_acl ;
2008-05-21 21:49:27 +00:00
}
}
}
2010-02-06 03:38:24 +00:00
2008-05-20 16:41:57 +00:00
if ( profile - > reg_acl_count ) {
uint32_t x = 0 ;
int ok = 1 ;
char * last_acl = NULL ;
2008-05-13 23:22:21 +00:00
2008-05-27 04:54:52 +00:00
for ( x = 0 ; x < profile - > reg_acl_count ; x + + ) {
2008-05-13 23:22:21 +00:00
last_acl = profile - > reg_acl [ x ] ;
if ( ! ( ok = switch_check_network_list_ip ( network_ip , last_acl ) ) ) {
break ;
2008-03-26 22:14:09 +00:00
}
}
2008-05-27 04:54:52 +00:00
2009-02-09 17:56:38 +00:00
if ( ok & & ! sofia_test_pflag ( profile , PFLAG_BLIND_REG ) ) {
2008-05-13 23:22:21 +00:00
type = REG_AUTO_REGISTER ;
} else if ( ! ok ) {
2010-01-07 18:47:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " IP %s Rejected by register acl \" %s \" \n " , network_ip , profile - > reg_acl [ x ] ) ;
2011-06-16 14:37:22 -05:00
nua_respond ( nh , SIP_403_FORBIDDEN , NUTAG_WITH_THIS_MSG ( de - > data - > e_msg ) , TAG_END ( ) ) ;
2008-05-13 23:22:21 +00:00
goto end ;
}
2008-03-26 22:14:09 +00:00
}
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
if ( ! sip | | ! sip - > sip_request | | ! sip - > sip_request - > rq_method_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Received an invalid packet! \n " ) ;
2008-05-27 04:54:52 +00:00
nua_respond ( nh , SIP_500_INTERNAL_SERVER_ERROR , TAG_END ( ) ) ;
2008-03-05 20:31:18 +00:00
goto end ;
2007-03-31 19:01:33 +00:00
}
2010-02-06 03:38:24 +00:00
2009-12-02 01:58:05 +00:00
if ( is_nat & & profile - > local_network & & switch_check_network_list_ip ( network_ip , profile - > local_network ) ) {
2009-12-08 22:28:52 +00:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " IP %s is on local network, not seting NAT mode. \n " , network_ip ) ;
}
2009-11-16 21:14:38 +00:00
is_nat = NULL ;
}
2007-03-31 19:01:33 +00:00
2011-06-16 14:37:22 -05:00
sofia_reg_handle_register ( nua , profile , nh , sip , de , type , key , sizeof ( key ) , & v_event , is_nat ) ;
2010-02-06 03:38:24 +00:00
2007-05-14 22:04:28 +00:00
if ( v_event ) {
2009-10-08 15:29:06 +00:00
switch_event_destroy ( & v_event ) ;
2007-05-14 22:04:28 +00:00
}
2008-03-05 20:31:18 +00:00
2008-05-27 04:54:52 +00:00
end :
2008-03-05 20:31:18 +00:00
nua_handle_destroy ( nh ) ;
2007-03-31 19:01:33 +00:00
}
void sofia_reg_handle_sip_r_register ( int status ,
2008-05-20 22:28:34 +00:00
char const * phrase ,
2008-05-27 04:54:52 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip ,
2011-06-16 14:37:22 -05:00
sofia_dispatch_event_t * de ,
2008-05-27 04:54:52 +00:00
tagi_t tags [ ] )
2007-03-31 19:01:33 +00:00
{
2010-02-04 21:23:36 +00:00
if ( status > = 500 ) {
2009-11-05 05:01:41 +00:00
if ( sofia_private & & sofia_private - > gateway ) {
nua_handle_destroy ( sofia_private - > gateway - > nh ) ;
sofia_private - > gateway - > nh = NULL ;
2009-11-05 07:06:19 +00:00
} else {
nua_handle_destroy ( nh ) ;
2009-11-05 05:01:41 +00:00
}
}
2010-02-06 03:38:24 +00:00
2007-03-31 19:01:33 +00:00
if ( sofia_private & & sofia_private - > gateway ) {
2008-10-10 15:36:02 +00:00
reg_state_t ostate = sofia_private - > gateway - > state ;
2007-03-31 19:01:33 +00:00
switch ( status ) {
case 200 :
2008-10-07 22:18:40 +00:00
if ( sip & & sip - > sip_contact ) {
2008-10-07 21:55:58 +00:00
sip_contact_t * contact = sip - > sip_contact ;
const char * new_expires ;
uint32_t expi ;
if ( contact - > m_next ) {
2011-07-29 21:55:52 -05:00
char * full ;
for ( ; contact ; contact = contact - > m_next ) {
if ( ( full = sip_header_as_string ( nh - > nh_home , ( void * ) contact ) ) ) {
if ( switch_stristr ( sofia_private - > gateway - > register_contact , full ) ) {
break ;
}
su_free ( nh - > nh_home , full ) ;
}
}
2008-10-07 21:55:58 +00:00
}
2008-10-07 22:15:51 +00:00
if ( ! contact ) {
contact = sip - > sip_contact ;
}
2008-10-07 21:55:58 +00:00
if ( contact - > m_expires ) {
new_expires = contact - > m_expires ;
expi = ( uint32_t ) atoi ( new_expires ) ;
2010-02-06 03:38:24 +00:00
2009-05-19 15:17:44 +00:00
if ( expi > 0 & & expi ! = sofia_private - > gateway - > freq ) {
2008-10-07 21:55:58 +00:00
sofia_private - > gateway - > freq = expi ;
2009-06-04 20:00:53 +00:00
sofia_private - > gateway - > expires_str = switch_core_sprintf ( sofia_private - > gateway - > pool , " %d " , expi ) ;
if ( expi > 60 ) {
sofia_private - > gateway - > expires = switch_epoch_time_now ( NULL ) + ( expi - 15 ) ;
} else {
sofia_private - > gateway - > expires = switch_epoch_time_now ( NULL ) + ( expi - 2 ) ;
}
2008-10-07 21:55:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Changing expire time to %d by request of proxy %s \n " , expi , sofia_private - > gateway - > register_proxy ) ;
}
2007-03-31 19:01:33 +00:00
}
}
sofia_private - > gateway - > state = REG_STATE_REGISTER ;
break ;
case 100 :
break ;
default :
sofia_private - > gateway - > state = REG_STATE_FAILED ;
2009-12-02 20:47:46 +00:00
sofia_private - > gateway - > failure_status = status ;
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s Registration Failed with status %s [%d]. failure #%d \n " ,
2009-01-02 19:58:36 +00:00
sofia_private - > gateway - > name , switch_str_nil ( phrase ) , status , + + sofia_private - > gateway - > failures ) ;
2007-03-31 19:01:33 +00:00
break ;
}
2008-10-10 15:36:02 +00:00
if ( ostate ! = sofia_private - > gateway - > state ) {
2010-01-15 15:18:07 +00:00
sofia_reg_fire_custom_gateway_state_event ( sofia_private - > gateway , status , phrase ) ;
2008-10-10 15:36:02 +00:00
}
2007-03-31 19:01:33 +00:00
}
}
void sofia_reg_handle_sip_r_challenge ( int status ,
2007-12-04 00:21:32 +00:00
char const * phrase ,
2008-11-03 17:39:09 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private ,
2011-06-16 14:37:22 -05:00
switch_core_session_t * session , sofia_gateway_t * gateway , sip_t const * sip ,
sofia_dispatch_event_t * de , tagi_t tags [ ] )
2007-03-31 19:01:33 +00:00
{
sip_www_authenticate_t const * authenticate = NULL ;
char const * realm = NULL ;
char const * scheme = NULL ;
int indexnum ;
char * cur ;
char authentication [ 256 ] = " " ;
int ss_state ;
2008-07-17 13:36:02 +00:00
sofia_gateway_t * var_gateway = NULL ;
const char * gw_name = NULL ;
2009-03-28 02:16:34 +00:00
switch_channel_t * channel = NULL ;
const char * sip_auth_username = NULL ;
const char * sip_auth_password = NULL ;
2010-10-27 14:09:38 -05:00
char * dup_user = NULL ;
char * dup_pass = NULL ;
2009-03-28 02:27:20 +00:00
if ( session & & ( channel = switch_core_session_get_channel ( session ) ) ) {
2009-03-28 02:16:34 +00:00
sip_auth_username = switch_channel_get_variable ( channel , " sip_auth_username " ) ;
sip_auth_password = switch_channel_get_variable ( channel , " sip_auth_password " ) ;
}
2007-03-31 19:01:33 +00:00
2008-11-03 17:39:09 +00:00
if ( sofia_private & & * sofia_private - > auth_gateway_name ) {
gw_name = sofia_private - > auth_gateway_name ;
}
2007-03-31 19:01:33 +00:00
if ( session ) {
private_object_t * tech_pvt ;
2008-07-17 13:36:02 +00:00
2009-02-09 17:56:38 +00:00
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) & & sofia_test_flag ( tech_pvt , TFLAG_REFER ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Received reply from REFER \n " ) ;
2008-07-17 13:36:02 +00:00
goto end ;
}
2009-04-09 22:43:00 +00:00
gw_name = switch_channel_get_variable ( switch_core_session_get_channel ( session ) , " sip_use_gateway " ) ;
2008-07-17 13:36:02 +00:00
}
2007-03-31 19:01:33 +00:00
if ( sip - > sip_www_authenticate ) {
authenticate = sip - > sip_www_authenticate ;
} else if ( sip - > sip_proxy_authenticate ) {
authenticate = sip - > sip_proxy_authenticate ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Missing Authenticate Header! \n " ) ;
2008-07-17 13:36:02 +00:00
goto end ;
2007-03-31 19:01:33 +00:00
}
scheme = ( char const * ) authenticate - > au_scheme ;
if ( authenticate - > au_params ) {
for ( indexnum = 0 ; ( cur = ( char * ) authenticate - > au_params [ indexnum ] ) ; indexnum + + ) {
if ( ( realm = strstr ( cur , " realm= " ) ) ) {
realm + = 6 ;
break ;
}
}
}
2008-07-17 14:32:01 +00:00
if ( ! gateway ) {
if ( gw_name ) {
2010-02-06 03:38:24 +00:00
var_gateway = sofia_reg_find_gateway ( ( char * ) gw_name ) ;
2008-07-17 14:32:01 +00:00
}
if ( ! var_gateway & & realm ) {
char rb [ 512 ] = " " ;
char * p = ( char * ) realm ;
2010-02-06 03:38:24 +00:00
while ( ( * p = = ' " ' ) ) {
2008-07-17 14:32:01 +00:00
p + + ;
}
switch_set_string ( rb , p ) ;
if ( ( p = strchr ( rb , ' " ' ) ) ) {
* p = ' \0 ' ;
}
2009-11-15 03:14:06 +00:00
if ( ! ( var_gateway = sofia_reg_find_gateway ( rb ) ) ) {
var_gateway = sofia_reg_find_gateway_by_realm ( rb ) ;
}
2008-07-17 14:32:01 +00:00
}
if ( ! var_gateway & & sip & & sip - > sip_to ) {
var_gateway = sofia_reg_find_gateway ( sip - > sip_to - > a_url - > url_host ) ;
}
2010-02-06 03:38:24 +00:00
2008-07-17 14:32:01 +00:00
if ( var_gateway ) {
gateway = var_gateway ;
}
}
2010-10-27 14:09:38 -05:00
if ( ! gateway & & ! sip_auth_username & & sip & & sip - > sip_to & & sip - > sip_to - > a_url & & sip - > sip_to - > a_url - > url_user & & sip - > sip_to - > a_url - > url_host ) {
switch_xml_t x_user , x_param , x_params ;
switch_event_t * locate_params ;
switch_event_create ( & locate_params , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( locate_params ) ;
2011-12-15 13:22:14 -05:00
switch_event_add_header_string ( locate_params , SWITCH_STACK_BOTTOM , " action " , " reverse-auth-lookup " ) ;
2010-10-27 14:09:38 -05:00
if ( switch_xml_locate_user_merged ( " id " , sip - > sip_to - > a_url - > url_user , sip - > sip_to - > a_url - > url_host , NULL ,
& x_user , locate_params ) = = SWITCH_STATUS_SUCCESS ) {
if ( ( x_params = switch_xml_child ( x_user , " params " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " param " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr_soft ( x_param , " name " ) ;
const char * val = switch_xml_attr_soft ( x_param , " value " ) ;
if ( ! strcasecmp ( var , " reverse-auth-user " ) ) {
dup_user = strdup ( val ) ;
sip_auth_username = dup_user ;
} else if ( ! strcasecmp ( var , " reverse-auth-pass " ) ) {
dup_pass = strdup ( val ) ;
sip_auth_password = dup_pass ;
}
}
2010-02-06 03:38:24 +00:00
2010-10-27 14:09:38 -05:00
switch_xml_free ( x_user ) ;
}
}
2008-07-17 14:32:01 +00:00
2010-10-27 14:09:38 -05:00
switch_event_destroy ( & locate_params ) ;
}
2008-07-17 14:32:01 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( scheme & & realm ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " No scheme and realm! \n " ) ;
2008-07-17 13:36:02 +00:00
goto end ;
2007-03-31 19:01:33 +00:00
}
2009-03-28 01:50:36 +00:00
if ( sip_auth_username & & sip_auth_password ) {
switch_snprintf ( authentication , sizeof ( authentication ) , " %s:%s:%s:%s " , scheme , realm , sip_auth_username , sip_auth_password ) ;
} else if ( gateway ) {
switch_snprintf ( authentication , sizeof ( authentication ) , " %s:%s:%s:%s " , scheme , realm , gateway - > auth_username , gateway - > register_password ) ;
} else {
2011-03-14 11:54:08 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Cannot locate any authentication credentials to complete an authentication request for realm '%s' \n " , realm ) ;
2010-02-06 03:38:24 +00:00
goto cancel ;
2007-03-31 19:01:33 +00:00
}
2007-09-19 15:28:16 +00:00
2008-10-12 03:56:11 +00:00
if ( profile - > debug ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Authenticating '%s' with '%s'. \n " ,
2010-02-06 03:38:24 +00:00
( sip_auth_username & & sip_auth_password ) ? sip_auth_username : gateway - > auth_username , authentication ) ;
2008-10-12 03:56:11 +00:00
}
2007-03-31 19:01:33 +00:00
ss_state = nua_callstate_authenticating ;
tl_gets ( tags , NUTAG_CALLSTATE_REF ( ss_state ) , SIPTAG_WWW_AUTHENTICATE_REF ( authenticate ) , TAG_END ( ) ) ;
2009-03-28 01:50:36 +00:00
nua_authenticate ( nh , SIPTAG_EXPIRES_STR ( gateway ? gateway - > expires_str : " 3600 " ) , NUTAG_AUTH ( authentication ) , TAG_END ( ) ) ;
2007-12-04 00:21:32 +00:00
2008-07-17 13:36:02 +00:00
goto end ;
2007-04-20 16:05:37 +00:00
2008-05-27 04:54:52 +00:00
cancel :
2007-12-04 00:21:32 +00:00
2007-04-20 16:05:37 +00:00
if ( session ) {
2008-01-28 07:26:10 +00:00
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_MANDATORY_IE_MISSING ) ;
2007-04-20 16:05:37 +00:00
} else {
nua_cancel ( nh , TAG_END ( ) ) ;
}
2008-05-27 04:54:52 +00:00
2010-02-06 03:38:24 +00:00
end :
2008-07-17 13:36:02 +00:00
2010-10-27 14:09:38 -05:00
switch_safe_free ( dup_user ) ;
switch_safe_free ( dup_pass ) ;
2008-07-17 13:36:02 +00:00
if ( var_gateway ) {
sofia_reg_release_gateway ( var_gateway ) ;
}
return ;
2007-03-31 19:01:33 +00:00
}
2009-11-12 03:52:07 +00:00
typedef struct {
char * nonce ;
switch_size_t nplen ;
int last_nc ;
} nonce_cb_t ;
static int sofia_reg_nonce_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
nonce_cb_t * cb = ( nonce_cb_t * ) pArg ;
switch_copy_string ( cb - > nonce , argv [ 0 ] , cb - > nplen ) ;
2009-11-23 14:57:56 +00:00
if ( argc = = 2 ) {
cb - > last_nc = zstr ( argv [ 1 ] ) ? 0 : atoi ( argv [ 1 ] ) ;
} else {
cb - > last_nc = 0 ;
}
2009-11-12 03:52:07 +00:00
return 0 ;
}
2010-02-02 21:04:41 +00:00
static int sofia_reg_regcount_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
int * ret = ( int * ) pArg ;
if ( argc = = 1 ) {
* ret = atoi ( argv [ 0 ] ) ;
}
return 0 ;
}
2010-02-06 03:38:24 +00:00
auth_res_t sofia_reg_parse_auth ( sofia_profile_t * profile ,
sip_authorization_t const * authorization ,
sip_t const * sip ,
2011-06-16 14:37:22 -05:00
sofia_dispatch_event_t * de ,
2009-03-25 20:14:07 +00:00
const char * regstr ,
2010-02-06 03:38:24 +00:00
char * np ,
size_t nplen ,
char * ip ,
switch_event_t * * v_event ,
long exptime , sofia_regtype_t regtype , const char * to_user , switch_event_t * * auth_params , long * reg_count )
2007-03-31 19:01:33 +00:00
{
int indexnum ;
const char * cur ;
su_md5_t ctx ;
char uridigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] ;
char bigdigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] ;
2007-04-20 18:06:06 +00:00
char * username , * realm , * nonce , * uri , * qop , * cnonce , * nc , * response , * input = NULL , * input2 = NULL ;
2007-03-31 19:01:33 +00:00
auth_res_t ret = AUTH_FORBIDDEN ;
2008-01-31 22:40:48 +00:00
int first = 0 ;
2007-08-21 14:48:16 +00:00
const char * passwd = NULL ;
const char * a1_hash = NULL ;
2009-09-25 20:07:40 +00:00
const char * mwi_account = NULL ;
2010-04-26 06:04:45 -04:00
switch_bool_t allow_empty_password = SWITCH_TRUE ;
2010-02-04 14:50:53 +00:00
const char * call_id = NULL ;
2009-10-27 06:14:00 +00:00
char * sql ;
2009-05-18 17:16:48 +00:00
char * number_alias = NULL ;
2011-05-23 17:15:32 -05:00
switch_xml_t user = NULL , param , uparams ;
2007-08-27 20:43:34 +00:00
char hexdigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] = " " ;
2007-10-30 14:32:00 +00:00
char * domain_name = NULL ;
2008-01-23 20:59:25 +00:00
switch_event_t * params = NULL ;
2008-06-04 16:04:08 +00:00
const char * auth_acl = NULL ;
2009-11-12 03:52:07 +00:00
long ncl = 0 ;
2010-01-07 18:47:53 +00:00
sip_unknown_t * un ;
2010-02-02 21:04:41 +00:00
const char * user_agent = NULL ;
const char * user_agent_filter = profile - > user_agent_filter ;
uint32_t max_registrations_perext = profile - > max_registrations_perext ;
2007-10-30 14:32:00 +00:00
2007-04-30 16:26:44 +00:00
username = realm = nonce = uri = qop = cnonce = nc = response = NULL ;
2008-05-27 04:54:52 +00:00
2007-03-31 19:01:33 +00:00
if ( authorization - > au_params ) {
for ( indexnum = 0 ; ( cur = authorization - > au_params [ indexnum ] ) ; indexnum + + ) {
char * var , * val , * p , * work ;
var = val = work = NULL ;
if ( ( work = strdup ( cur ) ) ) {
var = work ;
if ( ( val = strchr ( var , ' = ' ) ) ) {
* val + + = ' \0 ' ;
while ( * val = = ' " ' ) {
* val + + = ' \0 ' ;
}
if ( ( p = strchr ( val , ' " ' ) ) ) {
* p = ' \0 ' ;
}
2007-04-20 18:06:06 +00:00
if ( ! strcasecmp ( var , " username " ) ) {
username = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " realm " ) ) {
realm = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " nonce " ) ) {
2007-03-31 19:01:33 +00:00
nonce = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " uri " ) ) {
uri = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " qop " ) ) {
qop = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " cnonce " ) ) {
cnonce = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " response " ) ) {
response = strdup ( val ) ;
} else if ( ! strcasecmp ( var , " nc " ) ) {
nc = strdup ( val ) ;
}
}
free ( work ) ;
}
}
}
2008-01-31 22:40:48 +00:00
if ( ! ( username & & realm & & nonce & & uri & & response ) ) {
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Authorization header! \n " ) ;
2008-01-16 15:06:33 +00:00
ret = AUTH_STALE ;
2007-03-31 19:01:33 +00:00
goto end ;
}
2008-05-27 04:54:52 +00:00
2008-01-12 19:15:05 +00:00
/* Optional check that auth name == SIP username */
2009-02-09 17:56:38 +00:00
if ( ( regtype = = REG_REGISTER ) & & sofia_test_pflag ( profile , PFLAG_CHECKUSER ) ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( username ) | | zstr ( to_user ) | | strcasecmp ( to_user , username ) ) {
2008-01-12 19:15:05 +00:00
/* Names don't match, so fail */
2009-11-17 00:12:54 +00:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SIP username %s does not match auth username \n " , switch_str_nil ( to_user ) ) ;
}
2008-01-12 19:15:05 +00:00
goto end ;
}
}
2007-03-31 19:01:33 +00:00
2010-02-02 21:04:41 +00:00
user_agent = ( sip & & sip - > sip_user_agent ) ? sip - > sip_user_agent - > g_string : " unknown " ;
2009-10-23 16:03:42 +00:00
if ( zstr ( np ) ) {
2009-11-12 03:52:07 +00:00
nonce_cb_t cb = { 0 } ;
long nc_long = 0 ;
2007-08-21 14:48:16 +00:00
first = 1 ;
2010-02-06 03:38:24 +00:00
2009-10-28 16:55:29 +00:00
if ( nc ) {
2009-11-12 03:52:07 +00:00
nc_long = strtoul ( nc , 0 , 16 ) ;
sql = switch_mprintf ( " select nonce,last_nc from sip_authentication where nonce='%q' and last_nc < %lu " , nonce , nc_long ) ;
2009-10-28 16:55:29 +00:00
} else {
sql = switch_mprintf ( " select nonce from sip_authentication where nonce='%q' " , nonce ) ;
}
2009-11-12 03:52:07 +00:00
cb . nonce = np ;
cb . nplen = nplen ;
2010-02-06 03:38:24 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2010-05-04 09:50:55 -05:00
sofia_glue_execute_sql_callback ( profile , profile - > ireg_mutex , sql , sofia_reg_nonce_callback , & cb ) ;
2009-11-12 03:52:07 +00:00
free ( sql ) ;
//if (!sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, np, nplen)) {
if ( zstr ( np ) ) {
sql = switch_mprintf ( " delete from sip_authentication where nonce='%q' " , nonce ) ;
sofia_glue_execute_sql ( profile , & sql , SWITCH_TRUE ) ;
2007-03-31 19:01:33 +00:00
ret = AUTH_STALE ;
goto end ;
}
2009-11-12 03:52:07 +00:00
if ( reg_count ) {
* reg_count = cb . last_nc + 1 ;
}
2008-05-27 04:54:52 +00:00
}
2008-10-02 17:10:05 +00:00
switch_event_create ( & params , SWITCH_EVENT_REQUEST_PARAMS ) ;
2008-01-23 20:59:25 +00:00
switch_assert ( params ) ;
2008-01-24 11:56:57 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " action " , " sip_auth " ) ;
2008-01-24 22:09:39 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_profile " , profile - > name ) ;
2010-02-02 21:04:41 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_user_agent " , user_agent ) ;
2008-01-24 22:09:39 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_username " , username ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_realm " , realm ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_nonce " , nonce ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_uri " , uri ) ;
2008-10-14 22:13:49 +00:00
if ( sip - > sip_contact ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_contact_user " , sip - > sip_contact - > m_url - > url_user ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_contact_host " , sip - > sip_contact - > m_url - > url_host ) ;
}
if ( sip - > sip_to ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_to_user " , sip - > sip_to - > a_url - > url_user ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_to_host " , sip - > sip_to - > a_url - > url_host ) ;
if ( sip - > sip_to - > a_url - > url_port ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_to_port " , sip - > sip_to - > a_url - > url_port ) ;
}
}
if ( sip - > sip_from ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_from_user " , sip - > sip_from - > a_url - > url_user ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_from_host " , sip - > sip_from - > a_url - > url_host ) ;
if ( sip - > sip_from - > a_url - > url_port ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_from_port " , sip - > sip_from - > a_url - > url_port ) ;
}
}
if ( sip - > sip_request ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_request_user " , sip - > sip_request - > rq_url - > url_user ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_request_host " , sip - > sip_request - > rq_url - > url_host ) ;
if ( sip - > sip_request - > rq_url - > url_port ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_request_port " , sip - > sip_request - > rq_url - > url_port ) ;
}
}
2010-01-07 18:47:53 +00:00
for ( un = sip - > sip_unknown ; un ; un = un - > un_next ) {
if ( ! strncasecmp ( un - > un_name , " X- " , 2 ) ) {
if ( ! zstr ( un - > un_value ) ) {
2010-01-21 00:12:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG10 , " adding %s => %s to xml_curl request \n " , un - > un_name , un - > un_value ) ;
2010-01-07 18:47:53 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , un - > un_name , un - > un_value ) ;
}
} else {
2010-01-21 00:12:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG10 , " skipping %s => %s from xml_curl request \n " , un - > un_name , un - > un_value ) ;
2010-01-07 18:47:53 +00:00
}
}
2008-05-27 04:54:52 +00:00
if ( qop ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_qop " , qop ) ;
}
if ( cnonce ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_cnonce " , cnonce ) ;
}
if ( nc ) {
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_nc " , nc ) ;
}
2008-01-24 22:09:39 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_response " , response ) ;
2008-01-31 22:40:48 +00:00
2008-01-24 22:09:39 +00:00
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " sip_auth_method " , ( sip & & sip - > sip_request ) ? sip - > sip_request - > rq_method_name : NULL ) ;
2009-03-25 20:14:07 +00:00
if ( auth_params ) {
switch_event_dup ( auth_params , params ) ;
}
2008-05-27 04:54:52 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( profile - > reg_domain ) ) {
2007-10-30 14:32:00 +00:00
domain_name = profile - > reg_domain ;
} else {
domain_name = realm ;
}
2008-05-27 04:54:52 +00:00
2011-05-23 17:15:32 -05:00
if ( switch_xml_locate_user_merged ( " id " , zstr ( username ) ? " nobody " : username , domain_name , ip , & user , params ) ! = SWITCH_STATUS_SUCCESS ) {
2008-10-11 05:42:52 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Can't find user [%s@%s] \n "
2008-07-22 15:07:16 +00:00
" You must define a domain called '%s' in your directory and add a user with the id= \" %s \" attribute \n "
2010-02-06 03:38:24 +00:00
" and you must configure your device to use the proper domain in it's authentication credentials. \n " , username , domain_name ,
domain_name , username ) ;
2008-07-22 15:07:16 +00:00
2007-08-21 14:48:16 +00:00
ret = AUTH_FORBIDDEN ;
goto end ;
2009-02-27 16:03:22 +00:00
} else {
const char * type = switch_xml_attr ( user , " type " ) ;
if ( type & & ! strcasecmp ( type , " pointer " ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cant register a pointer. \n " ) ;
ret = AUTH_FORBIDDEN ;
goto end ;
}
2007-08-21 14:48:16 +00:00
}
2010-02-06 03:38:24 +00:00
2009-05-18 17:16:48 +00:00
if ( ! ( number_alias = ( char * ) switch_xml_attr ( user , " number-alias " ) ) ) {
2009-10-23 16:03:42 +00:00
number_alias = zstr ( username ) ? " nobody " : username ;
2007-10-12 17:12:31 +00:00
}
2011-05-23 17:15:32 -05:00
if ( ! ( uparams = switch_xml_child ( user , " params " ) ) ) {
2007-12-10 23:48:54 +00:00
ret = AUTH_OK ;
goto skip_auth ;
2011-05-23 17:15:32 -05:00
} else {
2007-12-10 23:48:54 +00:00
for ( param = switch_xml_child ( uparams , " param " ) ; param ; param = param - > next ) {
const char * var = switch_xml_attr_soft ( param , " name " ) ;
const char * val = switch_xml_attr_soft ( param , " value " ) ;
2008-05-27 04:54:52 +00:00
2008-08-12 18:28:13 +00:00
if ( ! strcasecmp ( var , " sip-forbid-register " ) & & switch_true ( val ) ) {
ret = AUTH_FORBIDDEN ;
goto end ;
}
2007-12-10 23:48:54 +00:00
if ( ! strcasecmp ( var , " password " ) ) {
passwd = val ;
}
2008-05-27 04:54:52 +00:00
2008-06-04 16:13:15 +00:00
if ( ! strcasecmp ( var , " auth-acl " ) ) {
2008-06-04 16:04:08 +00:00
auth_acl = val ;
}
2007-12-10 23:48:54 +00:00
if ( ! strcasecmp ( var , " a1-hash " ) ) {
a1_hash = val ;
}
2009-09-25 20:07:40 +00:00
if ( ! strcasecmp ( var , " mwi-account " ) ) {
mwi_account = val ;
}
2010-04-26 06:04:45 -04:00
if ( ! strcasecmp ( var , " allow-empty-password " ) ) {
allow_empty_password = switch_true ( val ) ;
}
2010-02-02 21:04:41 +00:00
if ( ! strcasecmp ( var , " user-agent-filter " ) ) {
user_agent_filter = val ;
}
if ( ! strcasecmp ( var , " max-registrations-per-extension " ) ) {
max_registrations_perext = atoi ( val ) ;
}
2007-04-20 18:06:06 +00:00
}
2007-08-21 14:48:16 +00:00
}
2007-04-30 16:26:44 +00:00
2008-06-04 16:04:08 +00:00
if ( auth_acl ) {
if ( ! switch_check_network_list_ip ( ip , auth_acl ) ) {
2010-09-29 15:47:58 -05:00
int network_ip_is_proxy = 0 ;
uint32_t x = 0 ;
2010-01-07 18:47:53 +00:00
char * last_acl = NULL ;
if ( profile - > proxy_acl_count = = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " IP %s Rejected by user acl [%s] and no proxy acl present \n " , ip , auth_acl ) ;
ret = AUTH_FORBIDDEN ;
goto end ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " IP %s Rejected by user acl [%s] checking proxy ACLs now \n " , ip , auth_acl ) ;
}
/* Check if network_ip is a proxy allowed to send us calls */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %d acls to check for proxy \n " , profile - > proxy_acl_count ) ;
2010-02-06 03:38:24 +00:00
2010-01-07 18:47:53 +00:00
for ( x = 0 ; x < profile - > proxy_acl_count ; x + + ) {
last_acl = profile - > proxy_acl [ x ] ;
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " checking %s against acl %s \n " , ip , last_acl ) ;
2010-01-07 18:47:53 +00:00
if ( switch_check_network_list_ip ( ip , last_acl ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s is a proxy according to the %s acl \n " , ip , last_acl ) ;
2010-01-07 18:47:53 +00:00
network_ip_is_proxy = 1 ;
break ;
}
}
/*
* if network_ip is a proxy allowed to send traffic , check for auth
* ip header and see if it matches against the auth acl
*/
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " network ip is a proxy [%d] \n " , network_ip_is_proxy ) ;
if ( network_ip_is_proxy ) {
int x_auth_ip = 0 ;
for ( un = sip - > sip_unknown ; un ; un = un - > un_next ) {
if ( ! strcasecmp ( un - > un_name , " X-AUTH-IP " ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " found auth ip [%s] header of [%s] \n " , un - > un_name , un - > un_value ) ;
2010-01-07 18:47:53 +00:00
if ( ! zstr ( un - > un_value ) ) {
if ( ! switch_check_network_list_ip ( un - > un_value , auth_acl ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " IP %s Rejected by user acl %s \n " , un - > un_value , auth_acl ) ;
ret = AUTH_FORBIDDEN ;
goto end ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
2010-02-06 03:38:24 +00:00
" IP %s allowed by acl %s, checking credentials \n " , un - > un_value , auth_acl ) ;
2010-01-07 18:47:53 +00:00
x_auth_ip = 1 ;
break ;
}
}
}
}
if ( ! x_auth_ip ) {
ret = AUTH_FORBIDDEN ;
goto end ;
}
}
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " IP [%s] passed ACL check [%s] \n " , ip , auth_acl ) ;
2008-06-04 16:04:08 +00:00
}
}
2010-02-06 03:38:24 +00:00
2010-04-26 06:04:45 -04:00
if ( ! allow_empty_password & & zstr ( passwd ) & & zstr ( a1_hash ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Empty password denied for user %s@%s \n " , username , domain_name ) ;
ret = AUTH_FORBIDDEN ;
goto end ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( passwd ) & & zstr ( a1_hash ) ) {
2007-09-19 18:39:46 +00:00
ret = AUTH_OK ;
2007-12-10 23:48:54 +00:00
goto skip_auth ;
2007-09-19 18:39:46 +00:00
}
2010-02-06 03:38:24 +00:00
2007-09-19 18:39:46 +00:00
if ( ! a1_hash ) {
input = switch_mprintf ( " %s:%s:%s " , username , realm , passwd ) ;
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input ) ;
su_md5_hexdigest ( & ctx , hexdigest ) ;
su_md5_deinit ( & ctx ) ;
switch_safe_free ( input ) ;
a1_hash = hexdigest ;
2008-05-27 04:54:52 +00:00
2007-09-19 18:39:46 +00:00
}
2010-02-02 21:04:41 +00:00
if ( user_agent_filter ) {
if ( switch_regex_match ( user_agent , user_agent_filter ) = = SWITCH_STATUS_SUCCESS ) {
if ( sofia_test_pflag ( profile , PFLAG_LOG_AUTH_FAIL ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" SIP auth OK (REGISTER) due to user-agent-filter. Filter \" %s \" User-Agent \" %s \" \n " , user_agent_filter , user_agent ) ;
2010-02-02 21:04:41 +00:00
}
} else {
ret = AUTH_FORBIDDEN ;
if ( sofia_test_pflag ( profile , PFLAG_LOG_AUTH_FAIL ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING ,
" SIP auth failure (REGISTER) due to user-agent-filter. Filter \" %s \" User-Agent \" %s \" \n " , user_agent_filter ,
user_agent ) ;
2010-02-02 21:04:41 +00:00
}
goto end ;
}
}
2010-02-06 03:38:24 +00:00
if ( max_registrations_perext > 0 & & ( sip & & sip - > sip_contact & & ( sip - > sip_contact - > m_expires = = NULL | | atol ( sip - > sip_contact - > m_expires ) > 0 ) ) ) {
/* if expires is null still process */
/* expires == 0 means the phone is going to unregiser, so don't count against max */
2010-09-29 15:47:58 -05:00
uint32_t count = 0 ;
2010-02-04 14:50:53 +00:00
call_id = sip - > sip_call_id - > i_id ;
switch_assert ( call_id ) ;
2010-02-06 03:38:24 +00:00
2010-02-04 14:50:53 +00:00
sql = switch_mprintf ( " select count(sip_user) from sip_registrations where sip_user='%q' AND call_id <> '%q' " , username , call_id ) ;
2010-02-02 21:04:41 +00:00
switch_assert ( sql ! = NULL ) ;
sofia_glue_execute_sql_callback ( profile , NULL , sql , sofia_reg_regcount_callback , & count ) ;
free ( sql ) ;
2010-02-06 03:38:24 +00:00
if ( count + 1 > max_registrations_perext ) {
2010-02-02 21:04:41 +00:00
ret = AUTH_FORBIDDEN ;
if ( sofia_test_pflag ( profile , PFLAG_LOG_AUTH_FAIL ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING ,
" SIP auth failure (REGISTER) due to reaching max allowed registrations. Count: %d \n " , count ) ;
2010-02-02 21:04:41 +00:00
}
goto end ;
}
}
2010-02-06 03:38:24 +00:00
2008-05-27 04:54:52 +00:00
for_the_sake_of_interop :
2007-09-19 18:39:46 +00:00
if ( ( input = switch_mprintf ( " %s:%q " , regstr , uri ) ) ) {
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input ) ;
su_md5_hexdigest ( & ctx , uridigest ) ;
su_md5_deinit ( & ctx ) ;
}
2008-05-27 04:54:52 +00:00
if ( nc & & cnonce & & qop ) {
2009-07-23 17:48:36 +00:00
input2 = switch_mprintf ( " %s:%s:%s:%s:%s:%s " , a1_hash , nonce , nc , cnonce , qop , uridigest ) ;
2008-05-27 04:54:52 +00:00
} else {
2009-07-23 17:48:36 +00:00
input2 = switch_mprintf ( " %s:%s:%s " , a1_hash , nonce , uridigest ) ;
2008-05-27 04:54:52 +00:00
}
2007-09-19 18:39:46 +00:00
2009-10-28 16:55:29 +00:00
if ( input2 ) {
memset ( & ctx , 0 , sizeof ( ctx ) ) ;
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input2 ) ;
su_md5_hexdigest ( & ctx , bigdigest ) ;
su_md5_deinit ( & ctx ) ;
}
2008-01-31 22:40:48 +00:00
2009-10-28 16:55:29 +00:00
if ( input2 & & ! strcasecmp ( bigdigest , response ) ) {
2008-05-27 04:54:52 +00:00
ret = AUTH_OK ;
} else {
if ( ( profile - > ndlb & PFLAG_NDLB_BROKEN_AUTH_HASH ) & & strcasecmp ( regstr , " REGISTER " ) & & strcasecmp ( regstr , " INVITE " ) ) {
/* some clients send an ACK with the method 'INVITE' in the hash which will break auth so we will
try again with INVITE so we don ' t get people complaining to us when someone else ' s client has a bug . . . . . .
*/
switch_safe_free ( input ) ;
switch_safe_free ( input2 ) ;
regstr = " INVITE " ;
goto for_the_sake_of_interop ;
}
2008-01-31 22:40:48 +00:00
2008-05-27 04:54:52 +00:00
ret = AUTH_FORBIDDEN ;
}
2009-10-29 14:33:48 +00:00
2009-10-29 08:35:53 +00:00
switch_safe_free ( input2 ) ;
2008-05-27 04:54:52 +00:00
skip_auth :
2011-12-16 14:31:15 -05:00
if ( first & & ( ret = = AUTH_OK | | ret = = AUTH_RENEWED ) ) {
2007-11-02 19:19:19 +00:00
if ( v_event ) {
2009-03-24 23:44:03 +00:00
switch_event_create_plain ( v_event , SWITCH_EVENT_REQUEST_PARAMS ) ;
2007-11-02 19:19:19 +00:00
}
2009-03-24 23:44:03 +00:00
2010-02-06 03:38:24 +00:00
2007-11-02 17:34:14 +00:00
if ( v_event & & * v_event ) {
2009-06-19 20:49:18 +00:00
short int xparams_type [ 6 ] ;
switch_xml_t xparams [ 6 ] ;
2007-12-10 23:48:54 +00:00
int i = 0 ;
2009-05-18 17:16:48 +00:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " sip_number_alias " , number_alias ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " sip_auth_username " , username ) ;
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " sip_auth_realm " , realm ) ;
2009-05-18 17:16:48 +00:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " number_alias " , number_alias ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " user_name " , username ) ;
2009-01-21 22:57:58 +00:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " domain_name " , domain_name ) ;
2008-05-27 04:54:52 +00:00
2009-09-25 20:07:40 +00:00
if ( mwi_account ) {
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , " mwi-account " , mwi_account ) ;
}
2010-02-06 03:38:24 +00:00
2010-09-09 15:37:41 -04:00
if ( ( uparams = switch_xml_child ( user , " params " ) ) ) {
2009-06-19 20:49:18 +00:00
xparams_type [ i ] = 0 ;
2010-09-09 15:37:41 -04:00
xparams [ i + + ] = uparams ;
2009-06-19 20:49:18 +00:00
}
2010-09-09 15:37:41 -04:00
if ( ( uparams = switch_xml_child ( user , " variables " ) ) ) {
2009-06-19 20:49:18 +00:00
xparams_type [ i ] = 1 ;
2010-09-09 15:37:41 -04:00
xparams [ i + + ] = uparams ;
2009-06-19 20:49:18 +00:00
}
if ( i < = 6 ) {
2007-12-10 23:48:54 +00:00
int j = 0 ;
2010-09-09 15:37:41 -04:00
const char * gw_val = NULL ;
2007-12-10 23:48:54 +00:00
for ( j = 0 ; j < i ; j + + ) {
2010-02-06 03:38:24 +00:00
for ( param = switch_xml_child ( xparams [ j ] , ( xparams_type [ j ] ? " variable " : " param " ) ) ; param ; param = param - > next ) {
2007-12-10 23:48:54 +00:00
const char * var = switch_xml_attr_soft ( param , " name " ) ;
const char * val = switch_xml_attr_soft ( param , " value " ) ;
2010-02-06 03:38:24 +00:00
if ( ! zstr ( var ) & & ! zstr ( val ) & & ( xparams_type [ j ] = = 1 | | ! strncasecmp ( var , " sip- " , 4 ) | | ! strcasecmp ( var , " register-gateway " ) ) ) {
2010-09-09 15:37:41 -04:00
if ( profile - > debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " event_add_header -> '%s' = '%s' \n " , var , val ) ;
2009-06-19 20:49:18 +00:00
}
2010-09-09 15:37:41 -04:00
switch_event_add_header_string ( * v_event , SWITCH_STACK_BOTTOM , var , val ) ;
}
}
}
if ( ( gw_val = switch_event_get_header ( * v_event , " register-gateway " ) ) ) {
sofia_gateway_t * gateway_ptr = NULL ;
if ( ! strcasecmp ( gw_val , " all " ) ) {
switch_xml_t gateways_tag , gateway_tag ;
if ( ( gateways_tag = switch_xml_child ( user , " gateways " ) ) ) {
for ( gateway_tag = switch_xml_child ( gateways_tag , " gateway " ) ; gateway_tag ; gateway_tag = gateway_tag - > next ) {
char * name = ( char * ) switch_xml_attr_soft ( gateway_tag , " name " ) ;
if ( zstr ( name ) ) {
name = " anonymous " ;
}
2008-05-27 04:54:52 +00:00
2010-09-09 15:37:41 -04:00
if ( ( gateway_ptr = sofia_reg_find_gateway ( name ) ) ) {
reg_state_t ostate = gateway_ptr - > state ;
gateway_ptr - > retry = 0 ;
if ( exptime ) {
gateway_ptr - > state = REG_STATE_UNREGED ;
} else {
gateway_ptr - > state = REG_STATE_UNREGISTER ;
2007-12-10 23:48:54 +00:00
}
2010-09-09 15:37:41 -04:00
if ( ostate ! = gateway_ptr - > state ) {
sofia_reg_fire_custom_gateway_state_event ( gateway_ptr , 0 , NULL ) ;
2007-11-02 19:19:19 +00:00
}
2010-09-09 15:37:41 -04:00
sofia_reg_release_gateway ( gateway_ptr ) ;
}
2007-11-02 19:19:19 +00:00
2010-09-09 15:37:41 -04:00
}
}
} else {
int x , argc ;
char * mydata , * argv [ 50 ] ;
mydata = strdup ( gw_val ) ;
switch_assert ( mydata ! = NULL ) ;
argc = switch_separate_string ( mydata , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
for ( x = 0 ; x < argc ; x + + ) {
if ( ( gateway_ptr = sofia_reg_find_gateway ( ( char * ) argv [ x ] ) ) ) {
reg_state_t ostate = gateway_ptr - > state ;
gateway_ptr - > retry = 0 ;
if ( exptime ) {
gateway_ptr - > state = REG_STATE_UNREGED ;
} else {
gateway_ptr - > state = REG_STATE_UNREGISTER ;
}
if ( ostate ! = gateway_ptr - > state ) {
sofia_reg_fire_custom_gateway_state_event ( gateway_ptr , 0 , NULL ) ;
2007-12-10 23:48:54 +00:00
}
2010-09-09 15:37:41 -04:00
sofia_reg_release_gateway ( gateway_ptr ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Gateway '%s' not found. \n " , argv [ x ] ) ;
2007-09-18 17:31:36 +00:00
}
}
2010-09-09 15:37:41 -04:00
free ( mydata ) ;
2007-04-30 16:26:44 +00:00
}
}
}
}
2007-08-21 14:48:16 +00:00
}
2008-05-27 04:54:52 +00:00
end :
2008-01-23 20:59:25 +00:00
2009-10-28 16:55:29 +00:00
if ( nc & & cnonce & & qop ) {
2009-11-12 03:52:07 +00:00
ncl = strtoul ( nc , 0 , 16 ) ;
2009-10-28 16:55:29 +00:00
2009-10-30 11:09:53 +00:00
# if defined(_WIN32) && !defined(_WIN64)
2009-10-30 04:07:49 +00:00
# define LL_FMT "ll"
# else
# define LL_FMT "l"
# endif
2010-02-06 03:38:24 +00:00
sql = switch_mprintf ( " update sip_authentication set expires='% " LL_FMT " u',last_nc=%lu where nonce='%s' " ,
2009-11-12 03:52:07 +00:00
switch_epoch_time_now ( NULL ) + ( profile - > nonce_ttl ? profile - > nonce_ttl : exptime + 10 ) , ncl , nonce ) ;
2009-10-28 16:55:29 +00:00
switch_assert ( sql ! = NULL ) ;
2009-11-12 03:52:07 +00:00
sofia_glue_actually_execute_sql ( profile , sql , profile - > ireg_mutex ) ;
2009-10-28 16:55:29 +00:00
switch_safe_free ( sql ) ;
2011-12-16 14:31:15 -05:00
if ( ret = = AUTH_OK )
ret = AUTH_RENEWED ;
2009-10-28 16:55:29 +00:00
}
2008-01-23 20:59:25 +00:00
switch_event_destroy ( & params ) ;
2011-05-23 17:15:32 -05:00
if ( user ) {
switch_xml_free ( user ) ;
2007-08-28 17:08:32 +00:00
}
2008-01-23 20:59:25 +00:00
2007-03-31 19:01:33 +00:00
switch_safe_free ( input ) ;
2007-04-20 18:06:06 +00:00
switch_safe_free ( username ) ;
switch_safe_free ( realm ) ;
2007-03-31 19:01:33 +00:00
switch_safe_free ( nonce ) ;
switch_safe_free ( uri ) ;
switch_safe_free ( qop ) ;
switch_safe_free ( cnonce ) ;
switch_safe_free ( nc ) ;
switch_safe_free ( response ) ;
2009-11-12 03:52:07 +00:00
if ( reg_count & & ! * reg_count ) {
2011-12-16 14:31:15 -05:00
if ( ( ret = = AUTH_OK | | ret = = AUTH_RENEWED ) ) {
2009-11-12 03:52:07 +00:00
if ( ncl ) {
* reg_count = ncl ;
} else {
* reg_count = 1 ;
}
} else {
* reg_count = 0 ;
}
}
2007-03-31 19:01:33 +00:00
return ret ;
}
2008-07-17 14:32:01 +00:00
sofia_gateway_t * sofia_reg_find_gateway__ ( const char * file , const char * func , int line , const char * key )
2007-03-31 19:01:33 +00:00
{
2007-04-29 01:16:49 +00:00
sofia_gateway_t * gateway = NULL ;
2007-03-31 19:01:33 +00:00
2007-04-01 01:16:16 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-04-29 01:16:49 +00:00
if ( ( gateway = ( sofia_gateway_t * ) switch_core_hash_find ( mod_sofia_globals . gateway_hash , key ) ) ) {
2009-02-09 17:56:38 +00:00
if ( ! sofia_test_pflag ( gateway - > profile , PFLAG_RUNNING ) | | gateway - > deleted ) {
2008-05-27 04:54:52 +00:00
gateway = NULL ;
2008-04-04 18:53:24 +00:00
goto done ;
2008-01-08 16:35:20 +00:00
}
2010-02-16 00:07:50 +00:00
if ( sofia_reg_gateway_rdlock__ ( file , func , line , gateway ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-29 01:16:49 +00:00
gateway = NULL ;
}
}
2008-04-04 18:53:24 +00:00
2008-05-27 04:54:52 +00:00
done :
2007-04-29 01:16:49 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
return gateway ;
}
2009-11-15 03:14:06 +00:00
sofia_gateway_t * sofia_reg_find_gateway_by_realm__ ( const char * file , const char * func , int line , const char * key )
{
sofia_gateway_t * gateway = NULL ;
switch_hash_index_t * hi ;
const void * var ;
2010-02-06 03:38:24 +00:00
void * val ;
2009-11-15 03:14:06 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
for ( hi = switch_hash_first ( NULL , mod_sofia_globals . gateway_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
switch_hash_this ( hi , & var , NULL , & val ) ;
2011-09-27 08:44:29 -05:00
if ( key & & ( gateway = ( sofia_gateway_t * ) val ) & & ! gateway - > deleted & & gateway - > register_realm & & ! strcasecmp ( gateway - > register_realm , key ) ) {
2010-05-21 14:40:36 -04:00
break ;
2009-11-15 03:14:06 +00:00
} else {
gateway = NULL ;
}
}
if ( gateway ) {
if ( ! sofia_test_pflag ( gateway - > profile , PFLAG_RUNNING ) | | gateway - > deleted ) {
gateway = NULL ;
goto done ;
}
if ( switch_thread_rwlock_tryrdlock ( gateway - > profile - > rwlock ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , NULL , SWITCH_LOG_ERROR , " Profile %s is locked \n " , gateway - > profile - > name ) ;
gateway = NULL ;
}
}
if ( gateway ) {
# ifdef SOFIA_DEBUG_RWLOCKS
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , SWITCH_LOG_ERROR , " XXXXXXXXXXXXXX GW LOCK %s \n " , gateway - > profile - > name ) ;
# endif
}
done :
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
return gateway ;
}
2010-02-16 00:07:50 +00:00
switch_status_t sofia_reg_gateway_rdlock__ ( const char * file , const char * func , int line , sofia_gateway_t * gateway )
{
switch_status_t status = sofia_glue_profile_rdlock__ ( file , func , line , gateway - > profile ) ;
# ifdef SOFIA_DEBUG_RWLOCKS
2010-02-16 17:34:32 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2010-02-16 00:07:50 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , SWITCH_LOG_ERROR , " XXXXXXXXXXXXXX GW LOCK %s \n " , gateway - > profile - > name ) ;
}
# endif
return status ;
}
2009-11-15 03:14:06 +00:00
2007-05-03 01:55:25 +00:00
void sofia_reg_release_gateway__ ( const char * file , const char * func , int line , sofia_gateway_t * gateway )
2007-04-29 01:16:49 +00:00
{
switch_thread_rwlock_unlock ( gateway - > profile - > rwlock ) ;
2007-05-03 01:55:25 +00:00
# ifdef SOFIA_DEBUG_RWLOCKS
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , SWITCH_LOG_ERROR , " XXXXXXXXXXXXXX GW UNLOCK %s \n " , gateway - > profile - > name ) ;
# endif
2007-04-29 01:16:49 +00:00
}
2010-03-25 00:28:56 +00:00
switch_status_t sofia_reg_add_gateway ( sofia_profile_t * profile , const char * key , sofia_gateway_t * gateway )
2007-03-31 19:01:33 +00:00
{
2007-04-30 20:35:35 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2010-03-25 00:28:56 +00:00
char * pkey = switch_mprintf ( " %s::%s " , profile - > name , key ) ;
2011-09-27 08:44:29 -05:00
sofia_gateway_t * gp ;
2007-04-30 20:35:35 +00:00
2011-06-16 14:32:08 -05:00
switch_mutex_lock ( profile - > gw_mutex ) ;
2010-03-25 00:28:56 +00:00
gateway - > next = profile - > gateways ;
profile - > gateways = gateway ;
2011-06-16 14:32:08 -05:00
switch_mutex_unlock ( profile - > gw_mutex ) ;
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2011-09-27 08:44:29 -05:00
if ( ( gp = switch_core_hash_find ( mod_sofia_globals . gateway_hash , key ) ) ) {
if ( gp - > deleted ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Removing deleted gateway from hash. \n " ) ;
switch_core_hash_delete ( mod_sofia_globals . gateway_hash , gp - > name ) ;
switch_core_hash_delete ( mod_sofia_globals . gateway_hash , pkey ) ;
switch_core_hash_delete ( mod_sofia_globals . gateway_hash , key ) ;
}
2007-04-30 20:35:35 +00:00
}
2010-03-25 00:28:56 +00:00
2011-09-27 08:44:29 -05:00
if ( ! switch_core_hash_find ( mod_sofia_globals . gateway_hash , key ) & & ! switch_core_hash_find ( mod_sofia_globals . gateway_hash , pkey ) ) {
status = switch_core_hash_insert ( mod_sofia_globals . gateway_hash , key , gateway ) ;
2010-02-18 22:39:08 +00:00
status = switch_core_hash_insert ( mod_sofia_globals . gateway_hash , pkey , gateway ) ;
2011-09-27 08:44:29 -05:00
} else {
status = SWITCH_STATUS_FALSE ;
2010-02-18 22:39:08 +00:00
}
2007-04-01 01:16:16 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
2010-02-18 22:39:08 +00:00
free ( pkey ) ;
2008-07-08 22:05:34 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2010-01-23 18:43:38 +00:00
switch_event_t * s_event ;
2008-07-08 22:05:34 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Added gateway '%s' to profile '%s' \n " , gateway - > name , gateway - > profile - > name ) ;
2010-01-23 18:43:38 +00:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_GATEWAY_ADD ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " Gateway " , gateway - > name ) ;
2010-01-23 19:08:44 +00:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , gateway - > profile - > name ) ;
2010-01-23 18:43:38 +00:00
switch_event_fire ( & s_event ) ;
}
2008-07-08 22:05:34 +00:00
}
2007-04-30 20:35:35 +00:00
return status ;
}
2007-03-31 19:01:33 +00:00
2008-01-27 05:02:52 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2008-01-27 05:02:52 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2008-07-03 19:12:26 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2008-01-27 05:02:52 +00:00
*/