blob: 54be68120b95eabd451129fd92ed09929f3c8f3e [file] [log] [blame]
/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
*
* Copyright (c) 2002-2023 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
*
* https://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 <SystemConfiguration/SystemConfiguration.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "mDNSEmbeddedAPI.h" // for domain name structure
#include <mdns/private.h> // for mdns_interface_monitor_t struct
#include <net/if.h>
#include <os/log.h>
//#define MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
#include <dispatch/dispatch.h>
#include <dispatch/private.h>
#endif
#if TARGET_OS_IPHONE
#define NO_SECURITYFRAMEWORK 1
#define NO_CFUSERNOTIFICATION 1
#endif
#ifndef NO_SECURITYFRAMEWORK
#include <Security/SecureTransport.h>
#include <Security/Security.h>
#endif /* NO_SECURITYFRAMEWORK */
#define kMDNSResponderIDStr "com.apple.mDNSResponder"
#define kMDNSResponderID CFSTR(kMDNSResponderIDStr)
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
{
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with mDNSIPPort
TCPSocketFlags flags; // MUST BE SECOND FIELD -- mDNSCore expects every TCPSocket_struct have TCPSocketFlags flags after mDNSIPPort
TCPConnectionCallback callback;
int fd;
KQueueEntry kqEntry;
#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;
};
struct TCPListener_struct
{
TCPAcceptedCallback callback;
int fd;
KQueueEntry kqEntry;
void *context;
mDNSAddr_Type addressType;
TCPSocketFlags socketFlags;
mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
};
// 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
uint32_t ift_family; // IFRTYPE_FAMILY_XXX
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;
uint32_t ift_subfamily; // The interface's subfamily type from the SIOCGIFTYPE ioctl().
uint32_t if_functional_type; // The interface's functional type from the SIOCGIFFUNCTIONALTYPE
// ioctl().
mDNSBool isAWDL; // True if this interface has the IFEF_AWDL flag set.
mDNSBool isPrivacyRisk; // True if this interface is a privacy risk.
#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;
#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
CFMutableArrayRef InterfaceMonitors;
#endif
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
#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
mDNSBool if_interface_changed; // There are some changes that we do not know from LastConfigGeneration, such as
// if the interface is expensive/constrained or not. Therefore, we need an additional
// field to determine if the interface has changed.
#endif
UDPSocket UDPProxy;
TCPSocket TCPProxyV4;
TCPSocket TCPProxyV6;
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 myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF);
extern void mDNSDynamicStoreSetConfig(enum mDNSDynamicStoreSetConfigKey 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, 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 mDNSBool DictionaryIsEnabled(CFDictionaryRef dict);
// 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) <= 8704) ? 1 : -1];
char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 1378) ? 1 : -1];
};
extern mDNSInterfaceID AWDLInterfaceID;
extern mDNSInterfaceID WiFiAwareInterfaceID;
void initializeD2DPlugins(mDNS *const m);
void terminateD2DPlugins(void);
#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
extern void mDNSPlatformUpdateDNSStatus(const DNSQuestion *q);
extern void mDNSPlatformTriggerDNSRetry(const DNSQuestion *v4q, const DNSQuestion *v6q);
#endif
extern mdns_interface_monitor_t GetInterfaceMonitorForIndex(uint32_t ifIndex);
#ifdef __cplusplus
}
#endif
#endif