ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/firedns.c
Revision: 5170
Committed: Fri Dec 26 20:53:09 2014 UTC (9 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 18890 byte(s)
Log Message:
- Continue to use inet_pton() until we add full ipv6 support, but at least
  replace all occurrences of inet_aton() with inet_pton()

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

Properties

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