1 /* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*- 2 * 3 * Copyright (c) 2002-2018 Apple Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #ifndef __mDNSMacOSX_h 19 #define __mDNSMacOSX_h 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 #include <SystemConfiguration/SystemConfiguration.h> 26 #include <IOKit/pwr_mgt/IOPM.h> 27 #include <IOKit/pwr_mgt/IOPMLib.h> 28 #include <IOKit/pwr_mgt/IOPMLibPrivate.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include "mDNSEmbeddedAPI.h" // for domain name structure 32 #include "mdns_private.h" // for mdns_interface_monitor_t struct 33 34 #include <net/if.h> 35 #include <os/log.h> 36 37 //#define MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 38 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 39 #include <dispatch/dispatch.h> 40 #include <dispatch/private.h> 41 #endif 42 43 #if TARGET_OS_IPHONE 44 #define NO_SECURITYFRAMEWORK 1 45 #define NO_CFUSERNOTIFICATION 1 46 #endif 47 48 #ifndef NO_SECURITYFRAMEWORK 49 #include <Security/SecureTransport.h> 50 #include <Security/Security.h> 51 #endif /* NO_SECURITYFRAMEWORK */ 52 53 enum mDNSDynamicStoreSetConfigKey 54 { 55 kmDNSMulticastConfig = 1, 56 kmDNSDynamicConfig, 57 kmDNSPrivateConfig, 58 kmDNSBackToMyMacConfig, 59 kmDNSSleepProxyServersState, 60 kmDNSDebugState, 61 }; 62 63 typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX; 64 65 typedef void (*KQueueEventCallback)(int fd, short filter, void *context, mDNSBool encounteredEOF); 66 typedef struct 67 { 68 KQueueEventCallback KQcallback; 69 void *KQcontext; 70 const char *KQtask; // For debugging messages 71 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 72 dispatch_source_t readSource; 73 dispatch_source_t writeSource; 74 mDNSBool fdClosed; 75 #endif 76 } KQueueEntry; 77 78 typedef struct 79 { 80 mDNSIPPort port; // MUST BE FIRST FIELD -- UDPSocket_struct begins with a KQSocketSet, 81 // and mDNSCore requires every UDPSocket_struct to begin with a mDNSIPPort port 82 mDNS *m; 83 int sktv4; 84 KQueueEntry kqsv4; 85 int sktv6; 86 KQueueEntry kqsv6; 87 int *closeFlag; 88 mDNSBool proxy; 89 mDNSBool sktv4EOF; 90 mDNSBool sktv6EOF; 91 } KQSocketSet; 92 93 struct UDPSocket_struct 94 { 95 KQSocketSet ss; // First field of KQSocketSet has to be mDNSIPPort -- mDNSCore requires every UDPSocket_struct to begin with mDNSIPPort port 96 }; 97 98 // TCP socket support 99 100 typedef enum 101 { 102 handshake_required, 103 handshake_in_progress, 104 handshake_completed, 105 handshake_to_be_closed 106 } handshakeStatus; 107 108 struct TCPSocket_struct 109 { 110 mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with mDNSIPPort 111 TCPSocketFlags flags; // MUST BE SECOND FIELD -- mDNSCore expects every TCPSocket_struct have TCPSocketFlags flags after mDNSIPPort 112 TCPConnectionCallback callback; 113 int fd; 114 KQueueEntry kqEntry; 115 #ifndef NO_SECURITYFRAMEWORK 116 SSLContextRef tlsContext; 117 pthread_t handshake_thread; 118 #endif /* NO_SECURITYFRAMEWORK */ 119 domainname *hostname; 120 void *context; 121 mDNSBool setup; 122 mDNSBool connected; 123 handshakeStatus handshake; 124 mDNS *m; // So we can call KQueueLock from the SSLHandshake thread 125 mStatus err; 126 }; 127 128 struct TCPListener_struct 129 { 130 TCPAcceptedCallback callback; 131 int fd; 132 KQueueEntry kqEntry; 133 void *context; 134 mDNSAddr_Type addressType; 135 TCPSocketFlags socketFlags; 136 mDNS *m; // So we can call KQueueLock from the SSLHandshake thread 137 }; 138 139 // Value assiged to 'Exists' to indicate the multicast state of the interface has changed. 140 #define MulticastStateChanged 2 141 142 struct NetworkInterfaceInfoOSX_struct 143 { 144 NetworkInterfaceInfo ifinfo; // MUST be the first element in this structure 145 NetworkInterfaceInfoOSX *next; 146 mDNS *m; 147 mDNSu8 Exists; // 1 = currently exists in getifaddrs list; 0 = doesn't 148 // 2 = exists, but McastTxRx state changed 149 mDNSu8 Flashing; // Set if interface appeared for less than 60 seconds and then vanished 150 mDNSu8 Occulting; // Set if interface vanished for less than 60 seconds and then came back 151 mDNSu8 D2DInterface; // IFEF_LOCALNET_PRIVATE flag indicates we should call 152 // D2D plugin for operations over this interface 153 mDNSs32 AppearanceTime; // Time this interface appeared most recently in getifaddrs list 154 // i.e. the first time an interface is seen, AppearanceTime is set. 155 // If an interface goes away temporarily and then comes back then 156 // AppearanceTime is updated to the time of the most recent appearance. 157 mDNSs32 LastSeen; // If Exists==0, last time this interface appeared in getifaddrs list 158 uint32_t ift_family; // IFRTYPE_FAMILY_XXX 159 unsigned int ifa_flags; 160 struct in_addr ifa_v4addr; 161 mDNSu32 scope_id; // interface index / IPv6 scope ID 162 mDNSEthAddr BSSID; // BSSID of 802.11 base station, if applicable 163 u_short sa_family; 164 int BPF_fd; // -1 uninitialized; -2 requested BPF; -3 failed 165 int BPF_mcfd; // Socket for our IPv6 ND group membership 166 u_int BPF_len; 167 mDNSBool isAWDL; // True if this interface has the IFEF_AWDL flag set. 168 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 169 dispatch_source_t BPF_source; 170 #else 171 CFSocketRef BPF_cfs; 172 CFRunLoopSourceRef BPF_rls; 173 #endif 174 NetworkInterfaceInfoOSX *Registered; // non-NULL means registered with mDNS Core 175 }; 176 177 struct mDNS_PlatformSupport_struct 178 { 179 NetworkInterfaceInfoOSX *InterfaceList; 180 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) 181 CFMutableArrayRef InterfaceMonitors; 182 #endif 183 KQSocketSet permanentsockets; 184 int num_mcasts; // Number of multicasts received during this CPU scheduling period (used for CPU limiting) 185 domainlabel userhostlabel; // The hostlabel as it was set in System Preferences the last time we looked 186 domainlabel usernicelabel; // The nicelabel as it was set in System Preferences the last time we looked 187 // Following four variables are used for optimization where the helper is not 188 // invoked when not needed. It records the state of what we told helper the 189 // last time we invoked mDNSPreferencesSetName 190 domainlabel prevoldhostlabel; // Previous m->p->userhostlabel 191 domainlabel prevnewhostlabel; // Previous m->hostlabel 192 domainlabel prevoldnicelabel; // Previous m->p->usernicelabel 193 domainlabel prevnewnicelabel; // Previous m->nicelabel 194 mDNSs32 NotifyUser; 195 mDNSs32 HostNameConflict; // Time we experienced conflict on our link-local host name 196 mDNSs32 KeyChainTimer; 197 198 SCDynamicStoreRef Store; 199 CFRunLoopSourceRef StoreRLS; 200 CFRunLoopSourceRef PMRLS; 201 int SysEventNotifier; 202 KQueueEntry SysEventKQueue; 203 IONotificationPortRef PowerPortRef; 204 io_connect_t PowerConnection; 205 io_object_t PowerNotifier; 206 #ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements 207 IOPMConnection IOPMConnection; 208 #endif 209 IOPMAssertionID IOPMAssertion; 210 long SleepCookie; // Cookie we need to pass to IOAllowPowerChange() 211 long WakeAtUTC; 212 mDNSs32 RequestReSleep; 213 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 214 dispatch_source_t timer; 215 dispatch_source_t custom; 216 #else 217 pthread_mutex_t BigMutex; 218 #endif 219 mDNSs32 BigMutexStartTime; 220 int WakeKQueueLoopFD; 221 mDNSu8 v4answers; // non-zero if we are receiving answers 222 mDNSu8 v6answers; // for A/AAAA from external DNS servers 223 mDNSs32 DNSTrigger; // Time the DNSTrigger was given 224 uint64_t LastConfigGeneration; // DNS configuration generation number 225 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) 226 mDNSBool if_interface_changed; // There are some changes that we do not know from LastConfigGeneration, such as 227 // if the interface is expensive/constrained or not. Therefore, we need an additional 228 // field to determine if the interface has changed. 229 #endif 230 UDPSocket UDPProxy; 231 TCPSocket TCPProxyV4; 232 TCPSocket TCPProxyV6; 233 ProxyCallback *UDPProxyCallback; 234 ProxyCallback *TCPProxyCallback; 235 }; 236 237 extern int OfferSleepProxyService; 238 extern int DisableSleepProxyClient; 239 extern int UseInternalSleepProxy; 240 extern int OSXVers, iOSVers; 241 242 extern int KQueueFD; 243 244 extern void NotifyOfElusiveBug(const char *title, const char *msg); // Both strings are UTF-8 text 245 extern void SetDomainSecrets(mDNS *m); 246 extern void mDNSMacOSXNetworkChanged(void); 247 extern void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring); 248 extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex); 249 extern void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord); 250 extern void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF); 251 extern void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value); 252 extern void UpdateDebugState(void); 253 254 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 255 extern int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef); 256 mDNSexport void TriggerEventCompletion(void); 257 #else 258 extern int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef); 259 #endif 260 261 // When events are processed on the non-kqueue thread (i.e. CFRunLoop notifications like Sleep/Wake, 262 // Interface changes, Keychain changes, etc.) they must use KQueueLock/KQueueUnlock to lock out the kqueue thread 263 extern void KQueueLock(void); 264 extern void KQueueUnlock(const char* task); 265 extern void mDNSPlatformCloseFD(KQueueEntry *kq, int fd); 266 267 extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict); 268 269 // If any event takes more than WatchDogReportingThreshold milliseconds to be processed, we log a warning message 270 // General event categories are: 271 // o Mach client request initiated / terminated 272 // o UDS client request 273 // o Handling UDP packets received from the network 274 // o Environmental change events: 275 // - network interface changes 276 // - sleep/wake 277 // - keychain changes 278 // o Name conflict dialog dismissal 279 // o Reception of Unix signal (e.g. SIGINFO) 280 // o Idle task processing 281 // If we find that we're getting warnings for any of these categories, and it's not evident 282 // what's causing the problem, we may need to subdivide some categories into finer-grained 283 // sub-categories (e.g. "Idle task processing" covers a pretty broad range of sub-tasks). 284 285 extern int WatchDogReportingThreshold; 286 287 struct CompileTimeAssertionChecks_mDNSMacOSX 288 { 289 // Check our structures are reasonable sizes. Including overly-large buffers, or embedding 290 // other overly-large structures instead of having a pointer to them, can inadvertently 291 // cause structure sizes (and therefore memory usage) to balloon unreasonably. 292 char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 8704) ? 1 : -1]; 293 char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 1378) ? 1 : -1]; 294 }; 295 296 extern mDNSInterfaceID AWDLInterfaceID; 297 void initializeD2DPlugins(mDNS *const m); 298 void terminateD2DPlugins(void); 299 300 #if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER) 301 extern void mDNSPlatformUpdateDNSStatus(const DNSQuestion *q); 302 extern void mDNSPlatformTriggerDNSRetry(const DNSQuestion *v4q, const DNSQuestion *v6q); 303 #endif 304 305 extern mdns_interface_monitor_t GetInterfaceMonitorForIndex(uint32_t ifIndex); 306 307 #ifdef __cplusplus 308 } 309 #endif 310 311 #endif 312