2
0

ipops_pv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * This file 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. *
  14. * This file is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. #include <assert.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <netdb.h>
  29. #include <arpa/inet.h>
  30. #include <netinet/in.h>
  31. #include "../../dprint.h"
  32. #include "../../hashes.h"
  33. #include "../../resolve.h"
  34. #include "../../pvar.h"
  35. #define PV_DNS_ADDR 64
  36. #define PV_DNS_RECS 32
  37. typedef struct _sr_dns_record {
  38. int type;
  39. char addr[PV_DNS_ADDR];
  40. } sr_dns_record_t;
  41. typedef struct _sr_dns_item {
  42. str name;
  43. unsigned int hashid;
  44. char hostname[256];
  45. int count;
  46. int ipv4;
  47. int ipv6;
  48. sr_dns_record_t r[PV_DNS_RECS];
  49. struct _sr_dns_item *next;
  50. } sr_dns_item_t;
  51. #define SR_DNS_PVIDX 1
  52. typedef struct _dns_pv {
  53. sr_dns_item_t *item;
  54. int type;
  55. int flags;
  56. pv_spec_t *pidx;
  57. int nidx;
  58. } dns_pv_t;
  59. static sr_dns_item_t *_sr_dns_list = NULL;
  60. /**
  61. *
  62. */
  63. sr_dns_item_t *sr_dns_get_item(str *name)
  64. {
  65. sr_dns_item_t *it = NULL;
  66. unsigned int hashid = 0;
  67. hashid = get_hash1_raw(name->s, name->len);
  68. it = _sr_dns_list;
  69. while(it!=NULL)
  70. {
  71. if(it->hashid==hashid && it->name.len == name->len
  72. && strncmp(it->name.s, name->s, name->len)==0)
  73. return it;
  74. it = it->next;
  75. }
  76. return NULL;
  77. }
  78. /**
  79. *
  80. */
  81. sr_dns_item_t *sr_dns_add_item(str *name)
  82. {
  83. sr_dns_item_t *it = NULL;
  84. unsigned int hashid = 0;
  85. hashid = get_hash1_raw(name->s, name->len);
  86. it = _sr_dns_list;
  87. while(it!=NULL)
  88. {
  89. if(it->hashid==hashid && it->name.len == name->len
  90. && strncmp(it->name.s, name->s, name->len)==0)
  91. return it;
  92. it = it->next;
  93. }
  94. /* add new */
  95. it = (sr_dns_item_t*)pkg_malloc(sizeof(sr_dns_item_t));
  96. if(it==NULL)
  97. {
  98. LM_ERR("no more pkg\n");
  99. return NULL;
  100. }
  101. memset(it, 0, sizeof(sr_dns_item_t));
  102. it->name.s = (char*)pkg_malloc(name->len+1);
  103. if(it->name.s==NULL)
  104. {
  105. LM_ERR("no more pkg.\n");
  106. pkg_free(it);
  107. return NULL;
  108. }
  109. memcpy(it->name.s, name->s, name->len);
  110. it->name.s[name->len] = '\0';
  111. it->name.len = name->len;
  112. it->hashid = hashid;
  113. it->next = _sr_dns_list;
  114. _sr_dns_list = it;
  115. return it;
  116. }
  117. /**
  118. *
  119. */
  120. int pv_parse_dns_name(pv_spec_t *sp, str *in)
  121. {
  122. dns_pv_t *dpv=NULL;
  123. char *p;
  124. str pvc;
  125. str pvs;
  126. str pvi;
  127. int sign;
  128. if(sp==NULL || in==NULL || in->len<=0)
  129. return -1;
  130. dpv = (dns_pv_t*)pkg_malloc(sizeof(dns_pv_t));
  131. if(dpv==NULL)
  132. return -1;
  133. memset(dpv, 0, sizeof(dns_pv_t));
  134. p = in->s;
  135. while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
  136. p++;
  137. if(p>in->s+in->len || *p=='\0')
  138. goto error;
  139. pvc.s = p;
  140. while(p < in->s + in->len)
  141. {
  142. if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
  143. break;
  144. p++;
  145. }
  146. if(p>in->s+in->len || *p=='\0')
  147. goto error;
  148. pvc.len = p - pvc.s;
  149. if(*p!='=')
  150. {
  151. while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
  152. p++;
  153. if(p>in->s+in->len || *p=='\0' || *p!='=')
  154. goto error;
  155. }
  156. p++;
  157. if(*p!='>')
  158. goto error;
  159. p++;
  160. pvs.len = in->len - (int)(p - in->s);
  161. pvs.s = p;
  162. pvi.s = 0;
  163. pvi.len = 0;
  164. if(pvs.s[pvs.len-1]==']') {
  165. /* index */
  166. p = memchr(pvs.s, '[', pvs.len-1);
  167. if(p==NULL) {
  168. goto error;
  169. }
  170. pvi.s = p + 1;
  171. pvi.len = pvs.s + pvs.len - pvi.s;
  172. pvs.len = p - pvs.s;
  173. }
  174. LM_DBG("dns [%.*s] - key [%.*s] index [%.*s]\n", pvc.len, pvc.s,
  175. pvs.len, pvs.s, (pvi.len>0)?pvi.len:0, (pvi.s!=NULL)?pvi.s:0);
  176. dpv->item = sr_dns_add_item(&pvc);
  177. if(dpv->item==NULL)
  178. goto error;
  179. switch(pvs.len)
  180. {
  181. case 4:
  182. if(strncmp(pvs.s, "addr", 4)==0)
  183. dpv->type = 0;
  184. else if(strncmp(pvs.s, "type", 4)==0)
  185. dpv->type = 1;
  186. else if(strncmp(pvs.s, "ipv4", 4)==0)
  187. dpv->type = 2;
  188. else if(strncmp(pvs.s, "ipv6", 4)==0)
  189. dpv->type = 3;
  190. else goto error;
  191. break;
  192. case 5:
  193. if(strncmp(pvs.s, "count", 5)==0)
  194. dpv->type = 4;
  195. else goto error;
  196. break;
  197. default:
  198. goto error;
  199. }
  200. if(pvi.len>0)
  201. {
  202. if(pvi.s[0]==PV_MARKER)
  203. {
  204. dpv->pidx = pv_cache_get(&pvi);
  205. if(dpv->pidx==NULL)
  206. goto error;
  207. dpv->flags |= SR_DNS_PVIDX;
  208. } else {
  209. sign = 1;
  210. p = pvi.s;
  211. if(*p=='-')
  212. {
  213. sign = -1;
  214. p++;
  215. }
  216. dpv->nidx = 0;
  217. while(p<pvi.s+pvi.len && *p>='0' && *p<='9')
  218. {
  219. dpv->nidx = dpv->nidx * 10 + *p - '0';
  220. p++;
  221. }
  222. if(p!=pvi.s+pvi.len)
  223. {
  224. LM_ERR("invalid index [%.*s]\n", in->len, in->s);
  225. return -1;
  226. }
  227. dpv->nidx *= sign;
  228. }
  229. }
  230. sp->pvp.pvn.u.dname = (void*)dpv;
  231. sp->pvp.pvn.type = PV_NAME_OTHER;
  232. return 0;
  233. error:
  234. LM_ERR("error at PV dns name: %.*s\n", in->len, in->s);
  235. if(dpv) pkg_free(dpv);
  236. return -1;
  237. }
  238. /**
  239. *
  240. */
  241. int pv_get_dns(sip_msg_t *msg, pv_param_t *param,
  242. pv_value_t *res)
  243. {
  244. dns_pv_t *dpv;
  245. pv_value_t val;
  246. if(msg==NULL || param==NULL)
  247. return -1;
  248. dpv = (dns_pv_t*)param->pvn.u.dname;
  249. if(dpv==NULL || dpv->item==NULL)
  250. return -1;
  251. if(dpv->pidx!=NULL)
  252. {
  253. if(pv_get_spec_value(msg, dpv->pidx, &val)<0
  254. || (!(val.flags&PV_VAL_INT)))
  255. {
  256. LM_ERR("failed to evaluate index variable\n");
  257. return pv_get_null(msg, param, res);
  258. }
  259. } else {
  260. val.ri = dpv->nidx;
  261. }
  262. if(val.ri<0)
  263. {
  264. if(dpv->item->count+val.ri<0) {
  265. return pv_get_null(msg, param, res);
  266. }
  267. val.ri = dpv->item->count+val.ri;
  268. }
  269. if(val.ri>=dpv->item->count) {
  270. return pv_get_null(msg, param, res);
  271. }
  272. switch(dpv->type)
  273. {
  274. case 0: /* address */
  275. return pv_get_strzval(msg, param, res,
  276. dpv->item->r[val.ri].addr);
  277. case 1: /* type */
  278. return pv_get_sintval(msg, param, res,
  279. dpv->item->r[val.ri].type);
  280. case 2: /* ipv4 */
  281. return pv_get_sintval(msg, param, res,
  282. dpv->item->ipv4);
  283. case 3: /* ipv6 */
  284. return pv_get_sintval(msg, param, res,
  285. dpv->item->ipv6);
  286. case 4: /* count */
  287. return pv_get_sintval(msg, param, res,
  288. dpv->item->count);
  289. default: /* else */
  290. return pv_get_null(msg, param, res);
  291. }
  292. }
  293. /**
  294. *
  295. */
  296. int dns_init_pv(char *path)
  297. {
  298. return 0;
  299. }
  300. /**
  301. *
  302. */
  303. void dns_destroy_list(void)
  304. {
  305. return;
  306. }
  307. /**
  308. *
  309. */
  310. void dns_destroy_pv(void)
  311. {
  312. return;
  313. }
  314. /**
  315. *
  316. */
  317. int dns_update_pv(str *hostname, str *name)
  318. {
  319. sr_dns_item_t *dr = NULL;
  320. struct addrinfo hints, *res, *p;
  321. struct sockaddr_in *ipv4;
  322. struct sockaddr_in6 *ipv6;
  323. void *addr;
  324. int status;
  325. int i;
  326. if(hostname->len>255)
  327. {
  328. LM_DBG("target hostname too long (max 255): %s\n", hostname->s);
  329. return -2;
  330. }
  331. dr = sr_dns_get_item(name);
  332. if(dr==NULL)
  333. {
  334. LM_DBG("container not found: %s\n", name->s);
  335. return -3;
  336. }
  337. /* reset the counter */
  338. dr->count = 0;
  339. dr->ipv4 = 0;
  340. dr->ipv6 = 0;
  341. strncpy(dr->hostname, hostname->s, hostname->len);
  342. dr->hostname[hostname->len] = '\0';
  343. LM_DBG("attempting to resolve: %s\n", dr->hostname);
  344. memset(&hints, 0, sizeof(hints));
  345. hints.ai_family = AF_UNSPEC; /* allow any of AF_INET or AF_INET6 */
  346. // hints.ai_socktype = SOCK_STREAM;
  347. hints.ai_socktype = SOCK_DGRAM;
  348. if ((status = getaddrinfo(dr->hostname, NULL, &hints, &res)) != 0)
  349. {
  350. LM_ERR("unable to resolve %s - getaddrinfo: %s\n",
  351. dr->hostname, gai_strerror(status));
  352. return -4;
  353. }
  354. i=0;
  355. for(p=res; p!=NULL; p=p->ai_next)
  356. {
  357. if (p->ai_family==AF_INET)
  358. {
  359. dr->ipv4 = 1;
  360. dr->r[i].type = 4;
  361. ipv4 = (struct sockaddr_in *)p->ai_addr;
  362. addr = &(ipv4->sin_addr);
  363. } else {
  364. dr->ipv6 = 1;
  365. dr->r[i].type = 6;
  366. ipv6 = (struct sockaddr_in6 *)p->ai_addr;
  367. addr = &(ipv6->sin6_addr);
  368. }
  369. inet_ntop(p->ai_family, addr, dr->r[i].addr,
  370. PV_DNS_ADDR);
  371. LM_DBG("#%d - type %d addr: %s (%d)\n", i, dr->r[i].type,
  372. dr->r[i].addr, p->ai_socktype);
  373. i++;
  374. if(i==PV_DNS_RECS) {
  375. LM_WARN("more than %d addresses for %s - truncating\n",
  376. PV_DNS_RECS, dr->hostname);
  377. break;
  378. }
  379. }
  380. freeaddrinfo(res);
  381. dr->count = i;
  382. LM_DBG("dns PV updated for: %s (%d)\n", dr->hostname, i);
  383. return 1;
  384. }
  385. struct _hn_pv_data {
  386. str data;
  387. str fullname;
  388. str hostname;
  389. str domain;
  390. str ipaddr;
  391. };
  392. static struct _hn_pv_data *_hn_data = NULL;
  393. /**
  394. *
  395. */
  396. int hn_pv_data_init(void)
  397. {
  398. char hbuf[512];
  399. int hlen;
  400. char *d;
  401. struct hostent *he;
  402. int i;
  403. if(_hn_data != NULL)
  404. return 0;
  405. if (gethostname(hbuf, 512)<0) {
  406. LM_WARN("gethostname failed - host pvs will be null\n");
  407. return -1;
  408. }
  409. hlen = strlen(hbuf);
  410. if(hlen<=0) {
  411. LM_WARN("empty hostname result - host pvs will be null\n");
  412. return -1;
  413. }
  414. _hn_data = (struct _hn_pv_data*)pkg_malloc(sizeof(struct _hn_pv_data)+46+2*(hlen+1));
  415. if(_hn_data==NULL) {
  416. LM_ERR("no more pkg to init hostname data\n");
  417. return -1;
  418. }
  419. memset(_hn_data, 0, sizeof(struct _hn_pv_data)+46+2*(hlen+1));
  420. _hn_data->data.len = hlen;
  421. _hn_data->data.s = (char*)_hn_data + sizeof(struct _hn_pv_data);
  422. _hn_data->fullname.len = hlen;
  423. _hn_data->fullname.s = _hn_data->data.s + hlen + 1;
  424. strcpy(_hn_data->data.s, hbuf);
  425. strcpy(_hn_data->fullname.s, hbuf);
  426. d=strchr(_hn_data->data.s, '.');
  427. if (d) {
  428. _hn_data->hostname.len = d - _hn_data->data.s;
  429. _hn_data->hostname.s = _hn_data->data.s;
  430. _hn_data->domain.len = _hn_data->fullname.len
  431. - _hn_data->hostname.len-1;
  432. _hn_data->domain.s = d+1;
  433. } else {
  434. _hn_data->hostname = _hn_data->fullname;
  435. }
  436. he=resolvehost(_hn_data->fullname.s);
  437. if (he) {
  438. if ((strlen(he->h_name)!=_hn_data->fullname.len)
  439. || strncmp(he->h_name, _hn_data->fullname.s,
  440. _hn_data->fullname.len)) {
  441. LM_WARN("hostname '%.*s' different than gethostbyname '%s'\n",
  442. _hn_data->fullname.len, _hn_data->fullname.s, he->h_name);
  443. }
  444. if (he->h_addr_list) {
  445. for (i=0; he->h_addr_list[i]; i++) {
  446. if (inet_ntop(he->h_addrtype, he->h_addr_list[i], hbuf, 46)) {
  447. if (_hn_data->ipaddr.len==0) {
  448. _hn_data->ipaddr.len = strlen(hbuf);
  449. _hn_data->ipaddr.s = _hn_data->fullname.s + hlen + 1;
  450. strcpy(_hn_data->ipaddr.s, hbuf);
  451. } else if (strncmp(_hn_data->ipaddr.s, hbuf,
  452. _hn_data->ipaddr.len)!=0) {
  453. LM_WARN("many IPs to hostname: %s not used\n", hbuf);
  454. }
  455. }
  456. }
  457. } else {
  458. LM_WARN(" can't resolve hostname's address: %s\n",
  459. _hn_data->fullname.s);
  460. }
  461. }
  462. DBG("Hostname: %.*s\n", _hn_data->hostname.len, ZSW(_hn_data->hostname.s));
  463. DBG("Domain: %.*s\n", _hn_data->domain.len, ZSW(_hn_data->domain.s));
  464. DBG("Fullname: %.*s\n", _hn_data->fullname.len, ZSW(_hn_data->fullname.s));
  465. DBG("IPaddr: %.*s\n", _hn_data->ipaddr.len, ZSW(_hn_data->ipaddr.s));
  466. return 0;
  467. }
  468. /**
  469. *
  470. */
  471. int pv_parse_hn_name(pv_spec_p sp, str *in)
  472. {
  473. if(sp==NULL || in==NULL || in->len<=0)
  474. return -1;
  475. switch(in->len)
  476. {
  477. case 1:
  478. if(strncmp(in->s, "n", 1)==0)
  479. sp->pvp.pvn.u.isname.name.n = 0;
  480. else if(strncmp(in->s, "f", 1)==0)
  481. sp->pvp.pvn.u.isname.name.n = 1;
  482. else if(strncmp(in->s, "d", 1)==0)
  483. sp->pvp.pvn.u.isname.name.n = 2;
  484. else if(strncmp(in->s, "i", 1)==0)
  485. sp->pvp.pvn.u.isname.name.n = 3;
  486. else goto error;
  487. break;
  488. default:
  489. goto error;
  490. }
  491. sp->pvp.pvn.type = PV_NAME_INTSTR;
  492. sp->pvp.pvn.u.isname.type = 0;
  493. hn_pv_data_init();
  494. return 0;
  495. error:
  496. LM_ERR("unknown host PV name %.*s\n", in->len, in->s);
  497. return -1;
  498. }
  499. /**
  500. *
  501. */
  502. int pv_get_hn(struct sip_msg *msg, pv_param_t *param,
  503. pv_value_t *res)
  504. {
  505. if(param==NULL)
  506. return -1;
  507. if(_hn_data==NULL)
  508. return pv_get_null(msg, param, res);;
  509. switch(param->pvn.u.isname.name.n)
  510. {
  511. case 1:
  512. if(_hn_data->fullname.len==0)
  513. return pv_get_null(msg, param, res);;
  514. return pv_get_strval(msg, param, res, &_hn_data->fullname);
  515. case 2:
  516. if(_hn_data->domain.len==0)
  517. return pv_get_null(msg, param, res);;
  518. return pv_get_strval(msg, param, res, &_hn_data->domain);
  519. case 3:
  520. if(_hn_data->ipaddr.len==0)
  521. return pv_get_null(msg, param, res);;
  522. return pv_get_strval(msg, param, res, &_hn_data->ipaddr);
  523. default:
  524. if(_hn_data->hostname.len==0)
  525. return pv_get_null(msg, param, res);;
  526. return pv_get_strval(msg, param, res, &_hn_data->hostname);
  527. }
  528. }