EmuProxyZA / tivodns.c

From TivoZA

Back to emuProxyZA.
Download source (You will need to rename it to: tivodns.c)

To update the below source file, select Upload file and upload your new tivodns.c file (there is no need to upload it as a .txt). If you do upload a new version, please add a brief description to the change log at the bottom of this page indicating what changes you made and why.

Source

  1. /*
  2. tivodns.c - tivodns library declarations
  3. Copyright (C) 2003 Christopher R. Wingert
  4. firedns.c - firedns library
  5. Copyright (C) 2002 Ian Gulliver
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of version 2 of the GNU General Public License as
  8. published by the Free Software Foundation.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17.  
  18. #include <stdlib.h>
  19. #include <time.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <sys/time.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <fcntl.h>
  28. #include "tivodns.h"
  29.  
  30. #ifdef TIVO
  31. int snprintf(char *str, size_t size, const char *format, ...);
  32. #endif
  33.  
  34. static const char tagstring[] = "$Id: tivodns.c,v 1.60 2004/01/03 23:30:49 ian Exp $";
  35.  
  36. #define tivodns_TRIES 3
  37. #define RESULTSIZE 1024
  38. #define min(a,b) (a < b ? a : b)
  39.  
  40. static struct in_addr servers4[FDNS_MAX]; /* up to FDNS_MAX nameservers; populated by tivodns_init() */
  41. static int i4; /* actual count of nameservers; set by tivodns_init() */
  42. #ifdef tivodns_USE_IPV6
  43. static int i6;
  44. static struct in6_addr servers6[FDNS_MAX];
  45. #endif
  46.  
  47. static int initdone = 0; /* to ensure tivodns_init() only runs once (on the first call) */
  48. static int wantclose = 0;
  49. static int lastcreate = -1;
  50.  
  51. struct s_connection { /* open DNS query */
  52. struct s_connection *next; /* next in list */
  53. unsigned char id[2]; /* unique ID (random number), matches header ID; both set by tivodns_add_query() */
  54. unsigned short class;
  55. unsigned short type;
  56. int want_list;
  57. int fd; /* file descriptor returned from sockets */
  58. #ifdef tivodns_USE_IPV6
  59. int v6;
  60. #endif
  61. };
  62.  
  63. static char resolv_conf[ 255 ] = FDNS_CONFIG_PREF;
  64.  
  65. struct s_rr_middle {
  66. unsigned short type;
  67. unsigned short class;
  68. unsigned long ttl;
  69. unsigned short rdlength;
  70. };
  71.  
  72. #define tivodns_POINTER_VALUE 0xc000
  73.  
  74. #define MY_PTHREAD_MUTEX_INITIALIZER ( -1 )
  75. typedef int my_pthread_mutex_t;
  76.  
  77. static my_pthread_mutex_t connlist_lock = MY_PTHREAD_MUTEX_INITIALIZER;
  78. static struct s_connection *connection_head = NULL; /* linked list of open DNS queries; populated by tivodns_add_query(), decimated by tivodns_getresult_s() */
  79.  
  80. struct s_header { /* DNS query header */
  81. unsigned char id[2];
  82. unsigned char flags1;
  83. #define FLAGS1_MASK_QR 0x80
  84. #define FLAGS1_MASK_OPCODE 0x78 /* bitshift right 3 */
  85. #define FLAGS1_MASK_AA 0x04
  86. #define FLAGS1_MASK_TC 0x02
  87. #define FLAGS1_MASK_RD 0x01
  88. unsigned char flags2;
  89. #define FLAGS2_MASK_RA 0x80
  90. #define FLAGS2_MASK_Z 0x70
  91. #define FLAGS2_MASK_RCODE 0x0f
  92. unsigned short qdcount;
  93. unsigned short ancount;
  94. unsigned short nscount;
  95. unsigned short arcount;
  96. unsigned char payload[512]; /* DNS question, populated by tivodns_build_query_payload() */
  97. };
  98.  
  99. static inline void tivodns_close(int fd) { /* close query */
  100. if (fd == lastcreate) {
  101. wantclose = 1;
  102. return;
  103. }
  104. close(fd);
  105. return;
  106. }
  107.  
  108. void my_pthread_mutex_lock( my_pthread_mutex_t *m )
  109. {
  110. if ( *m == MY_PTHREAD_MUTEX_INITIALIZER ) *m = 0;
  111. while ( *m != 0 ) sleep( 1 );
  112. ( *m ) ++;
  113. }
  114.  
  115. void my_pthread_mutex_unlock( my_pthread_mutex_t *m )
  116. {
  117. if ( *m == MY_PTHREAD_MUTEX_INITIALIZER ) *m = 0;
  118. if ( *m > 0 ) ( *m )--;
  119. }
  120.  
  121. #if 0
  122. static int hextoi( char *str )
  123. {
  124. int val;
  125. char *ptr;
  126.  
  127. ptr = str;
  128. if ( strncmp( str, "0x", 2 ) == 0 ) ptr +=2;
  129.  
  130. sscanf( ptr, "%x", &val );
  131.  
  132. return( val );
  133. }
  134. #endif
  135.  
  136. void tivodns_init( char *resolv ) { /* on first call only: populates servers4 (or -6) struct with up to FDNS_MAX nameserver IP addresses from /etc/tivodns.conf (or /etc/resolv.conf) */
  137. FILE *f;
  138. int i;
  139. struct in_addr addr4;
  140. char buf[1024];
  141.  
  142. if ( strlen( resolv ) > 0 ) strcpy( resolv_conf, resolv );
  143.  
  144. #ifdef tivodns_USE_IPV6
  145. struct in6_addr addr6;
  146. #endif
  147. if (initdone == 1)
  148. return;
  149. #ifdef tivodns_USE_IPV6
  150. i6 = 0;
  151. #endif
  152. i4 = 0;
  153.  
  154. initdone = 1;
  155. srand((unsigned int) time(NULL));
  156. memset(servers4,'\0',sizeof(struct in_addr) * FDNS_MAX);
  157. #ifdef tivodns_USE_IPV6
  158. memset(servers6,'\0',sizeof(struct in6_addr) * FDNS_MAX);
  159. #endif
  160. /* read /etc/tivodns.conf if we've got it, otherwise parse /etc/resolv.conf */
  161. f = fopen(FDNS_CONFIG_PREF,"r");
  162. if (f == NULL) {
  163. f = fopen(resolv_conf,"r");
  164. if ( f == NULL )
  165. {
  166. printf( "Opening backup resolv.conf\n" );
  167. f = fopen(FDNS_CONFIG_FBCK,"r");
  168. }
  169. if (f == NULL)
  170. return;
  171. while (fgets(buf,1024,f) != NULL) {
  172. if (strncmp(buf,"nameserver",10) == 0) {
  173. i = 10;
  174. while (buf[i] == ' ' || buf[i] == '\t')
  175. i++;
  176. #ifdef tivodns_USE_IPV6
  177. /* glibc /etc/resolv.conf seems to allow ipv6 server names */
  178. if (i6 < FDNS_MAX) {
  179. if (tivodns_aton6_s(&buf[i],&addr6) != NULL) {
  180. memcpy(&servers6[i6++],&addr6,sizeof(struct in6_addr));
  181. continue;
  182. }
  183. }
  184. #endif
  185. if (i4 < FDNS_MAX) {
  186. if (tivodns_aton4_s(&buf[i],&addr4) != NULL)
  187. memcpy(&servers4[i4++],&addr4,sizeof(struct in_addr));
  188. }
  189. }
  190. }
  191. } else {
  192. while (fgets(buf,1024,f) != NULL) {
  193. #ifdef tivodns_USE_IPV6
  194. if (i6 < FDNS_MAX) {
  195. if (tivodns_aton6_s(buf,&addr6) != NULL) {
  196. memcpy(&servers6[i6++],&addr6,sizeof(struct in6_addr));
  197. continue;
  198. }
  199. }
  200. #endif
  201. if (i4 < FDNS_MAX) {
  202. if (tivodns_aton4_s(buf,&addr4) != NULL)
  203. memcpy(&servers4[i4++],&addr4,sizeof(struct in_addr));
  204. }
  205. }
  206. }
  207. fclose(f);
  208.  
  209. }
  210.  
  211. static int tivodns_send_requests(const struct s_header *h, const struct s_connection *s, const int l) { /* send DNS query */
  212. int i;
  213. struct sockaddr_in addr4;
  214.  
  215. #ifdef tivodns_USE_IPV6
  216. struct sockaddr_in6 addr6;
  217. /* if we've got ipv6 support, an ip v6 socket, and ipv6 servers, send to them */
  218. if (i6 > 0 && s->v6 == 1) {
  219. for (i = 0; i < i6; i++) {
  220. memset(&addr6,0,sizeof(addr6));
  221. memcpy(&addr6.sin6_addr,&servers6[i],sizeof(addr6.sin6_addr));
  222. addr6.sin6_family = AF_INET6;
  223. addr6.sin6_port = htons(FDNS_PORT);
  224. sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr6, sizeof(addr6));
  225. }
  226. }
  227. #endif
  228.  
  229. for ( i = 0 ; i < i4 ; i++ ) {
  230. #ifdef tivodns_USE_IPV6
  231. /* send via ipv4-over-ipv6 if we've got an ipv6 socket */
  232. if (s->v6 == 1) {
  233. memset(&addr6,0,sizeof(addr6));
  234. memcpy(addr6.sin6_addr.s6_addr,"\0\0\0\0\0\0\0\0\0\0\xff\xff",12);
  235. memcpy(&addr6.sin6_addr.s6_addr[12],&servers4[i].s_addr,4);
  236. addr6.sin6_family = AF_INET6;
  237. addr6.sin6_port = htons(FDNS_PORT);
  238. sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr6, sizeof(addr6));
  239. continue;
  240. }
  241. #endif
  242. /* otherwise send via standard ipv4 boringness */
  243. memset(&addr4,0,sizeof(addr4));
  244. memcpy(&addr4.sin_addr,&servers4[i],sizeof(addr4.sin_addr));
  245. addr4.sin_family = AF_INET;
  246. addr4.sin_port = htons(FDNS_PORT);
  247. sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr4, sizeof(addr4));
  248. }
  249.  
  250. return 0;
  251. }
  252.  
  253. static struct s_connection *tivodns_add_query(struct s_header *h) { /* build DNS query, add to list */
  254. struct s_connection *s;
  255.  
  256. /* set header flags */
  257. h->id[0] = rand() % 255; /* verified by tivodns_getresult_s() */
  258. h->id[1] = rand() % 255;
  259. h->flags1 = 0 | FLAGS1_MASK_RD;
  260. h->flags2 = 0;
  261. h->qdcount = htons(1);
  262. h->ancount = htons(0);
  263. h->nscount = htons(0);
  264. h->arcount = htons(0);
  265.  
  266. /* create new connection object, add to linked list */
  267. s = malloc(sizeof(struct s_connection));
  268. my_pthread_mutex_lock(&connlist_lock);
  269. s->next = connection_head;
  270. connection_head = s;
  271.  
  272. /* turn off want_list by default */
  273. s->want_list = 0;
  274.  
  275. /* needed for security later */
  276. memcpy(s->id,h->id,2);
  277.  
  278. /* try to create ipv6 or ipv4 socket */
  279. #ifdef tivodns_USE_IPV6
  280. s->v6 = 0;
  281. if (i6 > 0) {
  282. s->fd = socket(PF_INET6, SOCK_DGRAM, 0);
  283. if (s->fd != -1) {
  284. if (fcntl(s->fd, F_SETFL, O_NONBLOCK) != 0) {
  285. close(s->fd);
  286. s->fd = -1;
  287. }
  288. }
  289. if (s->fd != -1) {
  290. struct sockaddr_in6 addr6;
  291. memset(&addr6,0,sizeof(addr6));
  292. addr6.sin6_family = AF_INET6;
  293. if (bind(s->fd,(struct sockaddr *)&addr6,sizeof(addr6)) == 0)
  294. s->v6 = 1;
  295. else
  296. close(s->fd);
  297. }
  298. }
  299. if (s->v6 == 0) {
  300. #endif
  301. s->fd = socket(PF_INET, SOCK_DGRAM, 0);
  302. if (s->fd != -1) {
  303. if (fcntl(s->fd, F_SETFL, O_NONBLOCK) != 0) {
  304. close(s->fd);
  305. s->fd = -1;
  306. }
  307. }
  308. if (s->fd != -1) {
  309. struct sockaddr_in addr;
  310. memset(&addr,0,sizeof(addr));
  311. addr.sin_family = AF_INET;
  312. addr.sin_port = 0;
  313. addr.sin_addr.s_addr = INADDR_ANY;
  314. if (bind(s->fd,(struct sockaddr *)&addr,sizeof(addr)) != 0) {
  315. close(s->fd);
  316. s->fd = -1;
  317. }
  318. }
  319. if (s->fd == -1) {
  320. connection_head = s->next;
  321. my_pthread_mutex_unlock(&connlist_lock);
  322. free(s);
  323. return NULL;
  324. }
  325. #ifdef tivodns_USE_IPV6
  326. }
  327. #endif
  328. if (wantclose == 1) {
  329. close(lastcreate);
  330. wantclose = 0;
  331. }
  332. lastcreate = s->fd;
  333. my_pthread_mutex_unlock(&connlist_lock);
  334. return s;
  335. }
  336.  
  337. static int tivodns_build_query_payload(const char * const name, const unsigned short rr, const unsigned short class, unsigned char * const payload) { /* populate payload with query: name= question, rr= record type */
  338. short payloadpos;
  339. const char * tempchr, * tempchr2;
  340. unsigned short l;
  341. payloadpos = 0;
  342. tempchr2 = name;
  343.  
  344. /* split name up into labels, create query */
  345. while ((tempchr = strchr(tempchr2,'.')) != NULL) {
  346. l = tempchr - tempchr2;
  347. if (payloadpos + l + 1 > 507)
  348. return -1;
  349. payload[payloadpos++] = l;
  350. memcpy(&payload[payloadpos],tempchr2,l);
  351. payloadpos += l;
  352. tempchr2 = &tempchr[1];
  353. }
  354. l = strlen(tempchr2);
  355. if (l) {
  356. if (payloadpos + l + 2 > 507)
  357. return -1;
  358. payload[payloadpos++] = l;
  359. memcpy(&payload[payloadpos],tempchr2,l);
  360. payloadpos += l;
  361. payload[payloadpos++] = '\0';
  362. }
  363. if (payloadpos > 508)
  364. return -1;
  365. l = htons(rr);
  366. memcpy(&payload[payloadpos],&l,2);
  367. l = htons(class);
  368. memcpy(&payload[payloadpos + 2],&l,2);
  369. return payloadpos + 4;
  370. }
  371.  
  372. struct in_addr *tivodns_aton4(const char * const ipstring) { /* ascii to numeric: convert string to static 4part IP addr struct */
  373. static struct in_addr ip;
  374. return tivodns_aton4_s(ipstring,&ip);
  375. }
  376.  
  377. struct in_addr *tivodns_aton4_r(const char * ipstring) { /* ascii to numeric (reentrant): convert string to new 4part IP addr struct */
  378. struct in_addr *ip;
  379. ip = malloc(sizeof(struct in_addr));
  380. if(tivodns_aton4_s(ipstring,ip) == NULL) {
  381. free(ip);
  382. return NULL;
  383. }
  384. return ip;
  385. }
  386.  
  387. struct in_addr *tivodns_aton4_s(const char * ipstring, struct in_addr * ip) { /* ascii to numeric (buffered): convert string to given 4part IP addr struct */
  388. unsigned char *myip;
  389. int i,part = 0;
  390. myip = (unsigned char *)ip;
  391.  
  392. memset(myip,'\0',4);
  393. for (i = 0; i < 16; i++) {
  394. switch (ipstring[i]) {
  395. case '\0':
  396. if (part != 3)
  397. return NULL;
  398. return ip;
  399. break;
  400. case '0':
  401. case '1':
  402. case '2':
  403. case '3':
  404. case '4':
  405. case '5':
  406. case '6':
  407. case '7':
  408. case '8':
  409. case '9':
  410. if (myip[part] > 25)
  411. return NULL;
  412. myip[part] *= 10;
  413. if (myip[part] == 250 && ipstring[i] - '0' > 6)
  414. return NULL;
  415. myip[part] += ipstring[i] - '0';
  416. break;
  417. case '.':
  418. if (part == 3)
  419. return ip;
  420. else
  421. part++;
  422. break;
  423. default:
  424. if (part == 3)
  425. return ip;
  426. else
  427. return NULL;
  428. break;
  429. }
  430. }
  431. if (part == 3)
  432. return ip;
  433. else
  434. return NULL;
  435. }
  436.  
  437. #ifdef tivodns_USE_IPV6
  438. struct in6_addr *tivodns_aton6(const char * const ipstring) {
  439. static struct in6_addr ip;
  440. return tivodns_aton6_s(ipstring,&ip);
  441. }
  442.  
  443. struct in6_addr *tivodns_aton6_r(const char * ipstring) {
  444. struct in6_addr *ip;
  445. ip = malloc(sizeof(struct in6_addr));
  446. if(tivodns_aton6_s(ipstring,ip) == NULL) {
  447. free(ip);
  448. return NULL;
  449. }
  450. return ip;
  451. }
  452.  
  453. struct in6_addr *tivodns_aton6_s(const char * ipstring, struct in6_addr * ip) {
  454. /* black magic */
  455. char instring[40];
  456. char tempstr[5];
  457. int i,o;
  458. int direction = 1;
  459. char *tempchr,*tempchr2;;
  460.  
  461. i = strlen(ipstring);
  462. if (i > 39)
  463. return NULL;
  464. memcpy(instring,ipstring,i+1);
  465.  
  466. memset(ip->s6_addr,'\0',16);
  467.  
  468. tempchr2 = instring;
  469. i = 0;
  470. while (direction > 0) {
  471. if (direction == 1) {
  472. tempchr = strchr(tempchr2,':');
  473. if (tempchr == NULL && i != 14)
  474. return NULL;
  475. if (tempchr != NULL)
  476. tempchr[0] = '\0';
  477. o = strlen(tempchr2);
  478. if (o > 4)
  479. return NULL;
  480. strcpy(tempstr,"0000");
  481. strcpy(&tempstr[4 - o],tempchr2);
  482. o = hextoi(tempstr);
  483. if (o == -1)
  484. return NULL;
  485. ip->s6_addr[i++] = o;
  486. o = hextoi(&tempstr[2]);
  487. if (o == -1)
  488. return NULL;
  489. ip->s6_addr[i++] = o;
  490. if (i >= 15)
  491. break;
  492. tempchr2 = tempchr + 1;
  493. if (tempchr2[0] == ':') {
  494. tempchr2++;
  495. direction = 2;
  496. i = 15;
  497. continue;
  498. }
  499. }
  500. if (direction == 2) {
  501. tempchr = strrchr(tempchr2,':');
  502. if (tempchr == NULL)
  503. tempchr = tempchr2;
  504. else {
  505. tempchr[0] = '\0';
  506. tempchr++;
  507. }
  508. o = strlen(tempchr);
  509. if (o > 4)
  510. return NULL;
  511. strcpy(tempstr,"0000");
  512. strcpy(&tempstr[4 - o],tempchr);
  513. o = hextoi(&tempstr[2]);
  514. if (o == -1)
  515. return NULL;
  516. ip->s6_addr[i--] = o;
  517. o = hextoi(tempstr);
  518. if (o == -1)
  519. return NULL;
  520. ip->s6_addr[i--] = o;
  521. if (i <= 1)
  522. break;
  523. if (tempchr == tempchr2)
  524. break;
  525. }
  526. }
  527. return ip;
  528. }
  529. #endif
  530.  
  531. int tivodns_getip4(const char * name) { /* build, add and send A query; retrieve result with tivodns_getresult() */
  532. struct s_header h;
  533. struct s_connection *s;
  534. int l;
  535.  
  536. tivodns_init( "" );
  537.  
  538. l = tivodns_build_query_payload(name,FDNS_QRY_A,1,(unsigned char *)&h.payload);
  539. if (l == -1)
  540. return -1;
  541. s = tivodns_add_query(&h);
  542. if (s == NULL)
  543. return -1;
  544. s->class = 1;
  545. s->type = FDNS_QRY_A;
  546. if (tivodns_send_requests(&h,s,l) == -1)
  547. return -1;
  548.  
  549. return s->fd;
  550. }
  551.  
  552. int tivodns_getip6(const char * name) {
  553. struct s_header h;
  554. struct s_connection *s;
  555. int l;
  556.  
  557. tivodns_init( "" );
  558.  
  559. l = tivodns_build_query_payload(name,FDNS_QRY_AAAA,1,(unsigned char *)&h.payload);
  560. if (l == -1)
  561. return -1;
  562. s = tivodns_add_query(&h);
  563. if (s == NULL)
  564. return -1;
  565. s->class = 1;
  566. s->type = FDNS_QRY_AAAA;
  567. if (tivodns_send_requests(&h,s,l) == -1)
  568. return -1;
  569.  
  570. return s->fd;
  571. }
  572.  
  573. int tivodns_gettxt(const char * name) { /* build, add and send TXT query; retrieve result with tivodns_getresult() */
  574. struct s_header h;
  575. struct s_connection *s;
  576. int l;
  577.  
  578. tivodns_init( "" );
  579.  
  580. l = tivodns_build_query_payload(name,FDNS_QRY_TXT,1,(unsigned char *)&h.payload);
  581. if (l == -1)
  582. return -1;
  583. s = tivodns_add_query(&h);
  584. if (s == NULL)
  585. return -1;
  586. s->class = 1;
  587. s->type = FDNS_QRY_TXT;
  588. if (tivodns_send_requests(&h,s,l) == -1)
  589. return -1;
  590.  
  591. return s->fd;
  592. }
  593.  
  594. int tivodns_getmx(const char * name) { /* build, add and send MX query; retrieve result with tivodns_getresult() */
  595. struct s_header h;
  596. struct s_connection *s;
  597. int l;
  598.  
  599. tivodns_init( "" );
  600.  
  601. l = tivodns_build_query_payload(name,FDNS_QRY_MX,1,(unsigned char *)&h.payload);
  602. if (l == -1)
  603. return -1;
  604. s = tivodns_add_query(&h);
  605. if (s == NULL)
  606. return -1;
  607. s->class = 1;
  608. s->type = FDNS_QRY_MX;
  609. if (tivodns_send_requests(&h,s,l) == -1)
  610. return -1;
  611.  
  612. return s->fd;
  613. }
  614.  
  615. int tivodns_getmxlist(const char * const name) {
  616. struct s_header h;
  617. struct s_connection *s;
  618. int l;
  619.  
  620. tivodns_init( "" );
  621.  
  622. l = tivodns_build_query_payload(name,FDNS_QRY_MX,1,(unsigned char *)&h.payload);
  623. if (l == -1)
  624. return -1;
  625. s = tivodns_add_query(&h);
  626. if (s == NULL)
  627. return -1;
  628. s->class = 1;
  629. s->type = FDNS_QRY_MX;
  630. s->want_list = 1;
  631. if (tivodns_send_requests(&h,s,l) == -1)
  632. return -1;
  633.  
  634. return s->fd;
  635. }
  636.  
  637. int tivodns_getname4(const struct in_addr * ip) { /* build, add and send PTR query; retrieve result with tivodns_getresult() */
  638. char query[512];
  639. struct s_header h;
  640. struct s_connection *s;
  641. unsigned char *c;
  642. int l;
  643.  
  644. tivodns_init( "" );
  645.  
  646. c = (unsigned char *)&ip->s_addr;
  647.  
  648. sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
  649.  
  650. l = tivodns_build_query_payload(query,FDNS_QRY_PTR,1,(unsigned char *)&h.payload);
  651. if (l == -1)
  652. return -1;
  653. s = tivodns_add_query(&h);
  654. if (s == NULL)
  655. return -1;
  656. s->class = 1;
  657. s->type = FDNS_QRY_PTR;
  658. if (tivodns_send_requests(&h,s,l) == -1)
  659. return -1;
  660.  
  661. return s->fd;
  662. }
  663.  
  664. #ifdef tivodns_USE_IPV6
  665. int tivodns_getname6(const struct in6_addr * ip) {
  666. char query[512];
  667. struct s_header h;
  668. struct s_connection *s;
  669. int l;
  670.  
  671. tivodns_init( "" );
  672.  
  673. sprintf(query,"%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.ip6.int",
  674. ip->s6_addr[15] & 0x0f,
  675. (ip->s6_addr[15] & 0xf0) >> 4,
  676. ip->s6_addr[14] & 0x0f,
  677. (ip->s6_addr[14] & 0xf0) >> 4,
  678. ip->s6_addr[13] & 0x0f,
  679. (ip->s6_addr[13] & 0xf0) >> 4,
  680. ip->s6_addr[12] & 0x0f,
  681. (ip->s6_addr[12] & 0xf0) >> 4,
  682. ip->s6_addr[11] & 0x0f,
  683. (ip->s6_addr[11] & 0xf0) >> 4,
  684. ip->s6_addr[10] & 0x0f,
  685. (ip->s6_addr[10] & 0xf0) >> 4,
  686. ip->s6_addr[9] & 0x0f,
  687. (ip->s6_addr[9] & 0xf0) >> 4,
  688. ip->s6_addr[8] & 0x0f,
  689. (ip->s6_addr[8] & 0xf0) >> 4,
  690. ip->s6_addr[7] & 0x0f,
  691. (ip->s6_addr[7] & 0xf0) >> 4,
  692. ip->s6_addr[6] & 0x0f,
  693. (ip->s6_addr[6] & 0xf0) >> 4,
  694. ip->s6_addr[5] & 0x0f,
  695. (ip->s6_addr[5] & 0xf0) >> 4,
  696. ip->s6_addr[4] & 0x0f,
  697. (ip->s6_addr[4] & 0xf0) >> 4,
  698. ip->s6_addr[3] & 0x0f,
  699. (ip->s6_addr[3] & 0xf0) >> 4,
  700. ip->s6_addr[2] & 0x0f,
  701. (ip->s6_addr[2] & 0xf0) >> 4,
  702. ip->s6_addr[1] & 0x0f,
  703. (ip->s6_addr[1] & 0xf0) >> 4,
  704. ip->s6_addr[0] & 0x0f,
  705. (ip->s6_addr[0] & 0xf0) >> 4
  706. );
  707.  
  708. l = tivodns_build_query_payload(query,12,1,(unsigned char *)&h.payload);
  709. if (l == -1)
  710. return -1;
  711. s = tivodns_add_query(&h);
  712. if (s == NULL)
  713. return -1;
  714. s->class = 1;
  715. s->type = 12;
  716. if (tivodns_send_requests(&h,s,l) == -1)
  717. return -1;
  718.  
  719. return s->fd;
  720. }
  721. #endif
  722.  
  723. int tivodns_dnsbl_lookup_a(const struct in_addr * ip, const char * name) { /* build, add and send A query to given DNSBL list; retrieve result with tivodns_getresult() */
  724. char hostname[256];
  725. snprintf(hostname,256,"%u.%u.%u.%u.%s",(unsigned int) ((unsigned char *)&ip->s_addr)[3],(unsigned int) ((unsigned char *)&ip->s_addr)[2],(unsigned int) ((unsigned char *)&ip->s_addr)[1],(unsigned int) ((unsigned char *)&ip->s_addr)[0],name);
  726. return tivodns_getip4(hostname);
  727. }
  728.  
  729. int tivodns_dnsbl_lookup_txt(const struct in_addr * ip, const char * name) { /* build, add and send TXT query to given DNSBL list; retrieve result with tivodns_getresult() */
  730. char hostname[256];
  731. snprintf(hostname,256,"%u.%u.%u.%u.%s",(unsigned int) ((unsigned char *)&ip->s_addr)[3],(unsigned int) ((unsigned char *)&ip->s_addr)[2],(unsigned int) ((unsigned char *)&ip->s_addr)[1],(unsigned int) ((unsigned char *)&ip->s_addr)[0],name);
  732. return tivodns_gettxt(hostname);
  733. }
  734.  
  735. char *tivodns_ntoa4(const struct in_addr * const ip) { /* numeric to ascii: convert 4part IP addr struct to static string */
  736. static char result[256];
  737. return tivodns_ntoa4_s(ip,result);
  738. }
  739.  
  740. char *tivodns_ntoa4_r(const struct in_addr * ip) { /* numeric to ascii (reentrant): convert 4part IP addr struct to new string */
  741. char *result;
  742. result = malloc(256);
  743. return tivodns_ntoa4_s(ip,result);
  744. }
  745.  
  746. char *tivodns_ntoa4_s(const struct in_addr * ip, char * result) { /* numeric to ascii (buffered): convert 4part IP addr struct to given string */
  747. unsigned char *m;
  748. m = (unsigned char *)&ip->s_addr;
  749. sprintf(result,"%d.%d.%d.%d",m[0],m[1],m[2],m[3]);
  750. return result;
  751. }
  752.  
  753. #ifdef tivodns_USE_IPV6
  754. char *tivodns_ntoa6(const struct in6_addr *ip) {
  755. static char result[256];
  756. return tivodns_ntoa6_s(ip,result);
  757. }
  758.  
  759. char *tivodns_ntoa6_r(const struct in6_addr *ip) {
  760. char *result;
  761. result = malloc(256);
  762. return tivodns_ntoa6_s(ip,result);
  763. }
  764.  
  765. char *tivodns_ntoa6_s(const struct in6_addr * ip, char * result) {
  766. sprintf(result,"%x:%x:%x:%x:%x:%x:%x:%x",
  767. ntohs(*((unsigned short *)&ip->s6_addr[0])),
  768. ntohs(*((unsigned short *)&ip->s6_addr[2])),
  769. ntohs(*((unsigned short *)&ip->s6_addr[4])),
  770. ntohs(*((unsigned short *)&ip->s6_addr[6])),
  771. ntohs(*((unsigned short *)&ip->s6_addr[8])),
  772. ntohs(*((unsigned short *)&ip->s6_addr[10])),
  773. ntohs(*((unsigned short *)&ip->s6_addr[12])),
  774. ntohs(*((unsigned short *)&ip->s6_addr[14])));
  775. return result;
  776. }
  777. #endif
  778.  
  779. char *tivodns_getresult(const int fd) { /* retrieve result of DNS query */
  780. static char result[RESULTSIZE];
  781. return tivodns_getresult_s(fd,result);
  782. }
  783.  
  784. char *tivodns_getresult_r(const int fd) { /* retrieve result of DNS query (reentrant) */
  785. char *result;
  786. result = malloc(RESULTSIZE);
  787. if(tivodns_getresult_s(fd,result) == NULL) {
  788. free(result);
  789. return NULL;
  790. }
  791. return result;
  792. }
  793.  
  794. char *tivodns_getresult_s(const int fd, char * result) { /* retrieve result of DNS query (buffered) */
  795. struct s_header h;
  796. struct s_connection *c, *prev;
  797. int l,i,q,curanswer,o;
  798. struct s_rr_middle *rr, rrbacking;
  799. char *src, *dst;
  800. int bytes;
  801. unsigned short p;
  802.  
  803. rr = 0;
  804.  
  805. prev = NULL;
  806. my_pthread_mutex_lock(&connlist_lock);
  807. c = connection_head;
  808. while (c != NULL) { /* find query in list of open queries */
  809. if (c->fd == fd)
  810. break;
  811. prev = c;
  812. c = c->next;
  813. }
  814. if (c == NULL) {
  815. my_pthread_mutex_unlock(&connlist_lock);
  816. return NULL; /* query not found */
  817. }
  818. /* query found-- pull from list: */
  819. if (prev != NULL)
  820. prev->next = c->next;
  821. else
  822. connection_head = c->next;
  823. my_pthread_mutex_unlock(&connlist_lock);
  824.  
  825. l = recv(c->fd,&h,sizeof(struct s_header),0);
  826. tivodns_close(c->fd);
  827. if (l < 12) {
  828. free(c);
  829. return NULL;
  830. }
  831. if (c->id[0] != h.id[0] || c->id[1] != h.id[1]) {
  832. free(c);
  833. return NULL; /* ID mismatch */
  834. }
  835. if ((h.flags1 & FLAGS1_MASK_QR) == 0) {
  836. free(c);
  837. return NULL;
  838. }
  839. if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0) {
  840. free(c);
  841. return NULL;
  842. }
  843. if ((h.flags2 & FLAGS2_MASK_RCODE) != 0) {
  844. free(c);
  845. return NULL;
  846. }
  847. h.ancount = ntohs(h.ancount);
  848. if (h.ancount < 1) { /* no sense going on if we don't have any answers */
  849. free(c);
  850. return NULL;
  851. }
  852. /* skip queries */
  853. i = 0;
  854. q = 0;
  855. l -= 12;
  856. h.qdcount = ntohs(h.qdcount);
  857. while (q < h.qdcount && i < l) {
  858. if (h.payload[i] > 63) { /* pointer */
  859. i += 6; /* skip pointer, class and type */
  860. q++;
  861. } else { /* label */
  862. if (h.payload[i] == 0) {
  863. q++;
  864. i += 5; /* skip nil, class and type */
  865. } else
  866. i += h.payload[i] + 1; /* skip length and label */
  867. }
  868. }
  869. /* &h.payload[i] should now be the start of the first response */
  870. curanswer = 0;
  871. while (