this repo has no description
at fixPythonPipStalling 315 lines 14 kB view raw
1/* 2 * Copyright (c) 2018 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#import <Foundation/Foundation.h> 25#import <EventFactory/EventFactory.h> 26#import <arpa/inet.h> 27 28#import "StateDumpParser.h" 29 30#define TokenFlagsDescription "flagsDescription" 31#define TokenAddress "address" 32#define TokenReachabilityDescription "reachabilityDescription" 33#define TokenRank "rank" 34#define TokenOrder "order" 35#define TokenDomain "domain" 36#define TokenSearchDomains "searchDomains" 37#define TokenNameServers "nameServers" 38 39#define ResolverSearchDomainsKey @"searchDomains" 40#define ResolverNameServersKey @"nameServers" 41#define ResolverInterfaceNameKey @"interfaceName" 42#define ResolverFlagsDescriptionKey @"flagsDescription" 43#define ResolverReachabilityDescriptionKey @"reachabilityDescription" 44#define ResolverMatchDomainsKey @"matchDomains" 45 46@interface StateDumpParser () 47@property (readonly, nonatomic) NSRegularExpression *nwiRegex; 48@property (readonly, nonatomic) NSRegularExpression *dnsRegex; 49@property (readonly, nonatomic) NSRegularExpression *nameserverRegex; 50@property (readonly, nonatomic) NSRegularExpression *searchDomainRegex; 51@end 52 53@implementation StateDumpParser 54 55- (instancetype)init 56{ 57 NSError *regexError = nil; 58 59 _nwiRegex = [[NSRegularExpression alloc] initWithPattern:@"\\s+(?<"TokenInterfaceName">\\w+) : flags\\s+: \\w+ \\(.+\\)\\n" 60 "\\s+address\\s+: (?<"TokenAddress">\\S+)\\n" 61 "(\\s+VPN server\\s+: \\S+\\n)?" 62 "\\s+reach\\s+: \\w+ \\(.+\\)\\n" 63 "\\s+rank\\s+: \\w+ \\((?<"TokenRank">\\w+), (?<"TokenOrder">\\w+)\\)" 64 options:0 65 error:&regexError]; 66 if (_nwiRegex == nil || regexError != nil) { 67 specs_log_err("Failed to create NWI regex: %@", regexError); 68 return nil; 69 } 70 71 regexError = nil; 72 _dnsRegex = [[NSRegularExpression alloc] initWithPattern:@"resolver #\\d+\\n" 73 "( domain : (?<"TokenDomain">\\S+)\\n)?" 74 "(?<"TokenSearchDomains">(?: search domain\\[\\d+\\] : \\S+\\n)*)" 75 "(?<"TokenNameServers">(?: nameserver\\[\\d+\\] : \\S+\\n)*)" 76 "( if_index : \\d+ \\((?<"TokenInterfaceName">\\w+)\\)\\n)" 77 "( flags : \\w+ \\((?<"TokenFlagsDescription">.+)\\)\\n)" 78 "( reach : \\w+ \\((?<"TokenReachabilityDescription">.+)\\)\\n)" 79 options:0 80 error:&regexError]; 81 if (_dnsRegex == nil || regexError != nil) { 82 specs_log_err("Failed to create DNS configuration regex: %@", regexError); 83 return nil; 84 } 85 86 regexError = nil; 87 _nameserverRegex = [[NSRegularExpression alloc] initWithPattern:@" nameserver\\[\\d+\\] : (?<"TokenAddress">\\S+)\\n" 88 options:0 89 error:&regexError]; 90 if (_nameserverRegex == nil || regexError != nil) { 91 specs_log_err("Failed to create the nameserver regex: %@", regexError); 92 return nil; 93 } 94 95 regexError = nil; 96 _searchDomainRegex = [[NSRegularExpression alloc] initWithPattern:@" search domain\\[\\d+\\] : (?<"TokenDomain">\\S+)\\n" 97 options:0 98 error:&regexError]; 99 if (_searchDomainRegex == nil || regexError != nil) { 100 specs_log_err("Failed to create the search domain regex: %@", regexError); 101 return nil; 102 } 103 104 NSArray<EFLogEventMatch *> *matches = @[ 105 [[EFLogEventMatch alloc] initWithPattern:@"^Network information" 106 multipleNewEventHandler: 107 ^NSArray<EFEvent *> *(__unused NSTextCheckingResult *matchResult, EFLogEvent *logEvent) { 108 NSMutableDictionary<NSString *, EFNetworkControlPathEvent *> *newEvents = nil; 109 NSArray<NSTextCheckingResult *> *matches = [self.nwiRegex matchesInString:logEvent.eventMessage options:0 range:NSMakeRange(0, logEvent.eventMessage.length)]; 110 BOOL primaryV4 = YES; 111 BOOL primaryV6 = YES; 112 113 for (NSString *interfaceName in SCLogParser.interfaceMap.allKeys) { 114 SCLogParser.interfaceMap[interfaceName] = @[ ]; 115 } 116 117 for (NSTextCheckingResult *match in matches) { 118 NSString *interfaceName = [logEvent substringForCaptureGroup:@TokenInterfaceName inMatchResult:match]; 119 if (interfaceName == nil) { 120 continue; 121 } 122 EFNetworkControlPathEvent *event = newEvents[interfaceName]; 123 if (event == nil) { 124 event = [self createInterfaceEventWithLogEvent:logEvent matchResult:match]; 125 if (newEvents == nil) { 126 newEvents = [[NSMutableDictionary alloc] init]; 127 } 128 newEvents[event.interfaceBSDName] = event; 129 event.primaryStateIPv4 = EFPrimaryStateNotPrimary; 130 event.primaryStateIPv6 = EFPrimaryStateNotPrimary; 131 } 132 NSString *addressString = [logEvent substringForCaptureGroup:@TokenAddress inMatchResult:match]; 133 if (addressString.length > 0) { 134 if (primaryV4 || primaryV6) { 135 sa_family_t addressFamily = [self getAddressFamilyOfAddress:addressString]; 136 if (primaryV4 && addressFamily == AF_INET) { 137 event.primaryStateIPv4 = EFPrimaryStatePrimary; 138 primaryV4 = NO; 139 } else if (primaryV6 && addressFamily == AF_INET6) { 140 event.primaryStateIPv6 = EFPrimaryStatePrimary; 141 primaryV6 = NO; 142 } 143 } 144 [self addAddress:addressString toInterfaceEvent:event]; 145 } 146 NSString *rankString = [logEvent substringForCaptureGroup:@TokenRank inMatchResult:match]; 147 if (rankString.length > 0) { 148 event.rank = rankString; 149 } 150 NSString *orderString = [logEvent substringForCaptureGroup:@TokenOrder inMatchResult:match]; 151 if (orderString.length > 0) { 152 if ([orderString isEqualToString:@"Last"]) { 153 event.order = -1; 154 } else { 155 event.order = orderString.integerValue; 156 } 157 } 158 } 159 return newEvents.allValues; 160 }], 161 [[EFLogEventMatch alloc] initWithPattern:@"^DNS Configuration" 162 multipleNewEventHandler: 163 ^NSArray<EFEvent *> *(__unused NSTextCheckingResult *matchResult, EFLogEvent *logEvent) { 164 NSMutableArray<EFNetworkControlPathEvent *> *newEvents = nil; 165 NSArray<NSTextCheckingResult *> *matches = [self.dnsRegex matchesInString:logEvent.eventMessage options:0 range:NSMakeRange(0, logEvent.eventMessage.length)]; 166 NSMutableDictionary<NSString *, NSDictionary<NSString *, NSObject *> *> *interfaceDNSConfigurations = nil; 167 NSMutableArray<NSDictionary<NSString *, NSObject *> *> *orderedDNSConfigurations = nil; 168 169 for (NSTextCheckingResult *match in matches) { 170 NSMutableDictionary<NSString *, NSObject *> *dnsConfiguration = [[NSMutableDictionary alloc] init]; 171 NSString *matchDomain = [logEvent substringForCaptureGroup:@TokenDomain inMatchResult:match]; 172 BOOL scoped = NO; 173 if (matchDomain.length > 0) { 174 NSArray<NSString *> *domains = (NSArray<NSString *> *)dnsConfiguration[ResolverMatchDomainsKey]; 175 dnsConfiguration[ResolverMatchDomainsKey] = [self addUniqueString:matchDomain toArray:domains]; 176 } 177 NSString *searchDomainsString = [logEvent substringForCaptureGroup:@TokenSearchDomains inMatchResult:match]; 178 if (searchDomainsString.length > 0) { 179 [self addSubstringsFromString:searchDomainsString 180 forCaptureGroup:@TokenDomain 181 inRegex:self.searchDomainRegex 182 toArrayAtKey:ResolverSearchDomainsKey 183 inDictionary:dnsConfiguration]; 184 } 185 NSString *nameServersString = [logEvent substringForCaptureGroup:@TokenNameServers inMatchResult:match]; 186 if (nameServersString.length > 0) { 187 [self addSubstringsFromString:nameServersString 188 forCaptureGroup:@TokenAddress 189 inRegex:self.nameserverRegex 190 toArrayAtKey:ResolverNameServersKey 191 inDictionary:dnsConfiguration]; 192 } 193 NSString *flagsDescription = [logEvent substringForCaptureGroup:@TokenFlagsDescription inMatchResult:match]; 194 if (flagsDescription.length > 0) { 195 dnsConfiguration[ResolverFlagsDescriptionKey] = flagsDescription; 196 if ([flagsDescription containsString:@"Scoped"]) { 197 scoped = YES; 198 } 199 } 200 NSString *reachabilityDescription = [logEvent substringForCaptureGroup:@TokenReachabilityDescription inMatchResult:match]; 201 if (reachabilityDescription.length > 0) { 202 dnsConfiguration[ResolverReachabilityDescriptionKey] = reachabilityDescription; 203 } 204 205 NSString *interfaceName = [logEvent substringForCaptureGroup:@TokenInterfaceName inMatchResult:match]; 206 if (interfaceName != nil) { 207 dnsConfiguration[ResolverInterfaceNameKey] = interfaceName; 208 } 209 210 NSDictionary<NSString *, NSObject *> *newConfiguration = nil; 211 if (interfaceName != nil && (scoped || matchDomain.length > 0)) { 212 NSDictionary<NSString *, NSObject *> *existingConfiguration = interfaceDNSConfigurations[interfaceName]; 213 if (existingConfiguration != nil) { 214 if (matchDomain.length > 0) { 215 NSArray<NSString *> *matchDomains = (NSArray<NSString *> *)existingConfiguration[ResolverMatchDomainsKey]; 216 dnsConfiguration[ResolverMatchDomainsKey] = [self addUniqueString:matchDomain toArray:matchDomains]; 217 } else { 218 dnsConfiguration[ResolverMatchDomainsKey] = existingConfiguration[ResolverMatchDomainsKey]; 219 } 220 } 221 newConfiguration = [[NSDictionary alloc] initWithDictionary:dnsConfiguration]; 222 if (interfaceDNSConfigurations == nil) { 223 interfaceDNSConfigurations = [[NSMutableDictionary alloc] init]; 224 } 225 interfaceDNSConfigurations[interfaceName] = newConfiguration; 226 } else { 227 newConfiguration = [[NSDictionary alloc] initWithDictionary:dnsConfiguration]; 228 } 229 230 if (!scoped) { 231 if (orderedDNSConfigurations == nil) { 232 orderedDNSConfigurations = [[NSMutableArray alloc] init]; 233 } 234 NSUInteger existingIndex = [orderedDNSConfigurations indexOfObjectPassingTest: 235 ^BOOL(NSDictionary<NSString *,NSObject *> *obj, __unused NSUInteger idx, __unused BOOL *stop) { 236 NSString *existingInterfaceName = (NSString *)obj[ResolverInterfaceNameKey]; 237 return (existingInterfaceName != nil && [interfaceName isEqualToString:existingInterfaceName]); 238 }]; 239 if (existingIndex == NSNotFound) { 240 [orderedDNSConfigurations addObject:newConfiguration]; 241 } else { 242 orderedDNSConfigurations[existingIndex] = newConfiguration; 243 } 244 } 245 } 246 247 for (NSString *interfaceName in interfaceDNSConfigurations) { 248 NSDictionary<NSString *, NSObject *> *dnsConfiguration = interfaceDNSConfigurations[interfaceName]; 249 if (dnsConfiguration == nil || ![NSJSONSerialization isValidJSONObject:dnsConfiguration]) { 250 specs_log_err("DNS configuration is not valid JSON: %@", dnsConfiguration); 251 continue; 252 } 253 NSError *jsonError = nil; 254 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dnsConfiguration options:NSJSONWritingPrettyPrinted error:&jsonError]; 255 if (jsonData == nil) { 256 specs_log_err("Failed to generate JSON from %@: %@", dnsConfiguration, jsonError); 257 continue; 258 } 259 EFNetworkControlPathEvent *newEvent = [self createInterfaceEventWithLogEvent:logEvent interfaceName:interfaceName]; 260 newEvent.dnsConfiguration = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 261 262 if (newEvents == nil) { 263 newEvents = [[NSMutableArray alloc] init]; 264 } 265 [newEvents addObject:newEvent]; 266 } 267 if (orderedDNSConfigurations.count > 0) { 268 NSError *jsonError = nil; 269 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:orderedDNSConfigurations options:NSJSONWritingPrettyPrinted error:&jsonError]; 270 if (jsonData != nil) { 271 NSData *subsystemIdentifier = [self createSubsystemIdentifier]; 272 EFNetworkControlPathEvent *newEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:subsystemIdentifier]; 273 newEvent.interfaceBSDName = @"system"; 274 newEvent.interfaceDescription = @"System Configuration"; 275 newEvent.dnsConfiguration = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 276 277 if (newEvents == nil) { 278 newEvents = [[NSMutableArray alloc] init]; 279 } 280 [newEvents addObject:newEvent]; 281 } 282 } 283 for (NSString *interfaceName in SCLogParser.interfaceMap) { 284 if (interfaceDNSConfigurations[interfaceName] == nil) { 285 EFNetworkControlPathEvent *newEvent = [self createInterfaceEventWithLogEvent:logEvent interfaceName:interfaceName]; 286 newEvent.dnsConfiguration = EFNetworkControlPathEvent.configurationNotSet; 287 if (newEvents == nil) { 288 newEvents = [[NSMutableArray alloc] init]; 289 } 290 [newEvents addObject:newEvent]; 291 } 292 } 293 return newEvents; 294 }], 295 ]; 296 EFLogEventParser *parser = [[EFLogEventParser alloc] initWithMatches:matches]; 297 return [super initWithCategory:@"StateDump" eventParser:parser]; 298} 299 300- (void)addSubstringsFromString:(NSString *)string forCaptureGroup:(NSString *)groupName inRegex:(NSRegularExpression *)regex toArrayAtKey:(NSString *)configKey inDictionary:(NSMutableDictionary<NSString *, NSObject *> *)dictionary 301{ 302 NSArray<NSTextCheckingResult *> *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)]; 303 for (NSTextCheckingResult *match in matches) { 304 NSRange groupRange = [match rangeWithName:groupName]; 305 if (!NSEqualRanges(groupRange, NSMakeRange(NSNotFound, 0))) { 306 NSString *substring = [string substringWithRange:groupRange]; 307 if (substring.length > 0) { 308 NSArray<NSString *> *existingList = (NSArray<NSString *> *)dictionary[configKey]; 309 dictionary[configKey] = [self addUniqueString:substring toArray:existingList]; 310 } 311 } 312 } 313} 314 315@end