d9f242f43b8d97d66ca924d1241111ab298f1c1e
[kamailio] / src / modules / ims_qos / rx_aar.c
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  * History:
47  * --------
48  *  2011-02-02  initial version (jason.penton)
49  */
50
51 #include "../../core/mem/shm_mem.h"
52 #include "../../core/parser/sdp/sdp.h"
53 #include "../cdp_avp/cdp_avp_mod.h"
54
55 #include "../../modules/ims_dialog/dlg_load.h"
56 #include "../../modules/tm/tm_load.h"
57 #include "../ims_usrloc_pcscf/usrloc.h"
58 #include "rx_authdata.h"
59
60 #include "rx_aar.h"
61 #include "rx_avp.h"
62
63 #include "../../lib/ims/ims_getters.h"
64
65 #include "ims_qos_mod.h"
66
67 #include "../../lib/ims/useful_defs.h"
68 #include "ims_qos_stats.h"
69
70
71 #define macro_name(_rc) #_rc
72
73 //extern struct tm_binds tmb;
74 extern usrloc_api_t ul;
75
76 extern struct ims_qos_counters_h ims_qos_cnts_h;
77
78 extern int authorize_video_flow;
79
80 extern str af_signaling_ip;
81
82 str IMS_Serv_AVP_val = {"IMS Services", 12};
83 str IMS_Em_Serv_AVP_val = {"Emergency IMS Call", 18};
84 str IMS_Reg_AVP_val = {"IMS Registration", 16};
85
86 static void free_dialog_data(void *data) {
87     str *rx_session_id = (str*) data;
88     if (rx_session_id) {
89         if (rx_session_id->s) {
90             shm_free(rx_session_id->s);
91             rx_session_id->s = 0;
92         }
93         shm_free(rx_session_id);
94         rx_session_id = 0;
95     }
96
97 }
98
99 void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) {
100     struct cell *t = 0;
101     unsigned int cdp_result;
102     int result = CSCF_RETURN_ERROR;
103     rx_authsessiondata_t* p_session_data = 0;
104     AAASession *auth = 0;
105
106     LM_DBG("Received AAR callback\n");
107     saved_transaction_t* data = (saved_transaction_t*) param;
108
109     LM_DBG("received AAA answer");
110
111     if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
112         LM_ERR("t_continue: transaction not found\n");
113         goto error;
114     } else {
115         LM_DBG("t_continue: transaction found\n");
116     }
117     //we have T, lets restore our state (esp. for AVPs)
118     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
119     set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
120     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
121     set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
122     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
123     set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);
124
125     if (is_timeout != 0) {
126         LM_ERR("Error timeout when sending AAR message via CDP\n");
127         counter_inc(ims_qos_cnts_h.media_aar_timeouts);
128         goto error;
129     }
130     if (!aaa) {
131         LM_ERR("Error sending message via CDP\n");
132         goto error;
133     }
134
135     counter_inc(ims_qos_cnts_h.media_aars);
136     counter_add(ims_qos_cnts_h.media_aar_response_time, elapsed_msecs);
137     counter_inc(ims_qos_cnts_h.media_aar_replies_received);
138
139     /* Process the response to AAR, retrieving result code and associated Rx session ID */
140     if (rx_process_aaa(aaa, &cdp_result) < 0) {
141         LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s);
142         goto error;
143     }
144
145     if (cdp_result >= 2000 && cdp_result < 3000) {
146         LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", cdp_result);
147         counter_inc(ims_qos_cnts_h.successful_media_aars);
148
149         LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s);
150
151         if(!data->aar_update) {
152             LM_DBG("This is an AAA response to an initial AAR");
153             //need to set Rx auth data to say this session has been successfully opened
154             //This is used elsewhere to prevent acting on termination events when the session has not been opened
155             //getting auth session
156             auth = cdpb.AAAGetAuthSession(aaa->sessionId->data);
157             if (!auth) {
158                 LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
159                 goto error;
160             }
161             //getting session data
162             p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
163             if (!p_session_data) {
164                 LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
165                 if (auth) cdpb.AAASessionsUnlock(auth->hash);
166                 goto error;
167             }
168             p_session_data->session_has_been_opened = 1;
169             counter_inc(ims_qos_cnts_h.active_media_rx_sessions);
170                         counter_inc(ims_qos_cnts_h.media_rx_sessions);
171
172             if (auth) cdpb.AAASessionsUnlock(auth->hash);
173
174             str * passed_rx_session_id = shm_malloc(sizeof (struct _str));
175             passed_rx_session_id->s = 0;
176             passed_rx_session_id->len = 0;
177             STR_SHM_DUP(*passed_rx_session_id, aaa->sessionId->data, "cb_passed_rx_session_id");
178             LM_DBG("passed rx session id [%.*s]", passed_rx_session_id->len, passed_rx_session_id->s);
179             dlgb.register_dlgcb_nodlg( data->dlg, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED | DLGCB_FAILED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data);
180         }
181         result = CSCF_RETURN_TRUE;
182     } else {
183         LM_DBG("Received negative reply from PCRF for AAR Request\n");
184         counter_inc(ims_qos_cnts_h.failed_media_aars);
185         //we don't free rx_authdata_p here - it is free-ed when the CDP session expires
186         goto error; // if its not a success then that means i want to reject this call!
187     }
188
189     //set success response code AVP
190     create_return_code(result);
191     goto done;
192
193 out_of_memory:
194     error :
195             //set failure response code
196             create_return_code(result);
197
198 done:
199     if (t) tmb.unref_cell(t);
200     //free memory
201     if (aaa)
202         cdpb.AAAFreeMessage(&aaa);
203
204     tmb.t_continue(data->tindex, data->tlabel, data->act);
205     free_saved_transaction_global_data(data);
206 }
207
208 void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) {
209     struct cell *t = 0;
210     pcontact_t* pcontact;
211     unsigned int cdp_result;
212     struct pcontact_info ci;
213     udomain_t* domain_t;
214     int finalReply = 0;
215     AAASession *auth = 0;
216     rx_authsessiondata_t* p_session_data = 0;
217     int result = CSCF_RETURN_ERROR;
218     pcontact_info_t contact_info;
219
220     LM_DBG("Received AAR callback\n");
221     saved_transaction_local_t* local_data = (saved_transaction_local_t*) param;
222     saved_transaction_t* data = local_data->global_data;
223     domain_t = data->domain;
224
225     int is_rereg = local_data->is_rereg;
226
227     //before we do anything else, lets decrement the reference counter on replies
228     lock_get(data->lock);
229     data->answers_not_received--;
230     if (data->answers_not_received <= 0) {
231         finalReply = 1;
232     }
233     if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory
234         free_saved_transaction_data(local_data);
235         if (finalReply) {
236             free_saved_transaction_global_data(data);
237         }
238         return;
239     }
240     lock_release(data->lock);
241
242     LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed);
243
244     if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
245         LM_ERR("t_continue: transaction not found\n");
246         goto error;
247     }
248     //we have T, lets restore our state (esp. for AVPs)
249     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
250     set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
251     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
252     set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
253     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
254     set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);
255
256     if (is_timeout != 0) {
257         LM_ERR("Error timeout when sending AAR message via CDP\n");
258         counter_inc(ims_qos_cnts_h.registration_aar_timeouts);
259         goto error;
260     }
261     if (!aaa) {
262         LM_ERR("Error sending message via CDP\n");
263         goto error;
264     }
265
266     counter_inc(ims_qos_cnts_h.registration_aars);
267     counter_add(ims_qos_cnts_h.registration_aar_response_time, elapsed_msecs);
268     counter_inc(ims_qos_cnts_h.registration_aar_replies_received);
269
270     /* Process the response to AAR, retrieving result code and associated Rx session ID */
271     if (rx_process_aaa(aaa, &cdp_result) < 0) {
272         LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s);
273         goto error;
274     }
275
276     if (cdp_result >= 2000 && cdp_result < 3000) {
277         counter_inc(ims_qos_cnts_h.successful_registration_aars);
278         if (is_rereg) {
279             LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the subscription was successful\n");
280             result = CSCF_RETURN_TRUE;
281             create_return_code(result);
282             goto done;
283         }
284         //need to set Rx auth data to say this session has been successfully opened
285         //This is used elsewhere to prevent acting on termination events when the session has not been opened
286         //getting auth session
287         auth = cdpb.AAAGetAuthSession(aaa->sessionId->data);
288         if (!auth) {
289             LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
290             goto error;
291         }
292         //getting session data
293         p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
294         if (!p_session_data) {
295             LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
296             if (auth) cdpb.AAASessionsUnlock(auth->hash);
297             goto error;
298         }
299         p_session_data->session_has_been_opened = 1;
300         counter_inc(ims_qos_cnts_h.active_registration_rx_sessions);
301
302         if (auth) cdpb.AAASessionsUnlock(auth->hash);
303
304
305         LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n",
306                 cdp_result, local_data->contact.len, local_data->contact.s,
307                 local_data->auth_session_id.len, local_data->auth_session_id.s);
308         LM_DBG("Registering for Usrloc callbacks on DELETE\n");
309
310         ul.lock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
311                 memset(&contact_info, 0, sizeof(struct pcontact_info));
312         contact_info.received_host = local_data->recv_host;
313         contact_info.received_port = local_data->recv_port;
314         contact_info.received_proto = local_data->recv_proto;
315         contact_info.searchflag = (1 << SEARCH_RECEIVED);
316
317
318         contact_info.aor = local_data->contact;
319         contact_info.via_host = local_data->via_host;
320         contact_info.via_port = local_data->via_port;
321         contact_info.via_prot = local_data->via_proto;
322         contact_info.reg_state = PCONTACT_ANY;
323
324         if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) {
325             LM_ERR("Shouldn't get here, can't find contact....\n");
326             ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
327             goto error;
328         }
329
330         //at this point we have the contact
331         /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again
332          * for the duration of the registration.
333          * */
334         if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) {
335             LM_ERR("unable to update pcontact......\n");
336             ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
337             goto error;
338         }
339         memset(&ci, 0, sizeof (struct pcontact_info));
340         ci.reg_state = PCONTACT_REG_PENDING_AAR;
341         ci.num_service_routes = 0;
342         ci.num_public_ids = 0;
343         LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s);
344         ul.update_pcontact(domain_t, &ci, pcontact);
345         //register for callbacks on contact
346         ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE,
347                 callback_pcscf_contact_cb, NULL);
348         ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
349         result = CSCF_RETURN_TRUE;
350     } else {
351         LM_DBG("Received negative reply from PCRF for AAR Request\n");
352         counter_inc(ims_qos_cnts_h.failed_registration_aars);
353         result = CSCF_RETURN_FALSE;
354         goto error;
355     }
356
357     //set success response code AVP
358     create_return_code(result);
359     goto done;
360
361 error:
362     //set failure response code
363     create_return_code(result);
364
365 done:
366     if (t) tmb.unref_cell(t);
367     //free memory
368     if (aaa)
369         cdpb.AAAFreeMessage(&aaa);
370
371     if (finalReply) {
372         tmb.t_continue(data->tindex, data->tlabel, data->act);
373         free_saved_transaction_global_data(data);
374     }
375     free_saved_transaction_data(local_data);
376 }
377
378 /* handle an AAA response to an AAR for resource reservation for a successful registration or initiated/updated dialog
379  * @param aaa - the diameter reply
380  * @return -  1 if result code found and processing ok, -1 if error
381  */
382 int rx_process_aaa(AAAMessage *aaa, unsigned int * rc) {
383     int ret = 1;
384
385     ret = rx_get_result_code(aaa, rc);
386
387     if (ret == 0) {
388         LM_DBG("AAA message without result code\n");
389         return ret;
390     }
391
392     return ret;
393 }
394
395 /** Helper function for adding media component AVPs - uses previously stored flow descriptions not SDP from messages*/
396 int add_media_components_using_current_flow_description(AAAMessage* aar, rx_authsessiondata_t *p_session_data) {
397
398     flow_description_t *flow_description;
399     int add_flow = 1;
400
401     flow_description = p_session_data->first_current_flow_description;
402     if(!flow_description) {
403         return -1;
404     }
405     while (flow_description) {
406
407         if(!authorize_video_flow) {
408             if (strncmp(flow_description->media.s, "video", 5) == 0) {
409                 add_flow = 0;
410             }
411         }
412
413         if(add_flow) {
414             rx_add_media_component_description_avp(aar, flow_description->stream_num,
415                     &flow_description->media, &flow_description->req_sdp_ip_addr,
416                     &flow_description->req_sdp_port, &flow_description->rpl_sdp_ip_addr,
417                     &flow_description->rpl_sdp_port, &flow_description->rpl_sdp_transport,
418                     &flow_description->req_sdp_raw_stream,
419                     &flow_description->rpl_sdp_raw_stream, flow_description->direction, AVP_EPC_Flow_Usage_No_Information);
420         }
421
422         flow_description = flow_description->next;
423         add_flow = 1;
424     }
425     return 0;
426 }
427
428
429
430 /** Helper function for adding media component AVPs for each SDP stream*/
431 int add_media_components(AAAMessage* aar, struct sip_msg *req,
432         struct sip_msg *rpl, enum dialog_direction direction, AAASession* auth) {
433     int sdp_session_num;
434     int sdp_stream_num;
435     sdp_session_cell_t* req_sdp_session, *rpl_sdp_session;
436     sdp_stream_cell_t* req_sdp_stream, *rpl_sdp_stream;
437     int add_flow = 1;
438         str ttag = {0, 0};
439         str ftag = {0, 0};
440         int request_originated_from_callee = 0;  
441         str ipA, ipB, portA, portB;
442         
443         rx_authsessiondata_t* p_session_data = 0;
444     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
445         
446         if (!req || !rpl) {
447                         goto error;
448     }
449
450     if (parse_sdp(req) < 0) {
451         LM_ERR("Unable to parse req SDP\n");
452         goto error;
453     }
454
455     if (parse_sdp(rpl) < 0) {
456         LM_ERR("Unable to parse res SDP\n");
457         goto error;
458     }
459
460     sdp_session_num = 0;
461
462     //Loop through req sessions and streams and get corresponding rpl sessions and streams and populate avps
463     for (;;) {
464         //we only cater for one session at the moment: TDOD: extend
465         if (sdp_session_num > 0) {
466             break;
467         }
468
469         req_sdp_session = get_sdp_session(req, sdp_session_num);
470         rpl_sdp_session = get_sdp_session(rpl, sdp_session_num);
471         if (!req_sdp_session || !rpl_sdp_session) {
472             if (!req_sdp_session)
473                 LM_ERR("Missing SDP session information from req\n");
474
475             if (!rpl_sdp_session)
476                 LM_ERR("Missing SDP session information from rpl\n");
477
478                         goto error;
479         }
480
481         sdp_stream_num = 0;
482         for (;;) {
483             req_sdp_stream = get_sdp_stream(req, sdp_session_num,
484                     sdp_stream_num);
485             rpl_sdp_stream = get_sdp_stream(rpl, sdp_session_num,
486                     sdp_stream_num);
487             if (!req_sdp_stream || !rpl_sdp_stream) {
488                 //LM_ERR("Missing SDP stream information\n");
489                 break;
490             }
491             //is this a stream to add to AAR.
492             if (req_sdp_stream->is_rtp) {
493
494                 //check if the src or dst port is 0 and if so then don't add to rx
495                 int intportA = atoi(req_sdp_stream->port.s);
496                 int intportB = atoi(rpl_sdp_stream->port.s);
497                 if(intportA != 0 && intportB != 0){
498                         if(!authorize_video_flow) {
499                         if (strncmp(req_sdp_stream->media.s, "video", 5) == 0) {
500                             add_flow = 0;
501                         }
502                     }
503
504                         if(add_flow) {
505
506                                         
507                                                 if (cscf_get_to_tag(rpl, &ttag) && cscf_get_from_tag(rpl, &ftag)) {
508                                                                 LM_DBG("Original ftag [%.*s] ttag [%.*s].  Current ftag [%.*s] ttag [%.*s]\n", 
509                                                                                 p_session_data->ftag.len, p_session_data->ftag.s, p_session_data->ttag.len, p_session_data->ttag.s,
510                                                                                 ftag.len, ftag.s, ttag.len, ttag.s);
511                                                         if (!(strncmp(p_session_data->ttag.s, ttag.s, p_session_data->ttag.len) == 0 && strncmp(p_session_data->ftag.s, ftag.s, p_session_data->ftag.len) == 0)) {
512                                                                 LM_DBG("ftag and ttag of this response do not match initial response so this request came from callee\n");
513                                                                 request_originated_from_callee = 1;
514                                                         }
515                                                 } else {
516                                                         LM_ERR("Couldn't retrieve ftag so assume this request originated from caller\n");
517                                                 }
518                                         
519                                                 if (request_originated_from_callee) {
520                                                         LM_DBG("Request originated from callee so IPs are reversed\n"); 
521                                                         ipA = rpl_sdp_session->ip_addr;
522                                                         portA = rpl_sdp_stream->port;
523                                                         
524                                                         ipB = req_sdp_session->ip_addr;
525                                                         portB = req_sdp_stream->port;
526                                                 } else {
527                                                         ipA = req_sdp_session->ip_addr;
528                                                         portA = req_sdp_stream->port;
529                                                         
530                                                         
531                                                         ipB = rpl_sdp_session->ip_addr;
532                                                         portB = rpl_sdp_stream->port;
533                                                 }
534                                                 
535
536                                                 if (ipA.len <= 0) {
537                                                                 LM_DBG("Request SDP connection IP could not be retrieved, so we use SDP 1st stream IP\n");
538                                                                 if (request_originated_from_callee) {
539                                                                         LM_DBG("Request originated from callee so IPs are reversed\n"); 
540                                                                         ipA = rpl_sdp_stream->ip_addr;
541                                                                         portA = rpl_sdp_stream->port;
542                                                                 } else {
543                                                                         ipA = req_sdp_stream->ip_addr;
544                                                                         portA = req_sdp_stream->port;
545                                                                 }
546                                                                 
547                                                                 
548                                                                 if (ipA.len <= 0) {
549                                                                                 LM_ERR("Requested SDP IP information could not be retrieved\n");
550                                                                                 goto error;
551                                                                 }
552                                                 }
553
554                                                 if (ipB.len <= 0) {
555                                                                 LM_DBG("Reply SDP connection IP could not be retrieved, so we use SDP 1st stream IP\n");
556                                                                 if (request_originated_from_callee) {
557                                                                         LM_DBG("Request originated from callee so IPs are reversed\n"); 
558                                                                         ipB = req_sdp_stream->ip_addr;
559                                                                         portB = req_sdp_stream->port;
560                                                                 } else {
561                                                                         ipB = rpl_sdp_stream->ip_addr;
562                                                                         portB = rpl_sdp_stream->port;
563                                                                 }
564                                                                 
565                                                                 
566                                                                 if (ipB.len <= 0) {
567                                                                                 LM_ERR("Request SDP IP information could not be retrieved\n");
568                                                                                 goto error;
569                                                                 }
570                                                 }
571
572                                                 //add this to auth session data
573                         add_flow_description((rx_authsessiondata_t*) auth->u.auth.generic_data, sdp_stream_num + 1,
574                                 &req_sdp_stream->media, &ipA,
575                                 &portA, &ipB,
576                                 &portB, &rpl_sdp_stream->transport,
577                                 &req_sdp_stream->raw_stream,
578                                 &rpl_sdp_stream->raw_stream, direction, 0 /*This is a new mcd, we are not setting it as active*/);
579
580                         rx_add_media_component_description_avp(aar, sdp_stream_num + 1,
581                                 &req_sdp_stream->media, &ipA,
582                                 &portA, &ipB,
583                                 &portB, &rpl_sdp_stream->transport,
584                                 &req_sdp_stream->raw_stream,
585                                 &rpl_sdp_stream->raw_stream, direction, AVP_EPC_Flow_Usage_No_Information);
586                     }
587                     add_flow = 1;
588                 }
589             }
590             sdp_stream_num++;
591         }
592         sdp_session_num++;
593     }
594
595     free_sdp((sdp_info_t**) (void*) &req->body);
596     free_sdp((sdp_info_t**) (void*) &rpl->body);
597
598         return 1;
599
600         error:
601
602     return 0;
603 }
604
605 /**
606  * Sends the Authorization Authentication Request - specifically this is an asynchronous AAR sent if another update adding video has failed so we need to remove video
607  */
608
609 int rx_send_aar_update_no_video(AAASession* auth) {
610
611     AAAMessage* aar = 0;
612
613     str identifier;
614     int identifier_type;
615
616
617     AAA_AVP* avp = 0;
618     char x[4];
619     int ret = 0;
620
621     str recv_ip;
622     uint16_t ip_version;
623
624     //we get ip and identifier for the auth session data
625     rx_authsessiondata_t* p_session_data = 0;
626     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
627     identifier = p_session_data->identifier;
628     identifier_type = p_session_data->identifier_type;
629     recv_ip = p_session_data->ip;
630     ip_version = p_session_data->ip_version;
631
632     aar = cdpb.AAACreateRequest(IMS_Rx, IMS_AAR, Flag_Proxyable, auth);
633
634     LM_DBG("Sending AAR update to remove a video bearer\n");
635     show_callsessiondata(p_session_data);
636
637     if (!aar)
638         goto error;
639
640     /*Adding AVPs*/
641
642     LM_DBG("Adding auth app id AVP...\n");
643     /* Add Auth-Application-Id AVP */
644     if (!rx_add_auth_application_id_avp(aar, IMS_Rx))
645         goto error;
646     if (!rx_add_vendor_specific_application_id_group(aar, IMS_vendor_id_3GPP,
647             IMS_Rx))
648         goto error;
649
650     LM_DBG("Adding dest realm if not there already...\n");
651     /* Add Destination-Realm AVP, if not already there */
652     avp = cdpb.AAAFindMatchingAVP(aar, aar->avpList.head, AVP_Destination_Realm,
653             0, AAA_FORWARD_SEARCH);
654     if (!avp) {
655         str realm = rx_dest_realm;
656         if (realm.len && !rx_add_destination_realm_avp(aar, realm))
657             goto error;
658     }
659
660     LM_DBG("Adding AF App identifier...\n");
661     /* Add AF-Application-Identifier AVP */
662     str af_id = {0, 0};
663     af_id = IMS_Serv_AVP_val;
664     if (!rx_add_avp(aar, af_id.s, af_id.len, AVP_IMS_AF_Application_Identifier,
665             AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA,
666             __FUNCTION__))
667         goto error;
668
669     LM_DBG("Adding service info status...\n");
670     /* Add Service-Info-Status AVP, if prelimiary
671      * by default(when absent): final status is considered*/
672
673     set_4bytes(x,
674             AVP_EPC_Service_Info_Status_Preliminary_Service_Information);
675     if (!rx_add_avp(aar, x, 4, AVP_IMS_Service_Info_Status,
676             AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA,
677             __FUNCTION__))
678         goto error;
679
680     /* Add Auth lifetime AVP */LM_DBG("auth_lifetime %u\n", rx_auth_expiry); //TODO check why this is 0 all the time
681     if (rx_auth_expiry) {
682         set_4bytes(x, rx_auth_expiry);
683         if (!rx_add_avp(aar, x, 4, AVP_Authorization_Lifetime,
684                 AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__))
685             goto error;
686     }
687
688     LM_DBG("Adding subscription id...\n");
689
690     rx_add_subscription_id_avp(aar, identifier, identifier_type);
691
692
693     LM_DBG("Adding reservation priority...\n");
694     /* Add Reservation Priority AVP*/
695     set_4bytes(x, 0);
696     if (!rx_add_avp(aar, x, 4, AVP_ETSI_Reservation_Priority,
697             AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_ETSI,
698             AVP_DUPLICATE_DATA, __FUNCTION__))
699         goto error;
700
701     LM_DBG("Adding media component...\n");
702     //Note we add this AVP first as it gets the IP address which we need to create the auth session
703     //Could and maybe should have a separate method that retrieves the IP from SDP - TODO
704
705     /*---------- 2. Create and add Media-Component-Description AVP ----------*/
706
707     /*
708      *  See 3GPP TS29214
709      *
710      *  <Media-Component-Description> = {Media-Component-Number}
711      *                                                                  [Media-Sub-Component]
712      *                                                                  [AF-Application-Identifier]
713      *                                                                  [Media-Type]
714      *                                                                  [Max-Requested-Bandwidth-UL]
715      *                                                                  [Max-Requested-Bandwidth-DL]
716      *                                                                  [Flow-Status]
717      *                                                                  [Reservation-Priority] (Not used yet)
718      *                                                                  [RS-Bandwidth]
719      *                                                                  [RR-Bandwidth]
720      *                                                                  *[Codec-Data]
721      */
722
723     add_media_components_using_current_flow_description(aar, p_session_data);
724
725     LM_DBG("Adding framed ip address [%.*s]\n", recv_ip.len, recv_ip.s);
726     /* Add Framed IP address AVP*/
727     if (!rx_add_framed_ip_avp(&aar->avpList, recv_ip, ip_version)) {
728         LM_ERR("Unable to add framed IP AVP\n");
729         goto error;
730     }
731     LM_DBG("Unlocking AAA session...\n");
732
733     if (auth)
734         cdpb.AAASessionsUnlock(auth->hash);
735
736     LM_DBG("sending AAR to PCRF\n");
737     if (rx_forced_peer.len)
738         ret = cdpb.AAASendMessageToPeer(aar, &rx_forced_peer,
739             NULL, NULL);
740     else
741         ret = cdpb.AAASendMessage(aar, NULL,
742             NULL);
743
744     return ret;
745
746 error:
747     LM_ERR("unexpected error\n");
748     if (aar)
749         cdpb.AAAFreeMessage(&aar);
750     if (auth) {
751         cdpb.AAASessionsUnlock(auth->hash);
752         cdpb.AAADropAuthSession(auth);
753         auth = 0;
754     }
755     return ret;
756 }
757
758
759
760 /**
761  * Sends the Authorization Authentication Request.
762  * @param req - SIP request
763  * @param res - SIP response
764  * @param direction - 0/o/orig for originating side, 1/t/term for terminating side
765  * @param rx_auth_data - the returned rx auth data
766  * @returns AAA message or NULL on error
767  */
768
769 int rx_send_aar(struct sip_msg *req, struct sip_msg *res,
770         AAASession* auth, char* direction, saved_transaction_t* saved_t_data) {
771
772     AAAMessage* aar = 0;
773
774     str identifier;
775     int identifier_type;
776
777
778     AAA_AVP* avp = 0;
779     char x[4];
780     int ret = 0;
781
782     str ip;
783     uint16_t ip_version;
784
785     //we get ip and identifier for the auth session data
786     rx_authsessiondata_t* p_session_data = 0;
787     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
788     identifier = p_session_data->identifier;
789     identifier_type = p_session_data->identifier_type;
790     ip = p_session_data->ip;
791     ip_version = p_session_data->ip_version;
792
793     /* find direction for AAR (orig/term) */
794     //need this to add the media component details
795     enum dialog_direction dlg_direction = get_dialog_direction(direction);
796     if (dlg_direction == DLG_MOBILE_UNKNOWN) {
797         LM_DBG("Asked to send AAR for unknown direction.....Aborting...\n");
798         goto error;
799     }
800
801     aar = cdpb.AAACreateRequest(IMS_Rx, IMS_AAR, Flag_Proxyable, auth);
802
803     LM_DBG("Created aar request...\n");
804
805     if (!aar)
806         goto error;
807
808     /*Adding AVPs*/
809
810     LM_DBG("Adding auth app id AVP...\n");
811     /* Add Auth-Application-Id AVP */
812     if (!rx_add_auth_application_id_avp(aar, IMS_Rx))
813         goto error;
814     if (!rx_add_vendor_specific_application_id_group(aar, IMS_vendor_id_3GPP,
815             IMS_Rx))
816         goto error;
817
818     LM_DBG("Adding dest realm if not there already...\n");
819     /* Add Destination-Realm AVP, if not already there */
820     avp = cdpb.AAAFindMatchingAVP(aar, aar->avpList.head, AVP_Destination_Realm,
821             0, AAA_FORWARD_SEARCH);
822     if (!avp) {
823         str realm = rx_dest_realm;
824         if (realm.len && !rx_add_destination_realm_avp(aar, realm))
825             goto error;
826     }
827
828     LM_DBG("Adding AF App identifier...\n");
829     /* Add AF-Application-Identifier AVP */
830     str af_id = {0, 0};
831     af_id = IMS_Serv_AVP_val;
832     if (!rx_add_avp(aar, af_id.s, af_id.len, AVP_IMS_AF_Application_Identifier,
833             AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA,
834             __FUNCTION__))
835         goto error;
836
837     LM_DBG("Adding service info status...\n");
838     /* Add Service-Info-Status AVP, if prelimiary
839      * by default(when absent): final status is considered*/
840     if (!res) {
841         set_4bytes(x,
842                 AVP_EPC_Service_Info_Status_Preliminary_Service_Information);
843         if (!rx_add_avp(aar, x, 4, AVP_IMS_Service_Info_Status,
844                 AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA,
845                 __FUNCTION__))
846             goto error;
847     }
848
849     /* Add Auth lifetime AVP */LM_DBG("auth_lifetime %u\n", rx_auth_expiry); //TODO check why this is 0 all the time
850     if (rx_auth_expiry) {
851         set_4bytes(x, rx_auth_expiry);
852         if (!rx_add_avp(aar, x, 4, AVP_Authorization_Lifetime,
853                 AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__))
854             goto error;
855     }
856
857     LM_DBG("Adding subscription id...\n");
858
859     rx_add_subscription_id_avp(aar, identifier, identifier_type);
860
861
862     LM_DBG("Adding reservation priority...\n");
863     /* Add Reservation Priority AVP*/
864     set_4bytes(x, 0);
865     if (!rx_add_avp(aar, x, 4, AVP_ETSI_Reservation_Priority,
866             AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_ETSI,
867             AVP_DUPLICATE_DATA, __FUNCTION__))
868         goto error;
869
870     LM_DBG("Adding media component...\n");
871     //Note we add this AVP first as it gets the IP address which we need to create the auth session
872     //Could and maybe should have a separate method that retrieves the IP from SDP - TODO
873
874     /*---------- 2. Create and add Media-Component-Description AVP ----------*/
875
876     /*
877      *  See 3GPP TS29214
878      *
879      *  <Media-Component-Description> = {Media-Component-Number}
880      *                                                                  [Media-Sub-Component]
881      *                                                                  [AF-Application-Identifier]
882      *                                                                  [Media-Type]
883      *                                                                  [Max-Requested-Bandwidth-UL]
884      *                                                                  [Max-Requested-Bandwidth-DL]
885      *                                                                  [Flow-Status]
886      *                                                                  [Reservation-Priority] (Not used yet)
887      *                                                                  [RS-Bandwidth]
888      *                                                                  [RR-Bandwidth]
889      *                                                                  *[Codec-Data]
890      */
891
892     add_media_components(aar, req, res, dlg_direction, auth);
893
894     LM_DBG("Adding framed ip address [%.*s]\n", ip.len, ip.s);
895     /* Add Framed IP address AVP*/
896     if (!rx_add_framed_ip_avp(&aar->avpList, ip, ip_version)) {
897         LM_ERR("Unable to add framed IP AVP\n");
898         goto error;
899     }
900
901     /* Add specific action AVP's */
902     rx_add_specific_action_avp(aar, 1); // CHARGING_CORRELATION_EXCHANGE
903     rx_add_specific_action_avp(aar, 2); // INDICATION_OF_LOSS_OF_BEARER
904     rx_add_specific_action_avp(aar, 3); // INDICATION_RECOVERY_OF_BEARER
905     rx_add_specific_action_avp(aar, 4); // INDICATION_RELEASE_OF_BEARER
906     rx_add_specific_action_avp(aar, 5); // INDICATION_ESTABLISHMENT_OF_BEARER (now void)
907     rx_add_specific_action_avp(aar, 6); // IP-CAN_CHANGE
908     rx_add_specific_action_avp(aar, 12); // ACCESS_NETWORK_INFO_REPORT
909
910     show_callsessiondata(p_session_data);
911
912     LM_DBG("Unlocking AAA session...\n");
913
914     if (auth)
915         cdpb.AAASessionsUnlock(auth->hash);
916
917     LM_DBG("sending AAR to PCRF\n");
918     if (rx_forced_peer.len)
919         ret = cdpb.AAASendMessageToPeer(aar, &rx_forced_peer,
920             (void*) async_aar_callback, (void*) saved_t_data);
921     else
922         ret = cdpb.AAASendMessage(aar, (void*) async_aar_callback,
923             (void*) saved_t_data);
924
925     return ret;
926
927 error:
928     LM_ERR("unexpected error\n");
929     if (aar)
930         cdpb.AAAFreeMessage(&aar);
931     if (auth) {
932         cdpb.AAASessionsUnlock(auth->hash);
933         cdpb.AAADropAuthSession(auth);
934         auth = 0;
935     }
936     return ret;
937 }
938
939 /**
940  * Sends the Authorization Authentication Request for Register messages
941  * @param req - SIP Register msg
942  * @param rx_auth_data - the returned rx auth data
943  * @param ip - ip address extracted from contact to register
944  * @param ip_version - AF_INET or AF_INET6
945  * @returns int >0 if sent AAR successfully, otherwise 0
946  */
947
948 int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, saved_transaction_local_t* saved_t_data) {
949     AAAMessage* aar = 0;
950     int ret = 0;
951     AAA_AVP* avp = 0;
952     char x[4];
953     str identifier;
954     str media;
955
956     str ip;
957     uint16_t ip_version;
958
959     //we get ip and identifier for the auth session data
960     rx_authsessiondata_t* p_session_data = 0;
961     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
962     identifier = p_session_data->identifier;
963     ip = p_session_data->ip;
964     ip_version = p_session_data->ip_version;
965
966     LM_DBG("Send AAR register\n");
967
968     aar = cdpb.AAACreateRequest(IMS_Rx, IMS_AAR, Flag_Proxyable, auth);
969
970     if (!aar)
971         goto error;
972
973     /*Add AVPs*/
974
975     /* Add Auth-Application-Id AVP */
976     if (!rx_add_auth_application_id_avp(aar, IMS_Rx))
977         goto error;
978     if (!rx_add_vendor_specific_application_id_group(aar, IMS_vendor_id_3GPP,
979             IMS_Rx))
980         goto error;
981
982     /* Add Destination-Realm AVP, if not already there */
983     avp = cdpb.AAAFindMatchingAVP(aar, aar->avpList.head, AVP_Destination_Realm,
984             0, AAA_FORWARD_SEARCH);
985     if (!avp) {
986         str realm = rx_dest_realm;
987         if (realm.len && !rx_add_destination_realm_avp(aar, realm))
988             goto error;
989     }
990
991     /* Add Subscription ID AVP*/
992
993     identifier = cscf_get_public_identity(msg);
994
995     int identifier_type = AVP_Subscription_Id_Type_SIP_URI; //we only do IMPU now
996     rx_add_subscription_id_avp(aar, identifier, identifier_type);
997
998     /* Create flow description for AF-Signaling */
999     //add this to auth session data
1000     media.s = "control";
1001     media.len = strlen("control");
1002     str raw_stream;
1003     raw_stream.s = 0;
1004     raw_stream.len = 0;
1005
1006     char c_port_from[10];
1007     str port_from;
1008     port_from.len = snprintf(c_port_from, 10, "%u", saved_t_data->via_port);
1009     port_from.s = c_port_from;
1010
1011     char c_port_to[10];
1012     str port_to;
1013     port_to.len = snprintf(c_port_to, 10, "%u", saved_t_data->recv_port);
1014     port_to.s = c_port_to;
1015
1016     str protocol;
1017     protocol.s = "IP";
1018     protocol.len = strlen("IP");
1019
1020     //rx_add_media_component_description_avp_register(aar);
1021     /* Add media component description avp for register*/
1022     rx_add_media_component_description_avp(aar, 1,
1023                &media, &saved_t_data->via_host,
1024                &port_from, &af_signaling_ip,
1025                &port_to, &protocol,
1026                &raw_stream,
1027                &raw_stream, DLG_MOBILE_REGISTER, AVP_EPC_Flow_Usage_AF_Signaling);
1028
1029     /* Add specific action AVP's */
1030     rx_add_specific_action_avp(aar, 1); // CHARGING_CORRELATION_EXCHANGE
1031     rx_add_specific_action_avp(aar, 2); // INDICATION_OF_LOSS_OF_BEARER
1032     rx_add_specific_action_avp(aar, 3); // INDICATION_RECOVERY_OF_BEARER
1033     rx_add_specific_action_avp(aar, 4); // INDICATION_RELEASE_OF_BEARER
1034     rx_add_specific_action_avp(aar, 5); // INDICATION_ESTABLISHMENT_OF_BEARER (now void)
1035     rx_add_specific_action_avp(aar, 6); // IP-CAN_CHANGE
1036     rx_add_specific_action_avp(aar, 12); // ACCESS_NETWORK_INFO_REPORT
1037
1038     /* Add Framed IP address AVP*/
1039     if (!rx_add_framed_ip_avp(&aar->avpList, ip, ip_version)) {
1040         LM_ERR("Unable to add framed IP AVP\n");
1041         goto error;
1042     }
1043
1044     /* Add Auth lifetime AVP */LM_DBG("auth_lifetime %u\n", rx_auth_expiry); //TODO check why this is 0 all the time
1045     if (rx_auth_expiry) {
1046         set_4bytes(x, rx_auth_expiry);
1047         if (!rx_add_avp(aar, x, 4, AVP_Authorization_Lifetime,
1048                 AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__))
1049             goto error;
1050     }
1051
1052     if (auth)
1053         cdpb.AAASessionsUnlock(auth->hash);
1054
1055     LM_DBG("sending AAR to PCRF\n");
1056     if (rx_forced_peer.len)
1057         ret = cdpb.AAASendMessageToPeer(aar, &rx_forced_peer,
1058             (void*) async_aar_reg_callback, (void*) saved_t_data);
1059     else
1060         ret = cdpb.AAASendMessage(aar, (void*) async_aar_reg_callback,
1061             (void*) saved_t_data);
1062
1063     return ret;
1064
1065 error:
1066     LM_ERR("unexpected error\n");
1067     if (aar)
1068         cdpb.AAAFreeMessage(&aar);
1069     if (auth) {
1070         cdpb.AAASessionsUnlock(auth->hash);
1071         cdpb.AAADropAuthSession(auth);
1072         auth = 0;
1073     }
1074     return ret;
1075 }
1076
1077 enum dialog_direction get_dialog_direction(char *direction) {
1078     if (!direction) {
1079         LM_CRIT("Unknown direction NULL");
1080         return DLG_MOBILE_UNKNOWN;
1081     }
1082     switch (direction[0]) {
1083         case 'o':
1084         case 'O':
1085         case '0':
1086             return DLG_MOBILE_ORIGINATING;
1087         case 't':
1088         case 'T':
1089         case '1':
1090             return DLG_MOBILE_TERMINATING;
1091         default:
1092             LM_CRIT("Unknown direction %s", direction);
1093             return DLG_MOBILE_UNKNOWN;
1094     }
1095 }
1096
1097 void free_saved_transaction_global_data(saved_transaction_t* data) {
1098     if (!data)
1099         return;
1100     if (data->callid.s && data->callid.len) {
1101         shm_free(data->callid.s);
1102         data->callid.len = 0;
1103     }
1104     if (data->ftag.s && data->ftag.len) {
1105         shm_free(data->ftag.s);
1106         data->ftag.len = 0;
1107     }
1108     if (data->ttag.s && data->ttag.len) {
1109         shm_free(data->ttag.s);
1110         data->ttag.len = 0;
1111     }
1112     if (data->lock) {
1113         lock_dealloc(data->lock);
1114         lock_destroy(data->lock);
1115     }
1116     shm_free(data);
1117 }
1118
1119 void free_saved_transaction_data(saved_transaction_local_t* data) {
1120     if (!data)
1121         return;
1122     shm_free(data);
1123 }