Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -130,15 +130,27 @@ * @brief Asynchronously resolves the specified host. * * @param host The host to resolve * @param target The target to call with the result once resolving is done * @param selector The selector to call on the target. The signature must be - * `void (OFDNSResolver *resolver, + * `void (OFDNSResolver *resolver, OFString *domainName, * nullable OFArray *answerRecords, * nullable OFArray *authorityRecords, * nullable OFArray *additionalRecords, - * nullable id context, nullable id exception)`. + * nullable id context, nullable id exception)`.@n + * `resolver` is the acting resolver.@n + * `domainName` is the fully qualified domain name used to + * resolve the host.@n + * `answerRecords` are the answer records from the name server. + * @n + * `authorityRecords` are the authority records from the name + * server.@n + * `additionalRecords` are additional records sent by the name + * server. + * `context` is the context object originally passed.@n + * `exception` is an exception that happened during resolving, + * otherwise nil. * @param context A context object to pass along to the target */ - (void)asyncResolveHost: (OFString *)host target: (id)target selector: (SEL)selector @@ -150,12 +162,27 @@ * @param host The host to resolve * @param recordClass The desired class of the records to query * @param recordType The desired type of the records to query * @param target The target to call with the result once resolving is done * @param selector The selector to call on the target. The signature must be - * `void (OFArray *response, id context, - * id exception)`. + * `void (OFDNSResolver *resolver, OFString *domainName, + * nullable OFArray *answerRecords, + * nullable OFArray *authorityRecords, + * nullable OFArray *additionalRecords, + * nullable id context, nullable id exception)`.@n + * `resolver` is the acting resolver.@n + * `domainName` is the fully qualified domain name used to + * resolve the host.@n + * `answerRecords` are the answer records from the name server. + * @n + * `authorityRecords` are the authority records from the name + * server.@n + * `additionalRecords` are additional records sent by the name + * server. + * `context` is the context object originally passed.@n + * `exception` is an exception that happened during resolving, + * otherwise nil. * @param context A context object to pass along to the target */ - (void)asyncResolveHost: (OFString *)host recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -66,11 +66,11 @@ * - Fallback to TCP */ @interface OFDNSResolverQuery: OFObject { - OFString *_host; + OFString *_host, *_domainName; of_dns_resource_record_class_t _recordClass; of_dns_resource_record_type_t _recordType; OFNumber *_ID; OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains; size_t _nameServersIndex, _searchDomainsIndex; @@ -80,11 +80,11 @@ id _context; OFData *_queryData; OFTimer *_cancelTimer; } -@property (readonly, nonatomic) OFString *host; +@property (readonly, nonatomic) OFString *host, *domainName; @property (readonly, nonatomic) of_dns_resource_record_class_t recordClass; @property (readonly, nonatomic) of_dns_resource_record_type_t recordType; @property (readonly, nonatomic) OFNumber *ID; @property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers; @property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains; @@ -96,10 +96,11 @@ @property (readonly, nonatomic) id context; @property (readonly, nonatomic) OFData *queryData; @property (retain, nonatomic) OFTimer *cancelTimer; - (instancetype)initWithHost: (OFString *)host + domainName: (OFString *)domainName recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType ID: (OFNumber *)ID nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains @@ -501,32 +502,33 @@ return ret; } static void callback(id target, SEL selector, OFDNSResolver *resolver, - OFArray *answerRecords, OFArray *authorityRecords, + OFString *domainName, OFArray *answerRecords, OFArray *authorityRecords, OFArray *additionalRecords, id context, id exception) { - void (*method)(id, SEL, OFDNSResolver *, OFArray *, OFArray *, - OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *, OFArray *, - OFArray *, OFArray *, id, id)) + void (*method)(id, SEL, OFDNSResolver *, OFString *, OFArray *, + OFArray *, OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *, + OFString *, OFArray *, OFArray *, OFArray *, id, id)) [target methodForSelector: selector]; - method(target, selector, resolver, answerRecords, authorityRecords, - additionalRecords, context, exception); + method(target, selector, resolver, domainName, answerRecords, + authorityRecords, additionalRecords, context, exception); } @implementation OFDNSResolverQuery -@synthesize host = _host, recordClass = _recordClass, recordType = _recordType; -@synthesize ID = _ID, nameServers = _nameServers; +@synthesize host = _host, domainName = _domainName, recordClass = _recordClass; +@synthesize recordType = _recordType, ID = _ID, nameServers = _nameServers; @synthesize searchDomains = _searchDomains; @synthesize nameServersIndex = _nameServersIndex; @synthesize searchDomainsIndex = _searchDomainsIndex, attempt = _attempt; @synthesize target = _target, selector = _selector, context = _context; @synthesize queryData = _queryData, cancelTimer = _cancelTimer; - (instancetype)initWithHost: (OFString *)host + domainName: (OFString *)domainName recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType ID: (OFNumber *)ID nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains @@ -540,10 +542,11 @@ void *pool = objc_autoreleasePoolPush(); OFMutableData *queryData; uint16_t tmp; _host = [host copy]; + _domainName = [domainName copy]; _recordClass = recordClass; _recordType = recordType; _ID = [ID retain]; _nameServers = [nameServers copy]; _searchDomains = [searchDomains copy]; @@ -574,11 +577,11 @@ /* Question */ /* QNAME */ for (OFString *component in - [host componentsSeparatedByString: @"."]) { + [domainName componentsSeparatedByString: @"."]) { size_t length = [component UTF8StringLength]; uint8_t length8; if (length > 63 || [queryData count] + length > 512) @throw [OFOutOfRangeException exception]; @@ -613,10 +616,11 @@ } - (void)dealloc { [_host release]; + [_domainName release]; [_ID release]; [_nameServers release]; [_searchDomains release]; [_target release]; [_context release]; @@ -975,26 +979,30 @@ selector: (SEL)selector context: (id)context { void *pool = objc_autoreleasePoolPush(); OFNumber *ID; + OFString *domainName; OFDNSResolverQuery *query; - /* TODO: Properly try all search domains */ - if (![host hasSuffix: @"."]) - host = [host stringByAppendingString: @"."]; - - if ([host UTF8StringLength] > 253) - @throw [OFOutOfRangeException exception]; - /* Random, unused ID */ do { ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; } while ([_queries objectForKey: ID] != nil); + if ([host hasSuffix: @"."]) + domainName = host; + else + /* TODO: Properly try all search domains */ + domainName = [host stringByAppendingString: @"."]; + + if ([domainName UTF8StringLength] > 253) + @throw [OFOutOfRangeException exception]; + query = [[[OFDNSResolverQuery alloc] initWithHost: host + domainName: domainName recordClass: recordClass recordType: recordType ID: ID nameServers: _nameServers searchDomains: _searchDomains @@ -1061,12 +1069,10 @@ context: query]; } - (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query { - id target, context; - SEL selector; OFResolveHostFailedException *exception; if (query == nil) return; @@ -1081,23 +1087,21 @@ [query setNameServersIndex: 0]; [self of_sendQuery: query]; return; } - target = [[[query target] retain] autorelease]; - selector = [query selector]; - context = [[[query context] retain] autorelease]; + query = [[query retain] autorelease]; + [_queries removeObjectForKey: [query ID]]; exception = [OFResolveHostFailedException exceptionWithHost: [query host] recordClass: [query recordClass] recordType: [query recordType] error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; - [_queries removeObjectForKey: [query ID]]; - - callback(target, selector, self, nil, nil, nil, context, exception); + callback([query target], [query selector], self, [query domainName], + nil, nil, nil, [query context], exception); } - (size_t)of_socket: (OFUDPSocket *)sock didSendBuffer: (void **)buffer bytesSent: (size_t)bytesSent @@ -1104,17 +1108,15 @@ receiver: (of_socket_address_t *)receiver context: (OFDNSResolverQuery *)query exception: (id)exception { if (exception != nil) { - id target = [[[query target] retain] autorelease]; - SEL selector = [query selector]; - id context = [[[query context] retain] autorelease]; - + query = [[query retain] autorelease]; [_queries removeObjectForKey: [query ID]]; - callback(target, selector, self, nil, nil, nil, context, + callback([query target], [query selector], self, + [query domainName], nil, nil, nil, [query context], exception); return 0; } @@ -1239,17 +1241,18 @@ authorityRecords = parseSection(buffer, length, &i, numAuthorityRecords); additionalRecords = parseSection(buffer, length, &i, numAdditionalRecords); } @catch (id e) { - callback([query target], [query selector], self, nil, nil, nil, - [query context], e); + callback([query target], [query selector], self, + [query domainName], nil, nil, nil, [query context], e); return false; } - callback([query target], [query selector], self, answerRecords, - authorityRecords, additionalRecords, [query context], nil); + callback([query target], [query selector], self, [query domainName], + answerRecords, authorityRecords, additionalRecords, + [query context], nil); return false; } - (void)close @@ -1276,14 +1279,15 @@ exceptionWithHost: [query host] recordClass: [query recordClass] recordType: [query recordType] error: OF_DNS_RESOLVER_ERROR_CANCELED]; - callback([query target], [query selector], self, nil, nil, nil, - [query context], exception); + callback([query target], [query selector], self, + [query domainName], nil, nil, nil, [query context], + exception); } [_queries removeAllObjects]; objc_autoreleasePoolPop(pool); } @end Index: utils/ofdns/OFDNS.m ================================================================== --- utils/ofdns/OFDNS.m +++ utils/ofdns/OFDNS.m @@ -26,26 +26,28 @@ @end OF_APPLICATION_DELEGATE(OFDNS) @implementation OFDNS -- (void)DNSResolver: (OFDNSResolver *)resolver - didReceiveAnswerRecords: (OFArray *)answerRecords - authorityRecords: (OFArray *)authorityRecords - additionalRecords: (OFArray *)additionalRecords - context: (id)context - exception: (id)exception +- (void)DNSResolver: (OFDNSResolver *)resolver + didResolveDomainName: (OFString *)domainName + answerRecords: (OFArray *)answerRecords + authorityRecords: (OFArray *)authorityRecords + additionalRecords: (OFArray *)additionalRecords + context: (id)context + exception: (id)exception { if (exception != nil) { [of_stderr writeFormat: @"Failed to resolve: %@\n", exception]; [OFApplication terminateWithStatus: 1]; } - [of_stdout writeFormat: @"Answer records: %@\n" + [of_stdout writeFormat: @"FQDN: %@\n" + @"Answer records: %@\n" @"Authority records: %@\n" @"Additional records: %@\n", - answerRecords, authorityRecords, + domainName, answerRecords, authorityRecords, additionalRecords]; [OFApplication terminate]; } @@ -81,12 +83,11 @@ [resolver asyncResolveHost: [arguments objectAtIndex: 0] recordClass: recordClass recordType: recordType target: self - selector: @selector(DNSResolver: - didReceiveAnswerRecords: - authorityRecords:additionalRecords: - context:exception:) + selector: @selector(DNSResolver:didResolveDomainName: + answerRecords:authorityRecords: + additionalRecords:context:exception:) context: nil]; } @end