ObjFW  Diff

Differences From Artifact [c86401e34e]:

To Artifact [3f193a223c]:


75
76
77
78
79
80
81
82
83
84
















85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

/*
 * TODO:
 *
 *  - Resolve with each search domain
 *  - Fallback to TCP
 */

















@interface OFDNSResolverQuery: OFObject
{
@public
	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;
	of_time_interval_t _timeout;
	unsigned int _maxAttempts;
	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
		 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
	    nameServersIndex: (size_t)nameServersIndex
	       searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
	  searchDomainsIndex: (size_t)searchDomainsIndex
		     timeout: (of_time_interval_t)timeout
		 maxAttempts: (unsigned int)maxAttempts
		      target: (id)target
		    selector: (SEL)selector
		     context: (id)context;
@end

@interface OFDNSResolver ()
- (void)of_setDefaults;







<


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|

<
|
<













|

<

<
<







75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126


127
128
129
130
131
132
133
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

/*
 * TODO:
 *

 *  - Fallback to TCP
 */

@interface OFDNSResolverSettings: OFObject
{
@public
	OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
	of_time_interval_t _timeout;
	unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
}

- (instancetype)
	      initWithNameServers: (OFArray *)nameServers
		    searchDomains: (OFArray *)searchDomains
			  timeout: (of_time_interval_t)timeout
		      maxAttempts: (unsigned int)maxAttempts
    minNumberOfDotsInAbsoluteName: (unsigned int)minNumberOfDotsInAbsoluteName;
@end

@interface OFDNSResolverQuery: OFObject
{
@public
	OFString *_host, *_domainName;
	of_dns_resource_record_class_t _recordClass;
	of_dns_resource_record_type_t _recordType;
	OFNumber *_ID;
	OFDNSResolverSettings *_settings;
	size_t _nameServersIndex, _searchDomainsIndex;

	unsigned int _attempt;

	id _target;
	SEL _selector;
	id _context;
	OFData *_queryData;
	of_socket_address_t _usedNameServer;
	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
		    settings: (OFDNSResolverSettings *)settings
	    nameServersIndex: (size_t)nameServersIndex

	  searchDomainsIndex: (size_t)searchDomainsIndex


		      target: (id)target
		    selector: (SEL)selector
		     context: (id)context;
@end

@interface OFDNSResolver ()
- (void)of_setDefaults;
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#ifdef OF_WINDOWS
- (void)of_parseNetworkParams;
#endif
- (void)of_reloadConfig;
- (void)of_resolveHost: (OFString *)host
	   recordClass: (of_dns_resource_record_class_t)recordClass
	    recordType: (of_dns_resource_record_type_t)recordType
	   nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
      nameServersIndex: (size_t)nameServersIndex
	 searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
    searchDomainsIndex: (size_t)searchDomainsIndex
	       timeout: (unsigned int)timeout
	   maxAttempts: (unsigned int)maxAttempts
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
- (void)of_sendQuery: (OFDNSResolverQuery *)query;
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query;
- (size_t)of_socket: (OFUDPSocket *)sock
      didSendBuffer: (void **)buffer







|

<

<
<







142
143
144
145
146
147
148
149
150

151


152
153
154
155
156
157
158
#ifdef OF_WINDOWS
- (void)of_parseNetworkParams;
#endif
- (void)of_reloadConfig;
- (void)of_resolveHost: (OFString *)host
	   recordClass: (of_dns_resource_record_class_t)recordClass
	    recordType: (of_dns_resource_record_type_t)recordType
	      settings: (OFDNSResolverSettings *)settings
      nameServersIndex: (size_t)nameServersIndex

    searchDomainsIndex: (size_t)searchDomainsIndex


		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
- (void)of_sendQuery: (OFDNSResolverQuery *)query;
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query;
- (size_t)of_socket: (OFUDPSocket *)sock
      didSendBuffer: (void **)buffer
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
		return nil;

