ObjFW  Check-in [17397bfad4]

Overview
Comment:OFDNSResourceRecord: Cleaner subclass separation
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 17397bfad437dd0a7cb9dc11a61204b27b77cb8891c4405f0cf92aebcf812e70
User & Date: js on 2018-08-01 23:02:57
Other Links: manifest | tags
Context
2018-08-02
01:16
OFDNSResolver: Add support for parsing SOA records check-in: c165d49455 user: js tags: trunk
2018-08-01
23:02
OFDNSResourceRecord: Cleaner subclass separation check-in: 17397bfad4 user: js tags: trunk
2018-07-31
23:48
OFDNSResolver: Add support for {NS,PTR,TXT} RRs check-in: 1124f7d4d4 user: js tags: trunk
Changes

Modified src/OFDNSResolver.m from [7f7fd809d0] to [4b3c509e3e].

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
315
316
317
318
319
320
321
322
323
324




325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
}

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)
{
	uint16_t preference;
	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]];

			return [[[OFADNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_NS:
			j = i;

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

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

			return [[[OFNSDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data

				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
			j = i;

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

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

			return [[[OFCNAMEDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_PTR:
			j = i;

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

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

			return [[[OFPTRDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_MX:




			if (dataLength < 2)
				@throw [OFInvalidServerReplyException
				    exception];

			preference = (buffer[i] << 8) | buffer[i + 1];

			j = i + 2;

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

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

			return [[[OFMXDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
			      preference: preference
				    data: data
				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_TXT:
			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];

			return [[[OFTXTDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:



			if (dataLength != 16)
				@throw [OFInvalidServerReplyException
				    exception];

			data = parseAAAAData(&buffer[i]);

			return [[[OFAAAADNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		default:
			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];

			return [[[OFDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];
		}
	} else {
		data = [OFData dataWithItems: &buffer[i]
				       count: dataLength];

		return [[[OFDNSResourceRecord 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;







<
<
|
|
<
>

<
<
|
|
<

|
<
|
<

|
|
|
<
<
|
|
|
<
|
|

|
|
<

|
|
|
<
<
>
|
|
|
<
|


|
|
<

|
|
|
<
|
|
|
|
<
|
|

|
|
<

|
|
|
<
|
|
|
>
>
>
>
|
|
<

|

|
<
|
|

|
|
<

|


<

|

|
|
|

|
|
|
<
|
|
|
>
>
>
|
|
|

|

|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<




<

<







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
315
316

317
318
319
320
321

322
323
324
325

326
327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343
344
345
346
347
348
349







350





351

352



353
354
355
356

357

358
359
360
361
362
363
364
}

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)
{


	if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_A &&
	    recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) {

		OFString *address;



		if (dataLength != 4)
			@throw [OFInvalidServerReplyException exception];


		address = [OFString stringWithFormat: @"%u.%u.%u.%u",

		    buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]];


		return [[[OFADNSResourceRecord alloc]
		    initWithName: name
			 address: address


			     TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_NS) {
		size_t j = i;

		OFString *authoritativeHost = parseName(buffer, length, &j,
		    ALLOWED_POINTER_LEVELS);

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


		return [[[OFNSDNSResourceRecord alloc]
			 initWithName: name
			  recordClass: recordClass


		    authoritativeHost: authoritativeHost
				  TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_CNAME) {
		size_t j = i;

		OFString *alias = parseName(buffer, length, &j,
			    ALLOWED_POINTER_LEVELS);

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


		return [[[OFCNAMEDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass

			   alias: alias
			     TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_PTR) {
		size_t j = i;

		OFString *domainName = parseName(buffer, length, &j,
		    ALLOWED_POINTER_LEVELS);

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


		return [[[OFPTRDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass

		      domainName: domainName
			     TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_MX) {
		uint16_t preference;
		size_t j;
		OFString *mailExchange;

		if (dataLength < 2)
			@throw [OFInvalidServerReplyException exception];


		preference = (buffer[i] << 8) | buffer[i + 1];

		j = i + 2;

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

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


		return [[[OFMXDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass

			      preference: preference
			    mailExchange: mailExchange
				     TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_TXT) {
		OFData *textData = [OFData dataWithItems: &buffer[i]
						   count: dataLength];

		return [[[OFTXTDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass

			textData: textData
			     TTL: TTL] autorelease];
	} else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_AAAA &&
	    recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) {
		OFString *address;

		if (dataLength != 16)
			@throw [OFInvalidServerReplyException
			    exception];

		address = parseAAAAData(&buffer[i]);

		return [[[OFAAAADNSResourceRecord alloc]
		    initWithName: name







			 address: address





			     TTL: TTL] autorelease];

	} else



		return [[[OFDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass
		      recordType: recordType

			     TTL: TTL] autorelease];

}

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

Modified src/OFDNSResourceRecord.h from [494b9e3242] to [60ca2991f0].

44
45
46
47
48
49
50


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
134
135
136
137




138
139
140
141

















142
143
144
145
146
147
148
149
150




151
152
153
154



















155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
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
202
203
204
205
206
207
208
209
210
211




212
213
214
215



















216
217
218
219
220
221
222
223
224




225
226
227
228



















229
230
231
232
233
234
235
236
237




238
239
240
241



















242
243
244
245
246
247
248
	OF_DNS_RESOURCE_RECORD_TYPE_NS	  =   2,
	/*! CNAME */
	OF_DNS_RESOURCE_RECORD_TYPE_CNAME =   5,
	/*! SOA */
	OF_DNS_RESOURCE_RECORD_TYPE_SOA	  =   6,
	/*! PTR */
	OF_DNS_RESOURCE_RECORD_TYPE_PTR	  =  12,


	/*! MX */
	OF_DNS_RESOURCE_RECORD_TYPE_MX	  =  15,
	/*! TXT */
	OF_DNS_RESOURCE_RECORD_TYPE_TXT	  =  16,
	/*! AAAA */
	OF_DNS_RESOURCE_RECORD_TYPE_AAAA  =  28,
	/*! All types. Only for queries. */
	OF_DNS_RESOURCE_RECORD_TYPE_ALL	  = 255,
} of_dns_resource_record_type_t;

/*!
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */
@interface OFDNSResourceRecord: OFObject
{
	OFString *_name;
	of_dns_resource_record_class_t _recordClass;
	of_dns_resource_record_type_t _recordType;
	id _data;
	uint32_t _TTL;
}

/**
 * @brief The domain name to which the resource record belongs.
 */
@property (readonly, nonatomic) OFString *name;

/*!
 * @brief The resource record class code.
 */
@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass;

/*!
 * @brief The resource record type code.
 */
@property (readonly, nonatomic) of_dns_resource_record_type_t recordType;

/*!
 * The class and type-dependent data of the resource.
 */
@property (readonly, nonatomic) id data;

/*!
 * @brief The number of seconds after which the resource record should be
 *	  discarded from the cache.
 */
@property (readonly, nonatomic) uint32_t TTL;

/*!
 * @brief Initializes an already allocated OFDNSResourceRecord with the
 *	  specified name, resource record class, resource record type, resource
 *	  record data and resource record time to live.
 *
 * @param name The name of the resource record
 * @param recordClass The class code for the resource record
 * @param recordType The type code for the resource record
 * @param data The data for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			data: (id)data
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFADNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an A DNS resource record.
 */
@interface OFADNSResourceRecord: OFDNSResourceRecord




/*!
 * A string with the IP address.
 */
@property (readonly, nonatomic) OFString *data;

















@end

/*!
 * @class OFAAAADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class represenging a DNS resource record.
 */
@interface OFAAAADNSResourceRecord: OFDNSResourceRecord




/*!
 * A string with the IP address.
 */
@property (readonly, nonatomic) OFString *data;

















@end

/*!
 * @class OFCNAMEDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord




/*!
 * A string with the alias.
 */
@property (readonly, nonatomic) OFString *data;



















@end

/*!
 * @class OFMXDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an MX DNS resource record.
 */
@interface OFMXDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _preference;

}

/*!
 * The preference of the resource record.
 */
@property (readonly, nonatomic) uint16_t preference;

/*!
 * A string with the mail exchange.
 */
@property (readonly, nonatomic) OFString *data;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			data: (id)data
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFMXDNSResourceRecord with the
 *	  specified name, resource record class, resource record type, resource
 *	  record preference, resource record data and resource record time to
 *	  live.
 *
 * @param name The name of the resource record
 * @param recordClass The class code for the resource record
 * @param recordType The type code for the resource record
 * @param preference The preference of the resource record
 * @param data The data for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
		  preference: (uint16_t)preference
			data: (id)data
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFNSDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFNSDNSResourceRecord: OFDNSResourceRecord




/*!
 * A string with the authoritative host of the resource record.
 */
@property (readonly, nonatomic) OFString *data;



















@end

/*!
 * @class OFPTRDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFPTRDNSResourceRecord: OFDNSResourceRecord




/*!
 * A string with the domain name for the resource record.
 */
@property (readonly, nonatomic) OFString *data;



















@end

/*!
 * @class OFTXTDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFTXTDNSResourceRecord: OFDNSResourceRecord




/*!
 * Data with the text of the resource record.
 */
@property (readonly, nonatomic) OFString *data;



















@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFString *_Nonnull of_dns_resource_record_class_to_string(
    of_dns_resource_record_class_t recordClass);







>
>




















<


















<
<
<
<
<








|
<

|


<





<









>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>








|

|




<




|
<
<

|

<
|
|




<

|







|


>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|


>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|


>
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
	OF_DNS_RESOURCE_RECORD_TYPE_NS	  =   2,
	/*! CNAME */
	OF_DNS_RESOURCE_RECORD_TYPE_CNAME =   5,
	/*! SOA */
	OF_DNS_RESOURCE_RECORD_TYPE_SOA	  =   6,
	/*! PTR */
	OF_DNS_RESOURCE_RECORD_TYPE_PTR	  =  12,
	/*! HINFO */
	OF_DNS_RESOURCE_RECORD_TYPE_HINFO =  13,
	/*! MX */
	OF_DNS_RESOURCE_RECORD_TYPE_MX	  =  15,
	/*! TXT */
	OF_DNS_RESOURCE_RECORD_TYPE_TXT	  =  16,
	/*! AAAA */
	OF_DNS_RESOURCE_RECORD_TYPE_AAAA  =  28,
	/*! All types. Only for queries. */
	OF_DNS_RESOURCE_RECORD_TYPE_ALL	  = 255,
} of_dns_resource_record_type_t;

/*!
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */
@interface OFDNSResourceRecord: OFObject
{
	OFString *_name;
	of_dns_resource_record_class_t _recordClass;
	of_dns_resource_record_type_t _recordType;

	uint32_t _TTL;
}

/**
 * @brief The domain name to which the resource record belongs.
 */
@property (readonly, nonatomic) OFString *name;

/*!
 * @brief The resource record class code.
 */
@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass;

/*!
 * @brief The resource record type code.
 */
@property (readonly, nonatomic) of_dns_resource_record_type_t recordType;






/*!
 * @brief The number of seconds after which the resource record should be
 *	  discarded from the cache.
 */
@property (readonly, nonatomic) uint32_t TTL;

/*!
 * @brief Initializes an already allocated OFDNSResourceRecord with the
 *	  specified name, class, type, data and time to live.

 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record
 * @param recordType The type code for the resource record

 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType

			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFADNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an A DNS resource record.
 */
@interface OFADNSResourceRecord: OFDNSResourceRecord
{
	OFString *_address;
}

/*!
 * The IPv4 address of the resource record.
 */
@property (readonly, nonatomic) OFString *address;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		     address: (OFString *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFAAAADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class represenging a DNS resource record.
 */
@interface OFAAAADNSResourceRecord: OFDNSResourceRecord
{
	OFString *_address;
}

/*!
 * The IPv6 address of the resource record.
 */
@property (readonly, nonatomic) OFString *address;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFAAAADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		     address: (OFString *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFCNAMEDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_alias;
}

/*!
 * The alias of the resource record.
 */
@property (readonly, nonatomic) OFString *alias;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFCNAMEDNSResourceRecord with the
 *	  specified name, class, alias and time to live.
 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record
 * @param alias The alias for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFMXDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an MX DNS resource record.
 */
@interface OFMXDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _preference;
	OFString *_mailExchange;
}

/*!
 * The preference of the resource record.
 */
@property (readonly, nonatomic) uint16_t preference;

/*!
 * The mail exchange of the resource record.
 */
@property (readonly, nonatomic) OFString *mailExchange;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType

			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFMXDNSResourceRecord with the
 *	  specified name, class, preference, mail exchange and time to live.


 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record

 * @param preference The preference for the resource record
 * @param mailExchange The mail exchange for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass

		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFNSDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an NS DNS resource record.
 */
@interface OFNSDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_authoritativeHost;
}

/*!
 * The authoritative host of the resource record.
 */
@property (readonly, nonatomic) OFString *authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFNSDNSResourceRecord with the
 *	  specified name, class, authoritative host and time to live.
 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record
 * @param authoritativeHost The authoritative host for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFPTRDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a PTR DNS resource record.
 */
@interface OFPTRDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_domainName;
}

/*!
 * The domain name of the resource record.
 */
@property (readonly, nonatomic) OFString *domainName;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFPTRDNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record
 * @param domainName The domain name for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/*!
 * @class OFTXTDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a TXT DNS resource record.
 */
@interface OFTXTDNSResourceRecord: OFDNSResourceRecord
{
	OFData *_textData;
}

/*!
 * The text of the resource record.
 */
@property (readonly, nonatomic) OFData *textData;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFTXTDNSResourceRecord with the
 *	  specified name, class, text data and time to live.
 *
 * @param name The name for the resource record
 * @param recordClass The class code for the resource record
 * @param textData The data for the resource record
 * @param TTL The time to live for the resource record
 */
- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		    textData: (OFData *)textData
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFString *_Nonnull of_dns_resource_record_class_to_string(
    of_dns_resource_record_class_t recordClass);

Modified src/OFDNSResourceRecord.m from [627ddd0813] to [86511b150e].

46
47
48
49
50
51
52


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
		return @"NS";
	case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
		return @"CNAME";
	case OF_DNS_RESOURCE_RECORD_TYPE_SOA:
		return @"SOA";
	case OF_DNS_RESOURCE_RECORD_TYPE_PTR:
		return @"PTR";


	case OF_DNS_RESOURCE_RECORD_TYPE_MX:
		return @"MX";
	case OF_DNS_RESOURCE_RECORD_TYPE_TXT:
		return @"TXT";
	case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
		return @"AAAA";
	case OF_DNS_RESOURCE_RECORD_TYPE_ALL:
		return @"all";
	default:
		return [OFString stringWithFormat: @"%u", recordType];
	}
}

@implementation OFDNSResourceRecord
@synthesize name = _name, recordClass = _recordClass, recordType = _recordType;
@synthesize data = _data, TTL = _TTL;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			data: (id)data
			 TTL: (uint32_t)TTL
{
	self = [super init];

	@try {
		_name = [name copy];
		_recordClass = recordClass;
		_recordType = recordType;
		_data = [data copy];
		_TTL = TTL;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_name release];



















































































































































































































































































































































































































































































































































































































































	[_data release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_data != _data && ![otherRecord->_data isEqual: _data])
		return false;

	if (otherRecord->_TTL != _TTL)

		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_data hash]);
	OF_HASH_ADD(hash, _TTL >> 24);
	OF_HASH_ADD(hash, _TTL >> 16);
	OF_HASH_ADD(hash, _TTL >> 8);
	OF_HASH_ADD(hash, _TTL);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tType = %@\n"
	    @"\tData = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass),
	    of_dns_resource_record_type_to_string(_recordType), _data, _TTL];
}
@end

@implementation OFADNSResourceRecord
@dynamic data;
@end

@implementation OFAAAADNSResourceRecord
@dynamic data;
@end

@implementation OFCNAMEDNSResourceRecord
@dynamic data;
@end

@implementation OFMXDNSResourceRecord
@dynamic data;
@synthesize preference = _preference;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			data: (id)data
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
		  preference: (uint16_t)preference
			data: (id)data
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: recordType
			      data: data
			       TTL: TTL];

	_preference = preference;

	return self;
}

- (bool)isEqual: (id)otherObject
{
	OFMXDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFMXDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (![super isEqual: otherRecord])
		return false;

	if (otherRecord->_preference != _preference)
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [super hash]);
	OF_HASH_ADD(hash, _preference >> 8);
	OF_HASH_ADD(hash, _preference);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tType = %@\n"
	    @"\tPreference = %" PRIu16 "\n"
	    @"\tData = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass),
	    of_dns_resource_record_type_to_string(_recordType), _preference,
	    _data, _TTL];
}
@end

@implementation OFNSDNSResourceRecord
@dynamic data;
@end

@implementation OFPTRDNSResourceRecord
@dynamic data;
@end

@implementation OFTXTDNSResourceRecord
@dynamic data;
@end







>
>















|




<








<












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|






|

|













<
<
<
|
>
















|
<
<
<
<












<
|



|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


<
<
<
<
<
<
<
<
<
<
<
<
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
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
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
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744



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












		return @"NS";
	case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
		return @"CNAME";
	case OF_DNS_RESOURCE_RECORD_TYPE_SOA:
		return @"SOA";
	case OF_DNS_RESOURCE_RECORD_TYPE_PTR:
		return @"PTR";
	case OF_DNS_RESOURCE_RECORD_TYPE_HINFO:
		return @"HINFO";
	case OF_DNS_RESOURCE_RECORD_TYPE_MX:
		return @"MX";
	case OF_DNS_RESOURCE_RECORD_TYPE_TXT:
		return @"TXT";
	case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
		return @"AAAA";
	case OF_DNS_RESOURCE_RECORD_TYPE_ALL:
		return @"all";
	default:
		return [OFString stringWithFormat: @"%u", recordType];
	}
}

@implementation OFDNSResourceRecord
@synthesize name = _name, recordClass = _recordClass, recordType = _recordType;
@synthesize TTL = _TTL;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType

			 TTL: (uint32_t)TTL
{
	self = [super init];

	@try {
		_name = [name copy];
		_recordClass = recordClass;
		_recordType = recordType;

		_TTL = TTL;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_name release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tType = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass),
	    of_dns_resource_record_type_to_string(_recordType), _TTL];
}
@end

@implementation OFADNSResourceRecord
@synthesize address = _address;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (OFString *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_A
			       TTL: TTL];

	@try {
		_address = [address copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_address release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFADNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFADNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_address != _address &&
	    ![otherRecord->_address isEqual: _address])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_address hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name, _address, _TTL];
}
@end

@implementation OFAAAADNSResourceRecord
@synthesize address = _address;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (OFString *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA
			       TTL: TTL];

	@try {
		_address = [address copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_address release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFAAAADNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFAAAADNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_address != _address &&
	    ![otherRecord->_address isEqual: _address])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_address hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name, _address, _TTL];
}
@end

@implementation OFCNAMEDNSResourceRecord
@synthesize alias = _alias;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_CNAME
			       TTL: TTL];

	@try {
		_alias = [alias copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_alias release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFCNAMEDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFCNAMEDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_alias != _alias &&
	    ![otherRecord->_alias isEqual: _alias])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_alias hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAlias = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass), _alias, _TTL];
}
@end

@implementation OFMXDNSResourceRecord
@synthesize preference = _preference, mailExchange = _mailExchange;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_MX
			       TTL: TTL];

	@try {
		_preference = preference;
		_mailExchange = [mailExchange copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mailExchange release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFMXDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFMXDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_preference != _preference)
		return false;

	if (otherRecord->_mailExchange != _mailExchange &&
	    ![otherRecord->_mailExchange isEqual: _mailExchange])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD(hash, _preference >> 8);
	OF_HASH_ADD(hash, _preference);
	OF_HASH_ADD_HASH(hash, [_mailExchange hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPreference = %" PRIu16 "\n"
	    @"\tMail Exchange = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass), _preference,
	    _mailExchange, _TTL];
}
@end

@implementation OFNSDNSResourceRecord
@synthesize authoritativeHost = _authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_NS
			       TTL: TTL];

	@try {
		_authoritativeHost = [authoritativeHost copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_authoritativeHost release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFNSDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFNSDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_authoritativeHost != _authoritativeHost &&
	    ![otherRecord->_authoritativeHost isEqual: _authoritativeHost])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_authoritativeHost hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAuthoritative Host = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass),
	    _authoritativeHost, _TTL];
}
@end

@implementation OFPTRDNSResourceRecord
@synthesize domainName = _domainName;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_PTR
			       TTL: TTL];

	@try {
		_domainName = [domainName copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_domainName release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFPTRDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFPTRDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;

	if (otherRecord->_domainName != _domainName &&
	    ![otherRecord->_domainName isEqual: _domainName])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_domainName hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tDomain Name = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass), _domainName,
	    _TTL];
}
@end

@implementation OFTXTDNSResourceRecord
@synthesize textData = _textData;

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		  recordType: (of_dns_resource_record_type_t)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		 recordClass: (of_dns_resource_record_class_t)recordClass
		    textData: (OFData *)textData
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
		       recordClass: recordClass
			recordType: OF_DNS_RESOURCE_RECORD_TYPE_TXT
			       TTL: TTL];

	@try {
		_textData = [textData copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_textData release];

	[super dealloc];
}

- (bool)isEqual: (id)otherObject
{
	OFTXTDNSResourceRecord *otherRecord;

	if (![otherObject isKindOfClass: [OFTXTDNSResourceRecord class]])
		return false;

	otherRecord = otherObject;

	if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name])
		return false;

	if (otherRecord->_recordClass != _recordClass)
		return false;

	if (otherRecord->_recordType != _recordType)
		return false;




	if (otherRecord->_textData != _textData &&
	    ![otherRecord->_textData isEqual: _textData])
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	OF_HASH_ADD_HASH(hash, [_name hash]);
	OF_HASH_ADD(hash, _recordClass >> 8);
	OF_HASH_ADD(hash, _recordClass);
	OF_HASH_ADD(hash, _recordType >> 8);
	OF_HASH_ADD(hash, _recordType);
	OF_HASH_ADD_HASH(hash, [_textData hash]);





	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"

	    @"\tText Data = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    [self className], _name,
	    of_dns_resource_record_class_to_string(_recordClass), _textData,






























































































	    _TTL];
}
@end