1 /*
2  * $Id$
3  *
4  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
5  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
6  *
7  * The initial version of this code was written by Dragos Vingarzan
8  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
9  * Fruanhofer Institute. It was and still is maintained in a separate
10  * branch of the original SER. We are therefore migrating it to
11  * Kamailio/SR and look forward to maintaining it from here on out.
12  * 2011/2012 Smile Communications, Pty. Ltd.
13  * ported/maintained/improved by
14  * Jason Penton (jason(dot)penton(at)smilecoms.com and
15  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
16  * effort to add full IMS support to Kamailio/SR using a new and
17  * improved architecture
18  *
19  * NB: Alot of this code was originally part of OpenIMSCore,
20  * FhG Fokus.
21  * Copyright (C) 2004-2006 FhG Fokus
22  * Thanks for great work! This is an effort to
23  * break apart the various CSCF functions into logically separate
24  * components. We hope this will drive wider use. We also feel
25  * that in this way the architecture is more complete and thereby easier
26  * to manage in the Kamailio/SR environment
27  *
28  * This file is part of Kamailio, a free SIP server.
29  *
30  * Kamailio is free software; you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation; either version 2 of the License, or
33  * (at your option) any later version
34  *
35  * Kamailio is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License
41  * along with this program; if not, write to the Free Software
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
43  *
44  */
45 
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include "../../core/sr_module.h"
51 #include "../../core/events.h"
52 #include "../../core/dprint.h"
53 #include "../../core/ut.h"
54 #include "../../lib/ims/ims_getters.h"
55 #include "../tm/tm_load.h"
56 #include "../../core/mod_fix.h"
57 #include "../../core/parser/parse_uri.h"
58 #include "../../core/parser/parse_content.h"
59 #include "../ims_usrloc_pcscf/usrloc.h"
60 #include "../../modules/ims_dialog/dlg_load.h"
61 #include "../../modules/ims_dialog/dlg_hash.h"
62 #include "../cdp/cdp_load.h"
63 #include "../cdp_avp/cdp_avp_mod.h"
64 #include "../../core/cfg/cfg_struct.h"
65 #include "cdpeventprocessor.h"
66 #include "rx_authdata.h"
67 #include "rx_asr.h"
68 #include "rx_str.h"
69 #include "rx_aar.h"
70 #include "ims_qos_mod.h"
71 #include "../../core/parser/sdp/sdp.h"
72 
73 #include "../../lib/ims/useful_defs.h"
74 #include "ims_qos_stats.h"
75 
76 MODULE_VERSION
77 
78 extern gen_lock_t* process_lock; /* lock on the process table */
79 
80 stat_var* stat_aar_timeouts;
81 stat_var* aar_replies_received;
82 stat_var* aar_replies_response_time;
83 
84 str orig_session_key = str_init("originating");
85 str term_session_key = str_init("terminating");
86 
87 int rx_auth_expiry = 7200;
88 
89 int must_send_str = 1;
90 
91 int authorize_video_flow = 1; //by default we authorize resources for video flow descriptions
92 
93 struct tm_binds tmb;
94 struct cdp_binds cdpb;
95 ims_dlg_api_t dlgb;
96 bind_usrloc_t bind_usrloc;
97 cdp_avp_bind_t *cdp_avp;
98 usrloc_api_t ul;
99 
100 int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events or not - default enabled */
101 int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
102 int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
103 
104 int audio_default_bandwidth = 64;
105 int video_default_bandwidth = 128;
106 
107 //If set then any IP in SDP that does not match this regex then filter is added with any in flow description AVP
108 //Very useful for UEs that change ports mid way through call therefore breaking flow description filters
109 str regex_sdp_ip_prefix_to_maintain_in_fd = {0, 0};
110 
111 //If set this will include an additional filter for all existing filters using the next odd port up - as this is the RTCP port
112 int include_rtcp_fd = 0;
113 
114 int cdp_event_list_size_threshold = 0; /**Threshold for size of cdp event list after which a warning is logged */
115 
116 stat_var *aars;
117 stat_var *strs;
118 stat_var *asrs;
119 stat_var *successful_aars;
120 stat_var *successful_strs;
121 
122 static str identifier = {0, 0};
123 static int identifier_size = 0;
124 
125 /** module functions */
126 static int mod_init(void);
127 static int mod_child_init(int);
128 static void mod_destroy(void);
129 
130 static int fixup_aar_register(void** param, int param_no);
131 static int fixup_aar(void** param, int param_no);
132 
133 int * callback_singleton; /*< Callback singleton */
134 
135 int terminate_dialog_on_rx_failure = 1; //this specifies whether a dialog is torn down when a media rx session fails - in some cases you might not want the dialog torn down
136 int delete_contact_on_rx_failure = 1;  //If this is set we delete the contact if the associated signalling bearer is removed
137 
138 
139 str early_qosrelease_reason = {"QoS released", 12};
140 str confirmed_qosrelease_headers = {NULL, 0};
141 
142 
143 /* parameters storage */
144 str rx_dest_realm = str_init("ims.smilecoms.com");
145 /* Only used if we want to force the Rx peer usually this is configured at a stack level and the first request uses realm routing */
146 str rx_forced_peer = str_init("");
147 
148 /* P-CSCF IP address to generate the flows for the UE<->PCSCF signaling path */
149 str af_signaling_ip = str_init("127.0.0.1");
150 
151 
152 /* commands wrappers and fixups */
153 static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *id, int id_type);
154 static int w_rx_aar_register(struct sip_msg *msg, char *route, char* str1, char *bar);
155 
156 struct _pv_req_data {
157 		struct cell *T;
158 		struct sip_msg msg;
159 		struct sip_msg *tmsgp;
160 		char *buf;
161 		int buf_size;
162   msg_ctx_id_t msg_ctx;
163 };
164 
165 static struct _pv_req_data _pv_treq;
166 
pv_tmx_data_init(void)167 static void pv_tmx_data_init(void)
168 {
169 		memset(&_pv_treq, 0, sizeof(struct _pv_req_data));
170 }
171 
pv_t_copy_msg(struct sip_msg * src,struct sip_msg * dst)172 static int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst)
173 {
174 		dst->id = src->id;
175 		dst->rcv = src->rcv;
176 		dst->set_global_address = src->set_global_address;
177 		dst->set_global_port = src->set_global_port;
178 		dst->flags = src->flags;
179 		dst->fwd_send_flags = src->fwd_send_flags;
180 		dst->rpl_send_flags = src->rpl_send_flags;
181 		dst->force_send_socket = src->force_send_socket;
182 
183 		if (parse_msg(dst->buf, dst->len, dst) != 0) {
184 				LM_ERR("parse msg failed\n");
185 				return -1;
186 		}
187 		return 0;
188 }
189 
190 
191 static cmd_export_t cmds[] = {
192 		{ "Rx_AAR", (cmd_function) w_rx_aar, 4, fixup_aar, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
193 		{ "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 2, fixup_aar_register, 0, REQUEST_ROUTE},
194 		{ 0, 0, 0, 0, 0, 0}
195 };
196 
197 static param_export_t params[] = {
198 		{ "rx_dest_realm", PARAM_STR, &rx_dest_realm},
199 		{ "rx_forced_peer", PARAM_STR, &rx_forced_peer},
200 		{ "rx_auth_expiry", INT_PARAM, &rx_auth_expiry},
201 		{ "af_signaling_ip", PARAM_STR, &af_signaling_ip}, /* IP of this P-CSCF, to be used in the flow for the AF-signaling */
202 		{ "cdp_event_latency", INT_PARAM, &cdp_event_latency}, /*flag: report slow processing of CDP callback events or not */
203 		{ "cdp_event_threshold", INT_PARAM, &cdp_event_threshold}, /*time in ms above which we should report slow processing of CDP callback event*/
204 		{ "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel}, /*log-level to use to report slow processing of CDP callback event*/
205 		{ "authorize_video_flow", INT_PARAM, &authorize_video_flow}, /*whether or not we authorize resources for video flows*/
206 		{ "cdp_event_list_size_threshold", INT_PARAM, &cdp_event_list_size_threshold}, /**Threshold for size of cdp event list after which a warning is logged */
207 		{ "audio_default_bandwidth", INT_PARAM, &audio_default_bandwidth},
208 		{ "video_default_bandwidth", INT_PARAM, &video_default_bandwidth},
209 		{ "early_qosrelease_reason", PARAM_STR, &early_qosrelease_reason},
210 		{ "confirmed_qosrelease_headers", PARAM_STR, &confirmed_qosrelease_headers},
211 		{ "terminate_dialog_on_rx_failure", INT_PARAM, &terminate_dialog_on_rx_failure},
212 		{ "delete_contact_on_rx_failure", INT_PARAM, &delete_contact_on_rx_failure},
213 		{ "regex_sdp_ip_prefix_to_maintain_in_fd", PARAM_STR, &regex_sdp_ip_prefix_to_maintain_in_fd},
214 		{ "include_rtcp_fd", INT_PARAM, &include_rtcp_fd},
215 		{ 0, 0, 0}
216 };
217 
218 
219 /** module exports */
220 struct module_exports exports = {
221 	"ims_qos",
222 	DEFAULT_DLFLAGS, /* dlopen flags */
223 	cmds, 		 /* Exported functions */
224 	params,
225 	0, 		 /* exported RPC methods */
226 	0, 		 /* exported pseudo-variables */
227 	0, 		 /* response handling function */
228 	mod_init, 	 /* module initialization function */
229 	mod_child_init,	 /* per-child init function */
230 	mod_destroy
231 };
232 
233 /**
234  * init module function
235  */
mod_init(void)236 static int mod_init(void)
237 {
238 
239 		callback_singleton = shm_malloc(sizeof(int));
240 		*callback_singleton = 0;
241 
242 		/*register space for event processor*/
243 		register_procs(1);
244 
245 		cdp_avp = 0;
246 		/* load the TM API */
247 		if (load_tm_api(&tmb) != 0) {
248 				LM_ERR("can't load TM API\n");
249 				goto error;
250 		}
251 
252 		/* load the CDP API */
253 		if (load_cdp_api(&cdpb) != 0) {
254 				LM_ERR("can't load CDP API\n");
255 				goto error;
256 		}
257 
258 		/* load the dialog API */
259 		if (load_ims_dlg_api(&dlgb) != 0) {
260 				LM_ERR("can't load Dialog API\n");
261 				goto error;
262 		}
263 
264 		cdp_avp = load_cdp_avp();
265 		if (!cdp_avp) {
266 				LM_ERR("can't load CDP_AVP API\n");
267 				goto error;
268 		}
269 
270 		/* load the usrloc API */
271 		bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
272 		if (!bind_usrloc) {
273 				LM_ERR("can't bind usrloc_pcscf\n");
274 				return CSCF_RETURN_FALSE;
275 		}
276 
277 		if (bind_usrloc(&ul) < 0) {
278 				LM_ERR("can't bind to usrloc pcscf\n");
279 				return CSCF_RETURN_FALSE;
280 		}
281 		LM_DBG("Successfully bound to PCSCF Usrloc module\n");
282 
283 		LM_DBG("Diameter RX interface successfully bound to TM, Dialog, Usrloc and CDP modules\n");
284 
285 		/*init cdb cb event list*/
286 		if (!init_cdp_cb_event_list()) {
287 				LM_ERR("unable to initialise cdp callback event list\n");
288 				return -1;
289 		}
290 
291 		if (ims_qos_init_counters() != 0) {
292 				LM_ERR("Failed to register counters for ims_qos module\n");
293 				return -1;
294 		}
295 
296 		pv_tmx_data_init();
297 
298 		return 0;
299 error:
300 		LM_ERR("Failed to initialise ims_qos module\n");
301 		return CSCF_RETURN_FALSE;
302 }
303 
304 /**
305  * Initializes the module in child.
306  */
mod_child_init(int rank)307 static int mod_child_init(int rank)
308 {
309 		LM_DBG("Initialization of module in child [%d] \n", rank);
310 
311 		if (rank == PROC_MAIN) {
312 				int pid = fork_process(PROC_MIN, "Rx Event Processor", 1);
313 				if (pid < 0)
314 						return -1; //error
315 				if (pid == 0) {
316 						if (cfg_child_init())
317 								return -1; //error
318 						cdp_cb_event_process();
319 				}
320 		}
321 		/* don't do anything for main process and TCP manager process */
322 		if (rank == PROC_MAIN || rank == PROC_TCP_MAIN) {
323 				return 0;
324 		}
325 
326 		lock_get(process_lock);
327 		if ((*callback_singleton) == 0) {
328 				*callback_singleton = 1;
329 				cdpb.AAAAddRequestHandler(callback_cdp_request, NULL);
330 		}
331 		lock_release(process_lock);
332 
333 		return 0;
334 }
335 
mod_destroy(void)336 static void mod_destroy(void)
337 {
338 		if (identifier_size > 0 && identifier.s) {
339 				pkg_free(identifier.s);
340 		}
341 }
342 
343 /*callback of CDP session*/
callback_for_cdp_session(int event,void * session)344 void callback_for_cdp_session(int event, void *session)
345 {
346 		rx_authsessiondata_t* p_session_data = 0;
347 		AAASession *x = session;
348 
349 		str* rx_session_id = (str*) & x->id;
350 		p_session_data = (rx_authsessiondata_t*) x->u.auth.generic_data;
351 
352 		if (!rx_session_id || rx_session_id->len <= 0 || !rx_session_id->s) {
353 				LM_ERR("Invalid Rx session id");
354 				return;
355 		}
356 
357 		if (!p_session_data) {
358 				LM_ERR("Invalid associated session data\n");
359 				return;
360 		}
361 
362 		//only put the events we care about on the event stack
363 		if (event == AUTH_EV_SESSION_TIMEOUT ||
364 				event == AUTH_EV_SESSION_GRACE_TIMEOUT ||
365 				event == AUTH_EV_RECV_ASR ||
366 				event == AUTH_EV_SERVICE_TERMINATED) {
367 
368 				LOG(L_DBG, "callback_for_cdp session(): called with event %d and session id [%.*s]\n", event, rx_session_id->len, rx_session_id->s);
369 
370 				//create new event to process async
371 				cdp_cb_event_t *new_event = new_cdp_cb_event(event, rx_session_id, p_session_data);
372 				if (!new_event) {
373 						LM_ERR("Unable to create event for cdp callback\n");
374 						return;
375 				}
376 				//push the new event onto the stack (FIFO)
377 				push_cdp_cb_event(new_event);
378 		} else {
379 				LM_DBG("Ignoring event [%d] from CDP session\n", event);
380 		}
381 }
382 
383 /**
384  * Handler for incoming Diameter requests.
385  * @param request - the received request
386  * @param param - generic pointer
387  * @returns the answer to this request
388  */
callback_cdp_request(AAAMessage * request,void * param)389 AAAMessage* callback_cdp_request(AAAMessage *request, void *param)
390 {
391 		if (is_req(request)) {
392 
393 				switch (request->applicationId) {
394 				case IMS_Rx:
395 				case IMS_Gq:
396 						switch (request->commandCode) {
397 						case IMS_RAR:
398 								LM_INFO("Rx request handler():- Received an IMS_RAR \n");
399 								/* TODO: Add support for Re-Auth Requests */
400 								return 0;
401 								break;
402 						case IMS_ASR:
403 								LM_INFO("Rx request handler(): - Received an IMS_ASR \n");
404 								return rx_process_asr(request);
405 								break;
406 						default:
407 								LM_ERR("Rx request handler(): - Received unknown request for Rx/Gq command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId);
408 								return 0;
409 								break;
410 						}
411 						break;
412 				default:
413 						LM_ERR("Rx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
414 						return 0;
415 						break;
416 				}
417 		}
418 		return 0;
419 }
420 
421 const str match_cseq_method = {"INVITE", 6};
422 
callback_dialog(struct dlg_cell * dlg,int type,struct dlg_cb_params * params)423 void callback_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params * params)
424 {
425 
426 		struct sip_msg* msg = params->rpl;
427 		struct cseq_body *parsed_cseq;
428 		str *rx_session_id;
429 		rx_session_id = (str*) * params->param;
430 		AAASession *auth = 0;
431 		rx_authsessiondata_t* p_session_data = 0;
432 		flow_description_t *current_fd = 0;
433 		flow_description_t *new_fd = 0;
434 		int current_has_video = 0;
435 		int new_has_video = 0;
436 		int must_unlock_aaa = 1;
437 
438 		if (rx_session_id == 0) {
439 				LM_WARN("Strange... no rx session ID in callback.... why?\n");
440 				return;
441 		}
442 		//getting session data
443 
444 		LM_DBG("Dialog callback of type %d received\n", type);
445 
446 		if (type == DLGCB_TERMINATED || type == DLGCB_DESTROY || type == DLGCB_EXPIRED || type == DLGCB_FAILED) {
447 				LM_DBG("Dialog has ended or failed - we need to terminate Rx bearer session\n");
448 
449 				LM_DBG("Received notification of termination of dialog with Rx session ID: [%.*s]\n",
450 						rx_session_id->len, rx_session_id->s);
451 
452 				LM_DBG("Sending STR\n");
453 				rx_send_str(rx_session_id);
454 		} else if (type == DLGCB_CONFIRMED) {
455 
456 				LM_DBG("Callback for confirmed dialog - copy new flow description into current flow description\n");
457 				if (!rx_session_id || !rx_session_id->s || !rx_session_id->len) {
458 						LM_ERR("Dialog has no Rx session associated\n");
459 						goto error;
460 				}
461 
462 				//getting auth session
463 				auth = cdpb.AAAGetAuthSession(*rx_session_id);
464 				if (!auth) {
465 						LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
466 						goto error;
467 				}
468 
469 				//getting session data
470 				p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
471 				if (!p_session_data) {
472 						LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
473 						goto error;
474 				}
475 
476 				//check if there is a new flow description - if there is then free the current flow description and replace it with the new flow description
477 				if (p_session_data->first_new_flow_description) {
478 						//free the current
479 						LM_DBG("Free-ing the current fd\n");
480 						free_flow_description(p_session_data, 1);
481 						//point the current to the new
482 						LM_DBG("Point the first current fd to the first new fd\n");
483 						p_session_data->first_current_flow_description = p_session_data->first_new_flow_description;
484 						//point the new to 0
485 						LM_DBG("Point the first new fd to 0\n");
486 						p_session_data->first_new_flow_description = 0;
487 				} else {
488 						LM_ERR("There is no new flow description - this shouldn't happen\n");
489 				}
490 
491 				show_callsessiondata(p_session_data);
492 				if (auth) cdpb.AAASessionsUnlock(auth->hash);
493 
494 		} else if (type == DLGCB_RESPONSE_WITHIN) {
495 
496 				LM_DBG("Dialog has received a response to a request within dialog\n");
497 				if (!rx_session_id || !rx_session_id->s || !rx_session_id->len) {
498 						LM_ERR("Dialog has no Rx session associated\n");
499 						goto error;
500 				}
501 
502 				//getting auth session
503 				auth = cdpb.AAAGetAuthSession(*rx_session_id);
504 				if (!auth) {
505 						LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
506 						goto error;
507 				}
508 
509 				//getting session data
510 				p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
511 
512 				if (!p_session_data) {
513 						LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
514 						goto error;
515 				}
516 
517 				show_callsessiondata(p_session_data);
518 
519 				if (msg->first_line.type == SIP_REPLY) {
520 						LM_DBG("This is a SIP REPLY\n");
521 						if (msg->cseq && (parsed_cseq = get_cseq(msg)) && memcmp(parsed_cseq->method.s, match_cseq_method.s, match_cseq_method.len) == 0) {
522 								LM_DBG("This response has a cseq method [%.*s]\n", match_cseq_method.len, match_cseq_method.s);
523 
524 								if (msg->first_line.u.reply.statuscode == 200) {
525 										LM_DBG("Response is 200 - this is success\n");
526 										//check if there is a new flow description - if there is then free the current flow description and replace it with the new flow description
527 										if (p_session_data->first_new_flow_description) {
528 												//free the current
529 												free_flow_description(p_session_data, 1);
530 												//point the current to the new
531 												p_session_data->first_current_flow_description = p_session_data->first_new_flow_description;
532 												//point the new to 0
533 												p_session_data->first_new_flow_description = 0;
534 										} else {
535 												LM_DBG("There is no new flow description - duplicate dialog callback - we ignore.\n");
536 										}
537 								} else if (msg->first_line.u.reply.statuscode > 299) {
538 										LM_DBG("Response is more than 299 so this is an error code\n");
539 
540 										new_fd = p_session_data->first_new_flow_description;
541 										//check if there is video in the new flow description
542 										while (new_fd) {
543 												if (strncmp(new_fd->media.s, "video", 5) == 0) {
544 														LM_DBG("The new flow has a video fd in it\n");
545 														new_has_video = 1;
546 
547 												}
548 												new_fd = new_fd->next;
549 										}
550 										//check if there is video in the current flow description
551 										current_fd = p_session_data->first_current_flow_description;
552 										while (current_fd) {
553 												if (strncmp(current_fd->media.s, "video", 5) == 0) {
554 														LM_DBG("The current flow has a video fd in it\n");
555 														current_has_video = 1;
556 
557 												}
558 												current_fd = current_fd->next;
559 										}
560 										if (new_has_video && !current_has_video) {
561 												LM_DBG("New flow description has video in it, and current does not - this means we added video and it failed further upstream - "
562 														"so we must remove the video\n");
563 												//We need to send AAR asynchronously with current fd
564 												rx_send_aar_update_no_video(auth);
565 												must_unlock_aaa = 0;
566 
567 										}
568 										//free the new flow description
569 										free_flow_description(p_session_data, 0);
570 								}
571 						}
572 				}
573 
574 				show_callsessiondata(p_session_data);
575 
576 				if (must_unlock_aaa) {
577 						LM_DBG("Unlocking AAA session");
578 						cdpb.AAASessionsUnlock(auth->hash);
579 				}
580 		} else {
581 				LM_DBG("Callback type not supported - just returning");
582 		}
583 
584 		return;
585 
586 error:
587 		if (auth) cdpb.AAASessionsUnlock(auth->hash);
588 		return;
589 }
590 
callback_pcscf_contact_cb(struct pcontact * c,int type,void * param)591 void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param)
592 {
593 		LM_DBG("----------------------!\n");
594 		LM_DBG("PCSCF Contact Callback!\n");
595 		LM_DBG("Contact AOR: [%.*s]\n", c->aor.len, c->aor.s);
596 		LM_DBG("Callback type [%d]\n", type);
597 
598 
599 		if (type == PCSCF_CONTACT_EXPIRE || type == PCSCF_CONTACT_DELETE) {
600 				// we dont need to send STR if no QoS was ever successfully registered!
601 				if (must_send_str && (c->reg_state != PCONTACT_REG_PENDING) && (c->reg_state != PCONTACT_REG_PENDING_AAR)) {
602 						LM_DBG("Received notification of contact (in state [%d] deleted for signalling bearer with  with Rx session ID: [%.*s]\n",
603 								c->reg_state, c->rx_session_id.len, c->rx_session_id.s);
604 						LM_DBG("Sending STR\n");
605 						rx_send_str(&c->rx_session_id);
606 				}
607 		}
608 }
609 
get_identifier(str * src)610 static int get_identifier(str* src)
611 {
612 		char *sep;
613 
614 		if (src == 0 || src->len == 0) {
615 				return -1;
616 		}
617 
618 		if (identifier_size <= src->len) {
619 				if (identifier.s) {
620 						pkg_free(identifier.s);
621 				}
622 				identifier.s = (char*) pkg_malloc(src->len + 1);
623 				if (!identifier.s) {
624 						LM_ERR("no more pkg mem\n");
625 						return -1;
626 				}
627 				memset(identifier.s, 0, src->len + 1);
628 				identifier_size = src->len + 1;
629 		}
630 
631 		memcpy(identifier.s, src->s, src->len);
632 		identifier.len = src->len;
633 		sep = memchr(identifier.s, 59 /* ; */, identifier.len);
634 
635 		if (sep) identifier.len = (int) (sep - identifier.s);
636 
637 		return 0;
638 }
639 
check_ip_version(str ip)640 uint16_t check_ip_version(str ip)
641 {
642 		struct addrinfo hint, *res = NULL;
643 		memset(&hint, '\0', sizeof(hint));
644 		hint.ai_family = AF_UNSPEC;
645 		hint.ai_flags = AI_NUMERICHOST;
646 		int getaddrret = getaddrinfo(ip.s, NULL, &hint, &res);
647 		if (getaddrret) {
648 				LM_ERR("GetAddrInfo returned an error !\n");
649 				return 0;
650 		}
651 		if (res->ai_family == AF_INET) {
652 				return AF_INET;
653 		} else if (res->ai_family == AF_INET6) {
654 				return AF_INET6;
655 		} else {
656 				LM_ERR("unknown IP format \n");
657 				return 0;
658 		}
659 }
660 
661 /* Wrapper to send AAR from config file - this only allows for AAR for calls - not register, which uses r_rx_aar_register
662  * return: 1 - success, <=0 failure. 2 - message not a AAR generating message (ie proceed without PCC if you wish)
663  */
w_rx_aar(struct sip_msg * msg,char * route,char * dir,char * c_id,int id_type)664 static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int id_type)
665 {
666 
667 		int ret = CSCF_RETURN_ERROR;
668 		int result = CSCF_RETURN_ERROR;
669 		struct cell *t;
670 		struct sip_msg* orig_sip_request_msg = NULL;
671 
672 		AAASession* auth_session = 0;
673 		rx_authsessiondata_t* rx_authdata_p = 0;
674 		str *rx_session_id = 0;
675 		str callid = {0, 0};
676 		str ftag = {0, 0};
677 		str ttag = {0, 0};
678 
679 		str route_name;
680 		str ip, uri;
681 		int identifier_type;
682 		int ip_version = 0;
683 		sdp_session_cell_t* sdp_session;
684 		sdp_stream_cell_t* sdp_stream;
685 		str s_id;
686 		struct hdr_field *h = 0;
687 		struct dlg_cell* dlg = 0;
688 
689 		cfg_action_t* cfg_action = 0;
690 		saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
691 		char* direction = dir;
692 		if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
693 				LM_ERR("no async route block for assign_server_unreg\n");
694 				return result;
695 		}
696 
697 		if (get_str_fparam(&s_id, msg, (fparam_t*) c_id) < 0) {
698 				LM_ERR("failed to get s__id\n");
699 				return result;
700 		}
701 
702 		LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
703 		int ri = route_get(&main_rt, route_name.s);
704 		if (ri < 0) {
705 				LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
706 				return result;
707 		}
708 		cfg_action = main_rt.rlist[ri];
709 		if (cfg_action == NULL) {
710 				LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
711 				return result;
712 		}
713 
714 		LM_DBG("Rx AAR called\n");
715 		//create the default return code AVP
716 		create_return_code(ret);
717 
718 		//We don't ever do AAR on request for calling scenario...
719 		if (msg->first_line.type != SIP_REPLY) {
720 				LM_DBG("Can't do AAR for call session in request\n");
721 				return result;
722 		}
723 
724 		//is it appropriate to send AAR at this stage?
725 		t = tmb.t_gett();
726 		if (t == NULL || t == T_UNDEFINED) {
727 				LM_WARN("Cannot get transaction for AAR based on SIP Request\n");
728 				//goto aarna;
729 				return result;
730 		}
731 
732 		if (t->uas.status >= 200) {
733 				LM_DBG("trasaction sent out a final response already - %d\n",
734 						t->uas.status);
735 				return result;
736 		}
737 
738 
739 		/*  we may need the request message from here on.. if there are headers we need that were not parsed in the original request
740 			(which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to
741 			make a private copy of the message and free it when we are done
742 		 */
743 		if (msg_ctx_id_match(t->uas.request, &_pv_treq.msg_ctx) != 1) {
744 
745 				/* make a copy */
746 				if (_pv_treq.buf == NULL || _pv_treq.buf_size < t->uas.request->len + 1) {
747 						if (_pv_treq.buf != NULL)
748 								pkg_free(_pv_treq.buf);
749 						if (_pv_treq.tmsgp)
750 								free_sip_msg(&_pv_treq.msg);
751 						_pv_treq.tmsgp = NULL;
752                                                 _pv_treq.msg_ctx.msgid=0;
753                                                 _pv_treq.msg_ctx.pid=0;
754 						_pv_treq.T = NULL;
755 						_pv_treq.buf_size = t->uas.request->len + 1;
756 						_pv_treq.buf = (char*) pkg_malloc(_pv_treq.buf_size * sizeof(char));
757 						if (_pv_treq.buf == NULL) {
758 								LM_ERR("no more pkg\n");
759 								_pv_treq.buf_size = 0;
760 								return -1;
761 						}
762 				}
763 				if (_pv_treq.tmsgp)
764 						free_sip_msg(&_pv_treq.msg);
765 				memset(&_pv_treq.msg, 0, sizeof(struct sip_msg));
766 				memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
767 				_pv_treq.buf[t->uas.request->len] = '\0';
768 				_pv_treq.msg.len = t->uas.request->len;
769 				_pv_treq.msg.buf = _pv_treq.buf;
770 				_pv_treq.tmsgp = t->uas.request;
771                                 msg_ctx_id_set(t->uas.request, &_pv_treq.msg_ctx);
772 				_pv_treq.T = t;
773 
774 
775 				if (pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) {
776 						pkg_free(_pv_treq.buf);
777 						_pv_treq.buf_size = 0;
778 						_pv_treq.buf = NULL;
779 						_pv_treq.tmsgp = NULL;
780 						_pv_treq.T = NULL;
781 						return -1;
782 				}
783 		}
784 
785 		orig_sip_request_msg = &_pv_treq.msg;
786 
787 
788 		//we dont apply QoS if its not a reply to an INVITE! or UPDATE or PRACK!
789 		if ((t->method.len == 5 && memcmp(t->method.s, "PRACK", 5) == 0)
790 				|| (t->method.len == 6 && (memcmp(t->method.s, "INVITE", 6) == 0
791 				|| memcmp(t->method.s, "UPDATE", 6) == 0))) {
792 				if (cscf_get_content_length(msg) == 0
793 						|| cscf_get_content_length(orig_sip_request_msg) == 0) {
794 						LM_DBG("No SDP offer answer -> therefore we can not do Rx AAR");
795 						//goto aarna; //AAR na if we dont have offer/answer pair
796 						return result;
797 				}
798 		} else {
799 				LM_DBG("Message is not response to INVITE, PRACK or UPDATE -> therefore we do not Rx AAR");
800 				return result;
801 		}
802 
803 		/* get callid, from and to tags to be able to identify dialog */
804 		callid = cscf_get_call_id(msg, 0);
805 		if (callid.len <= 0 || !callid.s) {
806 				LM_ERR("unable to get callid\n");
807 				return result;
808 		}
809 		if (!cscf_get_from_tag(msg, &ftag)) {
810 				LM_ERR("Unable to get ftag\n");
811 				return result;
812 		}
813 		if (!cscf_get_to_tag(msg, &ttag)) {
814 				LM_ERR("Unable to get ttag\n");
815 				return result;
816 		}
817 
818 		//check to see that this is not a result of a retransmission in reply route only
819 		if (msg->cseq == NULL
820 				&& ((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || (msg->cseq == NULL))) {
821 				LM_ERR("No Cseq header found - aborting\n");
822 				return result;
823 		}
824 
825 		saved_t_data = (saved_transaction_t*) shm_malloc(sizeof(saved_transaction_t));
826 		if (!saved_t_data) {
827 				LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
828 				return result;
829 		}
830 		memset(saved_t_data, 0, sizeof(saved_transaction_t));
831 		saved_t_data->act = cfg_action;
832 		//OTHER parms need after async response set here
833 		//store call id
834 		saved_t_data->callid.s = (char*) shm_malloc(callid.len + 1);
835 		if (!saved_t_data->callid.s) {
836 				LM_ERR("no more memory trying to save transaction state : callid\n");
837 				shm_free(saved_t_data);
838 				return result;
839 		}
840 		memset(saved_t_data->callid.s, 0, callid.len + 1);
841 		memcpy(saved_t_data->callid.s, callid.s, callid.len);
842 		saved_t_data->callid.len = callid.len;
843 
844 		//store ttag
845 		saved_t_data->ttag.s = (char*) shm_malloc(ttag.len + 1);
846 		if (!saved_t_data->ttag.s) {
847 				LM_ERR("no more memory trying to save transaction state : ttag\n");
848 				shm_free(saved_t_data);
849 				return result;
850 		}
851 		memset(saved_t_data->ttag.s, 0, ttag.len + 1);
852 		memcpy(saved_t_data->ttag.s, ttag.s, ttag.len);
853 		saved_t_data->ttag.len = ttag.len;
854 
855 		//store ftag
856 		saved_t_data->ftag.s = (char*) shm_malloc(ftag.len + 1);
857 		if (!saved_t_data->ftag.s) {
858 				LM_ERR("no more memory trying to save transaction state : ftag\n");
859 				shm_free(saved_t_data);
860 				return result;
861 		}
862 		memset(saved_t_data->ftag.s, 0, ftag.len + 1);
863 		memcpy(saved_t_data->ftag.s, ftag.s, ftag.len);
864 		saved_t_data->ftag.len = ftag.len;
865 
866 		saved_t_data->aar_update = 0; //by default we say this is not an aar update - if it is we set it below
867 
868 		//store branch
869 		int branch;
870 		if (tmb.t_check(msg, &branch) == -1) {
871 				LOG(L_ERR, "ERROR: t_suspend: failed find UAC branch\n");
872 				return result;
873 		}
874 
875 		//Check that we dont already have an auth session for this specific dialog
876 		//if not we create a new one and attach it to the dialog (via session ID).
877 		enum dialog_direction dlg_direction = get_dialog_direction(direction);
878 		if (dlg_direction == DLG_MOBILE_ORIGINATING) {
879 				rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
880 						&orig_session_key);
881 		} else {
882 				rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
883 						&term_session_key);
884 		}
885 		if (rx_session_id && rx_session_id->len > 0 && rx_session_id->s) {
886 				auth_session = cdpb.AAAGetAuthSession(*rx_session_id);
887 				if (auth_session && auth_session->u.auth.state != AUTH_ST_OPEN) {
888 						LM_DBG("This session is not state open - so we will create a new session");
889 						if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
890 						auth_session = 0;
891 				}
892 		}
893 
894 		if (!auth_session) {
895 				LM_DBG("New AAR session for this dialog in mode %s\n", direction);
896 
897 
898 				//get ip and subscription_id and store them in the call session data
899 
900 				//SUBSCRIPTION-ID
901 
902 				//if subscription-id and identifier_type is passed from config file we use them - if not we use default behaviour of
903 
904 				//if its mo we use p_asserted_identity in request - if that not there we use from_uri
905 				//if its mt we use p_asserted_identity in reply - if that not there we use to_uri
906 				if (s_id.len > 0 && id_type > -1) {
907 						get_identifier(&s_id);
908 						identifier_type = id_type;
909 						LM_DBG("Passed in subscription_id [%.*s] and subscription_id_type [%d]\n", identifier.len, identifier.s, identifier_type);
910 				} else {
911 						if (dlg_direction == DLG_MOBILE_ORIGINATING) {
912 								LM_DBG("originating direction\n");
913 								uri = cscf_get_asserted_identity(orig_sip_request_msg, 0);
914 								if (uri.len == 0) {
915 										LM_ERR("No P-Asserted-Identity hdr found in request. Using From hdr in req - we shouldn't have to do this");
916 
917 										if (!cscf_get_from_uri(orig_sip_request_msg, &uri)) {
918 												LM_ERR("Error assigning P-Asserted-Identity using From hdr in req");
919 												goto error;
920 										}
921 										LM_DBG("going to remove parameters if any from identity: [%.*s]\n", uri.len, uri.s);
922 										get_identifier(&uri);
923 										LM_DBG("identifier from uri : [%.*s]\n", identifier.len, identifier.s);
924 
925 								} else {
926 										get_identifier(&uri);
927 										//free this cscf_get_asserted_identity allocates it
928 										//                    pkg_free(uri.s);
929 								}
930 						} else {
931 								LM_DBG("terminating direction\n");
932 								uri = cscf_get_asserted_identity(msg, 0);
933 								if (uri.len == 0) {
934 										LM_DBG("No P-Asserted-Identity hdr found in response. Using Called party id in resp");
935 										//get identity from called party id
936 										//getting called asserted identity
937 										uri = cscf_get_public_identity_from_called_party_id(orig_sip_request_msg, &h);
938 										if (uri.len == 0) {
939 												LM_ERR("No P-Called-Party hdr found in response. Using req URI from dlg - we shouldn't have to do this");
940 												//get dialog and get the req URI from there
941 												dlg = dlgb.get_dlg(msg);
942 												if (!dlg) {
943 													if (!cscf_get_to_uri(orig_sip_request_msg, &uri)) {
944 														LM_ERR("Error assigning P-Asserted-Identity using To hdr in req");
945 														goto error;
946 													}
947 													LM_DBG("going to remove parameters if any from identity: [%.*s]\n", uri.len, uri.s);
948 													get_identifier(&uri);
949 													LM_DBG("identifier from uri : [%.*s]\n", identifier.len, identifier.s);
950 												}else{
951 													LM_DBG("dlg req uri : [%.*s] going to remove parameters if any\n", dlg->req_uri.len, dlg->req_uri.s);
952 
953 													if (get_identifier(&dlg->req_uri) != 0) {
954 															dlgb.release_dlg(dlg);
955 															goto error;
956 													}
957 													dlgb.release_dlg(dlg);
958 													LM_DBG("identifier from dlg req uri : [%.*s]\n", identifier.len, identifier.s);
959 												}
960 										} else {
961 												get_identifier(&uri);
962 										}
963 								} else {
964 										get_identifier(&uri);
965 								}
966 						}
967 						if (strncasecmp(identifier.s, "tel:", 4) == 0) {
968 								identifier_type = AVP_Subscription_Id_Type_E164; //
969 						} else {
970 								identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
971 						}
972 				}
973 				//IP
974 				//if its mo we use request SDP
975 				//if its mt we use reply SDP
976 				if (dlg_direction == DLG_MOBILE_ORIGINATING) {
977 						LM_DBG("originating direction\n");
978 						//get ip from request sdp (we use first SDP session)
979 						if (parse_sdp(orig_sip_request_msg) < 0) {
980 								LM_ERR("Unable to parse req SDP\n");
981 								goto error;
982 						}
983 
984 						sdp_session = get_sdp_session(orig_sip_request_msg, 0);
985 						if (!sdp_session) {
986 								LM_ERR("Missing SDP session information from req\n");
987 								goto error;
988 						}
989 						ip = sdp_session->ip_addr;
990 						ip_version = sdp_session->pf;
991 
992 						LM_DBG("IP retrieved from Request SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
993 
994 						if (ip.len <= 0) {
995 								LM_DBG("Request SDP connection IP could not be retrieved, so we use SDP stream IP");
996 								sdp_stream = get_sdp_stream(orig_sip_request_msg, 0, 0);
997 								if (!sdp_stream) {
998 										LM_ERR("Missing SDP stream information from request\n");
999 										goto error;
1000 								}
1001 
1002 								ip = sdp_stream->ip_addr;
1003 								if (ip.len <= 0) {
1004 										LM_ERR("Request SDP IP information could not be retrieved");
1005 										goto error;
1006 								}
1007 								ip_version = check_ip_version(ip);
1008 								if (!ip_version) {
1009 										LM_ERR("check_ip_version returned 0 \n");
1010 										goto error;
1011 								}
1012 
1013 						}
1014 
1015 						free_sdp((sdp_info_t**) (void*) &t->uas.request->body);
1016 
1017 				} else {
1018 						LM_DBG("terminating direction\n");
1019 						//get ip from reply sdp (we use first SDP session)
1020 						if (parse_sdp(msg) < 0) {
1021 								LM_ERR("Unable to parse reply SDP\n");
1022 								goto error;
1023 						}
1024 
1025 						sdp_session = get_sdp_session(msg, 0);
1026 						if (!sdp_session) {
1027 								LM_ERR("Missing SDP session information from reply\n");
1028 								goto error;
1029 						}
1030 						ip = sdp_session->ip_addr;
1031 						ip_version = sdp_session->pf;
1032 
1033 						LM_DBG("IP retrieved from Reply SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
1034 
1035 						if (ip.len <= 0) {
1036 								LM_DBG("Reply SDP connection IP could not be retrieved, so we use SDP stream IP");
1037 								sdp_stream = get_sdp_stream(msg, 0, 0);
1038 								if (!sdp_stream) {
1039 										LM_ERR("Missing SDP stream information from reply\n");
1040 										goto error;
1041 								}
1042 
1043 								ip = sdp_stream->ip_addr;
1044 								if (ip.len <= 0) {
1045 										LM_ERR("Reply SDP IP information could not be retrieved");
1046 										goto error;
1047 								}
1048 								ip_version = check_ip_version(ip);
1049 								if (!ip_version) {
1050 										LM_ERR("check_ip_version returned 0 \n");
1051 										goto error;
1052 								}
1053 
1054 						}
1055 
1056 						free_sdp((sdp_info_t**) (void*) &msg->body);
1057 				}
1058 
1059 				int ret = create_new_callsessiondata(&callid, &ftag, &ttag, &identifier, identifier_type, &ip, ip_version, &rx_authdata_p);
1060 				if (!ret) {
1061 						LM_DBG("Unable to create new media session data parcel\n");
1062 						goto error;
1063 				}
1064 
1065 				//create new diameter auth session
1066 				auth_session = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_authdata_p); //returns with a lock
1067 				if (!auth_session) {
1068 						LM_ERR("Rx: unable to create new Rx Media Session\n");
1069 						if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
1070 						if (rx_authdata_p) {
1071 								free_callsessiondata(rx_authdata_p);
1072 						}
1073 						goto error;
1074 				}
1075 				auth_session->u.auth.class = AUTH_CLASS_RXMEDIA;
1076 
1077 				//attach new cdp auth session to dlg for this direction
1078 				if (dlg_direction == DLG_MOBILE_ORIGINATING) {
1079 						dlgb.set_dlg_var(&callid, &ftag, &ttag,
1080 								&orig_session_key, &auth_session->id);
1081 				} else {
1082 						dlgb.set_dlg_var(&callid, &ftag, &ttag,
1083 								&term_session_key, &auth_session->id);
1084 				}
1085 				LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
1086 		} else {
1087 				LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
1088 				//check if this is triggered by a 183 - if so break here as its probably a re-transmit
1089 				if ((msg->first_line).u.reply.statuscode == 183) {
1090 						LM_DBG("Received a 183 for a diameter session that already exists - just going to ignore this\n");
1091 						cdpb.AAASessionsUnlock(auth_session->hash);
1092 						result = CSCF_RETURN_TRUE;
1093 						goto ignore;
1094 				}
1095 				saved_t_data->aar_update = 1; //this is an update aar - we set this so on async_aar we know this is an update and act accordingly
1096 		}
1097 
1098                 dlg = dlgb.get_dlg(msg);
1099                 if (!dlg) {
1100                     LM_ERR("Unable to find dialog and cannot do Rx without it\n");
1101                     goto error;
1102                 }
1103                 saved_t_data->dlg = dlg;
1104 
1105 		LM_DBG("Suspending SIP TM transaction\n");
1106 		if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) != 0) {
1107 				LM_ERR("failed to suspend the TM processing\n");
1108 				if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
1109 				goto error;
1110 		}
1111 
1112 		LM_DBG("Sending Rx AAR");
1113 		ret = rx_send_aar(orig_sip_request_msg, msg, auth_session, direction, saved_t_data);
1114 
1115 		if (!ret) {
1116 				LM_ERR("Failed to send AAR\n");
1117 				tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1118 				goto error;
1119 
1120 
1121 		} else {
1122 				LM_DBG("Successful async send of AAR\n");
1123 				result = CSCF_RETURN_BREAK;
1124 				return result; //on success we break - because rest of cfg file will be executed by async process
1125 		}
1126 
1127 error:
1128 		LM_ERR("Error trying to send AAR (calling)\n");
1129 		if (auth_session != NULL) {
1130 				cdpb.AAASessionsUnlock(auth_session->hash);
1131 				cdpb.AAADropAuthSession(auth_session);
1132 		}
1133 ignore:
1134 		if (saved_t_data)
1135 				free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
1136 		//otherwise the callback will segfault
1137 		return result;
1138 }
1139 
1140 /* Wrapper to send AAR from config file - only used for registration */
w_rx_aar_register(struct sip_msg * msg,char * route,char * str1,char * bar)1141 static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* bar)
1142 {
1143 
1144 		int ret = CSCF_RETURN_ERROR;
1145 		struct pcontact_info ci;
1146 		struct cell *t;
1147 		contact_t* c;
1148 		struct hdr_field* h;
1149 		pcontact_t* pcontact;
1150 		pcontact_info_t contact_info;
1151 		contact_body_t* cb = 0;
1152 		AAASession* auth;
1153 		rx_authsessiondata_t* rx_regsession_data_p;
1154 		cfg_action_t* cfg_action = 0;
1155 		str route_name;
1156 		char* p;
1157 		int aar_sent = 0;
1158 		saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
1159 		saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
1160 		str recv_ip;
1161 		int recv_port;
1162 		unsigned short recv_proto;
1163 		uint16_t ip_version;
1164 
1165 		struct via_body* vb;
1166 		unsigned short via_port;
1167 		unsigned short via_proto;
1168 
1169 		if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
1170 				LM_ERR("no async route block for assign_server_unreg\n");
1171 				return -1;
1172 		}
1173 
1174 		LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
1175 		int ri = route_get(&main_rt, route_name.s);
1176 		if (ri < 0) {
1177 				LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
1178 				return -1;
1179 		}
1180 		cfg_action = main_rt.rlist[ri];
1181 		if (cfg_action == NULL) {
1182 				LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
1183 				return -1;
1184 		}
1185 
1186 		udomain_t* domain_t = (udomain_t*) str1;
1187 
1188 		int is_rereg = 0; //is this a reg/re-reg
1189 
1190 		LM_DBG("Rx AAR Register called\n");
1191 
1192 		//create the default return code AVP
1193 		create_return_code(ret);
1194 
1195 		memset(&ci, 0, sizeof(struct pcontact_info));
1196 
1197 		/** If this is a response then let's check the status before we try and do an AAR.
1198 		 * We will only do AAR for register on success response and of course if message is register
1199 		 */
1200 		if (msg->first_line.type == SIP_REPLY) {
1201 				//check this is a response to a register
1202 				/* Get the SIP request from this transaction */
1203 				t = tmb.t_gett();
1204 				if (!t) {
1205 						LM_ERR("Cannot get transaction for AAR based on SIP Request\n");
1206 						goto error;
1207 				}
1208 				if ((strncmp(t->method.s, "REGISTER", 8) != 0)) {
1209 						LM_ERR("Method is not a response to a REGISTER\n");
1210 						goto error;
1211 				}
1212 				if (msg->first_line.u.reply.statuscode < 200
1213 						|| msg->first_line.u.reply.statuscode >= 300) {
1214 						LM_DBG("Message is not a 2xx OK response to a REGISTER\n");
1215 						goto error;
1216 				}
1217 				tmb.t_release(msg);
1218 		} else { //SIP Request
1219 				/* in case of request make sure it is a REGISTER */
1220 				if (msg->first_line.u.request.method_value != METHOD_REGISTER) {
1221 						LM_DBG("This is not a register request\n");
1222 						goto error;
1223 				}
1224 
1225 				if ((cscf_get_max_expires(msg, 0) == 0)) {
1226 						//if ((cscf_get_expires(msg) == 0)) {
1227 						LM_DBG("This is a de registration\n");
1228 						LM_DBG("We ignore it as these are dealt with by usrloc callbacks \n");
1229 						create_return_code(CSCF_RETURN_TRUE);
1230 						return CSCF_RETURN_TRUE;
1231 				}
1232 		}
1233 
1234 		vb = cscf_get_ue_via(msg);
1235 		via_port = vb->port ? vb->port : 5060;
1236 		via_proto = vb->proto;
1237 
1238 		//before we continue, make sure we have a transaction to work with (viz. cdp async)
1239 		t = tmb.t_gett();
1240 		if (t == NULL || t == T_UNDEFINED) {
1241 				if (tmb.t_newtran(msg) < 0) {
1242 						LM_ERR("cannot create the transaction for UAR async\n");
1243 						return CSCF_RETURN_ERROR;
1244 				}
1245 				t = tmb.t_gett();
1246 				if (t == NULL || t == T_UNDEFINED) {
1247 						LM_ERR("cannot lookup the transaction\n");
1248 						return CSCF_RETURN_ERROR;
1249 				}
1250 		}
1251 
1252 		saved_t_data = (saved_transaction_t*) shm_malloc(sizeof(saved_transaction_t));
1253 		if (!saved_t_data) {
1254 				LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
1255 				return CSCF_RETURN_ERROR;
1256 		}
1257 		memset(saved_t_data, 0, sizeof(saved_transaction_t));
1258 		saved_t_data->act = cfg_action;
1259 		saved_t_data->domain = domain_t;
1260 		saved_t_data->lock = lock_alloc();
1261 		if (saved_t_data->lock == NULL) {
1262 				LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
1263 				return CSCF_RETURN_ERROR;
1264 		}
1265 		if (lock_init(saved_t_data->lock) == NULL) {
1266 				LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
1267 				return CSCF_RETURN_ERROR;
1268 		}
1269 
1270 		LM_DBG("Suspending SIP TM transaction\n");
1271 		if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) != 0) {
1272 				LM_ERR("failed to suspend the TM processing\n");
1273 				free_saved_transaction_global_data(saved_t_data);
1274 				return CSCF_RETURN_ERROR;
1275 		}
1276 
1277 		LM_DBG("Successfully suspended transaction\n");
1278 
1279 		//now get the contacts in the REGISTER and do AAR for each one.
1280 		cb = cscf_parse_contacts(msg);
1281 		if (!cb || (!cb->contacts && !cb->star)) {
1282 				LM_DBG("No contact headers in Register message\n");
1283 				goto error;
1284 		}
1285 
1286 		//we use the received IP address for the framed_ip_address
1287 		recv_ip.s = ip_addr2a(&msg->rcv.src_ip);
1288 		recv_ip.len = strlen(ip_addr2a(&msg->rcv.src_ip));
1289 
1290 		ip_version = check_ip_version(recv_ip);
1291 		if (!ip_version) {
1292 				LM_ERR("check_ip_version returned 0 \n");
1293 				goto error;
1294 		}
1295 
1296 		recv_port = msg->rcv.src_port;
1297 		recv_proto = msg->rcv.proto;
1298 
1299 		LM_DBG("Message received IP address is: [%.*s]\n", recv_ip.len, recv_ip.s);
1300 		LM_DBG("Message via is [%d://%.*s:%d]\n", vb->proto, vb->host.len, vb->host.s, via_port);
1301 
1302 		lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
1303 		for (h = msg->contact; h; h = h->next) {
1304 				if (h->type == HDR_CONTACT_T && h->parsed) {
1305 						for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
1306 								ul.lock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1307 								memset(&contact_info, 0, sizeof(struct pcontact_info));
1308 								contact_info.aor = c->uri;
1309 								contact_info.via_host = vb->host;
1310 								contact_info.via_port = vb->port;
1311 								contact_info.via_prot = vb->proto;
1312 								contact_info.searchflag = SEARCH_NORMAL;
1313 								contact_info.received_host.s = 0;
1314 								contact_info.received_host.len = 0;
1315 								contact_info.reg_state = PCONTACT_ANY; //search for any state
1316 
1317 								if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) {
1318 										LM_ERR("This contact does not exist in PCSCF usrloc - error in cfg file\n");
1319 										ul.unlock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1320 										lock_release(saved_t_data->lock);
1321 										goto error;
1322 								} else if (pcontact->reg_state == PCONTACT_REG_PENDING
1323 										|| pcontact->reg_state == PCONTACT_REGISTERED) { //NEW reg request
1324 										LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
1325 												, pcontact->aor.len, pcontact->aor.s);
1326 
1327 										//check for existing Rx session
1328 										if (pcontact->rx_session_id.len > 0
1329 												&& pcontact->rx_session_id.s
1330 												&& (auth = cdpb.AAAGetAuthSession(pcontact->rx_session_id))) {
1331 												LM_DBG("Rx session already exists for this user\n");
1332 												if (memcmp(pcontact->rx_session_id.s, auth->id.s, auth->id.len) != 0) {
1333 														LM_ERR("Rx session mismatch for rx_session_id [%.*s].......Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1334 														if (auth) cdpb.AAASessionsUnlock(auth->hash);
1335 														lock_release(saved_t_data->lock);
1336 														goto error;
1337 												}
1338 												//re-registration - update auth lifetime
1339 												auth->u.auth.lifetime = time(NULL) + rx_auth_expiry;
1340 												is_rereg = 1;
1341 										} else {
1342 												LM_DBG("Creating new Rx session for contact <%.*s>\n", pcontact->aor.len, pcontact->aor.s);
1343 												int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &recv_ip, ip_version, recv_port, recv_proto, &vb->host, vb->port, vb->proto, &rx_regsession_data_p);
1344 												if (!ret) {
1345 														LM_ERR("Unable to create regsession data parcel for rx_session_id [%.*s]...Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1346 														ul.unlock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1347 														if (rx_regsession_data_p) {
1348 																shm_free(rx_regsession_data_p);
1349 																rx_regsession_data_p = 0;
1350 														}
1351 														lock_release(saved_t_data->lock);
1352 														goto error;
1353 												}
1354 												auth = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_regsession_data_p); //returns with a lock
1355 												if (!auth) {
1356 														LM_ERR("Rx: unable to create new Rx Reg Session for rx_session_id is [%.*s]\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1357 														if (rx_regsession_data_p) {
1358 																shm_free(rx_regsession_data_p);
1359 																rx_regsession_data_p = 0;
1360 														}
1361 														ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1362 														if (auth) cdpb.AAASessionsUnlock(auth->hash);
1363 														if (rx_regsession_data_p) {
1364 																shm_free(rx_regsession_data_p);
1365 																rx_regsession_data_p = 0;
1366 														}
1367 														lock_release(saved_t_data->lock);
1368 														goto error;
1369 												}
1370 												auth->u.auth.class = AUTH_CLASS_RXREG;
1371 										}
1372 
1373 										//we are ready to send the AAR async. lets save the local data data
1374 										int local_data_len = sizeof(saved_transaction_local_t) + c->uri.len + auth->id.len + vb->host.len + recv_ip.len;
1375 										local_data = shm_malloc(local_data_len);
1376 										if (!local_data) {
1377 												LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
1378 												lock_release(saved_t_data->lock);
1379 												goto error;
1380 										}
1381 										memset(local_data, 0, local_data_len);
1382 
1383 										local_data->is_rereg = is_rereg;
1384 										local_data->global_data = saved_t_data;
1385 										p = (char*) (local_data + 1);
1386 
1387 										local_data->contact.s = p;
1388 										local_data->contact.len = c->uri.len;
1389 										memcpy(p, c->uri.s, c->uri.len);
1390 										p += c->uri.len;
1391 
1392 										local_data->auth_session_id.s = p;
1393 										local_data->auth_session_id.len = auth->id.len;
1394 										memcpy(p, auth->id.s, auth->id.len);
1395 										p += auth->id.len;
1396 
1397 										local_data->via_host.s = p;
1398 										local_data->via_host.len = vb->host.len;
1399 										memcpy(p, vb->host.s, vb->host.len);
1400 										p += vb->host.len;
1401 
1402 										local_data->recv_host.s = p;
1403 										local_data->recv_host.len = recv_ip.len;
1404 										memcpy(p, recv_ip.s, recv_ip.len);
1405 										p += recv_ip.len;
1406 
1407 										local_data->via_port = via_port;
1408 										local_data->via_proto = via_proto;
1409 										local_data->recv_port = recv_port;
1410 										local_data->recv_proto = recv_proto;
1411 
1412 										if (p != (((char*) local_data) + local_data_len)) {
1413 												LM_CRIT("buffer overflow\n");
1414 												free_saved_transaction_data(local_data);
1415 												goto error;
1416 										}
1417 
1418 										LM_DBG("Calling send aar register");
1419 
1420 										//TODOD remove - no longer user AOR parm
1421 										//ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
1422 										ret = rx_send_aar_register(msg, auth, local_data); //returns a locked rx auth object
1423 
1424 										ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1425 
1426 										if (!ret) {
1427 												LM_ERR("Failed to send AAR\n");
1428 												lock_release(saved_t_data->lock);
1429 												free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
1430 												goto error;
1431 										} else {
1432 												aar_sent = 1;
1433 												//before we send - bump up the reply counter
1434 												saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
1435 										}
1436 								} else {
1437 										//contact exists - this is a re-registration, for now we just ignore this
1438 										LM_DBG("This contact exists and is not in state REGISTER PENDING - we assume re (or de) registration and ignore\n");
1439 										ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1440 										//now we loop for any other contacts.
1441 								}
1442 						}
1443 				} else {
1444 						if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
1445 								LM_ERR("Failed to parse contact header\n");
1446 								lock_release(saved_t_data->lock);
1447 								goto error;
1448 						}
1449 				}
1450 		}
1451 		//all requests sent at this point - we can unlock the reply lock
1452 		lock_release(saved_t_data->lock);
1453 
1454 		/*if we get here, we have either:
1455 		 * 1. Successfully sent AAR's for ALL contacts, or
1456 		 * 2. haven't needed to send ANY AAR's for ANY contacts
1457 		 */
1458 		if (aar_sent) {
1459 				LM_DBG("Successful async send of AAR\n");
1460 				return CSCF_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
1461 		} else {
1462 				create_return_code(CSCF_RETURN_TRUE);
1463 				tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1464 				if (saved_t_data) {
1465 						free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
1466 				}
1467 				//return CSCF_RETURN_ERROR;
1468 				return CSCF_RETURN_TRUE;
1469 		}
1470 error:
1471 		LM_ERR("Error trying to send AAR\n");
1472 		if (!aar_sent) {
1473 				tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1474 				if (saved_t_data) {
1475 
1476 						free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
1477 						//otherwise the callback will segfault
1478 				}
1479 		}
1480 		return CSCF_RETURN_ERROR;
1481 		//return CSCF_RETURN_FALSE;
1482 }
1483 
fixup_aar_register(void ** param,int param_no)1484 static int fixup_aar_register(void** param, int param_no)
1485 {
1486 		//    udomain_t* d;
1487 		//    aar_param_t *ap;
1488 		//
1489 		//    if (param_no != 1)
1490 		//        return 0;
1491 		//    ap = (aar_param_t*) pkg_malloc(sizeof (aar_param_t));
1492 		//    if (ap == NULL) {
1493 		//        LM_ERR("no more pkg\n");
1494 		//        return -1;
1495 		//    }
1496 		//    memset(ap, 0, sizeof (aar_param_t));
1497 		//    ap->paction = get_action_from_param(param, param_no);
1498 		//
1499 		//    if (ul.register_udomain((char*) *param, &d) < 0) {
1500 		//        LM_ERR("failed to register domain\n");
1501 		//        return E_UNSPEC;
1502 		//    }
1503 		//    ap->domain = d;
1504 		//
1505 		//    *param = (void*) ap;
1506 		//    return 0;
1507 		if (strlen((char*) *param) <= 0) {
1508 				LM_ERR("empty parameter %d not allowed\n", param_no);
1509 				return -1;
1510 		}
1511 
1512 		if (param_no == 1) { //route name - static or dynamic string (config vars)
1513 				if (fixup_spve_null(param, param_no) < 0)
1514 						return -1;
1515 				return 0;
1516 		} else if (param_no == 2) {
1517 				udomain_t* d;
1518 
1519 				if (ul.register_udomain((char*) *param, &d) < 0) {
1520 						LM_ERR("Error doing fixup on assign save");
1521 
1522 						return -1;
1523 				}
1524 				*param = (void*) d;
1525 		}
1526 
1527 		return 0;
1528 }
1529 
fixup_aar(void ** param,int param_no)1530 static int fixup_aar(void** param, int param_no)
1531 {
1532 		str s;
1533 		int num;
1534 
1535 		//param 3 can be empty
1536 		if (param_no != 3 && strlen((char*) *param) <= 0) {
1537 				LM_ERR("empty parameter %d not allowed\n", param_no);
1538 				return -1;
1539 		}
1540 
1541 		if (param_no == 1) { //route name - static or dynamic string (config vars)
1542 				if (fixup_spve_null(param, param_no) < 0)
1543 						return -1;
1544 				return 0;
1545 		} else if (param_no == 3) {
1546 				return fixup_var_str_12(param, param_no);
1547 		} else if (param_no == 4) {
1548 				/*convert to int */
1549 				s.s = (char*) *param;
1550 				s.len = strlen(s.s);
1551 				if (str2sint(&s, &num) == 0) {
1552 						pkg_free(*param);
1553 						*param = (void*) (unsigned long) num;
1554 						return 0;
1555 				}
1556 				LM_ERR("Bad subscription id: <%s>n", (char*) (*param));
1557 
1558 				return E_CFG;
1559 		}
1560 
1561 		return 0;
1562 }
1563 
1564 /*create a return code to be passed back into config file*/
create_return_code(int result)1565 int create_return_code(int result)
1566 {
1567 		int rc;
1568 		int_str avp_val, avp_name;
1569 		avp_name.s.s = "aar_return_code";
1570 		avp_name.s.len = 15;
1571 
1572 		LM_DBG("Creating return code of [%d] for aar_return_code\n", result);
1573 		//build avp spec for uaa_return_code
1574 		avp_val.n = result;
1575 
1576 		rc = add_avp(AVP_NAME_STR, avp_name, avp_val);
1577 
1578 		if (rc < 0)
1579 				LM_ERR("couldn't create [aar_return_code] AVP\n");
1580 		else
1581 				LM_DBG("created AVP successfully : [%.*s]\n", avp_name.s.len, avp_name.s.s);
1582 
1583 		return rc;
1584 }
1585