	return [OFString stringWithCString: domain + 1
				  encoding: [OFLocale encoding]];
}

static bool
isFQDN(OFString *host, unsigned int minNumberOfDotsInAbsoluteName)
{
	const char *UTF8String = [host UTF8String];
	size_t length = [host UTF8StringLength];
	unsigned int dots = 0;

	if ([host hasSuffix: @"."])
		return true;

	for (size_t i = 0; i < length; i++)
		if (UTF8String[i] == '.')
			dots++;

	return (dots >= minNumberOfDotsInAbsoluteName);
}

static OFString *
parseString(const unsigned char *buffer, size_t length, size_t *i)
{
	uint8_t stringLength;
	OFString *string;







|












|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
		return nil;

	return [OFString stringWithCString: domain + 1
				  encoding: [OFLocale encoding]];
}

static bool
isFQDN(OFString *host, OFDNSResolverSettings *settings)
{
	const char *UTF8String = [host UTF8String];
	size_t length = [host UTF8StringLength];
	unsigned int dots = 0;

	if ([host hasSuffix: @"."])
		return true;

	for (size_t i = 0; i < length; i++)
		if (UTF8String[i] == '.')
			dots++;

	return (dots >= settings->_minNumberOfDotsInAbsoluteName);
}

static OFString *
parseString(const unsigned char *buffer, size_t length, size_t *i)
{
	uint8_t stringLength;
	OFString *string;
553
554
555
556
557
558
559
































560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
	    OFArray *, OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *,
	    OFString *, OFArray *, OFArray *, OFArray *, id, id))
	    [target methodForSelector: selector];

	method(target, selector, resolver, domainName, answerRecords,
	    authorityRecords, additionalRecords, context, exception);
}

































@implementation OFDNSResolverQuery
- (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
	    nameServersIndex: (size_t)nameServersIndex
	       searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
	  searchDomainsIndex: (size_t)searchDomainsIndex
		     timeout: (of_time_interval_t)timeout
		 maxAttempts: (unsigned int)maxAttempts
		      target: (id)target
		    selector: (SEL)selector
		     context: (id)context
{
	self = [super init];

	@try {
		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];
		_nameServersIndex = nameServersIndex;
		_searchDomains = [searchDomains copy];
		_searchDomainsIndex = searchDomainsIndex;
		_timeout = timeout;
		_maxAttempts = maxAttempts;
		_target = [target retain];
		_selector = selector;
		_context = [context retain];

		queryData = [OFMutableData dataWithCapacity: 512];

		/* Header */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|

<

<
<
















|

<

<
<







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

608


609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

627


628
629
630
631
632
633
634
	    OFArray *, OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *,
	    OFString *, OFArray *, OFArray *, OFArray *, id, id))
	    [target methodForSelector: selector];

	method(target, selector, resolver, domainName, answerRecords,
	    authorityRecords, additionalRecords, context, exception);
}

@implementation OFDNSResolverSettings
- (instancetype)initWithNameServers: (OFArray *)nameServers
		      searchDomains: (OFArray *)searchDomains
			    timeout: (of_time_interval_t)timeout
			maxAttempts: (unsigned int)maxAttempts
      minNumberOfDotsInAbsoluteName: (unsigned int)minNumberOfDotsInAbsoluteName
{
	self = [super init];

	@try {
		_nameServers = [nameServers copy];
		_searchDomains = [searchDomains copy];
		_timeout = timeout;
		_maxAttempts = maxAttempts;
		_minNumberOfDotsInAbsoluteName = minNumberOfDotsInAbsoluteName;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_nameServers release];
	[_searchDomains release];

	[super dealloc];
}
@end

@implementation OFDNSResolverQuery
- (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
		    settings: (OFDNSResolverSettings *)settings
	    nameServersIndex: (size_t)nameServersIndex

	  searchDomainsIndex: (size_t)searchDomainsIndex


		      target: (id)target
		    selector: (SEL)selector
		     context: (id)context
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFMutableData *queryData;
		uint16_t tmp;

		_host = [host copy];
		_domainName = [domainName copy];
		_recordClass = recordClass;
		_recordType = recordType;
		_ID = [ID retain];
		_settings = [settings retain];
		_nameServersIndex = nameServersIndex;

		_searchDomainsIndex = searchDomainsIndex;


		_target = [target retain];
		_selector = selector;
		_context = [context retain];

		queryData = [OFMutableData dataWithCapacity: 512];

		/* Header */
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
}

- (void)dealloc
{
	[_host release];
	[_domainName release];
	[_ID release];
	[_nameServers release];
	[_searchDomains release];
	[_target release];
	[_context release];
	[_queryData release];
	[_cancelTimer release];

	[super dealloc];
}







|
<







691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
}

- (void)dealloc
{
	[_host release];
	[_domainName release];
	[_ID release];
	[_settings release];

	[_target release];
	[_context release];
	[_queryData release];
	[_cancelTimer release];

	[super dealloc];
}
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092



1093



1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129









1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141


1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
		      selector: selector
		       context: context];
}

