@@ -15,10 +15,11 @@ * file. */ #include "config.h" +#include #include #include "unistd_wrapper.h" #import "OFDNSResolver.h" #import "OFArray.h" @@ -96,10 +97,11 @@ size_t _attempt; id _target; SEL _selector; id _context; OFData *_queryData; + of_socket_address_t _usedNameServer; OFTimer *_cancelTimer; } - (instancetype)initWithHost: (OFString *)host domainName: (OFString *)domainName @@ -1075,11 +1077,10 @@ objc_autoreleasePoolPop(pool); } - (void)of_sendQuery: (OFDNSResolverQuery *)query { - of_socket_address_t address; OFUDPSocket *sock; [query->_cancelTimer invalidate]; [query->_cancelTimer release]; query->_cancelTimer = nil; @@ -1088,14 +1089,14 @@ target: self selector: @selector(of_queryWithIDTimedOut:) object: query repeats: false] retain]; - address = of_socket_address_parse_ip( + query->_usedNameServer = of_socket_address_parse_ip( [query->_nameServers objectAtIndex: query->_nameServersIndex], 53); - switch (address.family) { + switch (query->_usedNameServer.family) { #ifdef OF_HAVE_IPV6 case OF_SOCKET_ADDRESS_FAMILY_IPV6: if (_IPv6Socket == nil) { _IPv6Socket = [[OFUDPSocket alloc] init]; [_IPv6Socket bindToHost: @"::" @@ -1120,11 +1121,11 @@ @throw [OFInvalidArgumentException exception]; } [sock asyncSendBuffer: [query->_queryData items] length: [query->_queryData count] - receiver: address + receiver: query->_usedNameServer target: self selector: @selector(of_socket:didSendBuffer:bytesSent: receiver:context:exception:) context: query]; } @@ -1200,22 +1201,29 @@ OFArray *answerRecords = nil, *authorityRecords = nil; OFArray *additionalRecords = nil; OFNumber *ID; OFDNSResolverQuery *query; - if (exception != nil) + if (exception != nil) { + if ([exception respondsToSelector: @selector(errNo)]) + return ([exception errNo] == EINTR); + return false; + } if (length < 2) - /* We can't get the ID to get the query. Give up. */ - return false; + /* We can't get the ID to get the query. Ignore packet. */ + return true; ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]]; query = [[[_queries objectForKey: ID] retain] autorelease]; if (query == nil) - return false; + return true; + + if (!of_socket_address_equal(&sender, &query->_usedNameServer)) + return true; [query->_cancelTimer invalidate]; [query->_cancelTimer release]; query->_cancelTimer = nil; [_queries removeObjectForKey: ID];