From ea13b172f9571a565466917d240a48504e1b6451 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 28 Dec 2014 23:34:01 +0000 Subject: [PATCH] - firedns.c: style corrections git-svn-id: svn://svn.ircd-hybrid.org/svnroot/hopm/trunk@5181 82007160-df01-0410-b94d-b575c5fd34c7 --- src/firedns.c | 1262 ++++++++++++++++++++++++++----------------------- 1 file changed, 666 insertions(+), 596 deletions(-) diff --git a/src/firedns.c b/src/firedns.c index 8bae600..90bed49 100644 --- a/src/firedns.c +++ b/src/firedns.c @@ -47,8 +47,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define FIREDNS_TRIES 3 #define min(a,b) (a < b ? a : b) -/* Global variables */ - int fdns_errno = FDNS_ERR_NONE; unsigned int fdns_fdinuse = 0; @@ -58,31 +56,31 @@ unsigned int fdns_fdinuse = 0; static struct in_addr servers4[FDNS_MAX]; /* actual count of nameservers; set by firedns_init() */ static int i4; - static int i6; static struct in6_addr servers6[FDNS_MAX]; /* - * linked list of open DNS queries; populated by firedns_add_query(), + * Linked list of open DNS queries; populated by firedns_add_query(), * decimated by firedns_getresult() */ -static list_t *CONNECTIONS = NULL; +static list_t *CONNECTIONS; /* * List of errors, in order of values used in FDNS_ERR_*, returned by * firedns_strerror */ -static const char *errors[] = { - "Success", - "Format error", - "Server failure", - "Name error", - "Not implemented", - "Refused", - "Timeout", - "Network error", - "FD Limit reached", - "Unknown error" +static const char *errors[] = +{ + "Success", + "Format error", + "Server failure", + "Name error", + "Not implemented", + "Refused", + "Timeout", + "Network error", + "FD Limit reached", + "Unknown error" }; /* Structures */ @@ -90,35 +88,37 @@ static const char *errors[] = { /* open DNS query */ struct s_connection { - /* - * unique ID (random number), matches header ID; both set by - * firedns_add_query() - */ - unsigned char id[2]; - uint16_t class; - uint16_t type; - /* file descriptor returned from sockets */ - int fd; - void *info; - time_t start; - char lookup[256]; - int v6; + /* + * unique ID (random number), matches header ID; both set by + * firedns_add_query() + */ + unsigned char id[2]; + uint16_t class; + uint16_t type; + + /* file descriptor returned from sockets */ + int fd; + void *info; + time_t start; + char lookup[256]; + int v6; }; struct s_rr_middle { - uint16_t type; - uint16_t class; - /* XXX - firedns depends on this being 4 bytes */ - uint32_t ttl; - uint16_t rdlength; + uint16_t type; + uint16_t class; + + /* XXX - firedns depends on this being 4 bytes */ + uint32_t ttl; + uint16_t rdlength; }; /* DNS query header */ struct s_header { - unsigned char id[2]; - unsigned char flags1; + unsigned char id[2]; + unsigned char flags1; #define FLAGS1_MASK_QR 0x80 /* bitshift right 3 */ #define FLAGS1_MASK_OPCODE 0x78 @@ -126,669 +126,739 @@ struct s_header #define FLAGS1_MASK_TC 0x02 #define FLAGS1_MASK_RD 0x01 - unsigned char flags2; + unsigned char flags2; #define FLAGS2_MASK_RA 0x80 #define FLAGS2_MASK_Z 0x70 #define FLAGS2_MASK_RCODE 0x0f - uint16_t qdcount; - uint16_t ancount; - uint16_t nscount; - uint16_t arcount; - /* DNS question, populated by firedns_build_query_payload() */ - unsigned char payload[512]; + uint16_t qdcount; + uint16_t ancount; + uint16_t nscount; + uint16_t arcount; + + /* DNS question, populated by firedns_build_query_payload() */ + unsigned char payload[512]; }; /* Function prototypes */ - static struct s_connection *firedns_add_query(void); -static int firedns_doquery(struct s_connection *s); -static int firedns_build_query_payload(const char * const name, - uint16_t, uint16_t, unsigned char * payload); -static int firedns_send_requests(struct s_header *h, struct s_connection *s, - int l); +static int firedns_doquery(struct s_connection *); +static int firedns_build_query_payload(const char *const, uint16_t, uint16_t, unsigned char *); +static int firedns_send_requests(struct s_header *, struct s_connection *, int); -void firedns_init(void) +void +firedns_init(void) { - /* - * populates servers4 (or -6) struct with up to FDNS_MAX nameserver IP - * addresses from /etc/firedns.conf (or /etc/resolv.conf) - */ - FILE *f; - int i; - struct in_addr addr4; - char buf[1024]; - const char *file; - struct in6_addr addr6; - - i6 = 0; - i4 = 0; - - /* Initialize connections list */ - CONNECTIONS = list_create(); - - srand((unsigned int) time(NULL)); - memset(servers4,'\0',sizeof(struct in_addr) * FDNS_MAX); - memset(servers6,'\0',sizeof(struct in6_addr) * FDNS_MAX); - - /* read etc/firedns.conf if we've got it, otherwise parse /etc/resolv.conf */ - f = fopen(FDNS_CONFIG_PREF,"r"); - if (f == NULL) - { - f = fopen(FDNS_CONFIG_FBCK,"r"); - if (f == NULL) + /* + * populates servers4 (or -6) struct with up to FDNS_MAX nameserver IP + * addresses from /etc/firedns.conf (or /etc/resolv.conf) + */ + FILE *f; + int i; + struct in_addr addr4; + struct in6_addr addr6; + char buf[1024]; + const char *file; + + i6 = 0; + i4 = 0; + + /* Initialize connections list */ + CONNECTIONS = list_create(); + + srand((unsigned int)time(NULL)); + memset(servers4, 0, sizeof(struct in_addr) * FDNS_MAX); + memset(servers6, 0, sizeof(struct in6_addr) * FDNS_MAX); + + /* read etc/firedns.conf if we've got it, otherwise parse /etc/resolv.conf */ + f = fopen(FDNS_CONFIG_PREF, "r"); + + if (f == NULL) + { + f = fopen(FDNS_CONFIG_FBCK, "r"); + + if (f == NULL) + { + log_printf("Unable to open %s", FDNS_CONFIG_FBCK); + return; + } + + file = FDNS_CONFIG_FBCK; + + while (fgets(buf, 1024, f)) + { + if (strncmp(buf, "nameserver", 10) == 0) { - log_printf("Unable to open %s", FDNS_CONFIG_FBCK); - return; + i = 10; + + while (buf[i] == ' ' || buf[i] == '\t') + ++i; + + /* glibc /etc/resolv.conf seems to allow ipv6 server names */ + if (i6 < FDNS_MAX) + { + if (inet_pton(AF_INET6, &buf[i], &addr6) > 0) + { + memcpy(&servers6[i6++], &addr6, sizeof(struct in6_addr)); + continue; + } + } + + if (i4 < FDNS_MAX) + { + if (inet_pton(AF_INET, &buf[i], &addr4) > 0) + memcpy(&servers4[i4++], &addr4, sizeof(struct in_addr)); + } } - file = FDNS_CONFIG_FBCK; - while (fgets(buf,1024,f) != NULL) + } + } + else + { + file = FDNS_CONFIG_PREF; + + while (fgets(buf, 1024, f)) + { + buf[strspn(buf, "0123456789.")] = '\0'; + + if (i6 < FDNS_MAX) { - if (strncmp(buf,"nameserver",10) == 0) - { - i = 10; - while (buf[i] == ' ' || buf[i] == '\t') - i++; - - /* glibc /etc/resolv.conf seems to allow ipv6 server names */ - if (i6 < FDNS_MAX) - { - if (inet_pton(AF_INET6, &buf[i], &addr6) > 0) - { - memcpy(&servers6[i6++],&addr6,sizeof(struct in6_addr)); - continue; - } - } - - if (i4 < FDNS_MAX) - { - if (inet_pton(AF_INET, &buf[i], &addr4) > 0) - memcpy(&servers4[i4++],&addr4,sizeof(struct in_addr)); - } - } + if (inet_pton(AF_INET6, buf, &addr6) > 0) + { + memcpy(&servers6[i6++], &addr6, sizeof(struct in6_addr)); + continue; + } } - } - else - { - file = FDNS_CONFIG_PREF; - while (fgets(buf,1024,f) != NULL) + + if (i4 < FDNS_MAX) { - buf[strspn(buf, "0123456789.")] = '\0'; - - if (i6 < FDNS_MAX) - { - if (inet_pton(AF_INET6, buf, &addr6) > 0) - { - memcpy(&servers6[i6++], &addr6, sizeof(struct in6_addr)); - continue; - } - } - - if (i4 < FDNS_MAX) - { - if (inet_pton(AF_INET, buf, &addr4) > 0) - memcpy(&servers4[i4++],&addr4,sizeof(struct in_addr)); - } + if (inet_pton(AF_INET, buf, &addr4) > 0) + memcpy(&servers4[i4++], &addr4, sizeof(struct in_addr)); } - } - fclose(f); - - if(i4 == 0 - /* (yuck) */ - && i6 - ) - { - log_printf("FIREDNS -> No nameservers found in %s", file); - exit(EXIT_FAILURE); - } + } + } + + fclose(f); + + if (i4 == 0 /* (yuck) */ && i6) + { + log_printf("FIREDNS -> No nameservers found in %s", file); + exit(EXIT_FAILURE); + } } -struct in_addr *firedns_resolveip4(const char * const name) -{ /* immediate A query */ - static struct in_addr addr; +/* immediate A query */ +struct in_addr * +firedns_resolveip4(const char *const name) +{ + static struct in_addr addr; + + if (inet_pton(AF_INET, name, &addr) > 0) + return &addr; - if (inet_pton(AF_INET, name, &addr) > 0) - return &addr; - - return (struct in_addr *) firedns_resolveip(FDNS_QRY_A, name); + return (struct in_addr *)firedns_resolveip(FDNS_QRY_A, name); } -struct in6_addr *firedns_resolveip6(const char * const name) -{ /* immediate AAAA query */ - return (struct in6_addr *) firedns_resolveip(FDNS_QRY_AAAA, name); +/* immediate AAAA query */ +struct in6_addr * +firedns_resolveip6(const char * const name) +{ + return (struct in6_addr *)firedns_resolveip(FDNS_QRY_AAAA, name); } -char *firedns_resolveip(int type, const char * const name) -{ /* resolve a query of a given type */ - int fd, t; - struct firedns_result *result; - struct timeval tv; - fd_set s; - - for (t = 0; t < FIREDNS_TRIES; t++) - { - fd = firedns_getip(type, name, NULL); - if (fd == -1) - return NULL; - - tv.tv_sec = 5; - tv.tv_usec = 0; - FD_ZERO(&s); - FD_SET(fd, &s); - select(fd + 1, &s, NULL, NULL, &tv); - - result = firedns_getresult(fd); - - if (fdns_errno == FDNS_ERR_NONE) - /* Return is from static memory in getresult, so there is no need to - copy it until the next call to firedns. */ - return result->text; - else if(fdns_errno == FDNS_ERR_NXDOMAIN) - return NULL; - } - if(fdns_errno == FDNS_ERR_NONE) - fdns_errno = FDNS_ERR_TIMEOUT; - return NULL; +/* resolve a query of a given type */ +char * +firedns_resolveip(int type, const char *const name) +{ + struct firedns_result *result; + struct timeval tv; + fd_set s; + + for (int t = 0; t < FIREDNS_TRIES; ++t) + { + int fd = firedns_getip(type, name, NULL); + + if (fd == -1) + return NULL; + + tv.tv_sec = 5; + tv.tv_usec = 0; + FD_ZERO(&s); + FD_SET(fd, &s); + select(fd + 1, &s, NULL, NULL, &tv); + + result = firedns_getresult(fd); + + if (fdns_errno == FDNS_ERR_NONE) + /* + * Return is from static memory in getresult, so there is no need to + * copy it until the next call to firedns. + */ + return result->text; + else if (fdns_errno == FDNS_ERR_NXDOMAIN) + return NULL; + } + + if (fdns_errno == FDNS_ERR_NONE) + fdns_errno = FDNS_ERR_TIMEOUT; + + return NULL; } /* * build, add and send specified query; retrieve result with * firedns_getresult() */ -int firedns_getip(int type, const char * const name, void *info) +int +firedns_getip(int type, const char * const name, void *info) { - struct s_connection *s; - node_t *node; - int fd; - - s = firedns_add_query(); - - s->class = 1; - s->type = type; - strlcpy(s->lookup, name, sizeof(s->lookup)); - s->info = info; - - if(fdns_fdinuse >= OptionsItem->dns_fdlimit) - { - fdns_errno = FDNS_ERR_FDLIMIT; - /* Don't add to queue if there is no info */ - if(info == NULL) - { - MyFree(s); - }else{ - node = node_create(s); - list_add(CONNECTIONS, node); - } - return -1; - } + struct s_connection *s; + node_t *node; + int fd; + + s = firedns_add_query(); + s->class = 1; + s->type = type; + s->info = info; + strlcpy(s->lookup, name, sizeof(s->lookup)); + + if (fdns_fdinuse >= OptionsItem->dns_fdlimit) + { + fdns_errno = FDNS_ERR_FDLIMIT; + + /* Don't add to queue if there is no info */ + if (info == NULL) + MyFree(s); + else + { + node = node_create(s); + list_add(CONNECTIONS, node); + } - fd = firedns_doquery(s); + return -1; + } - if(fd == -1) - { - MyFree(s); - return -1; - } + fd = firedns_doquery(s); - node = node_create(s); - list_add(CONNECTIONS, node); - return fd; -} + if (fd == -1) + { + MyFree(s); + return -1; + } -static struct s_connection *firedns_add_query(void) -{ /* build DNS query, add to list */ - struct s_connection *s; + node = node_create(s); + list_add(CONNECTIONS, node); - /* create new connection object */ - s = MyMalloc(sizeof *s); + return fd; +} + +/* build DNS query, add to list */ +static struct s_connection * +firedns_add_query(void) +{ + struct s_connection *s; - /* verified by firedns_getresult() */ - s->id[0] = rand() % 255; - s->id[1] = rand() % 255; + /* create new connection object */ + s = MyMalloc(sizeof *s); - s->fd = -1; + /* verified by firedns_getresult() */ + s->id[0] = rand() % 255; + s->id[1] = rand() % 255; + s->fd = -1; - return s; + return s; } -static int firedns_doquery(struct s_connection *s) +static int +firedns_doquery(struct s_connection *s) { - int len; - struct s_header h; + int len; + struct s_header h; - len = firedns_build_query_payload(s->lookup, s->type, 1, - (unsigned char *)&h.payload); + len = firedns_build_query_payload(s->lookup, s->type, 1, (unsigned char *)&h.payload); - if(len == -1) - { - fdns_errno = FDNS_ERR_FORMAT; - return -1; - } + if (len == -1) + { + fdns_errno = FDNS_ERR_FORMAT; + return -1; + } - return firedns_send_requests(&h, s, len); + return firedns_send_requests(&h, s, len); } /* * populate payload with query: name= question, rr= record type */ -static int firedns_build_query_payload(const char * const name, - uint16_t rr, uint16_t class, unsigned char * payload) +static int +firedns_build_query_payload(const char *const name, uint16_t rr, uint16_t class, + unsigned char *payload) { - int16_t payloadpos; - const char * tempchr, * tempchr2; - uint16_t l; - - payloadpos = 0; - tempchr2 = name; - - /* split name up into labels, create query */ - while ((tempchr = strchr(tempchr2,'.')) != NULL) - { - l = tempchr - tempchr2; - if (payloadpos + l + 1 > 507) - return -1; - payload[payloadpos++] = l; - memcpy(&payload[payloadpos],tempchr2,l); - payloadpos += l; - tempchr2 = &tempchr[1]; - } - l = strlen(tempchr2); - if (l) - { - if (payloadpos + l + 2 > 507) - return -1; - payload[payloadpos++] = l; - memcpy(&payload[payloadpos],tempchr2,l); - payloadpos += l; - payload[payloadpos++] = '\0'; - } - if (payloadpos > 508) + int16_t payloadpos = 0; + const char *tempchr, *tempchr2; + uint16_t l; + + tempchr2 = name; + + /* split name up into labels, create query */ + while ((tempchr = strchr(tempchr2, '.'))) + { + l = tempchr - tempchr2; + + if (payloadpos + l + 1 > 507) + return -1; + + payload[payloadpos++] = l; + memcpy(&payload[payloadpos], tempchr2, l); + payloadpos += l; + tempchr2 = &tempchr[1]; + } + + l = strlen(tempchr2); + + if (l) + { + if (payloadpos + l + 2 > 507) return -1; - l = htons(rr); - memcpy(&payload[payloadpos],&l,2); - l = htons(class); - memcpy(&payload[payloadpos + 2],&l,2); - return payloadpos + 4; + + payload[payloadpos++] = l; + memcpy(&payload[payloadpos], tempchr2, l); + payloadpos += l; + payload[payloadpos++] = '\0'; + } + + if (payloadpos > 508) + return -1; + + l = htons(rr); + memcpy(&payload[payloadpos], &l, 2); + + l = htons(class); + memcpy(&payload[payloadpos + 2], &l, 2); + + return payloadpos + 4; } /* send DNS query */ -static int firedns_send_requests(struct s_header *h, struct s_connection *s, - int l) +static int +firedns_send_requests(struct s_header *h, struct s_connection *s, int l) { - int i, sent_ok = 0; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - - /* set header flags */ - h->flags1 = 0 | FLAGS1_MASK_RD; - h->flags2 = 0; - h->qdcount = htons(1); - h->ancount = htons(0); - h->nscount = htons(0); - h->arcount = htons(0); - memcpy(h->id, s->id, 2); - - /* try to create ipv6 or ipv4 socket */ - s->v6 = 0; - if (i6 > 0) - { - s->fd = socket(PF_INET6, SOCK_DGRAM, 0); - if (s->fd != -1) - { - if (fcntl(s->fd, F_SETFL, O_NONBLOCK) != 0) - { - close(s->fd); - s->fd = -1; - } - } - if (s->fd != -1) + int i, sent_ok = 0; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + + /* set header flags */ + h->flags1 = 0 | FLAGS1_MASK_RD; + h->flags2 = 0; + h->qdcount = htons(1); + h->ancount = htons(0); + h->nscount = htons(0); + h->arcount = htons(0); + memcpy(h->id, s->id, 2); + + /* try to create ipv6 or ipv4 socket */ + s->v6 = 0; + + if (i6 > 0) + { + s->fd = socket(PF_INET6, SOCK_DGRAM, 0); + + if (s->fd != -1) + { + if (fcntl(s->fd, F_SETFL, O_NONBLOCK)) { - struct sockaddr_in6 addr6; - memset(&addr6,0,sizeof(addr6)); - addr6.sin6_family = AF_INET6; - if (bind(s->fd,(struct sockaddr *)&addr6,sizeof(addr6)) == 0) - s->v6 = 1; - else - { - close(s->fd); - } + close(s->fd); + s->fd = -1; } - } - if (s->v6 == 0) - { - s->fd = socket(PF_INET, SOCK_DGRAM, 0); - if (s->fd != -1) - { - if (fcntl(s->fd, F_SETFL, O_NONBLOCK) != 0) - { - close(s->fd); - s->fd = -1; - } - } - if (s->fd != -1) - { - struct sockaddr_in addr; - memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(s->fd,(struct sockaddr *)&addr,sizeof(addr)) != 0) - { - close(s->fd); - s->fd = -1; - } - } - if (s->fd == -1) - { - fdns_errno = FDNS_ERR_NETWORK; - return -1; - } - } + } + + if (s->fd != -1) + { + struct sockaddr_in6 addr6; - /* if we've got ipv6 support, an ip v6 socket, and ipv6 servers, send to them */ - if (i6 > 0 && s->v6 == 1) - { - for (i = 0; i < i6; i++) + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + + if (bind(s->fd, (struct sockaddr *)&addr6, sizeof(addr6)) == 0) + s->v6 = 1; + else + close(s->fd); + } + } + + if (s->v6 == 0) + { + s->fd = socket(PF_INET, SOCK_DGRAM, 0); + + if (s->fd != -1) + { + if (fcntl(s->fd, F_SETFL, O_NONBLOCK)) { - memset(&addr6,0,sizeof(addr6)); - memcpy(&addr6.sin6_addr,&servers6[i],sizeof(addr6.sin6_addr)); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(FDNS_PORT); - if(sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr6, sizeof(addr6)) > 0) - sent_ok = 1; + close(s->fd); + s->fd = -1; } - } + } + + if (s->fd != -1) + { + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = 0; + addr.sin_addr.s_addr = INADDR_ANY; - for (i = 0; i < i4; i++) - { - /* send via ipv4-over-ipv6 if we've got an ipv6 socket */ - if (s->v6 == 1) + if (bind(s->fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - memset(&addr6,0,sizeof(addr6)); - memcpy(addr6.sin6_addr.s6_addr,"\0\0\0\0\0\0\0\0\0\0\xff\xff",12); - memcpy(&addr6.sin6_addr.s6_addr[12],&servers4[i].s_addr,4); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(FDNS_PORT); - if(sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr6, sizeof(addr6)) > 0) - sent_ok = 1; - continue; + close(s->fd); + s->fd = -1; } + } - /* otherwise send via standard ipv4 boringness */ - memset(&addr4,0,sizeof(addr4)); - memcpy(&addr4.sin_addr,&servers4[i],sizeof(addr4.sin_addr)); - addr4.sin_family = AF_INET; - addr4.sin_port = htons(FDNS_PORT); - if(sendto(s->fd, h, l + 12, 0, (struct sockaddr *) &addr4, sizeof(addr4)) > 0) - sent_ok = 1; - } - - if(!sent_ok) - { - close(s->fd); - s->fd = -1; + if (s->fd == -1) + { fdns_errno = FDNS_ERR_NETWORK; return -1; - } - - time(&s->start); - fdns_fdinuse++; - fdns_errno = FDNS_ERR_NONE; - return s->fd; + } + } + + /* if we've got ipv6 support, an ip v6 socket, and ipv6 servers, send to them */ + if (i6 > 0 && s->v6 == 1) + { + for (i = 0; i < i6; i++) + { + memset(&addr6, 0, sizeof(addr6)); + memcpy(&addr6.sin6_addr, &servers6[i], sizeof(addr6.sin6_addr)); + + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(FDNS_PORT); + + if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr6, sizeof(addr6)) > 0) + sent_ok = 1; + } + } + + for (i = 0; i < i4; i++) + { + /* send via ipv4-over-ipv6 if we've got an ipv6 socket */ + if (s->v6 == 1) + { + memset(&addr6, 0, sizeof(addr6)); + memcpy(addr6.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); + memcpy(&addr6.sin6_addr.s6_addr[12], &servers4[i].s_addr, 4); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(FDNS_PORT); + + if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr6, sizeof(addr6)) > 0) + sent_ok = 1; + + continue; + } + + /* otherwise send via standard ipv4 boringness */ + memset(&addr4, 0, sizeof(addr4)); + memcpy(&addr4.sin_addr, &servers4[i], sizeof(addr4.sin_addr)); + addr4.sin_family = AF_INET; + addr4.sin_port = htons(FDNS_PORT); + + if (sendto(s->fd, h, l + 12, 0, (struct sockaddr *)&addr4, sizeof(addr4)) > 0) + sent_ok = 1; + } + + if (!sent_ok) + { + close(s->fd); + s->fd = -1; + fdns_errno = FDNS_ERR_NETWORK; + return -1; + } + + time(&s->start); + fdns_fdinuse++; + fdns_errno = FDNS_ERR_NONE; + + return s->fd; } -struct firedns_result *firedns_getresult(const int fd) -{ /* retrieve result of DNS query */ - static struct firedns_result result; - struct s_header h; - struct s_connection *c; - node_t *node; - int l,i,q,curanswer; - struct s_rr_middle *rr, rrbacking; - char *src, *dst; - int bytes; - - fdns_errno = FDNS_ERR_OTHER; - result.info = (void *) NULL; - memset(result.text, 0, sizeof(result.text)); - - /* Find query in list of dns lookups */ - LIST_FOREACH(node, CONNECTIONS->head) - { - c = node->data; - if(c->fd == fd) - break; +/* retrieve result of DNS query */ +struct firedns_result * +firedns_getresult(const int fd) +{ + static struct firedns_result result; + struct s_header h; + struct s_connection *c; + node_t *node; + int l, i, q, curanswer; + struct s_rr_middle *rr, rrbacking; + char *src, *dst; + int bytes; + + fdns_errno = FDNS_ERR_OTHER; + result.info = NULL; + + memset(result.text, 0, sizeof(result.text)); + + /* Find query in list of dns lookups */ + LIST_FOREACH(node, CONNECTIONS->head) + { + c = node->data; + + if (c->fd == fd) + break; + else + c = NULL; + } + + /* query not found */ + if (c == NULL) + return &result; + + /* query found -- we remove in cleanup */ + l = recv(c->fd, &h,sizeof(struct s_header), 0); + result.info = c->info; + strlcpy(result.lookup, c->lookup, sizeof(result.lookup)); + + if (l == -1) + { + fdns_errno = FDNS_ERR_NETWORK; + goto cleanup; + } + + if (l < 12) + goto cleanup; + + if (c->id[0] != h.id[0] || c->id[1] != h.id[1]) + /* + * ID mismatch: we keep the connection, as this could be an answer to + * a previous lookup.. + */ + return NULL; + + if ((h.flags1 & FLAGS1_MASK_QR) == 0) + goto cleanup; + + if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0) + goto cleanup; + + if ((h.flags2 & FLAGS2_MASK_RCODE) != 0) + { + fdns_errno = (h.flags2 & FLAGS2_MASK_RCODE); + goto cleanup; + } + + h.ancount = ntohs(h.ancount); + + if (h.ancount < 1) + { + fdns_errno = FDNS_ERR_NXDOMAIN; + /* no sense going on if we don't have any answers */ + goto cleanup; + } + + /* skip queries */ + i = 0; + q = 0; + l -= 12; + h.qdcount = ntohs(h.qdcount); + + while (q < h.qdcount && i < l) + { + if (h.payload[i] > 63) + { + /* pointer */ + i += 6; /* skip pointer, class and type */ + q++; + } + else + { + /* label */ + if (h.payload[i] == 0) + { + q++; + i += 5; /* skip nil, class and type */ + } else - c = NULL; - } - - /* query not found */ - if(c == NULL) - return &result; - - /* query found -- we remove in cleanup */ + i += h.payload[i] + 1; /* skip length and label */ + } + } - l = recv(c->fd,&h,sizeof(struct s_header),0); - result.info = (void *) c->info; - strlcpy(result.lookup, c->lookup, sizeof(result.lookup)); + /* &h.payload[i] should now be the start of the first response */ + curanswer = 0; - if(l == -1) - { - fdns_errno = FDNS_ERR_NETWORK; - goto cleanup; - } + while (curanswer < h.ancount) + { + q = 0; - if (l < 12) - goto cleanup; - if (c->id[0] != h.id[0] || c->id[1] != h.id[1]) - /* ID mismatch: we keep the connection, as this could be an answer to - a previous lookup.. */ - return NULL; - if ((h.flags1 & FLAGS1_MASK_QR) == 0) - goto cleanup; - if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0) - goto cleanup; - if ((h.flags2 & FLAGS2_MASK_RCODE) != 0) - { - fdns_errno = (h.flags2 & FLAGS2_MASK_RCODE); - goto cleanup; - } - h.ancount = ntohs(h.ancount); - if (h.ancount < 1) { - fdns_errno = FDNS_ERR_NXDOMAIN; - /* no sense going on if we don't have any answers */ - goto cleanup; - } - /* skip queries */ - i = 0; - q = 0; - l -= 12; - h.qdcount = ntohs(h.qdcount); - while (q < h.qdcount && i < l) - { + while (q == 0 && i < l) + { if (h.payload[i] > 63) - { /* pointer */ - i += 6; /* skip pointer, class and type */ - q++; - } - else - { /* label */ - if (h.payload[i] == 0) - { - q++; - i += 5; /* skip nil, class and type */ - } - else - i += h.payload[i] + 1; /* skip length and label */ - } - } - /* &h.payload[i] should now be the start of the first response */ - curanswer = 0; - while (curanswer < h.ancount) - { - q = 0; - while (q == 0 && i < l) - { - if (h.payload[i] > 63) - { /* pointer */ - i += 2; /* skip pointer */ - q = 1; - } - else - { /* label */ - if (h.payload[i] == 0) - { - i++; - q = 1; - } - else - i += h.payload[i] + 1; /* skip length and label */ - } - } - if (l - i < 10) - goto cleanup; - rr = (struct s_rr_middle *)&h.payload[i]; - src = (char *) rr; - dst = (char *) &rrbacking; - for (bytes = sizeof(rrbacking); bytes; bytes--) - *dst++ = *src++; - rr = &rrbacking; - i += 10; - rr->rdlength = ntohs(rr->rdlength); - if (ntohs(rr->type) != c->type) { - curanswer++; - i += rr->rdlength; - continue; + /* pointer */ + i += 2; /* skip pointer */ + q = 1; } - if (ntohs(rr->class) != c->class) + else { - curanswer++; - i += rr->rdlength; - continue; + /* label */ + if (h.payload[i] == 0) + { + i++; + q = 1; + } + else + i += h.payload[i] + 1; /* skip length and label */ } - break; - } + } - if (curanswer == h.ancount) - goto cleanup; - if (i + rr->rdlength > l) + if (l - i < 10) goto cleanup; - if (rr->rdlength > 1023) - goto cleanup; - - fdns_errno = FDNS_ERR_NONE; - memcpy(result.text,&h.payload[i],rr->rdlength); - result.text[rr->rdlength] = '\0'; - /* Clean-up */ + rr = (struct s_rr_middle *)&h.payload[i]; + src = (char *)rr; + dst = (char *)&rrbacking; + + for (bytes = sizeof(rrbacking); bytes; bytes--) + *dst++ = *src++; + + rr = &rrbacking; + i += 10; + rr->rdlength = ntohs(rr->rdlength); + + if (ntohs(rr->type) != c->type) + { + curanswer++; + i += rr->rdlength; + continue; + } + + if (ntohs(rr->class) != c->class) + { + curanswer++; + i += rr->rdlength; + continue; + } + + break; + } + + if (curanswer == h.ancount) + goto cleanup; + if (i + rr->rdlength > l) + goto cleanup; + if (rr->rdlength > 1023) + goto cleanup; + + fdns_errno = FDNS_ERR_NONE; + memcpy(result.text, &h.payload[i], rr->rdlength); + result.text[rr->rdlength] = '\0'; + +/* Clean-up */ cleanup: - list_remove(CONNECTIONS, node); - node_free(node); - close(c->fd); - fdns_fdinuse--; - MyFree(c); + list_remove(CONNECTIONS, node); + node_free(node); + close(c->fd); + fdns_fdinuse--; + MyFree(c); - return &result; + return &result; } -void firedns_cycle(void) +void +firedns_cycle(void) { - node_t *node, *next; - struct s_connection *p; - struct firedns_result *res, new_result; - static struct pollfd *ufds = NULL; - int fd; - unsigned int size, i; - time_t timenow; - - if(LIST_SIZE(CONNECTIONS) == 0) - return; - - if(ufds == NULL) - ufds = MyMalloc((sizeof *ufds) * OptionsItem->dns_fdlimit); + node_t *node, *next; + struct s_connection *p; + struct firedns_result *res, new_result; + static struct pollfd *ufds = NULL; + int fd; + unsigned int size, i; + time_t timenow; + + if (LIST_SIZE(CONNECTIONS) == 0) + return; + + if (ufds == NULL) + ufds = MyMalloc((sizeof *ufds) * OptionsItem->dns_fdlimit); + + time(&timenow); + size = 0; + + LIST_FOREACH_SAFE(node, next, CONNECTIONS->head) + { + if (size >= OptionsItem->dns_fdlimit) + break; - time(&timenow); - size = 0; + p = node->data; - LIST_FOREACH_SAFE(node, next, CONNECTIONS->head) - { - if(size >= OptionsItem->dns_fdlimit) - break; + if (p->fd < 0) + continue; - p = node->data; + if (p->fd > 0 && (p->start + FDNS_TIMEOUT) < timenow) + { + /* Timed out - remove from list */ + list_remove(CONNECTIONS, node); + node_free(node); - if(p->fd < 0) - continue; + memset(new_result.text, 0, sizeof(new_result.text)); + new_result.info = p->info; + strlcpy(new_result.lookup, p->lookup, sizeof(new_result.lookup)); - if(p->fd > 0 && (p->start + FDNS_TIMEOUT) < timenow) - { - /* Timed out - remove from list */ - list_remove(CONNECTIONS, node); - node_free(node); + close(p->fd); + fdns_fdinuse--; + MyFree(p); - memset(new_result.text, 0, sizeof(new_result.text)); - new_result.info = p->info; - strlcpy(new_result.lookup, p->lookup, sizeof(new_result.lookup)); + fdns_errno = FDNS_ERR_TIMEOUT; - close(p->fd); - fdns_fdinuse--; - MyFree(p); + if (new_result.info) + dnsbl_result(&new_result); - fdns_errno = FDNS_ERR_TIMEOUT; + continue; + } - if(new_result.info != NULL) - dnsbl_result(&new_result); + ufds[size].events = 0; + ufds[size].revents = 0; + ufds[size].fd = p->fd; + ufds[size].events = POLLIN; - continue; - } + size++; + } - ufds[size].events = 0; - ufds[size].revents = 0; - ufds[size].fd = p->fd; - ufds[size].events = POLLIN; + switch (poll(ufds, size, 0)) + { + case -1: + case 0: + return; + } - size++; - } + LIST_FOREACH_SAFE(node, next, CONNECTIONS->head) + { + p = node->data; + if (p->fd > 0) + { + for (i = 0; i < size; i++) + { + if ((ufds[i].revents & POLLIN) && ufds[i].fd == p->fd) + { + fd = p->fd; + res = firedns_getresult(fd); - switch(poll(ufds, size, 0)) - { - case -1: - case 0: - return; - } + if (res && res->info) + dnsbl_result(res); - LIST_FOREACH_SAFE(node, next, CONNECTIONS->head) - { - p = node->data; - if(p->fd > 0) - { - for(i = 0; i < size; i++) - { - if((ufds[i].revents & POLLIN) && ufds[i].fd == p->fd) - { - fd = p->fd; - res = firedns_getresult(fd); - - if(res != NULL && res->info != NULL) - dnsbl_result(res); - break; - } - } - } - else if(fdns_fdinuse < OptionsItem->dns_fdlimit) - { - firedns_doquery(p); + break; + } } - } + } + else if (fdns_fdinuse < OptionsItem->dns_fdlimit) + firedns_doquery(p); + } } -const char *firedns_strerror(int error) +const char * +firedns_strerror(int error) { - if(error == FDNS_ERR_NETWORK) - return strerror(errno); - return errors[error]; -} + if (error == FDNS_ERR_NETWORK) + return strerror(errno); + return errors[error]; +} -- 2.30.2