- (void)of_resolveHost: (OFString *)host
	   recordClass: (of_dns_resource_record_class_t)recordClass
	    recordType: (of_dns_resource_record_type_t)recordType
	   nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
      nameServersIndex: (size_t)nameServersIndex
	 searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
    searchDomainsIndex: (size_t)searchDomainsIndex
	       timeout: (unsigned int)timeout
	   maxAttempts: (unsigned int)maxAttempts
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *ID;
	OFString *domainName;
	OFDNSResolverQuery *query;

	[self of_reloadConfig];

	/* Random, unused ID */
	do {
		ID = [OFNumber numberWithUInt16: (uint16_t)of_random()];
	} while ([_queries objectForKey: ID] != nil);

	if (isFQDN(host, _minNumberOfDotsInAbsoluteName))
		domainName = host;



	else



		domainName = [OFString stringWithFormat: @"%@.%@.",
		    host, [searchDomains objectAtIndex: searchDomainsIndex]];


	if ([domainName UTF8StringLength] > 253)
		@throw [OFOutOfRangeException exception];

	query = [[[OFDNSResolverQuery alloc]
		  initWithHost: host
		    domainName: domainName
		   recordClass: recordClass
		    recordType: recordType
			    ID: ID
		   nameServers: _nameServers
	      nameServersIndex: nameServersIndex
		 searchDomains: _searchDomains
	    searchDomainsIndex: searchDomainsIndex
		       timeout: _timeout
		   maxAttempts: _maxAttempts
			target: target
		      selector: selector
		       context: context] autorelease];
	[_queries setObject: query
		     forKey: ID];

	[self of_sendQuery: query];

	objc_autoreleasePoolPop(pool);
}

- (void)asyncResolveHost: (OFString *)host
	     recordClass: (of_dns_resource_record_class_t)recordClass
	      recordType: (of_dns_resource_record_type_t)recordType
		  target: (id)target
		selector: (SEL)selector
		 context: (id)context
{









	[self of_resolveHost: host
		 recordClass: recordClass
		  recordType: recordType
		 nameServers: _nameServers
	    nameServersIndex: 0
	       searchDomains: _searchDomains
	  searchDomainsIndex: 0
		     timeout: _timeout
		 maxAttempts: _maxAttempts
		      target: target
		    selector: selector
		     context: context];


}

