cxdx_avp.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  43. *
  44. */
  45. #include "../cdp/cdp_load.h"
  46. #include "../../modules/tm/tm_load.h"
  47. #include "cxdx_avp.h"
  48. static str s_empty = {0, 0};
  49. /**
  50. * Create and add an AVP to a Diameter message.
  51. * @param m - Diameter message to add to
  52. * @param d - the payload data
  53. * @param len - length of the payload data
  54. * @param avp_code - the code of the AVP
  55. * @param flags - flags for the AVP
  56. * @param vendorid - the value of the vendor id or 0 if none
  57. * @param data_do - what to do with the data when done
  58. * @param func - the name of the calling function, for debugging purposes
  59. * @returns 1 on success or 0 on failure
  60. */
  61. static inline int cxdx_add_avp(AAAMessage *m,char *d,int len,int avp_code,
  62. int flags,int vendorid,int data_do,const char *func)
  63. {
  64. AAA_AVP *avp;
  65. if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
  66. avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do);
  67. if (!avp) {
  68. LM_ERR("%s: Failed creating avp\n",func);
  69. return 0;
  70. }
  71. if (cdpb.AAAAddAVPToMessage(m,avp,m->avpList.tail)!=AAA_ERR_SUCCESS) {
  72. LM_ERR("%s: Failed adding avp to message\n",func);
  73. cdpb.AAAFreeAVP(&avp);
  74. return 0;
  75. }
  76. return 1;
  77. }
  78. /**
  79. * Create and add an AVP to a list of AVPs.
  80. * @param list - the AVP list to add to
  81. * @param d - the payload data
  82. * @param len - length of the payload data
  83. * @param avp_code - the code of the AVP
  84. * @param flags - flags for the AVP
  85. * @param vendorid - the value of the vendor id or 0 if none
  86. * @param data_do - what to do with the data when done
  87. * @param func - the name of the calling function, for debugging purposes
  88. * @returns 1 on success or 0 on failure
  89. */
  90. static inline int cxdx_add_avp_list(AAA_AVP_LIST *list,char *d,int len,int avp_code,
  91. int flags,int vendorid,int data_do,const char *func)
  92. {
  93. AAA_AVP *avp;
  94. if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
  95. avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do);
  96. if (!avp) {
  97. LM_ERR("%s: Failed creating avp\n",func);
  98. return 0;
  99. }
  100. if (list->tail) {
  101. avp->prev=list->tail;
  102. avp->next=0;
  103. list->tail->next = avp;
  104. list->tail=avp;
  105. } else {
  106. list->head = avp;
  107. list->tail = avp;
  108. avp->next=0;
  109. avp->prev=0;
  110. }
  111. return 1;
  112. }
  113. /**
  114. * Returns the value of a certain AVP from a Diameter message.
  115. * @param m - Diameter message to look into
  116. * @param avp_code - the code to search for
  117. * @param vendorid - the value of the vendor id to look for or 0 if none
  118. * @param func - the name of the calling function, for debugging purposes
  119. * @returns the str with the payload on success or an empty string on failure
  120. */
  121. static inline str cxdx_get_avp(AAAMessage *msg,int avp_code,int vendor_id,
  122. const char *func)
  123. {
  124. AAA_AVP *avp;
  125. str r={0,0};
  126. avp = cdpb.AAAFindMatchingAVP(msg,0,avp_code,vendor_id,0);
  127. if (avp==0){
  128. LM_INFO("%s: Failed finding avp (avp_code = %d, vendor_id = %d)\n",func, avp_code, vendor_id);
  129. return r;
  130. }
  131. else
  132. return avp->data;
  133. }
  134. /**
  135. * Creates and adds a Destination-Realm AVP.
  136. * @param msg - the Diameter message to add to.
  137. * @param data - the value for the AVP payload
  138. * @returns 1 on success or 0 on error
  139. */
  140. inline int cxdx_add_destination_realm(AAAMessage *msg,str data)
  141. {
  142. return
  143. cxdx_add_avp(msg,data.s,data.len,
  144. AVP_Destination_Realm,
  145. AAA_AVP_FLAG_MANDATORY,
  146. 0,
  147. AVP_DUPLICATE_DATA,
  148. __FUNCTION__);
  149. }
  150. /**
  151. * Creates and adds a Vendor-Specifig-Application-ID AVP.
  152. * @param msg - the Diameter message to add to.
  153. * @param vendor_id - the value of the vendor_id,
  154. * @param auth_id - the authorization application id
  155. * @param acct_id - the accounting application id
  156. * @returns 1 on success or 0 on error
  157. */
  158. inline int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id,
  159. unsigned int auth_id,unsigned int acct_id)
  160. {
  161. AAA_AVP_LIST list;
  162. str group;
  163. char x[4];
  164. list.head=0;list.tail=0;
  165. set_4bytes(x,vendor_id);
  166. cxdx_add_avp_list(&list,
  167. x,4,
  168. AVP_Vendor_Id,
  169. AAA_AVP_FLAG_MANDATORY,
  170. 0,
  171. AVP_DUPLICATE_DATA,
  172. __FUNCTION__);
  173. if (auth_id) {
  174. set_4bytes(x,auth_id);
  175. cxdx_add_avp_list(&list,
  176. x,4,
  177. AVP_Auth_Application_Id,
  178. AAA_AVP_FLAG_MANDATORY,
  179. 0,
  180. AVP_DUPLICATE_DATA,
  181. __FUNCTION__);
  182. }
  183. if (acct_id) {
  184. set_4bytes(x,acct_id);
  185. cxdx_add_avp_list(&list,
  186. x,4,
  187. AVP_Acct_Application_Id,
  188. AAA_AVP_FLAG_MANDATORY,
  189. 0,
  190. AVP_DUPLICATE_DATA,
  191. __FUNCTION__);
  192. }
  193. group = cdpb.AAAGroupAVPS(list);
  194. cdpb.AAAFreeAVPList(&list);
  195. return
  196. cxdx_add_avp(msg,group.s,group.len,
  197. AVP_Vendor_Specific_Application_Id,
  198. AAA_AVP_FLAG_MANDATORY,
  199. 0,
  200. AVP_FREE_DATA,
  201. __FUNCTION__);
  202. }
  203. /**
  204. * Creates and adds a Auth-Session-State AVP.
  205. * @param msg - the Diameter message to add to.
  206. * @param data - the value for the AVP payload
  207. * @returns 1 on success or 0 on error
  208. */
  209. inline int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data)
  210. {
  211. char x[4];
  212. set_4bytes(x,data);
  213. return
  214. cxdx_add_avp(msg,x,4,
  215. AVP_Auth_Session_State,
  216. AAA_AVP_FLAG_MANDATORY,
  217. 0,
  218. AVP_DUPLICATE_DATA,
  219. __FUNCTION__);
  220. }
  221. /**
  222. * Creates and adds a User-Name AVP.
  223. * @param msg - the Diameter message to add to.
  224. * @param data - the value for the AVP payload
  225. * @returns 1 on success or 0 on error
  226. */
  227. inline int cxdx_add_user_name(AAAMessage *msg,str data)
  228. {
  229. return
  230. cxdx_add_avp(msg,data.s,data.len,
  231. AVP_User_Name,
  232. AAA_AVP_FLAG_MANDATORY,
  233. 0,
  234. AVP_DUPLICATE_DATA,
  235. __FUNCTION__);
  236. }
  237. /**
  238. * Creates and adds a Public Identity AVP.
  239. * @param msg - the Diameter message to add to.
  240. * @param data - the value for the AVP payload
  241. * @returns 1 on success or 0 on error
  242. */
  243. inline int cxdx_add_public_identity(AAAMessage *msg,str data)
  244. {
  245. return
  246. cxdx_add_avp(msg,data.s,data.len,
  247. AVP_IMS_Public_Identity,
  248. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  249. IMS_vendor_id_3GPP,
  250. AVP_DUPLICATE_DATA,
  251. __FUNCTION__);
  252. }
  253. /**
  254. * Creates and adds a Visited-Network-ID AVP.
  255. * @param msg - the Diameter message to add to.
  256. * @param data - the value for the AVP payload
  257. * @returns 1 on success or 0 on error
  258. */
  259. inline int cxdx_add_visited_network_id(AAAMessage *msg,str data)
  260. {
  261. return
  262. cxdx_add_avp(msg,data.s,data.len,
  263. AVP_IMS_Visited_Network_Identifier,
  264. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  265. IMS_vendor_id_3GPP,
  266. AVP_DUPLICATE_DATA,
  267. __FUNCTION__);
  268. }
  269. /**
  270. * Creates and adds a UAR-Flags AVP.
  271. * @param msg - the Diameter message to add to.
  272. * @param data - the value for the AVP payload
  273. * @returns 1 on success or 0 on error
  274. */
  275. inline int cxdx_add_UAR_flags(AAAMessage *msg, unsigned int sos_reg)
  276. {
  277. char x[4];
  278. /* optional AVP*/
  279. if(!sos_reg)
  280. return 1;
  281. set_4bytes(x, AVP_IMS_UAR_Flags_Emergency_Registration);
  282. return
  283. cxdx_add_avp(msg,x,4,
  284. AVP_IMS_UAR_Flags,
  285. AAA_AVP_FLAG_VENDOR_SPECIFIC,
  286. IMS_vendor_id_3GPP,
  287. AVP_DUPLICATE_DATA,
  288. __FUNCTION__);
  289. }
  290. /**
  291. * Creates and adds a Authorization-Type AVP.
  292. * @param msg - the Diameter message to add to.
  293. * @param data - the value for the AVP payload
  294. * @returns 1 on success or 0 on error
  295. */
  296. inline int cxdx_add_authorization_type(AAAMessage *msg,unsigned int data)
  297. {
  298. char x[4];
  299. set_4bytes(x,data);
  300. return
  301. cxdx_add_avp(msg,x,4,
  302. AVP_IMS_User_Authorization_Type,
  303. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  304. IMS_vendor_id_3GPP,
  305. AVP_DUPLICATE_DATA,
  306. __FUNCTION__);
  307. }
  308. /**
  309. * Returns the Result-Code AVP from a Diameter message.
  310. * @param msg - the Diameter message
  311. * @returns the AVP payload on success or an empty string on error
  312. */
  313. inline int cxdx_get_result_code(AAAMessage *msg, int *data)
  314. {
  315. str s;
  316. s = cxdx_get_avp(msg,
  317. AVP_Result_Code,
  318. 0,
  319. __FUNCTION__);
  320. if (!s.s) return 0;
  321. *data = get_4bytes(s.s);
  322. return 1;
  323. }
  324. /**
  325. * Returns the Experimental-Result-Code AVP from a Diameter message.
  326. * @param msg - the Diameter message
  327. * @returns the AVP payload on success or an empty string on error
  328. */
  329. inline int cxdx_get_experimental_result_code(AAAMessage *msg, int *data)
  330. {
  331. AAA_AVP_LIST list;
  332. AAA_AVP *avp;
  333. str grp;
  334. grp = cxdx_get_avp(msg,
  335. AVP_IMS_Experimental_Result,
  336. 0,
  337. __FUNCTION__);
  338. if (!grp.s) return 0;
  339. list = cdpb.AAAUngroupAVPS(grp);
  340. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Experimental_Result_Code,0,0);
  341. if (!avp||!avp->data.s) {
  342. cdpb.AAAFreeAVPList(&list);
  343. return 0;
  344. }
  345. *data = get_4bytes(avp->data.s);
  346. cdpb.AAAFreeAVPList(&list);
  347. return 1;
  348. }
  349. /**
  350. * Returns the Server-Name AVP from a Diameter message.
  351. * @param msg - the Diameter message
  352. * @returns the AVP payload on success or an empty string on error
  353. */
  354. inline str cxdx_get_server_name(AAAMessage *msg)
  355. {
  356. return cxdx_get_avp(msg,
  357. AVP_IMS_Server_Name,
  358. IMS_vendor_id_3GPP,
  359. __FUNCTION__);
  360. }
  361. /**
  362. * Returns the Capabilities from the grouped AVP from a Diameter message.
  363. * @param msg - the Diameter message
  364. * @param m - array to be filled with the retrieved mandatory capabilities
  365. * @param m_cnt - size of the array above to be filled
  366. * @param o - array to be filled with the retrieved optional capabilities
  367. * @param o_cnt - size of the array above to be filled
  368. * @returns 1 on success 0 on fail
  369. */
  370. inline int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt,
  371. str **p,int *p_cnt)
  372. {
  373. AAA_AVP_LIST list;
  374. AAA_AVP *avp;
  375. str grp;
  376. grp = cxdx_get_avp(msg,
  377. AVP_IMS_Server_Capabilities,
  378. IMS_vendor_id_3GPP,
  379. __FUNCTION__);
  380. if (!grp.s) return 0;
  381. list = cdpb.AAAUngroupAVPS(grp);
  382. avp = list.head;
  383. *m_cnt=0;
  384. *o_cnt=0;
  385. *p_cnt=0;
  386. while(avp){
  387. if (avp->code == AVP_IMS_Mandatory_Capability) (*m_cnt)++;
  388. if (avp->code == AVP_IMS_Optional_Capability) (*o_cnt)++;
  389. if (avp->code == AVP_IMS_Server_Name) (*p_cnt)++;
  390. avp = avp->next;
  391. }
  392. avp = list.head;
  393. *m=shm_malloc(sizeof(int)*(*m_cnt));
  394. if (!*m){
  395. LM_ERR("cannot allocated %lx bytes of shm.\n",
  396. sizeof(int)*(*m_cnt));
  397. goto error;
  398. }
  399. *o=shm_malloc(sizeof(int)*(*o_cnt));
  400. if (!*o){
  401. LM_ERR("cannot allocated %lx bytes of shm.\n",
  402. sizeof(int)*(*o_cnt));
  403. goto error;
  404. }
  405. *p=shm_malloc(sizeof(str)*(*p_cnt));
  406. if (!*p){
  407. LM_ERR("cannot allocated %lx bytes of shm.\n",
  408. sizeof(str)*(*p_cnt));
  409. goto error;
  410. }
  411. *m_cnt=0;
  412. *o_cnt=0;
  413. *p_cnt=0;
  414. while(avp){
  415. if (avp->code == AVP_IMS_Mandatory_Capability)
  416. (*m)[(*m_cnt)++]=get_4bytes(avp->data.s);
  417. if (avp->code == AVP_IMS_Optional_Capability)
  418. (*o)[(*o_cnt)++]=get_4bytes(avp->data.s);
  419. if (avp->code == AVP_IMS_Server_Name)
  420. (*p)[(*p_cnt)++]=avp->data;
  421. avp = avp->next;
  422. }
  423. cdpb.AAAFreeAVPList(&list);
  424. return 1;
  425. error:
  426. cdpb.AAAFreeAVPList(&list);
  427. if (*m) shm_free(*m);
  428. if (*o) shm_free(*o);
  429. if (*p) shm_free(*p);
  430. *m_cnt=0;
  431. *o_cnt=0;
  432. *p_cnt=0;
  433. return 0;
  434. }
  435. /**
  436. * Transactional SIP response - tries to create a transaction if none found.
  437. * @param msg - message to reply to
  438. * @param code - the Status-code for the response
  439. * @param text - the Reason-Phrase for the response
  440. * @returns the tmb.t_repy() result
  441. */
  442. int cscf_reply_transactional(struct sip_msg *msg, int code, char *text)
  443. {
  444. unsigned int hash,label;
  445. if (tmb.t_get_trans_ident(msg,&hash,&label)<0){
  446. if (tmb.t_newtran(msg)<0)
  447. LM_ERR("Failed creating SIP transaction\n");
  448. }
  449. return tmb.t_reply(msg,code,text);
  450. }
  451. /**
  452. * Creates and adds a SIP-Number-Auth-Items AVP.
  453. * @param msg - the Diameter message to add to.
  454. * @param data - the value for the AVP payload
  455. * @returns 1 on success or 0 on error
  456. */
  457. inline int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data)
  458. {
  459. char x[4];
  460. set_4bytes(x,data);
  461. return
  462. cxdx_add_avp(msg,x,4,
  463. AVP_IMS_SIP_Number_Auth_Items,
  464. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  465. IMS_vendor_id_3GPP,
  466. AVP_DUPLICATE_DATA,
  467. __FUNCTION__);
  468. }
  469. /**
  470. * Creates and adds a SIP-Auth-Data-Item AVP.
  471. * @param msg - the Diameter message to add to.
  472. * @param auth_scheme - the value for the authorization scheme AVP
  473. * @param auth - the value for the authorization AVP
  474. * @returns 1 on success or 0 on error
  475. */
  476. inline int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str auth, str username, str realm,str method, str server_name)
  477. {
  478. AAA_AVP_LIST list;
  479. str group;
  480. str etsi_authorization = {0, 0};
  481. list.head=0;list.tail=0;
  482. if (auth_scheme.len){
  483. cxdx_add_avp_list(&list,
  484. auth_scheme.s,auth_scheme.len,
  485. AVP_IMS_SIP_Authentication_Scheme,
  486. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  487. IMS_vendor_id_3GPP,
  488. AVP_DONT_FREE_DATA,
  489. __FUNCTION__);
  490. }
  491. if (auth.len){
  492. cxdx_add_avp_list(&list,
  493. auth.s,auth.len,
  494. AVP_IMS_SIP_Authorization,
  495. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  496. IMS_vendor_id_3GPP,
  497. AVP_DONT_FREE_DATA,
  498. __FUNCTION__);
  499. }
  500. if (server_name.len)
  501. {
  502. etsi_authorization = cxdx_ETSI_sip_authorization(username, realm, s_empty, server_name, s_empty, s_empty, method, s_empty);
  503. if (etsi_authorization.len){
  504. cxdx_add_avp_list(&list,
  505. etsi_authorization.s,etsi_authorization.len,
  506. AVP_ETSI_SIP_Authorization,
  507. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  508. IMS_vendor_id_ETSI,
  509. AVP_FREE_DATA,
  510. __FUNCTION__);
  511. }
  512. }
  513. if (!list.head) return 1;
  514. group = cdpb.AAAGroupAVPS(list);
  515. cdpb.AAAFreeAVPList(&list);
  516. return
  517. cxdx_add_avp(msg,group.s,group.len,
  518. AVP_IMS_SIP_Auth_Data_Item,
  519. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  520. IMS_vendor_id_3GPP,
  521. AVP_FREE_DATA,
  522. __FUNCTION__);
  523. }
  524. /**
  525. * Creates and adds a Server-Name AVP.
  526. * @param msg - the Diameter message to add to.
  527. * @param data - the value for the AVP payload
  528. * @returns 1 on success or 0 on error
  529. */
  530. inline int cxdx_add_server_name(AAAMessage *msg,str data)
  531. {
  532. return
  533. cxdx_add_avp(msg,data.s,data.len,
  534. AVP_IMS_Server_Name,
  535. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  536. IMS_vendor_id_3GPP,
  537. AVP_DUPLICATE_DATA,
  538. __FUNCTION__);
  539. }
  540. /**
  541. * Returns the SIP-Number-Auth-Items AVP from a Diameter message.
  542. * @param msg - the Diameter message
  543. * @returns the number or 0 on error
  544. */
  545. inline int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data)
  546. {
  547. str s;
  548. s = cxdx_get_avp(msg,
  549. AVP_IMS_SIP_Number_Auth_Items,
  550. IMS_vendor_id_3GPP,
  551. __FUNCTION__);
  552. if (!s.s) return 0;
  553. *data = get_4bytes(s.s);
  554. return 1;
  555. }
  556. /**
  557. * Returns the Auth-Data-Item from a Diameter answer message.
  558. * @param msg - the Diameter message
  559. * @param auth_date - the string to fill with the authorization data
  560. * @param item_number - the int to fill with the item number
  561. * @param auth_scheme - the string to fill with the authentication scheme data
  562. * @param authenticate - the string to fill with the authenticate data
  563. * @param authorization - the string to fill with the authorization data
  564. * @param ck - the string to fill with the cipher key
  565. * @param ik - the string to fill with the integrity key
  566. * @returns the AVP payload on success or an empty string on error
  567. */
  568. int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data,
  569. int *item_number,str *auth_scheme,str *authenticate,str *authorization,
  570. str *ck,str *ik,
  571. str *ip,
  572. str *ha1, str *response_auth, str *digest_realm,
  573. str *line_identifier)
  574. {
  575. AAA_AVP_LIST list;
  576. AAA_AVP_LIST list2;
  577. AAA_AVP *avp;
  578. AAA_AVP *avp2;
  579. str grp;
  580. ha1->s = 0; ha1->len = 0;
  581. *auth_data = cdpb.AAAFindMatchingAVP(msg,*auth_data,AVP_IMS_SIP_Auth_Data_Item,
  582. IMS_vendor_id_3GPP,0);
  583. if (!*auth_data) return 0;
  584. grp = (*auth_data)->data;
  585. if (!grp.len) return 0;
  586. list = cdpb.AAAUngroupAVPS(grp);
  587. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Item_Number,
  588. IMS_vendor_id_3GPP,0);
  589. if (!avp||!avp->data.len==4) *item_number=0;
  590. else *item_number = get_4bytes(avp->data.s);
  591. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authentication_Scheme,
  592. IMS_vendor_id_3GPP,0);
  593. if (!avp||!avp->data.s) {auth_scheme->s=0;auth_scheme->len=0;}
  594. else *auth_scheme = avp->data;
  595. /* Early-IMS */
  596. ip->s=0;ip->len=0;
  597. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IP_Address,0,0);
  598. if (avp && avp->data.s){
  599. if (avp->data.len!=4){
  600. LM_ERR("Invalid length of AVP Framed IP Address (should be 4 for AVP_Framed_IP_Address) >%d.\n",
  601. avp->data.len);
  602. }
  603. ip->len = 4;
  604. ip->s = avp->data.s;
  605. } else {
  606. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IPv6_Prefix,0,0);
  607. if (avp && avp->data.s){
  608. if (avp->data.len==0){
  609. LM_ERR("Invalid length of AVP Framed IPv6 Prefix (should be >0 for AVP_Framed_IPv6_Prefix) >%d.\n",
  610. avp->data.len);
  611. }
  612. ip->len = avp->data.len;
  613. ip->s = avp->data.s;
  614. }
  615. }
  616. /* Digest */
  617. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_CableLabs_SIP_Digest_Authenticate,IMS_vendor_id_CableLabs,0);
  618. if (avp && avp->data.s)
  619. {
  620. list2 = cdpb.AAAUngroupAVPS(avp->data);
  621. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_CableLabs_Digest_HA1,IMS_vendor_id_CableLabs,0);
  622. if (!avp2||!avp2->data.s) {
  623. ha1->s = 0; ha1->len = 0;
  624. cdpb.AAAFreeAVPList(&list2);
  625. return 0;
  626. }
  627. *ha1 = avp2->data;
  628. cdpb.AAAFreeAVPList(&list2);
  629. }
  630. /* SIP Digest */
  631. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Digest_Authenticate,IMS_vendor_id_3GPP,0);
  632. if (avp && avp->data.s)
  633. {
  634. list2 = cdpb.AAAUngroupAVPS(avp->data);
  635. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_IMS_Digest_HA1,0,0);
  636. if (!avp2||!avp2->data.s) {
  637. ha1->s = 0; ha1->len = 0;
  638. cdpb.AAAFreeAVPList(&list2);
  639. return 0;
  640. }
  641. *ha1 = avp2->data;
  642. cdpb.AAAFreeAVPList(&list2);
  643. }
  644. /* AKA, MD5 */
  645. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authenticate,
  646. IMS_vendor_id_3GPP,0);
  647. if (!avp||!avp->data.s) {authenticate->s=0;authenticate->len=0;}
  648. else *authenticate = avp->data;
  649. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authorization,
  650. IMS_vendor_id_3GPP,0);
  651. if (!avp||!avp->data.s) {authorization->s=0;authorization->len=0;}
  652. else *authorization = avp->data;
  653. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Confidentiality_Key,
  654. IMS_vendor_id_3GPP,0);
  655. if (!avp||!avp->data.s) {ck->s=0;ck->len=0;}
  656. else *ck = avp->data;
  657. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Integrity_Key,
  658. IMS_vendor_id_3GPP,0);
  659. if (!avp||!avp->data.s) {ik->s=0;ik->len=0;}
  660. else *ik = avp->data;
  661. /* ETSI HTTP Digest */
  662. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authenticate,IMS_vendor_id_ETSI,0);
  663. if (avp && avp->data.s)
  664. {
  665. list2 = cdpb.AAAUngroupAVPS(avp->data);
  666. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Realm, IMS_vendor_id_ETSI,0);
  667. if (!avp2||!avp2->data.s) {
  668. digest_realm->s=0;digest_realm->len=0;
  669. cdpb.AAAFreeAVPList(&list2);
  670. return 0;
  671. }
  672. *digest_realm = avp2->data;
  673. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Nonce, IMS_vendor_id_ETSI,0);
  674. if (!avp2||!avp2->data.s) {
  675. authenticate->s=0;authenticate->len=0;
  676. cdpb.AAAFreeAVPList(&list2);
  677. return 0;
  678. }
  679. *authenticate = avp2->data;
  680. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_HA1, IMS_vendor_id_ETSI,0);
  681. if (!avp2||!avp2->data.s) {
  682. ha1->s = 0; ha1->len = 0;
  683. cdpb.AAAFreeAVPList(&list2);
  684. return 0;
  685. }
  686. *ha1 = avp2->data;
  687. cdpb.AAAFreeAVPList(&list2);
  688. }
  689. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authentication_Info,IMS_vendor_id_ETSI,0);
  690. if (avp && avp->data.s)
  691. {
  692. list2 = cdpb.AAAUngroupAVPS(avp->data);
  693. avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Response_Auth, IMS_vendor_id_ETSI,0);
  694. if (!avp2||!avp2->data.s) {
  695. response_auth->s=0;response_auth->len=0;
  696. cdpb.AAAFreeAVPList(&list2);
  697. return 0;
  698. }
  699. *response_auth = avp2->data;
  700. cdpb.AAAFreeAVPList(&list2);
  701. }
  702. else
  703. {
  704. response_auth->s=0;response_auth->len=0;
  705. }
  706. /* NASS Bundled */
  707. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_Line_Identifier, IMS_vendor_id_ETSI,0);
  708. if (!avp||!avp->data.s) {line_identifier->s=0;line_identifier->len=0;}
  709. else *line_identifier = avp->data;
  710. cdpb.AAAFreeAVPList(&list);
  711. return 1;
  712. }
  713. /**
  714. * Creates and adds a ETSI_sip_authorization AVP.
  715. * @param username - UserName
  716. * @param realm - Realm
  717. * @param nonce - Nonce
  718. * @param URI - URI
  719. * @param response - Response
  720. * @param algoritm - Algorithm
  721. * @param method - Method
  722. * @param hash - Enitity-Body-Hash
  723. * @returns grouped str on success
  724. */
  725. str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, str response, str algorithm, str method, str hash)
  726. {
  727. AAA_AVP_LIST list;
  728. str group = {0, 0};
  729. list.head=0;list.tail=0;
  730. if (username.len){
  731. cxdx_add_avp_list(&list,
  732. username.s,username.len,
  733. AVP_ETSI_Digest_Username,
  734. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  735. IMS_vendor_id_ETSI,
  736. AVP_DONT_FREE_DATA,
  737. __FUNCTION__);
  738. }
  739. if (realm.len){
  740. cxdx_add_avp_list(&list,
  741. realm.s,realm.len,
  742. AVP_ETSI_Digest_Realm,
  743. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  744. IMS_vendor_id_ETSI,
  745. AVP_DONT_FREE_DATA,
  746. __FUNCTION__);
  747. }
  748. if (nonce.len){
  749. cxdx_add_avp_list(&list,
  750. nonce.s,nonce.len,
  751. AVP_ETSI_Digest_Nonce,
  752. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  753. IMS_vendor_id_ETSI,
  754. AVP_DONT_FREE_DATA,
  755. __FUNCTION__);
  756. }
  757. if (URI.len){
  758. cxdx_add_avp_list(&list,
  759. URI.s,URI.len,
  760. AVP_ETSI_Digest_URI,
  761. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  762. IMS_vendor_id_ETSI,
  763. AVP_DONT_FREE_DATA,
  764. __FUNCTION__);
  765. }
  766. if (response.len){
  767. cxdx_add_avp_list(&list,
  768. response.s,response.len,
  769. AVP_ETSI_Digest_Response,
  770. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  771. IMS_vendor_id_ETSI,
  772. AVP_DONT_FREE_DATA,
  773. __FUNCTION__);
  774. }
  775. if (algorithm.len){
  776. cxdx_add_avp_list(&list,
  777. algorithm.s,algorithm.len,
  778. AVP_ETSI_Digest_Algorithm,
  779. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  780. IMS_vendor_id_ETSI,
  781. AVP_DONT_FREE_DATA,
  782. __FUNCTION__);
  783. }
  784. if (method.len){
  785. cxdx_add_avp_list(&list,
  786. method.s,method.len,
  787. AVP_ETSI_Digest_Method,
  788. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  789. IMS_vendor_id_ETSI,
  790. AVP_DONT_FREE_DATA,
  791. __FUNCTION__);
  792. }
  793. if (hash.len){
  794. cxdx_add_avp_list(&list,
  795. hash.s,hash.len,
  796. AVP_ETSI_Digest_Entity_Body_Hash,
  797. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  798. IMS_vendor_id_ETSI,
  799. AVP_DONT_FREE_DATA,
  800. __FUNCTION__);
  801. }
  802. if (!list.head) return group;
  803. group = cdpb.AAAGroupAVPS(list);
  804. cdpb.AAAFreeAVPList(&list);
  805. return group;
  806. }
  807. /**
  808. * Returns the User-Data from a Diameter message.
  809. * @param msg - the Diameter message
  810. * @returns the AVP payload on success or an empty string on error
  811. */
  812. inline str cxdx_get_user_data(AAAMessage *msg)
  813. {
  814. return cxdx_get_avp(msg,
  815. AVP_IMS_User_Data_Cx,
  816. IMS_vendor_id_3GPP,
  817. __FUNCTION__);
  818. }
  819. /**
  820. * Returns the Charging-Information from a Diameter message.
  821. * @param msg - the Diameter message
  822. * @returns the AVP payload on success or an empty string on error
  823. */
  824. inline int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ecf2)
  825. {
  826. AAA_AVP_LIST list;
  827. AAA_AVP *avp;
  828. str grp;
  829. grp = cxdx_get_avp(msg,
  830. AVP_IMS_Charging_Information,
  831. IMS_vendor_id_3GPP,
  832. __FUNCTION__);
  833. if (!grp.s) return 0;
  834. list = cdpb.AAAUngroupAVPS(grp);
  835. if (ccf1){
  836. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Charging_Collection_Function_Name,
  837. IMS_vendor_id_3GPP,0);
  838. if (avp) *ccf1 = avp->data;
  839. }
  840. if (ccf2){
  841. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Charging_Collection_Function_Name,
  842. IMS_vendor_id_3GPP,0);
  843. if (avp) *ccf2 = avp->data;
  844. }
  845. if (ecf1){
  846. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Event_Charging_Function_Name,
  847. IMS_vendor_id_3GPP,0);
  848. if (avp) *ecf1 = avp->data;
  849. }
  850. if (ecf2){
  851. avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Event_Charging_Function_Name,
  852. IMS_vendor_id_3GPP,0);
  853. if (avp) *ecf2 = avp->data;
  854. }
  855. cdpb.AAAFreeAVPList(&list);
  856. return 1;
  857. }
  858. /**
  859. * Creates and adds a Server-Assignment-Type AVP.
  860. * @param msg - the Diameter message to add to.
  861. * @param data - the value for the AVP payload
  862. * @returns 1 on success or 0 on error
  863. */
  864. inline int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data)
  865. {
  866. char x[4];
  867. set_4bytes(x,data);
  868. return
  869. cxdx_add_avp(msg,x,4,
  870. AVP_IMS_Server_Assignment_Type,
  871. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  872. IMS_vendor_id_3GPP,
  873. AVP_DUPLICATE_DATA,
  874. __FUNCTION__);
  875. }
  876. /**
  877. * Creates and adds Userdata-Available AVP.
  878. * @param msg - the Diameter message to add to.
  879. * @param data - the value for the AVP payload
  880. * @returns 1 on success or 0 on error
  881. */
  882. inline int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data)
  883. {
  884. char x[4];
  885. set_4bytes(x,data);
  886. return
  887. cxdx_add_avp(msg,x,4,
  888. AVP_IMS_User_Data_Already_Available,
  889. AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
  890. IMS_vendor_id_3GPP,
  891. AVP_DUPLICATE_DATA,
  892. __FUNCTION__);
  893. }
  894. /**
  895. * Finds out the next Public-Identity AVP from a Diameter message.
  896. * @param msg - the Diameter message
  897. * @param pos - position to resume search or NULL if to start from the first AVP
  898. * @param avp_code - the code of the AVP to look for
  899. * @param vendor_id - the vendor id of the AVP to look for
  900. * @param func - the name of the calling function for debugging purposes
  901. * @returns the AVP payload on success or an empty string on error
  902. */
  903. inline AAA_AVP* cxdx_get_next_public_identity(AAAMessage *msg,AAA_AVP* pos,int avp_code,int vendor_id,const char *func)
  904. {
  905. AAA_AVP *avp;
  906. avp = cdpb.AAAFindMatchingAVP(msg,pos,avp_code,vendor_id,0);
  907. if (avp==0){
  908. LM_DBG("INFO:%s: Failed finding avp\n",func);
  909. return avp;
  910. }
  911. else
  912. return avp;
  913. }
  914. /**
  915. * Returns the User-Name AVP from a Diameter message.
  916. * @param msg - the Diameter message
  917. * @returns the AVP payload on success or an empty string on error
  918. */
  919. inline str cxdx_get_user_name(AAAMessage *msg)
  920. {
  921. return cxdx_get_avp(msg,
  922. AVP_User_Name,
  923. 0,
  924. __FUNCTION__);
  925. }
  926. /**
  927. * Creates and adds a Result-Code AVP.
  928. * @param msg - the Diameter message to add to.
  929. * @param data - the value for the AVP payload
  930. * @returns 1 on success or 0 on error
  931. */
  932. inline int cxdx_add_result_code(AAAMessage *msg,unsigned int data)
  933. {
  934. char x[4];
  935. set_4bytes(x,data);
  936. return
  937. cxdx_add_avp(msg,x,4,
  938. AVP_Result_Code,
  939. AAA_AVP_FLAG_MANDATORY,
  940. 0,
  941. AVP_DUPLICATE_DATA,
  942. __FUNCTION__);
  943. }