2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #import <Foundation/Foundation.h>
25 #import <EventFactory/EventFactory.h>
28 #import "SCLogParser.h"
30 @interface SCLogParser ()
31 @property uint64_t nextEventCounter;
34 @implementation SCLogParser
36 - (instancetype)initWithCategory:(NSString *)category eventParser:(EFLogEventParser *)eventParser
41 _eventParser = eventParser;
42 _nextEventCounter = 1;
47 + (NSMutableDictionary<NSString *, NSArray<NSString *> *> *)interfaceMap
49 static NSMutableDictionary<NSString *, NSArray<NSString *> *> *_interfaceMap = nil;
50 static dispatch_once_t onceToken;
51 dispatch_once(&onceToken, ^{
52 _interfaceMap = [[NSMutableDictionary alloc] init];
57 - (NSData *)createSubsystemIdentifier
59 NSString *identifierString = [[NSString alloc] initWithFormat:@"%@.%llu", _category, _nextEventCounter];
61 const char *utf8String = identifierString.UTF8String;
62 return [[NSData alloc] initWithBytes:utf8String length:strlen(utf8String)];
65 - (NSArray<NSString *> *)addUniqueString:(NSString *)newString toArray:(NSArray<NSString *> *)array
67 if (array.count > 0) {
68 NSInteger index = [array indexOfObject:newString];
69 return (index == NSNotFound ? [array arrayByAddingObject:newString] : array);
71 return @[ newString ];
75 - (NSArray<NSString *> *)addUniqueStrings:(NSArray<NSString *> *)strings toArray:(NSArray<NSString *> *)array
81 NSMutableArray<NSString *> *uniqueStrings = [[NSMutableArray alloc] init];
82 for (NSString *string in strings) {
83 NSInteger index = [array indexOfObject:string];
84 if (index == NSNotFound) {
85 [uniqueStrings addObject:string];
88 if (uniqueStrings.count > 0) {
89 return [array arrayByAddingObjectsFromArray:uniqueStrings];
95 - (EFNetworkControlPathEvent *)createInterfaceEventWithLogEvent:(EFLogEvent *)logEvent matchResult:(NSTextCheckingResult *)matchResult
97 EFNetworkControlPathEvent *newEvent = nil;
98 NSString *interfaceName = [logEvent substringForCaptureGroup:@TokenInterfaceName inMatchResult:matchResult];
99 if (interfaceName != nil) {
100 if (SCLogParser.interfaceMap[interfaceName] == nil) {
101 SCLogParser.interfaceMap[interfaceName] = @[];
103 NSData *identifier = [self createSubsystemIdentifier];
104 newEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:identifier];
105 newEvent.interfaceBSDName = interfaceName;
110 - (EFNetworkControlPathEvent *)createInterfaceEventWithLogEvent:(EFLogEvent *)logEvent interfaceName:(NSString *)interfaceName
112 EFNetworkControlPathEvent *newEvent = nil;
113 if (SCLogParser.interfaceMap[interfaceName] == nil) {
114 SCLogParser.interfaceMap[interfaceName] = @[];
116 NSData *identifier = [self createSubsystemIdentifier];
117 newEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:identifier];
118 newEvent.interfaceBSDName = interfaceName;
122 - (void)addAddress:(NSString *)addressString toInterfaceEvent:(EFNetworkControlPathEvent *)event
124 if (event.interfaceBSDName != nil) {
125 NSArray<NSString *> *addresses = SCLogParser.interfaceMap[event.interfaceBSDName];
126 event.addresses = [self addUniqueString:addressString toArray:addresses];
127 SCLogParser.interfaceMap[event.interfaceBSDName] = event.addresses;
131 - (BOOL)removeAddress:(NSString *)addressString fromInterfaceEvent:(EFNetworkControlPathEvent *)event
133 if (event.interfaceBSDName != nil) {
134 NSArray<NSString *> *addresses = SCLogParser.interfaceMap[event.interfaceBSDName];
135 if (addresses.count > 0) {
136 NSPredicate *matchPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, __unused NSDictionary<NSString *,id> *bindings) {
137 NSString *matchString = (NSString *)evaluatedObject;
138 if (matchString != nil) {
139 return ![matchString isEqualToString:addressString];
144 event.addresses = [addresses filteredArrayUsingPredicate:matchPredicate];
145 SCLogParser.interfaceMap[event.interfaceBSDName] = event.addresses;
153 - (NSString *)substringOfString:(NSString *)matchedString forCaptureGroup:(NSString *)groupName inMatchResult:(NSTextCheckingResult *)result
155 NSString *substring = nil;
156 NSRange groupRange = [result rangeWithName:groupName];
157 if (!NSEqualRanges(groupRange, NSMakeRange(NSNotFound, 0))) {
158 substring = [matchedString substringWithRange:groupRange];
163 - (sa_family_t)getAddressFamilyOfAddress:(NSString *)addressString
165 sa_family_t af = AF_UNSPEC;
166 struct in6_addr v6addr;
167 struct in_addr v4addr;
169 if (inet_pton(AF_INET6, addressString.UTF8String, &v6addr) == 1) {
171 } else if (inet_pton(AF_INET, addressString.UTF8String, &v4addr)) {