- (void)of_sendQuery: (OFDNSResolverQuery *)query
{
	OFUDPSocket *sock;


	[query->_cancelTimer invalidate];
	[query->_cancelTimer release];
	query->_cancelTimer = nil;
	query->_cancelTimer = [[OFTimer
	    scheduledTimerWithTimeInterval: query->_timeout
				    target: self
				  selector: @selector(of_queryWithIDTimedOut:)
				    object: query
				   repeats: false] retain];

	query->_usedNameServer = of_socket_address_parse_ip(
	    [query->_nameServers objectAtIndex: query->_nameServersIndex], 53);


	switch (query->_usedNameServer.family) {
#ifdef OF_HAVE_IPV6
	case OF_SOCKET_ADDRESS_FAMILY_IPV6:
		if (_IPv6Socket == nil) {
			_IPv6Socket = [[OFUDPSocket alloc] init];
			[_IPv6Socket bindToHost: @"::"







|

<

<
<
















|

>
>
>
|
>
>
>

|
>










|

<

<
<


















>
>
>
>
>
>
>
>
>



|

<

<
<



>
>





>





|





|
|
>







1094
1095
1096
1097
1098
1099
1100
1101
1102

1103


1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144


1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

1177


1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
		      selector: selector
		       context: context];
}

- (void)of_resolveHost: (OFString *)host
	   recordClass: (of_dns_resource_record_class_t)recordClass
	    recordType: (of_dns_resource_record_type_t)recordType
	      settings: (OFDNSResolverSettings *)settings
      nameServersIndex: (size_t)nameServersIndex

    searchDomainsIndex: (size_t)searchDomainsIndex


		target: (id)target
	      selector: (SEL)selector
	       context: (id)context
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *ID;
	OFString *domainName;
	OFDNSResolverQuery *query;

	[self of_reloadConfig];

	/* Random, unused ID */
	do {
		ID = [OFNumber numberWithUInt16: (uint16_t)of_random()];
	} while ([_queries objectForKey: ID] != nil);

	if (isFQDN(host, settings)) {
		domainName = host;

		if (![domainName hasSuffix: @"."])
			domainName = [domainName stringByAppendingString: @"."];
	} else {
		OFString *searchDomain = [settings->_searchDomains
		    objectAtIndex: searchDomainsIndex];

		domainName = [OFString stringWithFormat: @"%@.%@.",
		    host, searchDomain];
	}

	if ([domainName UTF8StringLength] > 253)
		@throw [OFOutOfRangeException exception];

	query = [[[OFDNSResolverQuery alloc]
		  initWithHost: host
		    domainName: domainName
		   recordClass: recordClass
		    recordType: recordType
			    ID: ID
		      settings: settings
	      nameServersIndex: nameServersIndex

	    searchDomainsIndex: searchDomainsIndex


			target: target
		      selector: selector
		       context: context] autorelease];
	[_queries setObject: query
		     forKey: ID];

	[self of_sendQuery: query];

	objc_autoreleasePoolPop(pool);
}

- (void)asyncResolveHost: (OFString *)host
	     recordClass: (of_dns_resource_record_class_t)recordClass
	      recordType: (of_dns_resource_record_type_t)recordType
		  target: (id)target
		selector: (SEL)selector
		 context: (id)context
{
	void *pool = objc_autoreleasePoolPush();
	OFDNSResolverSettings *settings = [[[OFDNSResolverSettings alloc]
		      initWithNameServers: _nameServers
			    searchDomains: _searchDomains
				  timeout: _timeout
			      maxAttempts: _maxAttempts
	    minNumberOfDotsInAbsoluteName: _minNumberOfDotsInAbsoluteName]
	    autorelease];

	[self of_resolveHost: host
		 recordClass: recordClass
		  recordType: recordType
		    settings: settings
	    nameServersIndex: 0

	  searchDomainsIndex: 0


		      target: target
		    selector: selector
		     context: context];

	objc_autoreleasePoolPop(pool);
}

- (void)of_sendQuery: (OFDNSResolverQuery *)query
{
	OFUDPSocket *sock;
	OFString *nameServer;

	[query->_cancelTimer invalidate];
	[query->_cancelTimer release];
	query->_cancelTimer = nil;
	query->_cancelTimer = [[OFTimer
	    scheduledTimerWithTimeInterval: query->_settings->_timeout
				    target: self
				  selector: @selector(of_queryWithIDTimedOut:)
				    object: query
				   repeats: false] retain];

	nameServer = [query->_settings->_nameServers
	    objectAtIndex: query->_nameServersIndex];
	query->_usedNameServer = of_socket_address_parse_ip(nameServer, 53);

	switch (query->_usedNameServer.family) {
#ifdef OF_HAVE_IPV6
	case OF_SOCKET_ADDRESS_FAMILY_IPV6:
		if (_IPv6Socket == nil) {
			_IPv6Socket = [[OFUDPSocket alloc] init];
			[_IPv6Socket bindToHost: @"::"
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query
{
	OFResolveHostFailedException *exception;

	if (query == nil)
		return;

	if (query->_nameServersIndex + 1 < [query->_nameServers count]) {

		query->_nameServersIndex++;
		[self of_sendQuery: query];
		return;
	}

	if (query->_attempt < query->_maxAttempts) {
		query->_attempt++;
		query->_nameServersIndex = 0;
		[self of_sendQuery: query];
		return;
	}

	query = [[query retain] autorelease];







|
>





|







1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query
{
	OFResolveHostFailedException *exception;

	if (query == nil)
		return;

	if (query->_nameServersIndex + 1 <
	    [query->_settings->_nameServers count]) {
		query->_nameServersIndex++;
		[self of_sendQuery: query];
		return;
	}

	if (query->_attempt < query->_settings->_maxAttempts) {
		query->_attempt++;
		query->_nameServersIndex = 0;
		[self of_sendQuery: query];
		return;
	}

	query = [[query retain] autorelease];
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
			error = OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT;
			break;
		case 2:
			error = OF_DNS_RESOLVER_ERROR_SERVER_FAILURE;
			break;
		case 3:
			if (query->_searchDomainsIndex + 1 <
			    [query->_searchDomains count]) {
				query->_searchDomainsIndex++;

				[self of_resolveHost: query->_host
					 recordClass: query->_recordClass
					  recordType: query->_recordType
					 nameServers: query->_nameServers
				    nameServersIndex: query->_nameServersIndex
				       searchDomains: query->_searchDomains
				  searchDomainsIndex: query->_searchDomainsIndex
					     timeout: query->_timeout
					 maxAttempts: query->_maxAttempts
					      target: query->_target
					    selector: query->_selector
					     context: query->_context];

				return false;
			}








|





|

<

<
<







1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386

1387


1388
1389
1390
1391
1392
1393
1394
			error = OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT;
			break;
		case 2:
			error = OF_DNS_RESOLVER_ERROR_SERVER_FAILURE;
			break;
		case 3:
			if (query->_searchDomainsIndex + 1 <
			    [query->_settings->_searchDomains count]) {
				query->_searchDomainsIndex++;

				[self of_resolveHost: query->_host
					 recordClass: query->_recordClass
					  recordType: query->_recordType
					    settings: query->_settings
				    nameServersIndex: query->_nameServersIndex

				  searchDomainsIndex: query->_searchDomainsIndex


					      target: query->_target
					    selector: query->_selector
					     context: query->_context];

				return false;
			}