︙ | | | ︙ | |
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFString.h"
#import "OFUDPSocket.h"
#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif
#import "OFInvalidArgumentException.h"
#import "OFInvalidServerReplyException.h"
|
>
|
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFString.h"
#import "OFTimer.h"
#import "OFUDPSocket.h"
#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif
#import "OFInvalidArgumentException.h"
#import "OFInvalidServerReplyException.h"
|
︙ | | | ︙ | |
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
|
* RFC 1035 doesn't specify if pointers to pointers are allowed, and if so how
* many. Since it's unspecified, we have to assume that it might happen, but we
* also want to limit it to avoid DoS. Limiting it to 16 levels of pointers and
* immediately rejecting pointers to itself seems like a fair balance.
*/
#define MAX_ALLOWED_POINTERS 16
/*
* TODO:
*
* - Timeouts
* - Resolve with each search domain
* - Iterate through name servers
* - Fallback to TCP
*/
@interface OFDNSResolver_context: OFObject
{
OFString *_host;
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;
OFMutableData *_queryData;
id _target;
SEL _selector;
id _userContext;
}
@property (readonly, nonatomic) OFString *host;
@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass;
@property (readonly, nonatomic) of_dns_resource_record_type_t recordType;
@property (readonly, nonatomic) OFNumber *ID;
@property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers;
@property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains;
@property (nonatomic) size_t nameServersIndex;
@property (nonatomic) size_t searchDomainsIndex;
@property (readonly, nonatomic) OFMutableData *queryData;
@property (readonly, nonatomic) id target;
@property (readonly, nonatomic) SEL selector;
@property (readonly, nonatomic) id userContext;
- (instancetype)initWithHost: (OFString *)host
recordClass: (of_dns_resource_record_class_t)recordClass
recordType: (of_dns_resource_record_type_t)recordType
ID: (OFNumber *)ID
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
queryData: (OFMutableData *)queryData
target: (id)target
selector: (SEL)selector
userContext: (id)userContext;
@end
@interface OFDNSResolver ()
#ifdef OF_HAVE_FILES
- (void)of_parseHosts: (OFString *)path;
# ifndef OF_WINDOWS
- (void)of_parseResolvConf: (OFString *)path;
|
>
>
<
>
>
|
>
|
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
|
* RFC 1035 doesn't specify if pointers to pointers are allowed, and if so how
* many. Since it's unspecified, we have to assume that it might happen, but we
* also want to limit it to avoid DoS. Limiting it to 16 levels of pointers and
* immediately rejecting pointers to itself seems like a fair balance.
*/
#define MAX_ALLOWED_POINTERS 16
#define TIMEOUT 2
/*
* TODO:
*
* - Resolve with each search domain
* - Iterate through name servers
* - Fallback to TCP
*/
@interface OFDNSResolver_context: OFObject
{
OFString *_host;
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;
OFMutableData *_queryData;
id _target;
SEL _selector;
id _userContext;
OFTimer *_timer;
}
@property (readonly, nonatomic) OFString *host;
@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass;
@property (readonly, nonatomic) of_dns_resource_record_type_t recordType;
@property (readonly, nonatomic) OFNumber *ID;
@property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers;
@property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains;
@property (nonatomic) size_t nameServersIndex;
@property (nonatomic) size_t searchDomainsIndex;
@property (readonly, nonatomic) OFMutableData *queryData;
@property (readonly, nonatomic) id target;
@property (readonly, nonatomic) SEL selector;
@property (readonly, nonatomic) id userContext;
@property (readonly, nonatomic) OFTimer *timer;
- (instancetype)initWithHost: (OFString *)host
recordClass: (of_dns_resource_record_class_t)recordClass
recordType: (of_dns_resource_record_type_t)recordType
ID: (OFNumber *)ID
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
queryData: (OFMutableData *)queryData
target: (id)target
selector: (SEL)selector
userContext: (id)userContext
timer: (OFTimer *)timer;
@end
@interface OFDNSResolver ()
#ifdef OF_HAVE_FILES
- (void)of_parseHosts: (OFString *)path;
# ifndef OF_WINDOWS
- (void)of_parseResolvConf: (OFString *)path;
|
︙ | | | ︙ | |
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
|
@implementation OFDNSResolver_context
@synthesize host = _host, recordClass = _recordClass, recordType = _recordType;
@synthesize ID = _ID, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;
@synthesize target = _target, selector = _selector, userContext = _userContext;
- (instancetype)initWithHost: (OFString *)host
recordClass: (of_dns_resource_record_class_t)recordClass
recordType: (of_dns_resource_record_type_t)recordType
ID: (OFNumber *)ID
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
queryData: (OFMutableData *)queryData
target: (id)target
selector: (SEL)selector
userContext: (id)userContext
{
self = [super init];
@try {
_host = [host copy];
_recordClass = recordClass;
_recordType = recordType;
_ID = [ID retain];
_nameServers = [nameServers copy];
_searchDomains = [searchDomains copy];
_queryData = [queryData retain];
_target = [target retain];
_selector = selector;
_userContext = [userContext retain];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_host release];
[_ID release];
[_nameServers release];
[_searchDomains release];
[_queryData release];
[_target release];
[_userContext release];
[super dealloc];
}
@end
@implementation OFDNSResolver
@synthesize staticHosts = _staticHosts, nameServers = _nameServers;
|
>
>
>
>
|
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
|
@implementation OFDNSResolver_context
@synthesize host = _host, recordClass = _recordClass, recordType = _recordType;
@synthesize ID = _ID, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;
@synthesize target = _target, selector = _selector, userContext = _userContext;
@synthesize timer = _timer;
- (instancetype)initWithHost: (OFString *)host
recordClass: (of_dns_resource_record_class_t)recordClass
recordType: (of_dns_resource_record_type_t)recordType
ID: (OFNumber *)ID
nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers
searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains
queryData: (OFMutableData *)queryData
target: (id)target
selector: (SEL)selector
userContext: (id)userContext
timer: (OFTimer *)timer
{
self = [super init];
@try {
_host = [host copy];
_recordClass = recordClass;
_recordType = recordType;
_ID = [ID retain];
_nameServers = [nameServers copy];
_searchDomains = [searchDomains copy];
_queryData = [queryData retain];
_target = [target retain];
_selector = selector;
_userContext = [userContext retain];
_timer = [timer retain];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_host release];
[_ID release];
[_nameServers release];
[_searchDomains release];
[_queryData release];
[_target release];
[_userContext release];
[_timer release];
[super dealloc];
}
@end
@implementation OFDNSResolver
@synthesize staticHosts = _staticHosts, nameServers = _nameServers;
|
︙ | | | ︙ | |
902
903
904
905
906
907
908
909
910
911
912
913
914
915
|
ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]];
DNSResolverContext = [[[_queries objectForKey: ID] retain] autorelease];
if (DNSResolverContext == nil)
return false;
[_queries removeObjectForKey: ID];
target = [DNSResolverContext target];
selector = [DNSResolverContext selector];
callback = (void (*)(id, SEL, OFArray *, id, id))
[target methodForSelector: selector];
queryData = [DNSResolverContext queryData];
|
>
|
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
|
ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]];
DNSResolverContext = [[[_queries objectForKey: ID] retain] autorelease];
if (DNSResolverContext == nil)
return false;
[[DNSResolverContext timer] invalidate];
[_queries removeObjectForKey: ID];
target = [DNSResolverContext target];
selector = [DNSResolverContext selector];
callback = (void (*)(id, SEL, OFArray *, id, id))
[target methodForSelector: selector];
queryData = [DNSResolverContext queryData];
|
︙ | | | ︙ | |
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
|
}
callback(target, selector, answers, [DNSResolverContext userContext],
nil);
return false;
}
- (size_t)of_socket: (OFUDPSocket *)sock
didSendBuffer: (void **)buffer
bytesSent: (size_t)bytesSent
receiver: (of_socket_address_t *)receiver
context: (id)DNSResolverContext
exception: (id)exception
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
|
}
callback(target, selector, answers, [DNSResolverContext userContext],
nil);
return false;
}
- (void)of_queryWithIDTimedOut: (OFNumber *)ID
{
OFDNSResolver_context *DNSResolverContext = [_queries objectForKey: ID];
id target;
SEL selector;
void (*callback)(id, SEL, OFArray *, id, id);
OFResolveHostFailedException *exception;
if (DNSResolverContext == nil)
return;
target = [[[DNSResolverContext target] retain] autorelease];
selector = [DNSResolverContext selector];
callback = (void (*)(id, SEL, OFArray *, id, id))
[target methodForSelector: selector];
exception = [OFResolveHostFailedException
exceptionWithHost: [DNSResolverContext host]
recordClass: [DNSResolverContext recordClass]
recordType: [DNSResolverContext recordType]
error: OF_DNS_RESOLVER_ERROR_TIMEOUT];
[_queries removeObjectForKey: [DNSResolverContext ID]];
callback(target, selector, nil,
[DNSResolverContext userContext], exception);
}
- (size_t)of_socket: (OFUDPSocket *)sock
didSendBuffer: (void **)buffer
bytesSent: (size_t)bytesSent
receiver: (of_socket_address_t *)receiver
context: (id)DNSResolverContext
exception: (id)exception
|
︙ | | | ︙ | |
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
|
recordType: (of_dns_resource_record_type_t)recordType
target: (id)target
selector: (SEL)selector
context: (id)context
{
void *pool = objc_autoreleasePoolPush();
OFMutableData *data = [OFMutableData dataWithCapacity: 512];
OFDNSResolver_context *DNSResolverContext;
OFNumber *ID;
uint16_t tmp;
OFUDPSocket *sock;
of_socket_address_t address;
/* TODO: Properly try all search domains */
|
>
|
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
|
recordType: (of_dns_resource_record_type_t)recordType
target: (id)target
selector: (SEL)selector
context: (id)context
{
void *pool = objc_autoreleasePoolPush();
OFMutableData *data = [OFMutableData dataWithCapacity: 512];
OFTimer *timer;
OFDNSResolver_context *DNSResolverContext;
OFNumber *ID;
uint16_t tmp;
OFUDPSocket *sock;
of_socket_address_t address;
/* TODO: Properly try all search domains */
|
︙ | | | ︙ | |
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
|
count: 2];
/* QCLASS */
tmp = OF_BSWAP16_IF_LE(recordClass);
[data addItems: &tmp
count: 2];
DNSResolverContext = [[[OFDNSResolver_context alloc]
initWithHost: host
recordClass: recordClass
recordType: recordType
ID: ID
nameServers: _nameServers
searchDomains: _searchDomains
queryData: data
target: target
selector: selector
userContext: context] autorelease];
[_queries setObject: DNSResolverContext
forKey: ID];
address = of_socket_address_parse_ip(
[[DNSResolverContext nameServers] firstObject], 53);
#ifdef OF_HAVE_IPV6
|
>
>
>
>
>
>
>
|
>
|
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
1210
1211
1212
1213
1214
|
count: 2];
/* QCLASS */
tmp = OF_BSWAP16_IF_LE(recordClass);
[data addItems: &tmp
count: 2];
timer = [OFTimer
scheduledTimerWithTimeInterval: TIMEOUT
target: self
selector: @selector(of_queryWithIDTimedOut:)
object: ID
repeats: false];
DNSResolverContext = [[[OFDNSResolver_context alloc]
initWithHost: host
recordClass: recordClass
recordType: recordType
ID: ID
nameServers: _nameServers
searchDomains: _searchDomains
queryData: data
target: target
selector: selector
userContext: context
timer: timer] autorelease];
[_queries setObject: DNSResolverContext
forKey: ID];
address = of_socket_address_parse_ip(
[[DNSResolverContext nameServers] firstObject], 53);
#ifdef OF_HAVE_IPV6
|
︙ | | | ︙ | |