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