Bug Summary

File:src/mod/endpoints/mod_sofia/sofia_reg.c
Location:line 3318, column 3
Description:Value stored to 'status' is never read

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Ken Rice, <krice at cometsig.com> (work sponsored by Comet Signaling LLC, CopperCom, Inc and Asteria Solutions Group, Inc)
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 * Bret McDanel <trixter AT 0xdecafbad.com>
30 * Marcel Barbulescu <marcelbarbulescu@gmail.com>
31 * David Knell <david.knell@telng.com>
32 * Eliot Gable <egable AT.AT broadvox.com>
33 * Leon de Rooij <leon@scarlet-internet.nl>
34 * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
35 * William King <william.king@quentustech.com>
36 *
37 * sofia_reg.c -- SOFIA SIP Endpoint (registration code)
38 *
39 */
40#include "mod_sofia.h"
41
42static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach)
43{
44 int ss_state = nua_callstate_authenticating;
45
46 if (gateway_ptr->nh) {
47 nua_handle_bind(gateway_ptr->nh, NULL((void*)0));
48 nua_handle_destroy(gateway_ptr->nh);
49 gateway_ptr->nh = NULL((void*)0);
50 sofia_private_free(gateway_ptr->sofia_private)if (gateway_ptr->sofia_private && ! gateway_ptr->
sofia_private->is_static) {free(gateway_ptr->sofia_private
);} gateway_ptr->sofia_private = ((void*)0);
;
51 }
52
53 gateway_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL((void*)0),
54 SIPTAG_CALL_ID_STR(gateway_ptr->uuid_str)siptag_call_id_str, tag_str_v(gateway_ptr->uuid_str),
55 SIPTAG_TO_STR(gateway_ptr->register_to)siptag_to_str, tag_str_v(gateway_ptr->register_to),
56 NUTAG_CALLSTATE_REF(ss_state)nutag_callstate_ref, tag_int_vr(&(ss_state)), SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from), TAG_END()(tag_type_t)0, (tag_value_t)0);
57 if (attach) {
58 if (!gateway_ptr->sofia_private) {
59 switch_zmalloc(gateway_ptr->sofia_private, sizeof(*gateway_ptr->sofia_private))(void)((((gateway_ptr->sofia_private = calloc(1, (sizeof(*
gateway_ptr->sofia_private))))) ? (void) (0) : __assert_fail
("(gateway_ptr->sofia_private = calloc(1, (sizeof(*gateway_ptr->sofia_private))))"
, "sofia_reg.c", 59, __PRETTY_FUNCTION__)),gateway_ptr->sofia_private
)
;
60 }
61
62 switch_set_string(gateway_ptr->sofia_private->gateway_name, gateway_ptr->name)switch_copy_string(gateway_ptr->sofia_private->gateway_name
, gateway_ptr->name, sizeof(gateway_ptr->sofia_private->
gateway_name))
;
63 nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
64 }
65}
66
67static void sofia_reg_new_sub_handle(sofia_gateway_subscription_t *gw_sub_ptr)
68{
69 sofia_gateway_t *gateway_ptr = gw_sub_ptr->gateway;
70 char *user_via = NULL((void*)0);
71 char *register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
72 int ss_state = nua_callstate_authenticating;
73
74
75 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
76 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
77 user_via = sofia_glue_create_external_via(NULL((void*)0), gateway_ptr->profile, gateway_ptr->register_transport);
78 }
79
80 if (gw_sub_ptr->nh) {
81 nua_handle_bind(gw_sub_ptr->nh, NULL((void*)0));
82 nua_handle_destroy(gw_sub_ptr->nh);
83 gw_sub_ptr->nh = NULL((void*)0);
84 sofia_private_free(gw_sub_ptr->sofia_private)if (gw_sub_ptr->sofia_private && ! gw_sub_ptr->
sofia_private->is_static) {free(gw_sub_ptr->sofia_private
);} gw_sub_ptr->sofia_private = ((void*)0);
;
85 }
86
87 gw_sub_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL((void*)0),
88 NUTAG_URL(gateway_ptr->register_proxy)nutag_url, urltag_url_v(gateway_ptr->register_proxy),
89 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
90 SIPTAG_TO_STR(gateway_ptr->register_to)siptag_to_str, tag_str_v(gateway_ptr->register_to),
91 NUTAG_CALLSTATE_REF(ss_state)nutag_callstate_ref, tag_int_vr(&(ss_state)), SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from), TAG_END()(tag_type_t)0, (tag_value_t)0);
92 if (!gw_sub_ptr->sofia_private) {
93 switch_zmalloc(gw_sub_ptr->sofia_private, sizeof(*gw_sub_ptr->sofia_private))(void)((((gw_sub_ptr->sofia_private = calloc(1, (sizeof(*gw_sub_ptr
->sofia_private))))) ? (void) (0) : __assert_fail ("(gw_sub_ptr->sofia_private = calloc(1, (sizeof(*gw_sub_ptr->sofia_private))))"
, "sofia_reg.c", 93, __PRETTY_FUNCTION__)),gw_sub_ptr->sofia_private
)
;
94 }
95
96 switch_set_string(gw_sub_ptr->sofia_private->gateway_name, gateway_ptr->name)switch_copy_string(gw_sub_ptr->sofia_private->gateway_name
, gateway_ptr->name, sizeof(gw_sub_ptr->sofia_private->
gateway_name))
;
97 nua_handle_bind(gw_sub_ptr->nh, gw_sub_ptr->sofia_private);
98
99 switch_safe_free(register_host)if (register_host) {free(register_host);register_host=((void*
)0);}
;
100 switch_safe_free(user_via)if (user_via) {free(user_via);user_via=((void*)0);};
101}
102
103static void sofia_reg_kill_sub(sofia_gateway_subscription_t *gw_sub_ptr)
104{
105 sofia_gateway_t *gateway_ptr = gw_sub_ptr->gateway;
106
107 sofia_private_free(gw_sub_ptr->sofia_private)if (gw_sub_ptr->sofia_private && ! gw_sub_ptr->
sofia_private->is_static) {free(gw_sub_ptr->sofia_private
);} gw_sub_ptr->sofia_private = ((void*)0);
;
108
109 if (gw_sub_ptr->nh) {
110 nua_handle_bind(gw_sub_ptr->nh, NULL((void*)0));
111 }
112
113 if (gw_sub_ptr->state != SUB_STATE_SUBED && gw_sub_ptr->state != SUB_STATE_UNSUBSCRIBE) {
114 if (gw_sub_ptr->nh) {
115 nua_handle_destroy(gw_sub_ptr->nh);
116 gw_sub_ptr->nh = NULL((void*)0);
117 }
118 return;
119 }
120
121 if (gw_sub_ptr->nh) {
122 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
122, ((void*)0)
, SWITCH_LOG_NOTICE, "UN-Subbing %s %s\n", gateway_ptr->name, gw_sub_ptr->event);
123 nua_unsubscribe(gw_sub_ptr->nh, NUTAG_URL(gw_sub_ptr->request_uri)nutag_url, urltag_url_v(gw_sub_ptr->request_uri), TAG_END()(tag_type_t)0, (tag_value_t)0);
124 }
125}
126
127static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
128{
129
130 if (!gateway_ptr->nh) {
131 return;
132 }
133
134 if (gateway_ptr->state == REG_STATE_REGED || gateway_ptr->state == REG_STATE_UNREGISTER) {
135 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
135, ((void*)0)
, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name);
136 nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url)nutag_url, urltag_url_v(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy)nutag_registrar, urltag_url_v(gateway_ptr->register_proxy), TAG_END()(tag_type_t)0, (tag_value_t)0);
137 } else {
138 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
138, ((void*)0)
, SWITCH_LOG_NOTICE, "Destroying registration handle for %s\n", gateway_ptr->name);
139 }
140
141 sofia_private_free(gateway_ptr->sofia_private)if (gateway_ptr->sofia_private && ! gateway_ptr->
sofia_private->is_static) {free(gateway_ptr->sofia_private
);} gateway_ptr->sofia_private = ((void*)0);
;
142 nua_handle_bind(gateway_ptr->nh, NULL((void*)0));
143 nua_handle_destroy(gateway_ptr->nh);
144 gateway_ptr->nh = NULL((void*)0);
145}
146
147void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase)
148{
149 switch_event_t *s_event;
150 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_STATE)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 150, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::gateway_state")
== SWITCH_STATUS_SUCCESS) {
151 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Gateway", gateway->name);
152 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "State", sofia_state_string(gateway->state));
153 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Ping-Status", sofia_gateway_status_name(gateway->status));
154 if (!zstr(phrase)_zstr(phrase)) {
155 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Phrase", phrase);
156 }
157 if (status) {
158 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Status", "%d", status);
159 }
160 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 160, &s_event, ((void*)0))
;
161 }
162}
163
164void sofia_reg_fire_custom_sip_user_state_event(sofia_profile_t *profile, const char *sip_user, const char *contact,
165 const char* from_user, const char* from_host, const char *call_id, sofia_sip_user_status_t status, int options_res, const char *phrase)
166{
167 switch_event_t *s_event;
168 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_SIP_USER_STATE)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 168, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::sip_user_state")
== SWITCH_STATUS_SUCCESS) {
169 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_contact", contact);
170 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
171 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_user", sip_user);
172 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", from_user);
173 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", from_host);
174 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
175 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Ping-Status", sofia_sip_user_status_name(status));
176 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Status", "%d", options_res);
177 if (!zstr(phrase)_zstr(phrase)) {
178 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Phrase", phrase);
179 }
180 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 180, &s_event, ((void*)0))
;
181 }
182}
183
184void sofia_reg_unregister(sofia_profile_t *profile)
185{
186 sofia_gateway_t *gateway_ptr;
187 sofia_gateway_subscription_t *gw_sub_ptr;
188
189 switch_mutex_lock(mod_sofia_globals.hash_mutex);
190 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
191
192 if (gateway_ptr->nh) {
193 nua_handle_bind(gateway_ptr->nh, NULL((void*)0));
194 }
195
196 if (gateway_ptr->state == REG_STATE_REGED) {
197 sofia_reg_kill_reg(gateway_ptr);
198 }
199
200 for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
201
202 if (gw_sub_ptr->state == SUB_STATE_SUBED) {
203 sofia_reg_kill_sub(gw_sub_ptr);
204 }
205 }
206
207 gateway_ptr->subscriptions = NULL((void*)0);
208 }
209 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
210}
211
212void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
213{
214 /* NOTE: A lot of the mechanism in place here for refreshing subscriptions is
215 * pretty much redundant, as the sofia stack takes it upon itself to
216 * refresh subscriptions on its own, based on the value of the Expires
217 * header (which we control in the outgoing subscription request)
218 */
219 sofia_gateway_t *gateway_ptr;
220
221 switch_mutex_lock(profile->gw_mutex);
222 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
223 sofia_gateway_subscription_t *gw_sub_ptr;
224
225 for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
226 sub_state_t ostate = gw_sub_ptr->state;
227
228 if (!now) {
229 gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED;
230 gw_sub_ptr->expires_str = "0";
231 }
232
233 //gateway_ptr->sub_state = gw_sub_ptr->state;
234
235 switch (ostate) {
236 case SUB_STATE_NOSUB:
237 break;
238 case SUB_STATE_SUBSCRIBE:
239 gw_sub_ptr->expires = now + gw_sub_ptr->freq;
240 gw_sub_ptr->state = SUB_STATE_SUBED;
241 break;
242 case SUB_STATE_UNSUBSCRIBE:
243 gw_sub_ptr->state = SUB_STATE_NOSUB;
244 sofia_reg_kill_sub(gw_sub_ptr);
245 break;
246 case SUB_STATE_UNSUBED:
247
248 sofia_reg_new_sub_handle(gw_sub_ptr);
249
250 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
250, ((void*)0)
, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name);
251
252 if (now) {
253 nua_subscribe(gw_sub_ptr->nh,
254 NUTAG_URL(gw_sub_ptr->request_uri)nutag_url, urltag_url_v(gw_sub_ptr->request_uri),
255 SIPTAG_EVENT_STR(gw_sub_ptr->event)siptag_event_str, tag_str_v(gw_sub_ptr->event),
256 TAG_IF(strcmp(gw_sub_ptr->content_type, "NO_CONTENT_TYPE"), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type))!(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(gw_sub_ptr->content_type) && __builtin_constant_p
("NO_CONTENT_TYPE") && (__s1_len = __builtin_strlen (
gw_sub_ptr->content_type), __s2_len = __builtin_strlen ("NO_CONTENT_TYPE"
), (!((size_t)(const void *)((gw_sub_ptr->content_type) + 1
) - (size_t)(const void *)(gw_sub_ptr->content_type) == 1)
|| __s1_len >= 4) && (!((size_t)(const void *)(("NO_CONTENT_TYPE"
) + 1) - (size_t)(const void *)("NO_CONTENT_TYPE") == 1) || __s2_len
>= 4)) ? __builtin_strcmp (gw_sub_ptr->content_type, "NO_CONTENT_TYPE"
) : (__builtin_constant_p (gw_sub_ptr->content_type) &&
((size_t)(const void *)((gw_sub_ptr->content_type) + 1) -
(size_t)(const void *)(gw_sub_ptr->content_type) == 1) &&
(__s1_len = __builtin_strlen (gw_sub_ptr->content_type), __s1_len
< 4) ? (__builtin_constant_p ("NO_CONTENT_TYPE") &&
((size_t)(const void *)(("NO_CONTENT_TYPE") + 1) - (size_t)(
const void *)("NO_CONTENT_TYPE") == 1) ? __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE") : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
("NO_CONTENT_TYPE"); int __result = (((const unsigned char *
) (const char *) (gw_sub_ptr->content_type))[0] - __s2[0])
; if (__s1_len > 0 && __result == 0) { __result = (
((const unsigned char *) (const char *) (gw_sub_ptr->content_type
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (gw_sub_ptr
->content_type))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (gw_sub_ptr->content_type))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p ("NO_CONTENT_TYPE") &&
((size_t)(const void *)(("NO_CONTENT_TYPE") + 1) - (size_t)(
const void *)("NO_CONTENT_TYPE") == 1) && (__s2_len =
__builtin_strlen ("NO_CONTENT_TYPE"), __s2_len < 4) ? (__builtin_constant_p
(gw_sub_ptr->content_type) && ((size_t)(const void
*)((gw_sub_ptr->content_type) + 1) - (size_t)(const void *
)(gw_sub_ptr->content_type) == 1) ? __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(gw_sub_ptr->content_type); int __result = (((const unsigned
char *) (const char *) ("NO_CONTENT_TYPE"))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ("NO_CONTENT_TYPE"))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("NO_CONTENT_TYPE"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("NO_CONTENT_TYPE"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE")))); })) ? tag_skip : siptag_accept_str
, tag_str_v(gw_sub_ptr->content_type)
,
257 SIPTAG_TO_STR(gateway_ptr->register_from)siptag_to_str, tag_str_v(gateway_ptr->register_from),
258 SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from),
259 SIPTAG_CONTACT_STR(gateway_ptr->register_contact)siptag_contact_str, tag_str_v(gateway_ptr->register_contact
)
,
260 SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str)siptag_expires_str, tag_str_v(gw_sub_ptr->expires_str), /* sofia stack bases its auto-refresh stuff on this */
261 TAG_NULL()(tag_type_t)0, (tag_value_t)0);
262 gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds;
263 } else {
264 nua_unsubscribe(gw_sub_ptr->nh,
265 NUTAG_URL(gw_sub_ptr->request_uri)nutag_url, urltag_url_v(gw_sub_ptr->request_uri),
266 SIPTAG_EVENT_STR(gw_sub_ptr->event)siptag_event_str, tag_str_v(gw_sub_ptr->event),
267 TAG_IF(strcmp(gw_sub_ptr->content_type, "NO_CONTENT_TYPE"), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type))!(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(gw_sub_ptr->content_type) && __builtin_constant_p
("NO_CONTENT_TYPE") && (__s1_len = __builtin_strlen (
gw_sub_ptr->content_type), __s2_len = __builtin_strlen ("NO_CONTENT_TYPE"
), (!((size_t)(const void *)((gw_sub_ptr->content_type) + 1
) - (size_t)(const void *)(gw_sub_ptr->content_type) == 1)
|| __s1_len >= 4) && (!((size_t)(const void *)(("NO_CONTENT_TYPE"
) + 1) - (size_t)(const void *)("NO_CONTENT_TYPE") == 1) || __s2_len
>= 4)) ? __builtin_strcmp (gw_sub_ptr->content_type, "NO_CONTENT_TYPE"
) : (__builtin_constant_p (gw_sub_ptr->content_type) &&
((size_t)(const void *)((gw_sub_ptr->content_type) + 1) -
(size_t)(const void *)(gw_sub_ptr->content_type) == 1) &&
(__s1_len = __builtin_strlen (gw_sub_ptr->content_type), __s1_len
< 4) ? (__builtin_constant_p ("NO_CONTENT_TYPE") &&
((size_t)(const void *)(("NO_CONTENT_TYPE") + 1) - (size_t)(
const void *)("NO_CONTENT_TYPE") == 1) ? __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE") : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
("NO_CONTENT_TYPE"); int __result = (((const unsigned char *
) (const char *) (gw_sub_ptr->content_type))[0] - __s2[0])
; if (__s1_len > 0 && __result == 0) { __result = (
((const unsigned char *) (const char *) (gw_sub_ptr->content_type
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (gw_sub_ptr
->content_type))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (gw_sub_ptr->content_type))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p ("NO_CONTENT_TYPE") &&
((size_t)(const void *)(("NO_CONTENT_TYPE") + 1) - (size_t)(
const void *)("NO_CONTENT_TYPE") == 1) && (__s2_len =
__builtin_strlen ("NO_CONTENT_TYPE"), __s2_len < 4) ? (__builtin_constant_p
(gw_sub_ptr->content_type) && ((size_t)(const void
*)((gw_sub_ptr->content_type) + 1) - (size_t)(const void *
)(gw_sub_ptr->content_type) == 1) ? __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(gw_sub_ptr->content_type); int __result = (((const unsigned
char *) (const char *) ("NO_CONTENT_TYPE"))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ("NO_CONTENT_TYPE"))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("NO_CONTENT_TYPE"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("NO_CONTENT_TYPE"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (gw_sub_ptr
->content_type, "NO_CONTENT_TYPE")))); })) ? tag_skip : siptag_accept_str
, tag_str_v(gw_sub_ptr->content_type)
,
268 SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from),
269 SIPTAG_TO_STR(gateway_ptr->register_from)siptag_to_str, tag_str_v(gateway_ptr->register_from),
270 SIPTAG_CONTACT_STR(gateway_ptr->register_contact)siptag_contact_str, tag_str_v(gateway_ptr->register_contact
)
, SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str)siptag_expires_str, tag_str_v(gw_sub_ptr->expires_str), TAG_NULL()(tag_type_t)0, (tag_value_t)0);
271 }
272 gw_sub_ptr->state = SUB_STATE_TRYING;
273 break;
274
275 case SUB_STATE_FAILED:
276 gw_sub_ptr->expires = now;
277 gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds;
278 gw_sub_ptr->state = SUB_STATE_FAIL_WAIT;
279 break;
280 case SUB_STATE_FAIL_WAIT:
281 if (!gw_sub_ptr->retry || now >= gw_sub_ptr->retry) {
282 gw_sub_ptr->state = SUB_STATE_UNSUBED;
283 }
284 break;
285 case SUB_STATE_TRYING:
286 if (gw_sub_ptr->retry && now >= gw_sub_ptr->retry) {
287 gw_sub_ptr->state = SUB_STATE_UNSUBED;
288 gw_sub_ptr->retry = 0;
289 }
290 break;
291 default:
292 if (now >= gw_sub_ptr->expires) {
293 gw_sub_ptr->state = SUB_STATE_UNSUBED;
294 }
295 break;
296 }
297
298 }
299 }
300 switch_mutex_unlock(profile->gw_mutex);
301}
302
303void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
304{
305 sofia_gateway_t *check, *gateway_ptr, *last = NULL((void*)0);
306 switch_event_t *event;
307 int delta = 0;
308
309 switch_mutex_lock(profile->gw_mutex);
310 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
311 if (gateway_ptr->deleted) {
312 if ((check = switch_core_hash_find(mod_sofia_globals.gateway_hash, gateway_ptr->name)) && check == gateway_ptr) {
313 char *pkey = switch_mprintf("%s::%s", profile->name, gateway_ptr->name);
314 switch_assert(pkey)((pkey) ? (void) (0) : __assert_fail ("pkey", "sofia_reg.c", 314
, __PRETTY_FUNCTION__))
;
315 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
315, ((void*)0)
, SWITCH_LOG_DEBUG, "Removing gateway %s from hash.\n", pkey);
316 switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
317 switch_core_hash_delete(mod_sofia_globals.gateway_hash, gateway_ptr->name);
318 free(pkey);
319 }
320
321 if (gateway_ptr->state == REG_STATE_NOREG) {
322
323 if (last) {
324 last->next = gateway_ptr->next;
325 } else {
326 profile->gateways = gateway_ptr->next;
327 }
328
329 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
329, ((void*)0)
, SWITCH_LOG_NOTICE, "Deleted gateway %s\n", gateway_ptr->name);
330 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_DEL)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 330, &event, SWITCH_EVENT_CUSTOM
, "sofia::gateway_delete")
== SWITCH_STATUS_SUCCESS) {
331 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile-name", gateway_ptr->profile->name);
332 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Gateway", gateway_ptr->name);
333 switch_event_fire(&event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 333, &event, ((void*)0))
;
334 }
335 if (gateway_ptr->ob_vars) {
336 switch_event_destroy(&gateway_ptr->ob_vars);
337 }
338 if (gateway_ptr->ib_vars) {
339 switch_event_destroy(&gateway_ptr->ib_vars);
340 }
341 } else {
342 last = gateway_ptr;
343 }
344 } else {
345 last = gateway_ptr;
346 }
347 }
348
349 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
350 reg_state_t ostate = gateway_ptr->state;
351 char *user_via = NULL((void*)0);
352 char *register_host = NULL((void*)0);
353
354 if (!now) {
355 gateway_ptr->state = ostate = REG_STATE_UNREGED;
356 gateway_ptr->expires_str = "0";
357 }
358
359 if (gateway_ptr->ping && !gateway_ptr->pinging && (now >= gateway_ptr->ping && (ostate == REG_STATE_NOREG || ostate == REG_STATE_REGED)) &&
360 !gateway_ptr->deleted) {
361 nua_handle_t *nh = nua_handle(profile->nua, NULL((void*)0), NUTAG_URL(gateway_ptr->register_url)nutag_url, urltag_url_v(gateway_ptr->register_url), TAG_END()(tag_type_t)0, (tag_value_t)0);
362 sofia_private_t *pvt;
363
364 register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
365
366 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
367 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
368 user_via = sofia_glue_create_external_via(NULL((void*)0), gateway_ptr->profile, gateway_ptr->register_transport);
369 }
370
371 switch_safe_free(register_host)if (register_host) {free(register_host);register_host=((void*
)0);}
;
372
373 pvt = malloc(sizeof(*pvt));
374 switch_assert(pvt)((pvt) ? (void) (0) : __assert_fail ("pvt", "sofia_reg.c", 374
, __PRETTY_FUNCTION__))
;
375 memset(pvt, 0, sizeof(*pvt));
376 pvt->destroy_nh = 1;
377 pvt->destroy_me = 1;
378 switch_copy_string(pvt->gateway_name, gateway_ptr->name, sizeof(pvt->gateway_name));
379 nua_handle_bind(nh, pvt);
380
381 gateway_ptr->pinging = 1;
382 gateway_ptr->ping_sent = switch_time_now();
383 nua_options(nh,
384 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy))!(gateway_ptr->register_sticky_proxy) ? tag_skip : ntatag_default_proxy
, urltag_url_v((gateway_ptr->register_sticky_proxy))
,
385 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
386 SIPTAG_TO_STR(gateway_ptr->options_to_uri)siptag_to_str, tag_str_v(gateway_ptr->options_to_uri), SIPTAG_FROM_STR(gateway_ptr->options_from_uri)siptag_from_str, tag_str_v(gateway_ptr->options_from_uri),
387 TAG_IF(gateway_ptr->options_user_agent, SIPTAG_USER_AGENT_STR(gateway_ptr->options_user_agent))!(gateway_ptr->options_user_agent) ? tag_skip : siptag_user_agent_str
, tag_str_v(gateway_ptr->options_user_agent)
,
388 TAG_END()(tag_type_t)0, (tag_value_t)0);
389
390 switch_safe_free(user_via)if (user_via) {free(user_via);user_via=((void*)0);};
391 user_via = NULL((void*)0);
392 }
393
394 switch (ostate) {
395 case REG_STATE_NOREG:
396 if (!gateway_ptr->ping && !gateway_ptr->pinging && gateway_ptr->status != SOFIA_GATEWAY_UP) {
397 gateway_ptr->status = SOFIA_GATEWAY_UP;
398 gateway_ptr->uptime = switch_time_now();
399 }
400 break;
401 case REG_STATE_REGISTER:
402 if (profile->debug) {
403 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
403, ((void*)0)
, SWITCH_LOG_DEBUG, "Registered %s\n", gateway_ptr->name);
404 }
405
406 gateway_ptr->failures = 0;
407
408 if (gateway_ptr->freq > 30) {
409 delta = (gateway_ptr->freq - 15);
410 } else {
411 delta = (gateway_ptr->freq / 2);
412 }
413
414 if (delta < 1) {
415 delta = 1;
416 }
417
418 gateway_ptr->expires = now + delta;
419
420 gateway_ptr->state = REG_STATE_REGED;
421 if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
422 gateway_ptr->status = SOFIA_GATEWAY_UP;
423 gateway_ptr->uptime = switch_time_now();
424 }
425 break;
426
427 case REG_STATE_UNREGISTER:
428 sofia_reg_kill_reg(gateway_ptr);
429 gateway_ptr->state = REG_STATE_NOREG;
430 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
431 break;
432 case REG_STATE_UNREGED:
433 gateway_ptr->retry = 0;
434
435 if (!gateway_ptr->nh) {
436 sofia_reg_new_handle(gateway_ptr, now ? 1 : 0);
437 }
438
439 register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
440
441 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
442 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
443 user_via = sofia_glue_create_external_via(NULL((void*)0), gateway_ptr->profile, gateway_ptr->register_transport);
444 }
445
446 switch_safe_free(register_host)if (register_host) {free(register_host);register_host=((void*
)0);}
;
447
448 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
448, ((void*)0)
, SWITCH_LOG_NOTICE, "Registering %s\n", gateway_ptr->name);
449
450 if (now) {
451 nua_register(gateway_ptr->nh,
452 NUTAG_URL(gateway_ptr->register_url)nutag_url, urltag_url_v(gateway_ptr->register_url),
453 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy))!(gateway_ptr->register_sticky_proxy) ? tag_skip : ntatag_default_proxy
, urltag_url_v((gateway_ptr->register_sticky_proxy))
,
454 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
455 SIPTAG_TO_STR(gateway_ptr->distinct_to ? gateway_ptr->register_to : gateway_ptr->register_from)siptag_to_str, tag_str_v(gateway_ptr->distinct_to ? gateway_ptr
->register_to : gateway_ptr->register_from)
,
456 SIPTAG_CONTACT_STR(gateway_ptr->register_contact)siptag_contact_str, tag_str_v(gateway_ptr->register_contact
)
,
457 SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from),
458 SIPTAG_EXPIRES_STR(gateway_ptr->expires_str)siptag_expires_str, tag_str_v(gateway_ptr->expires_str),
459 NUTAG_REGISTRAR(gateway_ptr->register_proxy)nutag_registrar, urltag_url_v(gateway_ptr->register_proxy),
460 NUTAG_OUTBOUND("no-options-keepalive")nutag_outbound, tag_str_v("no-options-keepalive"), NUTAG_OUTBOUND("no-validate")nutag_outbound, tag_str_v("no-validate"), NUTAG_KEEPALIVE(0)nutag_keepalive, tag_uint_v(0), TAG_NULL()(tag_type_t)0, (tag_value_t)0);
461 gateway_ptr->retry = now + gateway_ptr->retry_seconds;
462 } else {
463 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
464 nua_unregister(gateway_ptr->nh,
465 NUTAG_URL(gateway_ptr->register_url)nutag_url, urltag_url_v(gateway_ptr->register_url),
466 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy))!(gateway_ptr->register_sticky_proxy) ? tag_skip : ntatag_default_proxy
, urltag_url_v((gateway_ptr->register_sticky_proxy))
,
467 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
468 SIPTAG_FROM_STR(gateway_ptr->register_from)siptag_from_str, tag_str_v(gateway_ptr->register_from),
469 SIPTAG_TO_STR(gateway_ptr->distinct_to ? gateway_ptr->register_to : gateway_ptr->register_from)siptag_to_str, tag_str_v(gateway_ptr->distinct_to ? gateway_ptr
->register_to : gateway_ptr->register_from)
,
470 SIPTAG_EXPIRES_STR(gateway_ptr->expires_str)siptag_expires_str, tag_str_v(gateway_ptr->expires_str),
471 NUTAG_REGISTRAR(gateway_ptr->register_proxy)nutag_registrar, urltag_url_v(gateway_ptr->register_proxy),
472 NUTAG_OUTBOUND("no-options-keepalive")nutag_outbound, tag_str_v("no-options-keepalive"), NUTAG_OUTBOUND("no-validate")nutag_outbound, tag_str_v("no-validate"), NUTAG_KEEPALIVE(0)nutag_keepalive, tag_uint_v(0), TAG_NULL()(tag_type_t)0, (tag_value_t)0);
473 }
474 gateway_ptr->reg_timeout = now + gateway_ptr->reg_timeout_seconds;
475 gateway_ptr->state = REG_STATE_TRYING;
476 switch_safe_free(user_via)if (user_via) {free(user_via);user_via=((void*)0);};
477 user_via = NULL((void*)0);
478 break;
479
480 case REG_STATE_TIMEOUT:
481 {
482 nua_handle_t *nh = gateway_ptr->nh;
483
484 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
484, ((void*)0)
, SWITCH_LOG_WARNING, "Timeout Registering %s\n", gateway_ptr->name);
485
486 gateway_ptr->nh = NULL((void*)0);
487 nua_handle_destroy(nh);
488 gateway_ptr->state = REG_STATE_FAILED;
489 gateway_ptr->failures++;
490 gateway_ptr->failure_status = 908;
491 }
492 break;
493 case REG_STATE_FAILED:
494 {
495 int sec;
496
497 if (gateway_ptr->fail_908_retry_seconds && gateway_ptr->failure_status == 908) {
498 sec = gateway_ptr->fail_908_retry_seconds;
499 } else if (gateway_ptr->failure_status == 503 || gateway_ptr->failure_status == 908 || gateway_ptr->failures < 1) {
500 sec = gateway_ptr->retry_seconds;
501 } else {
502 sec = gateway_ptr->retry_seconds * gateway_ptr->failures;
503 }
504
505 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
505, ((void*)0)
, SWITCH_LOG_WARNING, "%s Failed Registration [%d], setting retry to %d seconds.\n",
506 gateway_ptr->name, gateway_ptr->failure_status, sec);
507
508 gateway_ptr->retry = switch_epoch_time_now(NULL((void*)0)) + sec;
509 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
510 gateway_ptr->state = REG_STATE_FAIL_WAIT;
511 gateway_ptr->failure_status = 0;
512
513 }
514 break;
515 case REG_STATE_FAIL_WAIT:
516 if (!gateway_ptr->retry || now >= gateway_ptr->retry) {
517 gateway_ptr->state = REG_STATE_UNREGED;
518 }
519 break;
520 case REG_STATE_TRYING:
521 if (now >= gateway_ptr->reg_timeout) {
522 gateway_ptr->state = REG_STATE_TIMEOUT;
523 }
524 break;
525 default:
526 if (now >= gateway_ptr->expires) {
527 gateway_ptr->state = REG_STATE_UNREGED;
528 }
529 break;
530 }
531 if (ostate != gateway_ptr->state) {
532 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL((void*)0));
533 }
534 }
535 switch_mutex_unlock(profile->gw_mutex);
536}
537
538
539int sofia_reg_find_callback(void *pArg, int argc, char **argv, char **columnNames)
540{
541 struct callback_t *cbt = (struct callback_t *) pArg;
542
543 if (!cbt->len) {
544 switch_console_push_match(&cbt->list, argv[0]);
545 cbt->matches++;
546 return 0;
547 }
548
549 switch_copy_string(cbt->val, argv[0], cbt->len);
550 cbt->matches++;
551 return cbt->matches == 1 ? 0 : 1;
552}
553
554
555int sofia_reg_find_reg_with_positive_expires_callback(void *pArg, int argc, char **argv, char **columnNames)
556{
557 struct callback_t *cbt = (struct callback_t *) pArg;
558 sofia_destination_t *dst = NULL((void*)0);
559 long int expires;
560 char *contact = NULL((void*)0);
561
562 if (zstr(argv[0])_zstr(argv[0])) {
563 return 0;
564 }
565
566 if (cbt->contact_str && !strcasecmp(argv[0], cbt->contact_str)) {
567 expires = cbt->exptime;
568 } else {
569 expires = atol(argv[1]) - 60 - (long) cbt->time;
570 }
571
572 if (expires > 0) {
573 dst = sofia_glue_get_destination(argv[0]);
574 contact = switch_mprintf("<%s>;expires=%ld", dst->contact, expires);
575
576 if (!cbt->len) {
577 switch_console_push_match(&cbt->list, contact);
578 switch_safe_free(contact)if (contact) {free(contact);contact=((void*)0);};
579 sofia_glue_free_destination(dst);
580 cbt->matches++;
581 return 0;
582 }
583
584 switch_copy_string(cbt->val, contact, cbt->len);
585 switch_safe_free(contact)if (contact) {free(contact);contact=((void*)0);};
586 sofia_glue_free_destination(dst);
587 cbt->matches++;
588 return cbt->matches == 1 ? 0 : 1;
589 }
590
591 return 0;
592}
593
594
595int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames)
596{
597 sofia_profile_t *profile = (sofia_profile_t *) pArg;
598 nua_handle_t *nh;
599 char to[512] = "", call_id[512] = "";
600 sofia_destination_t *dst = NULL((void*)0);
601 switch_uuid_t uuid;
602
603 switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]);
604
605 // create call-id for OPTIONS in the form "<uuid>_<original-register-call-id>"
606 switch_uuid_get(&uuid);
607 switch_uuid_format(call_id, &uuid);
608 strcat(call_id, "_");
609 strncat(call_id, argv[0], sizeof(call_id) - SWITCH_UUID_FORMATTED_LENGTH - 2)__builtin_strncat (call_id, argv[0], sizeof(call_id) - 256 - 2
)
;
610
611 dst = sofia_glue_get_destination(argv[3]);
612 switch_assert(dst)((dst) ? (void) (0) : __assert_fail ("dst", "sofia_reg.c", 612
, __PRETTY_FUNCTION__))
;
613
614 nh = nua_handle(profile->nua, NULL((void*)0), SIPTAG_FROM_STR(profile->url)siptag_from_str, tag_str_v(profile->url), SIPTAG_TO_STR(to)siptag_to_str, tag_str_v(to), NUTAG_URL(dst->contact)nutag_url, urltag_url_v(dst->contact), SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url),
615 SIPTAG_CALL_ID_STR(call_id)siptag_call_id_str, tag_str_v(call_id), TAG_END()(tag_type_t)0, (tag_value_t)0);
616 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
617 nua_options(nh,
618 NTATAG_SIP_T2(5000)ntatag_sip_t2, tag_uint_v((5000)),
619 NTATAG_SIP_T4(10000)ntatag_sip_t4, tag_uint_v((10000)),
620 TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((dst->route_uri))
, TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
621
622 sofia_glue_free_destination(dst);
623
624 return 0;
625}
626
627
628void sofia_reg_send_reboot(sofia_profile_t *profile, const char *callid, const char *user, const char *host, const char *contact, const char *user_agent,
629 const char *network_ip)
630{
631 const char *event = "check-sync";
632 const char *contenttype = "application/simple-message-summary";
633 char *body = NULL((void*)0);
634
635 if (switch_stristr("snom", user_agent) || switch_stristr("yealink", user_agent)) {
636 event = "check-sync;reboot=true";
637 } else if (switch_stristr("Linksys/SPA8000", user_agent)) {
638 event = "check-sync";
639 } else if (switch_stristr("linksys", user_agent)) {
640 event = "reboot_now";
641 } else if (switch_stristr("spa", user_agent)) {
642 event = "reboot";
643 } else if (switch_stristr("Cisco-CP7960G", user_agent) || switch_stristr("Cisco-CP7940G", user_agent)) {
644 event = "check-sync";
645 } else if (switch_stristr("cisco", user_agent)) {
646 event = "service-control";
647 contenttype = "text/plain";
648 body = switch_mprintf("action=restart\n"
649 "RegisterCallId={%s}\n"
650 "ConfigVersionStamp={0000000000000000}\n"
651 "DialplanVersionStamp={0000000000000000}\n"
652 "SoftkeyVersionStamp={0000000000000000}", callid);
653 }
654
655 sofia_glue_send_notify(profile, user, host, event, contenttype, body ? body : "", contact, network_ip, callid);
656
657 switch_safe_free(body)if (body) {free(body);body=((void*)0);};
658}
659
660int sofia_sla_dialog_del_callback(void *pArg, int argc, char **argv, char **columnNames)
661{
662 sofia_profile_t *profile = (sofia_profile_t *) pArg;
663 nua_handle_t *nh = NULL((void*)0);
664
665 if ((nh = nua_handle_by_call_id(profile->nua, argv[0]))) {
666 nua_handle_destroy(nh);
667 }
668
669 return 0;
670}
671
672void sofia_reg_check_socket(sofia_profile_t *profile, const char *call_id, const char *network_addr, const char *network_ip)
673{
674 char key[256] = "";
675 nua_handle_t *hnh;
676
677 switch_snprintf(key, sizeof(key), "%s%s%s", call_id, network_addr, network_ip);
678 switch_mutex_lock(profile->flag_mutex);
679 if ((hnh = switch_core_hash_find(profile->reg_nh_hash, key))) {
680 switch_core_hash_delete(profile->reg_nh_hash, key);
681 nua_handle_unref(hnh);
682 nua_handle_destroy(hnh);
683 }
684 switch_mutex_unlock(profile->flag_mutex);
685}
686
687
688
689int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames)
690{
691 switch_event_t *s_event;
692 sofia_profile_t *profile = (sofia_profile_t *) pArg;
693
694 if (argc > 13 && atoi(argv[13]) == 1) {
695 sofia_reg_send_reboot(profile, argv[0], argv[1], argv[2], argv[3], argv[7], argv[11]);
696 }
697
698 sofia_reg_check_socket(profile, argv[0], argv[11], argv[12]);
699
700
701 if (argc >= 3) {
702 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_EXPIRE)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 702, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::expire")
== SWITCH_STATUS_SUCCESS) {
703 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", argv[10]);
704 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", argv[0]);
705 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user", argv[1]);
706 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "host", argv[2]);
707 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", argv[3]);
708 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "expires", argv[6]);
709 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", argv[7]);
710 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", argv[14]);
711 sofia_event_fire(profile, &s_event);
712 }
713
714 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 714, &s_event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
715 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
716 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "away");
717 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->url);
718
719 if (argv[4]) {
720 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", argv[4]);
721 }
722
723 if (argv[1] && argv[2]) {
724 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", argv[1], argv[2]);
725 }
726
727 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
728 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
729 sofia_event_fire(profile, &s_event);
730 }
731
732 }
733 return 0;
734}
735
736void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot)
737{
738 char *sql = NULL((void*)0);
739 char *sqlextra = NULL((void*)0);
740 char *dup = strdup(call_id)(__extension__ (__builtin_constant_p (call_id) && ((size_t
)(const void *)((call_id) + 1) - (size_t)(const void *)(call_id
) == 1) ? (((const char *) (call_id))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (call_id
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, call_id
, __len); __retval; })) : __strdup (call_id)))
;
741 char *host = NULL((void*)0), *user = NULL((void*)0);
742
743 switch_assert(dup)((dup) ? (void) (0) : __assert_fail ("dup", "sofia_reg.c", 743
, __PRETTY_FUNCTION__))
;
744
745 if ((host = strchr(dup, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup) && ('@') == '\0' ? (char *) __rawmemchr (dup, '@'
) : __builtin_strchr (dup, '@')))
)) {
746 *host++ = '\0';
747 user = dup;
748 } else {
749 host = dup;
750 }
751
752 if (!host) {
753 host = "none";
754 }
755
756 if (zstr(user)_zstr(user)) {
757 sqlextra = switch_mprintf(" or (sip_host='%q')", host);
758 } else {
759 sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host);
760 }
761
762 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
763 ",user_agent,server_user,server_host,profile_name,network_ip,network_port"
764 ",%d,sip_realm from sip_registrations where call_id='%q' %s", reboot, call_id, sqlextra);
765
766
767 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
768 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
769
770 sql = switch_mprintf("delete from sip_registrations where call_id='%q' %s", call_id, sqlextra);
771 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
772
773 switch_safe_free(sqlextra)if (sqlextra) {free(sqlextra);sqlextra=((void*)0);};
774 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
775 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
776
777}
778
779void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
780{
781 char *sql;
782
783 if (now) {
784 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
785 ",user_agent,server_user,server_host,profile_name,network_ip, network_port"
786 ",%d,sip_realm from sip_registrations where expires > 0 and expires <= %ld", reboot, (long) now);
787 } else {
788 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
789 ",user_agent,server_user,server_host,profile_name,network_ip, network_port" ",%d,sip_realm from sip_registrations where expires > 0", reboot);
790 }
791
792 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
793 free(sql);
794
795 if (now) {
796 sql = switch_mprintf("delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'",
797 (long) now, mod_sofia_globals.hostname);
798 } else {
799 sql = switch_mprintf("delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
800 }
801 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
802
803
804
805
806 if (now) {
807 sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' "
808 "and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now);
809
810 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_sla_dialog_del_callback, profile);
811 free(sql);
812
813 sql = switch_mprintf("delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld",
814 mod_sofia_globals.hostname, (long) now);
815
816
817 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
818 }
819
820
821 if (now) {
822 sql = switch_mprintf("delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q'",
823 (long) now, mod_sofia_globals.hostname);
824 } else {
825 sql = switch_mprintf("delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
826 }
827
828 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
829
830 if (now) {
831 sql = switch_mprintf("delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'",
832 (long) now, mod_sofia_globals.hostname);
833 } else {
834 sql = switch_mprintf("delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
835 }
836
837 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
838
839 sofia_presence_check_subscriptions(profile, now);
840
841 if (now) {
842 sql = switch_mprintf("delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
843 (long) now, mod_sofia_globals.hostname);
844 } else {
845 sql = switch_mprintf("delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
846 }
847
848 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
849
850}
851
852long sofia_reg_uniform_distribution(int max)
853{
854/*
855 * Generate a random number following a uniform distribution between 0 and max
856 */
857 int result;
858 int range = max + 1;
859
860 srand((intptr_t) switch_thread_self() + switch_micro_time_now());
861 result = (int)((double)rand() / (((double)RAND_MAX2147483647 + (double)1) / range));
862
863 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
863, ((void*)0)
, SWITCH_LOG_DEBUG9, "Generated random %ld, max is %d\n", (long) result, max);
864 return (long) result;
865}
866
867void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int interval)
868{
869 char *sql;
870 int mean = interval / 2;
871 long next, irand;
872
873 if (now) {
874 if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)((profile)->pflags[PFLAG_ALL_REG_OPTIONS_PING] ? 1 : 0)) {
875 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
876 "expires,user_agent,server_user,server_host,profile_name"
877 " from sip_registrations where hostname='%s' and "
878 "profile_name='%s' and orig_hostname='%s' and "
879 "ping_expires > 0 and ping_expires <= %ld", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
880
881 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
882 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
883 } else if (sofia_test_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING)((profile)->pflags[PFLAG_UDP_NAT_OPTIONS_PING] ? 1 : 0)) {
884 sql = switch_mprintf( " select call_id,sip_user,sip_host,contact,status,rpid, "
885 " expires,user_agent,server_user,server_host,profile_name "
886 " from sip_registrations where status like '%%UDP-NAT%%' "
887 " and hostname='%s' and profile_name='%s' and ping_expires > 0 and ping_expires <= %ld ",
888 mod_sofia_globals.hostname, profile->name, (long) now);
889
890 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
891 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
892 } else if (sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)((profile)->pflags[PFLAG_NAT_OPTIONS_PING] ? 1 : 0)) {
893 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
894 "expires,user_agent,server_user,server_host,profile_name"
895 " from sip_registrations where (status like '%%NAT%%' "
896 "or contact like '%%fs_nat=yes%%') and hostname='%s' "
897 "and profile_name='%s' and orig_hostname='%s' and "
898 "ping_expires > 0 and ping_expires <= %ld", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
899
900 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
901 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
902 }
903
904 if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)((profile)->pflags[PFLAG_ALL_REG_OPTIONS_PING] ? 1 : 0) ||
905 sofia_test_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING)((profile)->pflags[PFLAG_UDP_NAT_OPTIONS_PING] ? 1 : 0) ||
906 sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)((profile)->pflags[PFLAG_NAT_OPTIONS_PING] ? 1 : 0)) {
907 char buf[32] = "";
908 int count;
909
910 sql = switch_mprintf("select count(*) from sip_registrations where hostname='%q' and profile_name='%q' and ping_expires <= %ld",
911 mod_sofia_globals.hostname, profile->name, (long) now);
912
913 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
914 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
915 count = atoi(buf);
916
917 /* only update if needed */
918 if (count) {
919 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
919, ((void*)0)
, SWITCH_LOG_DEBUG9, "Updating ping expires for profile %s\n", profile->name);
920 irand = mean + sofia_reg_uniform_distribution(interval);
921 next = (long) now + irand;
922
923 sql = switch_mprintf("update sip_registrations set ping_expires = %ld where hostname='%q' and profile_name='%q' and ping_expires <= %ld ",
924 next, mod_sofia_globals.hostname, profile->name, (long) now);
925 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
926 }
927 }
928 }
929
930}
931
932
933int sofia_reg_check_callback(void *pArg, int argc, char **argv, char **columnNames)
934{
935 sofia_profile_t *profile = (sofia_profile_t *) pArg;
936
937 sofia_reg_send_reboot(profile, argv[0], argv[1], argv[2], argv[3], argv[7], argv[11]);
938
939 return 0;
940}
941
942void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id)
943{
944 char *sql = NULL((void*)0);
945 char *sqlextra = NULL((void*)0);
946 char *dup = strdup(call_id)(__extension__ (__builtin_constant_p (call_id) && ((size_t
)(const void *)((call_id) + 1) - (size_t)(const void *)(call_id
) == 1) ? (((const char *) (call_id))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (call_id
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, call_id
, __len); __retval; })) : __strdup (call_id)))
;
947 char *host = NULL((void*)0), *user = NULL((void*)0);
948
949 switch_assert(dup)((dup) ? (void) (0) : __assert_fail ("dup", "sofia_reg.c", 949
, __PRETTY_FUNCTION__))
;
950
951 if ((host = strchr(dup, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup) && ('@') == '\0' ? (char *) __rawmemchr (dup, '@'
) : __builtin_strchr (dup, '@')))
)) {
952 *host++ = '\0';
953 user = dup;
954 } else {
955 host = dup;
956 }
957
958 if (!host) {
959 host = "none";
960 }
961
962 if (zstr(user)_zstr(user)) {
963 sqlextra = switch_mprintf(" or (sip_host='%q')", host);
964 } else {
965 sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host);
966 }
967
968 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
969 ",user_agent,server_user,server_host,profile_name,network_ip"
970 " from sip_registrations where call_id='%q' %s", call_id, sqlextra);
971
972
973 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_check_callback, profile);
974
975
976 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
977 switch_safe_free(sqlextra)if (sqlextra) {free(sqlextra);sqlextra=((void*)0);};
978 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
979
980}
981
982void sofia_reg_check_sync(sofia_profile_t *profile)
983{
984 char *sql;
985
986 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
987 ",user_agent,server_user,server_host,profile_name,network_ip,network_port,0,sip_realm"
988 " from sip_registrations where expires > 0");
989
990
991 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
992 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
993
994 sql = switch_mprintf("delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
995 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
996
997 sql = switch_mprintf("delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
998 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
999
1000 sql = switch_mprintf("delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
1001 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1002
1003 sql = switch_mprintf("delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
1004 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1005
1006 sql = switch_mprintf("delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
1007 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1008
1009}
1010
1011char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len)
1012{
1013 struct callback_t cbt = { 0 };
1014 char *sql;
1015
1016 if (!user) {
1017 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1017, ((void*)0)
, SWITCH_LOG_ERROR, "Called with null user!\n");
1018 return NULL((void*)0);
1019 }
1020
1021 cbt.val = val;
1022 cbt.len = len;
1023
1024 if (host) {
1025 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1026 user, host, host);
1027 } else {
1028 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q'", user);
1029 }
1030
1031
1032 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_callback, &cbt);
1033
1034 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1035
1036 if (cbt.list) {
1037 switch_console_free_matches(&cbt.list);
1038 }
1039
1040 if (cbt.matches) {
1041 return val;
1042 } else {
1043 return NULL((void*)0);
1044 }
1045}
1046
1047
1048switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host)
1049{
1050 struct callback_t cbt = { 0 };
1051 char *sql;
1052
1053 if (!user) {
1054 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1054, ((void*)0)
, SWITCH_LOG_ERROR, "Called with null user!\n");
1055 return NULL((void*)0);
1056 }
1057
1058 if (host) {
1059 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1060 user, host, host);
1061 } else {
1062 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q'", user);
1063 }
1064
1065
1066 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_callback, &cbt);
1067
1068 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1069
1070 return cbt.list;
1071}
1072
1073
1074switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_multi(sofia_profile_t *profile, const char *user, const char *host, time_t reg_time, const char *contact_str, long exptime)
1075{
1076 struct callback_t cbt = { 0 };
1077 char *sql;
1078
1079 if (!user) {
1080 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1080, ((void*)0)
, SWITCH_LOG_ERROR, "Called with null user!\n");
1081 return NULL((void*)0);
1082 }
1083
1084 if (host) {
1085 sql = switch_mprintf("select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1086 user, host, host);
1087 } else {
1088 sql = switch_mprintf("select contact,expires from sip_registrations where sip_user='%q'", user);
1089 }
1090
1091 cbt.time = reg_time;
1092 cbt.contact_str = contact_str;
1093 cbt.exptime = exptime;
1094
1095 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt);
1096 free(sql);
1097
1098 return cbt.list;
1099}
1100
1101
1102void sofia_reg_auth_challenge(sofia_profile_t *profile, nua_handle_t *nh, sofia_dispatch_event_t *de,
1103 sofia_regtype_t regtype, const char *realm, int stale, long exptime)
1104{
1105 switch_uuid_t uuid;
1106 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1];
1107 char *sql, *auth_str;
1108 msg_t *msg = NULL((void*)0);
1109
1110
1111 if (de && de->data) {
1112 msg = de->data->e_msg;
1113 }
1114
1115 switch_uuid_get(&uuid);
1116 switch_uuid_format(uuid_str, &uuid);
1117
1118 sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) "
1119 "values('%q', %ld, '%q', '%q', 0)", uuid_str,
1120 (long) switch_epoch_time_now(NULL((void*)0)) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL60) + exptime,
1121 profile->name, mod_sofia_globals.hostname);
1122 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_reg.c", 1122, __PRETTY_FUNCTION__))
;
1123 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1124
1125 auth_str = switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", realm, uuid_str, stale ? " stale=true," : "");
1126
1127 if (regtype == REG_REGISTER) {
1128 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg))!(msg) ? tag_skip : nutag_with, tag_ptr_v(msg), SIPTAG_WWW_AUTHENTICATE_STR(auth_str)siptag_www_authenticate_str, tag_str_v(auth_str), TAG_END()(tag_type_t)0, (tag_value_t)0);
1129 } else if (regtype == REG_INVITE) {
1130 nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED407, sip_407_Proxy_auth_required,
1131 TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg))!(msg) ? tag_skip : nutag_with, tag_ptr_v(msg),
1132 SIPTAG_PROXY_AUTHENTICATE_STR(auth_str)siptag_proxy_authenticate_str, tag_str_v(auth_str), TAG_END()(tag_type_t)0, (tag_value_t)0);
1133 }
1134
1135 switch_safe_free(auth_str)if (auth_str) {free(auth_str);auth_str=((void*)0);};
1136}
1137
1138uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host)
1139{
1140 char buf[32] = "";
1141 char *sql;
1142
1143 sql = switch_mprintf("select count(*) from sip_registrations where profile_name='%q' and "
1144 "sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", profile->name, user, host, host);
1145
1146 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
1147 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1148 return atoi(buf);
1149}
1150
1151static int debounce_check(sofia_profile_t *profile, const char *user, const char *host)
1152{
1153 char key[512] = "";
1154 int r = 0;
1155 time_t *last, now = switch_epoch_time_now(NULL((void*)0));
1156
1157 snprintf(key, sizeof(key)-1, "%s%s", user, host);
1158 key[sizeof(key)-1] = '\0';
1159
1160 switch_mutex_lock(profile->ireg_mutex);
1161 if ((last = switch_core_hash_find(profile->mwi_debounce_hash, key))) {
1162 if (now - *last > 30) {
1163 *last = now;
1164 r = 1;
1165 }
1166 } else {
1167 last = switch_core_alloc(profile->pool, sizeof(*last))switch_core_perform_alloc(profile->pool, sizeof(*last), "sofia_reg.c"
, (const char *)__func__, 1167)
;
1168 *last = now;
1169
1170 switch_core_hash_insert(profile->mwi_debounce_hash, key, last)switch_core_hash_insert_destructor(profile->mwi_debounce_hash
, key, last, ((void*)0))
;
1171 r = 1;
1172 }
1173 switch_mutex_unlock(profile->ireg_mutex);
1174
1175 return r;
1176}
1177
1178void sofia_reg_close_handles(sofia_profile_t *profile)
1179{
1180 nua_handle_t *nh = NULL((void*)0);
1181 switch_hash_index_t *hi = NULL((void*)0);
1182 const void *var;
1183 void *val;
1184
1185
1186 switch_mutex_lock(profile->flag_mutex);
1187 if (profile->reg_nh_hash) {
1188 top:
1189 for (hi = switch_core_hash_first_iter( profile->reg_nh_hash, hi); hi; hi = switch_core_hash_next(&hi)) {
1190 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
1191 if ((nh = (nua_handle_t *) val)) {
1192 nua_handle_unref(nh);
1193 nua_handle_destroy(nh);
1194 switch_core_hash_delete(profile->reg_nh_hash, (char *) var);
1195 goto top;
1196 }
1197 }
1198 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
1199
1200 }
1201 switch_mutex_unlock(profile->flag_mutex);
1202
1203 return;
1204
1205}
1206
1207
1208uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
1209 sofia_dispatch_event_t *de, sofia_regtype_t regtype, char *key,
1210 uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml, const char *sw_acl_token)
1211{
1212 sip_to_t const *to = NULL((void*)0);
1213 sip_from_t const *from = NULL((void*)0);
1214 sip_expires_t const *expires = NULL((void*)0);
1215 sip_authorization_t const *authorization = NULL((void*)0);
1216 sip_contact_t const *contact = NULL((void*)0);
1217 char *sql;
1218 switch_event_t *s_event;
1219 const char *reg_meta = NULL((void*)0);
1220 const char *to_user = NULL((void*)0);
1221 const char *to_host = NULL((void*)0);
1222 char *mwi_account = NULL((void*)0);
1223 char *dup_mwi_account = NULL((void*)0);
1224 char *display_m = NULL((void*)0);
1225 char *mwi_user = NULL((void*)0);
1226 char *mwi_host = NULL((void*)0);
1227 char *var = NULL((void*)0);
1228 const char *from_user = NULL((void*)0);
1229 const char *from_host = NULL((void*)0);
1230 const char *reg_host = profile->reg_db_domain;
1231 const char *sub_host = profile->sub_domain;
1232 char contact_str[1024] = "";
1233 uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
1234 uint8_t stale = 0, forbidden = 0;
1235 auth_res_t auth_res = AUTH_OK;
1236 long exptime = 300;
1237 switch_event_t *event;
1238 const char *rpid = "unknown";
1239 const char *display = "\"user\"";
1240 char network_ip[80];
1241 char network_port_c[6];
1242 char url_ip[80];
1243 int network_port;
1244 const char *reg_desc = "Registered";
1245 const char *call_id = NULL((void*)0);
1246 char *force_user;
1247 char received_data[128] = "";
1248 char *path_val = NULL((void*)0);
1249 switch_event_t *auth_params = NULL((void*)0);
1250 int r = 0;
1251 long reg_count = 0;
1252 const char *agent = "unknown";
1253 const char *pres_on_reg = NULL((void*)0);
1254 int send_pres = 0;
1255 int is_tls = 0, is_tcp = 0, is_ws = 0, is_wss = 0;
1256 char expbuf[35] = "";
1257 time_t reg_time = switch_epoch_time_now(NULL((void*)0));
1258 const char *vproto = NULL((void*)0);
1259 const char *proto = "sip";
1260 const char *uparams = NULL((void*)0);
1261 const char *p;
1262 char *utmp = NULL((void*)0);
1263 sofia_private_t *sofia_private = NULL((void*)0);
1264 char *sw_to_user;
1265 char *sw_reg_host;
1266 char *token_val = NULL((void*)0);
1267
1268 if (sofia_private_p) {
1269 sofia_private = *sofia_private_p;
1270 }
1271
1272 if (sip && sip->sip_contact && sip->sip_contact->m_url && sip->sip_contact->m_url->url_params) {
1273 uparams = sip->sip_contact->m_url->url_params;
1274 } else {
1275 uparams = NULL((void*)0);
1276 }
1277
1278
1279 if (sip && sip->sip_via && (vproto = sip->sip_via->v_protocol)) {
1280 if (!strcasecmp(vproto, "sip/2.0/ws")) {
1281 is_ws = 1;
1282 is_nat = "ws";
1283 } else if (!strcasecmp(vproto, "sip/2.0/wss")) {
1284 is_wss = 1;
1285 is_nat = "wss";
1286
1287 if (uparams && (p = switch_stristr("transport=ws", uparams))) {
1288 if (p[12] != 's') {
1289 utmp = switch_string_replace(uparams, "transport=ws", "transport=wss");
1290 }
1291 }
1292 }
1293 }
1294
1295 if (v_event && *v_event) pres_on_reg = switch_event_get_header(*v_event, "send-presence-on-register")switch_event_get_header_idx(*v_event, "send-presence-on-register"
, -1)
;
1296
1297 if (!(send_pres = switch_true(pres_on_reg))) {
1298 if (pres_on_reg && !strcasecmp(pres_on_reg, "first-only")) {
1299 send_pres = 2;
1300 }
1301 }
1302
1303 /* all callers must confirm that sip and sip->sip_request are not NULL */
1304 switch_assert(sip != NULL && sip->sip_request != NULL)((sip != ((void*)0) && sip->sip_request != ((void*
)0)) ? (void) (0) : __assert_fail ("sip != ((void*)0) && sip->sip_request != ((void*)0)"
, "sofia_reg.c", 1304, __PRETTY_FUNCTION__))
;
1305
1306 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
1307
1308 snprintf(network_port_c, sizeof(network_port_c), "%d", network_port);
1309
1310 snprintf(url_ip, sizeof(url_ip), (msg_addrinfo(de->data->e_msg))->ai_addr->sa_family == AF_INET610 ? "[%s]" : "%s", network_ip);
1311
1312 expires = sip->sip_expires;
1313 authorization = sip->sip_authorization;
1314 contact = sip->sip_contact;
1315 to = sip->sip_to;
1316 from = sip->sip_from;
1317
1318 if (sip->sip_user_agent) {
1319 agent = sip->sip_user_agent->g_string;
1320 }
1321
1322 if (from) {
1323 from_user = from->a_url->url_user;
1324 from_host = from->a_url->url_host;
1325 }
1326
1327 if (to) {
1328 to_user = to->a_url->url_user;
1329 to_host = to->a_url->url_host;
1330 }
1331
1332 if (!to_user) {
1333 to_user = from_user;
1334 }
1335 if (!to_host) {
1336 to_host = from_host;
1337 }
1338
1339 if (!to_user || !to_host) {
1340 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1340, ((void*)0)
, SWITCH_LOG_ERROR, "Can not do authorization without a complete header in REGISTER request from %s:%d\n",
1341 network_ip, network_port);
1342
1343 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
1344 switch_goto_int(r, 1, end)r = 1; goto end;
1345 }
1346
1347 if (zstr(reg_host)_zstr(reg_host)) {
1348 reg_host = to_host;
1349 }
1350 if (zstr(sub_host)_zstr(sub_host)) {
1351 sub_host = to_host;
1352 }
1353
1354 if (contact) {
1355 const char *port = contact->m_url->url_port;
1356 char new_port[25] = "";
1357 const char *contact_host = contact->m_url->url_host;
1358 char *path_encoded = NULL((void*)0);
1359 int path_encoded_len = 0;
1360
1361
1362 if (uparams && switch_stristr("transport=tls", uparams)) {
1363 is_tls += 1;
1364 if (sofia_test_pflag(profile, PFLAG_TLS_ALWAYS_NAT)((profile)->pflags[PFLAG_TLS_ALWAYS_NAT] ? 1 : 0)) {
1365 is_nat = "tls";
1366 }
1367 }
1368
1369 if (!is_wss && !is_ws && uparams && switch_stristr("transport=ws", uparams)) {
1370 is_nat = "ws";
1371 is_ws += 1;
1372 }
1373
1374 if (sip->sip_contact->m_url->url_type == url_sips) {
1375 proto = "sips";
1376 is_tls += 2;
1377 if (sofia_test_pflag(profile, PFLAG_TLS_ALWAYS_NAT)((profile)->pflags[PFLAG_TLS_ALWAYS_NAT] ? 1 : 0)) {
1378 is_nat = "tls";
1379 }
1380 }
1381
1382 if (uparams && switch_stristr("transport=tcp", uparams)) {
1383 is_tcp = 1;
1384 if (sofia_test_pflag(profile, PFLAG_TCP_ALWAYS_NAT)((profile)->pflags[PFLAG_TCP_ALWAYS_NAT] ? 1 : 0)) {
1385 is_nat = "tcp";
1386 }
1387 }
1388
1389 display = contact->m_display;
1390
1391 if (is_nat) {
1392 if (is_tls) {
1393 reg_desc = "Registered(TLS-NAT)";
1394 } else if (is_tcp) {
1395 reg_desc = "Registered(TCP-NAT)";
1396 } else if (is_ws) {
1397 reg_desc = "Registered(WS-NAT)";
1398 } else if (is_wss) {
1399 reg_desc = "Registered(WSS-NAT)";
1400 } else {
1401 reg_desc = "Registered(UDP-NAT)";
1402 }
1403 //contact_host = url_ip;
1404 //switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
1405 //port = NULL;
1406 } else {
1407 if (is_tls) {
1408 reg_desc = "Registered(TLS)";
1409 } else if (is_tcp) {
1410 reg_desc = "Registered(TCP)";
1411 } else {
1412 reg_desc = "Registered(UDP)";
1413 }
1414 }
1415
1416 if (zstr(display)_zstr(display)) {
1417 if (to) {
1418 display = to->a_display;
1419 if (zstr(display)_zstr(display)) {
1420 display = "\"\"";
1421 }
1422 }
1423 }
1424
1425 if (display && !strchr(display, '"')(__extension__ (__builtin_constant_p ('"') && !__builtin_constant_p
(display) && ('"') == '\0' ? (char *) __rawmemchr (display
, '"') : __builtin_strchr (display, '"')))
) {
1426 display_m = switch_mprintf("\"%q\"", display);
1427 display = display_m;
1428 }
1429
1430
1431 if (sip->sip_path) {
1432 if ((path_val = sip_header_as_string(nua_handle_home(nh)((su_home_t *)(nh)), (void *) sip->sip_path))) {
1433 char *path_stripped = sofia_glue_get_url_from_contact(path_val, SWITCH_TRUE);
1434 su_free(nua_handle_home(nh)((su_home_t *)(nh)), path_val);
1435 path_val = path_stripped;
1436 path_encoded_len = (int)(strlen(path_val) * 3) + 1;
1437 switch_zmalloc(path_encoded, path_encoded_len)(void)((((path_encoded = calloc(1, (path_encoded_len)))) ? (void
) (0) : __assert_fail ("(path_encoded = calloc(1, (path_encoded_len)))"
, "sofia_reg.c", 1437, __PRETTY_FUNCTION__)),path_encoded)
;
1438 switch_copy_string(path_encoded, ";fs_path=", 10);
1439 switch_url_encode(path_val, path_encoded + 9, path_encoded_len - 9);
1440 }
1441 } else if (is_nat) {
1442 char my_contact_str[1024];
1443 if (uparams) {
1444 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d;%s", proto,
1445 contact->m_url->url_user, url_ip, network_port, utmp ? utmp : uparams);
1446 } else {
1447 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port);
1448 }
1449
1450 path_encoded_len = (int)(strlen(my_contact_str) * 3) + 1;
1451
1452 switch_zmalloc(path_encoded, path_encoded_len)(void)((((path_encoded = calloc(1, (path_encoded_len)))) ? (void
) (0) : __assert_fail ("(path_encoded = calloc(1, (path_encoded_len)))"
, "sofia_reg.c", 1452, __PRETTY_FUNCTION__)),path_encoded)
;
1453 switch_copy_string(path_encoded, ";fs_path=", 10);
1454 switch_url_encode(my_contact_str, path_encoded + 9, path_encoded_len - 9);
1455 exptime = 30;
1456 }
1457
1458 if (port) {
1459 switch_snprintf(new_port, sizeof(new_port), ":%s", port);
1460 }
1461
1462 if (is_nat && sofia_test_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT)((profile)->pflags[PFLAG_RECIEVED_IN_NAT_REG_CONTACT] ? 1 :
0)
) {
1463 switch_snprintf(received_data, sizeof(received_data), ";received=%s:%d", url_ip, network_port);
1464 }
1465
1466 if (uparams) {
1467 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s%s;%s%s%s%s>",
1468 display, proto, contact->m_url->url_user, contact_host, new_port,
1469 uparams,
1470 received_data, is_nat ? ";fs_nat=yes" : "", path_encoded ? path_encoded : "");
1471
1472 } else {
1473 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,
1474 received_data, is_nat ? ";fs_nat=yes" : "", path_encoded ? path_encoded : "");
1475 }
1476
1477 switch_safe_free(path_encoded)if (path_encoded) {free(path_encoded);path_encoded=((void*)0)
;}
;
1478 }
1479
1480 if (expires) {
1481 exptime = expires->ex_delta;
1482 } else if (contact && contact->m_expires) {
1483 exptime = atol(contact->m_expires);
1484 }
1485
1486 if (regtype == REG_REGISTER) {
1487 authorization = sip->sip_authorization;
1488 } else if (regtype == REG_INVITE) {
1489 authorization = sip->sip_proxy_authorization;
1490 }
1491
1492 if (regtype == REG_AUTO_REGISTER || (regtype == REG_REGISTER && sofia_test_pflag(profile, PFLAG_BLIND_REG)((profile)->pflags[PFLAG_BLIND_REG] ? 1 : 0))) {
1493 regtype = REG_REGISTER;
1494 if (!zstr(sw_acl_token)_zstr(sw_acl_token)) {
1495 token_val = strdup(sw_acl_token)(__extension__ (__builtin_constant_p (sw_acl_token) &&
((size_t)(const void *)((sw_acl_token) + 1) - (size_t)(const
void *)(sw_acl_token) == 1) ? (((const char *) (sw_acl_token
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (sw_acl_token) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, sw_acl_token, __len); __retval; }
)) : __strdup (sw_acl_token)))
;
1496
1497 switch_split_user_domain(token_val, &sw_to_user, &sw_reg_host);
1498 to_user = sw_to_user;
1499 reg_host = sw_reg_host;
1500 }
1501 goto reg;
1502 }
1503
1504 if (authorization) {
1505 char *v_contact_str = NULL((void*)0);
1506 const char *username = "unknown";
1507 const char *realm = reg_host;
1508 if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip, de, sip->sip_request->rq_method_name,
1509 key, keylen, network_ip, network_port, v_event, exptime, regtype, to_user, &auth_params, &reg_count, user_xml)) == AUTH_STALE) {
1510 stale = 1;
1511 }
1512
1513
1514 if (auth_params) {
1515 username = switch_event_get_header(auth_params, "sip_auth_username")switch_event_get_header_idx(auth_params, "sip_auth_username",
-1)
;
1516 realm = switch_event_get_header(auth_params, "sip_auth_realm")switch_event_get_header_idx(auth_params, "sip_auth_realm", -1
)
;
1517 }
1518 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER_ATTEMPT)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 1518, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::register_attempt")
== SWITCH_STATUS_SUCCESS) {
1519 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1520 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
1521 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
1522 if (contact)
1523 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
1524 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1525 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1526 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
1527 if (contact)
1528 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
1529 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
1530 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
1531 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1532 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1533 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
1534 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
1535 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1536 switch (auth_res) {
1537 case AUTH_OK:
1538 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "SUCCESS");
1539 break;
1540 case AUTH_RENEWED:
1541 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "RENEWED");
1542 break;
1543 case AUTH_STALE:
1544 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "STALE");
1545 break;
1546 case AUTH_FORBIDDEN:
1547 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "FORBIDDEN");
1548 break;
1549 }
1550 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 1550, &s_event, ((void*)0))
;
1551 }
1552
1553 if (contact && exptime && v_event && *v_event) {
1554 uint32_t exp_var;
1555 uint32_t exp_max_deviation_var;
1556 char *allow_multireg = NULL((void*)0);
1557 int auto_connectile = 0;
1558
1559 allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations")switch_event_get_header_idx(*v_event, "sip-allow-multiple-registrations"
, -1)
;
1560 if (allow_multireg && switch_false(allow_multireg)) {
1561 avoid_multi_reg = 1;
1562 }
1563
1564 /* Allow us to force the SIP user to be something specific - needed if
1565 * we - for example - want to be able to ensure that the username a UA can
1566 * be contacted at is the same one that they used for authentication.
1567 */
1568 if ((force_user = switch_event_get_header(*v_event, "sip-force-user")switch_event_get_header_idx(*v_event, "sip-force-user", -1))) {
1569 to_user = force_user;
1570 }
1571
1572 if (!is_tcp && !is_tls && (zstr(network_ip)_zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)switch_check_network_list_ip_token(network_ip, profile->local_network
, ((void*)0))
) &&
1573 profile->server_rport_level >= 2 && sip->sip_user_agent &&
1574 sip->sip_user_agent->g_string &&
1575 ( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
1576 !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
1577 !strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) {
1578 if (sip && sip->sip_via) {
1579 const char *host = sip->sip_via->v_host;
1580 const char *c_port = sip->sip_via->v_port;
1581 int port = 0;
1582
1583 if (c_port) port = atoi(c_port);
1584 if (!port) port = 5060;
1585
1586 if (host && strcmp(network_ip, host)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(network_ip) && __builtin_constant_p (host) &&
(__s1_len = __builtin_strlen (network_ip), __s2_len = __builtin_strlen
(host), (!((size_t)(const void *)((network_ip) + 1) - (size_t
)(const void *)(network_ip) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((host) + 1) - (size_t)(const void *
)(host) == 1) || __s2_len >= 4)) ? __builtin_strcmp (network_ip
, host) : (__builtin_constant_p (network_ip) && ((size_t
)(const void *)((network_ip) + 1) - (size_t)(const void *)(network_ip
) == 1) && (__s1_len = __builtin_strlen (network_ip),
__s1_len < 4) ? (__builtin_constant_p (host) && (
(size_t)(const void *)((host) + 1) - (size_t)(const void *)(host
) == 1) ? __builtin_strcmp (network_ip, host) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (host); int __result = (((const unsigned char *) (const
char *) (network_ip))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (network_ip))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (network_ip))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (network_ip))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(host) && ((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) && (__s2_len = __builtin_strlen
(host), __s2_len < 4) ? (__builtin_constant_p (network_ip
) && ((size_t)(const void *)((network_ip) + 1) - (size_t
)(const void *)(network_ip) == 1) ? __builtin_strcmp (network_ip
, host) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (network_ip); int __result =
(((const unsigned char *) (const char *) (host))[0] - __s2[0
]); if (__s2_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (host))[1] - __s2[1
]); if (__s2_len > 1 && __result == 0) { __result =
(((const unsigned char *) (const char *) (host))[2] - __s2[2
]); if (__s2_len > 2 && __result == 0) __result = (
((const unsigned char *) (const char *) (host))[3] - __s2[3])
; } } __result; })))) : __builtin_strcmp (network_ip, host)))
); })
) {
1587 auto_connectile = 1;
1588 } else if (port != network_port) {
1589 auto_connectile = 1;
1590 }
1591 } else {
1592 auto_connectile = 1;
1593 }
1594 }
1595
1596 if (auto_connectile || (v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")switch_event_get_header_idx(*v_event, "sip-force-contact", -1
)
)) {
1597 if (auto_connectile || (!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0"))) {
1598 char *path_encoded = NULL((void*)0);
1599 size_t path_encoded_len;
1600 char my_contact_str[1024];
1601
1602 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port);
1603 path_encoded_len = (strlen(my_contact_str) * 3) + 1;
1604
1605 if (!switch_stristr("fs_path=", contact_str)) {
1606 switch_zmalloc(path_encoded, path_encoded_len)(void)((((path_encoded = calloc(1, (path_encoded_len)))) ? (void
) (0) : __assert_fail ("(path_encoded = calloc(1, (path_encoded_len)))"
, "sofia_reg.c", 1606, __PRETTY_FUNCTION__)),path_encoded)
;
1607 switch_copy_string(path_encoded, ";fs_nat=yes;fs_path=", 21);
1608 switch_url_encode(my_contact_str, path_encoded + 20, path_encoded_len - 20);
1609 reg_desc = "Registered(AUTO-NAT-2.0)";
1610 exptime = 30;
1611
1612 /* place fs_path (the encoded path) inside the <...> of the contact string, if possible */
1613 if (contact_str[strlen(contact_str) - 1] == '>') {
1614 switch_snprintf(contact_str + strlen(contact_str) - 1, sizeof(contact_str) - strlen(contact_str) + 1, "%s>", path_encoded);
1615 } else {
1616 switch_snprintf(contact_str + strlen(contact_str), sizeof(contact_str) - strlen(contact_str), "%s", path_encoded);
1617 }
1618 switch_safe_free(path_encoded)if (path_encoded) {free(path_encoded);path_encoded=((void*)0)
;}
;
1619 }
1620 } else {
1621 if (*received_data && sofia_test_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT)((profile)->pflags[PFLAG_RECIEVED_IN_NAT_REG_CONTACT] ? 1 :
0)
) {
1622 switch_snprintf(received_data, sizeof(received_data), ";received=%s:%d", url_ip, network_port);
1623 }
1624
1625 if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") ||
1626 !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) {
1627 if (uparams) {
1628 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d;%s%s;fs_nat=yes>",
1629 display, proto, contact->m_url->url_user, url_ip, network_port, uparams, received_data);
1630 } else {
1631 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d%s;fs_nat=yes>", display, proto,
1632 contact->m_url->url_user, url_ip,
1633 network_port, received_data);
1634 }
1635 if (switch_stristr(v_contact_str, "transport=tls")) {
1636 reg_desc = "Registered(TLSHACK)";
1637 } else {
1638 reg_desc = "Registered(AUTO-NAT)";
1639 exptime = 30;
1640 }
1641 } else {
1642 char *p;
1643 switch_copy_string(contact_str, v_contact_str, sizeof(contact_str));
1644 for (p = contact_str; p && *p; p++) {
1645 if (*p == '\'' || *p == '[' || *p == ']') {
1646 *p = '"';
1647 }
1648 }
1649 }
1650 }
1651 }
1652
1653 if ( (( exp_var = atoi(switch_event_get_header_nil(*v_event, "sip-force-expires")(switch_event_get_header_idx(*v_event, "sip-force-expires", -
1) ? switch_event_get_header_idx(*v_event, "sip-force-expires"
, -1) : "")
) )) ||
1654 (( exp_var = profile->sip_force_expires )) ) {
1655 if (exp_var > 0) {
1656 exptime = exp_var;
1657 }
1658 }
1659
1660 if ( (( exp_max_deviation_var = atoi(switch_event_get_header_nil(*v_event, "sip-expires-max-deviation")(switch_event_get_header_idx(*v_event, "sip-expires-max-deviation"
, -1) ? switch_event_get_header_idx(*v_event, "sip-expires-max-deviation"
, -1) : "")
) )) ||
1661 (( exp_max_deviation_var = profile->sip_expires_max_deviation )) ) {
1662 if (exp_max_deviation_var > 0) {
1663 int exp_deviation;
1664 srand( (unsigned) ( (unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now() ) );
1665 /* random number between negative exp_max_deviation_var and positive exp_max_deviation_var: */
1666 exp_deviation = ( rand() % ( exp_max_deviation_var * 2 ) ) - exp_max_deviation_var;
1667 exptime += exp_deviation;
1668 }
1669 }
1670
1671 }
1672
1673 if (auth_res != AUTH_OK && auth_res != AUTH_RENEWED && !stale) {
1674 if (auth_res == AUTH_FORBIDDEN) {
1675 nua_respond(nh, SIP_403_FORBIDDEN403, sip_403_Forbidden, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
1676 forbidden = 1;
1677 } else {
1678 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
1679 }
1680
1681 if (profile->debug) {
1682 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1682, ((void*)0)
, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n",
1683 forbidden ? "forbidden" : "challenge", to_user, to_host);
1684 }
1685 /* Log line added to support Fail2Ban */
1686 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)((profile)->pflags[PFLAG_LOG_AUTH_FAIL] ? 1 : 0)) {
1687 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1687, ((void*)0)
, SWITCH_LOG_WARNING, "SIP auth %s (%s) on sofia profile '%s' "
1688 "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge",
1689 (regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip);
1690 }
1691
1692 if (forbidden && switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER_FAILURE)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 1692, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::register_failure")
== SWITCH_STATUS_SUCCESS) {
1693 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1694 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", to_user);
1695 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", to_host);
1696 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1697 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1698 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1699 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1700 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "registration-type", (regtype == REG_INVITE) ? "INVITE" : "REGISTER");
1701 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 1701, &s_event, ((void*)0))
;
1702 }
1703 switch_goto_int(r, 1, end)r = 1; goto end;
1704 }
1705 }
1706
1707 if (!authorization || stale) {
1708 const char *realm = profile->challenge_realm;
1709
1710 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_PRE_REGISTER)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 1710, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::pre_register")
== SWITCH_STATUS_SUCCESS) {
1711 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1712 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
1713 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
1714 if (contact)
1715 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
1716 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1717 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1718 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
1719 if (contact)
1720 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
1721 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
1722 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
1723 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1724 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1725 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1726 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 1726, &s_event, ((void*)0))
;
1727 }
1728
1729 if (zstr(realm)_zstr(realm) || !strcasecmp(realm, "auto_to")) {
1730 realm = to_host;
1731 } else if (!strcasecmp(realm, "auto_from")) {
1732 realm = from_host;
1733 }
1734
1735 sofia_reg_auth_challenge(profile, nh, de, regtype, realm, stale, exptime);
1736
1737 if (profile->debug) {
1738 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1738, ((void*)0)
, SWITCH_LOG_DEBUG, "Send challenge for [%s@%s]\n", to_user, to_host);
1739 }
1740 /* Log line added to support Fail2Ban */
1741 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)((profile)->pflags[PFLAG_LOG_AUTH_FAIL] ? 1 : 0)) {
1742 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1742, ((void*)0)
, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' "
1743 "for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER",
1744 profile->name, to_user, to_host, network_ip);
1745 }
1746
1747 switch_goto_int(r, 1, end)r = 1; goto end;
1748 }
1749
1750 if (!contact)
1751 goto respond_200_ok;
1752
1753 reg:
1754
1755
1756 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "sip-force-extension")switch_event_get_header_idx(*v_event, "sip-force-extension", -
1)
)) {
1757 to_user = var;
1758 }
1759
1760 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "registration_metadata")switch_event_get_header_idx(*v_event, "registration_metadata"
, -1)
)) {
1761 reg_meta = var;
1762 }
1763
1764 if (v_event && *v_event && (mwi_account = switch_event_get_header(*v_event, "mwi-account")switch_event_get_header_idx(*v_event, "mwi-account", -1))) {
1765 dup_mwi_account = strdup(mwi_account)(__extension__ (__builtin_constant_p (mwi_account) &&
((size_t)(const void *)((mwi_account) + 1) - (size_t)(const void
*)(mwi_account) == 1) ? (((const char *) (mwi_account))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (mwi_account) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, mwi_account, __len); __retval; })) : __strdup (mwi_account
)))
;
1766 switch_assert(dup_mwi_account != NULL)((dup_mwi_account != ((void*)0)) ? (void) (0) : __assert_fail
("dup_mwi_account != ((void*)0)", "sofia_reg.c", 1766, __PRETTY_FUNCTION__
))
;
1767 switch_split_user_domain(dup_mwi_account, &mwi_user, &mwi_host);
1768 }
1769
1770 if (!mwi_user) {
1771 mwi_user = (char *) to_user;
1772 }
1773 if (!mwi_host) {
1774 mwi_host = (char *) reg_host;
1775 }
1776
1777 if (regtype != REG_REGISTER) {
1778 switch_goto_int(r, 0, end)r = 0; goto end;
1779 }
1780
1781 call_id = sip->sip_call_id->i_id;
1782 switch_assert(call_id)((call_id) ? (void) (0) : __assert_fail ("call_id", "sofia_reg.c"
, 1782, __PRETTY_FUNCTION__))
;
1783
1784 /* Does this profile supports multiple registrations ? */
1785 multi_reg = (sofia_test_pflag(profile, PFLAG_MULTIREG)((profile)->pflags[PFLAG_MULTIREG] ? 1 : 0)) ? 1 : 0;
1786 multi_reg_contact = (sofia_test_pflag(profile, PFLAG_MULTIREG_CONTACT)((profile)->pflags[PFLAG_MULTIREG_CONTACT] ? 1 : 0)) ? 1 : 0;
1787
1788
1789 if (multi_reg && avoid_multi_reg) {
1790 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1790, ((void*)0)
, SWITCH_LOG_DEBUG,
1791 "Disabling multiple registrations on a per-user basis for %s@%s\n", switch_str_nil(to_user)(to_user ? to_user : ""), switch_str_nil(to_host)(to_host ? to_host : ""));
1792 multi_reg = 0;
1793 }
1794
1795 if (exptime) {
1796 char guess_ip4[256];
1797 const char *username = "unknown";
1798 const char *realm = reg_host;
1799 char *url = NULL((void*)0);
1800 char *contact = NULL((void*)0);
1801 switch_bool_t update_registration = SWITCH_FALSE;
1802
1803 if (auth_params) {
1804 username = switch_event_get_header(auth_params, "sip_auth_username")switch_event_get_header_idx(auth_params, "sip_auth_username",
-1)
;
1805 realm = switch_event_get_header(auth_params, "sip_auth_realm")switch_event_get_header_idx(auth_params, "sip_auth_realm", -1
)
;
1806 }
1807
1808 if (auth_res != AUTH_RENEWED || !multi_reg) {
1809 if (multi_reg) {
1810 if (multi_reg_contact) {
1811 sql =
1812 switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
1813 } else {
1814 sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
1815 }
1816 } else {
1817 sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
1818 }
1819
1820 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1821 } else {
1822 char buf[32] = "";
1823
1824
1825 sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
1826 to_user, username, reg_host, contact_str);
1827
1828
1829
1830 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
1831 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1832 if (atoi(buf) > 0) {
1833 update_registration = SWITCH_TRUE;
1834 }
1835 }
1836
1837 switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL((void*)0), AF_INET2);
1838
1839 contact = sofia_glue_get_url_from_contact(contact_str, 1);
1840 url = switch_mprintf("sofia/%q/%s:%q", profile->name, proto, sofia_glue_strip_proto(contact));
1841
1842 switch_core_add_registration(to_user, reg_host, call_id, url, (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
1843 network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp", reg_meta);
1844
1845 switch_safe_free(url)if (url) {free(url);url=((void*)0);};
1846 switch_safe_free(contact)if (contact) {free(contact);contact=((void*)0);};
1847
1848 if ((is_wss || is_ws || (sofia_test_pflag(profile, PFLAG_TCP_UNREG_ON_SOCKET_CLOSE)((profile)->pflags[PFLAG_TCP_UNREG_ON_SOCKET_CLOSE] ? 1 : 0
)
&& (is_tcp || is_tls))) && !sofia_private && call_id) {
1849 char key[256] = "";
1850 nua_handle_t *hnh;
1851 switch_snprintf(key, sizeof(key), "%s%s%s", call_id, network_ip, network_port_c);
1852
1853 switch_mutex_lock(profile->flag_mutex);
1854 hnh = switch_core_hash_find(profile->reg_nh_hash, key);
1855 switch_mutex_unlock(profile->flag_mutex);
1856
1857 if (!hnh) {
1858 if (!(sofia_private = su_alloc(nh->nh_home, sizeof(*sofia_private)))) {
1859 abort();
1860 }
1861
1862 memset(sofia_private, 0, sizeof(*sofia_private));
1863 sofia_private->call_id = su_strdup(nh->nh_home, call_id);
1864 sofia_private->network_ip = su_strdup(nh->nh_home, network_ip);
1865 sofia_private->network_port = su_strdup(nh->nh_home, network_port_c);
1866 sofia_private->key = su_strdup(nh->nh_home, key);
1867 sofia_private->user = su_strdup(nh->nh_home, to_user);
1868 sofia_private->realm = su_strdup(nh->nh_home, reg_host);
1869
1870 sofia_private->is_static++;
1871 *sofia_private_p = sofia_private;
1872 nua_handle_bind(nh, sofia_private);
1873 nua_handle_ref(nh);
1874 switch_core_hash_insert(profile->reg_nh_hash, key, nh)switch_core_hash_insert_destructor(profile->reg_nh_hash, key
, nh, ((void*)0))
;
1875 }
1876 }
1877
1878
1879 if (!update_registration) {
1880 sql = switch_mprintf("insert into sip_registrations "
1881 "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
1882 "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
1883 "mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host, ping_status, ping_count) "
1884 "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d)",
1885 call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : "",
1886 contact_str, reg_desc, rpid, (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
1887 agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
1888 mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0);
1889 } else {
1890 sql = switch_mprintf("update sip_registrations set call_id='%q',"
1891 "sub_host='%q', network_ip='%q',network_port='%q',"
1892 "presence_hosts='%q', server_host='%q', orig_server_host='%q',"
1893 "hostname='%q', orig_hostname='%q',"
1894 "expires = %ld where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
1895 call_id, sub_host, network_ip, network_port_c,
1896 profile->presence_hosts ? profile->presence_hosts : "", guess_ip4, guess_ip4,
1897 mod_sofia_globals.hostname, mod_sofia_globals.hostname,
1898 (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
1899 to_user, username, reg_host, contact_str);
1900 }
1901
1902 if (sql) {
1903 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1904 }
1905
1906 if (!update_registration && sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
1907 sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'",
1908 to_user, reg_host, profile->name);
1909 if (mod_sofia_globals.debug_presence > 0) {
1910 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1910, ((void*)0)
, SWITCH_LOG_ERROR, "DELETE PRESENCE SQL: %s\n", sql);
1911 }
1912 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1913 }
1914
1915 if (multi_reg) {
1916 if (multi_reg_contact) {
1917 sql = switch_mprintf("delete from sip_registrations where contact='%q' and expires!=%ld", contact_str, (long) reg_time + (long) exptime + profile->sip_expires_late_margin);
1918 } else {
1919 sql = switch_mprintf("delete from sip_registrations where call_id='%q' and expires!=%ld", call_id, (long) reg_time + (long) exptime + profile->sip_expires_late_margin);
1920 }
1921
1922 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
1923 }
1924
1925
1926
1927 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 1927, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::register")
== SWITCH_STATUS_SUCCESS) {
1928 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1929 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
1930 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
1931 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-hosts", profile->presence_hosts ? profile->presence_hosts : "n/a");
1932 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
1933 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1934 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1935 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
1936 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
1937 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
1938 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
1939 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1940 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1941 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
1942 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
1943 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1944 if (update_registration) {
1945 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "update-reg", "true");
1946 }
1947 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 1947, &s_event, ((void*)0))
;
1948 }
1949
1950
1951
1952 if (profile->debug) {
1953 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
1953, ((void*)0)
, SWITCH_LOG_DEBUG,
1954 "Register:\nFrom: [%s@%s]\nContact: [%s]\nExpires: [%ld]\n", to_user, reg_host, contact_str, (long) exptime);
1955 }
1956
1957 } else {
1958 int send = 1;
1959
1960 if (multi_reg) {
1961 if (sofia_reg_reg_count(profile, to_user, sub_host) > 0) {
1962 send = 0;
1963 }
1964 }
1965
1966 sofia_reg_check_socket(profile, call_id, network_ip, network_port_c);
1967
1968 if (send && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 1968, &event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1969 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
1970 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1971 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
1972 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
1973 (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
1974 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
1975 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
1976 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register");
1977 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
1978 switch_event_fire(&event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 1978, &event, ((void*)0))
;
1979 }
1980
1981
1982 if (multi_reg) {
1983 char *icontact, *p;
1984 icontact = sofia_glue_get_url_from_contact(contact_str, 1);
1985 if ((p = strchr(icontact, ';')(__extension__ (__builtin_constant_p (';') && !__builtin_constant_p
(icontact) && (';') == '\0' ? (char *) __rawmemchr (
icontact, ';') : __builtin_strchr (icontact, ';')))
)) {
1986 *p = '\0';
1987 }
1988 if ((p = strchr(icontact + 4, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(icontact + 4) && (':') == '\0' ? (char *) __rawmemchr
(icontact + 4, ':') : __builtin_strchr (icontact + 4, ':')))
)) {
1989 *p = '\0';
1990 }
1991
1992 if (multi_reg_contact) {
1993 sql =
1994 switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
1995 } else {
1996 sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
1997 }
1998
1999 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2000
2001 switch_safe_free(icontact)if (icontact) {free(icontact);icontact=((void*)0);};
2002 } else {
2003
2004 if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
2005 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2006 }
2007 }
2008 }
2009
2010 respond_200_ok:
2011
2012 if (regtype == REG_REGISTER) {
2013 char exp_param[128] = "";
2014 char date[80] = "";
2015 switch_event_t *s_mwi_event = NULL((void*)0);
2016
2017 switch_console_callback_match_t *contact_list = NULL((void*)0);
2018 tagi_t *contact_tags;
2019 switch_console_callback_match_node_t *m;
2020 int i;
2021
2022 s_event = NULL((void*)0);
2023
2024 if (contact) {
2025 if (exptime) {
2026 int debounce_ok = debounce_check(profile, mwi_user, mwi_host);
2027
2028 switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime);
2029 sip_contact_add_param(nua_handle_home(nh)((su_home_t *)(nh)), sip->sip_contact, exp_param);
2030
2031 if ((sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER)((profile)->pflags[PFLAG_MESSAGE_QUERY_ON_REGISTER] ? 1 : 0
)
||
2032 (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER)((profile)->pflags[PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER] ?
1 : 0)
)) && debounce_ok) {
2033
2034 if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2034, &s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2035 switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "%s:%s@%s", proto, mwi_user, mwi_host);
2036 switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name);
2037 switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id);
2038 }
2039 }
2040
2041 if ((sofia_test_pflag(profile, PFLAG_PRESENCE_ON_REGISTER)((profile)->pflags[PFLAG_PRESENCE_ON_REGISTER] ? 1 : 0) ||
2042 (reg_count == 1 && sofia_test_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER)((profile)->pflags[PFLAG_PRESENCE_ON_FIRST_REGISTER] ? 1 :
0)
)
2043 || send_pres == 1 || (reg_count == 1 && send_pres == 2)) && debounce_ok) {
2044
2045 if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)((profile)->pflags[PFLAG_PRESENCE_PROBE_ON_REGISTER] ? 1 :
0)
) {
2046 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2046, &s_event, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2047 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
2048 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
2049 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
2050 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
2051 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2052 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2053 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
2054 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 2054, &s_event, ((void*)0))
;
2055 }
2056 } else {
2057 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2057, &s_event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2058 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
2059 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
2060 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2061 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
2062 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
2063 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
2064 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 2064, &s_event, ((void*)0))
;
2065 }
2066 }
2067 }
2068 } else {
2069 const char *username = "unknown";
2070 const char *realm = "unknown";
2071
2072 if (auth_params) {
2073 username = switch_event_get_header(auth_params, "sip_auth_username")switch_event_get_header_idx(auth_params, "sip_auth_username",
-1)
;
2074 realm = switch_event_get_header(auth_params, "sip_auth_realm")switch_event_get_header_idx(auth_params, "sip_auth_realm", -1
)
;
2075 }
2076
2077 switch_core_del_registration(to_user, reg_host, call_id);
2078
2079 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2079, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::unregister")
== SWITCH_STATUS_SUCCESS) {
2080 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
2081 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
2082 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
2083 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
2084 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
2085 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
2086 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
2087 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
2088 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
2089 }
2090 }
2091 }
2092
2093 switch_rfc822_date(date, switch_micro_time_now());
2094
2095 /* generate and respond a 200 OK */
2096
2097 if ((profile->ndlb & PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE)) {
2098 switch_snprintf(expbuf, sizeof(expbuf), "%ld", exptime);
2099 }
2100
2101 if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup) {
2102 /* handle backwards compatibility - contacts will not be looked up but only copied from the request into the response
2103 remove this condition later if nobody complains about the extra select of the below new behavior
2104 also remove the parts in mod_sofia.h, sofia.c and sofia_reg.c that refer to reg_deny_binding_fetch_and_no_lookup */
2105 nua_respond(nh, SIP_200_OK200, sip_200_OK, TAG_IF(contact, SIPTAG_CONTACT(sip->sip_contact))!(contact) ? tag_skip : siptag_contact, siptag_contact_v(sip->
sip_contact)
, TAG_IF(path_val, SIPTAG_PATH_STR(path_val))!(path_val) ? tag_skip : siptag_path_str, tag_str_v(path_val),
2106 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf))!(!_zstr(expbuf)) ? tag_skip : siptag_expires_str, tag_str_v(
expbuf)
,
2107 NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), SIPTAG_DATE_STR(date)siptag_date_str, tag_str_v(date), TAG_END()(tag_type_t)0, (tag_value_t)0);
2108
2109 } else if ((contact_list = sofia_reg_find_reg_url_with_positive_expires_multi(profile, from_user, reg_host, reg_time, contact_str, exptime))) {
2110 /* all + 1 tag_i elements initialized as NULL - last one implies TAG_END() */
2111 switch_zmalloc(contact_tags, sizeof(*contact_tags) * (contact_list->count + 1))(void)((((contact_tags = calloc(1, (sizeof(*contact_tags) * (
contact_list->count + 1))))) ? (void) (0) : __assert_fail (
"(contact_tags = calloc(1, (sizeof(*contact_tags) * (contact_list->count + 1))))"
, "sofia_reg.c", 2111, __PRETTY_FUNCTION__)),contact_tags)
;
2112 i = 0;
2113 for (m = contact_list->head; m; m = m->next) {
2114 contact_tags[i].t_tag = siptag_contact_str;
2115 contact_tags[i].t_value = (tag_value_t) m->val;
2116 ++i;
2117 }
2118
2119
2120 nua_respond(nh, SIP_200_OK200, sip_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val))!(path_val) ? tag_skip : siptag_path_str, tag_str_v(path_val),
2121 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf))!(!_zstr(expbuf)) ? tag_skip : siptag_expires_str, tag_str_v(
expbuf)
,
2122 NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), SIPTAG_DATE_STR(date)siptag_date_str, tag_str_v(date), TAG_NEXT(contact_tags)tag_next, (tag_value_t)(contact_tags));
2123
2124 switch_safe_free(contact_tags)if (contact_tags) {free(contact_tags);contact_tags=((void*)0)
;}
;
2125 switch_console_free_matches(&contact_list);
2126
2127 } else {
2128 /* respond without any contacts */
2129 nua_respond(nh, SIP_200_OK200, sip_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val))!(path_val) ? tag_skip : siptag_path_str, tag_str_v(path_val),
2130 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf))!(!_zstr(expbuf)) ? tag_skip : siptag_expires_str, tag_str_v(
expbuf)
,
2131 NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), SIPTAG_DATE_STR(date)siptag_date_str, tag_str_v(date), TAG_END()(tag_type_t)0, (tag_value_t)0);
2132 }
2133
2134
2135 if (s_event) {
2136 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 2136, &s_event, ((void*)0))
;
2137 }
2138
2139 if (s_mwi_event) {
2140 switch_event_fire(&s_mwi_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 2140, &s_mwi_event, ((void*)0))
;
2141 }
2142
2143 switch_goto_int(r, 1, end)r = 1; goto end;
2144 }
2145
2146
2147 end:
2148 switch_safe_free(display_m)if (display_m) {free(display_m);display_m=((void*)0);};
2149 switch_safe_free(dup_mwi_account)if (dup_mwi_account) {free(dup_mwi_account);dup_mwi_account=(
(void*)0);}
;
2150 switch_safe_free(utmp)if (utmp) {free(utmp);utmp=((void*)0);};
2151 switch_safe_free(path_val)if (path_val) {free(path_val);path_val=((void*)0);};
2152 switch_safe_free(token_val)if (token_val) {free(token_val);token_val=((void*)0);};
2153
2154 if (auth_params) {
2155 switch_event_destroy(&auth_params);
2156 }
2157
2158 return (uint8_t) r;
2159}
2160
2161
2162
2163void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private_p, sip_t const *sip,
2164 sofia_dispatch_event_t *de,
2165 tagi_t tags[])
2166{
2167 char key[128] = "";
2168 switch_event_t *v_event = NULL((void*)0);
2169 char network_ip[80];
2170 sofia_regtype_t type = REG_REGISTER;
2171 int network_port = 0;
2172 char *is_nat = NULL((void*)0);
2173 const char *acl_token = NULL((void*)0);
2174
2175
2176#if 0 /* This seems to cause undesirable effects so nevermind */
2177 if (sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_host) {
2178 const char *to_host = sip->sip_to->a_url->url_host;
2179 if (profile->reg_db_domain) {
2180 if (!sofia_glue_profile_exists(to_host)) {
2181 if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host)switch_core_perform_strdup(profile->pool, to_host, "sofia_reg.c"
, (const char *)__func__, 2181)
, profile) == SWITCH_STATUS_SUCCESS) {
2182 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2182, ((void*)0)
, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
2183 }
2184 }
2185 }
2186 }
2187#endif
2188
2189 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
2190
2191 /* backwards compatibility */
2192 if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup && !(sip->sip_contact && sip->sip_contact->m_url)) {
2193 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2193, ((void*)0)
, SWITCH_LOG_ERROR, "NO CONTACT! ip: %s, port: %i\n", network_ip, network_port);
2194 nua_respond(nh, 400, "Missing Contact Header", TAG_END()(tag_type_t)0, (tag_value_t)0);
2195 goto end;
2196 }
2197
2198 if (!(profile->mflags & MFLAG_REGISTER)) {
2199 nua_respond(nh, SIP_403_FORBIDDEN403, sip_403_Forbidden, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
2200 goto end;
2201 }
2202
2203 if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)((profile)->pflags[PFLAG_AGGRESSIVE_NAT_DETECTION] ? 1 : 0
)
) {
2204 if (sip && sip->sip_via) {
2205 const char *port = sip->sip_via->v_port;
2206 const char *host = sip->sip_via->v_host;
2207
2208 if (host && sip->sip_via->v_received) {
2209 is_nat = "via received";
2210 } else if (host && strcmp(network_ip, host)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(network_ip) && __builtin_constant_p (host) &&
(__s1_len = __builtin_strlen (network_ip), __s2_len = __builtin_strlen
(host), (!((size_t)(const void *)((network_ip) + 1) - (size_t
)(const void *)(network_ip) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((host) + 1) - (size_t)(const void *
)(host) == 1) || __s2_len >= 4)) ? __builtin_strcmp (network_ip
, host) : (__builtin_constant_p (network_ip) && ((size_t
)(const void *)((network_ip) + 1) - (size_t)(const void *)(network_ip
) == 1) && (__s1_len = __builtin_strlen (network_ip),
__s1_len < 4) ? (__builtin_constant_p (host) && (
(size_t)(const void *)((host) + 1) - (size_t)(const void *)(host
) == 1) ? __builtin_strcmp (network_ip, host) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (host); int __result = (((const unsigned char *) (const
char *) (network_ip))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (network_ip))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (network_ip))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (network_ip))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(host) && ((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) && (__s2_len = __builtin_strlen
(host), __s2_len < 4) ? (__builtin_constant_p (network_ip
) && ((size_t)(const void *)((network_ip) + 1) - (size_t
)(const void *)(network_ip) == 1) ? __builtin_strcmp (network_ip
, host) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (network_ip); int __result =
(((const unsigned char *) (const char *) (host))[0] - __s2[0
]); if (__s2_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (host))[1] - __s2[1
]); if (__s2_len > 1 && __result == 0) { __result =
(((const unsigned char *) (const char *) (host))[2] - __s2[2
]); if (__s2_len > 2 && __result == 0) __result = (
((const unsigned char *) (const char *) (host))[3] - __s2[3])
; } } __result; })))) : __builtin_strcmp (network_ip, host)))
); })
) {
2211 is_nat = "via host";
2212 } else if (port && atoi(port) != network_port) {
2213 is_nat = "via port";
2214 }
2215
2216 if (!is_nat && sip->sip_via->v_port &&
2217 atoi(sip->sip_via->v_port) == 5060 && network_port != 5060 ) {
2218 is_nat = "via port";
2219 }
2220 }
2221 }
2222
2223 if (!is_nat && profile->nat_acl_count) {
2224 uint32_t x = 0;
2225 int ok = 1;
2226 char *last_acl = NULL((void*)0);
2227 const char *contact_host = NULL((void*)0);
2228
2229 if (sip && sip->sip_contact && sip->sip_contact->m_url) {
2230 contact_host = sip->sip_contact->m_url->url_host;
2231 }
2232
2233 if (!zstr(contact_host)_zstr(contact_host)) {
2234 for (x = 0; x < profile->nat_acl_count; x++) {
2235 last_acl = profile->nat_acl[x];
2236 if (!(ok = switch_check_network_list_ip(contact_host, last_acl)switch_check_network_list_ip_token(contact_host, last_acl, ((
void*)0))
)) {
2237 break;
2238 }
2239 }
2240
2241 if (ok) {
2242 is_nat = last_acl;
2243 }
2244 }
2245 }
2246
2247 if (profile->reg_acl_count) {
2248 uint32_t x = 0;
2249 int ok = 1;
2250 char *last_acl = NULL((void*)0);
2251 const char *token_sw = NULL((void*)0);
2252
2253 for (x = 0; x < profile->reg_acl_count; x++) {
2254 last_acl = profile->reg_acl[x];
2255 if (!(ok = switch_check_network_list_ip_token(network_ip, last_acl, &token_sw))) {
2256 break;
2257 }
2258 }
2259
2260 if (ok && !sofia_test_pflag(profile, PFLAG_BLIND_REG)((profile)->pflags[PFLAG_BLIND_REG] ? 1 : 0)) {
2261 type = REG_AUTO_REGISTER;
2262 acl_token = token_sw;
2263 } else if (!ok) {
2264 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2264, ((void*)0)
, SWITCH_LOG_WARNING, "IP %s Rejected by register acl \"%s\"\n", network_ip, profile->reg_acl[x]);
2265 nua_respond(nh, SIP_403_FORBIDDEN403, sip_403_Forbidden, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
2266 goto end;
2267 }
2268 }
2269
2270 if (!sip || !sip->sip_request || !sip->sip_request->rq_method_name) {
2271 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2271, ((void*)0)
, SWITCH_LOG_ERROR, "Received an invalid packet!\n");
2272 nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error, TAG_END()(tag_type_t)0, (tag_value_t)0);
2273 goto end;
2274 }
2275
2276 if (is_nat && profile->local_network && switch_check_network_list_ip(network_ip, profile->local_network)switch_check_network_list_ip_token(network_ip, profile->local_network
, ((void*)0))
) {
2277 if (profile->debug) {
2278 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2278, ((void*)0)
, SWITCH_LOG_DEBUG, "IP %s is on local network, not seting NAT mode.\n", network_ip);
2279 }
2280 is_nat = NULL((void*)0);
2281 }
2282
2283 sofia_reg_handle_register_token(nua, profile, nh, sip, de, type, key, sizeof(key), &v_event, is_nat, sofia_private_p, NULL((void*)0), acl_token);
2284
2285 if (v_event) {
2286 switch_event_destroy(&v_event);
2287 }
2288
2289 end:
2290
2291 if (!sofia_private_p || !*sofia_private_p) nua_handle_destroy(nh);
2292
2293}
2294
2295
2296void sofia_reg_handle_sip_r_register(int status,
2297 char const *phrase,
2298 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
2299 sofia_dispatch_event_t *de,
2300 tagi_t tags[])
2301{
2302 sofia_gateway_t *gateway = NULL((void*)0);
2303
2304
2305 if (!sofia_private) {
2306 nua_handle_destroy(nh);
2307 return;
2308 }
2309
2310 if (sofia_private && !zstr(sofia_private->gateway_name)_zstr(sofia_private->gateway_name)) {
2311 gateway = sofia_reg_find_gateway(sofia_private->gateway_name)sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 2311, sofia_private->gateway_name)
;
2312 }
2313
2314 if (sofia_private && gateway) {
2315 reg_state_t ostate = gateway->state;
2316 switch (status) {
2317 case 200:
2318 if (sip && sip->sip_contact) {
2319 sip_contact_t *contact = sip->sip_contact;
2320 const char *new_expires;
2321 uint32_t expi;
2322 if (contact->m_next) {
2323 char *full;
2324
2325 for (; contact; contact = contact->m_next) {
2326 if ((full = sip_header_as_string(nh->nh_home, (void *) contact))) {
2327 if (switch_stristr(gateway->register_contact, full)) {
2328 break;
2329 }
2330
2331 su_free(nh->nh_home, full);
2332 }
2333 }
2334 }
2335
2336 if (!contact) {
2337 contact = sip->sip_contact;
2338 }
2339
2340 if (contact->m_expires) {
2341 new_expires = contact->m_expires;
2342 expi = (uint32_t) atoi(new_expires);
2343
2344 if (expi > 0 && expi != gateway->freq) {
2345 //gateway->freq = expi;
2346 //gateway->expires_str = switch_core_sprintf(gateway->pool, "%d", expi);
2347
2348 if (expi > 60) {
2349 gateway->expires = switch_epoch_time_now(NULL((void*)0)) + (expi - 15);
2350 } else {
2351 gateway->expires = switch_epoch_time_now(NULL((void*)0)) + (expi - 2);
2352 }
2353
2354
2355 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2355, ((void*)0)
, SWITCH_LOG_DEBUG,
2356 "Changing expire time to %d by request of proxy %s\n", expi, gateway->register_proxy);
2357 }
2358 }
2359 }
2360 gateway->state = REG_STATE_REGISTER;
2361 break;
2362 case 100:
2363 break;
2364 default:
2365 gateway->state = REG_STATE_FAILED;
2366 gateway->failure_status = status;
2367 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2367, ((void*)0)
, SWITCH_LOG_ERROR, "%s Failed Registration with status %s [%d]. failure #%d\n",
2368 gateway->name, switch_str_nil(phrase)(phrase ? phrase : ""), status, ++gateway->failures);
2369 break;
2370 }
2371 if (ostate != gateway->state) {
2372 sofia_reg_fire_custom_gateway_state_event(gateway, status, phrase);
2373 }
2374 }
2375
2376 if (gateway) {
2377 sofia_reg_release_gateway(gateway)sofia_reg_release_gateway__("sofia_reg.c", (const char *)__func__
, 2377, gateway);
;
2378 }
2379
2380}
2381
2382void sofia_reg_handle_sip_r_challenge(int status,
2383 char const *phrase,
2384 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private,
2385 switch_core_session_t *session, sofia_gateway_t *gateway, sip_t const *sip,
2386 sofia_dispatch_event_t *de, tagi_t tags[])
2387{
2388 sip_www_authenticate_t const *authenticate = NULL((void*)0);
2389 char const *realm = NULL((void*)0);
2390 char const *scheme = NULL((void*)0);
2391 int indexnum;
2392 char *cur;
2393 char authentication[256] = "";
2394 int ss_state;
2395 sofia_gateway_t *var_gateway = NULL((void*)0);
2396 const char *gw_name = NULL((void*)0);
2397 switch_channel_t *channel = NULL((void*)0);
2398 const char *sip_auth_username = NULL((void*)0);
2399 const char *sip_auth_password = NULL((void*)0);
2400 char *dup_user = NULL((void*)0);
2401 char *dup_pass = NULL((void*)0);
2402
2403 if (session && (channel = switch_core_session_get_channel(session))) {
2404 sip_auth_username = switch_channel_get_variable(channel, "sip_auth_username")switch_channel_get_variable_dup(channel, "sip_auth_username",
SWITCH_TRUE, -1)
;
2405 sip_auth_password = switch_channel_get_variable(channel, "sip_auth_password")switch_channel_get_variable_dup(channel, "sip_auth_password",
SWITCH_TRUE, -1)
;
2406 }
2407
2408 if (sofia_private) {
2409 if (*sofia_private->auth_gateway_name) {
2410 gw_name = sofia_private->auth_gateway_name;
2411 } else if (*sofia_private->gateway_name) {
2412 gw_name = sofia_private->gateway_name;
2413 }
2414 }
2415
2416 if (session) {
2417 private_object_t *tech_pvt;
2418
2419 if ((tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
) && sofia_test_flag(tech_pvt, TFLAG_REFER)((tech_pvt)->flags[TFLAG_REFER] ? 1 : 0)) {
2420 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2420, (const char*)(session)
, SWITCH_LOG_DEBUG, "Received reply from REFER\n");
2421 goto end;
2422 }
2423
2424 gw_name = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_use_gateway")switch_channel_get_variable_dup(switch_core_session_get_channel
(session), "sip_use_gateway", SWITCH_TRUE, -1)
;
2425 }
2426
2427
2428 if (sip->sip_www_authenticate) {
2429 authenticate = sip->sip_www_authenticate;
2430 } else if (sip->sip_proxy_authenticate) {
2431 authenticate = sip->sip_proxy_authenticate;
2432 } else {
2433 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2433, (const char*)(session)
, SWITCH_LOG_DEBUG, "Missing Authenticate Header!\n");
2434 goto end;
2435 }
2436
2437
2438 scheme = (char const *) authenticate->au_scheme;
2439
2440 if (zstr(scheme)_zstr(scheme)) {
2441 scheme = "Digest";
2442 }
2443
2444 if (authenticate->au_params) {
2445 for (indexnum = 0; (cur = (char *) authenticate->au_params[indexnum]); indexnum++) {
2446 if ((realm = strstr(cur, "realm="))) {
2447 realm += 6;
2448 break;
2449 }
2450 }
2451
2452 if (zstr(realm)_zstr(realm)) {
2453 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2453, (const char*)(session)
, SWITCH_LOG_ERROR, "Realm: [%s] is invalid\n", switch_str_nil(realm)(realm ? realm : ""));
2454
2455 for (indexnum = 0; (cur = (char *) authenticate->au_params[indexnum]); indexnum++) {
2456 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2456, (const char*)(session)
, SWITCH_LOG_ERROR, "DUMP: [%s]\n", cur);
2457 }
2458 goto end;
2459 }
2460 } else {
2461 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2461, (const char*)(session)
, SWITCH_LOG_ERROR, "NO AUTHENTICATE PARAMS\n");
2462 goto end;
2463 }
2464
2465 if (!gateway) {
2466 if (gw_name) {
2467 var_gateway = sofia_reg_find_gateway((char *) gw_name)sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 2467, (char *) gw_name)
;
2468 }
2469
2470
2471 if (!var_gateway && realm) {
2472 char rb[512] = "";
2473 char *p = (char *) realm;
2474 while (*p == '"') {
2475 p++;
2476 }
2477 switch_set_string(rb, p)switch_copy_string(rb, p, sizeof(rb));
2478 if ((p = strchr(rb, '"')(__extension__ (__builtin_constant_p ('"') && !__builtin_constant_p
(rb) && ('"') == '\0' ? (char *) __rawmemchr (rb, '"'
) : __builtin_strchr (rb, '"')))
)) {
2479 *p = '\0';
2480 }
2481 if (!(var_gateway = sofia_reg_find_gateway(rb)sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 2481, rb)
)) {
2482 var_gateway = sofia_reg_find_gateway_by_realm(rb)sofia_reg_find_gateway_by_realm__("sofia_reg.c", (const char *
)__func__, 2482, rb)
;
2483 }
2484 }
2485
2486 if (!var_gateway && sip && sip->sip_to) {
2487 var_gateway = sofia_reg_find_gateway(sip->sip_to->a_url->url_host)sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 2487, sip->sip_to->a_url->url_host)
;
2488 }
2489
2490 if (var_gateway) {
2491 gateway = var_gateway;
2492 }
2493 }
2494
2495 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) {
2496 switch_xml_t x_user, x_param, x_params;
2497 switch_event_t *locate_params;
2498
2499 switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2499, &locate_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
2500 switch_assert(locate_params)((locate_params) ? (void) (0) : __assert_fail ("locate_params"
, "sofia_reg.c", 2500, __PRETTY_FUNCTION__))
;
2501
2502 switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "reverse-auth-lookup");
2503
2504 if ( sip->sip_call_id ) {
2505 switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "sip_call_id", sip->sip_call_id->i_id);
2506 }
2507
2508 if (switch_xml_locate_user_merged("id", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, NULL((void*)0),
2509 &x_user, locate_params) == SWITCH_STATUS_SUCCESS) {
2510 if ((x_params = switch_xml_child(x_user, "params"))) {
2511 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
2512 const char *var = switch_xml_attr_soft(x_param, "name");
2513 const char *val = switch_xml_attr_soft(x_param, "value");
2514
2515 if (!strcasecmp(var, "reverse-auth-user")) {
2516 dup_user = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2517 sip_auth_username = dup_user;
2518 } else if (!strcasecmp(var, "reverse-auth-pass")) {
2519 dup_pass = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2520 sip_auth_password = dup_pass;
2521 }
2522 }
2523
2524 switch_xml_free(x_user);
2525 }
2526 }
2527
2528 switch_event_destroy(&locate_params);
2529 }
2530
2531 if (sip_auth_username && sip_auth_password) {
2532 switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, sip_auth_username, sip_auth_password);
2533 } else if (gateway) {
2534 switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, gateway->auth_username, gateway->register_password);
2535 } else {
2536 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2536, (const char*)(session)
, SWITCH_LOG_ERROR,
2537 "Cannot locate any authentication credentials to complete an authentication request for realm '%s'\n", realm);
2538 goto cancel;
2539 }
2540
2541 if (profile->debug) {
2542 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "sofia_reg.c", (const char *)__func__
, 2542, (const char*)(session)
, SWITCH_LOG_DEBUG, "Authenticating '%s' with '%s'.\n",
2543 (sip_auth_username && sip_auth_password) ? sip_auth_username : gateway->auth_username, authentication);
2544 }
2545
2546 ss_state = nua_callstate_authenticating;
2547
2548 tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state)nutag_callstate_ref, tag_int_vr(&(ss_state)), SIPTAG_WWW_AUTHENTICATE_REF(authenticate)siptag_www_authenticate_ref, siptag_www_authenticate_vr(&
(authenticate))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
2549
2550 nua_authenticate(nh,
2551 TAG_IF(gateway, SIPTAG_EXPIRES_STR(gateway ? gateway->expires_str : "3600"))!(gateway) ? tag_skip : siptag_expires_str, tag_str_v(gateway
? gateway->expires_str : "3600")
,
2552 NUTAG_AUTH(authentication)nutag_auth, tag_str_v(authentication), TAG_END()(tag_type_t)0, (tag_value_t)0);
2553
2554 goto end;
2555
2556 cancel:
2557
2558 if (session) {
2559 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_MANDATORY_IE_MISSING)switch_channel_perform_hangup(switch_core_session_get_channel
(session), "sofia_reg.c", (const char *)__func__, 2559, SWITCH_CAUSE_MANDATORY_IE_MISSING
)
;
2560 } else {
2561 nua_cancel(nh, SIPTAG_CONTACT(SIP_NONE)siptag_contact, siptag_contact_v(((void const *)-1L)), TAG_END()(tag_type_t)0, (tag_value_t)0);
2562 }
2563
2564 end:
2565
2566
2567 switch_safe_free(dup_user)if (dup_user) {free(dup_user);dup_user=((void*)0);};
2568 switch_safe_free(dup_pass)if (dup_pass) {free(dup_pass);dup_pass=((void*)0);};
2569
2570 if (var_gateway) {
2571 sofia_reg_release_gateway(var_gateway)sofia_reg_release_gateway__("sofia_reg.c", (const char *)__func__
, 2571, var_gateway);
;
2572 }
2573
2574 return;
2575
2576
2577
2578}
2579
2580typedef struct {
2581 char *nonce;
2582 switch_size_t nplen;
2583 int last_nc;
2584} nonce_cb_t;
2585
2586static int sofia_reg_nonce_callback(void *pArg, int argc, char **argv, char **columnNames)
2587{
2588 nonce_cb_t *cb = (nonce_cb_t *) pArg;
2589 switch_copy_string(cb->nonce, argv[0], cb->nplen);
2590 if (argc == 2) {
2591 cb->last_nc = zstr(argv[1])_zstr(argv[1]) ? 0 : atoi(argv[1]);
2592 } else {
2593 cb->last_nc = 0;
2594 }
2595 return 0;
2596}
2597
2598static int sofia_reg_regcount_callback(void *pArg, int argc, char **argv, char **columnNames)
2599{
2600 int *ret = (int *) pArg;
2601 if (argc == 1) {
2602 *ret = atoi(argv[0]);
2603 }
2604 return 0;
2605}
2606
2607auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
2608 sip_authorization_t const *authorization,
2609 sip_t const *sip,
2610 sofia_dispatch_event_t *de,
2611 const char *regstr,
2612 char *np,
2613 size_t nplen,
2614 char *ip,
2615 int network_port,
2616 switch_event_t **v_event,
2617 long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count, switch_xml_t *user_xml)
2618{
2619 int indexnum;
2620 const char *cur;
2621 su_md5_t ctx;
2622 char uridigest[2 * SU_MD5_DIGEST_SIZE16 + 1];
2623 char bigdigest[2 * SU_MD5_DIGEST_SIZE16 + 1];
2624 char *username, *realm, *nonce, *uri, *qop, *cnonce, *nc, *response, *input = NULL((void*)0), *input2 = NULL((void*)0);
2625 auth_res_t ret = AUTH_FORBIDDEN;
2626 int first = 0;
2627 const char *passwd = NULL((void*)0);
2628 const char *a1_hash = NULL((void*)0);
2629 const char *mwi_account = NULL((void*)0);
2630 switch_bool_t allow_empty_password = SWITCH_TRUE;
2631 const char *call_id = NULL((void*)0);
2632 char *sql;
2633 char *number_alias = NULL((void*)0);
2634 switch_xml_t user = NULL((void*)0), param, uparams;
2635 char hexdigest[2 * SU_MD5_DIGEST_SIZE16 + 1] = "";
2636 char *domain_name = NULL((void*)0);
2637 switch_event_t *params = NULL((void*)0);
2638 const char *auth_acl = NULL((void*)0);
2639 long ncl = 0;
2640 sip_unknown_t *un;
2641 const char *user_agent = NULL((void*)0);
2642 const char *user_agent_filter = profile->user_agent_filter;
2643 uint32_t max_registrations_perext = profile->max_registrations_perext;
2644 char client_port[16];
2645 snprintf(client_port, 15, "%d", network_port);
2646
2647 username = realm = nonce = uri = qop = cnonce = nc = response = NULL((void*)0);
2648
2649 if (authorization->au_params) {
2650 for (indexnum = 0; (cur = authorization->au_params[indexnum]); indexnum++) {
2651 char *var, *val, *p, *work;
2652 var = val = work = NULL((void*)0);
2653 if ((work = strdup(cur)(__extension__ (__builtin_constant_p (cur) && ((size_t
)(const void *)((cur) + 1) - (size_t)(const void *)(cur) == 1
) ? (((const char *) (cur))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (cur) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, cur, __len); __retval
; })) : __strdup (cur)))
)) {
2654 var = work;
2655 if ((val = strchr(var, '=')(__extension__ (__builtin_constant_p ('=') && !__builtin_constant_p
(var) && ('=') == '\0' ? (char *) __rawmemchr (var, '='
) : __builtin_strchr (var, '=')))
)) {
2656 *val++ = '\0';
2657 while (*val == '"') {
2658 *val++ = '\0';
2659 }
2660 if ((p = strchr(val, '"')(__extension__ (__builtin_constant_p ('"') && !__builtin_constant_p
(val) && ('"') == '\0' ? (char *) __rawmemchr (val, '"'
) : __builtin_strchr (val, '"')))
)) {
2661 *p = '\0';
2662 }
2663
2664 if (!strcasecmp(var, "username") && !username) {
2665 username = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2666 } else if (!strcasecmp(var, "realm") && !realm) {
2667 realm = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2668 } else if (!strcasecmp(var, "nonce") && !nonce) {
2669 nonce = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2670 } else if (!strcasecmp(var, "uri") && !uri) {
2671 uri = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2672 } else if (!strcasecmp(var, "qop") && !qop) {
2673 qop = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2674 } else if (!strcasecmp(var, "cnonce") && !cnonce) {
2675 cnonce = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2676 } else if (!strcasecmp(var, "response") && !response) {
2677 response = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2678 } else if (!strcasecmp(var, "nc") && !nc) {
2679 nc = strdup(val)(__extension__ (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) ? (((const char *) (val))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (val) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, val, __len); __retval
; })) : __strdup (val)))
;
2680 }
2681 }
2682
2683 free(work);
2684 }
2685 }
2686 }
2687
2688 if (!(username && realm && nonce && uri && response)) {
2689 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2689, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid Authorization header!\n");
2690 ret = AUTH_STALE;
2691 goto end;
2692 }
2693
2694 /* Optional check that auth name == SIP username */
2695 if ((regtype == REG_REGISTER) && sofia_test_pflag(profile, PFLAG_CHECKUSER)((profile)->pflags[PFLAG_CHECKUSER] ? 1 : 0)) {
2696 if (zstr(username)_zstr(username) || zstr(to_user)_zstr(to_user) || strcasecmp(to_user, username)) {
2697 /* Names don't match, so fail */
2698 if (profile->debug) {
2699 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2699, ((void*)0)
, SWITCH_LOG_DEBUG, "SIP username %s does not match auth username\n", switch_str_nil(to_user)(to_user ? to_user : ""));
2700 }
2701 goto end;
2702 }
2703 }
2704
2705 user_agent = (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown";
2706
2707 if (zstr(np)_zstr(np)) {
2708 nonce_cb_t cb = { 0 };
2709 long nc_long = 0;
2710
2711 first = 1;
2712
2713 if (nc) {
2714 nc_long = strtoul(nc, 0, 16);
2715 sql = switch_mprintf("select nonce,last_nc from sip_authentication where nonce='%q' and last_nc < %lu", nonce, nc_long);
2716 } else {
2717 sql = switch_mprintf("select nonce from sip_authentication where nonce='%q'", nonce);
2718 }
2719
2720 cb.nonce = np;
2721 cb.nplen = nplen;
2722
2723 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_reg.c", 2723, __PRETTY_FUNCTION__))
;
2724
2725 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nonce_callback, &cb);
2726 free(sql);
2727
2728 //if (!sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, np, nplen)) {
2729 if (zstr(np)_zstr(np)) {
2730 sql = switch_mprintf("delete from sip_authentication where nonce='%q'", nonce);
2731 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2732 ret = AUTH_STALE;
2733 goto end;
2734 }
2735
2736 if (reg_count) {
2737 *reg_count = cb.last_nc + 1;
2738 }
2739 }
2740
2741 switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 2741, &params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
2742 switch_assert(params)((params) ? (void) (0) : __assert_fail ("params", "sofia_reg.c"
, 2742, __PRETTY_FUNCTION__))
;
2743 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "sip_auth");
2744 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
2745 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_user_agent", user_agent);
2746 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_username", username);
2747 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_realm", realm);
2748 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_nonce", nonce);
2749 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_uri", uri);
2750
2751 if (sip->sip_contact) {
2752 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_contact_user", sip->sip_contact->m_url->url_user);
2753 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_contact_host", sip->sip_contact->m_url->url_host);
2754 }
2755
2756 if (sip->sip_to) {
2757 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_user", sip->sip_to->a_url->url_user);
2758 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_host", sip->sip_to->a_url->url_host);
2759 if (sip->sip_to->a_url->url_port) {
2760 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_port", sip->sip_to->a_url->url_port);
2761 }
2762 }
2763
2764 if (sip->sip_via) {
2765 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_via_protocol", sofia_glue_transport2str(sofia_glue_via2transport(sip->sip_via)));
2766 }
2767
2768
2769 if (sip->sip_from) {
2770 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_user", sip->sip_from->a_url->url_user);
2771 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_host", sip->sip_from->a_url->url_host);
2772 if (sip->sip_from->a_url->url_port) {
2773 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_port", sip->sip_from->a_url->url_port);
2774 }
2775 }
2776
2777 if (sip->sip_call_id && sip->sip_call_id->i_id) {
2778 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_call_id", sip->sip_call_id->i_id);
2779 }
2780
2781
2782 if (sip->sip_request) {
2783 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_user", sip->sip_request->rq_url->url_user);
2784 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_host", sip->sip_request->rq_url->url_host);
2785 if (sip->sip_request->rq_url->url_port) {
2786 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_port", sip->sip_request->rq_url->url_port);
2787 }
2788 }
2789
2790 for (un = sip->sip_unknown; un; un = un->un_next) {
2791 if (!strncasecmp(un->un_name, "X-", 2)) {
2792 if (!zstr(un->un_value)_zstr(un->un_value)) {
2793 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2793, ((void*)0)
, SWITCH_LOG_DEBUG10, "adding %s => %s to xml_curl request\n", un->un_name, un->un_value);
2794 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);
2795 }
2796 } else {
2797 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2797, ((void*)0)
, SWITCH_LOG_DEBUG10, "skipping %s => %s from xml_curl request\n", un->un_name, un->un_value);
2798 }
2799 }
2800
2801 if (qop) {
2802 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_qop", qop);
2803 }
2804 if (cnonce) {
2805 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_cnonce", cnonce);
2806 }
2807 if (nc) {
2808 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_nc", nc);
2809 }
2810 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_response", response);
2811
2812 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_method", (sip && sip->sip_request) ? sip->sip_request->rq_method_name : NULL((void*)0));
2813
2814 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "client_port", client_port);
2815 if (auth_params) {
2816 switch_event_dup(auth_params, params);
2817 }
2818
2819
2820 if (!zstr(profile->reg_domain)_zstr(profile->reg_domain)) {
2821 domain_name = profile->reg_domain;
2822 } else {
2823 domain_name = realm;
2824 }
2825
2826 if (switch_xml_locate_user_merged("id", zstr(username)_zstr(username) ? "nobody" : username, domain_name, ip, &user, params) != SWITCH_STATUS_SUCCESS) {
2827 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2827, ((void*)0)
, SWITCH_LOG_WARNING, "Can't find user [%s@%s] from %s\n"
2828 "You must define a domain called '%s' in your directory and add a user with the id=\"%s\" attribute\n"
2829 "and you must configure your device to use the proper domain in it's authentication credentials.\n", username, domain_name,
2830 ip, domain_name, username);
2831
2832 ret = AUTH_FORBIDDEN;
2833 goto end;
2834 } else {
2835 const char *type = switch_xml_attr(user, "type");
2836 if (type && !strcasecmp(type, "pointer")) {
2837 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2837, ((void*)0)
, SWITCH_LOG_WARNING, "Cant register a pointer.\n");
2838 ret = AUTH_FORBIDDEN;
2839 goto end;
2840 }
2841 }
2842
2843 if (!(number_alias = (char *) switch_xml_attr(user, "number-alias"))) {
2844 number_alias = zstr(username)_zstr(username) ? "nobody" : username;
2845 }
2846
2847 if (!(uparams = switch_xml_child(user, "params"))) {
2848 ret = AUTH_OK;
2849 goto skip_auth;
2850 } else {
2851 for (param = switch_xml_child(uparams, "param"); param; param = param->next) {
2852 const char *var = switch_xml_attr_soft(param, "name");
2853 const char *val = switch_xml_attr_soft(param, "value");
2854
2855 if (!strcasecmp(var, "sip-forbid-register") && switch_true(val)) {
2856 ret = AUTH_FORBIDDEN;
2857 goto end;
2858 }
2859
2860 if (!strcasecmp(var, "password")) {
2861 passwd = val;
2862 }
2863
2864 if (!strcasecmp(var, "auth-acl")) {
2865 auth_acl = val;
2866 }
2867
2868 if (!strcasecmp(var, "a1-hash")) {
2869 a1_hash = val;
2870 }
2871 if (!strcasecmp(var, "mwi-account")) {
2872 mwi_account = val;
2873 }
2874 if (!strcasecmp(var, "allow-empty-password")) {
2875 allow_empty_password = switch_true(val);
2876 }
2877 if (!strcasecmp(var, "user-agent-filter")) {
2878 user_agent_filter = val;
2879 }
2880 if (!strcasecmp(var, "max-registrations-per-extension")) {
2881 max_registrations_perext = atoi(val);
2882 }
2883 }
2884 }
2885
2886 if (auth_acl) {
2887 if (!switch_check_network_list_ip(ip, auth_acl)switch_check_network_list_ip_token(ip, auth_acl, ((void*)0))) {
2888 int network_ip_is_proxy = 0;
2889 uint32_t x = 0;
2890 char *last_acl = NULL((void*)0);
2891 if (profile->proxy_acl_count == 0) {
2892 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2892, ((void*)0)
, SWITCH_LOG_WARNING, "IP %s Rejected by user acl [%s] and no proxy acl present\n", ip, auth_acl);
2893 ret = AUTH_FORBIDDEN;
2894 goto end;
2895 } else {
2896 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2896, ((void*)0)
, SWITCH_LOG_DEBUG, "IP %s Rejected by user acl [%s] checking proxy ACLs now\n", ip, auth_acl);
2897 }
2898 /* Check if network_ip is a proxy allowed to send us calls */
2899 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2899, ((void*)0)
, SWITCH_LOG_DEBUG, "%d acls to check for proxy\n", profile->proxy_acl_count);
2900
2901 for (x = 0; x < profile->proxy_acl_count; x++) {
2902 last_acl = profile->proxy_acl[x];
2903 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2903, ((void*)0)
, SWITCH_LOG_DEBUG, "checking %s against acl %s\n", ip, last_acl);
2904 if (switch_check_network_list_ip(ip, last_acl)switch_check_network_list_ip_token(ip, last_acl, ((void*)0))) {
2905 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2905, ((void*)0)
, SWITCH_LOG_DEBUG, "%s is a proxy according to the %s acl\n", ip, last_acl);
2906 network_ip_is_proxy = 1;
2907 break;
2908 }
2909 }
2910 /*
2911 * if network_ip is a proxy allowed to send traffic, check for auth
2912 * ip header and see if it matches against the auth acl
2913 */
2914 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2914, ((void*)0)
, SWITCH_LOG_DEBUG, "network ip is a proxy [%d]\n", network_ip_is_proxy);
2915 if (network_ip_is_proxy) {
2916 int x_auth_ip = 0;
2917 for (un = sip->sip_unknown; un; un = un->un_next) {
2918 if (!strcasecmp(un->un_name, "X-AUTH-IP")) {
2919 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2919, ((void*)0)
, SWITCH_LOG_DEBUG, "found auth ip [%s] header of [%s]\n", un->un_name, un->un_value);
2920 if (!zstr(un->un_value)_zstr(un->un_value)) {
2921 if (!switch_check_network_list_ip(un->un_value, auth_acl)switch_check_network_list_ip_token(un->un_value, auth_acl,
((void*)0))
) {
2922 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2922, ((void*)0)
, SWITCH_LOG_WARNING, "IP %s Rejected by user acl %s\n", un->un_value, auth_acl);
2923 ret = AUTH_FORBIDDEN;
2924 goto end;
2925 } else {
2926 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2926, ((void*)0)
, SWITCH_LOG_DEBUG,
2927 "IP %s allowed by acl %s, checking credentials\n", un->un_value, auth_acl);
2928 x_auth_ip = 1;
2929 break;
2930 }
2931 }
2932 }
2933 }
2934 if (!x_auth_ip) {
2935 ret = AUTH_FORBIDDEN;
2936 goto end;
2937 }
2938 }
2939 } else {
2940 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2940, ((void*)0)
, SWITCH_LOG_DEBUG, "IP [%s] passed ACL check [%s]\n", ip, auth_acl);
2941 }
2942 }
2943
2944 if (!allow_empty_password && zstr(passwd)_zstr(passwd) && zstr(a1_hash)_zstr(a1_hash)) {
2945 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2945, ((void*)0)
, SWITCH_LOG_WARNING, "Empty password denied for user %s@%s\n", username, domain_name);
2946 ret = AUTH_FORBIDDEN;
2947 goto end;
2948 }
2949
2950 if (zstr(passwd)_zstr(passwd) && zstr(a1_hash)_zstr(a1_hash)) {
2951 ret = AUTH_OK;
2952 goto skip_auth;
2953 }
2954
2955 if (!a1_hash) {
2956 input = switch_mprintf("%s:%s:%s", username, realm, passwd);
2957 su_md5_init(&ctx);
2958 su_md5_strupdate(&ctx, input);
2959 su_md5_hexdigest(&ctx, hexdigest);
2960 su_md5_deinit(&ctx);
2961 switch_safe_free(input)if (input) {free(input);input=((void*)0);};
2962 a1_hash = hexdigest;
2963
2964 }
2965
2966 if (user_agent_filter) {
2967 if (switch_regex_match(user_agent, user_agent_filter) == SWITCH_STATUS_SUCCESS) {
2968 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)((profile)->pflags[PFLAG_LOG_AUTH_FAIL] ? 1 : 0)) {
2969 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2969, ((void*)0)
, SWITCH_LOG_DEBUG,
2970 "SIP auth OK (REGISTER) due to user-agent-filter. Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter, user_agent);
2971 }
2972 } else {
2973 ret = AUTH_FORBIDDEN;
2974 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)((profile)->pflags[PFLAG_LOG_AUTH_FAIL] ? 1 : 0)) {
2975 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
2975, ((void*)0)
, SWITCH_LOG_WARNING,
2976 "SIP auth failure (REGISTER) due to user-agent-filter. Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter,
2977 user_agent);
2978 }
2979 goto end;
2980 }
2981 }
2982
2983 /* The max-registrations-per-extension-option only affects REGISTER-authentications */
2984 if ((REG_REGISTER == regtype || REG_AUTO_REGISTER == regtype) && max_registrations_perext > 0 && (sip && sip->sip_contact && (sip->sip_contact->m_expires == NULL((void*)0) || atol(sip->sip_contact->m_expires) > 0))) {
2985 /* if expires is null still process */
2986 /* expires == 0 means the phone is going to unregiser, so don't count against max */
2987 uint32_t count = 0;
2988
2989 call_id = sip->sip_call_id->i_id;
2990 switch_assert(call_id)((call_id) ? (void) (0) : __assert_fail ("call_id", "sofia_reg.c"
, 2990, __PRETTY_FUNCTION__))
;
2991
2992 sql = switch_mprintf("select count(sip_user) from sip_registrations where sip_user='%q' AND call_id <> '%q'", username, call_id);
2993 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_reg.c", 2993, __PRETTY_FUNCTION__))
;
2994 sofia_glue_execute_sql_callback(profile, NULL((void*)0), sql, sofia_reg_regcount_callback, &count);
2995 free(sql);
2996
2997 if (count + 1 > max_registrations_perext) {
2998 ret = AUTH_FORBIDDEN;
2999 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)((profile)->pflags[PFLAG_LOG_AUTH_FAIL] ? 1 : 0)) {
3000 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
3000, ((void*)0)
, SWITCH_LOG_WARNING,
3001 "SIP auth failure (REGISTER) due to reaching max allowed registrations. Count: %d\n", count);
3002 }
3003 goto end;
3004 }
3005 }
3006
3007 for_the_sake_of_interop:
3008
3009 if ((input = switch_mprintf("%s:%q", regstr, uri))) {
3010 su_md5_init(&ctx);
3011 su_md5_strupdate(&ctx, input);
3012 su_md5_hexdigest(&ctx, uridigest);
3013 su_md5_deinit(&ctx);
3014 }
3015
3016 if (nc && cnonce && qop) {
3017 input2 = switch_mprintf("%s:%s:%s:%s:%s:%s", a1_hash, nonce, nc, cnonce, qop, uridigest);
3018 } else {
3019 input2 = switch_mprintf("%s:%s:%s", a1_hash, nonce, uridigest);
3020 }
3021
3022 if (input2) {
3023 memset(&ctx, 0, sizeof(ctx));
3024 su_md5_init(&ctx);
3025 su_md5_strupdate(&ctx, input2);
3026 su_md5_hexdigest(&ctx, bigdigest);
3027 su_md5_deinit(&ctx);
3028 }
3029
3030 if (input2 && !strcasecmp(bigdigest, response)) {
3031 ret = AUTH_OK;
3032 } else {
3033 if ((profile->ndlb & PFLAG_NDLB_BROKEN_AUTH_HASH) && strcasecmp(regstr, "REGISTER") && strcasecmp(regstr, "INVITE")) {
3034 /* some clients send an ACK with the method 'INVITE' in the hash which will break auth so we will
3035 try again with INVITE so we don't get people complaining to us when someone else's client has a bug......
3036 */
3037 switch_safe_free(input)if (input) {free(input);input=((void*)0);};
3038 switch_safe_free(input2)if (input2) {free(input2);input2=((void*)0);};
3039 regstr = "INVITE";
3040 goto for_the_sake_of_interop;
3041 }
3042
3043 ret = AUTH_FORBIDDEN;
3044 }
3045
3046 switch_safe_free(input2)if (input2) {free(input2);input2=((void*)0);};
3047
3048 skip_auth:
3049 if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) {
3050 if (v_event && !*v_event) {
3051 switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS);
3052 }
3053
3054
3055 if (v_event && *v_event) {
3056 short int xparams_type[6];
3057 switch_xml_t xparams[6];
3058 int i = 0;
3059
3060 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_number_alias", number_alias);
3061 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_auth_username", username);
3062 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_auth_realm", realm);
3063 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "number_alias", number_alias);
3064 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "user_name", username);
3065 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "domain_name", domain_name);
3066
3067 if (mwi_account) {
3068 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "mwi-account", mwi_account);
3069 }
3070
3071 if ((uparams = switch_xml_child(user, "params"))) {
3072 xparams_type[i] = 0;
3073 xparams[i++] = uparams;
3074 }
3075
3076 if ((uparams = switch_xml_child(user, "variables"))) {
3077 xparams_type[i] = 1;
3078 xparams[i++] = uparams;
3079 }
3080
3081 if (i <= 6) {
3082 int j = 0;
3083 const char *gw_val = NULL((void*)0);
3084
3085 for (j = 0; j < i; j++) {
3086 for (param = switch_xml_child(xparams[j], (xparams_type[j] ? "variable" : "param")); param; param = param->next) {
3087 const char *var = switch_xml_attr_soft(param, "name");
3088 const char *val = switch_xml_attr_soft(param, "value");
3089
3090 if (!zstr(var)_zstr(var) && !zstr(val)_zstr(val) && (xparams_type[j] == 1 || !strncasecmp(var, "sip-", 4) || !strcasecmp(var, "register-gateway"))) {
3091 if (profile->debug) {
3092 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
3092, ((void*)0)
, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
3093 }
3094 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
3095 }
3096 }
3097 }
3098 if ((gw_val = switch_event_get_header(*v_event, "register-gateway")switch_event_get_header_idx(*v_event, "register-gateway", -1))) {
3099 sofia_gateway_t *gateway_ptr = NULL((void*)0);
3100 if (!strcasecmp(gw_val, "all")) {
3101 switch_xml_t gateways_tag, gateway_tag;
3102 if ((gateways_tag = switch_xml_child(user, "gateways"))) {
3103 for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
3104 char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
3105 if (zstr(name)_zstr(name)) {
3106 name = "anonymous";
3107 }
3108
3109 if ((gateway_ptr = sofia_reg_find_gateway(name)sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 3109, name)
)) {
3110 reg_state_t ostate = gateway_ptr->state;
3111 gateway_ptr->retry = 0;
3112 if (exptime) {
3113 gateway_ptr->state = REG_STATE_UNREGED;
3114 } else {
3115 gateway_ptr->state = REG_STATE_UNREGISTER;
3116 }
3117 if (ostate != gateway_ptr->state) {
3118 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL((void*)0));
3119 }
3120 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("sofia_reg.c", (const char *)__func__
, 3120, gateway_ptr);
;
3121 }
3122
3123 }
3124 }
3125 } else {
3126 int x, argc;
3127 char *mydata, *argv[50];
3128
3129 mydata = strdup(gw_val)(__extension__ (__builtin_constant_p (gw_val) && ((size_t
)(const void *)((gw_val) + 1) - (size_t)(const void *)(gw_val
) == 1) ? (((const char *) (gw_val))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (gw_val)
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, gw_val, __len
); __retval; })) : __strdup (gw_val)))
;
3130 switch_assert(mydata != NULL)((mydata != ((void*)0)) ? (void) (0) : __assert_fail ("mydata != ((void*)0)"
, "sofia_reg.c", 3130, __PRETTY_FUNCTION__))
;
3131
3132 argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
3133
3134 for (x = 0; x < argc; x++) {
3135 if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x])sofia_reg_find_gateway__("sofia_reg.c", (const char *)__func__
, 3135, (char *) argv[x])
)) {
3136 reg_state_t ostate = gateway_ptr->state;
3137 gateway_ptr->retry = 0;
3138 if (exptime) {
3139 gateway_ptr->state = REG_STATE_UNREGED;
3140 } else {
3141 gateway_ptr->state = REG_STATE_UNREGISTER;
3142 }
3143 if (ostate != gateway_ptr->state) {
3144 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL((void*)0));
3145 }
3146 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("sofia_reg.c", (const char *)__func__
, 3146, gateway_ptr);
;
3147 } else {
3148 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
3148, ((void*)0)
, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
3149 }
3150 }
3151
3152 free(mydata);
3153 }
3154 }
3155 }
3156 }
3157 }
3158 end:
3159
3160
3161 if (nc && cnonce && qop) {
3162 ncl = strtoul(nc, 0, 16);
3163
3164 sql = switch_mprintf("update sip_authentication set expires='%ld',last_nc=%lu where nonce='%s'",
3165 (long)switch_epoch_time_now(NULL((void*)0)) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL60) + exptime, ncl, nonce);
3166
3167 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_reg.c", 3167, __PRETTY_FUNCTION__))
;
3168 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3169
3170 if (ret == AUTH_OK)
3171 ret = AUTH_RENEWED;
3172 }
3173
3174 switch_event_destroy(&params);
3175
3176 if (user) {
3177 if (user_xml) {
3178 *user_xml = user;
3179 } else {
3180 switch_xml_free(user);
3181 }
3182 }
3183
3184 switch_safe_free(input)if (input) {free(input);input=((void*)0);};
3185 switch_safe_free(username)if (username) {free(username);username=((void*)0);};
3186 switch_safe_free(realm)if (realm) {free(realm);realm=((void*)0);};
3187 switch_safe_free(nonce)if (nonce) {free(nonce);nonce=((void*)0);};
3188 switch_safe_free(uri)if (uri) {free(uri);uri=((void*)0);};
3189 switch_safe_free(qop)if (qop) {free(qop);qop=((void*)0);};
3190 switch_safe_free(cnonce)if (cnonce) {free(cnonce);cnonce=((void*)0);};
3191 switch_safe_free(nc)if (nc) {free(nc);nc=((void*)0);};
3192 switch_safe_free(response)if (response) {free(response);response=((void*)0);};
3193
3194 if (reg_count && !*reg_count) {
3195 if ((ret == AUTH_OK || ret == AUTH_RENEWED)) {
3196 if (ncl) {
3197 *reg_count = ncl;
3198 } else {
3199 *reg_count = 1;
3200 }
3201 } else {
3202 *reg_count = 0;
3203 }
3204 }
3205
3206 return ret;
3207
3208}
3209
3210
3211sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, int line, const char *key)
3212{
3213 sofia_gateway_t *gateway = NULL((void*)0);
3214
3215 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3216 if ((gateway = (sofia_gateway_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
3217 if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING)((gateway->profile)->pflags[PFLAG_RUNNING] ? 1 : 0) || gateway->deleted) {
3218 gateway = NULL((void*)0);
3219 goto done;
3220 }
3221 if (sofia_reg_gateway_rdlock__(file, func, line, gateway) != SWITCH_STATUS_SUCCESS) {
3222 gateway = NULL((void*)0);
3223 }
3224 }
3225
3226 done:
3227 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3228 return gateway;
3229}
3230
3231
3232sofia_gateway_t *sofia_reg_find_gateway_by_realm__(const char *file, const char *func, int line, const char *key)
3233{
3234 sofia_gateway_t *gateway = NULL((void*)0);
3235 switch_hash_index_t *hi;
3236 const void *var;
3237 void *val;
3238
3239 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3240 for (hi = switch_core_hash_first(mod_sofia_globals.gateway_hash)switch_core_hash_first_iter(mod_sofia_globals.gateway_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
3241 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
3242 if (key && (gateway = (sofia_gateway_t *) val) && !gateway->deleted && gateway->register_realm && !strcasecmp(gateway->register_realm, key)) {
3243 break;
3244 } else {
3245 gateway = NULL((void*)0);
3246 }
3247 }
3248 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
3249
3250 if (gateway) {
3251 if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING)((gateway->profile)->pflags[PFLAG_RUNNING] ? 1 : 0) || gateway->deleted) {
3252 gateway = NULL((void*)0);
3253 goto done;
3254 }
3255 if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
3256 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "Profile %s is locked\n", gateway->profile->name);
3257 gateway = NULL((void*)0);
3258 }
3259 }
3260 if (gateway) {
3261#ifdef SOFIA_DEBUG_RWLOCKS
3262 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);
3263#endif
3264 }
3265
3266 done:
3267 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3268 return gateway;
3269}
3270
3271switch_status_t sofia_reg_gateway_rdlock__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
3272{
3273 switch_status_t status = sofia_glue_profile_rdlock__(file, func, line, gateway->profile);
3274
3275#ifdef SOFIA_DEBUG_RWLOCKS
3276 if (status == SWITCH_STATUS_SUCCESS) {
3277 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);
3278 }
3279#endif
3280
3281 return status;
3282}
3283
3284
3285void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
3286{
3287 switch_thread_rwlock_unlock(gateway->profile->rwlock);
3288#ifdef SOFIA_DEBUG_RWLOCKS
3289 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW UNLOCK %s\n", gateway->profile->name);
3290#endif
3291}
3292
3293switch_status_t sofia_reg_add_gateway(sofia_profile_t *profile, const char *key, sofia_gateway_t *gateway)
3294{
3295 switch_status_t status = SWITCH_STATUS_FALSE;
3296 char *pkey = switch_mprintf("%s::%s", profile->name, key);
3297 sofia_gateway_t *gp;
3298
3299 switch_mutex_lock(profile->gw_mutex);
3300
3301 gateway->next = profile->gateways;
3302 profile->gateways = gateway;
3303
3304 switch_mutex_unlock(profile->gw_mutex);
3305
3306 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3307
3308 if ((gp = switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
3309 if (gp->deleted) {
3310 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
3310, ((void*)0)
, SWITCH_LOG_DEBUG, "Removing deleted gateway from hash.\n");
3311 switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
3312 switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
3313 switch_core_hash_delete(mod_sofia_globals.gateway_hash, key);
3314 }
3315 }
3316
3317 if (!switch_core_hash_find(mod_sofia_globals.gateway_hash, key) && !switch_core_hash_find(mod_sofia_globals.gateway_hash, pkey)) {
3318 status = switch_core_hash_insert(mod_sofia_globals.gateway_hash, key, gateway)switch_core_hash_insert_destructor(mod_sofia_globals.gateway_hash
, key, gateway, ((void*)0))
;
Value stored to 'status' is never read
3319 status = switch_core_hash_insert(mod_sofia_globals.gateway_hash, pkey, gateway)switch_core_hash_insert_destructor(mod_sofia_globals.gateway_hash
, pkey, gateway, ((void*)0))
;
3320 } else {
3321 status = SWITCH_STATUS_FALSE;
3322 }
3323 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3324
3325 free(pkey);
3326
3327 if (status == SWITCH_STATUS_SUCCESS) {
3328 switch_event_t *s_event;
3329 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_reg.c", (const char *)__func__,
3329, ((void*)0)
, SWITCH_LOG_NOTICE, "Added gateway '%s' to profile '%s'\n", gateway->name, gateway->profile->name);
3330 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_ADD)switch_event_create_subclass_detailed("sofia_reg.c", (const char
* )(const char *)__func__, 3330, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::gateway_add")
== SWITCH_STATUS_SUCCESS) {
3331 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Gateway", gateway->name);
3332 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", gateway->profile->name);
3333 switch_event_fire(&s_event)switch_event_fire_detailed("sofia_reg.c", (const char * )(const
char *)__func__, 3333, &s_event, ((void*)0))
;
3334 }
3335 }
3336
3337 return status;
3338}
3339
3340/* For Emacs:
3341 * Local Variables:
3342 * mode:c
3343 * indent-tabs-mode:t
3344 * tab-width:4
3345 * c-basic-offset:4
3346 * End:
3347 * For VIM:
3348 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3349 */