ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/firedns.c
Revision: 8579
Committed: Sun Oct 14 15:12:50 2018 UTC (6 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 18908 byte(s)
Log Message:
- Allocate most list_t and node_t items from within their corresponding structure to save extra calloc/free calls

File Contents

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

Properties

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