destination.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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. #include <string.h>
  31. #include <stdio.h>
  32. #include <sys/socket.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35. #include "../../str.h"
  36. #include "../../dprint.h"
  37. #include "../../usr_avp.h"
  38. #include "destination.h"
  39. #include "usage.h"
  40. /* Name of AVP of OSP destination list */
  41. const str OSP_ORIGDEST_NAME = {"_osp_orig_dests_", 16};
  42. const str OSP_TERMDEST_NAME = {"_osp_term_dests_", 16};
  43. static int ospSaveDestination(osp_dest* dest, const str* name);
  44. static void ospRecordCode(int code, osp_dest* dest);
  45. static int ospIsToReportUsage(int code);
  46. /*
  47. * Initialize destination structure
  48. * param dest Destination data structure
  49. * return initialized destination sturcture
  50. */
  51. osp_dest* ospInitDestination(
  52. osp_dest* dest)
  53. {
  54. memset(dest, 0, sizeof(osp_dest));
  55. dest->callidsize = sizeof(dest->callid);
  56. dest->tokensize = sizeof(dest->token);
  57. LM_DBG("callidsize '%d' tokensize '%d'\n", dest->callidsize, dest->tokensize);
  58. return dest;
  59. }
  60. /*
  61. * Save destination as an AVP
  62. * name - OSP_ORIGDEST_NAME / OSP_TERMDEST_NAME
  63. * value - osp_dest wrapped in a string
  64. * param dest Destination structure
  65. * param name Name of AVP
  66. * return 0 success, -1 failure
  67. */
  68. static int ospSaveDestination(
  69. osp_dest* dest,
  70. const str* name)
  71. {
  72. str wrapper;
  73. int result = -1;
  74. wrapper.s = (char*)dest;
  75. wrapper.len = sizeof(osp_dest);
  76. /*
  77. * add_avp will make a private copy of both the name and value in shared memory
  78. * which will be released by TM at the end of the transaction
  79. */
  80. if (add_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)*name, (int_str)wrapper) == 0) {
  81. LM_DBG("destination saved\n");
  82. result = 0;
  83. } else {
  84. LM_ERR("failed to save destination\n");
  85. }
  86. return result;
  87. }
  88. /*
  89. * Save originate destination
  90. * param dest Originate destination structure
  91. * return 0 success, -1 failure
  92. */
  93. int ospSaveOrigDestination(
  94. osp_dest* dest)
  95. {
  96. return ospSaveDestination(dest, &OSP_ORIGDEST_NAME);
  97. }
  98. /*
  99. * Save terminate destination
  100. * param dest Terminate destination structure
  101. * return 0 success, -1 failure
  102. */
  103. int ospSaveTermDestination(
  104. osp_dest* dest)
  105. {
  106. return ospSaveDestination(dest, &OSP_TERMDEST_NAME);
  107. }
  108. /*
  109. * Check if there is an unused and supported originate destination from an AVP
  110. * name - OSP_ORIGDEST_NAME
  111. * value - osp_dest wrapped in a string
  112. * search unused (used==0) & supported (support==1)
  113. * return 0 success, -1 failure
  114. */
  115. int ospCheckOrigDestination(void)
  116. {
  117. struct usr_avp* destavp = NULL;
  118. int_str destval;
  119. osp_dest* dest = NULL;
  120. int result = -1;
  121. struct search_state st;
  122. for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st);
  123. destavp != NULL;
  124. destavp = search_next_avp(&st, NULL))
  125. {
  126. get_avp_val(destavp, &destval);
  127. /* OSP destintaion is wrapped in a string */
  128. dest = (osp_dest*)destval.s.s;
  129. if (dest->used == 0) {
  130. if (dest->supported == 1) {
  131. LM_DBG("orig dest exist\n");
  132. result = 0;
  133. break;
  134. } else {
  135. LM_DBG("destination does not been supported\n");
  136. }
  137. } else {
  138. LM_DBG("destination has already been used\n");
  139. }
  140. }
  141. if (result == -1) {
  142. LM_DBG("there is not unused destination\n");
  143. }
  144. return result;
  145. }
  146. /*
  147. * Retrieved an unused and supported originate destination from an AVP
  148. * name - OSP_ORIGDEST_NAME
  149. * value - osp_dest wrapped in a string
  150. * There can be 0, 1 or more originate destinations.
  151. * Find the 1st unused destination (used==0) & supported (support==1),
  152. * return it, and mark it as used (used==1).
  153. * return NULL on failure
  154. */
  155. osp_dest* ospGetNextOrigDestination(void)
  156. {
  157. struct usr_avp* destavp = NULL;
  158. int_str destval;
  159. osp_dest* dest = NULL;
  160. osp_dest* result = NULL;
  161. struct search_state st;
  162. for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st);
  163. destavp != NULL;
  164. destavp = search_next_avp(&st, NULL))
  165. {
  166. get_avp_val(destavp, &destval);
  167. /* OSP destintaion is wrapped in a string */
  168. dest = (osp_dest*)destval.s.s;
  169. if (dest->used == 0) {
  170. if (dest->supported == 1) {
  171. LM_DBG("orig dest found\n");
  172. dest->used = 1;
  173. result = dest;
  174. break;
  175. } else {
  176. /* Make it looks like used */
  177. dest->used = 1;
  178. /* 111 means wrong protocol */
  179. dest->lastcode = 111;
  180. LM_DBG("destination does not been supported\n");
  181. }
  182. } else {
  183. LM_DBG("destination has already been used\n");
  184. }
  185. }
  186. if (result == NULL) {
  187. LM_DBG("there is not unused destination\n");
  188. }
  189. return result;
  190. }
  191. /*
  192. * Retrieved the last used originate destination from an AVP
  193. * name - OSP_ORIGDEST_NAME
  194. * value - osp_dest wrapped in a string
  195. * There can be 0, 1 or more destinations.
  196. * Find the last used destination (used==1) & supported (support==1),
  197. * and return it.
  198. * In normal condition, this one is the current destination. But it may
  199. * be wrong for loop condition.
  200. * return NULL on failure
  201. */
  202. osp_dest* ospGetLastOrigDestination(void)
  203. {
  204. struct usr_avp* destavp = NULL;
  205. int_str destval;
  206. osp_dest* dest = NULL;
  207. osp_dest* lastdest = NULL;
  208. struct search_state st;
  209. for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st);
  210. destavp != NULL;
  211. destavp = search_next_avp(&st, NULL))
  212. {
  213. get_avp_val(destavp, &destval);
  214. /* OSP destination is wrapped in a string */
  215. dest = (osp_dest*)destval.s.s;
  216. if (dest->used == 1) {
  217. if (dest->supported == 1) {
  218. lastdest = dest;
  219. LM_DBG("curent destination '%s'\n", lastdest->host);
  220. }
  221. } else {
  222. break;
  223. }
  224. }
  225. return lastdest;
  226. }
  227. /*
  228. * Retrieved the terminate destination from an AVP
  229. * name - OSP_TERMDEST_NAME
  230. * value - osp_dest wrapped in a string
  231. * There can be 0 or 1 term destinations. Find and return it.
  232. * return NULL on failure (no terminate destination)
  233. */
  234. osp_dest* ospGetTermDestination(void)
  235. {
  236. int_str destval;
  237. osp_dest* dest = NULL;
  238. if (search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_TERMDEST_NAME, &destval, 0) != NULL) {
  239. /* OSP destination is wrapped in a string */
  240. dest = (osp_dest*)destval.s.s;
  241. LM_DBG("term dest found\n");
  242. }
  243. return dest;
  244. }
  245. /*
  246. * Record destination status
  247. * param code Destination status
  248. * param dest Destination
  249. */
  250. static void ospRecordCode(
  251. int code,
  252. osp_dest* dest)
  253. {
  254. LM_DBG("code '%d'\n", code);
  255. dest->lastcode = code;
  256. switch (code) {
  257. case 100:
  258. if (!dest->time100) {
  259. dest->time100 = time(NULL);
  260. } else {
  261. LM_DBG("100 already recorded\n");
  262. }
  263. break;
  264. case 180:
  265. case 181:
  266. case 182:
  267. case 183:
  268. if (!dest->time180) {
  269. dest->time180 = time(NULL);
  270. } else {
  271. LM_DBG("180, 181, 182 or 183 allready recorded\n");
  272. }
  273. break;
  274. case 200:
  275. case 202:
  276. if (!dest->time200) {
  277. dest->time200 = time(NULL);
  278. } else {
  279. LM_DBG("200 or 202 allready recorded\n");
  280. }
  281. break;
  282. default:
  283. LM_DBG("will not record time for '%d'\n", code);
  284. }
  285. }
  286. /*
  287. * Check destination status for reporting usage
  288. * param code Destination status
  289. * return 1 should report, 0 should not report
  290. */
  291. static int ospIsToReportUsage(
  292. int code)
  293. {
  294. int istime = 0;
  295. LM_DBG("code '%d'\n", code);
  296. if (code >= 200) {
  297. istime = 1;
  298. }
  299. return istime;
  300. }
  301. /*
  302. * Report call setup usage for both client and server side
  303. * param clientcode Client status
  304. * param servercode Server status
  305. */
  306. void ospRecordEvent(
  307. int clientcode,
  308. int servercode)
  309. {
  310. osp_dest* dest;
  311. LM_DBG("client status '%d'\n", clientcode);
  312. if ((clientcode != 0) && (dest = ospGetLastOrigDestination())) {
  313. ospRecordCode(clientcode, dest);
  314. if (ospIsToReportUsage(servercode) == 1) {
  315. ospReportOrigSetupUsage();
  316. }
  317. }
  318. LM_DBG("server status '%d'\n", servercode);
  319. if ((servercode != 0) && (dest = ospGetTermDestination())) {
  320. ospRecordCode(servercode, dest);
  321. if (ospIsToReportUsage(servercode) == 1) {
  322. ospReportTermSetupUsage();
  323. }
  324. }
  325. }
  326. /*
  327. * Dump destination information
  328. * param dest Destination
  329. */
  330. void ospDumpDestination(
  331. osp_dest* dest)
  332. {
  333. LM_DBG("dest->host..........'%s'\n", dest->host);
  334. LM_DBG("dest->used..........'%d'\n", dest->used);
  335. LM_DBG("dest->lastcode......'%d'\n", dest->lastcode);
  336. LM_DBG("dest->time100.......'%d'\n", (unsigned int)dest->time100);
  337. LM_DBG("dest->time180.......'%d'\n", (unsigned int)dest->time180);
  338. LM_DBG("dest->time200.......'%d'\n", (unsigned int)dest->time200);
  339. }
  340. /*
  341. * Dump all destination information
  342. */
  343. void ospDumpAllDestination(void)
  344. {
  345. struct usr_avp* destavp = NULL;
  346. int_str destval;
  347. osp_dest* dest = NULL;
  348. int count = 0;
  349. struct search_state st;
  350. for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st);
  351. destavp != NULL;
  352. destavp = search_next_avp(&st, NULL))
  353. {
  354. get_avp_val(destavp, &destval);
  355. /* OSP destination is wrapped in a string */
  356. dest = (osp_dest*)destval.s.s;
  357. LM_DBG("....originate '%d'....\n", count++);
  358. ospDumpDestination(dest);
  359. }
  360. if (count == 0) {
  361. LM_DBG("there is not originate destination AVP\n");
  362. }
  363. if (search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_TERMDEST_NAME, &destval, 0) != NULL) {
  364. /* OSP destination is wrapped in a string */
  365. dest = (osp_dest*)destval.s.s;
  366. LM_DBG("....terminate....\n");
  367. ospDumpDestination(dest);
  368. } else {
  369. LM_DBG("there is not terminate destination AVP\n");
  370. }
  371. }
  372. /*
  373. * Convert address to "[x.x.x.x]" or "host.domain" format
  374. * param src Source address
  375. * param dst Destination address
  376. * param buffersize Size of dst buffer
  377. */
  378. void ospConvertAddress(
  379. char* src,
  380. char* dst,
  381. int buffersize)
  382. {
  383. struct in_addr inp;
  384. if (inet_aton(src, &inp) != 0) {
  385. snprintf(dst, buffersize, "[%s]", src);
  386. } else {
  387. snprintf(dst, buffersize, "%s", src);
  388. }
  389. }