usage.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * Kamailio osp module.
  3. *
  4. * This module enables Kamailio 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 Kamailio, a free SIP server.
  15. *
  16. * Kamailio 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. * Kamailio is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  29. *
  30. * History:
  31. * ---------
  32. * 2006-03-13 RR functions are loaded via API function (bogdan)
  33. */
  34. #include <osp/osp.h>
  35. #include "../rr/api.h"
  36. #include "../../usr_avp.h"
  37. #include "usage.h"
  38. #include "destination.h"
  39. #include "osptoolkit.h"
  40. #include "sipheader.h"
  41. #define OSP_ORIG_COOKIE "osp-o"
  42. #define OSP_TERM_COOKIE "osp-t"
  43. #define OSP_RELEASE_ORIG 0
  44. #define OSP_RELEASE_TERM 1
  45. /* The up case tags for the destinations may corrupt OSP cookies */
  46. #define OSP_COOKIE_TRANSID 't'
  47. #define OSP_COOKIE_TRANSIDUP 'T'
  48. #define OSP_COOKIE_SRCIP 's'
  49. #define OSP_COOKIE_SRCIPUP 'S'
  50. #define OSP_COOKIE_AUTHTIME 'a'
  51. #define OSP_COOKIE_AUTHTIMEUP 'A'
  52. #define OSP_COOKIE_DSTCOUNT 'c'
  53. #define OSP_COOKIE_DSTCOUNTUP 'C'
  54. /* Flags for OSP cookies */
  55. #define OSP_COOKIEHAS_TRANSID (1 << 0)
  56. #define OSP_COOKIEHAS_SRCIP (1 << 1)
  57. #define OSP_COOKIEHAS_AUTHTIME (1 << 2)
  58. #define OSP_COOKIEHAS_DSTCOUNT (1 << 3)
  59. #define OSP_COOKIEHAS_ORIGALL (OSP_COOKIEHAS_TRANSID | OSP_COOKIEHAS_SRCIP | OSP_COOKIEHAS_AUTHTIME | OSP_COOKIEHAS_DSTCOUNT)
  60. #define OSP_COOKIEHAS_TERMALL (OSP_COOKIEHAS_TRANSID | OSP_COOKIEHAS_SRCIP | OSP_COOKIEHAS_AUTHTIME)
  61. extern char* _osp_device_ip;
  62. extern OSPTPROVHANDLE _osp_provider;
  63. extern str OSP_ORIGDEST_NAME;
  64. extern struct rr_binds osp_rr;
  65. static void ospRecordTransaction(struct sip_msg* msg, unsigned long long transid, char* uac, char* from, char* to, time_t authtime, int isorig, unsigned destinationCount);
  66. static int ospBuildUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest, int lastcode);
  67. static int ospReportUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest);
  68. static int ospReportUsageFromCookie(struct sip_msg* msg, char* cooky, OSPTCALLID* callid, int release, OSPE_MSG_ROLETYPES type);
  69. /*
  70. * Create OSP cookie and insert it into Record-Route header
  71. * param msg SIP message
  72. * param tansid Transaction ID
  73. * param uac Source IP
  74. * param from
  75. * param to
  76. * param authtime Request authorization time
  77. * param isorig Originate / Terminate
  78. * param destinationCount Destination count
  79. */
  80. static void ospRecordTransaction(
  81. struct sip_msg* msg,
  82. unsigned long long transid,
  83. char* uac,
  84. char* from,
  85. char* to,
  86. time_t authtime,
  87. int isorig,
  88. unsigned destinationCount)
  89. {
  90. str cookie;
  91. char buffer[OSP_STRBUF_SIZE];
  92. if (osp_rr.add_rr_param == 0) {
  93. LM_WARN("add_rr_param function is not found, cannot record information about the OSP transaction\n");
  94. return;
  95. }
  96. cookie.s = buffer;
  97. if (isorig == 1) {
  98. cookie.len = snprintf(
  99. buffer,
  100. sizeof(buffer),
  101. ";%s=%c%llu_%c%s_%c%d_%c%d",
  102. OSP_ORIG_COOKIE,
  103. OSP_COOKIE_TRANSID,
  104. transid,
  105. OSP_COOKIE_SRCIP,
  106. uac,
  107. OSP_COOKIE_AUTHTIME,
  108. (unsigned int)authtime,
  109. OSP_COOKIE_DSTCOUNT,
  110. destinationCount);
  111. } else {
  112. cookie.len = snprintf(
  113. buffer,
  114. sizeof(buffer),
  115. ";%s=%c%llu_%c%s_%c%d",
  116. OSP_TERM_COOKIE,
  117. OSP_COOKIE_TRANSID,
  118. transid,
  119. OSP_COOKIE_SRCIP,
  120. uac,
  121. OSP_COOKIE_AUTHTIME,
  122. (unsigned int)authtime);
  123. }
  124. if (cookie.len < 0) {
  125. LM_ERR("failed to create OSP cookie\n");
  126. return;
  127. }
  128. LM_DBG("adding RR parameter '%s'\n", buffer);
  129. osp_rr.add_rr_param(msg, &cookie);
  130. }
  131. /*
  132. * Create OSP originate cookie and insert it into Record-Route header
  133. * param msg SIP message
  134. * param tansid Transaction ID
  135. * param uac Source IP
  136. * param from
  137. * param to
  138. * param authtime Request authorization time
  139. * param destinationCount Destination count
  140. */
  141. void ospRecordOrigTransaction(
  142. struct sip_msg* msg,
  143. unsigned long long transid,
  144. char* uac,
  145. char* from,
  146. char* to,
  147. time_t authtime,
  148. unsigned destinationCount)
  149. {
  150. int isorig = 1;
  151. ospRecordTransaction(msg, transid, uac, from, to, authtime, isorig, destinationCount);
  152. }
  153. /*
  154. * Create OSP terminate cookie and insert it into Record-Route header
  155. * param msg SIP message
  156. * param tansid Transaction ID
  157. * param uac Source IP
  158. * param from
  159. * param to
  160. * param authtime Request authorization time
  161. */
  162. void ospRecordTermTransaction(
  163. struct sip_msg* msg,
  164. unsigned long long transid,
  165. char* uac,
  166. char* from,
  167. char* to,
  168. time_t authtime)
  169. {
  170. int isorig = 0;
  171. unsigned destinationCount = 0; /* N/A */
  172. ospRecordTransaction(msg, transid, uac, from, to, authtime, isorig, destinationCount);
  173. }
  174. /*
  175. * Report OSP usage from OSP cookie
  176. * param msg SIP message
  177. * param cookie OSP cookie (buffer owned by ospReportUsage, can be modified)
  178. * param callid Call ID
  179. * param release Who releases the call first. 0 orig, 1 term
  180. * param type Usage type
  181. * return
  182. */
  183. static int ospReportUsageFromCookie(
  184. struct sip_msg* msg,
  185. char* cookie,
  186. OSPTCALLID* callid,
  187. int release,
  188. OSPE_MSG_ROLETYPES type)
  189. {
  190. char* tmp;
  191. char* token;
  192. char tag;
  193. char* value;
  194. unsigned long long transid = 0;
  195. time_t authtime = 0;
  196. unsigned destinationCount = 0;
  197. time_t duration = 0;
  198. time_t endtime = time(NULL);
  199. int cookieflags = 0;
  200. unsigned releasecode;
  201. char firstvia[OSP_STRBUF_SIZE];
  202. char from[OSP_STRBUF_SIZE];
  203. char to[OSP_STRBUF_SIZE];
  204. char nexthop[OSP_STRBUF_SIZE];
  205. char* calling;
  206. char* called;
  207. char* originator = NULL;
  208. char* terminator;
  209. char* source;
  210. char srcbuf[OSP_STRBUF_SIZE];
  211. char* destination;
  212. char dstbuf[OSP_STRBUF_SIZE];
  213. char* srcdev;
  214. char devbuf[OSP_STRBUF_SIZE];
  215. OSPTTRANHANDLE transaction = -1;
  216. int errorcode;
  217. LM_DBG("'%s' type '%d'\n", cookie, type);
  218. if (cookie != NULL) {
  219. for (token = strtok_r(cookie, "_", &tmp);
  220. token;
  221. token = strtok_r(NULL, "_", &tmp))
  222. {
  223. tag = *token;
  224. value= token + 1;
  225. switch (tag) {
  226. case OSP_COOKIE_TRANSID:
  227. case OSP_COOKIE_TRANSIDUP:
  228. transid = atoll(value);
  229. cookieflags |= OSP_COOKIEHAS_TRANSID;
  230. break;
  231. case OSP_COOKIE_AUTHTIME:
  232. case OSP_COOKIE_AUTHTIMEUP:
  233. authtime = atoi(value);
  234. duration = endtime - authtime;
  235. cookieflags |= OSP_COOKIEHAS_AUTHTIME;
  236. break;
  237. case OSP_COOKIE_SRCIP:
  238. case OSP_COOKIE_SRCIPUP:
  239. originator = value;
  240. cookieflags |= OSP_COOKIEHAS_SRCIP;
  241. break;
  242. case OSP_COOKIE_DSTCOUNT:
  243. case OSP_COOKIE_DSTCOUNTUP:
  244. destinationCount = (unsigned)atoi(value);
  245. cookieflags |= OSP_COOKIEHAS_DSTCOUNT;
  246. break;
  247. default:
  248. LM_ERR("unexpected tag '%c' / value '%s'\n", tag, value);
  249. break;
  250. }
  251. }
  252. }
  253. switch (type) {
  254. case OSPC_DESTINATION:
  255. if (cookieflags == OSP_COOKIEHAS_TERMALL) {
  256. releasecode = 10016;
  257. } else {
  258. releasecode = 9016;
  259. }
  260. break;
  261. case OSPC_SOURCE:
  262. case OSPC_OTHER:
  263. case OSPC_UNDEFINED_ROLE:
  264. default:
  265. if (cookieflags == OSP_COOKIEHAS_ORIGALL) {
  266. releasecode = 10016;
  267. } else {
  268. releasecode = 9016;
  269. }
  270. break;
  271. }
  272. if (releasecode == 9016) {
  273. transid = 0;
  274. originator = NULL;
  275. authtime = 0;
  276. duration = 0;
  277. destinationCount = 0;
  278. }
  279. ospGetSourceAddress(msg, firstvia, sizeof(firstvia));
  280. ospGetFromUserpart(msg, from, sizeof(from));
  281. ospGetToUserpart(msg, to, sizeof(to));
  282. ospGetNextHop(msg, nexthop, sizeof(nexthop));
  283. LM_DBG("first via '%s' from '%s' to '%s' next hop '%s'\n",
  284. firstvia,
  285. from,
  286. to,
  287. nexthop);
  288. if (release == OSP_RELEASE_ORIG) {
  289. LM_DBG("orig '%s' released the call, call_id '%.*s' transaction_id '%llu'\n",
  290. firstvia,
  291. callid->ospmCallIdLen,
  292. callid->ospmCallIdVal,
  293. transid);
  294. if (originator == NULL) {
  295. originator = firstvia;
  296. }
  297. calling = from;
  298. called = to;
  299. terminator = nexthop;
  300. } else {
  301. release = OSP_RELEASE_TERM;
  302. LM_DBG("term '%s' released the call, call_id '%.*s' transaction_id '%llu'\n",
  303. firstvia,
  304. callid->ospmCallIdLen,
  305. callid->ospmCallIdVal,
  306. transid);
  307. if (originator == NULL) {
  308. originator = nexthop;
  309. }
  310. calling = to;
  311. called = from;
  312. terminator = firstvia;
  313. }
  314. errorcode = OSPPTransactionNew(_osp_provider, &transaction);
  315. LM_DBG("created transaction handle '%d' (%d)\n", transaction, errorcode);
  316. switch (type) {
  317. case OSPC_DESTINATION:
  318. ospConvertAddress(originator, srcbuf, sizeof(srcbuf));
  319. source = srcbuf;
  320. destination = _osp_device_ip;
  321. srcdev = "";
  322. break;
  323. case OSPC_SOURCE:
  324. case OSPC_OTHER:
  325. case OSPC_UNDEFINED_ROLE:
  326. default:
  327. source = _osp_device_ip;
  328. ospConvertAddress(terminator, dstbuf, sizeof(dstbuf));
  329. destination = dstbuf;
  330. ospConvertAddress(originator, devbuf, sizeof(devbuf));
  331. srcdev = devbuf;
  332. break;
  333. }
  334. errorcode = OSPPTransactionBuildUsageFromScratch(
  335. transaction,
  336. transid,
  337. type,
  338. source,
  339. destination,
  340. srcdev,
  341. "",
  342. calling,
  343. OSPC_E164,
  344. called,
  345. OSPC_E164,
  346. callid->ospmCallIdLen,
  347. callid->ospmCallIdVal,
  348. (enum OSPEFAILREASON)0,
  349. NULL,
  350. NULL);
  351. LM_DBG("built usage handle '%d' (%d)\n", transaction, errorcode);
  352. if ((errorcode == OSPC_ERR_NO_ERROR) && (destinationCount > 0)) {
  353. errorcode = OSPPTransactionSetDestinationCount(
  354. transaction,
  355. destinationCount);
  356. }
  357. ospReportUsageWrapper(
  358. transaction,
  359. releasecode,
  360. duration,
  361. authtime,
  362. endtime,
  363. 0,
  364. 0,
  365. 0,
  366. 0,
  367. release);
  368. return errorcode;
  369. }
  370. /*
  371. * Report OSP usage
  372. * param msg SIP message
  373. * param whorelease Who releases the call first, 0 orig, 1 term
  374. * param ignore2
  375. * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
  376. */
  377. int ospReportUsage(
  378. struct sip_msg* msg,
  379. char* whorelease,
  380. char* ignore2)
  381. {
  382. int release;
  383. char* tmp;
  384. char* token;
  385. char parameters[OSP_HEADERBUF_SIZE];
  386. OSPTCALLID* callid = NULL;
  387. int result = MODULE_RETURNCODE_FALSE;
  388. ospGetCallId(msg, &callid);
  389. if (callid != NULL) {
  390. /* Who releases the call first, 0 orig, 1 term */
  391. if (sscanf(whorelease, "%d", &release) != 1 || (release != OSP_RELEASE_ORIG && release != OSP_RELEASE_TERM)) {
  392. release = OSP_RELEASE_ORIG;
  393. }
  394. LM_DBG("who releases the call first '%d'\n", release);
  395. if (ospGetRouteParameters(msg, parameters, sizeof(parameters)) == 0) {
  396. for (token = strtok_r(parameters, ";", &tmp);
  397. token;
  398. token = strtok_r(NULL, ";", &tmp))
  399. {
  400. if (strncmp(token, OSP_ORIG_COOKIE, strlen(OSP_ORIG_COOKIE)) == 0) {
  401. LM_INFO("report orig duration for call_id '%.*s'\n",
  402. callid->ospmCallIdLen,
  403. callid->ospmCallIdVal);
  404. ospReportUsageFromCookie(msg, token + strlen(OSP_ORIG_COOKIE) + 1, callid, release, OSPC_SOURCE);
  405. result = MODULE_RETURNCODE_TRUE;
  406. } else if (strncmp(token, OSP_TERM_COOKIE, strlen(OSP_TERM_COOKIE)) == 0) {
  407. LM_INFO("report term duration for call_id '%.*s'\n",
  408. callid->ospmCallIdLen,
  409. callid->ospmCallIdVal);
  410. ospReportUsageFromCookie(msg, token + strlen(OSP_TERM_COOKIE) + 1, callid, release, OSPC_DESTINATION);
  411. result = MODULE_RETURNCODE_TRUE;
  412. } else {
  413. LM_DBG("ignoring parameter '%s'\n", token);
  414. }
  415. }
  416. }
  417. if (result == MODULE_RETURNCODE_FALSE) {
  418. LM_DBG("without orig or term OSP information\n");
  419. LM_INFO("report other duration for call_id '%.*s'\n",
  420. callid->ospmCallIdLen,
  421. callid->ospmCallIdVal);
  422. ospReportUsageFromCookie(msg, NULL, callid, release, OSPC_SOURCE);
  423. result = MODULE_RETURNCODE_TRUE;
  424. }
  425. OSPPCallIdDelete(&callid);
  426. }
  427. if (result == MODULE_RETURNCODE_FALSE) {
  428. LM_ERR("failed to report usage\n");
  429. }
  430. return result;
  431. }
  432. /*
  433. * Build OSP usage from destination
  434. * param transaction OSP transaction handle
  435. * param dest Destination
  436. * param lastcode Destination status
  437. * return 0 success, others failure
  438. */
  439. static int ospBuildUsageFromDestination(
  440. OSPTTRANHANDLE transaction,
  441. osp_dest* dest,
  442. int lastcode)
  443. {
  444. int errorcode;
  445. char addr[OSP_STRBUF_SIZE];
  446. char* source;
  447. char* srcdev;
  448. if (dest->type == OSPC_SOURCE) {
  449. ospConvertAddress(dest->srcdev, addr, sizeof(addr));
  450. source = dest->source;
  451. srcdev = addr;
  452. } else {
  453. ospConvertAddress(dest->source, addr, sizeof(addr));
  454. source = addr;
  455. srcdev = dest->srcdev;
  456. }
  457. errorcode = OSPPTransactionBuildUsageFromScratch(
  458. transaction,
  459. dest->transid,
  460. dest->type,
  461. source,
  462. dest->host,
  463. srcdev,
  464. dest->destdev,
  465. dest->calling,
  466. OSPC_E164,
  467. dest->origcalled, /* Report original called number */
  468. OSPC_E164,
  469. dest->callidsize,
  470. dest->callid,
  471. (enum OSPEFAILREASON)lastcode,
  472. NULL,
  473. NULL);
  474. return errorcode;
  475. }
  476. /*
  477. * Report OSP usage from destination
  478. * param transaction OSP transaction handle
  479. * param dest Destination
  480. * return 0 success
  481. */
  482. static int ospReportUsageFromDestination(
  483. OSPTTRANHANDLE transaction,
  484. osp_dest* dest)
  485. {
  486. ospReportUsageWrapper(
  487. transaction, /* In - Transaction handle */
  488. dest->lastcode, /* In - Release Code */
  489. 0, /* In - Length of call */
  490. dest->authtime, /* In - Call start time */
  491. 0, /* In - Call end time */
  492. dest->time180, /* In - Call alert time */
  493. dest->time200, /* In - Call connect time */
  494. dest->time180 ? 1 : 0, /* In - Is PDD Info present */
  495. dest->time180 ? dest->time180 - dest->authtime : 0, /* In - Post Dial Delay */
  496. 0);
  497. return 0;
  498. }
  499. /*
  500. * Report originate call setup usage
  501. */
  502. void ospReportOrigSetupUsage(void)
  503. {
  504. osp_dest* dest = NULL;
  505. osp_dest* lastused = NULL;
  506. struct usr_avp* destavp = NULL;
  507. int_str destval;
  508. OSPTTRANHANDLE transaction = -1;
  509. int lastcode = 0;
  510. int errorcode;
  511. struct search_state st;
  512. errorcode = OSPPTransactionNew(_osp_provider, &transaction);
  513. for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st);
  514. destavp != NULL;
  515. destavp = search_next_avp(&st, 0))
  516. {
  517. get_avp_val(destavp, &destval);
  518. /* OSP destination is wrapped in a string */
  519. dest = (osp_dest*)destval.s.s;
  520. if (dest->used == 1) {
  521. if (dest->reported == 1) {
  522. LM_DBG("orig setup already reported\n");
  523. break;
  524. } else {
  525. dest->reported = 1;
  526. }
  527. LM_DBG("iterating through used destination\n");
  528. ospDumpDestination(dest);
  529. lastused = dest;
  530. errorcode = ospBuildUsageFromDestination(transaction, dest, lastcode);
  531. lastcode = dest->lastcode;
  532. } else {
  533. LM_DBG("destination has not been used, breaking out\n");
  534. break;
  535. }
  536. }
  537. if (lastused) {
  538. LM_INFO("report orig setup for call_id '%.*s' transaction_id '%llu'\n",
  539. lastused->callidsize,
  540. lastused->callid,
  541. lastused->transid);
  542. errorcode = ospReportUsageFromDestination(transaction, lastused);
  543. } else {
  544. /* If a Toolkit transaction handle was created, but we did not find
  545. * any destinations to report, we need to release the handle. Otherwise,
  546. * the ospReportUsageFromDestination will release it.
  547. */
  548. OSPPTransactionDelete(transaction);
  549. }
  550. }
  551. /*
  552. * Report terminate call setup usage
  553. */
  554. void ospReportTermSetupUsage(void)
  555. {
  556. osp_dest* dest = NULL;
  557. OSPTTRANHANDLE transaction = -1;
  558. int errorcode;
  559. if ((dest = ospGetTermDestination())) {
  560. if (dest->reported == 0) {
  561. dest->reported = 1;
  562. LM_INFO("report term setup for call_id '%.*s' transaction_id '%llu'\n",
  563. dest->callidsize,
  564. dest->callid,
  565. dest->transid);
  566. errorcode = OSPPTransactionNew(_osp_provider, &transaction);
  567. errorcode = ospBuildUsageFromDestination(transaction, dest, 0);
  568. errorcode = ospReportUsageFromDestination(transaction, dest);
  569. } else {
  570. LM_DBG("term setup already reported\n");
  571. }
  572. } else {
  573. LM_ERR("without term setup to report\n");
  574. }
  575. }