sipheader.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. /*
  2. * ser osp module.
  3. *
  4. * This module enables ser to communicate with an Open Settlement
  5. * Protocol (OSP) server. The Open Settlement Protocol is an ETSI
  6. * defined standard for Inter-Domain VoIP pricing, authorization
  7. * and usage exchange. The technical specifications for OSP
  8. * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
  9. *
  10. * Uli Abend was the original contributor to this module.
  11. *
  12. * Copyright (C) 2001-2005 Fhg Fokus
  13. *
  14. * This file is part of ser, a free SIP server.
  15. *
  16. * ser is free software; you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation; either version 2 of the License, or
  19. * (at your option) any later version
  20. *
  21. * For a license to use the ser software under conditions
  22. * other than those described here, or to purchase support for this
  23. * software, please contact iptel.org by e-mail at the following addresses:
  24. * [email protected]
  25. *
  26. * ser is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. * GNU General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU General Public License
  32. * along with this program; if not, write to the Free Software
  33. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  34. */
  35. #include <osp/osp.h>
  36. #include <osp/ospb64.h>
  37. #include "../../trim.h"
  38. #include "../../forward.h"
  39. #include "../../parser/parse_from.h"
  40. #include "../../parser/parse_rpid.h"
  41. #include "../../parser/parse_rr.h"
  42. #include "../../parser/parse_uri.h"
  43. #include "../../data_lump.h"
  44. #include "../../mem/mem.h"
  45. #include "osp_mod.h"
  46. #include "sipheader.h"
  47. extern int _osp_use_rpid;
  48. static void ospSkipPlus(char* e164);
  49. static int ospAppendHeader(struct sip_msg* msg, str* header);
  50. /*
  51. * Copy str to buffer and check overflow
  52. * param source Str
  53. * param buffer Buffer
  54. * param buffersize Size of buffer
  55. */
  56. void ospCopyStrToBuffer(
  57. str* source,
  58. char* buffer,
  59. int buffersize)
  60. {
  61. int copybytes;
  62. LOG(L_DBG, "osp: ospCopyStrToBuffer\n");
  63. if (source->len > buffersize - 1) {
  64. LOG(L_ERR,
  65. "osp: ERROR: buffer for copying '%.*s' is too small, will copy the first '%d' bytes\n",
  66. source->len,
  67. source->s,
  68. buffersize);
  69. copybytes = buffersize - 1;
  70. } else {
  71. copybytes = source->len;
  72. }
  73. strncpy(buffer, source->s, copybytes);
  74. buffer[copybytes] = '\0';
  75. }
  76. /*
  77. * Remove '+' in E164 string
  78. * param e164 E164 string
  79. */
  80. static void ospSkipPlus(
  81. char* e164)
  82. {
  83. LOG(L_DBG, "osp: ospSkipPlus\n");
  84. if (*e164 == '+') {
  85. strncpy(e164, e164 + 1, strlen(e164) - 1);
  86. e164[strlen(e164) - 1] = '\0';
  87. }
  88. }
  89. /*
  90. * Get calling number from From header
  91. * param msg SIP message
  92. * param fromuser User part of From header
  93. * param buffersize Size of fromuser buffer
  94. * return 0 success, -1 failure
  95. */
  96. int ospGetFromUserpart(
  97. struct sip_msg* msg,
  98. char* fromuser,
  99. int buffersize)
  100. {
  101. struct to_body* from;
  102. struct sip_uri uri;
  103. int result = -1;
  104. LOG(L_DBG, "osp: ospGetFromUserpart\n");
  105. fromuser[0] = '\0';
  106. if (msg->from != NULL) {
  107. if (parse_from_header(msg) == 0) {
  108. from = get_from(msg);
  109. if (parse_uri(from->uri.s, from->uri.len, &uri) == 0) {
  110. ospCopyStrToBuffer(&uri.user, fromuser, buffersize);
  111. ospSkipPlus(fromuser);
  112. result = 0;
  113. } else {
  114. LOG(L_ERR, "osp: ERROR: failed to parse From uri\n");
  115. }
  116. } else {
  117. LOG(L_ERR, "osp: ERROR: failed to parse From header\n");
  118. }
  119. } else {
  120. LOG(L_ERR, "osp: ERROR: failed to find From header\n");
  121. }
  122. return result;
  123. }
  124. /*
  125. * Get calling number from Remote-Party-ID header
  126. * param msg SIP message
  127. * param rpiduser User part of Remote-Party-ID header
  128. * param buffersize Size of fromuser buffer
  129. * return 0 success, -1 failure
  130. */
  131. int ospGetRpidUserpart(
  132. struct sip_msg* msg,
  133. char* rpiduser,
  134. int buffersize)
  135. {
  136. struct to_body* rpid;
  137. struct sip_uri uri;
  138. int result = -1;
  139. LOG(L_DBG, "osp: ospGetRpidUserpart\n");
  140. rpiduser[0] = '\0';
  141. if (_osp_use_rpid != 0) {
  142. if (msg->rpid != NULL) {
  143. if (parse_rpid_header(msg) == 0) {
  144. rpid = get_rpid(msg);
  145. if (parse_uri(rpid->uri.s, rpid->uri.len, &uri) == 0) {
  146. ospCopyStrToBuffer(&uri.user, rpiduser, buffersize);
  147. ospSkipPlus(rpiduser);
  148. result = 0;
  149. } else {
  150. LOG(L_ERR, "osp: ERROR: failed to parse RPID uri\n");
  151. }
  152. } else {
  153. LOG(L_ERR, "osp: ERROR: failed to parse RPID header\n");
  154. }
  155. } else {
  156. LOG(L_DBG, "osp: without RPID header\n");
  157. }
  158. } else {
  159. LOG(L_DBG, "osp: do not use RPID header\n");
  160. }
  161. return result;
  162. }
  163. /*
  164. * Get called number from To header
  165. * param msg SIP message
  166. * param touser User part of To header
  167. * param buffersize Size of touser buffer
  168. * return 0 success, -1 failure
  169. */
  170. int ospGetToUserpart(
  171. struct sip_msg* msg,
  172. char* touser,
  173. int buffersize)
  174. {
  175. struct to_body* to;
  176. struct sip_uri uri;
  177. int result = -1;
  178. LOG(L_DBG, "osp: ospGetToUserpart\n");
  179. touser[0] = '\0';
  180. if (msg->to != NULL) {
  181. if (parse_headers(msg, HDR_TO_F, 0) == 0) {
  182. to = get_to(msg);
  183. if (parse_uri(to->uri.s, to->uri.len, &uri) == 0) {
  184. ospCopyStrToBuffer(&uri.user, touser, buffersize);
  185. ospSkipPlus(touser);
  186. result = 0;
  187. } else {
  188. LOG(L_ERR, "osp: ERROR: failed to parse To uri\n");
  189. }
  190. } else {
  191. LOG(L_ERR, "osp: ERROR: failed to parse To header\n");
  192. }
  193. } else {
  194. LOG(L_ERR, "osp: ERROR: failed to find To header\n");
  195. }
  196. return result;
  197. }
  198. /*
  199. * Get called number from Request-Line header
  200. * param msg SIP message
  201. * param touser User part of To header
  202. * param buffersize Size of touser buffer
  203. * return 0 success, -1 failure
  204. */
  205. int ospGetUriUserpart(
  206. struct sip_msg* msg,
  207. char* uriuser,
  208. int buffersize)
  209. {
  210. int result = -1;
  211. LOG(L_DBG, "osp: ospGetUriUserpart\n");
  212. uriuser[0] = '\0';
  213. if (parse_sip_msg_uri(msg) >= 0) {
  214. ospCopyStrToBuffer(&msg->parsed_uri.user, uriuser, buffersize);
  215. ospSkipPlus(uriuser);
  216. result = 0;
  217. } else {
  218. LOG(L_ERR, "osp: ERROR: failed to parse Request-Line URI\n");
  219. }
  220. return result;
  221. }
  222. /*
  223. * Append header to SIP message
  224. * param msg SIP message
  225. * param header Header to be appended
  226. * return 0 success, -1 failure
  227. */
  228. static int ospAppendHeader(
  229. struct sip_msg* msg,
  230. str* header)
  231. {
  232. char* s;
  233. struct lump* anchor;
  234. LOG(L_DBG, "osp: ospAppendHeader\n");
  235. if((msg == 0) || (header == 0) || (header->s == 0) || (header->len <= 0)) {
  236. LOG(L_ERR, "osp: ERROR: bad parameters for appending header\n");
  237. return -1;
  238. }
  239. if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
  240. LOG(L_ERR, "osp: ERROR: failed to parse message\n");
  241. return -1;
  242. }
  243. anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
  244. if (anchor == 0) {
  245. LOG(L_ERR, "osp: ERROR: failed to get anchor\n");
  246. return -1;
  247. }
  248. s = (char*)pkg_malloc(header->len);
  249. if (s == 0) {
  250. LOG(L_ERR, "osp: ERROR: no memory\n");
  251. return -1;
  252. }
  253. memcpy(s, header->s, header->len);
  254. if (insert_new_lump_before(anchor, s, header->len, 0) == 0) {
  255. LOG(L_ERR, "osp: ERROR: failed to insert lump\n");
  256. pkg_free(s);
  257. return -1;
  258. }
  259. return 0;
  260. }
  261. /*
  262. * Add OSP token header to SIP message
  263. * param msg SIP message
  264. * param token OSP authorization token
  265. * param tokensize Size of OSP authorization token
  266. * return 0 success, -1 failure
  267. */
  268. int ospAddOspHeader(
  269. struct sip_msg* msg,
  270. unsigned char* token,
  271. unsigned int tokensize)
  272. {
  273. str headerval;
  274. char buffer[OSP_HEADERBUF_SIZE];
  275. unsigned char encodedtoken[OSP_TOKENBUF_SIZE];
  276. unsigned int encodedtokensize = sizeof(encodedtoken);
  277. int result = -1;
  278. LOG(L_DBG, "osp: ospAddOspHeader\n");
  279. if (tokensize == 0) {
  280. LOG(L_DBG, "osp: destination is not OSP device\n");
  281. result = 0;
  282. } else {
  283. if (OSPPBase64Encode(token, tokensize, encodedtoken, &encodedtokensize) == 0) {
  284. snprintf(buffer,
  285. sizeof(buffer),
  286. "%s%.*s\r\n",
  287. OSP_TOKEN_HEADER,
  288. encodedtokensize,
  289. encodedtoken);
  290. headerval.s = buffer;
  291. headerval.len = strlen(buffer);
  292. LOG(L_DBG, "osp: setting osp token header field '%s'\n", buffer);
  293. if (ospAppendHeader(msg, &headerval) == 0) {
  294. result = 0;
  295. } else {
  296. LOG(L_ERR, "osp: ERROR: failed to append osp header\n");
  297. }
  298. } else {
  299. LOG(L_ERR, "osp: ERROR: failed to base64 encode token\n");
  300. }
  301. }
  302. return result;
  303. }
  304. /*
  305. * Get OSP token from SIP message
  306. * param msg SIP message
  307. * param token OSP authorization token
  308. * param tokensize Size of OSP authorization token
  309. * return 0 success, -1 failure
  310. */
  311. int ospGetOspHeader(
  312. struct sip_msg* msg,
  313. unsigned char* token,
  314. unsigned int* tokensize)
  315. {
  316. struct hdr_field* hf;
  317. int errorcode;
  318. int result = -1;
  319. LOG(L_DBG, "osp: ospGetOspHeader\n");
  320. if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
  321. LOG(L_ERR, "osp: ERROR: failed to parse headers\n");
  322. return result;
  323. }
  324. for (hf = msg->headers; hf; hf = hf->next) {
  325. if ((hf->type == HDR_OTHER_T) && (hf->name.len == OSP_HEADER_SIZE - 2)) {
  326. // possible hit
  327. if (strncasecmp(hf->name.s, OSP_TOKEN_HEADER, OSP_HEADER_SIZE) == 0) {
  328. if ((errorcode = OSPPBase64Decode(hf->body.s, hf->body.len, token, tokensize)) == 0) {
  329. result = 0;
  330. } else {
  331. LOG(L_ERR, "osp: ERROR: failed to base64 decode token (%d)\n", errorcode);
  332. LOG(L_ERR, "osp: ERROR: header '%.*s' length %d\n", hf->body.len, hf->body.s, hf->body.len);
  333. }
  334. break;
  335. }
  336. }
  337. }
  338. return result;
  339. }
  340. /*
  341. * Get first VIA header and use the IP or host name
  342. * param msg SIP message
  343. * param sourceaddress Source address
  344. * param buffersize Size of sourceaddress
  345. * return 0 success, -1 failure
  346. */
  347. int ospGetSourceAddress(
  348. struct sip_msg* msg,
  349. char* sourceaddress,
  350. int buffersize)
  351. {
  352. struct via_body* via;
  353. int result = -1;
  354. LOG(L_DBG, "osp: ospGetSourceAddress\n");
  355. if (msg->h_via1 || (parse_headers(msg, HDR_VIA_F, 0) == 0 && msg->h_via1)) {
  356. via = msg->h_via1->parsed;
  357. ospCopyStrToBuffer(&via->host, sourceaddress, buffersize);
  358. LOG(L_DBG, "osp: source address '%s'\n", sourceaddress);
  359. result = 0;
  360. }
  361. return result;
  362. }
  363. /*
  364. * Get Call-ID header from SIP message
  365. * param msg SIP message
  366. * param callid Call ID
  367. * return 0 success, -1 failure
  368. */
  369. int ospGetCallId(
  370. struct sip_msg* msg,
  371. OSPTCALLID** callid)
  372. {
  373. struct hdr_field* hf;
  374. int result = -1;
  375. LOG(L_DBG, "osp: ospGetCallId\n");
  376. if (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) == -1) {
  377. LOG(L_ERR, "osp: failed to parse Call-ID\n");
  378. return result;
  379. }
  380. hf = (struct hdr_field*)msg->callid;
  381. if (hf != NULL) {
  382. *callid = OSPPCallIdNew(hf->body.len, (unsigned char*)hf->body.s);
  383. if (*callid) {
  384. result = 0;
  385. } else {
  386. LOG(L_ERR, "osp: ERROR: failed to allocate OSPCALLID object for '%.*s'\n", hf->body.len, hf->body.s);
  387. }
  388. } else {
  389. LOG(L_ERR, "osp: ERROR: failed to find Call-ID header\n");
  390. }
  391. return result;
  392. }
  393. /*
  394. * Get route parameters from the 1st Route or Request-Line
  395. * param msg SIP message
  396. * param routeparameters Route parameters
  397. * param buffersize Size of routeparameters
  398. * return 0 success, -1 failure
  399. */
  400. int ospGetRouteParameters(
  401. struct sip_msg* msg,
  402. char* routeparameters,
  403. int buffersize)
  404. {
  405. struct hdr_field* hf;
  406. rr_t* rt;
  407. struct sip_uri uri;
  408. int result = -1;
  409. LOG(L_DBG, "osp: ospGetRouterParameters\n");
  410. LOG(L_DBG, "osp: parsed uri host '%.*s' port '%d' vars '%.*s'\n",
  411. msg->parsed_uri.host.len,
  412. msg->parsed_uri.host.s,
  413. msg->parsed_uri.port_no,
  414. msg->parsed_uri.params.len,
  415. msg->parsed_uri.params.s);
  416. if (!(hf = msg->route)) {
  417. LOG(L_DBG, "osp: there is no Route headers\n");
  418. } else if (!(rt = (rr_t*)hf->parsed)) {
  419. LOG(L_ERR, "osp: ERROR: route headers are not parsed\n");
  420. } else if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &uri) != 0) {
  421. LOG(L_ERR, "osp: ERROR: failed to parse the Route uri '%.*s'\n", rt->nameaddr.uri.len, rt->nameaddr.uri.s);
  422. } else if (check_self(&uri.host, uri.port_no ? uri.port_no : SIP_PORT, PROTO_NONE) != 1) {
  423. LOG(L_DBG, "osp: the Route uri is NOT mine\n");
  424. LOG(L_DBG, "osp: host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
  425. LOG(L_DBG, "osp: params '%.*s'\n", uri.params.len, uri.params.s);
  426. } else {
  427. LOG(L_DBG, "osp: the Route uri IS mine - '%.*s'\n", uri.params.len, uri.params.s);
  428. LOG(L_DBG, "osp: host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
  429. ospCopyStrToBuffer(&uri.params, routeparameters, buffersize);
  430. result = 0;
  431. }
  432. if ((result == -1) && (msg->parsed_uri.params.len > 0)) {
  433. LOG(L_DBG, "osp: using route parameters from Request-Line uri\n");
  434. ospCopyStrToBuffer(&msg->parsed_uri.params, routeparameters, buffersize);
  435. routeparameters[msg->parsed_uri.params.len] = '\0';
  436. result = 0;
  437. }
  438. return result;
  439. }
  440. /*
  441. * Rebuild URI using called number, destination IP, and port
  442. * param newuri URI to be built
  443. * param called Called number
  444. * param dest Destination IP
  445. * param port Destination port
  446. * param format URI format
  447. * return 0 success, -1 failure
  448. */
  449. int ospRebuildDestionationUri(
  450. str* newuri,
  451. char* called,
  452. char* dest,
  453. char* port,
  454. int format)
  455. {
  456. static const str TRANS = {";transport=tcp", 14};
  457. char* buffer;
  458. int calledsize;
  459. int destsize;
  460. int portsize;
  461. LOG(L_DBG, "osp: ospRebuildDestinationUri\n");
  462. calledsize = strlen(called);
  463. destsize = strlen(dest);
  464. portsize = strlen(port);
  465. LOG(L_DBG, "osp: '%s'(%i) '%s'(%i) '%s'(%i) '%d'\n",
  466. called,
  467. calledsize,
  468. dest,
  469. destsize,
  470. port,
  471. portsize,
  472. format);
  473. /* "sip:" + called + "@" + dest + : + port + " SIP/2.0" for URI format 0 */
  474. /* "<sip:" + called + "@" + dest + : + port> + " SIP/2.0" for URI format 1 */
  475. newuri->s = (char*)pkg_malloc(1 + 4 + calledsize + 1 + destsize + 1 + portsize + 1 + 1 + 16 + TRANS.len);
  476. if (newuri == NULL) {
  477. LOG(L_ERR, "osp: ERROR: no memory\n");
  478. return -1;
  479. }
  480. buffer = newuri->s;
  481. if (format == 1) {
  482. *buffer++ = '<';
  483. }
  484. *buffer++ = 's';
  485. *buffer++ = 'i';
  486. *buffer++ = 'p';
  487. *buffer++ = ':';
  488. memcpy(buffer, called, calledsize);
  489. buffer += calledsize;
  490. *buffer++ = '@';
  491. if (*dest == '[') {
  492. /* leave out annoying [] */
  493. memcpy(buffer, dest + 1, destsize - 2);
  494. buffer += destsize - 2;
  495. } else {
  496. memcpy(buffer, dest, destsize);
  497. buffer += destsize;
  498. }
  499. if (portsize > 0) {
  500. *buffer++ = ':';
  501. memcpy(buffer, port, portsize);
  502. buffer += portsize;
  503. }
  504. if (format == 1) {
  505. *buffer++ = '>';
  506. }
  507. /*
  508. *buffer++ = ' ';
  509. *buffer++ = 'S';
  510. *buffer++ = 'I';
  511. *buffer++ = 'P';
  512. *buffer++ = '/';
  513. *buffer++ = '2';
  514. *buffer++ = '.';
  515. *buffer++ = '0';
  516. memcpy(buffer, TRANS.s, TRANS.len);
  517. buffer += TRANS.len;
  518. *buffer = '\0';
  519. */
  520. newuri->len = buffer - newuri->s;
  521. LOG(L_DBG, "osp: new uri '%.*s'\n", newuri->len, newuri->s);
  522. return 0;
  523. }
  524. /*
  525. * Get next hop using the first Route not generated by this proxy or URI from the Request-Line
  526. * param msg SIP message
  527. * param nexthop Next hop IP
  528. * param buffersize Size of nexthop
  529. */
  530. void ospGetNextHop(
  531. struct sip_msg* msg,
  532. char* nexthop,
  533. int buffersize)
  534. {
  535. struct hdr_field* hf;
  536. struct sip_uri uri;
  537. rr_t* rt;
  538. int found = 0;
  539. LOG(L_DBG, "osp: ospGetNextHop\n");
  540. for (hf = msg->headers; hf; hf = hf->next) {
  541. if (hf->type == HDR_ROUTE_T) {
  542. for (rt = (rr_t*)hf->parsed; rt; rt = rt->next) {
  543. if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &uri) == 0) {
  544. LOG(L_DBG, "osp: host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
  545. if (check_self(&uri.host, uri.port_no ? uri.port_no : SIP_PORT, PROTO_NONE) != 1) {
  546. LOG(L_DBG, "osp: it is NOT me, FOUND!\n");
  547. ospCopyStrToBuffer(&uri.host, nexthop, buffersize);
  548. found = 1;
  549. break;
  550. } else {
  551. LOG(L_DBG, "osp: it IS me, keep looking\n");
  552. }
  553. } else {
  554. LOG(L_ERR,
  555. "osp: ERROR: failed to parsed route uri '%.*s'\n",
  556. rt->nameaddr.uri.len,
  557. rt->nameaddr.uri.s);
  558. }
  559. }
  560. if (found == 1) {
  561. break;
  562. }
  563. }
  564. }
  565. if (!found) {
  566. LOG(L_DBG, "osp: using the Request-Line instead host '%.*s' port '%d'\n",
  567. msg->parsed_uri.host.len,
  568. msg->parsed_uri.host.s,
  569. msg->parsed_uri.port_no);
  570. ospCopyStrToBuffer(&msg->parsed_uri.host, nexthop, buffersize);
  571. found = 1;
  572. }
  573. }
  574. /*
  575. * Get direction using the first Route not generated by this proxy or URI from the Request-Line
  576. * SER does not have is_direction as Kamailio. We have to write it.
  577. * The problem is we cannot check append_fromtag option before running. So, ftag may not exist.
  578. * param msg SIP message
  579. * return 0 originating, 1 terminating, -1 failed
  580. */
  581. int ospGetDirection(struct sip_msg* msg)
  582. {
  583. static const str FTAG = {"ftag", 4};
  584. char parameters[OSP_HEADERBUF_SIZE];
  585. char* tmp;
  586. char* token;
  587. str ftag;
  588. struct to_body* from;
  589. int result = -1;
  590. LOG(L_DBG, "osp: ospGetDirection\n");
  591. if (ospGetRouteParameters(msg, parameters, sizeof(parameters)) == 0) {
  592. for (token = strtok_r(parameters, ";", &tmp);
  593. token;
  594. token = strtok_r(NULL, ";", &tmp))
  595. {
  596. ftag.s = token;
  597. ftag.len = strlen(token);
  598. /* Remove leading white space char */
  599. trim_leading(&ftag);
  600. if (strncmp(ftag.s, FTAG.s, FTAG.len) == 0) {
  601. /* Remove "ftag" string */
  602. ftag.s += FTAG.len;
  603. ftag.len -= FTAG.len;
  604. /* Remove leading white space char */
  605. trim_leading(&ftag);
  606. /* Remove '=' char */
  607. ftag.s++;
  608. ftag.len--;
  609. /* Remove leading and tailing white space char */
  610. trim(&ftag);
  611. LOG(L_DBG, "osp: ftag '%s'\n", ftag.s);
  612. if ((parse_from_header(msg) == 0) && ((from = get_from(msg)) != 0)) {
  613. if ((ftag.len == from->tag_value.len) && !strncmp(ftag.s, from->tag_value.s, ftag.len)) {
  614. LOG(L_DBG, "osp: originating\n");
  615. result = 0;
  616. } else {
  617. LOG(L_DBG, "osp: terminating\n");
  618. result = 1;
  619. }
  620. }
  621. break;
  622. } else {
  623. LOG(L_DBG, "osp: ignoring parameter '%s'\n", token);
  624. }
  625. }
  626. }
  627. return result;
  628. }