destination.c 13 KB

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