94 |
|
|
95 |
|
struct reslist |
96 |
|
{ |
97 |
< |
dlink_node node; /**< Doubly linked list node. */ |
98 |
< |
int id; /**< Request ID (from request header). */ |
99 |
< |
int sent; /**< Number of requests sent */ |
100 |
< |
request_state state; /**< State the resolver machine is in */ |
101 |
< |
char type; /**< Current request type. */ |
102 |
< |
char retries; /**< Retry counter */ |
103 |
< |
unsigned int sends; /**< Number of sends (>1 means resent). */ |
104 |
< |
char resend; /**< Send flag; 0 == don't resend. */ |
105 |
< |
time_t sentat; /**< Timestamp we last sent this request. */ |
106 |
< |
time_t timeout; /**< When this request times out. */ |
107 |
< |
struct irc_ssaddr addr; /**< Address for this request. */ |
108 |
< |
char *name; /**< Hostname for this request. */ |
109 |
< |
dns_callback_fnc callback; /**< Callback function on completion. */ |
110 |
< |
void *callback_ctx; /**< Context pointer for callback. */ |
97 |
> |
dlink_node node; /**< Doubly linked list node. */ |
98 |
> |
int id; /**< Request ID (from request header). */ |
99 |
> |
int sent; /**< Number of requests sent */ |
100 |
> |
request_state state; /**< State the resolver machine is in */ |
101 |
> |
char type; /**< Current request type. */ |
102 |
> |
char retries; /**< Retry counter */ |
103 |
> |
unsigned int sends; /**< Number of sends (>1 means resent). */ |
104 |
> |
char resend; /**< Send flag; 0 == don't resend. */ |
105 |
> |
time_t sentat; /**< Timestamp we last sent this request. */ |
106 |
> |
time_t timeout; /**< When this request times out. */ |
107 |
> |
struct irc_ssaddr addr; /**< Address for this request. */ |
108 |
> |
char name[RFC1035_MAX_DOMAIN_LENGTH]; /**< Hostname for this request. */ |
109 |
> |
size_t namelength; /**< Actual hostname length. */ |
110 |
> |
dns_callback_fnc callback; /**< Callback function on completion. */ |
111 |
> |
void *callback_ctx; /**< Context pointer for callback. */ |
112 |
|
}; |
113 |
|
|
114 |
|
static fde_t ResolverFileDescriptor; |
125 |
|
rem_request(struct reslist *request) |
126 |
|
{ |
127 |
|
dlinkDelete(&request->node, &request_list); |
127 |
– |
|
128 |
– |
MyFree(request->name); |
128 |
|
mp_pool_release(request); |
129 |
|
} |
130 |
|
|
344 |
|
do_query_name(dns_callback_fnc callback, void *ctx, const char *name, |
345 |
|
struct reslist *request, int type) |
346 |
|
{ |
347 |
< |
char host_name[HOSTLEN + 1]; |
347 |
> |
char host_name[RFC1035_MAX_DOMAIN_LENGTH + 1]; |
348 |
|
|
349 |
|
strlcpy(host_name, name, sizeof(host_name)); |
350 |
|
|
351 |
|
if (request == NULL) |
352 |
|
{ |
353 |
< |
request = make_request(callback, ctx); |
354 |
< |
request->name = MyCalloc(strlen(host_name) + 1); |
355 |
< |
request->type = type; |
357 |
< |
strcpy(request->name, host_name); |
353 |
> |
request = make_request(callback, ctx); |
354 |
> |
request->type = type; |
355 |
> |
request->namelength = strlcpy(request->name, host_name, sizeof(request->name)); |
356 |
|
#ifdef IPV6 |
357 |
|
if (type != T_A) |
358 |
|
request->state = REQ_AAAA; |
416 |
|
request = make_request(callback, ctx); |
417 |
|
request->type = T_PTR; |
418 |
|
memcpy(&request->addr, addr, sizeof(struct irc_ssaddr)); |
421 |
– |
request->name = MyCalloc(HOSTLEN + 1); |
419 |
|
} |
420 |
|
|
421 |
|
query_name(ipbuf, C_IN, T_PTR, request); |
484 |
|
static int |
485 |
|
proc_answer(struct reslist *request, HEADER *header, char *buf, char *eob) |
486 |
|
{ |
487 |
< |
char hostbuf[HOSTLEN + 100]; /* working buffer */ |
487 |
> |
char hostbuf[RFC1035_MAX_DOMAIN_LENGTH + 100]; /* working buffer */ |
488 |
|
unsigned char *current; /* current position in buf */ |
489 |
|
int type; /* answer type */ |
490 |
|
int n; /* temp count */ |
516 |
|
if (n < 0 /* Broken message */ || n == 0 /* No more answers left */) |
517 |
|
return 0; |
518 |
|
|
519 |
< |
hostbuf[HOSTLEN] = '\0'; |
519 |
> |
hostbuf[RFC1035_MAX_DOMAIN_LENGTH] = '\0'; |
520 |
|
|
521 |
|
/* |
522 |
|
* With Address arithmetic you have to be very anal |
580 |
|
if (n < 0 /* Broken message */ || n == 0 /* No more answers left */) |
581 |
|
return 0; |
582 |
|
|
583 |
< |
strlcpy(request->name, hostbuf, HOSTLEN + 1); |
583 |
> |
request->namelength = strlcpy(request->name, hostbuf, sizeof(request->name)); |
584 |
|
return 1; |
585 |
|
break; |
586 |
|
case T_CNAME: /* First check we already haven't started looking into a cname */ |
627 |
|
socklen_t len = sizeof(struct irc_ssaddr); |
628 |
|
struct irc_ssaddr lsin; |
629 |
|
|
630 |
< |
rc = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len); |
631 |
< |
|
632 |
< |
/* |
633 |
< |
* Re-schedule a read *after* recvfrom, or we'll be registering |
637 |
< |
* interest where it'll instantly be ready for read :-) -- adrian |
638 |
< |
*/ |
639 |
< |
comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0); |
640 |
< |
|
641 |
< |
if (rc <= (ssize_t)sizeof(HEADER)) |
642 |
< |
return; |
630 |
> |
while ((rc = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len)) != -1) |
631 |
> |
{ |
632 |
> |
if (rc <= (ssize_t)sizeof(HEADER)) |
633 |
> |
continue; |
634 |
|
|
635 |
< |
/* |
636 |
< |
* Check against possibly fake replies |
637 |
< |
*/ |
638 |
< |
if (!res_ourserver(&lsin)) |
639 |
< |
return; |
635 |
> |
/* |
636 |
> |
* Check against possibly fake replies |
637 |
> |
*/ |
638 |
> |
if (!res_ourserver(&lsin)) |
639 |
> |
continue; |
640 |
|
|
641 |
< |
/* |
642 |
< |
* Convert DNS reply reader from Network byte order to CPU byte order. |
643 |
< |
*/ |
644 |
< |
header = (HEADER *)buf; |
645 |
< |
header->ancount = ntohs(header->ancount); |
646 |
< |
header->qdcount = ntohs(header->qdcount); |
647 |
< |
header->nscount = ntohs(header->nscount); |
648 |
< |
header->arcount = ntohs(header->arcount); |
641 |
> |
/* |
642 |
> |
* Convert DNS reply reader from Network byte order to CPU byte order. |
643 |
> |
*/ |
644 |
> |
header = (HEADER *)buf; |
645 |
> |
header->ancount = ntohs(header->ancount); |
646 |
> |
header->qdcount = ntohs(header->qdcount); |
647 |
> |
header->nscount = ntohs(header->nscount); |
648 |
> |
header->arcount = ntohs(header->arcount); |
649 |
|
|
650 |
< |
/* |
651 |
< |
* Response for an id which we have already received an answer for |
652 |
< |
* just ignore this response. |
653 |
< |
*/ |
654 |
< |
if ((request = find_id(header->id)) == NULL) |
655 |
< |
return; |
650 |
> |
/* |
651 |
> |
* Response for an id which we have already received an answer for |
652 |
> |
* just ignore this response. |
653 |
> |
*/ |
654 |
> |
if ((request = find_id(header->id)) == NULL) |
655 |
> |
continue; |
656 |
|
|
657 |
< |
if ((header->rcode != NO_ERRORS) || (header->ancount == 0)) |
667 |
< |
{ |
668 |
< |
if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN) |
657 |
> |
if ((header->rcode != NO_ERRORS) || (header->ancount == 0)) |
658 |
|
{ |
659 |
< |
/* |
660 |
< |
* If a bad error was returned, stop here and don't |
661 |
< |
* send any more (no retries granted). |
662 |
< |
*/ |
663 |
< |
(*request->callback)(request->callback_ctx, NULL, NULL); |
664 |
< |
rem_request(request); |
665 |
< |
} |
659 |
> |
if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN) |
660 |
> |
{ |
661 |
> |
/* |
662 |
> |
* If a bad error was returned, stop here and don't |
663 |
> |
* send any more (no retries granted). |
664 |
> |
*/ |
665 |
> |
(*request->callback)(request->callback_ctx, NULL, NULL, 0); |
666 |
> |
rem_request(request); |
667 |
> |
} |
668 |
|
#ifdef IPV6 |
669 |
< |
else |
679 |
< |
{ |
680 |
< |
/* |
681 |
< |
* If we havent already tried this, and we're looking up AAAA, try A now. |
682 |
< |
*/ |
683 |
< |
if (request->state == REQ_AAAA && request->type == T_AAAA) |
669 |
> |
else |
670 |
|
{ |
671 |
< |
request->timeout += 4; |
672 |
< |
resend_query(request); |
671 |
> |
/* |
672 |
> |
* If we havent already tried this, and we're looking up AAAA, try A now. |
673 |
> |
*/ |
674 |
> |
if (request->state == REQ_AAAA && request->type == T_AAAA) |
675 |
> |
{ |
676 |
> |
request->timeout += 4; |
677 |
> |
resend_query(request); |
678 |
> |
} |
679 |
|
} |
688 |
– |
} |
680 |
|
#endif |
681 |
+ |
continue; |
682 |
+ |
} |
683 |
|
|
684 |
< |
return; |
685 |
< |
} |
684 |
> |
/* |
685 |
> |
* If this fails there was an error decoding the received packet. |
686 |
> |
* We only give it one shot. If it fails, just leave the client |
687 |
> |
* unresolved. |
688 |
> |
*/ |
689 |
> |
if (!proc_answer(request, header, buf, buf + rc)) |
690 |
> |
{ |
691 |
> |
(*request->callback)(request->callback_ctx, NULL, NULL, 0); |
692 |
> |
rem_request(request); |
693 |
> |
continue; |
694 |
> |
} |
695 |
|
|
694 |
– |
/* |
695 |
– |
* If this fails there was an error decoding the received packet, |
696 |
– |
* try it again and hope it works the next time. |
697 |
– |
*/ |
698 |
– |
if (proc_answer(request, header, buf, buf + rc)) |
699 |
– |
{ |
696 |
|
if (request->type == T_PTR) |
697 |
|
{ |
698 |
< |
if (request->name == NULL) |
698 |
> |
if (request->namelength == 0) |
699 |
|
{ |
700 |
|
/* |
701 |
|
* Got a PTR response with no name, something bogus is happening |
702 |
|
* don't bother trying again, the client address doesn't resolve |
703 |
|
*/ |
704 |
< |
(*request->callback)(request->callback_ctx, NULL, NULL); |
704 |
> |
(*request->callback)(request->callback_ctx, NULL, NULL, 0); |
705 |
|
rem_request(request); |
706 |
< |
return; |
706 |
> |
continue; |
707 |
|
} |
708 |
|
|
709 |
|
/* |
722 |
|
/* |
723 |
|
* Got a name and address response, client resolved |
724 |
|
*/ |
725 |
< |
(*request->callback)(request->callback_ctx, &request->addr, request->name); |
725 |
> |
(*request->callback)(request->callback_ctx, &request->addr, request->name, request->namelength); |
726 |
|
rem_request(request); |
727 |
|
} |
732 |
– |
} |
733 |
– |
else if (!request->sent) |
734 |
– |
{ |
735 |
– |
/* XXX - we got a response for a query we didn't send with a valid id? |
736 |
– |
* this should never happen, bail here and leave the client unresolved |
737 |
– |
*/ |
738 |
– |
assert(0); |
728 |
|
|
729 |
< |
(*request->callback)(request->callback_ctx, NULL, NULL); |
741 |
< |
/* XXX don't leak it */ |
742 |
< |
rem_request(request); |
729 |
> |
continue; |
730 |
|
} |
731 |
+ |
|
732 |
+ |
comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0); |
733 |
|
} |
734 |
|
|
735 |
|
void |
767 |
|
{ |
768 |
|
if (--request->retries <= 0) |
769 |
|
{ |
770 |
< |
(*request->callback)(request->callback_ctx, NULL, NULL); |
770 |
> |
(*request->callback)(request->callback_ctx, NULL, NULL, 0); |
771 |
|
rem_request(request); |
772 |
|
continue; |
773 |
|
} |