File: | src/mod/endpoints/mod_sofia/sofia_reg.c |
Location: | line 3318, column 3 |
Description: | Value stored to 'status' is never read |
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 | |
42 | static 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 | |
67 | static 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 | |
103 | static 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 | |
127 | static 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 | |
147 | void 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 | |
164 | void 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 | |
184 | void 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 | |
212 | void 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 | |
303 | void 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 | |
539 | int 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 | |
555 | int 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 | |
595 | int 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 | |
628 | void 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 | |
660 | int 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 | |
672 | void 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 | |
689 | int 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 | |
736 | void 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 | |
779 | void 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 | |
852 | long 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 | |
867 | void 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 | |
933 | int 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 | |
942 | void 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 | |
982 | void 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 | |
1011 | char *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 | |
1048 | switch_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 | |
1074 | switch_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 | |
1102 | void 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 | |
1138 | uint32_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 | |
1151 | static 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 | |
1178 | void 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 | |
1208 | uint8_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, ®_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 | |
2163 | void 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 | |
2296 | void 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 | |
2382 | void 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 | |
2580 | typedef struct { |
2581 | char *nonce; |
2582 | switch_size_t nplen; |
2583 | int last_nc; |
2584 | } nonce_cb_t; |
2585 | |
2586 | static 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 | |
2598 | static 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 | |
2607 | auth_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(¶ms, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("sofia_reg.c", (const char * )(const char *)__func__, 2741, ¶ms, 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(¶ms); |
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 | |
3211 | sofia_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 | |
3232 | sofia_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 | |
3271 | switch_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 | |
3285 | void 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 | |
3293 | switch_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 | */ |