ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/firedns.c
Revision: 5380
Committed: Sat Jan 17 19:10:47 2015 UTC (10 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 17465 byte(s)
Log Message:
- Use 'static' and 'extern' keywords where appropriate 

File Contents

# User Rev Content
1 michael 5052 /*
2     firedns.c - firedns library
3     Copyright (C) 2002 Ian Gulliver
4    
5     This file has been gutted and mucked with for use in BOPM - see the
6     real library at http://ares.penguinhosting.net/~ian/ before you judge
7     firedns based on this..
8    
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of version 2 of the GNU General Public License as
11     published by the Free Software Foundation.
12    
13     This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     #include "setup.h"
24    
25     #include <stdlib.h>
26     #include <time.h>
27     #include <sys/types.h>
28     #include <sys/socket.h>
29 michael 5227 #include <poll.h>
30 michael 5052 #include <sys/time.h>
31     #include <netinet/in.h>
32 michael 5175 #include <arpa/inet.h>
33 michael 5052 #include <string.h>
34     #include <unistd.h>
35     #include <stdio.h>
36     #include <errno.h>
37     #include <fcntl.h>
38    
39     #include "compat.h"
40 michael 5333 #include "memory.h"
41 michael 5052 #include "firedns.h"
42     #include "config.h"
43     #include "list.h"
44     #include "log.h"
45     #include "dnsbl.h"
46    
47     #define FIREDNS_TRIES 3
48     #define min(a,b) (a < b ? a : b)
49    
50     int fdns_errno = FDNS_ERR_NONE;
51    
52     /* Variables local to this file */
53 michael 5380 static unsigned int fdns_fdinuse;
54 michael 5052
55     /* up to FDNS_MAX nameservers; populated by firedns_init() */
56     static struct in_addr servers4[FDNS_MAX];
57 michael 5380 static struct in6_addr servers6[FDNS_MAX];
58 michael 5052 /* actual count of nameservers; set by firedns_init() */
59     static int i4;
60     static int i6;
61    
62     /*
63 michael 5181 * Linked list of open DNS queries; populated by firedns_add_query(),
64 michael 5052 * decimated by firedns_getresult()
65     */
66 michael 5181 static list_t *CONNECTIONS;
67 michael 5052
68     /*
69     * List of errors, in order of values used in FDNS_ERR_*, returned by
70     * firedns_strerror
71     */
72 michael 5181 static const char *errors[] =
73     {
74     "Success",
75     "Format error",
76     "Server failure",
77     "Name error",
78     "Not implemented",
79     "Refused",
80     "Timeout",
81     "Network error",
82     "FD Limit reached",
83     "Unknown error"
84 michael 5052 };
85    
86     /* Structures */
87    
88     /* open DNS query */
89     struct s_connection
90     {
91 michael 5181 /*
92     * unique ID (random number), matches header ID; both set by
93     * firedns_add_query()
94     */
95     unsigned char id[2];
96     uint16_t class;
97     uint16_t type;
98    
99     /* file descriptor returned from sockets */
100     int fd;
101     void *info;
102     time_t start;
103     char lookup[256];
104     int v6;
105 michael 5052 };
106    
107     struct s_rr_middle
108     {
109 michael 5181 uint16_t type;
110     uint16_t class;
111    
112     /* XXX - firedns depends on this being 4 bytes */
113     uint32_t ttl;
114     uint16_t rdlength;
115 michael 5052 };
116    
117     /* DNS query header */
118     struct s_header
119     {
120 michael 5181 unsigned char id[2];
121     unsigned char flags1;
122 michael 5052 #define FLAGS1_MASK_QR 0x80
123     /* bitshift right 3 */
124     #define FLAGS1_MASK_OPCODE 0x78
125     #define FLAGS1_MASK_AA 0x04
126     #define FLAGS1_MASK_TC 0x02
127     #define FLAGS1_MASK_RD 0x01
128    
129 michael 5181 unsigned char flags2;
130 michael 5052 #define FLAGS2_MASK_RA 0x80
131     #define FLAGS2_MASK_Z 0x70
132     #define FLAGS2_MASK_RCODE 0x0f
133    
134 michael 5181 uint16_t qdcount;
135     uint16_t ancount;
136     uint16_t nscount;
137     uint16_t arcount;
138    
139     /* DNS question, populated by firedns_build_query_payload() */
140     unsigned char payload[512];
141 michael 5052 };
142    
143     /* Function prototypes */
144     static struct s_connection *firedns_add_query(void);
145 michael 5181 static int firedns_doquery(struct s_connection *);
146     static int firedns_build_query_payload(const char *const, uint16_t, uint16_t, unsigned char *);
147     static int firedns_send_requests(struct s_header *, struct s_connection *, int);
148 michael 5052
149    
150 michael 5181 void
151     firedns_init(void)
152 michael 5052 {
153 michael 5181 /*
154     * populates servers4 (or -6) struct with up to FDNS_MAX nameserver IP
155     * addresses from /etc/firedns.conf (or /etc/resolv.conf)
156     */
157     FILE *f;
158     int i;
159     struct in_addr addr4;
160     struct in6_addr addr6;
161     char buf[1024];
162 michael 5185 char *p = NULL;
163 michael 5052
164 michael 5181 i6 = 0;
165     i4 = 0;
166 michael 5052
167 michael 5181 /* Initialize connections list */
168     CONNECTIONS = list_create();
169 michael 5052
170 michael 5181 srand((unsigned int)time(NULL));
171     memset(servers4, 0, sizeof(struct in_addr) * FDNS_MAX);
172     memset(servers6, 0, sizeof(struct in6_addr) * FDNS_MAX);
173 michael 5052
174 michael 5181 /* read etc/firedns.conf if we've got it, otherwise parse /etc/resolv.conf */
175     f = fopen(FDNS_CONFIG_PREF, "r");
176    
177     if (f == NULL)
178     {
179     f = fopen(FDNS_CONFIG_FBCK, "r");
180    
181     if (f == NULL)
182     {
183     log_printf("Unable to open %s", FDNS_CONFIG_FBCK);
184     return;
185     }
186    
187 michael 5187 while (fgets(buf, sizeof(buf), f))
188 michael 5181 {
189 michael 5185 if ((p = strchr(buf, '\n')))
190     *p = '\0';
191    
192 michael 5181 if (strncmp(buf, "nameserver", 10) == 0)
193 michael 5052 {
194 michael 5181 i = 10;
195    
196     while (buf[i] == ' ' || buf[i] == '\t')
197     ++i;
198    
199     if (i6 < FDNS_MAX)
200     {
201     if (inet_pton(AF_INET6, &buf[i], &addr6) > 0)
202     {
203     memcpy(&servers6[i6++], &addr6, sizeof(struct in6_addr));
204     continue;
205     }
206     }
207    
208     if (i4 < FDNS_MAX)
209     {
210     if (inet_pton(AF_INET, &buf[i], &addr4) > 0)
211     memcpy(&servers4[i4++], &addr4, sizeof(struct in_addr));
212     }
213 michael 5052 }
214 michael 5181 }
215     }
216     else
217     {
218 michael 5187 while (fgets(buf, sizeof(buf), f))
219 michael 5181 {
220 michael 5185 if ((p = strchr(buf, '\n')))
221     *p = '\0';
222    
223 michael 5181 if (i6 < FDNS_MAX)
224     {
225     if (inet_pton(AF_INET6, buf, &addr6) > 0)
226     {
227     memcpy(&servers6[i6++], &addr6, sizeof(struct in6_addr));
228     continue;
229     }
230 michael 5052 }
231 michael 5181
232     if (i4 < FDNS_MAX)
233 michael 5052 {
234 michael 5181 if (inet_pton(AF_INET, buf, &addr4) > 0)
235     memcpy(&servers4[i4++], &addr4, sizeof(struct in_addr));
236     }
237     }
238     }
239 michael 5179
240 michael 5181 fclose(f);
241 michael 5052 }
242    
243 michael 5181 /* immediate A query */
244     struct in_addr *
245     firedns_resolveip4(const char *const name)
246     {
247     static struct in_addr addr;
248 michael 5052
249 michael 5181 if (inet_pton(AF_INET, name, &addr) > 0)
250     return &addr;
251    
252     return (struct in_addr *)firedns_resolveip(FDNS_QRY_A, name);
253 michael 5052 }
254    
255 michael 5181 /* immediate AAAA query */
256     struct in6_addr *
257     firedns_resolveip6(const char * const name)
258     {
259 michael 5183 static struct in6_addr addr;
260    
261     if (inet_pton(AF_INET6, name, &addr) > 0)
262     return &addr;
263    
264 michael 5181 return (struct in6_addr *)firedns_resolveip(FDNS_QRY_AAAA, name);
265 michael 5052 }
266    
267 michael 5181 /* resolve a query of a given type */
268     char *
269     firedns_resolveip(int type, const char *const name)
270     {
271     struct firedns_result *result;
272     struct timeval tv;
273     fd_set s;
274 michael 5052
275 michael 5181 for (int t = 0; t < FIREDNS_TRIES; ++t)
276     {
277     int fd = firedns_getip(type, name, NULL);
278 michael 5052
279 michael 5181 if (fd == -1)
280     return NULL;
281 michael 5052
282 michael 5181 tv.tv_sec = 5;
283     tv.tv_usec = 0;
284     FD_ZERO(&s);
285     FD_SET(fd, &s);
286     select(fd + 1, &s, NULL, NULL, &tv);
287    
288     result = firedns_getresult(fd);
289    
290     if (fdns_errno == FDNS_ERR_NONE)
291     /*
292     * Return is from static memory in getresult, so there is no need to
293     * copy it until the next call to firedns.
294     */
295     return result->text;
296     else if (fdns_errno == FDNS_ERR_NXDOMAIN)
297     return NULL;
298     }
299    
300     if (fdns_errno == FDNS_ERR_NONE)
301     fdns_errno = FDNS_ERR_TIMEOUT;
302    
303     return NULL;
304 michael 5052 }
305    
306     /*
307     * build, add and send specified query; retrieve result with
308     * firedns_getresult()
309     */
310 michael 5181 int
311     firedns_getip(int type, const char * const name, void *info)
312 michael 5052 {
313 michael 5181 struct s_connection *s;
314     node_t *node;
315     int fd;
316 michael 5052
317 michael 5181 s = firedns_add_query();
318     s->class = 1;
319     s->type = type;
320     s->info = info;
321     strlcpy(s->lookup, name, sizeof(s->lookup));
322 michael 5052
323 michael 5181 if (fdns_fdinuse >= OptionsItem->dns_fdlimit)
324     {
325     fdns_errno = FDNS_ERR_FDLIMIT;
326 michael 5052
327 michael 5181 /* Don't add to queue if there is no info */
328     if (info == NULL)
329 michael 5052 MyFree(s);
330 michael 5181 else
331     {
332     node = node_create(s);
333     list_add(CONNECTIONS, node);
334     }
335 michael 5052
336 michael 5181 return -1;
337     }
338    
339     fd = firedns_doquery(s);
340    
341     if (fd == -1)
342     {
343     MyFree(s);
344     return -1;
345     }
346    
347     node = node_create(s);
348     list_add(CONNECTIONS, node);
349    
350     return fd;
351 michael 5052 }
352    
353 michael 5181 /* build DNS query, add to list */
354     static struct s_connection *
355     firedns_add_query(void)
356     {
357     struct s_connection *s;
358 michael 5052
359 michael 5181 /* create new connection object */
360 michael 5274 s = xcalloc(sizeof *s);
361 michael 5052
362 michael 5181 /* verified by firedns_getresult() */
363     s->id[0] = rand() % 255;
364     s->id[1] = rand() % 255;
365     s->fd = -1;
366 michael 5052
367 michael 5181 return s;
368 michael 5052 }
369    
370 michael 5181 static int
371     firedns_doquery(struct s_connection *s)
372 michael 5052 {
373 michael 5181 int len;
374     struct s_header h;
375 michael 5052
376 michael 5181 len = firedns_build_query_payload(s->lookup, s->type, 1, (unsigned char *)&h.payload);
377 michael 5052
378 michael 5181 if (len == -1)
379     {
380     fdns_errno = FDNS_ERR_FORMAT;
381     return -1;
382     }
383 michael 5052
384 michael 5181 return firedns_send_requests(&h, s, len);
385 michael 5052 }
386    
387     /*
388     * populate payload with query: name= question, rr= record type
389     */
390 michael 5181 static int
391     firedns_build_query_payload(const char *const name, uint16_t rr, uint16_t class,
392     unsigned char *payload)
393 michael 5052 {
394 michael 5181 int16_t payloadpos = 0;
395     const char *tempchr, *tempchr2;
396     uint16_t l;
397 michael 5052
398 michael 5181 tempchr2 = name;
399 michael 5052
400 michael 5181 /* split name up into labels, create query */
401     while ((tempchr = strchr(tempchr2, '.')))
402     {
403     l = tempchr - tempchr2;
404    
405     if (payloadpos + l + 1 > 507)
406 michael 5052 return -1;
407 michael 5181
408     payload[payloadpos++] = l;
409     memcpy(&payload[payloadpos], tempchr2, l);
410     payloadpos += l;
411     tempchr2 = &tempchr[1];
412     }
413    
414     l = strlen(tempchr2);
415    
416     if (l)
417     {
418     if (payloadpos + l + 2 > 507)
419     return -1;
420    
421     payload[payloadpos++] = l;
422     memcpy(&payload[payloadpos], tempchr2, l);
423     payloadpos += l;
424     payload[payloadpos++] = '\0';
425     }
426    
427     if (payloadpos > 508)
428     return -1;
429    
430     l = htons(rr);
431     memcpy(&payload[payloadpos], &l, 2);
432    
433     l = htons(class);
434     memcpy(&payload[payloadpos + 2], &l, 2);
435    
436     return payloadpos + 4;
437 michael 5052 }
438    
439     /* send DNS query */
440 michael 5181 static int
441     firedns_send_requests(struct s_header *h, struct s_connection *s, int l)
442 michael 5052 {
443 michael 5181 int i, sent_ok = 0;
444     struct sockaddr_in addr4;
445     struct sockaddr_in6 addr6;
446 michael 5052
447 michael 5181 /* set header flags */
448     h->flags1 = 0 | FLAGS1_MASK_RD;
449     h->flags2 = 0;
450     h->qdcount = htons(1);
451     h->ancount = htons(0);
452     h->nscount = htons(0);
453     h->arcount = htons(0);
454     memcpy(h->id, s->id, 2);
455    
456     /* try to create ipv6 or ipv4 socket */
457     s->v6 = 0;
458    
459     if (i6 > 0)
460     {
461     s->fd = socket(PF_INET6, SOCK_DGRAM, 0);
462    
463     if (s->fd != -1)
464     {
465     if (fcntl(s->fd, F_SETFL, O_NONBLOCK))
466 michael 5052 {
467 michael 5181 close(s->fd);
468     s->fd = -1;
469 michael 5052 }
470 michael 5181 }
471 michael 5052
472 michael 5181 if (s->fd != -1)
473     {
474     struct sockaddr_in6 addr6;
475    
476     memset(&addr6, 0, sizeof(addr6));
477     addr6.sin6_family = AF_INET6;
478    
479     if (bind(s->fd, (struct sockaddr *)&addr6, sizeof(addr6)) == 0)
480     s->v6 = 1;
481     else
482     close(s->fd);
483     }
484     }
485    
486     if (s->v6 == 0)
487     {
488     s->fd = socket(PF_INET, SOCK_DGRAM, 0);
489    
490     if (s->fd != -1)
491     {
492     if (fcntl(s->fd, F_SETFL, O_NONBLOCK))
493 michael 5052 {
494 michael 5181 close(s->fd);
495     s->fd = -1;
496 michael 5052 }
497 michael 5181 }
498 michael 5052
499 michael 5181 if (s->fd != -1)
500     {
501     struct sockaddr_in addr;
502    
503     memset(&addr, 0, sizeof(addr));
504     addr.sin_family = AF_INET;
505     addr.sin_port = 0;
506     addr.sin_addr.s_addr = INADDR_ANY;
507    
508     if (bind(s->fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
509 michael 5052 {
510 michael 5181 close(s->fd);
511     s->fd = -1;
512 michael 5052 }
513 michael 5181 }
514 michael 5179
515 michael 5181 if (s->fd == -1)
516     {
517 michael 5052 fdns_errno = FDNS_ERR_NETWORK;
518     return -1;
519 michael 5181 }
520     }
521    
522     /* if we've got ipv6 support, an ip v6 socket, and ipv6 servers, send to them */
523     if (i6 > 0 && s->v6 == 1)
524     {
525     for (i = 0; i < i6; i++)
526     {
527     memset(&addr6, 0, sizeof(addr6));
528     memcpy(&addr6.sin6_addr, &servers6[i], sizeof(addr6.sin6_addr));
529    
530     addr6.sin6_family = AF_INET6;
531     addr6.sin6_port = htons(FDNS_PORT);
532    
533     if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr6, sizeof(addr6)) > 0)
534     sent_ok = 1;
535     }
536     }
537    
538     for (i = 0; i < i4; i++)
539     {
540     /* send via ipv4-over-ipv6 if we've got an ipv6 socket */
541     if (s->v6 == 1)
542     {
543     memset(&addr6, 0, sizeof(addr6));
544     memcpy(addr6.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
545     memcpy(&addr6.sin6_addr.s6_addr[12], &servers4[i].s_addr, 4);
546     addr6.sin6_family = AF_INET6;
547     addr6.sin6_port = htons(FDNS_PORT);
548    
549     if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr6, sizeof(addr6)) > 0)
550     sent_ok = 1;
551    
552     continue;
553     }
554    
555     /* otherwise send via standard ipv4 boringness */
556     memset(&addr4, 0, sizeof(addr4));
557     memcpy(&addr4.sin_addr, &servers4[i], sizeof(addr4.sin_addr));
558     addr4.sin_family = AF_INET;
559     addr4.sin_port = htons(FDNS_PORT);
560    
561     if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr4, sizeof(addr4)) > 0)
562     sent_ok = 1;
563     }
564    
565     if (!sent_ok)
566     {
567     close(s->fd);
568     s->fd = -1;
569     fdns_errno = FDNS_ERR_NETWORK;
570     return -1;
571     }
572    
573     time(&s->start);
574     fdns_fdinuse++;
575     fdns_errno = FDNS_ERR_NONE;
576    
577     return s->fd;
578 michael 5052 }
579    
580 michael 5181 /* retrieve result of DNS query */
581     struct firedns_result *
582     firedns_getresult(const int fd)
583     {
584     static struct firedns_result result;
585     struct s_header h;
586     struct s_connection *c;
587     node_t *node;
588     int l, i, q, curanswer;
589     struct s_rr_middle *rr, rrbacking;
590     char *src, *dst;
591     int bytes;
592 michael 5052
593 michael 5181 fdns_errno = FDNS_ERR_OTHER;
594     result.info = NULL;
595 michael 5052
596 michael 5181 memset(result.text, 0, sizeof(result.text));
597 michael 5052
598 michael 5181 /* Find query in list of dns lookups */
599     LIST_FOREACH(node, CONNECTIONS->head)
600     {
601     c = node->data;
602 michael 5052
603 michael 5181 if (c->fd == fd)
604     break;
605     else
606     c = NULL;
607     }
608 michael 5052
609 michael 5181 /* query not found */
610     if (c == NULL)
611     return &result;
612 michael 5052
613 michael 5181 /* query found -- we remove in cleanup */
614     l = recv(c->fd, &h,sizeof(struct s_header), 0);
615     result.info = c->info;
616     strlcpy(result.lookup, c->lookup, sizeof(result.lookup));
617 michael 5052
618 michael 5181 if (l == -1)
619     {
620     fdns_errno = FDNS_ERR_NETWORK;
621     goto cleanup;
622     }
623    
624     if (l < 12)
625     goto cleanup;
626    
627     if (c->id[0] != h.id[0] || c->id[1] != h.id[1])
628     /*
629     * ID mismatch: we keep the connection, as this could be an answer to
630     * a previous lookup..
631     */
632     return NULL;
633    
634     if ((h.flags1 & FLAGS1_MASK_QR) == 0)
635     goto cleanup;
636    
637     if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0)
638     goto cleanup;
639    
640     if ((h.flags2 & FLAGS2_MASK_RCODE) != 0)
641     {
642     fdns_errno = (h.flags2 & FLAGS2_MASK_RCODE);
643     goto cleanup;
644     }
645    
646     h.ancount = ntohs(h.ancount);
647    
648     if (h.ancount < 1)
649     {
650     fdns_errno = FDNS_ERR_NXDOMAIN;
651     /* no sense going on if we don't have any answers */
652     goto cleanup;
653     }
654    
655     /* skip queries */
656     i = 0;
657     q = 0;
658     l -= 12;
659     h.qdcount = ntohs(h.qdcount);
660    
661     while (q < h.qdcount && i < l)
662     {
663     if (h.payload[i] > 63)
664     {
665     /* pointer */
666     i += 6; /* skip pointer, class and type */
667     q++;
668     }
669     else
670     {
671     /* label */
672     if (h.payload[i] == 0)
673     {
674     q++;
675     i += 5; /* skip nil, class and type */
676 michael 5052 }
677     else
678 michael 5181 i += h.payload[i] + 1; /* skip length and label */
679     }
680     }
681    
682     /* &h.payload[i] should now be the start of the first response */
683     curanswer = 0;
684    
685     while (curanswer < h.ancount)
686     {
687     q = 0;
688    
689     while (q == 0 && i < l)
690     {
691     if (h.payload[i] > 63)
692 michael 5052 {
693 michael 5181 /* pointer */
694     i += 2; /* skip pointer */
695     q = 1;
696 michael 5052 }
697 michael 5181 else
698 michael 5052 {
699 michael 5181 /* label */
700     if (h.payload[i] == 0)
701     {
702     i++;
703     q = 1;
704     }
705     else
706     i += h.payload[i] + 1; /* skip length and label */
707 michael 5052 }
708 michael 5181 }
709 michael 5052
710 michael 5181 if (l - i < 10)
711 michael 5052 goto cleanup;
712    
713 michael 5181 rr = (struct s_rr_middle *)&h.payload[i];
714     src = (char *)rr;
715     dst = (char *)&rrbacking;
716 michael 5052
717 michael 5181 for (bytes = sizeof(rrbacking); bytes; bytes--)
718     *dst++ = *src++;
719    
720     rr = &rrbacking;
721     i += 10;
722     rr->rdlength = ntohs(rr->rdlength);
723    
724     if (ntohs(rr->type) != c->type)
725     {
726     curanswer++;
727     i += rr->rdlength;
728     continue;
729     }
730    
731     if (ntohs(rr->class) != c->class)
732     {
733     curanswer++;
734     i += rr->rdlength;
735     continue;
736     }
737    
738     break;
739     }
740    
741     if (curanswer == h.ancount)
742     goto cleanup;
743     if (i + rr->rdlength > l)
744     goto cleanup;
745     if (rr->rdlength > 1023)
746     goto cleanup;
747    
748     fdns_errno = FDNS_ERR_NONE;
749     memcpy(result.text, &h.payload[i], rr->rdlength);
750     result.text[rr->rdlength] = '\0';
751    
752     /* Clean-up */
753 michael 5052 cleanup:
754 michael 5181 list_remove(CONNECTIONS, node);
755     node_free(node);
756     close(c->fd);
757     fdns_fdinuse--;
758     MyFree(c);
759 michael 5052
760 michael 5181 return &result;
761 michael 5052 }
762    
763 michael 5181 void
764     firedns_cycle(void)
765 michael 5052 {
766 michael 5181 node_t *node, *next;
767     struct s_connection *p;
768     struct firedns_result *res, new_result;
769     static struct pollfd *ufds = NULL;
770     int fd;
771     unsigned int size, i;
772     time_t timenow;
773 michael 5052
774 michael 5181 if (LIST_SIZE(CONNECTIONS) == 0)
775     return;
776 michael 5052
777 michael 5181 if (ufds == NULL)
778 michael 5274 ufds = xcalloc((sizeof *ufds) * OptionsItem->dns_fdlimit);
779 michael 5052
780 michael 5181 time(&timenow);
781     size = 0;
782 michael 5052
783 michael 5181 LIST_FOREACH_SAFE(node, next, CONNECTIONS->head)
784     {
785     if (size >= OptionsItem->dns_fdlimit)
786     break;
787 michael 5052
788 michael 5181 p = node->data;
789 michael 5052
790 michael 5181 if (p->fd < 0)
791     continue;
792 michael 5052
793 michael 5181 if (p->fd > 0 && (p->start + FDNS_TIMEOUT) < timenow)
794     {
795     /* Timed out - remove from list */
796     list_remove(CONNECTIONS, node);
797     node_free(node);
798 michael 5052
799 michael 5181 memset(new_result.text, 0, sizeof(new_result.text));
800     new_result.info = p->info;
801     strlcpy(new_result.lookup, p->lookup, sizeof(new_result.lookup));
802 michael 5052
803 michael 5181 close(p->fd);
804     fdns_fdinuse--;
805     MyFree(p);
806 michael 5052
807 michael 5181 fdns_errno = FDNS_ERR_TIMEOUT;
808 michael 5052
809 michael 5181 if (new_result.info)
810     dnsbl_result(&new_result);
811 michael 5052
812 michael 5181 continue;
813     }
814 michael 5052
815 michael 5181 ufds[size].events = 0;
816     ufds[size].revents = 0;
817     ufds[size].fd = p->fd;
818     ufds[size].events = POLLIN;
819 michael 5052
820 michael 5181 size++;
821     }
822 michael 5052
823 michael 5181 switch (poll(ufds, size, 0))
824     {
825     case -1:
826     case 0:
827     return;
828     }
829 michael 5052
830 michael 5181 LIST_FOREACH_SAFE(node, next, CONNECTIONS->head)
831     {
832     p = node->data;
833 michael 5052
834 michael 5181 if (p->fd > 0)
835     {
836     for (i = 0; i < size; i++)
837 michael 5052 {
838 michael 5181 if ((ufds[i].revents & POLLIN) && ufds[i].fd == p->fd)
839     {
840     fd = p->fd;
841     res = firedns_getresult(fd);
842 michael 5052
843 michael 5181 if (res && res->info)
844     dnsbl_result(res);
845    
846     break;
847     }
848 michael 5052 }
849 michael 5181 }
850     else if (fdns_fdinuse < OptionsItem->dns_fdlimit)
851     firedns_doquery(p);
852     }
853 michael 5052 }
854    
855 michael 5181 const char *
856     firedns_strerror(int error)
857 michael 5052 {
858 michael 5181 if (error == FDNS_ERR_NETWORK)
859     return strerror(errno);
860    
861     return errors[error];
862 michael 5052 }

Properties

Name Value
svn:eol-style native
svn:keywords Id