/* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __mDNSMacOSX_h #define __mDNSMacOSX_h #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include "mDNSEmbeddedAPI.h" // for domain name structure #include #include //#define MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM #include #include #endif #if TARGET_OS_EMBEDDED #define NO_SECURITYFRAMEWORK 1 #define NO_CFUSERNOTIFICATION 1 #include // for IsAppleTV() #endif #ifndef NO_SECURITYFRAMEWORK #include #include #endif /* NO_SECURITYFRAMEWORK */ enum mDNSDynamicStoreSetConfigKey { kmDNSMulticastConfig = 1, kmDNSDynamicConfig, kmDNSPrivateConfig, kmDNSBackToMyMacConfig, kmDNSSleepProxyServersState, kmDNSDebugState, }; typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX; typedef void (*KQueueEventCallback)(int fd, short filter, void *context, mDNSBool encounteredEOF); typedef struct { KQueueEventCallback KQcallback; void *KQcontext; const char *KQtask; // For debugging messages #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM dispatch_source_t readSource; dispatch_source_t writeSource; mDNSBool fdClosed; #endif } KQueueEntry; typedef struct { mDNSIPPort port; // MUST BE FIRST FIELD -- UDPSocket_struct begins with a KQSocketSet, // and mDNSCore requires every UDPSocket_struct to begin with a mDNSIPPort port mDNS *m; int sktv4; KQueueEntry kqsv4; int sktv6; KQueueEntry kqsv6; int *closeFlag; mDNSBool proxy; mDNSBool sktv4EOF; mDNSBool sktv6EOF; } KQSocketSet; struct UDPSocket_struct { KQSocketSet ss; // First field of KQSocketSet has to be mDNSIPPort -- mDNSCore requires every UDPSocket_struct to begin with mDNSIPPort port }; // TCP socket support typedef enum { handshake_required, handshake_in_progress, handshake_completed, handshake_to_be_closed } handshakeStatus; struct TCPSocket_struct { TCPSocketFlags flags; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags TCPConnectionCallback callback; int fd; KQueueEntry *kqEntry; KQSocketSet ss; #ifndef NO_SECURITYFRAMEWORK SSLContextRef tlsContext; pthread_t handshake_thread; #endif /* NO_SECURITYFRAMEWORK */ domainname hostname; void *context; mDNSBool setup; mDNSBool connected; handshakeStatus handshake; mDNS *m; // So we can call KQueueLock from the SSLHandshake thread mStatus err; }; // Value assiged to 'Exists' to indicate the multicast state of the interface has changed. #define MulticastStateChanged 2 struct NetworkInterfaceInfoOSX_struct { NetworkInterfaceInfo ifinfo; // MUST be the first element in this structure NetworkInterfaceInfoOSX *next; mDNS *m; mDNSu8 Exists; // 1 = currently exists in getifaddrs list; 0 = doesn't // 2 = exists, but McastTxRx state changed mDNSu8 Flashing; // Set if interface appeared for less than 60 seconds and then vanished mDNSu8 Occulting; // Set if interface vanished for less than 60 seconds and then came back mDNSu8 D2DInterface; // IFEF_LOCALNET_PRIVATE flag indicates we should call // D2D plugin for operations over this interface mDNSs32 AppearanceTime; // Time this interface appeared most recently in getifaddrs list // i.e. the first time an interface is seen, AppearanceTime is set. // If an interface goes away temporarily and then comes back then // AppearanceTime is updated to the time of the most recent appearance. mDNSs32 LastSeen; // If Exists==0, last time this interface appeared in getifaddrs list unsigned int ifa_flags; struct in_addr ifa_v4addr; mDNSu32 scope_id; // interface index / IPv6 scope ID mDNSEthAddr BSSID; // BSSID of 802.11 base station, if applicable u_short sa_family; int BPF_fd; // -1 uninitialized; -2 requested BPF; -3 failed int BPF_mcfd; // Socket for our IPv6 ND group membership u_int BPF_len; mDNSBool isExpensive; // True if this interface has the IFEF_EXPENSIVE flag set. #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM dispatch_source_t BPF_source; #else CFSocketRef BPF_cfs; CFRunLoopSourceRef BPF_rls; #endif NetworkInterfaceInfoOSX *Registered; // non-NULL means registered with mDNS Core }; struct mDNS_PlatformSupport_struct { NetworkInterfaceInfoOSX *InterfaceList; KQSocketSet permanentsockets; int num_mcasts; // Number of multicasts received during this CPU scheduling period (used for CPU limiting) domainlabel userhostlabel; // The hostlabel as it was set in System Preferences the last time we looked domainlabel usernicelabel; // The nicelabel as it was set in System Preferences the last time we looked // Following four variables are used for optimization where the helper is not // invoked when not needed. It records the state of what we told helper the // last time we invoked mDNSPreferencesSetName domainlabel prevoldhostlabel; // Previous m->p->userhostlabel domainlabel prevnewhostlabel; // Previous m->hostlabel domainlabel prevoldnicelabel; // Previous m->p->usernicelabel domainlabel prevnewnicelabel; // Previous m->nicelabel mDNSs32 NotifyUser; mDNSs32 HostNameConflict; // Time we experienced conflict on our link-local host name mDNSs32 KeyChainTimer; SCDynamicStoreRef Store; CFRunLoopSourceRef StoreRLS; CFRunLoopSourceRef PMRLS; int SysEventNotifier; KQueueEntry SysEventKQueue; IONotificationPortRef PowerPortRef; io_connect_t PowerConnection; io_object_t PowerNotifier; #ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements IOPMConnection IOPMConnection; #endif IOPMAssertionID IOPMAssertion; long SleepCookie; // Cookie we need to pass to IOAllowPowerChange() long WakeAtUTC; mDNSs32 RequestReSleep; #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM dispatch_source_t timer; dispatch_source_t custom; #else pthread_mutex_t BigMutex; #endif mDNSs32 BigMutexStartTime; int WakeKQueueLoopFD; mDNSu8 v4answers; // non-zero if we are receiving answers mDNSu8 v6answers; // for A/AAAA from external DNS servers mDNSs32 DNSTrigger; // Time the DNSTrigger was given uint64_t LastConfigGeneration; // DNS configuration generation number UDPSocket UDPProxy; TCPSocket TCPProxy; ProxyCallback *UDPProxyCallback; ProxyCallback *TCPProxyCallback; }; extern int OfferSleepProxyService; extern int DisableSleepProxyClient; extern int UseInternalSleepProxy; extern int OSXVers, iOSVers; extern int KQueueFD; extern void NotifyOfElusiveBug(const char *title, const char *msg); // Both strings are UTF-8 text extern void SetDomainSecrets(mDNS *m); extern void mDNSMacOSXNetworkChanged(void); extern void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring); extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex); extern void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord); extern void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF); extern void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value); extern void UpdateDebugState(void); #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM extern int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef); mDNSexport void TriggerEventCompletion(void); #else extern int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef); #endif // When events are processed on the non-kqueue thread (i.e. CFRunLoop notifications like Sleep/Wake, // Interface changes, Keychain changes, etc.) they must use KQueueLock/KQueueUnlock to lock out the kqueue thread extern void KQueueLock(void); extern void KQueueUnlock(const char* task); extern void mDNSPlatformCloseFD(KQueueEntry *kq, int fd); extern ssize_t myrecvfrom(const int s, void *const buffer, const size_t max, struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char *ifname, mDNSu8 *ttl); extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict); extern const char *DNSScopeToString(mDNSu32 scope); // If any event takes more than WatchDogReportingThreshold milliseconds to be processed, we log a warning message // General event categories are: // o Mach client request initiated / terminated // o UDS client request // o Handling UDP packets received from the network // o Environmental change events: // - network interface changes // - sleep/wake // - keychain changes // o Name conflict dialog dismissal // o Reception of Unix signal (e.g. SIGINFO) // o Idle task processing // If we find that we're getting warnings for any of these categories, and it's not evident // what's causing the problem, we may need to subdivide some categories into finer-grained // sub-categories (e.g. "Idle task processing" covers a pretty broad range of sub-tasks). extern int WatchDogReportingThreshold; struct CompileTimeAssertionChecks_mDNSMacOSX { // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently // cause structure sizes (and therefore memory usage) to balloon unreasonably. char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 7464) ? 1 : -1]; char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 1378) ? 1 : -1]; }; extern mDNSInterfaceID AWDLInterfaceID; void initializeD2DPlugins(mDNS *const m); void terminateD2DPlugins(void); #ifdef __cplusplus } #endif #endif