ObjFW  Diff

Differences From Artifact [9fbb4cad64]:

To Artifact [16d3a398be]:


58
59
60
61
62
63
64

65
66
67
68
69
70
71
 * TODO:
 *
 *  - Timeouts
 *  - Resolve with each search domain
 *  - Iterate through name servers
 *  - IPv6 for talking to the name servers
 *  - Fallback to TCP

 */

@interface OFDNSResolver_context: OFObject
{
	OFString *_host;
	OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
	size_t _nameServersIndex, _searchDomainsIndex;







>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 * TODO:
 *
 *  - Timeouts
 *  - Resolve with each search domain
 *  - Iterate through name servers
 *  - IPv6 for talking to the name servers
 *  - Fallback to TCP
 *  - More record types
 */

@interface OFDNSResolver_context: OFObject
{
	OFString *_host;
	OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
	size_t _nameServersIndex, _searchDomainsIndex;
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

	*idx = i;

	return [components componentsJoinedByString: @"."];
}

static OFString *
parseAAAA(const unsigned char *buffer)
{
	OFMutableString *data = [OFMutableString string];
	int_fast8_t zerosStart = -1, maxZerosStart = -1;
	uint_fast8_t zerosCount = 0, maxZerosCount = 0;
	bool first = true;

	for (uint_fast8_t i = 0; i < 16; i += 2) {







|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

	*idx = i;

	return [components componentsJoinedByString: @"."];
}

static OFString *
parseAAAAData(const unsigned char *buffer)
{
	OFMutableString *data = [OFMutableString string];
	int_fast8_t zerosStart = -1, maxZerosStart = -1;
	uint_fast8_t zerosCount = 0, maxZerosCount = 0;
	bool first = true;

	for (uint_fast8_t i = 0; i < 16; i += 2) {
240
241
242
243
244
245
246
247
248
249
250

251

252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286

287
288
289
290
291

292
293
294




295

296
297
298
299
300
301
302
	}

	[data makeImmutable];

	return data;
}

static id
parseData(const unsigned char *buffer, size_t length, size_t i,
    size_t dataLength, of_dns_resource_record_class_t recordClass,
    of_dns_resource_record_type_t recordType)

{

	id data;

	if (recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) {
		size_t j;

		switch (recordType) {
		case OF_DNS_RESOURCE_RECORD_TYPE_A:
			if (dataLength != 4)
				@throw [OFInvalidServerReplyException
				    exception];


			data = [OFString stringWithFormat:
			    @"%u.%u.%u.%u",
			    buffer[i], buffer[i + 1],
			    buffer[i + 2], buffer[i + 3]];
			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
			j = i;


			data = parseName(buffer, length, &j,
			    ALLOWED_POINTER_LEVELS);

			if (j != i + dataLength)
				@throw [OFInvalidServerReplyException
				    exception];

			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
			if (dataLength != 16)
				@throw [OFInvalidServerReplyException
				    exception];


			data = parseAAAA(&buffer[i]);
			break;
		default:

			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];
			break;
		}
	} else

		data = [OFData dataWithItems: &buffer[i]
				       count: dataLength];





	return data;

}

@implementation OFDNSResolver_context
@synthesize host = _host, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;







|
<
|
|
>

>











>








>













>
|


>




|
>


|
>
>
>
>
|
>







241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	}

	[data makeImmutable];

	return data;
}

static OF_KINDOF(OFDNSResourceRecord *)

createResourceRecord(OFString *name, of_dns_resource_record_class_t recordClass,
    of_dns_resource_record_type_t recordType, uint32_t TTL,
    const unsigned char *buffer, size_t length, size_t i, size_t dataLength)
{
	Class class;
	id data;

	if (recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) {
		size_t j;

		switch (recordType) {
		case OF_DNS_RESOURCE_RECORD_TYPE_A:
			if (dataLength != 4)
				@throw [OFInvalidServerReplyException
				    exception];

			class = [OFADNSResourceRecord class];
			data = [OFString stringWithFormat:
			    @"%u.%u.%u.%u",
			    buffer[i], buffer[i + 1],
			    buffer[i + 2], buffer[i + 3]];
			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
			j = i;

			class = [OFCNAMEDNSResourceRecord class];
			data = parseName(buffer, length, &j,
			    ALLOWED_POINTER_LEVELS);

			if (j != i + dataLength)
				@throw [OFInvalidServerReplyException
				    exception];

			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
			if (dataLength != 16)
				@throw [OFInvalidServerReplyException
				    exception];

			class = [OFAAAADNSResourceRecord class];
			data = parseAAAAData(&buffer[i]);
			break;
		default:
			class = [OFDNSResourceRecord class];
			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];
			break;
		}
	} else {
		class = [OFDNSResourceRecord class];
		data = [OFData dataWithItems: &buffer[i]
				       count: dataLength];
	}

	return [[[class alloc] initWithName: name
				recordClass: recordClass
				 recordType: recordType
				       data: data
					TTL: TTL] autorelease];
}

@implementation OFDNSResolver_context
@synthesize host = _host, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
		for (uint_fast16_t j = 0; j < numAnswers; j++) {
			OFString *name = parseName(buffer, length, &i,
			    ALLOWED_POINTER_LEVELS);
			of_dns_resource_record_class_t recordClass;
			of_dns_resource_record_type_t recordType;
			uint32_t TTL;
			uint16_t dataLength;
			id data;
			OFDNSResourceRecord *record;

			if (i + 10 > length)
				@throw [OFTruncatedDataException exception];

			recordType = (buffer[i] << 16) | buffer[i + 1];
			recordClass = (buffer[i + 2] << 16) | buffer[i + 3];
			TTL = (buffer[i + 4] << 24) | (buffer[i + 5] << 16) |
			    (buffer[i + 6] << 8) | buffer[i + 7];
			dataLength = (buffer[i + 8] << 16) | buffer[i + 9];

			i += 10;

			if (i + dataLength > length)
				@throw [OFTruncatedDataException exception];


			data = parseData(buffer, length, i, dataLength,
			    recordClass, recordType);
			i += dataLength;

			record = [[[OFDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];

			[answers addObject: record];
		}
	} @catch (id e) {
		callback(target, selector, nil,
		    [DNSResolverContext userContext], e);
		return false;
	}







<
















>
|
<


<
<
<
<
<
<
<







757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783







784
785
786
787
788
789
790
		for (uint_fast16_t j = 0; j < numAnswers; j++) {
			OFString *name = parseName(buffer, length, &i,
			    ALLOWED_POINTER_LEVELS);
			of_dns_resource_record_class_t recordClass;
			of_dns_resource_record_type_t recordType;
			uint32_t TTL;
			uint16_t dataLength;

			OFDNSResourceRecord *record;

			if (i + 10 > length)
				@throw [OFTruncatedDataException exception];

			recordType = (buffer[i] << 16) | buffer[i + 1];
			recordClass = (buffer[i + 2] << 16) | buffer[i + 3];
			TTL = (buffer[i + 4] << 24) | (buffer[i + 5] << 16) |
			    (buffer[i + 6] << 8) | buffer[i + 7];
			dataLength = (buffer[i + 8] << 16) | buffer[i + 9];

			i += 10;

			if (i + dataLength > length)
				@throw [OFTruncatedDataException exception];

			record = createResourceRecord(name, recordClass,
			    recordType, TTL, buffer, length, i, dataLength);

			i += dataLength;








			[answers addObject: record];
		}
	} @catch (id e) {
		callback(target, selector, nil,
		    [DNSResolverContext userContext], e);
		return false;
	}