routing.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2005-2009 Voice Sistem SRL
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. *
  22. * History:
  23. * ---------
  24. * 2005-02-20 first version (cristian)
  25. * 2005-02-27 ported to 0.9.0 (bogdan)
  26. */
  27. #include <stdlib.h>
  28. #include <errno.h>
  29. #include <limits.h>
  30. #include "../../str.h"
  31. #include "../../resolve.h"
  32. #include "../../mem/shm_mem.h"
  33. #include "../../parser/parse_uri.h"
  34. #include "routing.h"
  35. #include "prefix_tree.h"
  36. #include "dr_time.h"
  37. #include "parse.h"
  38. #define IDX_SIZE 32
  39. extern int dr_force_dns;
  40. rt_data_t*
  41. build_rt_data( void )
  42. {
  43. rt_data_t *rdata;
  44. if( NULL==(rdata=shm_malloc(sizeof(rt_data_t)))) {
  45. LM_ERR("no more shm mem\n");
  46. goto err_exit;
  47. }
  48. memset(rdata, 0, sizeof(rt_data_t));
  49. INIT_PTREE_NODE(NULL, rdata->pt);
  50. return rdata;
  51. err_exit:
  52. return 0;
  53. }
  54. rt_info_t*
  55. build_rt_info(
  56. int priority,
  57. tmrec_t *trec,
  58. /* script routing table index */
  59. int route_idx,
  60. /* list of destinations indexes */
  61. char* dstlst,
  62. pgw_t* pgw_l
  63. )
  64. {
  65. char *tmp=NULL;
  66. char *ep=NULL;
  67. rt_info_t* rt = NULL;
  68. int *idx = NULL, *t_idx=NULL;
  69. int n=0, idx_size=0,i, grp_idx=0;
  70. long t=0;
  71. pgw_t *pgw=NULL;
  72. if(NULL == (rt = (rt_info_t*)shm_malloc(sizeof(rt_info_t)))) {
  73. LM_ERR("no more shm mem(1)\n");
  74. goto err_exit;
  75. }
  76. memset(rt, 0, sizeof(rt_info_t));
  77. idx_size = IDX_SIZE;
  78. if( NULL == (idx = (int*)shm_malloc(2*idx_size*sizeof(int)))) {
  79. LM_ERR("no more shm mem(2)\n");
  80. goto err_exit;
  81. }
  82. memset(idx, 0, 2*idx_size*sizeof(int));
  83. rt->priority = priority;
  84. rt->time_rec = trec;
  85. rt->route_idx = route_idx;
  86. tmp=dstlst;
  87. n=0;
  88. /* parse the dstlst */
  89. while(tmp && (*tmp!=0)) {
  90. errno = 0;
  91. t = strtol(tmp, &ep, 10);
  92. if (ep == tmp) {
  93. LM_ERR("bad id '%c' (%d)[%s]\n",
  94. *ep, (int)(ep-dstlst), dstlst);
  95. goto err_exit;
  96. }
  97. if ((!IS_SPACE(*ep)) && (*ep != SEP) && (*ep != SEP1)
  98. && (*ep != SEP_GRP) && (*ep!=0)) {
  99. LM_ERR("bad char %c (%d) [%s]\n",
  100. *ep, (int)(ep-dstlst), dstlst);
  101. goto err_exit;
  102. }
  103. if (errno == ERANGE && (t== LONG_MAX || t== LONG_MIN)) {
  104. LM_ERR("out of bounds\n");
  105. goto err_exit;
  106. }
  107. idx[2*n]=t;
  108. idx[2*n+1]=grp_idx;
  109. if(*ep == SEP_GRP)
  110. grp_idx++;
  111. n++;
  112. /* reallocate the array which keeps the parsed indexes */
  113. if(n>=idx_size){
  114. if(NULL==((t_idx)=(int*)shm_malloc((idx_size*2*2)*sizeof(int)))) {
  115. LM_ERR("out of shm\n");
  116. goto err_exit;
  117. }
  118. memset(t_idx+(2*idx_size), 0, 2*idx_size*sizeof(int));
  119. memcpy(t_idx, idx, 2*idx_size*sizeof(int));
  120. shm_free(idx);
  121. idx_size*=2;
  122. idx=t_idx;
  123. }
  124. if(IS_SPACE(*ep))
  125. EAT_SPACE(ep);
  126. if(ep && (*ep == SEP || *ep == SEP1 || *ep == SEP_GRP))
  127. ep++;
  128. tmp = ep;
  129. }
  130. if(n==0) {
  131. LM_ERR("invalid n\n");
  132. goto err_exit;
  133. }
  134. /* create the pgwl */
  135. rt->pgwa_len = n;
  136. if(NULL ==
  137. (rt->pgwl=(pgw_list_t*)shm_malloc(rt->pgwa_len*sizeof(pgw_list_t)))) {
  138. goto err_exit;
  139. }
  140. memset(rt->pgwl, 0, rt->pgwa_len*sizeof(pgw_list_t));
  141. /* translate GW ids to GW pointers */
  142. for(i=0;i<n; i++){
  143. if ( NULL == (pgw = get_pgw(pgw_l, idx[2*i]))) {
  144. LM_ERR("invalid GW id %d\n",
  145. idx[2*i]);
  146. goto err_exit;
  147. }
  148. rt->pgwl[i].pgw=pgw;
  149. rt->pgwl[i].grpid=idx[2*i+1];
  150. /* LM_DBG("added to gwlist [%d/%d/%p]\n",
  151. idx[2*i], idx[2*i+1], pgw); */
  152. }
  153. shm_free(idx);
  154. return rt;
  155. err_exit:
  156. if(NULL!=idx)
  157. shm_free(idx);
  158. if((NULL != rt) &&
  159. (NULL!=rt->pgwl))
  160. shm_free(rt->pgwl);
  161. if(NULL!=rt)
  162. shm_free(rt);
  163. return NULL;
  164. }
  165. int
  166. add_rt_info(
  167. ptree_node_t *pn,
  168. rt_info_t* r,
  169. unsigned int rgid
  170. )
  171. {
  172. rg_entry_t *trg=NULL;
  173. rt_info_wrp_t *rtl_wrp=NULL;
  174. rt_info_wrp_t *rtlw=NULL;
  175. int i=0;
  176. if((NULL == pn) || (NULL == r))
  177. goto err_exit;
  178. if (NULL == (rtl_wrp = (rt_info_wrp_t*)shm_malloc(sizeof(rt_info_wrp_t)))) {
  179. LM_ERR("no more shm mem\n");
  180. goto err_exit;
  181. }
  182. memset( rtl_wrp, 0, sizeof(rt_info_wrp_t));
  183. rtl_wrp->rtl = r;
  184. if(NULL==pn->rg) {
  185. /* allocate the routing groups array */
  186. pn->rg_len = RG_INIT_LEN;
  187. if(NULL == (pn->rg = (rg_entry_t*)shm_malloc(
  188. pn->rg_len*sizeof(rg_entry_t)))) {
  189. /* recover the old pointer to be able to shm_free mem */
  190. goto err_exit;
  191. }
  192. memset( pn->rg, 0, pn->rg_len*sizeof(rg_entry_t));
  193. pn->rg_pos=0;
  194. }
  195. /* search for the rgid up to the rg_pos */
  196. for(i=0; (i<pn->rg_pos) && (pn->rg[i].rgid!=rgid); i++);
  197. if((i==pn->rg_len-1)&&(pn->rg[i].rgid!=rgid)) {
  198. /* realloc & copy the old rg */
  199. trg = pn->rg;
  200. if(NULL == (pn->rg = (rg_entry_t*)shm_malloc(
  201. 2*pn->rg_len*sizeof(rg_entry_t)))) {
  202. /* recover the old pointer to be able to shm_free mem */
  203. pn->rg = trg;
  204. goto err_exit;
  205. }
  206. memset(pn->rg+pn->rg_len, 0, pn->rg_len*sizeof(rg_entry_t));
  207. memcpy(pn->rg, trg, pn->rg_len*sizeof(rg_entry_t));
  208. pn->rg_len*=2;
  209. shm_free( trg );
  210. }
  211. /* insert into list */
  212. r->ref_cnt++;
  213. if(NULL==pn->rg[i].rtlw){
  214. pn->rg[i].rtlw = rtl_wrp;
  215. pn->rg[i].rgid = rgid;
  216. pn->rg_pos++;
  217. goto ok_exit;
  218. }
  219. if( r->priority > pn->rg[i].rtlw->rtl->priority) {
  220. /* change the head of the list */
  221. rtl_wrp->next = pn->rg[i].rtlw;
  222. pn->rg[i].rtlw = rtl_wrp;
  223. goto ok_exit;
  224. }
  225. rtlw = pn->rg[i].rtlw;
  226. while( rtlw->next !=NULL) {
  227. if(r->priority > rtlw->next->rtl->priority) {
  228. rtl_wrp->next = rtlw->next;
  229. rtlw->next = rtl_wrp;
  230. goto ok_exit;
  231. }
  232. rtlw = rtlw->next;
  233. }
  234. /* the smallest priority is linked at the end */
  235. rtl_wrp->next=NULL;
  236. rtlw->next=rtl_wrp;
  237. ok_exit:
  238. return 0;
  239. err_exit:
  240. if (rtl_wrp) shm_free(rtl_wrp);
  241. return -1;
  242. }
  243. int
  244. add_dst(
  245. rt_data_t *r,
  246. /* id */
  247. int id,
  248. /* ip address */
  249. char* ip,
  250. /* strip len */
  251. int strip,
  252. /* pri prefix */
  253. char* pri,
  254. /* dst type*/
  255. int type,
  256. /* dst attrs*/
  257. char* attrs
  258. )
  259. {
  260. pgw_t *pgw=NULL, *tmp=NULL;
  261. pgw_addr_t *tmpa=NULL;
  262. struct hostent* he;
  263. struct sip_uri uri;
  264. struct ip_addr ipa;
  265. int l_ip,l_pri,l_attrs;
  266. #define GWABUF_MAX_SIZE 512
  267. char gwabuf[GWABUF_MAX_SIZE];
  268. str gwas;
  269. if (NULL==r || NULL==ip) {
  270. LM_ERR("invalid parametres\n");
  271. goto err_exit;
  272. }
  273. l_ip = strlen(ip);
  274. l_pri = pri?strlen(pri):0;
  275. l_attrs = attrs?strlen(attrs):0;
  276. pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_ip + l_pri + l_attrs);
  277. if (NULL==pgw) {
  278. LM_ERR("no more shm mem (%u)\n",
  279. (unsigned int)(sizeof(pgw_t)+l_ip+l_pri +l_attrs));
  280. goto err_exit;
  281. }
  282. memset(pgw,0,sizeof(pgw_t));
  283. pgw->ip.len= l_ip;
  284. pgw->ip.s = (char*)(pgw+1);
  285. memcpy(pgw->ip.s, ip, l_ip);
  286. if (pri) {
  287. pgw->pri.len = l_pri;
  288. pgw->pri.s = ((char*)(pgw+1))+l_ip;
  289. memcpy(pgw->pri.s, pri, l_pri);
  290. }
  291. if (attrs) {
  292. pgw->attrs.len = l_attrs;
  293. pgw->attrs.s = ((char*)(pgw+1))+l_ip+l_pri;
  294. memcpy(pgw->attrs.s, attrs, l_attrs);
  295. }
  296. pgw->id = id;
  297. pgw->strip = strip;
  298. pgw->type = type;
  299. /* add address in the list */
  300. if(pgw->ip.len<5 || (strncasecmp("sip:", ip, 4)
  301. &&strncasecmp("sips:", ip, 5)))
  302. {
  303. if(pgw->ip.len+4>=GWABUF_MAX_SIZE) {
  304. LM_ERR("GW address (%d) longer "
  305. "than %d\n",pgw->ip.len+4,GWABUF_MAX_SIZE);
  306. goto err_exit;
  307. }
  308. memcpy(gwabuf, "sip:", 4);
  309. memcpy(gwabuf+4, ip, pgw->ip.len);
  310. gwas.s = gwabuf;
  311. gwas.len = 4+pgw->ip.len;
  312. } else {
  313. gwas.s = ip;
  314. gwas.len = pgw->ip.len;
  315. }
  316. memset(&uri, 0, sizeof(struct sip_uri));
  317. if(parse_uri(gwas.s, gwas.len, &uri)!=0) {
  318. LM_ERR("invalid uri <%.*s>\n",
  319. gwas.len, gwas.s);
  320. goto err_exit;
  321. }
  322. /* note we discard the port discovered by the resolve function - we are
  323. interested only in the port that was actually configured. */
  324. if ((he=sip_resolvehost( &uri.host, NULL, (char*)(void*)&uri.proto))==0 ) {
  325. if(dr_force_dns)
  326. {
  327. LM_ERR("cannot resolve <%.*s>\n",
  328. uri.host.len, uri.host.s);
  329. goto err_exit;
  330. } else {
  331. LM_DBG("cannot resolve <%.*s> - won't be used"
  332. " by is_from_gw()\n", uri.host.len, uri.host.s);
  333. goto done;
  334. }
  335. }
  336. hostent2ip_addr(&ipa, he, 0);
  337. tmpa = r->pgw_addr_l;
  338. while(tmpa) {
  339. if(tmpa->type==type && uri.port_no==tmpa->port
  340. && ip_addr_cmp(&ipa, &tmpa->ip)) {
  341. LM_DBG("gw ip addr [%s]:%d loaded\n",
  342. ip_addr2a(&ipa), uri.port_no);
  343. goto done;
  344. }
  345. tmpa = tmpa->next;
  346. }
  347. LM_DBG("new gw ip addr [%s]\n", ip);
  348. tmpa = (pgw_addr_t*)shm_malloc(sizeof(pgw_addr_t));
  349. if(tmpa==NULL) {
  350. LM_ERR("no more shm mem (%u)\n",
  351. (unsigned int)sizeof(pgw_addr_t));
  352. goto err_exit;
  353. }
  354. memset(tmpa, 0, sizeof(pgw_addr_t));
  355. memcpy(&tmpa->ip, &ipa, sizeof(struct ip_addr));
  356. tmpa->port = uri.port_no;
  357. tmpa->type = type;
  358. tmpa->strip = strip;
  359. tmpa->next = r->pgw_addr_l;
  360. r->pgw_addr_l = tmpa;
  361. done:
  362. if(NULL==r->pgw_l)
  363. r->pgw_l = pgw;
  364. else {
  365. tmp = r->pgw_l;
  366. while(NULL != tmp->next)
  367. tmp = tmp->next;
  368. tmp->next = pgw;
  369. }
  370. return 0;
  371. err_exit:
  372. if(NULL!=pgw)
  373. shm_free(pgw);
  374. return -1;
  375. }
  376. void
  377. del_pgw_list(
  378. pgw_t *pgw_l
  379. )
  380. {
  381. pgw_t *t;
  382. while(NULL!=pgw_l){
  383. t = pgw_l;
  384. pgw_l=pgw_l->next;
  385. shm_free(t);
  386. }
  387. }
  388. void
  389. del_pgw_addr_list(
  390. pgw_addr_t *pgw_addr_l
  391. )
  392. {
  393. pgw_addr_t *t;
  394. while(NULL!=pgw_addr_l){
  395. t = pgw_addr_l;
  396. pgw_addr_l=pgw_addr_l->next;
  397. shm_free(t);
  398. }
  399. }
  400. void
  401. free_rt_data(
  402. rt_data_t* rt_data,
  403. int all
  404. )
  405. {
  406. int j;
  407. if(NULL!=rt_data) {
  408. /* del GW list */
  409. del_pgw_list(rt_data->pgw_l);
  410. rt_data->pgw_l = 0 ;
  411. /* del GW addr list */
  412. del_pgw_addr_list(rt_data->pgw_addr_l);
  413. rt_data->pgw_addr_l =0;
  414. /* del prefix tree */
  415. del_tree(rt_data->pt);
  416. /* del prefixless rules */
  417. if(NULL!=rt_data->noprefix.rg) {
  418. for(j=0;j<rt_data->noprefix.rg_pos;j++) {
  419. if(rt_data->noprefix.rg[j].rtlw !=NULL) {
  420. del_rt_list(rt_data->noprefix.rg[j].rtlw);
  421. rt_data->noprefix.rg[j].rtlw = 0;
  422. }
  423. }
  424. shm_free(rt_data->noprefix.rg);
  425. rt_data->noprefix.rg = 0;
  426. }
  427. /* del top level or reset to 0 it's content */
  428. if (all) shm_free(rt_data);
  429. else memset(rt_data, 0, sizeof(rt_data_t));
  430. }
  431. }