︙ | | |
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
|
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:
*
* - Resolve with each search domain
* - 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;
OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
OFDNSResolverSettings *_settings;
size_t _nameServersIndex, _searchDomainsIndex;
of_time_interval_t _timeout;
unsigned int _maxAttempts;
unsigned int _attempt;
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
settings: (OFDNSResolverSettings *)settings
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;
|
︙ | | |
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
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
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
settings: (OFDNSResolverSettings *)settings
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
|
︙ | | |
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
|
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, unsigned int minNumberOfDotsInAbsoluteName)
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 >= minNumberOfDotsInAbsoluteName);
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
|
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
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
settings: (OFDNSResolverSettings *)settings
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];
_settings = [settings retain];
_nameServersIndex = nameServersIndex;
_searchDomains = [searchDomains copy];
_searchDomainsIndex = searchDomainsIndex;
_timeout = timeout;
_maxAttempts = maxAttempts;
_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
|
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
|
-
+
-
|
}
- (void)dealloc
{
[_host release];
[_domainName release];
[_ID release];
[_nameServers release];
[_settings release];
[_searchDomains 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
|
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
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
settings: (OFDNSResolverSettings *)settings
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))
if (isFQDN(host, settings)) {
domainName = host;
if (![domainName hasSuffix: @"."])
domainName = [domainName stringByAppendingString: @"."];
else
} else {
OFString *searchDomain = [settings->_searchDomains
objectAtIndex: searchDomainsIndex];
domainName = [OFString stringWithFormat: @"%@.%@.",
host, [searchDomains objectAtIndex: searchDomainsIndex]];
host, searchDomain];
}
if ([domainName UTF8StringLength] > 253)
@throw [OFOutOfRangeException exception];
query = [[[OFDNSResolverQuery alloc]
initWithHost: host
domainName: domainName
recordClass: recordClass
recordType: recordType
ID: ID
nameServers: _nameServers
settings: settings
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
{
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
nameServers: _nameServers
settings: settings
nameServersIndex: 0
searchDomains: _searchDomains
searchDomainsIndex: 0
timeout: _timeout
maxAttempts: _maxAttempts
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->_timeout
scheduledTimerWithTimeInterval: query->_settings->_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);
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
|
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->_nameServers count]) {
if (query->_nameServersIndex + 1 <
[query->_settings->_nameServers count]) {
query->_nameServersIndex++;
[self of_sendQuery: query];
return;
}
if (query->_attempt < query->_maxAttempts) {
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
|
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->_searchDomains count]) {
[query->_settings->_searchDomains count]) {
query->_searchDomainsIndex++;
[self of_resolveHost: query->_host
recordClass: query->_recordClass
recordType: query->_recordType
nameServers: query->_nameServers
settings: query->_settings
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;
}
|
︙ | | |