ims_getters.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652
  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 "../../parser/msg_parser.h"
  46. #include "../../parser/digest/digest.h"
  47. #include "../../parser/parse_to.h"
  48. #include "../../parser/parse_expires.h"
  49. #include "../../parser/contact/parse_contact.h"
  50. #include "../../parser/parse_uri.h"
  51. #include "../../parser/parse_rr.h"
  52. #include "../../parser/parse_nameaddr.h"
  53. #include "../../data_lump.h"
  54. #include "../../data_lump_rpl.h"
  55. #include "../../parser/parse_from.h"
  56. #include "../../parser/parse_content.h"
  57. #include "ims_getters.h"
  58. #include "../../parser/parse_ppi_pai.h"
  59. /**
  60. * Delete parameters and stuff from uri.
  61. * @param uri - the string to operate on
  62. */
  63. static inline void cscf_strip_uri(str *uri)
  64. {
  65. int i;
  66. /* Strip the ending */
  67. i=0;
  68. while(i<uri->len&&uri->s[i]!='@')
  69. i++;
  70. while(i<uri->len&&
  71. uri->s[i]!=':'&&
  72. uri->s[i]!='/'&&
  73. uri->s[i]!='&')
  74. i++;
  75. uri->len=i;
  76. }
  77. /**
  78. * Parses all the contact headers.
  79. * @param msg - the SIP message
  80. * @returns the first contact_body
  81. */
  82. contact_body_t *cscf_parse_contacts(struct sip_msg *msg)
  83. {
  84. struct hdr_field* ptr;
  85. if (!msg) return 0;
  86. if (parse_headers(msg, HDR_EOH_F, 0)<0){
  87. LM_ERR("Error parsing headers \n");
  88. return 0;
  89. }
  90. if (msg->contact) {
  91. ptr = msg->contact;
  92. while(ptr) {
  93. if (ptr->type == HDR_CONTACT_T) {
  94. if (msg->contact->parsed==0){
  95. if (parse_contact(ptr)<0){
  96. LM_DBG("error parsing contacts [%.*s]\n",
  97. ptr->body.len,ptr->body.s);
  98. }
  99. }
  100. }
  101. ptr = ptr->next;
  102. }
  103. }
  104. if (!msg->contact) return 0;
  105. return msg->contact->parsed;
  106. }
  107. /**
  108. * Returns the Private Identity extracted from the Authorization header.
  109. * If none found there takes the SIP URI in To without the "sip:" prefix
  110. * \todo - remove the fallback case to the To header
  111. * @param msg - the SIP message
  112. * @param realm - the realm to match in an Authorization header
  113. * @returns the str containing the private id, no mem dup
  114. */
  115. str cscf_get_private_identity(struct sip_msg *msg, str realm)
  116. {
  117. str pi={0,0};
  118. struct hdr_field* h=0;
  119. int ret,i,res;
  120. if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
  121. return pi;
  122. }
  123. h = msg->authorization;
  124. if (!msg->authorization){
  125. goto fallback;
  126. }
  127. if (realm.len && realm.s) {
  128. ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_F, &h);
  129. if (ret < 0) {
  130. goto fallback;
  131. } else
  132. if (ret > 0) {
  133. goto fallback;
  134. }
  135. }
  136. res = parse_credentials(h);
  137. if (res != 0) {
  138. LOG(L_ERR, "Error while parsing credentials\n");
  139. return pi;
  140. }
  141. if (h) pi=((auth_body_t*)h->parsed)->digest.username.whole;
  142. goto done;
  143. fallback:
  144. pi = cscf_get_public_identity(msg);
  145. if (pi.len>4&&strncasecmp(pi.s,"sip:",4)==0) {pi.s+=4;pi.len-=4;}
  146. for(i=0;i<pi.len;i++)
  147. if (pi.s[i]==';') {
  148. pi.len=i;
  149. break;
  150. }
  151. done:
  152. return pi;
  153. }
  154. /**
  155. * Returns the Private Identity extracted from the Authorization header.
  156. * If none found there takes the SIP URI in To without the "sip:" prefix
  157. * \todo - remove the fallback case to the To header
  158. * @param msg - the SIP message
  159. * @param realm - the realm to match in an Authorization header
  160. * @returns the str containing the private id, no mem dup
  161. */
  162. str cscf_get_private_identity_no_realm(struct sip_msg *msg, str realm)
  163. {
  164. str pi={0,0};
  165. struct hdr_field* h=0;
  166. int i;
  167. if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
  168. return pi;
  169. }
  170. if (!msg->authorization){
  171. goto fallback;
  172. }
  173. h = msg->authorization;
  174. if (h) pi=((auth_body_t*)h->parsed)->digest.username.whole;
  175. goto done;
  176. fallback:
  177. pi = cscf_get_public_identity(msg);
  178. if (pi.len>4&&strncasecmp(pi.s,"sip:",4)==0) {pi.s+=4;pi.len-=4;}
  179. for(i=0;i<pi.len;i++)
  180. if (pi.s[i]==';') {
  181. pi.len=i;
  182. break;
  183. }
  184. done:
  185. return pi;
  186. }
  187. /**
  188. * Returns the Public Identity extracted from the To header
  189. * @param msg - the SIP message
  190. * @returns the str containing the public id, no mem dup
  191. */
  192. str cscf_get_public_identity(struct sip_msg *msg)
  193. {
  194. str pu={0,0};
  195. struct to_body *to;
  196. int i;
  197. if (parse_headers(msg,HDR_TO_F,0)!=0) {
  198. return pu;
  199. }
  200. if ( get_to(msg) == NULL ) {
  201. to = (struct to_body*) pkg_malloc(sizeof(struct to_body));
  202. parse_to( msg->to->body.s, msg->to->body.s + msg->to->body.len, to );
  203. msg->to->parsed = to;
  204. }
  205. else to=(struct to_body *) msg->to->parsed;
  206. pu = to->uri;
  207. /* truncate to sip:username@host or tel:number */
  208. for(i=4;i<pu.len;i++)
  209. if (pu.s[i]==';' || pu.s[i]=='?' ||pu.s[i]==':'){
  210. pu.len = i;
  211. }
  212. return pu;
  213. }
  214. /**
  215. * Returns the expires value from the Expires header in the message.
  216. * It searches into the Expires header and if not found returns -1
  217. * @param msg - the SIP message, if available
  218. * @is_shm - msg from from shared memory
  219. * @returns the value of the expire or -1 if not found
  220. */
  221. int cscf_get_expires_hdr(struct sip_msg *msg, int is_shm)
  222. {
  223. exp_body_t *exp;
  224. int expires;
  225. if (!msg) return -1;
  226. /*first search in Expires header */
  227. if (parse_headers(msg,HDR_EXPIRES_F,0)!=0) {
  228. return -1;
  229. }
  230. if (msg->expires){
  231. if (!msg->expires->parsed) {
  232. parse_expires(msg->expires);
  233. }
  234. if (msg->expires->parsed) {
  235. exp = (exp_body_t*) msg->expires->parsed;
  236. if (exp->valid) {
  237. expires = exp->val;
  238. if(is_shm) {
  239. free_expires((exp_body_t**)&exp);
  240. msg->expires->parsed = 0;
  241. }
  242. return expires;
  243. }
  244. }
  245. }
  246. return -1;
  247. }
  248. /**
  249. * Returns the expires value from the message.
  250. * First it searches into the Expires header and if not found it also looks
  251. * into the expires parameter in the contact header
  252. * @param msg - the SIP message
  253. * @param is_shm - msg from shared memory
  254. * @returns the value of the expire or the default 3600 if none found
  255. */
  256. int cscf_get_max_expires(struct sip_msg *msg, int is_shm)
  257. {
  258. unsigned int exp;
  259. int max_expires = -1;
  260. struct hdr_field *h;
  261. contact_t *c;
  262. /*first search in Expires header */
  263. max_expires = cscf_get_expires_hdr(msg, is_shm);
  264. cscf_parse_contacts(msg);
  265. for(h=msg->contact;h;h=h->next){
  266. if (h->type==HDR_CONTACT_T && h->parsed) {
  267. for(c=((contact_body_t *) h->parsed)->contacts;c;c=c->next){
  268. if(c->expires){
  269. if (!str2int(&(c->expires->body), (unsigned int*)&exp) && (int)exp>max_expires) max_expires = exp;
  270. }
  271. }
  272. }
  273. }
  274. if(is_shm){
  275. for(h=msg->contact;h;h=h->next){
  276. if (h->type==HDR_CONTACT_T && h->parsed) {
  277. free_contact((contact_body_t**)&(h->parsed));
  278. h->parsed = 0;
  279. }
  280. }
  281. }
  282. return max_expires;
  283. }
  284. /**
  285. * Get the Public Identity from the Request URI of the message
  286. * NB: free returned result str when done from shm
  287. * @param msg - the SIP message
  288. * @returns the public identity (don't forget to free from shm)
  289. */
  290. str cscf_get_public_identity_from_requri(struct sip_msg *msg)
  291. {
  292. str pu={0,0};
  293. if (msg->first_line.type!=SIP_REQUEST) {
  294. return pu;
  295. }
  296. if (parse_sip_msg_uri(msg)<0){
  297. return pu;
  298. }
  299. if(msg->parsed_uri.type==TEL_URI_T){
  300. pu.len = 4 + msg->parsed_uri.user.len ;
  301. pu.s = shm_malloc(pu.len+1);
  302. if (!pu.s){
  303. LM_ERR("cscf_get_public_identity_from_requri: Error allocating %d bytes\n", pu.len + 1);
  304. pu.len = 0;
  305. goto done;
  306. }
  307. sprintf(pu.s,"tel:%.*s",
  308. msg->parsed_uri.user.len,
  309. msg->parsed_uri.user.s);
  310. }else{
  311. pu.len = 4 + msg->parsed_uri.user.len + 1 + msg->parsed_uri.host.len;
  312. pu.s = shm_malloc(pu.len+1);
  313. if (!pu.s){
  314. LM_ERR("cscf_get_public_identity_from_requri: Error allocating %d bytes\n", pu.len + 1);
  315. pu.len = 0;
  316. goto done;
  317. }
  318. sprintf(pu.s,"sip:%.*s@%.*s",
  319. msg->parsed_uri.user.len,
  320. msg->parsed_uri.user.s,
  321. msg->parsed_uri.host.len,
  322. msg->parsed_uri.host.s);
  323. }
  324. done:
  325. return pu;
  326. }
  327. /**
  328. * Get the contact from the Request URI of the message
  329. * NB: free returned result str when done from shm
  330. * @param msg - the SIP message
  331. * @returns the contact (don't forget to free from shm)
  332. *
  333. * NOTE: should only be called when REQ URI has been converted sip:user@IP_ADDRESS:PORT or tel:IP_ADDRESS:PORT
  334. */
  335. str cscf_get_contact_from_requri(struct sip_msg *msg)
  336. {
  337. str pu={0,0};
  338. if (msg->first_line.type!=SIP_REQUEST) {
  339. return pu;
  340. }
  341. if (parse_sip_msg_uri(msg)<0){
  342. return pu;
  343. }
  344. if(!msg->parsed_uri.port.len){
  345. return pu;
  346. }
  347. if(msg->parsed_uri.type==TEL_URI_T){
  348. pu.len = 4 + msg->parsed_uri.user.len + msg->parsed_uri.port.len + 1 /*for colon before port*/;
  349. pu.s = shm_malloc(pu.len+1);
  350. if (!pu.s){
  351. LM_ERR("cscf_get_public_identity_from_requri: Error allocating %d bytes\n", pu.len + 1);
  352. pu.len = 0;
  353. goto done;
  354. }
  355. sprintf(pu.s,"tel:%.*s:%.*s",
  356. msg->parsed_uri.user.len,
  357. msg->parsed_uri.user.s,
  358. msg->parsed_uri.port.len,
  359. msg->parsed_uri.port.s);
  360. }else{
  361. pu.len = 4 + msg->parsed_uri.user.len + 1/*for @*/ + msg->parsed_uri.host.len + msg->parsed_uri.port.len + 1 /*for colon before port*/;
  362. pu.s = shm_malloc(pu.len+1);
  363. if (!pu.s){
  364. LM_ERR("cscf_get_public_identity_from_requri: Error allocating %d bytes\n", pu.len + 1);
  365. pu.len = 0;
  366. goto done;
  367. }
  368. sprintf(pu.s,"sip:%.*s@%.*s:%.*s",
  369. msg->parsed_uri.user.len,
  370. msg->parsed_uri.user.s,
  371. msg->parsed_uri.host.len,
  372. msg->parsed_uri.host.s,
  373. msg->parsed_uri.port.len,
  374. msg->parsed_uri.port.s);
  375. }
  376. done:
  377. return pu;
  378. }
  379. /**
  380. * Finds if the message contains the orig parameter in the first Route header
  381. * @param msg - the SIP message
  382. * @param str1 - not used
  383. * @param str2 - not used
  384. * @returns #CSCF_RETURN_TRUE if yes, else #CSCF_RETURN_FALSE
  385. */
  386. int cscf_has_originating(struct sip_msg *msg,char *str1,char *str2)
  387. {
  388. //int ret=CSCF_RETURN_FALSE;
  389. struct hdr_field *h;
  390. str* uri;
  391. rr_t *r;
  392. if (parse_headers(msg, HDR_ROUTE_F, 0)<0){
  393. LM_DBG("I_originating: error parsing headers\n");
  394. return CSCF_RETURN_FALSE;
  395. }
  396. h = msg->route;
  397. if (!h){
  398. LM_DBG("I_originating: Header Route not found\n");
  399. return CSCF_RETURN_FALSE;
  400. }
  401. if (parse_rr(h)<0){
  402. LM_DBG("I_originating: Error parsing as Route header\n");
  403. return CSCF_RETURN_FALSE;
  404. }
  405. r = (rr_t*)h->parsed;
  406. uri = &r->nameaddr.uri;
  407. struct sip_uri puri;
  408. if (parse_uri(uri->s, uri->len, &puri) < 0) {
  409. LM_DBG( "I_originating: Error while parsing the first route URI\n");
  410. return -1;
  411. }
  412. if (puri.params.len < 4) return CSCF_RETURN_FALSE;
  413. int c = 0;
  414. int state = 0;
  415. while (c < puri.params.len) {
  416. switch (puri.params.s[c]) {
  417. case 'o': if (state==0) state=1;
  418. break;
  419. case 'r': if (state==1) state=2;
  420. break;
  421. case 'i': if (state==2) state=3;
  422. break;
  423. case 'g': if (state==3) state=4;
  424. break;
  425. case ' ':
  426. case '\t':
  427. case '\r':
  428. case '\n':
  429. case ',':
  430. case ';':
  431. if (state==4) return CSCF_RETURN_TRUE;
  432. state=0;
  433. break;
  434. case '=': if (state==4) return CSCF_RETURN_TRUE;
  435. state=-1;
  436. break;
  437. default: state=-1;
  438. }
  439. c++;
  440. }
  441. return state==4 ? CSCF_RETURN_TRUE : CSCF_RETURN_FALSE;
  442. }
  443. str s_asserted_identity={"P-Asserted-Identity",19};
  444. /**
  445. * Looks for the P-Asserted-Identity header and extracts its content
  446. * @param msg - the sip message
  447. * @returns the asserted identity
  448. */
  449. str cscf_get_asserted_identity(struct sip_msg *msg, int is_shm) {
  450. int len;
  451. str uri = { 0, 0 };
  452. if (!msg || !msg->pai)
  453. return uri;
  454. if ((parse_pai_header(msg) == 0) && (msg->pai) && (msg->pai->parsed)) {
  455. to_body_t *pai = get_pai(msg)->id;
  456. if (!is_shm)
  457. return pai->uri;
  458. //make a pkg malloc str to return to consuming function
  459. len = pai->uri.len + 1;
  460. uri.s = (char*) pkg_malloc(pai->uri.len + 1);
  461. if (!uri.s) {
  462. LM_ERR("no more pkg mem\n");
  463. return uri;
  464. }
  465. memset(uri.s, 0, len);
  466. memcpy(uri.s, pai->uri.s, pai->uri.len);
  467. uri.len = pai->uri.len;
  468. p_id_body_t* ptr = (p_id_body_t*) msg->pai->parsed;
  469. msg->pai->parsed = 0;
  470. free_pai_ppi_body(ptr);
  471. }
  472. return uri;
  473. }
  474. static str phone_context_s={";phone-context=",15};
  475. /**
  476. * Extracts the realm from a SIP/TEL URI.
  477. * - SIP - the hostname
  478. * - TEL - the phone-context parameter
  479. * @param msg - the SIP message
  480. * @returns the realm
  481. */
  482. str cscf_get_realm_from_uri(str uri)
  483. {
  484. str realm={0,0};
  485. int i;
  486. if (uri.len<5) {
  487. LM_DBG( "cscf_get_realm_from_uri: Error trying to extra realm from too short URI <%.*s>.\n",uri.len,uri.s);
  488. return realm;
  489. }
  490. if (strncasecmp(uri.s,"sip:",4)==0||
  491. strncasecmp(uri.s,"sips:",5)==0) {
  492. /* SIP URI */
  493. realm = uri;
  494. for(i=0;i<realm.len;i++)
  495. if (realm.s[i]=='@'){
  496. realm.s = realm.s + i + 1;
  497. realm.len = realm.len - i - 1;
  498. break;
  499. }
  500. if (!realm.len) realm = uri;
  501. for(i=0;i<realm.len;i++)
  502. if (realm.s[i]==';'||realm.s[i]=='&'||realm.s[i]==':') {
  503. realm.len = i;
  504. break;
  505. }
  506. }else
  507. if (strncasecmp(uri.s,"tel:",4)==0) {
  508. /* TEL URI */
  509. realm = uri;
  510. while(realm.s[0]!=';' && realm.len>0){
  511. realm.s++;
  512. realm.len--;
  513. }
  514. if (realm.len<1) {realm.len=0;return realm;}
  515. else{
  516. while(realm.len>phone_context_s.len){
  517. if (strncasecmp(realm.s,phone_context_s.s,phone_context_s.len)==0){
  518. realm.s+=phone_context_s.len;
  519. realm.len-=phone_context_s.len;
  520. for(i=0;i<realm.len;i++)
  521. if (realm.s[i]==';' || realm.s[i]=='&'){
  522. realm.len = i;
  523. break;
  524. }
  525. break;
  526. }
  527. realm.s++;
  528. realm.len--;
  529. }
  530. }
  531. }else{
  532. /* unknown... just extract between @ and ;? */
  533. realm = uri;
  534. for(i=0;i<realm.len;i++)
  535. if (realm.s[i]=='@'){
  536. realm.s = realm.s + i + 1;
  537. realm.len = realm.len - i - 1;
  538. break;
  539. }
  540. if (!realm.len) realm = uri;
  541. for(i=0;i<realm.len;i++)
  542. if (realm.s[i]==';'||realm.s[i]=='&'||realm.s[i]==':') {
  543. realm.len = i;
  544. break;
  545. }
  546. }
  547. LM_DBG( "cscf_get_realm_from_uri: realm <%.*s>.\n",realm.len,realm.s);
  548. return realm;
  549. }
  550. /**
  551. * Delivers the Realm from request URI
  552. * @param msg sip message
  553. * @returns realm as String on success 0 on fail
  554. */
  555. str cscf_get_realm_from_ruri(struct sip_msg *msg)
  556. {
  557. str realm={0,0};
  558. if (!msg || msg->first_line.type!=SIP_REQUEST){
  559. LM_DBG("cscf_get_realm_from_ruri: This is not a request!!!\n");
  560. return realm;
  561. }
  562. if (!msg->parsed_orig_ruri_ok)
  563. if (parse_orig_ruri(msg) < 0)
  564. return realm;
  565. realm = msg->parsed_orig_ruri.host;
  566. return realm;
  567. }
  568. /**
  569. * Looks for the Call-ID header
  570. * @param msg - the sip message
  571. * @param hr - ptr to return the found hdr_field
  572. * @returns the callid value
  573. */
  574. str cscf_get_call_id(struct sip_msg *msg,struct hdr_field **hr)
  575. {
  576. struct hdr_field *h;
  577. str call_id={0,0};
  578. if (hr) *hr = 0;
  579. if (!msg) return call_id;
  580. if (parse_headers(msg, HDR_CALLID_F, 0)<0){
  581. LM_DBG("cscf_get_call_id: error parsing headers\n");
  582. return call_id;
  583. }
  584. h = msg->callid;
  585. if (!h){
  586. LM_DBG("cscf_get_call_id: Header Call-ID not found\n");
  587. return call_id;
  588. }
  589. if (hr) *hr = h;
  590. call_id = h->body;
  591. return call_id;
  592. }
  593. static str sos_uri_par={"sos", 3};
  594. /**
  595. * Check if the contact has an URI parameter with the value "sos",
  596. * used for detecting an Emergency Registration
  597. * http://tools.ietf.org/html/draft-patel-ecrit-sos-parameter-0x
  598. * @param uri - contact uri to be checked
  599. * @return 1 if found, 0 if not, -1 on error
  600. */
  601. int cscf_get_sos_uri_param(str uri)
  602. {
  603. struct sip_uri puri;
  604. param_hooks_t h;
  605. param_t *p=0, *crt;
  606. enum pclass p_class = CLASS_URI;
  607. int ret;
  608. ret = 0;
  609. p = NULL;
  610. if(parse_uri(uri.s, uri.len, &puri)<0){
  611. LM_DBG("cscf_get_sos_uri_param: failed to parse %.*s\n",
  612. uri.len, uri.s);
  613. return -1;
  614. }
  615. if(puri.params.len <= 0)
  616. return 0;
  617. LM_DBG( "cscf_get_sos_uri_param: searching through the uri parameters:%.*s\n",
  618. puri.params.len, puri.params.s);
  619. if(parse_params(&(puri.params), p_class, &h, &p)){
  620. LM_DBG( "cscf_get_sos_uri_param:error while parsing uri parameters\n");
  621. ret = -1;
  622. goto end;
  623. }
  624. for(crt = p ; crt ; crt=crt->next){
  625. LM_DBG( "cscf_get_sos_uri_param:name: %.*s body: %.*s\n",
  626. crt->name.len, crt->name.s,
  627. crt->body.len, crt->body.s);
  628. if((crt->name.len == sos_uri_par.len) &&
  629. (strncmp(crt->name.s, sos_uri_par.s, sos_uri_par.len) == 0)){
  630. ret =1;
  631. goto end;
  632. }
  633. }
  634. end:
  635. if(p) free_params(p);
  636. return ret;
  637. }
  638. str cscf_p_visited_network_id={"P-Visited-Network-ID",20};
  639. /**
  640. * Return the P-Visited-Network-ID header
  641. * @param msg - the SIP message
  642. * @returns the str with the header's body
  643. */
  644. str cscf_get_visited_network_id(struct sip_msg *msg, struct hdr_field **h)
  645. {
  646. str vnid={0,0};
  647. struct hdr_field *hdr;
  648. if (h) *h=0;
  649. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  650. LM_DBG("cscf_get_visited_network_id: Error parsing until header EOH: \n");
  651. return vnid;
  652. }
  653. hdr = msg->headers;
  654. while(hdr){
  655. if (hdr->name.len==cscf_p_visited_network_id.len &&
  656. strncasecmp(hdr->name.s,cscf_p_visited_network_id.s,hdr->name.len)==0)
  657. {
  658. if (h) *h = hdr;
  659. vnid = hdr->body;
  660. goto done;
  661. }
  662. hdr = hdr->next;
  663. }
  664. LM_DBG("cscf_get_visited_network_id: P-Visited-Network-ID header not found \n");
  665. done:
  666. LM_DBG("cscf_get_visited_network_id: <%.*s> \n",
  667. vnid.len,vnid.s);
  668. return vnid;
  669. }
  670. /**
  671. * Adds a header to the message as the first one in the message
  672. * @param msg - the message to add a header to
  673. * @param content - the str containing the new header
  674. * @returns 1 on succes, 0 on failure
  675. */
  676. int cscf_add_header_first(struct sip_msg *msg, str *hdr,int type)
  677. {
  678. struct hdr_field *first;
  679. struct lump* anchor,*l;
  680. first = msg->headers;
  681. anchor = anchor_lump(msg, first->name.s - msg->buf, 0 , 0 );
  682. if (anchor == NULL) {
  683. LM_DBG( "cscf_add_header_first: anchor_lump failed\n");
  684. return 0;
  685. }
  686. if (!(l=insert_new_lump_before(anchor, hdr->s,hdr->len,type))){
  687. LM_ERR( "cscf_add_header_first: error creating lump for header\n" );
  688. return 0;
  689. }
  690. return 1;
  691. }
  692. /**
  693. * Returns the next header structure for a given header name.
  694. * @param msg - the SIP message to look into
  695. * @param header_name - the name of the header to search for
  696. * @param last_header - last header to ignore in the search, or NULL if to start from the first one
  697. * @returns the hdr_field on success or NULL if not found
  698. */
  699. struct hdr_field* cscf_get_next_header(struct sip_msg * msg ,
  700. str header_name,struct hdr_field* last_header)
  701. {
  702. struct hdr_field *h;
  703. if (parse_headers(msg, HDR_EOH_F, 0)<0){
  704. LM_ERR("cscf_get_next_header_field: error parsing headers\n");
  705. return NULL;
  706. }
  707. if (last_header) h = last_header->next;
  708. else h = msg->headers;
  709. while(h){
  710. if (h->name.len==header_name.len &&strncasecmp(h->name.s,header_name.s,header_name.len)==0)
  711. break;
  712. h = h->next;
  713. }
  714. return h;
  715. }
  716. /**
  717. * Looks for the First Via header and returns its body.
  718. * @param msg - the SIP message
  719. * @param h - the hdr_field to fill with the result
  720. * @returns the first via_body
  721. */
  722. struct via_body* cscf_get_first_via(struct sip_msg *msg,struct hdr_field **h)
  723. {
  724. if (h) *h = 0;
  725. if (!msg->h_via1 && parse_headers(msg,HDR_VIA_F,0)!=0) {
  726. LM_ERR("cscf_get_first_via: Error parsing until header Via: \n");
  727. return msg->h_via1->parsed;
  728. }
  729. if (!msg->via1){
  730. LM_ERR( "cscf_get_first_via: Message does not contain Via header.\n");
  731. return msg->h_via1->parsed;
  732. }
  733. return msg->h_via1->parsed;
  734. }
  735. /**
  736. * Looks for the UE Via in First Via header if its a request
  737. * or in the last if its a response and returns its body
  738. * @param msg - the SIP message
  739. * @returns the via of the UE
  740. */
  741. struct via_body* cscf_get_ue_via(struct sip_msg *msg)
  742. {
  743. struct via_body *vb=0;
  744. if (msg->first_line.type==SIP_REQUEST) vb = cscf_get_first_via(msg,0);
  745. else vb = cscf_get_last_via(msg);
  746. if (!vb) return 0;
  747. if (vb->port == 0) vb->port=5060;
  748. return vb;
  749. }
  750. /**
  751. * Looks for the Last Via header and returns it.
  752. * @param msg - the SIP message
  753. * @returns the last via body body
  754. */
  755. struct via_body* cscf_get_last_via(struct sip_msg *msg)
  756. {
  757. struct hdr_field *h=0,*i;
  758. struct via_body *vb;
  759. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  760. LM_ERR("cscf_get_last_via: Error parsing until last header\n");
  761. return 0;
  762. }
  763. i = msg->headers;
  764. while(i){
  765. if (i->type == HDR_VIA_T){
  766. h = i;
  767. }
  768. i = i->next;
  769. }
  770. if (!h) return 0;
  771. if (!h->parsed){
  772. vb = pkg_malloc(sizeof(struct via_body));
  773. if (!vb){
  774. LM_ERR("cscf_get_last_via: Error allocating %lx bytes\n",sizeof(struct via_body));
  775. return 0;
  776. }
  777. parse_via(h->body.s,h->body.s+h->body.len,vb);
  778. h->parsed = vb;
  779. }
  780. vb = h->parsed;
  781. while(vb->next)
  782. vb = vb->next;
  783. return vb;
  784. }
  785. /**
  786. * Looks for the WWW-Authenticate header and returns its body.
  787. * @param msg - the SIP message
  788. * @param h - the hdr_field to fill with the result
  789. * @returns the www-authenticate body
  790. */
  791. str cscf_get_authenticate(struct sip_msg *msg,struct hdr_field **h)
  792. {
  793. str auth={0,0};
  794. struct hdr_field *hdr;
  795. *h = 0;
  796. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  797. LM_ERR("cscf_get_authorization: Error parsing until header WWW-Authenticate: \n");
  798. return auth;
  799. }
  800. hdr = msg->headers;
  801. while(hdr){
  802. if (hdr->name.len ==16 &&
  803. strncasecmp(hdr->name.s,"WWW-Authenticate",16)==0)
  804. {
  805. *h = hdr;
  806. auth = hdr->body;
  807. break;
  808. }
  809. hdr = hdr->next;
  810. }
  811. if (!hdr){
  812. LM_DBG( "cscf_get_authorization: Message does not contain WWW-Authenticate header.\n");
  813. return auth;
  814. }
  815. return auth;
  816. }
  817. /**
  818. * Adds a header to the message
  819. * @param msg - the message to add a header to
  820. * @param content - the str containing the new header
  821. * @returns 1 on succes, 0 on failure
  822. */
  823. int cscf_add_header(struct sip_msg *msg, str *hdr,int type)
  824. {
  825. struct hdr_field *last;
  826. struct lump* anchor;
  827. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  828. LM_ERR("cscf_add_header: Error parsing until end of headers: \n");
  829. return 0;
  830. }
  831. last = msg->headers;
  832. while(last->next)
  833. last = last->next;
  834. anchor = anchor_lump(msg, last->name.s + last->len - msg->buf, 0 , 0);
  835. if (anchor == NULL) {
  836. LM_ERR( "cscf_add_header_first: anchor_lump failed\n");
  837. return 0;
  838. }
  839. if (!insert_new_lump_after(anchor, hdr->s,hdr->len,type)){
  840. LM_ERR( "cscf_add_header_first: error creating lump for header\n" );
  841. return 0;
  842. }
  843. return 1;
  844. }
  845. /**
  846. * Get the expires header value from a message.
  847. * @param msg - the SIP message
  848. * @returns the expires value or -1 if not found
  849. */
  850. int cscf_get_expires(struct sip_msg *msg)
  851. {
  852. if (msg->expires) {
  853. if (parse_expires(msg->expires) < 0) {
  854. LM_INFO("ifc_get_expires:Error while parsing Expires header\n");
  855. return -1;
  856. }
  857. return ((exp_body_t*) msg->expires->parsed)->val;
  858. } else {
  859. return -1;
  860. }
  861. }
  862. static str bye_s={"BYE",3};
  863. static str ack_s={"ACK",3};
  864. static str prack_s={"PRACK",5};
  865. static str update_s={"UPDATE",6};
  866. static str notify_s={"NOTIFY",6};
  867. /**
  868. * Check if the message is an initial request for a dialog.
  869. * - BYE, PRACK, UPDATE, NOTIFY belong to an already existing dialog
  870. * @param msg - the message to check
  871. * @returns 1 if initial, 0 if not
  872. */
  873. int cscf_is_initial_request(struct sip_msg *msg)
  874. {
  875. if (msg->first_line.type != SIP_REQUEST ) return 0;
  876. if (strncasecmp(msg->first_line.u.request.method.s,bye_s.s,bye_s.len)==0) return 0;
  877. if (strncasecmp(msg->first_line.u.request.method.s,ack_s.s,ack_s.len)==0) return 0;
  878. if (strncasecmp(msg->first_line.u.request.method.s,prack_s.s,prack_s.len)==0) return 0;
  879. if (strncasecmp(msg->first_line.u.request.method.s,update_s.s,update_s.len)==0) return 0;
  880. if (strncasecmp(msg->first_line.u.request.method.s,notify_s.s,notify_s.len)==0) return 0;
  881. return 1;
  882. }
  883. /**
  884. * Get the public identity from P-Asserted-Identity, or From if asserted not found.
  885. * @param msg - the SIP message
  886. * @param uri - uri to fill into
  887. * @returns 1 if found, 0 if not
  888. */
  889. int cscf_get_originating_user( struct sip_msg * msg, str *uri )
  890. {
  891. struct to_body * from;
  892. *uri = cscf_get_asserted_identity(msg, 0);
  893. if (!uri->len) {
  894. /* Fallback to From header */
  895. if ( parse_from_header( msg ) == -1 ) {
  896. LM_ERR("ERROR:cscf_get_originating_user: unable to extract URI from FROM header\n" );
  897. return 0;
  898. }
  899. if (!msg->from) return 0;
  900. from = (struct to_body*) msg->from->parsed;
  901. *uri = from->uri;
  902. cscf_strip_uri(uri);
  903. }
  904. DBG("DEBUG:cscf_get_originating_user: From %.*s\n", uri->len,uri->s );
  905. return 1;
  906. }
  907. /**
  908. * Get public identity from Request-URI for terminating.
  909. * returns in uri the freshly pkg allocated uri - don't forget to free
  910. * @param msg - the SIP message
  911. * @param uri - uri to fill into
  912. * @returns 1 if found, else 0
  913. */
  914. int cscf_get_terminating_user( struct sip_msg * msg, str *uri )
  915. {
  916. *uri = cscf_get_public_identity_from_requri(msg);
  917. if (!uri->len) return 0;
  918. return 1;
  919. }
  920. str cscf_p_access_network_info={"P-Access-Network-Info",21};
  921. /**
  922. * Return the P-Access-Network-Info header
  923. * @param msg - the SIP message
  924. * @returns the str with the header's body
  925. */
  926. str cscf_get_access_network_info(struct sip_msg *msg, struct hdr_field **h)
  927. {
  928. str ani={0,0};
  929. struct hdr_field *hdr;
  930. *h=0;
  931. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  932. LM_DBG("cscf_get_access_network_info: Error parsing until header EOH: \n");
  933. return ani;
  934. }
  935. hdr = msg->headers;
  936. while(hdr){
  937. if (hdr->name.len==cscf_p_access_network_info.len &&
  938. strncasecmp(hdr->name.s,cscf_p_access_network_info.s,hdr->name.len)==0)
  939. {
  940. *h = hdr;
  941. ani = hdr->body;
  942. goto done;
  943. }
  944. hdr = hdr->next;
  945. }
  946. LM_DBG("cscf_get_access_network_info: P-Access-Network-Info header not found \n");
  947. done:
  948. LM_DBG("cscf_get_access_network_info: <%.*s> \n",
  949. ani.len,ani.s);
  950. return ani;
  951. }
  952. str cscf_p_charging_vector={"P-Charging-Vector",17};
  953. /**
  954. * Return the P-Charging-Vector header
  955. * @param msg - the SIP message
  956. * @returns the str with the header's body
  957. */
  958. str cscf_get_charging_vector(struct sip_msg *msg, struct hdr_field **h)
  959. {
  960. str cv={0,0};
  961. struct hdr_field *hdr;
  962. *h=0;
  963. if (parse_headers(msg,HDR_EOH_F,0)!=0) {
  964. LM_DBG("cscf_get_charging_vector: Error parsing until header EOH: \n");
  965. return cv;
  966. }
  967. hdr = msg->headers;
  968. while(hdr){
  969. if (hdr->name.len==cscf_p_charging_vector.len &&
  970. strncasecmp(hdr->name.s,cscf_p_charging_vector.s,hdr->name.len)==0)
  971. {
  972. *h = hdr;
  973. cv = hdr->body;
  974. goto done;
  975. }
  976. hdr = hdr->next;
  977. }
  978. LM_DBG("cscf_get_charging_vector: P-Charging-Vector header not found \n");
  979. done:
  980. LM_DBG("cscf_get_charging_vector: <%.*s> \n",
  981. cv.len,cv.s);
  982. return cv;
  983. }
  984. int cscf_get_p_charging_vector(struct sip_msg *msg, str * icid, str * orig_ioi,
  985. str * term_ioi) {
  986. struct hdr_field* header = 0;
  987. str header_body = { 0, 0 };
  988. char * p;
  989. int index;
  990. str temp = { 0, 0 };
  991. if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
  992. LM_ERR("cscf_get_p_charging_vector: error parsing headers\n");
  993. return 0;
  994. }
  995. header = msg->headers;
  996. while (header) {
  997. if (header->name.len == cscf_p_charging_vector.len
  998. && strncasecmp(header->name.s, cscf_p_charging_vector.s, cscf_p_charging_vector.len) == 0)
  999. break;
  1000. header = header->next;
  1001. }
  1002. if (!header) {
  1003. LM_DBG("no header %.*s was found\n", cscf_p_charging_vector.len, cscf_p_charging_vector.s);
  1004. return 0;
  1005. }
  1006. if (!header->body.s || !header->body.len)
  1007. return 0;
  1008. str_dup(header_body, header->body, pkg);
  1009. LM_DBG("p_charging_vector body is %.*s\n", header_body.len, header_body.s);
  1010. p = strtok(header_body.s, " ;:\r\t\n\"=");
  1011. loop: if (p > (header_body.s + header_body.len))
  1012. return 1;
  1013. if (strncmp(p, "icid-value", 10) == 0) {
  1014. p = strtok(NULL, " ;:\r\t\n\"=");
  1015. if (p > (header_body.s + header_body.len)) {
  1016. LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
  1017. return 0;
  1018. }
  1019. temp.s = p;
  1020. temp.len = 0;
  1021. while (*p != '\"') {
  1022. temp.len = temp.len + 1;
  1023. p++;
  1024. }
  1025. icid->len = temp.len;
  1026. index = temp.s - header_body.s;
  1027. LM_DBG("icid len %i, index %i\n", temp.len, index);
  1028. icid->s = header->body.s + index;
  1029. LM_DBG("icid is %.*s\n", icid->len, icid->s);
  1030. p = strtok(NULL, " ;:\r\t\n\"=");
  1031. goto loop;
  1032. } else if (strncmp(p, "orig-ioi", 8) == 0) {
  1033. p = strtok(NULL, " ;:\r\t\n\"=");
  1034. if (p > (header_body.s + header_body.len)) {
  1035. LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
  1036. return 0;
  1037. }
  1038. temp.s = p;
  1039. temp.len = 0;
  1040. while (*p != '\"') {
  1041. temp.len = temp.len + 1;
  1042. p++;
  1043. }
  1044. orig_ioi->len = temp.len;
  1045. index = temp.s - header_body.s;
  1046. LM_DBG("orig ioi len %i, index %i\n", temp.len, index);
  1047. orig_ioi->s = header->body.s + index;
  1048. LM_DBG("orig_ioi is %.*s\n", orig_ioi->len, orig_ioi->s);
  1049. p = strtok(NULL, " ;:\r\t\n\"=");
  1050. goto loop;
  1051. } else if (strncmp(p, "term-ioi", 8) == 0) {
  1052. p = strtok(NULL, " ;:\r\t\n\"=");
  1053. if (p > (header_body.s + header_body.len)) {
  1054. LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
  1055. return 0;
  1056. }
  1057. temp.s = p;
  1058. temp.len = 0;
  1059. while (*p != '\"') {
  1060. temp.len = temp.len + 1;
  1061. p++;
  1062. }
  1063. term_ioi->len = temp.len;
  1064. term_ioi->s = header->body.s + (temp.s - header_body.s);
  1065. p = strtok(NULL, " ;:\r\t\n\"=");
  1066. goto loop;
  1067. } else {
  1068. p = strtok(NULL, " ;:\r\t\n\"=");
  1069. goto loop;
  1070. }
  1071. LM_DBG("end\n");
  1072. str_free(header_body, pkg);
  1073. return 1;
  1074. out_of_memory:
  1075. LM_ERR("cscf_get_p_charging_vector:out of pkg memory\n");
  1076. return 0;
  1077. }
  1078. /**
  1079. * Get the from tag
  1080. * @param msg - the SIP message to look into
  1081. * @param tag - the pointer to the tag to write to
  1082. * @returns 0 on error or 1 on success
  1083. */
  1084. int cscf_get_from_tag(struct sip_msg* msg, str* tag)
  1085. {
  1086. struct to_body* from;
  1087. if (!msg || parse_from_header(msg)<0||!msg->from||!msg->from->parsed){
  1088. LM_DBG("cscf_get_from_tag: error parsing From header\n");
  1089. if (tag) {tag->s = 0;tag->len = 0;}
  1090. return 0;
  1091. }
  1092. from = msg->from->parsed;
  1093. if (tag) *tag = from->tag_value;
  1094. return 1;
  1095. }
  1096. /**
  1097. * Get the to tag
  1098. * @param msg - the SIP Message to look into
  1099. * @param tag - the pointer to the tag to write to
  1100. * @returns 0 on error or 1 on success
  1101. */
  1102. int cscf_get_to_tag(struct sip_msg* msg, str* tag)
  1103. {
  1104. if (!msg || !msg->to) {
  1105. LM_DBG("cscf_get_to_tag(): To header field missing\n");
  1106. if (tag) {tag->s = 0;tag->len = 0;}
  1107. return 0;
  1108. }
  1109. if (tag) *tag = get_to(msg)->tag_value;
  1110. return 1;
  1111. }
  1112. /**
  1113. * Get the local uri from the From header.
  1114. * @param msg - the message to look into
  1115. * @param local_uri - ptr to fill with the value
  1116. * @returns 1 on success or 0 on error
  1117. */
  1118. int cscf_get_from_uri(struct sip_msg* msg,str *local_uri)
  1119. {
  1120. struct to_body* from;
  1121. if (!msg || parse_from_header(msg)<0 || !msg->from || !msg->from->parsed){
  1122. LM_DBG("cscf_get_from_uri: error parsing From header\n");
  1123. if (local_uri) {local_uri->s = 0;local_uri->len = 0;}
  1124. return 0;
  1125. }
  1126. from = msg->from->parsed;
  1127. if (local_uri) *local_uri = from->uri;
  1128. return 1;
  1129. }
  1130. /**
  1131. * Get the local uri from the To header.
  1132. * @param msg - the message to look into
  1133. * @param local_uri - ptr to fill with the value
  1134. * @returns 1 on success or 0 on error
  1135. */
  1136. int cscf_get_to_uri(struct sip_msg* msg,str *local_uri)
  1137. {
  1138. struct to_body* to= NULL;
  1139. if (!msg || !msg->to || !msg->to->parsed || parse_headers(msg,HDR_TO_F,0)==-1 ){
  1140. LM_DBG("cscf_get_to_uri: error parsing TO header\n");
  1141. if (local_uri) {local_uri->s = 0;local_uri->len = 0;}
  1142. return 0;
  1143. }
  1144. to = msg->to->parsed;
  1145. if (local_uri) *local_uri = to->uri;
  1146. return 1;
  1147. }
  1148. /**
  1149. * Looks for the Event header and extracts its content.
  1150. * @param msg - the sip message
  1151. * @returns the string event value or an empty string if none found
  1152. */
  1153. str cscf_get_event(struct sip_msg *msg)
  1154. {
  1155. str e={0,0};
  1156. if (!msg) return e;
  1157. if (parse_headers(msg, HDR_EVENT_F, 0) != -1 && msg->event &&
  1158. msg->event->body.len > 0)
  1159. {
  1160. e.len = msg->event->body.len;
  1161. e.s = msg->event->body.s;
  1162. }
  1163. return e;
  1164. }
  1165. /**
  1166. * Returns the content of the P-Associated-URI header
  1167. * Public_id is pkg_alloced and should be later freed.
  1168. * Inside values are not duplicated.
  1169. * @param msg - the SIP message to look into
  1170. * @param public_id - array to be allocated and filled with the result
  1171. * @param public_id_cnt - the size of the public_id array
  1172. * @param is_shm - msg from shared memory
  1173. * @returns 1 on success or 0 on error
  1174. */
  1175. int cscf_get_p_associated_uri(struct sip_msg *msg, str **public_id,
  1176. int *public_id_cnt, int is_shm) {
  1177. struct hdr_field *h;
  1178. rr_t *r, *r2;
  1179. *public_id = 0;
  1180. *public_id_cnt = 0;
  1181. if (!msg)
  1182. return 0;
  1183. if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
  1184. LM_ERR("error parsing headers\n");
  1185. return 0;
  1186. }
  1187. h = msg->headers;
  1188. while (h) {
  1189. if (h->name.len == 16
  1190. && strncasecmp(h->name.s, "P-Associated-URI", 16) == 0) {
  1191. break;
  1192. }
  1193. h = h->next;
  1194. }
  1195. if (!h) {
  1196. LM_DBG("Header P-Associated-URI not found\n");
  1197. return 0;
  1198. }
  1199. if (parse_rr(h) < 0) {
  1200. LM_DBG("Error parsing as Route header\n");
  1201. return 0;
  1202. }
  1203. r = (rr_t*) h->parsed;
  1204. h->type = HDR_ROUTE_T;
  1205. *public_id_cnt = 0;
  1206. r2 = r;
  1207. while (r2) {
  1208. (*public_id_cnt) = (*public_id_cnt) + 1;
  1209. r2 = r2->next;
  1210. }
  1211. *public_id = pkg_malloc(sizeof(str)*(*public_id_cnt));
  1212. if (!public_id) {
  1213. LM_ERR("Error out of pkg memory");
  1214. return 0;
  1215. }
  1216. r2 = r;
  1217. *public_id_cnt = 0;
  1218. while (r2) {
  1219. (*public_id)[(*public_id_cnt)] = r2->nameaddr.uri;
  1220. (*public_id_cnt) = (*public_id_cnt) + 1;
  1221. r2 = r2->next;
  1222. }
  1223. if (is_shm) {
  1224. r = (rr_t*) h->parsed;
  1225. h->parsed = 0;
  1226. free_rr(&r);
  1227. }
  1228. return 1;
  1229. }
  1230. static str realm_p={"realm=\"",7};
  1231. /**
  1232. * Looks for the realm parameter in the Authorization header and returns its value.
  1233. * @param msg - the SIP message
  1234. * @returns the realm
  1235. */
  1236. str cscf_get_realm(struct sip_msg *msg)
  1237. {
  1238. str realm={0,0};
  1239. int i,k;
  1240. if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
  1241. LM_DBG("Error parsing until header Authorization: \n");
  1242. return realm;
  1243. }
  1244. if (!msg->authorization){
  1245. LM_DBG("Message does not contain Authorization header.\n");
  1246. return realm;
  1247. }
  1248. k = msg->authorization->body.len - realm_p.len;
  1249. for(i=0;i<k;i++)
  1250. if (strncasecmp(msg->authorization->body.s+i,realm_p.s,realm_p.len)==0){
  1251. realm.s = msg->authorization->body.s+ i + realm_p.len;
  1252. i+=realm_p.len;
  1253. while(i<msg->authorization->body.len && msg->authorization->body.s[i]!='\"'){
  1254. i++;
  1255. realm.len++;
  1256. }
  1257. break;
  1258. }
  1259. if (!realm.len){
  1260. LM_DBG("Realm parameter not found.\n");
  1261. return realm;
  1262. }
  1263. LM_DBG("realm <%.*s>.\n",realm.len,realm.s);
  1264. return realm;
  1265. }
  1266. /**
  1267. * Returns the content of the Service-Route header.
  1268. * data vector is pkg_alloced and should be later freed
  1269. * inside values are not duplicated
  1270. * @param msg - the SIP message
  1271. * @param size - size of the returned vector, filled with the result
  1272. * @param is_shm - msg from shared memory
  1273. * @returns - the str vector of uris
  1274. */
  1275. str* cscf_get_service_route(struct sip_msg *msg, int *size, int is_shm) {
  1276. struct hdr_field *h;
  1277. rr_t *r, *r2;
  1278. str *x = 0;
  1279. int k;
  1280. if (!size)
  1281. return 0;
  1282. *size = 0;
  1283. if (!msg)
  1284. return 0;
  1285. if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
  1286. LM_ERR("error parsing headers\n");
  1287. return 0;
  1288. }
  1289. h = msg->headers;
  1290. while (h) {
  1291. if (h->name.len == 13
  1292. && strncasecmp(h->name.s, "Service-Route", 13) == 0) {
  1293. if (parse_rr(h) < 0) {
  1294. LM_ERR("Error parsing as Route header\n");
  1295. continue;
  1296. }
  1297. r = (rr_t*) h->parsed;
  1298. h->type = HDR_ROUTE_T;
  1299. r2 = r;
  1300. k = 0;
  1301. while (r2) {
  1302. k++;
  1303. r2 = r2->next;
  1304. }
  1305. if (!k) {
  1306. LM_DBG("No items in this Service-Route\n");
  1307. continue;
  1308. }
  1309. x = pkg_realloc(x,(*size+k)*sizeof(str));
  1310. if (!x) {
  1311. LM_ERR("Error our of pkg memory");
  1312. return 0;
  1313. }
  1314. r2 = r;
  1315. while (r2) {
  1316. x[*size] = r2->nameaddr.uri;
  1317. (*size) = (*size) + 1;
  1318. r2 = r2->next;
  1319. }
  1320. }
  1321. h = h->next;
  1322. }
  1323. if (is_shm) {
  1324. h = msg->headers;
  1325. while (h) {
  1326. if (h->name.len == 13
  1327. && strncasecmp(h->name.s, "Service-Route", 13) == 0) {
  1328. r = (rr_t*) h->parsed;
  1329. h->parsed = 0;
  1330. free_rr(&r);
  1331. }
  1332. h = h->next;
  1333. }
  1334. }
  1335. return x;
  1336. }
  1337. /**
  1338. * Returns the s_dialog_direction from the direction string.
  1339. * @param direction - "orig" or "term"
  1340. * @returns the s_dialog_direction if ok or #DLG_MOBILE_UNKNOWN if not found
  1341. */
  1342. enum cscf_dialog_direction cscf_get_dialog_direction(char *direction)
  1343. {
  1344. switch(direction[0]){
  1345. case 'o':
  1346. case 'O':
  1347. case '0':
  1348. return CSCF_MOBILE_ORIGINATING;
  1349. case 't':
  1350. case 'T':
  1351. case '1':
  1352. return CSCF_MOBILE_TERMINATING;
  1353. default:
  1354. LM_WARN("Unknown direction %s",direction);
  1355. return CSCF_MOBILE_UNKNOWN;
  1356. }
  1357. }
  1358. long cscf_get_content_length (struct sip_msg* msg)
  1359. {
  1360. int cl = 0;
  1361. if (!msg)
  1362. return 0;
  1363. if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) != -1 && msg->content_length
  1364. && msg->content_length->parsed)
  1365. cl = get_content_length(msg);
  1366. return cl;
  1367. }
  1368. /**
  1369. * Looks for the Contact header and extracts its content
  1370. * @param msg - the sip message
  1371. * @returns the first contact in the message
  1372. */
  1373. str cscf_get_contact(struct sip_msg *msg)
  1374. {
  1375. str id={0,0};
  1376. struct hdr_field *h;
  1377. struct contact_body *cb;
  1378. if (!msg) return id;
  1379. if (parse_headers(msg, HDR_CONTACT_F, 0)<0) {
  1380. LM_ERR("ERR:cscf_get_contact: Error parsing headers until Contact.\n");
  1381. return id;
  1382. }
  1383. h = msg->contact;
  1384. if (!h) {
  1385. LM_ERR("ERR:cscf_get_contact: Contact header not found.\n");
  1386. return id;
  1387. }
  1388. if (h->parsed==0 &&
  1389. parse_contact(h)<0){
  1390. LM_ERR("ERR:cscf_get_contact: Error parsing contacts.\n");
  1391. return id;
  1392. }
  1393. cb = (struct contact_body *)h->parsed;
  1394. if (!cb || !cb->contacts){
  1395. LM_ERR("ERR:cscf_get_contact: No contacts in header.\n");
  1396. return id;
  1397. }
  1398. id = cb->contacts->uri;
  1399. return id;
  1400. }
  1401. /**
  1402. * Adds a header to the reply message
  1403. * @param msg - the request to add a header to its reply
  1404. * @param content - the str containing the new header
  1405. * @returns 1 on succes, 0 on failure
  1406. */
  1407. int cscf_add_header_rpl(struct sip_msg *msg, str *hdr)
  1408. {
  1409. if (add_lump_rpl( msg, hdr->s, hdr->len, LUMP_RPL_HDR)==0) {
  1410. LM_ERR("ERR:cscf_add_header_rpl: Can't add header <%.*s>\n",
  1411. hdr->len,hdr->s);
  1412. return 0;
  1413. }
  1414. return 1;
  1415. }
  1416. /**
  1417. * Looks for the Call-ID header
  1418. * @param msg - the sip message
  1419. * @param hr - ptr to return the found hdr_field
  1420. * @returns the callid value
  1421. */
  1422. int cscf_get_cseq(struct sip_msg *msg,struct hdr_field **hr)
  1423. {
  1424. struct hdr_field *h;
  1425. struct cseq_body *cseq;
  1426. int nr = 0,i;
  1427. if (hr) *hr = 0;
  1428. if (!msg) return 0;
  1429. if (parse_headers(msg, HDR_CSEQ_F, 0)<0){
  1430. LM_ERR("ERR:cscf_get_cseq: error parsing headers\n");
  1431. return 0;
  1432. }
  1433. h = msg->cseq;
  1434. if (!h){
  1435. LM_ERR("ERR:cscf_get_cseq: Header CSeq not found\n");
  1436. return 0;
  1437. }
  1438. if (hr) *hr = h;
  1439. if (!h->parsed){
  1440. cseq = pkg_malloc(sizeof(struct cseq_body));
  1441. if (!cseq){
  1442. LM_ERR("ERR:cscf_get_cseq: Header CSeq not found\n");
  1443. return 0;
  1444. }
  1445. parse_cseq(h->body.s,h->body.s+h->body.len,cseq);
  1446. h->parsed = cseq;
  1447. }else
  1448. cseq = (struct cseq_body*) h->parsed;
  1449. for(i=0;i<cseq->number.len;i++)
  1450. nr = (nr*10)+(cseq->number.s[i]-'0');
  1451. return nr;
  1452. }
  1453. static str s_called_party_id={"P-Called-Party-ID",17};
  1454. /**
  1455. * Looks for the P-Called-Party-ID header and extracts the public identity from it
  1456. * @param msg - the sip message
  1457. * @param hr - ptr to return the found hdr_field
  1458. * @returns the P-Called_Party-ID
  1459. */
  1460. str cscf_get_public_identity_from_called_party_id(struct sip_msg *msg,struct hdr_field **hr)
  1461. {
  1462. str id={0,0};
  1463. struct hdr_field *h;
  1464. int after_semi_colon=0;
  1465. int len=0;
  1466. int i=0;
  1467. if (hr) *hr=0;
  1468. if (!msg) return id;
  1469. if (parse_headers(msg, HDR_EOH_F, 0)<0) {
  1470. return id;
  1471. }
  1472. h = msg->headers;
  1473. while(h)
  1474. {
  1475. if (h->name.len == s_called_party_id.len &&
  1476. strncasecmp(h->name.s,s_called_party_id.s,s_called_party_id.len)==0)
  1477. {
  1478. id = h->body;
  1479. while(id.len && (id.s[0]==' ' || id.s[0]=='\t' || id.s[0]=='<')){
  1480. id.s = id.s+1;
  1481. id.len --;
  1482. }
  1483. while(id.len && (id.s[id.len-1]==' ' || id.s[id.len-1]=='\t' || id.s[id.len-1]=='>')){
  1484. id.len--;
  1485. }
  1486. //get only text in front of ';' there might not even be a semi-colon
  1487. //this caters for extra information after the public identity - e.g. phone-context
  1488. len= id.len;
  1489. for(i=0; i<len;i++) {
  1490. if(id.s[i]==';'){
  1491. //found semi-colon
  1492. after_semi_colon = 1;
  1493. }
  1494. if(after_semi_colon){
  1495. id.len--;
  1496. }
  1497. }
  1498. if (hr) *hr = h;
  1499. return id;
  1500. }
  1501. h = h->next;
  1502. }
  1503. return id;
  1504. }