Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
14 kB · 315 lines
Objective-C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316/* * Copyright (c) 2018 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */
#import <Foundation/Foundation.h>#import <EventFactory/EventFactory.h>#import <arpa/inet.h>
#import "StateDumpParser.h"
#define TokenFlagsDescription "flagsDescription"#define TokenAddress "address"#define TokenReachabilityDescription "reachabilityDescription"#define TokenRank "rank"#define TokenOrder "order"#define TokenDomain "domain"#define TokenSearchDomains "searchDomains"#define TokenNameServers "nameServers"
#define ResolverSearchDomainsKey @"searchDomains"#define ResolverNameServersKey @"nameServers"#define ResolverInterfaceNameKey @"interfaceName"#define ResolverFlagsDescriptionKey @"flagsDescription"#define ResolverReachabilityDescriptionKey @"reachabilityDescription"#define ResolverMatchDomainsKey @"matchDomains"
@interface StateDumpParser ()@property (readonly, nonatomic) NSRegularExpression *nwiRegex;@property (readonly, nonatomic) NSRegularExpression *dnsRegex;@property (readonly, nonatomic) NSRegularExpression *nameserverRegex;@property (readonly, nonatomic) NSRegularExpression *searchDomainRegex;@end
@implementation StateDumpParser
- (instancetype)init{ NSError *regexError = nil;
_nwiRegex = [[NSRegularExpression alloc] initWithPattern:@"\\s+(?<"TokenInterfaceName">\\w+) : flags\\s+: \\w+ \\(.+\\)\\n" "\\s+address\\s+: (?<"TokenAddress">\\S+)\\n" "(\\s+VPN server\\s+: \\S+\\n)?" "\\s+reach\\s+: \\w+ \\(.+\\)\\n" "\\s+rank\\s+: \\w+ \\((?<"TokenRank">\\w+), (?<"TokenOrder">\\w+)\\)" options:0 error:®exError]; if (_nwiRegex == nil || regexError != nil) { specs_log_err("Failed to create NWI regex: %@", regexError); return nil; }
regexError = nil; _dnsRegex = [[NSRegularExpression alloc] initWithPattern:@"resolver #\\d+\\n" "( domain : (?<"TokenDomain">\\S+)\\n)?" "(?<"TokenSearchDomains">(?: search domain\\[\\d+\\] : \\S+\\n)*)" "(?<"TokenNameServers">(?: nameserver\\[\\d+\\] : \\S+\\n)*)" "( if_index : \\d+ \\((?<"TokenInterfaceName">\\w+)\\)\\n)" "( flags : \\w+ \\((?<"TokenFlagsDescription">.+)\\)\\n)" "( reach : \\w+ \\((?<"TokenReachabilityDescription">.+)\\)\\n)" options:0 error:®exError]; if (_dnsRegex == nil || regexError != nil) { specs_log_err("Failed to create DNS configuration regex: %@", regexError); return nil; }
regexError = nil; _nameserverRegex = [[NSRegularExpression alloc] initWithPattern:@" nameserver\\[\\d+\\] : (?<"TokenAddress">\\S+)\\n" options:0 error:®exError]; if (_nameserverRegex == nil || regexError != nil) { specs_log_err("Failed to create the nameserver regex: %@", regexError); return nil; }
regexError = nil; _searchDomainRegex = [[NSRegularExpression alloc] initWithPattern:@" search domain\\[\\d+\\] : (?<"TokenDomain">\\S+)\\n" options:0 error:®exError]; if (_searchDomainRegex == nil || regexError != nil) { specs_log_err("Failed to create the search domain regex: %@", regexError); return nil; }
NSArray<EFLogEventMatch *> *matches = @[ [[EFLogEventMatch alloc] initWithPattern:@"^Network information" multipleNewEventHandler: ^NSArray<EFEvent *> *(__unused NSTextCheckingResult *matchResult, EFLogEvent *logEvent) { NSMutableDictionary<NSString *, EFNetworkControlPathEvent *> *newEvents = nil; NSArray<NSTextCheckingResult *> *matches = [self.nwiRegex matchesInString:logEvent.eventMessage options:0 range:NSMakeRange(0, logEvent.eventMessage.length)]; BOOL primaryV4 = YES; BOOL primaryV6 = YES;
for (NSString *interfaceName in SCLogParser.interfaceMap.allKeys) { SCLogParser.interfaceMap[interfaceName] = @[ ]; }
for (NSTextCheckingResult *match in matches) { NSString *interfaceName = [logEvent substringForCaptureGroup:@TokenInterfaceName inMatchResult:match]; if (interfaceName == nil) { continue; } EFNetworkControlPathEvent *event = newEvents[interfaceName]; if (event == nil) { event = [self createInterfaceEventWithLogEvent:logEvent matchResult:match]; if (newEvents == nil) { newEvents = [[NSMutableDictionary alloc] init]; } newEvents[event.interfaceBSDName] = event; event.primaryStateIPv4 = EFPrimaryStateNotPrimary; event.primaryStateIPv6 = EFPrimaryStateNotPrimary; } NSString *addressString = [logEvent substringForCaptureGroup:@TokenAddress inMatchResult:match]; if (addressString.length > 0) { if (primaryV4 || primaryV6) { sa_family_t addressFamily = [self getAddressFamilyOfAddress:addressString]; if (primaryV4 && addressFamily == AF_INET) { event.primaryStateIPv4 = EFPrimaryStatePrimary; primaryV4 = NO; } else if (primaryV6 && addressFamily == AF_INET6) { event.primaryStateIPv6 = EFPrimaryStatePrimary; primaryV6 = NO; } } [self addAddress:addressString toInterfaceEvent:event]; } NSString *rankString = [logEvent substringForCaptureGroup:@TokenRank inMatchResult:match]; if (rankString.length > 0) { event.rank = rankString; } NSString *orderString = [logEvent substringForCaptureGroup:@TokenOrder inMatchResult:match]; if (orderString.length > 0) { if ([orderString isEqualToString:@"Last"]) { event.order = -1; } else { event.order = orderString.integerValue; } } } return newEvents.allValues; }], [[EFLogEventMatch alloc] initWithPattern:@"^DNS Configuration" multipleNewEventHandler: ^NSArray<EFEvent *> *(__unused NSTextCheckingResult *matchResult, EFLogEvent *logEvent) { NSMutableArray<EFNetworkControlPathEvent *> *newEvents = nil; NSArray<NSTextCheckingResult *> *matches = [self.dnsRegex matchesInString:logEvent.eventMessage options:0 range:NSMakeRange(0, logEvent.eventMessage.length)]; NSMutableDictionary<NSString *, NSDictionary<NSString *, NSObject *> *> *interfaceDNSConfigurations = nil; NSMutableArray<NSDictionary<NSString *, NSObject *> *> *orderedDNSConfigurations = nil;
for (NSTextCheckingResult *match in matches) { NSMutableDictionary<NSString *, NSObject *> *dnsConfiguration = [[NSMutableDictionary alloc] init]; NSString *matchDomain = [logEvent substringForCaptureGroup:@TokenDomain inMatchResult:match]; BOOL scoped = NO; if (matchDomain.length > 0) { NSArray<NSString *> *domains = (NSArray<NSString *> *)dnsConfiguration[ResolverMatchDomainsKey]; dnsConfiguration[ResolverMatchDomainsKey] = [self addUniqueString:matchDomain toArray:domains]; } NSString *searchDomainsString = [logEvent substringForCaptureGroup:@TokenSearchDomains inMatchResult:match]; if (searchDomainsString.length > 0) { [self addSubstringsFromString:searchDomainsString forCaptureGroup:@TokenDomain inRegex:self.searchDomainRegex toArrayAtKey:ResolverSearchDomainsKey inDictionary:dnsConfiguration]; } NSString *nameServersString = [logEvent substringForCaptureGroup:@TokenNameServers inMatchResult:match]; if (nameServersString.length > 0) { [self addSubstringsFromString:nameServersString forCaptureGroup:@TokenAddress inRegex:self.nameserverRegex toArrayAtKey:ResolverNameServersKey inDictionary:dnsConfiguration]; } NSString *flagsDescription = [logEvent substringForCaptureGroup:@TokenFlagsDescription inMatchResult:match]; if (flagsDescription.length > 0) { dnsConfiguration[ResolverFlagsDescriptionKey] = flagsDescription; if ([flagsDescription containsString:@"Scoped"]) { scoped = YES; } } NSString *reachabilityDescription = [logEvent substringForCaptureGroup:@TokenReachabilityDescription inMatchResult:match]; if (reachabilityDescription.length > 0) { dnsConfiguration[ResolverReachabilityDescriptionKey] = reachabilityDescription; }
NSString *interfaceName = [logEvent substringForCaptureGroup:@TokenInterfaceName inMatchResult:match]; if (interfaceName != nil) { dnsConfiguration[ResolverInterfaceNameKey] = interfaceName; }
NSDictionary<NSString *, NSObject *> *newConfiguration = nil; if (interfaceName != nil && (scoped || matchDomain.length > 0)) { NSDictionary<NSString *, NSObject *> *existingConfiguration = interfaceDNSConfigurations[interfaceName]; if (existingConfiguration != nil) { if (matchDomain.length > 0) { NSArray<NSString *> *matchDomains = (NSArray<NSString *> *)existingConfiguration[ResolverMatchDomainsKey]; dnsConfiguration[ResolverMatchDomainsKey] = [self addUniqueString:matchDomain toArray:matchDomains]; } else { dnsConfiguration[ResolverMatchDomainsKey] = existingConfiguration[ResolverMatchDomainsKey]; } } newConfiguration = [[NSDictionary alloc] initWithDictionary:dnsConfiguration]; if (interfaceDNSConfigurations == nil) { interfaceDNSConfigurations = [[NSMutableDictionary alloc] init]; } interfaceDNSConfigurations[interfaceName] = newConfiguration; } else { newConfiguration = [[NSDictionary alloc] initWithDictionary:dnsConfiguration]; }
if (!scoped) { if (orderedDNSConfigurations == nil) { orderedDNSConfigurations = [[NSMutableArray alloc] init]; } NSUInteger existingIndex = [orderedDNSConfigurations indexOfObjectPassingTest: ^BOOL(NSDictionary<NSString *,NSObject *> *obj, __unused NSUInteger idx, __unused BOOL *stop) { NSString *existingInterfaceName = (NSString *)obj[ResolverInterfaceNameKey]; return (existingInterfaceName != nil && [interfaceName isEqualToString:existingInterfaceName]); }]; if (existingIndex == NSNotFound) { [orderedDNSConfigurations addObject:newConfiguration]; } else { orderedDNSConfigurations[existingIndex] = newConfiguration; } } }
for (NSString *interfaceName in interfaceDNSConfigurations) { NSDictionary<NSString *, NSObject *> *dnsConfiguration = interfaceDNSConfigurations[interfaceName]; if (dnsConfiguration == nil || ![NSJSONSerialization isValidJSONObject:dnsConfiguration]) { specs_log_err("DNS configuration is not valid JSON: %@", dnsConfiguration); continue; } NSError *jsonError = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dnsConfiguration options:NSJSONWritingPrettyPrinted error:&jsonError]; if (jsonData == nil) { specs_log_err("Failed to generate JSON from %@: %@", dnsConfiguration, jsonError); continue; } EFNetworkControlPathEvent *newEvent = [self createInterfaceEventWithLogEvent:logEvent interfaceName:interfaceName]; newEvent.dnsConfiguration = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (newEvents == nil) { newEvents = [[NSMutableArray alloc] init]; } [newEvents addObject:newEvent]; } if (orderedDNSConfigurations.count > 0) { NSError *jsonError = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:orderedDNSConfigurations options:NSJSONWritingPrettyPrinted error:&jsonError]; if (jsonData != nil) { NSData *subsystemIdentifier = [self createSubsystemIdentifier]; EFNetworkControlPathEvent *newEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:subsystemIdentifier]; newEvent.interfaceBSDName = @"system"; newEvent.interfaceDescription = @"System Configuration"; newEvent.dnsConfiguration = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (newEvents == nil) { newEvents = [[NSMutableArray alloc] init]; } [newEvents addObject:newEvent]; } } for (NSString *interfaceName in SCLogParser.interfaceMap) { if (interfaceDNSConfigurations[interfaceName] == nil) { EFNetworkControlPathEvent *newEvent = [self createInterfaceEventWithLogEvent:logEvent interfaceName:interfaceName]; newEvent.dnsConfiguration = EFNetworkControlPathEvent.configurationNotSet; if (newEvents == nil) { newEvents = [[NSMutableArray alloc] init]; } [newEvents addObject:newEvent]; } } return newEvents; }], ]; EFLogEventParser *parser = [[EFLogEventParser alloc] initWithMatches:matches]; return [super initWithCategory:@"StateDump" eventParser:parser];}
- (void)addSubstringsFromString:(NSString *)string forCaptureGroup:(NSString *)groupName inRegex:(NSRegularExpression *)regex toArrayAtKey:(NSString *)configKey inDictionary:(NSMutableDictionary<NSString *, NSObject *> *)dictionary{ NSArray<NSTextCheckingResult *> *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)]; for (NSTextCheckingResult *match in matches) { NSRange groupRange = [match rangeWithName:groupName]; if (!NSEqualRanges(groupRange, NSMakeRange(NSNotFound, 0))) { NSString *substring = [string substringWithRange:groupRange]; if (substring.length > 0) { NSArray<NSString *> *existingList = (NSArray<NSString *> *)dictionary[configKey]; dictionary[configKey] = [self addUniqueString:substring toArray:existingList]; } } }}
@end