ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/firedns.c
Revision: 9862
Committed: Sat Jan 2 18:39:00 2021 UTC (4 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 18957 byte(s)
Log Message:
- Use monotonic time whenever possible

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

Properties

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