mod.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2012 Smile Communications, [email protected]
  5. * Copyright (C) 2012 Smile Communications, [email protected]
  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  43. *
  44. */
  45. #include "stats.h"
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49. #include <unistd.h>
  50. #include "../../sr_module.h"
  51. #include "../../events.h"
  52. #include "../../dprint.h"
  53. #include "../../ut.h"
  54. #include "../../lib/ims/ims_getters.h"
  55. #include "../tm/tm_load.h"
  56. #include "../../mod_fix.h"
  57. #include "../../parser/parse_uri.h"
  58. #include "../../parser/parse_content.h"
  59. #include "../ims_usrloc_pcscf/usrloc.h"
  60. #include "../../modules/dialog_ng/dlg_load.h"
  61. #include "../../modules/dialog_ng/dlg_hash.h"
  62. #include "../cdp/cdp_load.h"
  63. #include "../cdp_avp/mod_export.h"
  64. #include "../../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 "mod.h"
  71. #include "../../lib/ims/useful_defs.h"
  72. MODULE_VERSION
  73. extern gen_lock_t* process_lock; /* lock on the process table */
  74. str orig_session_key = {"originating", 11};
  75. str term_session_key = {"terminating", 11};
  76. int rx_auth_expiry = 7200;
  77. int must_send_str = 1;
  78. struct tm_binds tmb;
  79. struct cdp_binds cdpb;
  80. struct dlg_binds dlgb;
  81. bind_usrloc_t bind_usrloc;
  82. cdp_avp_bind_t *cdp_avp;
  83. usrloc_api_t ul;
  84. int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events or not - default enabled */
  85. int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
  86. int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
  87. /** module functions */
  88. static int mod_init(void);
  89. static int mod_child_init(int);
  90. static void mod_destroy(void);
  91. static int fixup_aar_register(void** param, int param_no);
  92. static void free_dialog_data(void *data);
  93. int * callback_singleton; /*< Callback singleton */
  94. /* parameters storage */
  95. char* rx_dest_realm_s = "ims.smilecoms.com";
  96. str rx_dest_realm;
  97. /* 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 */
  98. char* rx_forced_peer_s = "";
  99. str rx_forced_peer;
  100. /* commands wrappers and fixups */
  101. static int w_rx_aar(struct sip_msg *msg, char* direction, char *bar);
  102. static int w_rx_aar_register(struct sip_msg *msg, char* str1, char *bar);
  103. static cmd_export_t cmds[] = {
  104. { "Rx_AAR", (cmd_function) w_rx_aar, 1, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
  105. { "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 1, fixup_aar_register, 0, REQUEST_ROUTE},
  106. { 0, 0, 0, 0, 0, 0}
  107. };
  108. static param_export_t params[] = {
  109. { "rx_dest_realm", STR_PARAM, &rx_dest_realm_s},
  110. { "rx_forced_peer", STR_PARAM, &rx_forced_peer_s},
  111. { "rx_auth_expiry", INT_PARAM, &rx_auth_expiry},
  112. { "cdp_event_latency", INT_PARAM, &cdp_event_latency}, /*flag: report slow processing of CDP callback events or not */
  113. { "cdp_event_threshold", INT_PARAM, &cdp_event_threshold}, /*time in ms above which we should report slow processing of CDP callback event*/
  114. { "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel}, /*log-level to use to report slow processing of CDP callback event*/
  115. { 0, 0, 0}
  116. };
  117. stat_export_t mod_stats[] = {
  118. {"aar_avg_response_time" , STAT_IS_FUNC, (stat_var**)get_avg_aar_response_time },
  119. {"aar_timeouts" , 0, (stat_var**)&stat_aar_timeouts },
  120. {0,0,0}
  121. };
  122. /** module exports */
  123. struct module_exports exports = {"ims_qos", DEFAULT_DLFLAGS, /* dlopen flags */
  124. cmds, /* Exported functions */
  125. params, 0, /* exported statistics */
  126. 0, /* exported MI functions */
  127. 0, /* exported pseudo-variables */
  128. 0, /* extra processes */
  129. mod_init, /* module initialization function */
  130. 0, mod_destroy, mod_child_init /* per-child init function */};
  131. int fix_parameters() {
  132. rx_dest_realm.s = rx_dest_realm_s;
  133. rx_dest_realm.len = strlen(rx_dest_realm_s);
  134. rx_forced_peer.s = rx_forced_peer_s;
  135. rx_forced_peer.len = strlen(rx_forced_peer_s);
  136. return RX_RETURN_TRUE;
  137. }
  138. /**
  139. * init module function
  140. */
  141. static int mod_init(void) {
  142. /* fix the parameters */
  143. if (!fix_parameters())
  144. goto error;
  145. #ifdef STATISTICS
  146. /* register statistics */
  147. if (register_module_stats( exports.name, mod_stats)!=0 ) {
  148. LM_ERR("failed to register core statistics\n");
  149. goto error;
  150. }
  151. if (!register_stats()){
  152. LM_ERR("Unable to register statistics\n");
  153. goto error;
  154. }
  155. #endif
  156. callback_singleton = shm_malloc(sizeof (int));
  157. *callback_singleton = 0;
  158. /*register space for event processor*/
  159. register_procs(1);
  160. cdp_avp = 0;
  161. /* load the TM API */
  162. if (load_tm_api(&tmb) != 0) {
  163. LM_ERR("can't load TM API\n");
  164. goto error;
  165. }
  166. /* load the CDP API */
  167. if (load_cdp_api(&cdpb) != 0) {
  168. LM_ERR("can't load CDP API\n");
  169. goto error;
  170. }
  171. /* load the dialog API */
  172. if (load_dlg_api(&dlgb) != 0) {
  173. LM_ERR("can't load Dialog API\n");
  174. goto error;
  175. }
  176. cdp_avp = load_cdp_avp();
  177. if (!cdp_avp) {
  178. LM_ERR("can't load CDP_AVP API\n");
  179. goto error;
  180. }
  181. /* load the usrloc API */
  182. bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
  183. if (!bind_usrloc) {
  184. LM_ERR("can't bind usrloc_pcscf\n");
  185. return RX_RETURN_FALSE;
  186. }
  187. if (bind_usrloc(&ul) < 0) {
  188. LM_ERR("can't bind to usrloc pcscf\n");
  189. return RX_RETURN_FALSE;
  190. }
  191. LM_DBG("Successfully bound to PCSCF Usrloc module\n");
  192. LM_DBG("Diameter RX interface successfully bound to TM, Dialog, Usrloc and CDP modules\n");
  193. /*init cdb cb event list*/
  194. if (!init_cdp_cb_event_list()) {
  195. LM_ERR("unable to initialise cdp callback event list\n");
  196. return -1;
  197. }
  198. return 0;
  199. error:
  200. LM_ERR("Failed to initialise ims_qos module\n");
  201. return RX_RETURN_FALSE;
  202. }
  203. /**
  204. * Initializes the module in child.
  205. */
  206. static int mod_child_init(int rank) {
  207. LM_DBG("Initialization of module in child [%d] \n", rank);
  208. if (rank == PROC_MAIN) {
  209. int pid = fork_process(PROC_NOCHLDINIT, "Rx Event Processor", 1);
  210. if (pid < 0)
  211. return -1; //error
  212. if (pid == 0) {
  213. if (cfg_child_init())
  214. return -1; //error
  215. cdp_cb_event_process();
  216. }
  217. }
  218. /* don't do anything for main process and TCP manager process */
  219. if (rank == PROC_MAIN || rank == PROC_TCP_MAIN) {
  220. return 0;
  221. }
  222. lock_get(process_lock);
  223. if ((*callback_singleton) == 0) {
  224. *callback_singleton = 1;
  225. cdpb.AAAAddRequestHandler(callback_cdp_request, NULL);
  226. }
  227. lock_release(process_lock);
  228. return 0;
  229. }
  230. static void mod_destroy(void) {
  231. }
  232. /*callback of CDP session*/
  233. void callback_for_cdp_session(int event, void *session) {
  234. rx_authsessiondata_t* p_session_data = 0;
  235. AAASession *x = session;
  236. str* rx_session_id = (str*) & x->id;
  237. p_session_data = (rx_authsessiondata_t*) x->u.auth.generic_data;
  238. if (!rx_session_id || rx_session_id->len <= 0 || !rx_session_id->s) {
  239. LM_ERR("Invalid Rx session id");
  240. return;
  241. }
  242. if (!p_session_data) {
  243. LM_ERR("Invalid associated session data\n");
  244. return;
  245. }
  246. //only put the events we care about on the event stack
  247. if (event == AUTH_EV_SESSION_TIMEOUT ||
  248. event == AUTH_EV_SESSION_GRACE_TIMEOUT ||
  249. event == AUTH_EV_SESSION_LIFETIME_TIMEOUT ||
  250. event == AUTH_EV_SERVICE_TERMINATED) {
  251. 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);
  252. //create new event to process async
  253. cdp_cb_event_t *new_event = new_cdp_cb_event(event, rx_session_id, p_session_data);
  254. if (!new_event) {
  255. LM_ERR("Unable to create event for cdp callback\n");
  256. return;
  257. }
  258. //push the new event onto the stack (FIFO)
  259. push_cdp_cb_event(new_event);
  260. } else {
  261. LM_DBG("Ignoring event [%d] from CDP session\n", event);
  262. }
  263. }
  264. /**
  265. * Handler for incoming Diameter requests.
  266. * @param request - the received request
  267. * @param param - generic pointer
  268. * @returns the answer to this request
  269. */
  270. AAAMessage* callback_cdp_request(AAAMessage *request, void *param) {
  271. if (is_req(request)) {
  272. switch (request->applicationId) {
  273. case IMS_Rx:
  274. case IMS_Gq:
  275. switch (request->commandCode) {
  276. case IMS_RAR:
  277. LM_INFO("Rx request handler():- Received an IMS_RAR \n");
  278. /* TODO: Add support for Re-Auth Requests */
  279. return 0;
  280. break;
  281. case IMS_ASR:
  282. LM_INFO("Rx request handler(): - Received an IMS_ASR \n");
  283. return rx_process_asr(request);
  284. break;
  285. default:
  286. 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);
  287. return 0;
  288. break;
  289. }
  290. break;
  291. default:
  292. LM_ERR("Rx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
  293. return 0;
  294. break;
  295. }
  296. }
  297. return 0;
  298. }
  299. static void free_dialog_data(void *data) {
  300. str *rx_session_id = (str*) data;
  301. if (rx_session_id) {
  302. if (rx_session_id->s) {
  303. shm_free(rx_session_id->s);
  304. rx_session_id->s = 0;
  305. }
  306. shm_free(rx_session_id);
  307. rx_session_id = 0;
  308. }
  309. }
  310. void callback_dialog_terminated(struct dlg_cell* dlg, int type, struct dlg_cb_params * params) {
  311. LM_DBG("Dialog has ended - we need to terminate Rx bearer session\n");
  312. str *rx_session_id;
  313. rx_session_id = (str*) * params->param;
  314. if (!rx_session_id) {
  315. LM_ERR("Invalid Rx session id");
  316. return;
  317. }
  318. LM_DBG("Received notification of termination of dialog with Rx session ID: [%.*s]\n",
  319. rx_session_id->len, rx_session_id->s);
  320. LM_DBG("Retrieving Rx auth data for this session id");
  321. LM_DBG("Sending STR\n");
  322. rx_send_str(rx_session_id);
  323. return;
  324. }
  325. void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param) {
  326. LM_DBG("----------------------!\n");
  327. LM_DBG("PCSCF Contact Callback!\n");
  328. LM_DBG("Contact AOR: [%.*s]\n", c->aor.len, c->aor.s);
  329. LM_DBG("Callback type [%d]\n", type);
  330. if (type == PCSCF_CONTACT_EXPIRE || type == PCSCF_CONTACT_DELETE) {
  331. //we dont need to send STR if no QoS was ever succesfully registered!
  332. if (must_send_str && (c->reg_state != PCONTACT_REG_PENDING) && (c->reg_state != PCONTACT_REG_PENDING_AAR)) {
  333. LM_DBG("Received notification of contact (in state [%d] deleted for signalling bearer with with Rx session ID: [%.*s]\n",
  334. c->reg_state, c->rx_session_id.len, c->rx_session_id.s);
  335. LM_DBG("Sending STR\n");
  336. rx_send_str(&c->rx_session_id);
  337. }
  338. }
  339. }
  340. /* Wrapper to send AAR from config file - this only allows for AAR for calls - not register, which uses r_rx_aar_register
  341. * return: 1 - success, <=0 failure. 2 - message not a AAR generating message (ie proceed without PCC if you wish)
  342. */
  343. static int w_rx_aar(struct sip_msg *msg, char* direction, char* bar) {
  344. struct cell *t;
  345. AAAMessage* resp;
  346. AAASession* auth_session;
  347. rx_authsessiondata_t* rx_authdata_p = 0;
  348. unsigned int result = AAA_SUCCESS;
  349. str *rx_session_id;
  350. str callid = {0, 0};
  351. str ftag = {0, 0};
  352. str ttag = {0, 0};
  353. //We don't ever do AAR on request for calling scenario...
  354. if (msg->first_line.type != SIP_REPLY) {
  355. LM_DBG("Can't do AAR for call session in request\n");
  356. goto error;
  357. }
  358. //is it appropriate to send AAR at this stage?
  359. t = tmb.t_gett();
  360. if (!t) {
  361. LM_WARN("Cannot get transaction for AAR based on SIP Request\n");
  362. goto aarna;
  363. }
  364. //we dont apply QoS if its not a reply to an INVITE! or UPDATE or PRACK!
  365. if ((t->method.len == 5 && memcmp(t->method.s, "PRACK", 5) == 0)
  366. || (t->method.len == 6 && (memcmp(t->method.s, "INVITE", 6) == 0
  367. || memcmp(t->method.s, "UPDATE", 6) == 0))) {
  368. if (cscf_get_content_length(msg) == 0
  369. || cscf_get_content_length(t->uas.request) == 0) {
  370. goto aarna; //AAR na if we dont have offer/answer pair
  371. }
  372. } else {
  373. goto aarna;
  374. }
  375. /* get callid, from and to tags to be able to identify dialog */
  376. callid = cscf_get_call_id(msg, 0);
  377. if (callid.len <= 0 || !callid.s) {
  378. LM_ERR("unable to get callid\n");
  379. goto error;
  380. }
  381. if (!cscf_get_from_tag(msg, &ftag)) {
  382. LM_ERR("Unable to get ftag\n");
  383. goto error;
  384. }
  385. if (!cscf_get_to_tag(msg, &ttag)) {
  386. LM_ERR("Unable to get ttag\n");
  387. goto error;
  388. }
  389. //check to see that this is not a result of a retransmission in reply route only
  390. if (msg->cseq == NULL
  391. && ((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || (msg->cseq == NULL))) {
  392. LM_ERR("No Cseq header found - aborting\n");
  393. goto error;
  394. }
  395. //Check that we dont already have an auth session for this specific dialog
  396. //if not we create a new one and attach it to the dialog (via session ID).
  397. enum dialog_direction dlg_direction = get_dialog_direction(direction);
  398. if (dlg_direction == DLG_MOBILE_ORIGINATING) {
  399. rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
  400. &orig_session_key);
  401. } else {
  402. rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
  403. &term_session_key);
  404. }
  405. if (!rx_session_id || rx_session_id->len <= 0 || !rx_session_id->s) {
  406. LM_DBG("New AAR session for this dialog in mode %s\n", direction);
  407. //create new diameter auth session
  408. int ret = create_new_callsessiondata(&callid, &ftag, &ttag, &rx_authdata_p);
  409. if (!ret) {
  410. LM_DBG("Unable to create new media session data parcel\n");
  411. goto error;
  412. }
  413. auth_session = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_authdata_p); //returns with a lock
  414. if (!auth_session) {
  415. LM_ERR("Rx: unable to create new Rx Media Session\n");
  416. if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
  417. if (rx_authdata_p) {
  418. shm_free(rx_authdata_p);
  419. rx_authdata_p = 0;
  420. }
  421. goto error;
  422. }
  423. //attach new cdp auth session to dlg for this direction
  424. if (dlg_direction == DLG_MOBILE_ORIGINATING) {
  425. dlgb.set_dlg_var(&callid, &ftag, &ttag,
  426. &orig_session_key, &auth_session->id);
  427. } else {
  428. dlgb.set_dlg_var(&callid, &ftag, &ttag,
  429. &term_session_key, &auth_session->id);
  430. }
  431. LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
  432. } else {
  433. LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
  434. //TODO - what to do on updates - reinvites, etc
  435. goto aarna; //TODO: for now we ignore
  436. }
  437. resp = rx_send_aar(t->uas.request, msg, auth_session, &callid, &ftag, &ttag,
  438. direction, &rx_authdata_p);
  439. if (!resp) {
  440. LM_ERR("No response received for AAR request\n");
  441. goto error;
  442. }
  443. if (!rx_authdata_p) {
  444. LM_ERR("Rx: mod.c: error creating new rx_auth_data\n");
  445. goto error;
  446. }
  447. //
  448. // /* Process the response to AAR, retrieving result code and associated Rx session ID */
  449. if (rx_process_aaa(resp, &result) < 0) {
  450. LM_DBG("Failed to process AAA from PCRF\n");
  451. cdpb.AAAFreeMessage(&resp);
  452. goto error;
  453. }
  454. cdpb.AAAFreeMessage(&resp);
  455. if (result >= 2000 && result < 3000) {
  456. LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", result);
  457. str * passed_rx_session_id = shm_malloc(sizeof (struct _str));
  458. passed_rx_session_id->s = 0;
  459. passed_rx_session_id->len = 0;
  460. STR_SHM_DUP(*passed_rx_session_id, auth_session->id, "cb_passed_rx_session_id");
  461. LM_DBG("passed rx session id %.*s", passed_rx_session_id->len, passed_rx_session_id->s);
  462. dlgb.register_dlgcb_nodlg(&callid, &ftag, &ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED, callback_dialog_terminated, (void*) (passed_rx_session_id), free_dialog_data);
  463. return RX_RETURN_TRUE;
  464. } else {
  465. LM_DBG("Received negative reply from PCRF for AAR Request\n");
  466. //we don't free rx_authdata_p here - it is free-ed when the CDP session expires
  467. goto error; // if its not a success then that means i want to reject this call!
  468. }
  469. out_of_memory:
  470. error :
  471. LM_ERR("Error trying to send AAR (calling)\n");
  472. return RX_RETURN_FALSE;
  473. aarna:
  474. LM_DBG("Policy and Charging Control non-applicable\n");
  475. return RX_RETURN_AAR_NA;
  476. }
  477. /* Wrapper to send AAR from config file - only used for registration */
  478. static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
  479. int ret = CSCF_RETURN_ERROR;
  480. struct pcontact_info ci;
  481. struct cell *t;
  482. contact_t* c;
  483. struct hdr_field* h;
  484. pcontact_t* pcontact;
  485. contact_body_t* cb = 0;
  486. AAASession* auth;
  487. rx_authsessiondata_t* rx_regsession_data_p;
  488. cfg_action_t* cfg_action = 0;
  489. char* p;
  490. int aar_sent = 0;
  491. saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
  492. saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
  493. aar_param_t* ap = (aar_param_t*) str1;
  494. udomain_t* domain_t = ap->domain;
  495. cfg_action = ap->paction->next;
  496. int is_rereg = 0; //is this a reg/re-reg
  497. LM_DBG("Rx AAR Register called\n");
  498. //create the default return code AVP
  499. create_return_code(ret);
  500. memset(&ci, 0, sizeof (struct pcontact_info));
  501. /** If this is a response then let's check the status before we try and do an AAR.
  502. * We will only do AAR for register on success response and of course if message is register
  503. */
  504. if (msg->first_line.type == SIP_REPLY) {
  505. //check this is a response to a register
  506. /* Get the SIP request from this transaction */
  507. t = tmb.t_gett();
  508. if (!t) {
  509. LM_ERR("Cannot get transaction for AAR based on SIP Request\n");
  510. goto error;
  511. }
  512. if ((strncmp(t->method.s, "REGISTER", 8) != 0)) {
  513. LM_ERR("Method is not a response to a REGISTER\n");
  514. goto error;
  515. }
  516. if (msg->first_line.u.reply.statuscode < 200
  517. || msg->first_line.u.reply.statuscode >= 300) {
  518. LM_DBG("Message is not a 2xx OK response to a REGISTER\n");
  519. goto error;
  520. }
  521. tmb.t_release(msg);
  522. } else { //SIP Request
  523. /* in case of request make sure it is a REGISTER */
  524. if (msg->first_line.u.request.method_value != METHOD_REGISTER) {
  525. LM_DBG("This is not a register request\n");
  526. goto error;
  527. }
  528. if ((cscf_get_max_expires(msg, 0) == 0)) {
  529. //if ((cscf_get_expires(msg) == 0)) {
  530. LM_DBG("This is a de registration\n");
  531. LM_DBG("We ignore it as these are dealt with by usrloc callbacks \n");
  532. create_return_code(RX_RETURN_TRUE);
  533. return RX_RETURN_TRUE;
  534. }
  535. }
  536. //before we continue, make sure we have a transaction to work with (viz. cdp async)
  537. t = tmb.t_gett();
  538. if (t == NULL || t == T_UNDEFINED) {
  539. if (tmb.t_newtran(msg) < 0) {
  540. LM_ERR("cannot create the transaction for UAR async\n");
  541. return CSCF_RETURN_ERROR;
  542. }
  543. t = tmb.t_gett();
  544. if (t == NULL || t == T_UNDEFINED) {
  545. LM_ERR("cannot lookup the transaction\n");
  546. return CSCF_RETURN_ERROR;
  547. }
  548. }
  549. saved_t_data = (saved_transaction_t*)shm_malloc(sizeof(saved_transaction_t));
  550. if (!saved_t_data){
  551. LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
  552. return CSCF_RETURN_ERROR;
  553. }
  554. memset(saved_t_data,0,sizeof(saved_transaction_t));
  555. saved_t_data->act = cfg_action;
  556. saved_t_data->domain = domain_t;
  557. saved_t_data->lock = lock_alloc();
  558. if (saved_t_data->lock == NULL) {
  559. LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
  560. return CSCF_RETURN_ERROR;
  561. }
  562. if (lock_init(saved_t_data->lock) == NULL) {
  563. LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
  564. return CSCF_RETURN_ERROR;
  565. }
  566. LM_DBG("Suspending SIP TM transaction\n");
  567. if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) < 0) {
  568. LM_ERR("failed to suspend the TM processing\n");
  569. free_saved_transaction_global_data(saved_t_data);
  570. return CSCF_RETURN_ERROR;
  571. }
  572. LM_DBG("Successfully suspended transaction\n");
  573. //now get the contacts in the REGISTER and do AAR for each one.
  574. cb = cscf_parse_contacts(msg);
  575. if (!cb || (!cb->contacts && !cb->star)) {
  576. LM_DBG("No contact headers in Register message\n");
  577. goto error;
  578. }
  579. lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
  580. for (h = msg->contact; h; h = h->next) {
  581. if (h->type == HDR_CONTACT_T && h->parsed) {
  582. for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
  583. ul.lock_udomain(domain_t, &c->uri);
  584. if (ul.get_pcontact(domain_t, &c->uri, &pcontact) != 0) {
  585. LM_DBG("This contact does not exist in PCSCF usrloc - error in cfg file\n");
  586. ul.unlock_udomain(domain_t, &c->uri);
  587. lock_release(saved_t_data->lock);
  588. goto error;
  589. } else if (pcontact->reg_state == PCONTACT_REG_PENDING
  590. || pcontact->reg_state == PCONTACT_REGISTERED) { //NEW reg request
  591. LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
  592. , pcontact->aor.len, pcontact->aor.s);
  593. //get IP address from contact
  594. struct sip_uri puri;
  595. if (parse_uri(c->uri.s, c->uri.len, &puri) < 0) {
  596. LM_ERR("failed to parse Contact\n");
  597. ul.unlock_udomain(domain_t, &c->uri);
  598. lock_release(saved_t_data->lock);
  599. goto error;
  600. }
  601. LM_DBG("Parsed URI of from host is [%.*s]\n", puri.host.len, puri.host.s);
  602. uint16_t ip_version = AF_INET; //TODO IPv6!!!?
  603. //check for existing Rx session
  604. if (pcontact->rx_session_id.len > 0
  605. && pcontact->rx_session_id.s
  606. && (auth = cdpb.AAAGetAuthSession(pcontact->rx_session_id))) {
  607. LM_DBG("Rx session already exists for this user\n");
  608. if (memcmp(pcontact->rx_session_id.s, auth->id.s, auth->id.len) != 0) {
  609. LM_ERR("Rx session mismatch when URI is [%.*s].......Aborting\n", puri.host.len, puri.host.s);
  610. if (auth) cdpb.AAASessionsUnlock(auth->hash);
  611. lock_release(saved_t_data->lock);
  612. goto error;
  613. }
  614. //re-registration - update auth lifetime
  615. auth->u.auth.lifetime = time(NULL) + rx_auth_expiry;
  616. is_rereg = 1;
  617. } else {
  618. LM_DBG("Creating new Rx session for contact <%.*s>\n", pcontact->aor.len, pcontact->aor.s);
  619. int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &rx_regsession_data_p);
  620. if (!ret) {
  621. LM_ERR("Unable to create regsession data parcel when URI is [%.*s]...Aborting\n", puri.host.len, puri.host.s);
  622. ul.unlock_udomain(domain_t, &c->uri);
  623. if (rx_regsession_data_p) {
  624. shm_free(rx_regsession_data_p);
  625. rx_regsession_data_p = 0;
  626. }
  627. lock_release(saved_t_data->lock);
  628. goto error;
  629. }
  630. auth = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_regsession_data_p); //returns with a lock
  631. if (!auth) {
  632. LM_ERR("Rx: unable to create new Rx Reg Session when URI is [%.*s]\n", puri.host.len, puri.host.s);
  633. if (rx_regsession_data_p) {
  634. shm_free(rx_regsession_data_p);
  635. rx_regsession_data_p = 0;
  636. }
  637. ul.unlock_udomain(domain_t, &c->uri);
  638. if (auth) cdpb.AAASessionsUnlock(auth->hash);
  639. if (rx_regsession_data_p) {
  640. shm_free(rx_regsession_data_p);
  641. rx_regsession_data_p = 0;
  642. }
  643. lock_release(saved_t_data->lock);
  644. goto error;
  645. }
  646. }
  647. //we are ready to send the AAR async. lets save the local data data
  648. int local_data_len = sizeof(saved_transaction_local_t) + c->uri.len + auth->id.len;
  649. local_data = shm_malloc(local_data_len);
  650. if (!local_data) {
  651. LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
  652. lock_release(saved_t_data->lock);
  653. goto error;
  654. }
  655. memset(local_data, 0, local_data_len);
  656. local_data->is_rereg = is_rereg;
  657. local_data->global_data = saved_t_data;
  658. p = (char*) (local_data + 1);
  659. local_data->contact.s = p;
  660. local_data->contact.len = c->uri.len;
  661. memcpy(p, c->uri.s, c->uri.len);
  662. p+=c->uri.len;
  663. local_data->auth_session_id.s = p;
  664. local_data->auth_session_id.len = auth->id.len;
  665. memcpy(p, auth->id.s, auth->id.len);
  666. p+=auth->id.len;
  667. if (p!=( ((char*)local_data) + local_data_len) ) {
  668. LM_CRIT("buffer overflow\n");
  669. free_saved_transaction_data(local_data);
  670. goto error;
  671. }
  672. LM_DBG("Calling send aar register");
  673. ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
  674. ul.unlock_udomain(domain_t, &c->uri);
  675. if (!ret) {
  676. LM_ERR("Failed to send AAR\n");
  677. lock_release(saved_t_data->lock);
  678. free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
  679. goto error;
  680. } else {
  681. aar_sent = 1;
  682. //before we send - bump up the reply counter
  683. saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
  684. }
  685. } else {
  686. //contact exists - this is a re-registration, for now we just ignore this
  687. LM_DBG("This contact exists and is not in state REGISTER PENDING - we assume re (or de) registration and ignore\n");
  688. ul.unlock_udomain(domain_t, &c->uri);
  689. //now we loop for any other contacts.
  690. }
  691. }
  692. } else {
  693. if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
  694. LM_ERR("Failed to parse contact header\n");
  695. lock_release(saved_t_data->lock);
  696. goto error;
  697. }
  698. }
  699. }
  700. //all requests sent at this point - we can unlock the reply lock
  701. lock_release(saved_t_data->lock);
  702. /*if we get here, we have either:
  703. * 1. Successfully sent AAR's for ALL contacts, or
  704. * 2. haven't needed to send ANY AAR's for ANY contacts
  705. */
  706. if (aar_sent) {
  707. LM_DBG("Successful async send of AAR\n");
  708. return RX_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
  709. } else {
  710. create_return_code(RX_RETURN_TRUE);
  711. free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
  712. return RX_RETURN_TRUE;
  713. }
  714. error:
  715. LM_ERR("Error trying to send AAR\n");
  716. if (!aar_sent)
  717. if (saved_t_data)
  718. 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
  719. //otherwise the callback will segfault
  720. return RX_RETURN_FALSE;
  721. }
  722. static int fixup_aar_register(void** param, int param_no)
  723. {
  724. udomain_t* d;
  725. aar_param_t *ap;
  726. if(param_no!=1)
  727. return 0;
  728. ap = (aar_param_t*)pkg_malloc(sizeof(aar_param_t));
  729. if(ap==NULL)
  730. {
  731. LM_ERR("no more pkg\n");
  732. return -1;
  733. }
  734. memset(ap, 0, sizeof(aar_param_t));
  735. ap->paction = get_action_from_param(param, param_no);
  736. if (ul.register_udomain((char*) *param, &d) < 0) {
  737. LM_ERR("failed to register domain\n");
  738. return E_UNSPEC;
  739. }
  740. ap->domain = d;
  741. *param = (void*)ap;
  742. return 0;
  743. }
  744. /*create a return code to be passed back into config file*/
  745. int create_return_code(int result) {
  746. int rc;
  747. int_str avp_val, avp_name;
  748. avp_name.s.s = "aar_return_code";
  749. avp_name.s.len = 15;
  750. LM_DBG("Creating return code of [%d] for aar_return_code\n", result);
  751. //build avp spec for uaa_return_code
  752. avp_val.n = result;
  753. rc = add_avp(AVP_NAME_STR, avp_name, avp_val);
  754. if (rc < 0)
  755. LM_ERR("couldn't create [aar_return_code] AVP\n");
  756. else
  757. LM_DBG("created AVP successfully : [%.*s]\n", avp_name.s.len, avp_name.s.s);
  758. return rc;
  759. }