diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-19 08:53:26 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-20 11:23:32 +0200 |
commit | f01edf10244ccd53e098abdc1773c1aa0e4c5f8d (patch) | |
tree | 958a1ee323520629c4f027de1d4c56715949aa5c /mDNSResponder/mDNSMacOSX | |
parent | mDNSResponder: Update to v625.41.2 (diff) | |
download | rtems-libbsd-f01edf10244ccd53e098abdc1773c1aa0e4c5f8d.tar.bz2 |
mDNSResponder: Update to v765.1.2
The sources can be obtained via:
https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-765.1.2.tar.gz
Move mDNS_StartResolveService() and mDNS_StopResolveService() to an
RTEMS-specific file (rtemsbsd/mdns/mDNSResolveService.c) using the
v576.30.4 implementation. Apple removed these functions without
explanation.
Update #3522.
Diffstat (limited to 'mDNSResponder/mDNSMacOSX')
50 files changed, 7773 insertions, 5817 deletions
diff --git a/mDNSResponder/mDNSMacOSX/BLE.c b/mDNSResponder/mDNSMacOSX/BLE.c new file mode 100644 index 00000000..85fb810c --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/BLE.c @@ -0,0 +1,853 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015-2016 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. + */ + +#include "mDNSEmbeddedAPI.h" +#include "DNSCommon.h" +#include "mDNSMacOSX.h" +#include "BLE.h" +#include <pthread.h> + +#pragma mark - Browse and Registration Request Handling + +// Disable use of BLE discovery APIs by default. +mDNSBool EnableBLEBasedDiscovery = mDNSfalse; + +typedef struct matchingResponses +{ + struct matchingResponses * next; + void * response; +} matchingResponses_t; + +// Initially used for both the browse and registration lists. +typedef struct requestList +{ + struct requestList * next; + unsigned int refCount; + domainname name; + mDNSu16 type; + DNSServiceFlags flags; + mDNSInterfaceID InterfaceID; + +// TODO: Possibly restructure the following browse and registration specific +// members as a union to save a bit of space. + + // The following fields are only used for browse requests currently + serviceHash_t browseHash; + DNSQuestion * question; + mDNSu8 key[MAX_DOMAIN_LABEL]; + size_t keySize; + matchingResponses_t * ourResponses; + + // The following fields are only used for registration requests currently + serviceHash_t registeredHash; + ServiceRecordSet * serviceRecordSet; // service record set in the original request + AuthRecType savedARType; + bool triggeredOnAWDL; +} requestList_t; + +// Lists for all DNSServiceBrowse() and DNSServiceRegister() requests using +// BLE beacon based triggering. +static requestList_t* BLEBrowseListHead = NULL; +static requestList_t* BLERegistrationListHead = NULL; + +#define isAutoTriggerRequest(ptr) ((ptr->InterfaceID == kDNSServiceInterfaceIndexAny) && (ptr->flags & kDNSServiceFlagsAutoTrigger)) + +#pragma mark - Manage list of responses that match this request. + +mDNSlocal bool inResponseListForRequest(requestList_t *request, void * response) +{ + matchingResponses_t * rp; + + for (rp = request->ourResponses; rp; rp = rp->next) + if (rp->response == response) + break; + + return (rp != 0); +} + +mDNSlocal void addToResponseListForRequest(requestList_t *request, void * response) +{ + matchingResponses_t *matchingResponse = calloc(1, sizeof(matchingResponses_t)); + + if (matchingResponse == NULL) + { + LogMsg("addToResponseListForRequest: calloc() failed!"); + return; + } + matchingResponse->response = response; + matchingResponse->next = request->ourResponses; + request->ourResponses = matchingResponse; +} + +// If response is currently in the list of responses, remove it and return true. +// Othewise, return false. +mDNSlocal bool removeFromResponseListForRequest(requestList_t *request, void * response) +{ + matchingResponses_t ** nextp; + bool responseRemoved = false; + + for (nextp = & request->ourResponses; *nextp; nextp = & (*nextp)->next) + if ((*nextp)->response == response) + break; + + if (*nextp) + { + LogInfo("removeFromResponseListForRequest: response no longer matches for %##s %s ", request->name.c, DNSTypeName(request->type)); + + responseRemoved = true; + matchingResponses_t *tmp = *nextp; + *nextp = (*nextp)->next; + free(tmp); + } + return responseRemoved; +} + +// Free all current entries on the response list for this request. +mDNSlocal void freeResponseListEntriesForRequest(requestList_t *request) +{ + matchingResponses_t * ptr; + + ptr = request->ourResponses; + while (ptr) + { + matchingResponses_t * tmp; + + tmp = ptr; + ptr = ptr->next; + free(tmp); + } +} + +#pragma mark - Manage request lists + +mDNSlocal requestList_t ** findInRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type) +{ + requestList_t **ptr = listHead; + + for ( ; *ptr; ptr = &(*ptr)->next) + if ((*ptr)->type == type && SameDomainName(&(*ptr)->name, name)) + break; + + return ptr; +} + +mDNSlocal requestList_t * addToRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type, DNSServiceFlags flags) +{ + requestList_t **ptr = findInRequestList(listHead, name, type); + + if (!*ptr) + { + *ptr = mDNSPlatformMemAllocate(sizeof(**ptr)); + mDNSPlatformMemZero(*ptr, sizeof(**ptr)); + (*ptr)->type = type; + (*ptr)->flags = flags; + AssignDomainName(&(*ptr)->name, name); + } + (*ptr)->refCount += 1; + + LogInfo("addToRequestList: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount); + + return *ptr; +} + +mDNSlocal void removeFromRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type) +{ + requestList_t **ptr = findInRequestList(listHead, name, type); + + if (!*ptr) { LogMsg("removeFromRequestList: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return; } + + (*ptr)->refCount -= 1; + + LogInfo("removeFromRequestList: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount); + + if (!(*ptr)->refCount) + { + requestList_t *tmp = *ptr; + *ptr = (*ptr)->next; + freeResponseListEntriesForRequest(tmp); + mDNSPlatformMemFree(tmp); + } +} + +#pragma mark - Hashing and beacon state + +// Simple string hash based on the Bernstein hash. + +#define PRIME 31 // small prime number +#define MODULO (sizeof(serviceHash_t) * 8) +#define CONVERT_TO_LOWER_CASE(x) (((x) <= 'Z' && (x) >= 'A') ? ((x) | 0x20) : (x)) + +mDNSlocal serviceHash_t BLELabelHash(const unsigned char *str, unsigned int length) +{ + serviceHash_t hash = 0; + + for (unsigned int i = 0; i < length; i++) { + hash = PRIME * hash + CONVERT_TO_LOWER_CASE(*str); + str++; + } + + hash %= MODULO; + LogInfo("BLELabelHash: %d characters hashed to %d", length, hash); + + return ((serviceHash_t)1 << hash); +} + +// Hash just the service type not including the protocol or first "_" character initially. +mDNSlocal serviceHash_t BLEServiceHash(const domainname *const domain) +{ + const unsigned char *p = domain->c; + unsigned int length = (unsigned int) *p; + + p++; + if (*p != '_') + { + LogInfo("BLEServiceHash: browse type does not begin with a _"); + return 0; + } + p++; // skip the '-" + length--; + + if (length > MAX_DOMAIN_LABEL || length == 0) + { + LogInfo("BLEServiceHash: invalid browse type length: %d characters", length); + return 0; + } + + return BLELabelHash(p, length); +} + +// Storage for the current Bonjour BLE beacon data; +typedef struct BLEBeacon +{ + serviceHash_t browseHash; + serviceHash_t registeredHash; +} BLEBeacon_t; + +BLEBeacon_t BLEBeacon; + +mDNSlocal void addServiceToBeacon(serviceHash_t browseHash, serviceHash_t registeredHash) +{ + bool beaconUpdated = false; + + if (BLEBeacon.browseHash & browseHash) + { + LogInfo("addServiceToBeacon: Bit 0x%x already set in browsing services hash", browseHash); + } + else + { + BLEBeacon.browseHash |= browseHash; + beaconUpdated = true; + } + + if (BLEBeacon.registeredHash & registeredHash) + { + LogInfo("addServiceToBeacon: Bit 0x%x already set in advertising services hash", registeredHash); + } + else + { + BLEBeacon.registeredHash |= registeredHash; + beaconUpdated = true; + } + + if (beaconUpdated) + updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash); +} + +// Go through all the existing browses and registrations to get the +// current hash values for the corresponding BLE beacon. +// We must do this when any hash bits are removed do accurately generate +// the correct combination of all currently set hash bits. +mDNSlocal void updateBeacon() +{ + requestList_t *ptr; + + BLEBeacon.browseHash = 0; + BLEBeacon.registeredHash = 0; + + for (ptr = BLEBrowseListHead; ptr; ptr = ptr->next) + { + BLEBeacon.browseHash |= ptr->browseHash; + } + + for (ptr = BLERegistrationListHead; ptr; ptr = ptr->next) + { + BLEBeacon.registeredHash |= ptr->registeredHash; + } + + updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash); +} + +#pragma mark - Request start/stop + +// Forward declarations for mDNSLocal functions that are called before they are defined. +mDNSlocal void checkForMatchingResponses(requestList_t *bp); +mDNSlocal void clearResponseLists(); + +void start_BLE_browse(DNSQuestion * q, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags, mDNSu8 *key, size_t keySize) +{ + requestList_t * ptr; + + if (!EnableBLEBasedDiscovery) + { + LogMsg("start_BLE_browse: EnableBLEBasedDiscovery disabled"); + return; + } + + LogInfo("start_BLE_browse: Starting BLE browse for: %##s %s", domain->c, DNSTypeName(type)); + + ptr = addToRequestList(&BLEBrowseListHead, domain, type, flags); + + // If equivalent BLE browse is already running, just return. + if (ptr->refCount > 1) + { + LogInfo("start_BLE_browse: Dup of existing BLE browse."); + return; + } + + ptr->browseHash = BLEServiceHash(domain); + ptr->question = q; + + if (ptr->browseHash == 0) + { + LogInfo("BLEServiceHash failed!"); + removeFromRequestList(&BLEBrowseListHead, domain, type); + return; + } + + // Save these for use in D2D plugin callback logic. + memcpy(ptr->key, key, keySize); + ptr->keySize = keySize; + // Extract the interface ID for easier access in the requestList_t structure + ptr->InterfaceID = q->InterfaceID; + + addServiceToBeacon(ptr->browseHash, 0); + + checkForMatchingResponses(ptr); +} + +// Stop the browse. +// Return true if this is the last reference to the browse, false otherwise. +bool stop_BLE_browse(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags) +{ + (void) flags; // not used initially + requestList_t * ptr; + bool lastReference = false; + + if (!EnableBLEBasedDiscovery) + { + LogMsg("stop_BLE_browse: EnableBLEBasedDiscovery disabled"); + return lastReference; + } + + LogInfo("stop_BLE_browse: Stopping BLE browse for: %##s %s", domain->c, DNSTypeName(type)); + + ptr = *(findInRequestList(&BLEBrowseListHead, domain, type)); + if (ptr == 0) + { + LogInfo("stop_BLE_browse: No matching browse found."); + return lastReference; + } + + // If this is the last reference for this browse, update advertising and browsing bits set in + // the beacon after removing this browse from the list. + if (ptr->refCount == 1) + lastReference = true; + + removeFromRequestList(&BLEBrowseListHead, domain, type); + + if (lastReference) + updateBeacon(); + + // If there are no active browse or registration requests, BLE scanning will be disabled. + // Clear the list of responses received to remove any stale response state. + if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0) + clearResponseLists(); + + return lastReference; +} + +extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q); +extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags); + +extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); +extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); + +void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags) +{ + requestList_t * ptr; + const domainname * instanceRemoved; + + if (!EnableBLEBasedDiscovery) + { + LogMsg("start_BLE_advertise: EnableBLEBasedDiscovery disabled"); + return; + } + + // Just process the SRV record for each service registration. The PTR + // record already has the service type at the beginning of the domain, but + // we want to filter out reverse address PTR records at this point in time, so using + // the SRV record instead. + if (type != kDNSServiceType_SRV) + return; + + if (serviceRecordSet == NULL) + { + LogInfo("start_BLE_advertise: NULL service record set for: %##s %s, returning", domain->c, DNSTypeName(type)); + return; + } + LogInfo("start_BLE_advertise: Starting BLE advertisement for: %##s %s", domain->c, DNSTypeName(type)); + + instanceRemoved = SkipLeadingLabels(domain, 1); + + ptr = addToRequestList(&BLERegistrationListHead, instanceRemoved, type, flags); + + // If equivalent BLE registration is already running, just return. + if (ptr->refCount > 1) + { + LogInfo("start_BLE_advertise: Dup of existing BLE advertisement."); + return; + } + + ptr->registeredHash = BLEServiceHash(instanceRemoved); + if (ptr->registeredHash == 0) + { + LogInfo("BLEServiceHash failed!"); + removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type); + return; + } + ptr->serviceRecordSet = serviceRecordSet; + // Extract the interface ID for easier access in the requestList_t structure + ptr->InterfaceID = serviceRecordSet->RR_SRV.resrec.InterfaceID; + + addServiceToBeacon(0, ptr->registeredHash); +} + +void stop_BLE_advertise(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags) +{ + (void) flags; // not used initially + requestList_t * ptr; + bool lastReference = false; + const domainname * instanceRemoved; + + if (!EnableBLEBasedDiscovery) + { + LogMsg("stop_BLE_advertise: EnableBLEBasedDiscovery disabled"); + return; + } + + // Just process the SRV record for each service registration. The PTR + // record already has the service type at the beginning of the domain, but + // we want to filter out reverse address PTR records at this point in time, so using + // the SRV record instead. + if (type != kDNSServiceType_SRV) + return; + + LogInfo("stop_BLE_advertise: Stopping BLE advertisement for: %##s %s", domain->c, DNSTypeName(type)); + + instanceRemoved = SkipLeadingLabels(domain, 1); + + // Get the request pointer from the indirect pointer returned. + ptr = *(findInRequestList(&BLERegistrationListHead, instanceRemoved, type)); + + if (ptr == 0) + { + LogInfo("stop_BLE_advertise: No matching advertisement found."); + return; + } + + // If this is the last reference for this registration, update advertising and browsing bits set in + // the beacon before removing this registration from the request list. + if (ptr->refCount == 1) + { + lastReference = true; + + if (isAutoTriggerRequest(ptr) && ptr->triggeredOnAWDL) + { + // And remove the corresponding advertisements from the AWDL D2D plugin. + // Do it directly here, since we do not set the kDNSServiceFlagsIncludeAWDL bit in the original client request structure + // when we trigger the registration over AWDL, we just update the record ARType field, so our caller, external_stop_browsing_for_service() + // would not call into the D2D plugin to remove the advertisements in this case. + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + } + } + removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type); + + if (lastReference) + updateBeacon(); + + // If there are no active browse or registration requests, BLE scanning will be disabled. + // Clear the list of responses received to remove any stale response state. + if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0) + clearResponseLists(); +} + +#pragma mark - Response Handling + +// Structure used to track the beacons received from various peers. +typedef struct responseList +{ + struct responseList * next; + serviceHash_t browseHash; + serviceHash_t registeredHash; + mDNSEthAddr senderMAC; +} responseList_t; + +#define RESPONSE_LIST_NUMBER 8 +static responseList_t* BLEResponseListHeads[RESPONSE_LIST_NUMBER]; + +mDNSlocal responseList_t ** findInResponseList(mDNSEthAddr * ptrToMAC) +{ + // Use the least significant byte of the MAC address as our hash index to find the list. + responseList_t **ptr = & BLEResponseListHeads[ptrToMAC->b[5] % RESPONSE_LIST_NUMBER]; + + for ( ; *ptr; ptr = &(*ptr)->next) + { + if (memcmp(&(*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr)) == 0) + break; + } + + return ptr; +} + + +mDNSlocal responseList_t ** addToResponseList(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC) +{ + responseList_t **ptr = findInResponseList(ptrToMAC); + + if (!*ptr) + { + *ptr = mDNSPlatformMemAllocate(sizeof(**ptr)); + mDNSPlatformMemZero(*ptr, sizeof(**ptr)); + (*ptr)->browseHash = browseHash; + (*ptr)->registeredHash = registeredHash; + memcpy(& (*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr)); + } + + return ptr; +} + +mDNSlocal void removeFromResponseList(mDNSEthAddr * ptrToMAC) +{ + responseList_t **ptr = findInResponseList(ptrToMAC); + + if (!*ptr) + { + LogMsg("removeFromResponseList: did not find entry for MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]); + return; + } + + LogInfo("removeFromResponseList: removing entry for MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]); + + responseList_t *tmp = *ptr; + *ptr = (*ptr)->next; + mDNSPlatformMemFree(tmp); +} + +// Free all current entries on the BLE response lists, removing all pointers +// to freed structures from the lists. +mDNSlocal void clearResponseLists() +{ + responseList_t **ptr; + + for (unsigned int i = 0; i < RESPONSE_LIST_NUMBER; i++) + { + ptr = & BLEResponseListHeads[i]; + while (*ptr) + { + responseList_t * tmp; + + tmp = *ptr; + *ptr = (*ptr)->next; + mDNSPlatformMemFree(tmp); + } + } +} + +// Called from mDNS_Execute() when NextBLEServiceTime is reached +// to stop the BLE beacon a few seconds after the last request has +// been stopped. This gives peers a chance to see that this device +// is no longer browsing for or advertising any services via the +// BLE beacon. +void serviceBLE(void) +{ + mDNSStorage.NextBLEServiceTime = 0; + if (BLEBrowseListHead || BLERegistrationListHead) + { + // We don't expect to be called if there are active requests. + LogInfo("serviceBLE: called with active BLE requests ??"); + return; + } + stopBLEBeacon(); +} + +// Called from start_BLE_browse() on the mDNSResonder kqueue thread +mDNSlocal void checkForMatchingResponses(requestList_t *bp) +{ + responseList_t *ptr; + + for (unsigned int i = 0; i < RESPONSE_LIST_NUMBER; i++) + { + for (ptr = BLEResponseListHeads[i]; ptr; ptr = ptr->next) + { + if ((bp->browseHash & ptr->registeredHash) == bp->browseHash) + { + // Clear the registered services hash for the response. + // The next beacon from this peer will update the hash and our + // newly started browse will get an add event if there is a match. + ptr->registeredHash = 0; + } + } + } +} + +// Define a fixed name to use for the instance name denoting that one or more instances +// of a service are being advetised by peers in their BLE beacons. +// Name format is: length byte + bytes of name string + two byte pointer to the PTR record name. +// See compression_lhs definition in the D2D plugin code for backgound on 0xc027 DNS name compression pointer value. +static Byte *BLEinstanceValue = (Byte *) "\x11ThresholdInstance\xc0\x27"; +#define BLEValueSize strlen((const char *)BLEinstanceValue) + +void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize); +void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize); + +// Find each unique browse that matches the registered service hash in the BLE response. +// Called on the CFRunLoop thread while handling a callback from CoreBluetooth. +// Caller should hold KQueueLock(). +mDNSlocal void findMatchingBrowse(responseList_t *response) +{ + requestList_t *ptr; + + ptr = BLEBrowseListHead; + for ( ; ptr; ptr = ptr->next) + { + if ((ptr->browseHash & response->registeredHash) == ptr->browseHash) + { + + LogInfo("findMatchingBrowse: Registration in response matched browse for: %##s", ptr->name.c); + + if (inResponseListForRequest(ptr, response)) + { + LogInfo("findMatchingBrowse: Already on response list for browse: %##s", ptr->name.c); + + continue; + } + else + { + LogInfo("findMatchingBrowse: Adding to response list for browse: %##s", ptr->name.c); + + if (ptr->ourResponses == 0) + { + if (isAutoTriggerRequest(ptr)) + { + LogInfo("findMatchingBrowse: First BLE response, triggering browse for %##s on AWDL", ptr->name.c); + ptr->question->flags |= kDNSServiceFlagsIncludeAWDL; + mDNSCoreRestartQuestion(& mDNSStorage, ptr->question); + // register with the AWDL D2D plugin, + internal_start_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags, ptr->question); + } + + // Browse on mDNSInterface_BLE is used to determine if there are one or more instances of the + // service type discoveryed over BLE. If this is the first instance, add the psuedo instance defined by BLEinstanceValue. + if (ptr->question->InterfaceID == mDNSInterface_BLE) + { + xD2DAddToCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize); + } + } + addToResponseListForRequest(ptr, response); + } + } + else + { + // If a previous response from this peer had matched the browse, remove that response from the + // list now. If this is the last matching response, remove the corresponding key from the AWDL D2D plugin + if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0)) + { + if (ptr->question->InterfaceID == mDNSInterface_BLE) + { + xD2DRemoveFromCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize); + } + + if (isAutoTriggerRequest(ptr)) + { + LogInfo("findMatchingBrowse: Last BLE response, disabling browse for %##s on AWDL", ptr->name.c); + internal_stop_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags); + } + } + } + } +} + +// Find each local registration that matches the service browse hash in the BLE response. +// Called on the CFRunLoop thread while handling a callback from CoreBluetooth. +// Caller should hold KQueueLock(). +mDNSlocal void findMatchingRegistration(responseList_t *response) +{ + requestList_t *ptr; + + ptr = BLERegistrationListHead; + for ( ; ptr; ptr = ptr->next) + { + if ((ptr->registeredHash & response->browseHash) == ptr->registeredHash) + { + + LogInfo("findMatchingRegistration: Incoming browse matched registration for: %##s", ptr->name.c); + + if (inResponseListForRequest(ptr, response)) + { + LogInfo("findMatchingRegistration: Already on response list for registration: %##s", ptr->name.c); + + continue; + } + else + { + LogInfo("findMatchingRegistration: Adding to response list for registration: %##s", ptr->name.c); + + // Also pass the registration to the AWDL D2D plugin if this is the first matching peer browse for + // an auto triggered local registration. + if ((ptr->ourResponses == 0) && isAutoTriggerRequest(ptr)) + { + AuthRecType newARType; + + LogInfo("findMatchingRegistration: First BLE response, triggering registration for %##s on AWDL", ptr->name.c); + if (ptr->serviceRecordSet == 0) + { + LogInfo("findMatchingRegistration: serviceRecordSet pointer is NULL ??"); + continue; + } + // Modify the PTR, TXT, and SRV records so that they now apply to AWDL and restart the registration. + // RR_ADV is not passed to the D2D plugins froma internal_start_advertising_helper(), so we don't do it here either. + + if (ptr->flags & kDNSServiceFlagsIncludeAWDL) + { + LogInfo("findMatchingRegistration: registration for %##s already applies to AWDL, skipping", ptr->name.c); + continue; + } + + // Save the current ARType value to restore when the promotion to use AWDL is stopped. + ptr->savedARType = ptr->serviceRecordSet->RR_PTR.ARType; + + // Preserve P2P attribute if original registration was applied to P2P. + if (ptr->serviceRecordSet->RR_PTR.ARType == AuthRecordAnyIncludeP2P) + newARType = AuthRecordAnyIncludeAWDLandP2P; + else + newARType = AuthRecordAnyIncludeAWDL; + + ptr->serviceRecordSet->RR_PTR.ARType = newARType; + ptr->serviceRecordSet->RR_SRV.ARType = newARType; + ptr->serviceRecordSet->RR_TXT.ARType = newARType; + mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_PTR, -1); + mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_SRV, -1); + mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_TXT, -1); + + internal_start_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_start_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_start_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + // indicate the registration has been applied to the AWDL interface + ptr->triggeredOnAWDL = true; + } + + addToResponseListForRequest(ptr, response); + } + } + else + { + // If a previous response from this peer had matched the browse, remove that response from the + // list now. If this is the last matching response for a local auto triggered registration, + // remove the advertised key/value pairs from the AWDL D2D plugin. + if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0) && isAutoTriggerRequest(ptr)) + { + LogInfo("findMatchingRegistration: Last BLE response, disabling registration for %##s on AWDL", ptr->name.c); + + // Restore the saved ARType and call into the AWDL D2D plugin to stop the corresponding record advertisements over AWDL. + ptr->serviceRecordSet->RR_PTR.ARType = ptr->savedARType; + ptr->serviceRecordSet->RR_SRV.ARType = ptr->savedARType; + ptr->serviceRecordSet->RR_TXT.ARType = ptr->savedARType; + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL)); + } + } + } +} + +// Called on CFRunLoop thread during CoreBluetooth beacon response processing. +// Thus, must call KQueueLock() prior to calling any core mDNSResponder routines to register records, etc. +void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC) +{ + responseList_t ** ptr; + + KQueueLock(& mDNSStorage); + ptr = findInResponseList(ptrToMAC); + if (*ptr == 0) + { + // Only add to list if peer is actively browsing or advertising. + if (browseHash || registeredHash) + { + LogInfo("responseReceived: First beacon of this type, adding to list"); + LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x", + browseHash, registeredHash); + LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]); + + ptr = addToResponseList(browseHash, registeredHash, ptrToMAC); + // See if we are browsing for any of the peers advertised services. + findMatchingBrowse(*ptr); + // See if we have a registration that matches the peer's browse. + findMatchingRegistration(*ptr); + } + } + else // have entry from this MAC in the list + { + if (((*ptr)->browseHash == browseHash) && ((*ptr)->registeredHash == registeredHash)) + { + // A duplicate of a current entry. +#if VERBOSE_BLE_DEBUG + LogInfo("responseReceived: Duplicate of previous beacon, ignoring"); + LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]); +#endif // VERBOSE_BLE_DEBUG + } + else + { + LogInfo("responseReceived: Update of previous beacon"); + LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x", + browseHash, registeredHash); + LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]); + + (*ptr)->browseHash = browseHash; + (*ptr)->registeredHash = registeredHash; + + findMatchingBrowse(*ptr); + findMatchingRegistration(*ptr); + } + + // If peer is no longer browsing or advertising, remove from list. + if ((browseHash == 0) && (registeredHash == 0)) + { + LogInfo("responseReceived: Removing peer entry from the list"); + + removeFromResponseList(ptrToMAC); + } + } + + KQueueUnlock(& mDNSStorage, "BLE responseReceived"); +} diff --git a/mDNSResponder/mDNSMacOSX/BLE.h b/mDNSResponder/mDNSMacOSX/BLE.h new file mode 100644 index 00000000..970c8faf --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/BLE.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015-2016 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 _BLE_H_ +#define _BLE_H_ + +#include "dns_sd.h" +#include "dns_sd_private.h" + +typedef unsigned int serviceHash_t; + +void start_BLE_browse(DNSQuestion * q, const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags, + mDNSu8 *key, size_t keySize); +bool stop_BLE_browse(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags); + +void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags); +void stop_BLE_advertise(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags); + +void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr *ptrToMAC); + +void serviceBLE(void); + +// C interfaces to Objective-C beacon management code. +void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash); +void stopBLEBeacon(void); + +extern mDNS mDNSStorage; +extern mDNSBool EnableBLEBasedDiscovery; + +// TODO: Add the following to a local D2D.h file +#include <DeviceToDeviceManager/DeviceToDeviceManager.h> + +// Just define as the current max value for now. +// TODO: Will need to define in DeviceToDeviceManager.framework if we convert this +// BLE discovery code to a D2D plugin. +#define D2DBLETransport D2DTransportMax + +#define applyToBLE(interface, flags) ((interface == mDNSInterface_BLE) || ((interface == mDNSInterface_Any) && (flags & kDNSServiceFlagsAutoTrigger))) + +#endif /* _BLE_H_ */ diff --git a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c index 34f21a57..7666cbc4 100644 --- a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c +++ b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c @@ -21,6 +21,7 @@ #include <sys/types.h> #include <sys/time.h> #include <sys/event.h> +#include <netinet/tcp.h> #define ValidSocket(s) ((s) >= 0) @@ -101,6 +102,9 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context) ProxyTCPInfo_t *ti = (ProxyTCPInfo_t *)context; TCPSocket *sock = &ti->sock; KQSocketSet *kq = &sock->ss; + struct tcp_info tcp_if; + socklen_t size = sizeof(tcp_if); + int32_t intf_id = 0; (void) filter; @@ -135,6 +139,12 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context) mDNSPlatformDisposeProxyContext(ti); return; } + if (getsockopt(s1, IPPROTO_TCP, TCP_INFO, &tcp_if, &size) != 0) + { + LogMsg("ProxyTCPReceive: getsockopt for TCP_INFO failed (fd=%d) errno %d", s1, errno); + return; + } + intf_id = tcp_if.tcpi_last_outif; if (from.ss_family == AF_INET) { @@ -148,7 +158,8 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context) destAddr.type = mDNSAddrType_IPv4; destAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr; - LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s", ti->replyLen, &senderAddr, &destAddr, s1, NULL); + LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d", + ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id); } else if (from.ss_family == AF_INET6) { @@ -161,7 +172,8 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context) destAddr.type = mDNSAddrType_IPv6; destAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr; - LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s", ti->replyLen, &senderAddr, &destAddr, s1, NULL); + LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d", + ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id); } else { @@ -174,7 +186,7 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context) // In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument) // would be NULL. kq->m->p->TCPProxyCallback(kq->m, sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr, - UnicastDNSPort, 0, ti); + UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti); } mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) @@ -204,6 +216,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) return; } mDNSPlatformMemZero(ti, sizeof(ProxyTCPInfo_t)); + TCPSocket *sock = &ti->sock; kq = &sock->ss; @@ -222,6 +235,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) { LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd, errno, strerror(errno)); mDNSPlatformDisposeProxyContext(ti); + close(newfd); return; } } @@ -235,6 +249,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) { LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd, errno, strerror(errno)); mDNSPlatformDisposeProxyContext(ti); + close(newfd); return; } } @@ -244,7 +259,6 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) // Instead of remembering the address family, we remember the right fd. sock->fd = newfd; sock->kqEntry = k; - k->KQcallback = ProxyTCPSocketCallBack; k->KQcontext = ti; k->KQtask = "TCP Proxy packet reception"; diff --git a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c index 6e5ae108..b87f0d44 100644 --- a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c +++ b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c @@ -44,6 +44,8 @@ // When we can't fetch the root TA due to network errors etc., we start off a timer // to fire at 60 seconds and then keep doubling it till we fetch it #define InitialTAFetchInterval 60 +#define DNSSECProbePercentage 1 + #if !TARGET_OS_IPHONE DNSQuestion DNSSECProbeQuestion; @@ -165,7 +167,7 @@ mDNSlocal mDNSu8 *ConvertDigest(char *digest, int digestType, int *diglen) int l, h; l = HexVal(digest[i]); h = HexVal(digest[i+1]); - if (l<0 || h<0) { LogMsg("ConvertDigest: Cannot convert digest"); return NULL;} + if (l<0 || h<0) { LogMsg("ConvertDigest: Cannot convert digest"); mDNSPlatformMemFree(dig); return NULL;} dig[j++] = (mDNSu8)((l << 4) | h); } return dig; @@ -560,8 +562,8 @@ mDNSexport void DNSSECProbe(mDNS *const m) return; rand = mDNSRandom(0x3FFFFFFF) % 100; - // Probe 5% of the time - if (rand > 5) + // Probe 1% of the time + if (rand >= DNSSECProbePercentage) return; mDNS_DropLockBeforeCallback(); diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c index efd61b30..dd670ab1 100644 --- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c +++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c @@ -25,7 +25,6 @@ #include "../mDNSMacOSX/DNSServiceDiscovery.h" #include "DNSServiceDiscoveryDefines.h" -#include "DNSServiceDiscoveryReplyServer.h" #include <stdlib.h> #include <stdio.h> @@ -49,25 +48,6 @@ kern_return_t DNSServiceBrowserCreate_rpc DNSCString domain ); -extern -kern_return_t DNSServiceDomainEnumerationCreate_rpc -( - mach_port_t server, - mach_port_t client, - int registrationDomains -); - -extern -kern_return_t DNSServiceRegistrationCreate_rpc -( - mach_port_t server, - mach_port_t client, - DNSCString name, - DNSCString regtype, - DNSCString domain, - IPPort port, - DNSCString txtRecord -); extern kern_return_t DNSServiceResolverResolve_rpc @@ -79,36 +59,6 @@ kern_return_t DNSServiceResolverResolve_rpc DNSCString domain ); -extern -kern_return_t DNSServiceRegistrationAddRecord_rpc -( - mach_port_t server, - mach_port_t client, - int type, - record_data_t data, - mach_msg_type_number_t record_dataCnt, - uint32_t ttl, - natural_t *reference -); - -extern -int DNSServiceRegistrationUpdateRecord_rpc -( - mach_port_t server, - mach_port_t client, - natural_t reference, - record_data_t data, - mach_msg_type_number_t record_dataCnt, - uint32_t ttl -); - -extern -kern_return_t DNSServiceRegistrationRemoveRecord_rpc -( - mach_port_t server, - mach_port_t client, - natural_t reference -); struct a_requests { struct a_requests *next; @@ -122,552 +72,51 @@ struct a_requests { void *context; }; -static struct a_requests *a_requests = NULL; -static pthread_mutex_t a_requests_lock = PTHREAD_MUTEX_INITIALIZER; - typedef struct _dns_service_discovery_t { mach_port_t port; } dns_service_discovery_t; -static mach_port_t DNSServiceDiscoveryLookupServer(void) -{ - static mach_port_t sndPort = MACH_PORT_NULL; - kern_return_t result; - - if (sndPort != MACH_PORT_NULL) { - return sndPort; - } - - result = bootstrap_look_up(bootstrap_port, DNS_SERVICE_DISCOVERY_SERVER, &sndPort); - if (result != KERN_SUCCESS) { - printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result); - sndPort = MACH_PORT_NULL; - } - - - return sndPort; -} - -static void _increaseQueueLengthOnPort(mach_port_t port) -{ - mach_port_limits_t qlimits; - kern_return_t result; - - qlimits.mpl_qlimit = 16; - result = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&qlimits, MACH_PORT_LIMITS_INFO_COUNT); - - if (result != KERN_SUCCESS) { - printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__, __FILE__, __LINE__, (int) result, mach_error_string(result)); - } -} dns_service_discovery_ref DNSServiceBrowserCreate (const char *regtype, const char *domain, DNSServiceBrowserReply callBack,void *context) { - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result; - dns_service_discovery_ref return_t; - struct a_requests *request; - - if (!serverPort) { - return NULL; - } - - result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort); - if (result != KERN_SUCCESS) { - printf("Mach port receive creation failed, %s\n", mach_error_string(result)); - return NULL; - } - result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND); - if (result != KERN_SUCCESS) { - printf("Mach port send creation failed, %s\n", mach_error_string(result)); - mach_port_destroy(mach_task_self(), clientPort); - return NULL; - } - _increaseQueueLengthOnPort(clientPort); - - return_t = malloc(sizeof(dns_service_discovery_t)); - return_t->port = clientPort; - - request = malloc(sizeof(struct a_requests)); - request->client_port = clientPort; - request->context = context; - request->callout.browserCallback = callBack; - - result = DNSServiceBrowserCreate_rpc(serverPort, clientPort, (char *)regtype, (char *)domain); - - if (result != KERN_SUCCESS) { - printf("There was an error creating a browser, %s\n", mach_error_string(result)); - free(request); - return NULL; - } - - pthread_mutex_lock(&a_requests_lock); - request->next = a_requests; - a_requests = request; - pthread_mutex_unlock(&a_requests_lock); - - return return_t; + + (void) regtype; // Unused + (void) domain; // Unused + (void) callBack; // Unused + (void) context; // Unused + + printf("DNSServiceBrowserCreate deprecated since 10.3 \n"); + return NULL; + } -/* Service Enumeration */ - -dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context) -{ - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result; - dns_service_discovery_ref return_t; - struct a_requests *request; - - if (!serverPort) { - return NULL; - } - - result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort); - if (result != KERN_SUCCESS) { - printf("Mach port receive creation failed, %s\n", mach_error_string(result)); - return NULL; - } - result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND); - if (result != KERN_SUCCESS) { - printf("Mach port send creation failed, %s\n", mach_error_string(result)); - mach_port_destroy(mach_task_self(), clientPort); - return NULL; - } - _increaseQueueLengthOnPort(clientPort); - - return_t = malloc(sizeof(dns_service_discovery_t)); - return_t->port = clientPort; - - request = malloc(sizeof(struct a_requests)); - request->client_port = clientPort; - request->context = context; - request->callout.enumCallback = callBack; - - result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains); - - if (result != KERN_SUCCESS) { - printf("There was an error creating an enumerator, %s\n", mach_error_string(result)); - free(request); - return NULL; - } - - pthread_mutex_lock(&a_requests_lock); - request->next = a_requests; - a_requests = request; - pthread_mutex_unlock(&a_requests_lock); - - return return_t; -} - - -/* Service Registration */ - -dns_service_discovery_ref DNSServiceRegistrationCreate - (const char *name, const char *regtype, const char *domain, uint16_t port, const char *txtRecord, DNSServiceRegistrationReply callBack, void *context) -{ - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result; - dns_service_discovery_ref return_t; - struct a_requests *request; - IPPort IpPort; - char *portptr = (char *)&port; - - if (!serverPort) { - return NULL; - } - - if (!txtRecord) { - txtRecord = ""; - } - - result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort); - if (result != KERN_SUCCESS) { - printf("Mach port receive creation failed, %s\n", mach_error_string(result)); - return NULL; - } - result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND); - if (result != KERN_SUCCESS) { - printf("Mach port send creation failed, %s\n", mach_error_string(result)); - mach_port_destroy(mach_task_self(), clientPort); - return NULL; - } - _increaseQueueLengthOnPort(clientPort); - - return_t = malloc(sizeof(dns_service_discovery_t)); - return_t->port = clientPort; - - request = malloc(sizeof(struct a_requests)); - request->client_port = clientPort; - request->context = context; - request->callout.regCallback = callBack; - - // older versions of this code passed the port via mach IPC as an int. - // we continue to pass it as 4 bytes to maintain binary compatibility, - // but now ensure that the network byte order is preserved by using a struct - IpPort.bytes[0] = 0; - IpPort.bytes[1] = 0; - IpPort.bytes[2] = portptr[0]; - IpPort.bytes[3] = portptr[1]; - - result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, IpPort, (char *)txtRecord); - - if (result != KERN_SUCCESS) { - printf("There was an error creating a resolve, %s\n", mach_error_string(result)); - free(request); - return NULL; - } - - pthread_mutex_lock(&a_requests_lock); - request->next = a_requests; - a_requests = request; - pthread_mutex_unlock(&a_requests_lock); - - return return_t; -} - -/* Resolver requests */ - dns_service_discovery_ref DNSServiceResolverResolve(const char *name, const char *regtype, const char *domain, DNSServiceResolverReply callBack, void *context) { - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result; - dns_service_discovery_ref return_t; - struct a_requests *request; - - if (!serverPort) { - return NULL; - } + (void) name; // Unused + (void) regtype; // Unused + (void) domain; // Unused + (void) callBack; // Unused + (void) context; // Unused + + printf("DNSServiceResolverResolve deprecated since 10.3 \n"); + return NULL; - result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort); - if (result != KERN_SUCCESS) { - printf("Mach port receive creation failed, %s\n", mach_error_string(result)); - return NULL; - } - result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND); - if (result != KERN_SUCCESS) { - printf("Mach port send creation failed, %s\n", mach_error_string(result)); - mach_port_destroy(mach_task_self(), clientPort); - return NULL; - } - _increaseQueueLengthOnPort(clientPort); - - return_t = malloc(sizeof(dns_service_discovery_t)); - return_t->port = clientPort; - - request = malloc(sizeof(struct a_requests)); - request->client_port = clientPort; - request->context = context; - request->callout.resolveCallback = callBack; - - DNSServiceResolverResolve_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain); - - pthread_mutex_lock(&a_requests_lock); - request->next = a_requests; - a_requests = request; - pthread_mutex_unlock(&a_requests_lock); - - return return_t; -} - -DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl) -{ - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - natural_t reference = 0; - kern_return_t result = KERN_SUCCESS; - - if (!serverPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - clientPort = DNSServiceDiscoveryMachPort(ref); - - if (!clientPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - result = DNSServiceRegistrationAddRecord_rpc(serverPort, clientPort, rrtype, (record_data_t)rdata, rdlen, ttl, &reference); - - if (result != KERN_SUCCESS) { - printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result)); - } - - return reference; -} - -DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl) -{ - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result = KERN_SUCCESS; - - if (!serverPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - clientPort = DNSServiceDiscoveryMachPort(ref); - - if (!clientPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - result = DNSServiceRegistrationUpdateRecord_rpc(serverPort, clientPort, (natural_t)reference, (record_data_t)rdata, rdlen, ttl); - if (result != KERN_SUCCESS) { - printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result)); - return result; - } - - return kDNSServiceDiscoveryNoError; -} - - -DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference) -{ - mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); - mach_port_t clientPort; - kern_return_t result = KERN_SUCCESS; - - if (!serverPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - clientPort = DNSServiceDiscoveryMachPort(ref); - - if (!clientPort) { - return kDNSServiceDiscoveryUnknownErr; - } - - result = DNSServiceRegistrationRemoveRecord_rpc(serverPort, clientPort, (natural_t)reference); - - if (result != KERN_SUCCESS) { - printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result)); - return result; - } - - return kDNSServiceDiscoveryNoError; } void DNSServiceDiscovery_handleReply(void *replyMsg) { - mach_msg_header_t * msgSendBufPtr; - mach_msg_header_t * receivedMessage; - unsigned msgSendBufLength; - - msgSendBufLength = internal_DNSServiceDiscoveryReply_subsystem.maxsize; - msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength); - - - receivedMessage = ( mach_msg_header_t * ) replyMsg; - - // Call DNSServiceDiscoveryReply_server to change mig-generated message into a - // genuine mach message. It will then cause the callback to get called. - DNSServiceDiscoveryReply_server ( receivedMessage, msgSendBufPtr ); - ( void ) mach_msg_send ( msgSendBufPtr ); - free(msgSendBufPtr); + (void) replyMsg; // Unused + printf("DNSServiceDiscovery_handleReply deprecated since 10.3 \n"); } mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery) { + printf("DNSServiceDiscoveryMachPort deprecated since 10.3 \n"); return dnsServiceDiscovery->port; } void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery) { - struct a_requests *request0, *request; - mach_port_t reply = dnsServiceDiscovery->port; - - if (dnsServiceDiscovery->port) { - pthread_mutex_lock(&a_requests_lock); - request0 = NULL; - request = a_requests; - while (request) { - if (request->client_port == reply) { - /* request info found, remove from list */ - if (request0) { - request0->next = request->next; - } else { - a_requests = request->next; - } - break; - } else { - /* not info for this request, skip to next */ - request0 = request; - request = request->next; - } - - } - pthread_mutex_unlock(&a_requests_lock); - - free(request); - - mach_port_destroy(mach_task_self(), dnsServiceDiscovery->port); - - free(dnsServiceDiscovery); - } - return; -} - -// reply functions, calls the users setup callbacks with function pointers - -kern_return_t internal_DNSServiceDomainEnumerationReply_rpc -( - mach_port_t reply, - int resultType, - DNSCString replyDomain, - int flags -) -{ - struct a_requests *request; - void *requestContext = NULL; - DNSServiceDomainEnumerationReply callback = NULL; - - pthread_mutex_lock(&a_requests_lock); - request = a_requests; - while (request) { - if (request->client_port == reply) { - break; - } - request = request->next; - } - - if (request != NULL) { - callback = (*request->callout.enumCallback); - requestContext = request->context; - } - pthread_mutex_unlock(&a_requests_lock); - - if (request != NULL) { - (callback)(resultType, replyDomain, flags, requestContext); - } - - return KERN_SUCCESS; - -} - -kern_return_t internal_DNSServiceBrowserReply_rpc -( - mach_port_t reply, - int resultType, - DNSCString replyName, - DNSCString replyType, - DNSCString replyDomain, - int flags -) -{ - struct a_requests *request; - void *requestContext = NULL; - DNSServiceBrowserReply callback = NULL; - - pthread_mutex_lock(&a_requests_lock); - request = a_requests; - while (request) { - if (request->client_port == reply) { - break; - } - request = request->next; - } - if (request != NULL) { - callback = (*request->callout.browserCallback); - requestContext = request->context; - } - - pthread_mutex_unlock(&a_requests_lock); - - if (request != NULL) { - (callback)(resultType, replyName, replyType, replyDomain, flags, requestContext); - } - - return KERN_SUCCESS; -} - - -kern_return_t internal_DNSServiceRegistrationReply_rpc -( - mach_port_t reply, - int resultType -) -{ - struct a_requests *request; - void *requestContext = NULL; - DNSServiceRegistrationReply callback = NULL; - - pthread_mutex_lock(&a_requests_lock); - request = a_requests; - while (request) { - if (request->client_port == reply) { - break; - } - request = request->next; - } - if (request != NULL) { - callback = (*request->callout.regCallback); - requestContext = request->context; - } - - pthread_mutex_unlock(&a_requests_lock); - if (request != NULL) { - (callback)(resultType, requestContext); - } - return KERN_SUCCESS; -} - - -kern_return_t internal_DNSServiceResolverReply_rpc -( - mach_port_t reply, - sockaddr_t interface, - sockaddr_t address, - DNSCString txtRecord, - int flags -) -{ - struct sockaddr *interface_storage = NULL; - struct sockaddr *address_storage = NULL; - struct a_requests *request; - void *requestContext = NULL; - DNSServiceResolverReply callback = NULL; - - if (interface) { - int len = ((struct sockaddr *)interface)->sa_len; - interface_storage = (struct sockaddr *)malloc(len); - memcpy(interface_storage, interface, len); - } - - if (address) { - int len = ((struct sockaddr *)address)->sa_len; - address_storage = (struct sockaddr *)malloc(len); - memcpy(address_storage, address, len); - } - - pthread_mutex_lock(&a_requests_lock); - request = a_requests; - while (request) { - if (request->client_port == reply) { - break; - } - request = request->next; - } - - if (request != NULL) { - callback = (*request->callout.resolveCallback); - requestContext = request->context; - } - pthread_mutex_unlock(&a_requests_lock); - - if (request != NULL) { - (callback)(interface_storage, address_storage, txtRecord, flags, requestContext); - } - - if (interface) { - free(interface_storage); - } - if (address) { - free(address_storage); - } - - return KERN_SUCCESS; + (void) dnsServiceDiscovery; // Unused + printf("DNSServiceDiscoveryDeallocate deprecated since 10.3 \n"); } diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h index a743dd74..004d3259 100644 --- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h +++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h @@ -17,31 +17,7 @@ /*! @header DNS Service Discovery (Deprecated Mach-based API) * - * @discussion This section describes the functions, callbacks, and data structures that - * make up the DNS Service Discovery API. - * - * The DNS Service Discovery API is part of Bonjour, Apple's implementation of - * zero-configuration networking (ZEROCONF). - * - * Bonjour allows you to register a network service, such as a - * printer or file server, so that it can be found by name or browsed - * for by service type and domain. Using Bonjour, applications can - * discover what services are available on the network, along with - * all necessary access information-such as name, IP address, and port - * number-for a given service. - * - * In effect, Bonjour combines the functions of a local DNS server - * and AppleTalk. Bonjour allows applications to provide user-friendly printer - * and server browsing, among other things, over standard IP networks. - * This behavior is a result of combining protocols such as multicast and DNS - * to add new functionality to the network (such as multicast DNS). - * - * Bonjour gives applications easy access to services over local IP - * networks without requiring the service or the application to support - * an AppleTalk or a Netbeui stack, and without requiring a DNS server - * for the local network. - * - * Note that this API was deprecated in Mac OS X 10.3, and replaced + * @discussion Note that this API was deprecated in Mac OS X 10.3, and replaced * by the portable cross-platform /usr/include/dns_sd.h API. */ @@ -71,29 +47,38 @@ enum { }; +typedef enum +{ + DNSServiceDomainEnumerationReplyAddDomain, + DNSServiceDomainEnumerationReplyAddDomainDefault, + DNSServiceDomainEnumerationReplyRemoveDomain, +} DNSServiceDomainEnumerationReplyResultType; + +typedef enum +{ + DNSServiceDiscoverReplyFlagsFinished, + DNSServiceDiscoverReplyFlagsMoreComing, +} DNSServiceDiscoveryReplyFlags; + +typedef void (*DNSServiceDomainEnumerationReply)( + DNSServiceDomainEnumerationReplyResultType resultType, // One of DNSServiceDomainEnumerationReplyResultType + const char *replyDomain, + DNSServiceDiscoveryReplyFlags flags, // DNS Service Discovery reply flags information + void *context +); + + /* possible error code values */ typedef enum { - kDNSServiceDiscoveryWaiting = 1, kDNSServiceDiscoveryNoError = 0, - // mDNS Error codes are in the range - // FFFE FF00 (-65792) to FFFE FFFF (-65537) - kDNSServiceDiscoveryUnknownErr = -65537, // 0xFFFE FFFF - kDNSServiceDiscoveryNoSuchNameErr = -65538, - kDNSServiceDiscoveryNoMemoryErr = -65539, - kDNSServiceDiscoveryBadParamErr = -65540, - kDNSServiceDiscoveryBadReferenceErr = -65541, - kDNSServiceDiscoveryBadStateErr = -65542, - kDNSServiceDiscoveryBadFlagsErr = -65543, - kDNSServiceDiscoveryUnsupportedErr = -65544, - kDNSServiceDiscoveryNotInitializedErr = -65545, - kDNSServiceDiscoveryNoCache = -65546, - kDNSServiceDiscoveryAlreadyRegistered = -65547, - kDNSServiceDiscoveryNameConflict = -65548, - kDNSServiceDiscoveryInvalid = -65549, - kDNSServiceDiscoveryMemFree = -65792 // 0xFFFE FF00 } DNSServiceRegistrationReplyErrorType; +typedef void (*DNSServiceRegistrationReply)( + DNSServiceRegistrationReplyErrorType errorCode, + void *context +); + typedef uint32_t DNSRecordReference; @@ -107,79 +92,6 @@ typedef uint32_t DNSRecordReference; */ void DNSServiceDiscovery_handleReply(void *replyMsg); -/* Service Registration */ - -typedef void (*DNSServiceRegistrationReply)( - DNSServiceRegistrationReplyErrorType errorCode, - void *context - ); - -/*! - @function DNSServiceRegistrationCreate - @discussion Register a named service with DNS Service Discovery - @param name The name of this service instance (e.g. "Steve's Printer") - @param regtype The service type (e.g. "_printer._tcp." -- see - RFC 2782 (DNS SRV) and <http://www.iana.org/assignments/port-numbers>) - @param domain The domain in which to register the service (e.g. "apple.com.") - @param port The local port on which this service is being offered (in network byte order) - @param txtRecord Optional protocol-specific additional information - @param callBack The DNSServiceRegistrationReply function to be called - @param context A user specified context which will be passed to the callout function. - @result A dns_registration_t - */ -dns_service_discovery_ref DNSServiceRegistrationCreate -( - const char *name, - const char *regtype, - const char *domain, - uint16_t port, - const char *txtRecord, - DNSServiceRegistrationReply callBack, - void *context -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; - -/***************************************************************************/ -/* DNS Domain Enumeration */ - -typedef enum -{ - DNSServiceDomainEnumerationReplyAddDomain, // Domain found - DNSServiceDomainEnumerationReplyAddDomainDefault, // Domain found (and should be selected by default) - DNSServiceDomainEnumerationReplyRemoveDomain, // Domain has been removed from network -} DNSServiceDomainEnumerationReplyResultType; - -typedef enum -{ - DNSServiceDiscoverReplyFlagsFinished, - DNSServiceDiscoverReplyFlagsMoreComing, -} DNSServiceDiscoveryReplyFlags; - -typedef void (*DNSServiceDomainEnumerationReply)( - DNSServiceDomainEnumerationReplyResultType resultType, // One of DNSServiceDomainEnumerationReplyResultType - const char *replyDomain, - DNSServiceDiscoveryReplyFlags flags, // DNS Service Discovery reply flags information - void *context - ); - -/*! - @function DNSServiceDomainEnumerationCreate - @discussion Asynchronously create a DNS Domain Enumerator - @param registrationDomains A boolean indicating whether you are looking - for recommended registration domains - (e.g. equivalent to the AppleTalk zone list in the AppleTalk Control Panel) - or recommended browsing domains - (e.g. equivalent to the AppleTalk zone list in the Chooser). - @param callBack The function to be called when domains are found or removed - @param context A user specified context which will be passed to the callout function. - @result A dns_registration_t - */ -dns_service_discovery_ref DNSServiceDomainEnumerationCreate -( - int registrationDomains, - DNSServiceDomainEnumerationReply callBack, - void *context -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; - /***************************************************************************/ /* DNS Service Browser */ @@ -271,44 +183,6 @@ mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDisc */ void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; -/***************************************************************************/ -/* Registration updating */ - - -/*! - @function DNSServiceRegistrationAddRecord - @discussion Request that the mDNS Responder add the DNS Record of a specific type - @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call - @param rrtype A standard DNS Resource Record Type, from http://www.iana.org/assignments/dns-parameters - @param rdlen Length of the data - @param rdata Opaque binary Resource Record data, up to 64 kB. - @param ttl time to live for the added record. - @result DNSRecordReference An opaque reference that can be passed to the update and remove record calls. If an error occurs, this value will be zero or negative - */ -DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref dnsServiceDiscovery, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; - -/*! - @function DNSServiceRegistrationUpdateRecord - @discussion Request that the mDNS Responder add the DNS Record of a specific type - @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call - @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call - @param rdlen Length of the data - @param rdata Opaque binary Resource Record data, up to 64 kB. - @param ttl time to live for the updated record. - @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero - */ -DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; - -/*! - @function DNSServiceRegistrationRemoveRecord - @discussion Request that the mDNS Responder remove the DNS Record(s) of a specific type - @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call - @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call - @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero - */ -DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3; - - __END_DECLS #endif /* __DNS_SERVICE_DISCOVERY_H */ diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h index 22687b90..01a28cd7 100644 --- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h +++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h @@ -20,8 +20,6 @@ #include <mach/mach_types.h> -#define DNS_SERVICE_DISCOVERY_SERVER "com.apple.mDNSResponder" - typedef char DNSCString[1024]; typedef char sockaddr_t[128]; diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs deleted file mode 100644 index 993c9553..00000000 --- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2002-2003, 2006 Apple Computer, 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. - */ - -subsystem - DNSServiceDiscoveryReply 7250; - -ServerPrefix internal_; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -import "DNSServiceDiscoveryDefines.h"; - -type DNSCString = c_string[*:1024]; -type sockaddr_t = array[128] of char; - -simpleroutine DNSServiceDomainEnumerationReply_rpc( - reply: mach_port_t; - in resultType: int; - in replyDomain: DNSCString; - in flags: int; - SendTime to: natural_t); - -simpleroutine DNSServiceBrowserReply_rpc( - reply: mach_port_t; - in resultType: int; - in replyName: DNSCString; - in replyType: DNSCString; - in replyDomain: DNSCString; - in flags: int; - SendTime to: natural_t); - - -simpleroutine DNSServiceRegistrationReply_rpc( - reply: mach_port_t; - in resultType: int; - SendTime to: natural_t); - - -simpleroutine DNSServiceResolverReply_rpc( - reply: mach_port_t; - in interface: sockaddr_t; - in address: sockaddr_t; - in txtRecord: DNSCString; - in flags: int; - SendTime to: natural_t); diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs deleted file mode 100644 index d3fe292a..00000000 --- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2002-2004, 2006 Apple Computer, 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. - */ - -subsystem - DNSServiceDiscoveryRequest 7200; - -ServerPrefix provide_; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -import "DNSServiceDiscoveryDefines.h"; - -type DNSCString = c_string[*:1024]; -type record_data = ^ array [] of MACH_MSG_TYPE_BYTE - ctype: record_data_t; -type IPPort = struct[4] of char ctype:IPPort; - -simpleroutine DNSServiceBrowserCreate_rpc( - server: mach_port_t; - in client: mach_port_t; - in regtype: DNSCString; - in domain: DNSCString); - - -simpleroutine DNSServiceDomainEnumerationCreate_rpc( - server: mach_port_t; - in client: mach_port_t; - in registrationDomains: int); - -simpleroutine DNSServiceRegistrationCreate_rpc( - server: mach_port_t; - in client: mach_port_t; - in name: DNSCString; - in regtype: DNSCString; - in domain: DNSCString; - in port: IPPort; - in txtRecord: DNSCString); - - -simpleroutine DNSServiceResolverResolve_rpc( - server: mach_port_t; - in client: mach_port_t; - in name: DNSCString; - in regtype: DNSCString; - in domain: DNSCString); - -routine DNSServiceRegistrationAddRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_type: int; - in record_data: record_data; - in ttl: uint32_t; - out record_reference: natural_t); - -simpleroutine DNSServiceRegistrationUpdateRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_reference: natural_t; - in record_data: record_data; - in ttl: uint32_t); - -simpleroutine DNSServiceRegistrationRemoveRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_reference: natural_t); diff --git a/mDNSResponder/mDNSMacOSX/Metrics.h b/mDNSResponder/mDNSMacOSX/Metrics.h index a9dea79a..dbe6196a 100644 --- a/mDNSResponder/mDNSMacOSX/Metrics.h +++ b/mDNSResponder/mDNSMacOSX/Metrics.h @@ -25,9 +25,10 @@ extern "C" { #endif #if TARGET_OS_EMBEDDED -mStatus MetricsInit(void); -void MetricsUpdateUDNSStats(const domainname *inQueryName, mDNSBool inAnswered, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCellular); -void LogMetrics(void); +mStatus MetricsInit(void); +void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); +void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell); +void LogMetrics(void); #endif #ifdef __cplusplus diff --git a/mDNSResponder/mDNSMacOSX/Metrics.m b/mDNSResponder/mDNSMacOSX/Metrics.m index 56467dfc..8dae3f5f 100644 --- a/mDNSResponder/mDNSMacOSX/Metrics.m +++ b/mDNSResponder/mDNSMacOSX/Metrics.m @@ -17,12 +17,18 @@ #import "Metrics.h" -#if TARGET_OS_EMBEDDED +#if (TARGET_OS_EMBEDDED) #import <CoreUtils/SoftLinking.h> #import <WirelessDiagnostics/AWDDNSDomainStats.h> #import <WirelessDiagnostics/AWDMDNSResponderDNSStatistics.h> +#import <WirelessDiagnostics/AWDMDNSResponderResolveStats.h> +#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDNSServer.h> +#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDomain.h> +#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsHostname.h> +#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsResult.h> #import <WirelessDiagnostics/AWDMetricIds_MDNSResponder.h> #import <WirelessDiagnostics/WirelessDiagnostics.h> +#import <WirelessDiagnostics/AWDMDNSResponderServicesStats.h> #import "DNSCommon.h" #import "mDNSMacOSX.h" @@ -34,44 +40,116 @@ SOFT_LINK_FRAMEWORK(PrivateFrameworks, WirelessDiagnostics) -SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection) -#define AWDServerConnectionSoft getAWDServerConnectionClass() - -SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics) -#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass() - SOFT_LINK_CLASS(WirelessDiagnostics, AWDDNSDomainStats) -#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass() +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStats) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDNSServer) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDomain) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsHostname) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsResult) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager) + +#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass() +#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass() +#define AWDMDNSResponderResolveStatsSoft getAWDMDNSResponderResolveStatsClass() +#define AWDMDNSResponderResolveStatsResultSoft getAWDMDNSResponderResolveStatsResultClass() +#define AWDMDNSResponderResolveStatsDNSServerSoft getAWDMDNSResponderResolveStatsDNSServerClass() +#define AWDMDNSResponderResolveStatsDomainSoft getAWDMDNSResponderResolveStatsDomainClass() +#define AWDMDNSResponderResolveStatsHostnameSoft getAWDMDNSResponderResolveStatsHostnameClass() +#define AWDServerConnectionSoft getAWDServerConnectionClass() +#define AWDMetricManagerSoft getAWDMetricManagerClass() //=========================================================================================================================== // Macros //=========================================================================================================================== -#define countof(X) (sizeof(X) / sizeof(X[0])) +#define countof(X) (sizeof(X) / sizeof(X[0])) +#define countof_field(TYPE, FIELD) countof(((TYPE *)0)->FIELD) +#define increment_saturate(VAR, MAX) do {if ((VAR) < (MAX)) {++(VAR);}} while (0) +#define ForgetMem(X) do {if(*(X)) {free(*(X)); *(X) = NULL;}} while(0) //=========================================================================================================================== // Constants //=========================================================================================================================== -#define kUDNSStatsMaxQuerySendCount 10 +#define kQueryStatsMaxQuerySendCount 10 +#define kQueryStatsSendCountBinCount (kQueryStatsMaxQuerySendCount + 1) +#define kQueryStatsLatencyBinCount 55 +#define kResolveStatsMaxObjCount 2000 + +//=========================================================================================================================== +// Data structures +//=========================================================================================================================== + +typedef struct +{ + const char * cstr; // Name of domain as a c-string. + const domainname * name; // Name of domain as length-prefixed labels. + int labelCount; // Number of labels in domain name. Used for domain name comparisons. + +} Domain; -// Important: Do not update this list without getting privacy approval. See <rdar://problem/24155761>. +// Important: Do not add to this list without getting privacy approval beforehand. See <rdar://problem/24155761&26397203>. +// If you get approval and do add a domain to this list, make sure it passes ValidateDNSStatsDomains() below. -static const char * const kUDNSStatsDomains[] = +static const Domain kQueryStatsDomains[] = { - ".", - "apple.com.", - "icloud.com.", - "me.com.", - "google.com.", - "facebook.com.", - "youtube.com.", - "baidu.com.", - "amazon.com.", - "yahoo.com.", - "wikipedia.org." + { ".", (domainname *)"", 0 }, + { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, + { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, + { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, + { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 }, + { "google.com.", (domainname *)"\x6" "google" "\x3" "com", 2 }, + { "youtube.com.", (domainname *)"\x7" "youtube" "\x3" "com", 2 }, + { "facebook.com.", (domainname *)"\x8" "facebook" "\x3" "com", 2 }, + { "baidu.com.", (domainname *)"\x5" "baidu" "\x3" "com", 2 }, + { "yahoo.com.", (domainname *)"\x5" "yahoo" "\x3" "com", 2 }, + { "qq.com.", (domainname *)"\x2" "qq" "\x3" "com", 2 }, }; +check_compile_time(countof(kQueryStatsDomains) == 11); + +// DNSHist contains the per domain per network type histogram data that goes in a DNSDomainStats protobuf message. See +// <rdar://problem/23980546> MDNSResponder.proto update. +// +// answeredQuerySendCountBins +// +// An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an answered DNS query +// was sent i times. The value at index 10 is the number of times that an answered query was sent 10+ times. +// +// unansweredQuerySendCountBins +// +// An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an unanswered DNS query +// was sent i times. The value at index 10 is the number of times that an unanswered query was sent 10+ times. +// +// responseLatencyBins +// +// An array of 55 histogram bins. Each array value is the number of DNS queries that were answered in a paricular time +// interval. The 55 consecutive non-overlapping time intervals have the following non-inclusive upper bounds (all values are +// in milliseconds): 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, +// 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000, 1500, 2000, 2500, 3000, 3500, 4000, +// 4500, 5000, 6000, 7000, 8000, 9000, 10000, ∞. + +typedef struct +{ + uint16_t unansweredQuerySendCountBins[kQueryStatsSendCountBinCount]; + uint16_t unansweredQueryDurationBins[kQueryStatsLatencyBinCount]; + uint16_t answeredQuerySendCountBins[kQueryStatsSendCountBinCount]; + uint16_t responseLatencyBins[kQueryStatsLatencyBinCount]; + uint16_t negAnsweredQuerySendCountBins[kQueryStatsSendCountBinCount]; + uint16_t negResponseLatencyBins[kQueryStatsLatencyBinCount]; + +} DNSHist; + +check_compile_time(sizeof(DNSHist) <= 512); +check_compile_time(countof_field(DNSHist, unansweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); +check_compile_time(countof_field(DNSHist, answeredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); +check_compile_time(countof_field(DNSHist, negAnsweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); + +// Important: Do not modify kResponseLatencyMsLimits because the code used to generate AWD reports expects the response +// latency histogram bins to observe these time interval upper bounds. + static const mDNSu32 kResponseLatencyMsLimits[] = { 1, 2, 3, 4, 5, @@ -83,51 +161,200 @@ static const mDNSu32 kResponseLatencyMsLimits[] = 10000 }; -//=========================================================================================================================== -// Data structures -//=========================================================================================================================== +check_compile_time(countof(kResponseLatencyMsLimits) == 54); +check_compile_time(countof_field(DNSHist, unansweredQueryDurationBins) == (countof(kResponseLatencyMsLimits) + 1)); +check_compile_time(countof_field(DNSHist, responseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); +check_compile_time(countof_field(DNSHist, negResponseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); typedef struct { - uint32_t answeredQuerySendCountBins[kUDNSStatsMaxQuerySendCount + 1]; - uint32_t unansweredQuerySendCountBins[kUDNSStatsMaxQuerySendCount + 1]; - uint32_t responseLatencyBins[countof(kResponseLatencyMsLimits) + 1]; + DNSHist * histAny; // Histogram data for queries of any resource record type. + DNSHist * histA; // Histogram data for queries for A resource records. + DNSHist * histAAAA; // Histogram data for queries for AAAA resource records. -} DNSStats; +} DNSHistSet; -typedef struct DNSDomainStats * DNSDomainStatsRef; +typedef struct DNSDomainStats DNSDomainStats; struct DNSDomainStats { - DNSDomainStatsRef next; - domainname domain; - int domainLabelCount; - char * domainStr; - DNSStats stats; - DNSStats statsCellular; + DNSDomainStats * next; // Pointer to next domain stats in list. + const Domain * domain; // Domain for which these stats are collected. + DNSHistSet * nonCellular; // Query stats for queries sent over non-cellular interfaces. + DNSHistSet * cellular; // Query stats for queries sent over cellular interfaces. +}; + +check_compile_time(sizeof(struct DNSDomainStats) <= 32); + +static const Domain kResolveStatsDomains[] = +{ + { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, + { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, + { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, + { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 }, +}; + +check_compile_time(countof(kResolveStatsDomains) == 4); + +typedef struct ResolveStatsDomain ResolveStatsDomain; +typedef struct ResolveStatsHostname ResolveStatsHostname; +typedef struct ResolveStatsDNSServer ResolveStatsDNSServer; +typedef struct ResolveStatsIPv4AddrSet ResolveStatsIPv4AddrSet; +typedef struct ResolveStatsIPv6Addr ResolveStatsIPv6Addr; +typedef struct ResolveStatsNegAAAASet ResolveStatsNegAAAASet; + +struct ResolveStatsDomain +{ + ResolveStatsDomain * next; // Next domain object in list. + ResolveStatsHostname * hostnameList; // List of hostname objects in this domain. + const Domain * domainInfo; // Pointer to domain info. +}; + +struct ResolveStatsHostname +{ + ResolveStatsHostname * next; // Next hostname object in list. + ResolveStatsIPv4AddrSet * addrV4List; // List of IPv4 addresses to which this hostname resolved. + ResolveStatsIPv6Addr * addrV6List; // List of IPv6 addresses to which this hostname resolved. + ResolveStatsNegAAAASet * negV6List; // List of negative AAAA response objects. + uint8_t name[1]; // Variable length storage for hostname as length-prefixed labels. +}; + +check_compile_time(sizeof(ResolveStatsHostname) <= 64); + +struct ResolveStatsDNSServer +{ + ResolveStatsDNSServer * next; // Next DNS server object in list. + uint8_t id; // 8-bit ID assigned to this DNS server used by IP address objects. + mDNSBool isForCell; // True if this DNS server belongs to a cellular interface. + mDNSBool isAddrV6; // True if this DNS server has an IPv6 address instead of IPv4. + uint8_t addrBytes[1]; // Variable length storage for DNS server's IP address. +}; + +check_compile_time(sizeof(ResolveStatsDNSServer) <= 32); + +typedef struct +{ + uint16_t count; // Number of times this IPv4 address was provided as a resolution result. + uint8_t serverID; // 8-bit ID of the DNS server from which this IPv4 address came. + uint8_t isNegative; + uint8_t addrBytes[4]; // IPv4 address bytes. + +} IPv4AddrCounter; + +check_compile_time(sizeof(IPv4AddrCounter) <= 8); + +struct ResolveStatsIPv4AddrSet +{ + ResolveStatsIPv4AddrSet * next; // Next set of IPv4 address counters in list. + IPv4AddrCounter counters[3]; // Array of IPv4 address counters. +}; + +check_compile_time(sizeof(ResolveStatsIPv4AddrSet) <= 32); + +struct ResolveStatsIPv6Addr +{ + ResolveStatsIPv6Addr * next; // Next IPv6 address object in list. + uint16_t count; // Number of times this IPv6 address was provided as a resolution result. + uint8_t serverID; // 8-bit ID of the DNS server from which this IPv6 address came. + uint8_t addrBytes[16]; // IPv6 address bytes. +}; + +check_compile_time(sizeof(ResolveStatsIPv6Addr) <= 32); + +typedef struct +{ + uint16_t count; // Number of times that a negative response was returned by a DNS server. + uint8_t serverID; // 8-bit ID of the DNS server that sent the negative responses. + +} NegAAAACounter; + +check_compile_time(sizeof(NegAAAACounter) <= 4); + +struct ResolveStatsNegAAAASet +{ + ResolveStatsNegAAAASet * next; // Next set of negative AAAA response counters in list. + NegAAAACounter counters[6]; // Array of negative AAAA response counters. }; +check_compile_time(sizeof(ResolveStatsNegAAAASet) <= 32); + +typedef enum +{ + kResponseType_IPv4Addr = 1, + kResponseType_IPv6Addr = 2, + kResponseType_NegA = 3, + kResponseType_NegAAAA = 4 + +} ResponseType; + +typedef struct +{ + ResponseType type; + const uint8_t * data; + +} Response; + //=========================================================================================================================== // Globals //=========================================================================================================================== extern mDNS mDNSStorage; -static DNSDomainStatsRef gDomainStatsList = NULL; -static AWDServerConnection * gAWDServerConnection = nil; +static DNSDomainStats * gDomainStatsList = NULL; +static ResolveStatsDomain * gResolveStatsList = NULL; +static ResolveStatsDNSServer * gResolveStatsServerList = NULL; +static unsigned int gResolveStatsNextServerID = 0; +static int gResolveStatsObjCount = 0; +static AWDServerConnection * gAWDServerConnection = nil; //=========================================================================================================================== // Local Prototypes //=========================================================================================================================== -mDNSlocal mStatus DNSDomainStatsCreate(const char *inDomain, DNSDomainStatsRef *outStats); -mDNSlocal void DNSDomainStatsFree(DNSDomainStatsRef inStats); -mDNSlocal void DNSDomainStatsFreeList(DNSDomainStatsRef inList); - -mDNSlocal mStatus CreateDomainStatsList(DNSDomainStatsRef *outList); -mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs); -mDNSlocal mStatus SubmitAWDMetric(void); -mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomain, mDNSBool inIsForCellular, AWDDNSDomainStats **outAWDStats); -mDNSlocal void LogDNSStats(const DNSStats *inStats); +mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats); +mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats); +mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList); +mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); + +mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain); +mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain); +mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell); +mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain); + +mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname); +mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname); +mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID); +mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname); + +mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer); +mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer); +mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer); + +mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet); +mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet); + +mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr); +mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr); + +mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet); +mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet); +mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID); + +mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList); +mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList); +mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList); +mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList); +mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID); +mDNSlocal mStatus SubmitAWDMetricQueryStats(void); +mDNSlocal mStatus SubmitAWDMetricResolveStats(void); +mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats); +mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); +mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); +mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType); +mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]); +mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]); +#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) +mDNSlocal void ValidateDNSStatsDomains(void); +#endif //=========================================================================================================================== // MetricsInit @@ -137,28 +364,48 @@ mStatus MetricsInit(void) { mStatus err; +#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) + ValidateDNSStatsDomains(); +#endif + err = CreateDomainStatsList(&gDomainStatsList); require_noerr_quiet(err, exit); + err = CreateResolveStatsList(&gResolveStatsList); + require_noerr_quiet(err, exit); + @autoreleasepool { gAWDServerConnection = [[AWDServerConnectionSoft alloc] - initWithComponentId: AWDComponentId_MDNSResponder - andBlockOnConfiguration: NO]; + initWithComponentId: AWDComponentId_MDNSResponder + andBlockOnConfiguration: NO]; if (gAWDServerConnection) { [gAWDServerConnection - registerQueriableMetricCallback: ^(UInt32 metricId) + registerQueriableMetricCallback: ^(UInt32 inMetricID) { - mStatus localErr; - - (void) metricId; - - localErr = SubmitAWDMetric(); - if (localErr) LogMsg("SubmitAWDMetric failed with error %d", localErr); + SubmitAWDMetric(inMetricID); } forIdentifier: (UInt32)AWDMetricId_MDNSResponder_DNSStatistics]; + + [gAWDServerConnection + registerQueriableMetricCallback: ^(UInt32 inMetricID) + { + SubmitAWDMetric(inMetricID); + } + forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ResolveStats]; + + [gAWDServerConnection + registerQueriableMetricCallback: ^(UInt32 inMetricID) + { + SubmitAWDMetric(inMetricID); + } + forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ServicesStats]; + } + else + { + LogMsg("MetricsInit: failed to create AWD server connection."); } } exit: @@ -166,67 +413,1022 @@ exit: } //=========================================================================================================================== -// MetricsUpdateUDNSStats +// MetricsUpdateUDNSQueryStats //=========================================================================================================================== -mDNSexport void MetricsUpdateUDNSStats(const domainname *inQueryName, mDNSBool inAnswered, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCellular) +mDNSexport void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) { - DNSStats * stats; - DNSDomainStatsRef domainStats; + DNSDomainStats * stats; int queryLabelCount; + const domainname * queryParentDomain; mDNSBool isQueryInDomain; + int skipCount; + int skipCountLast = -1; queryLabelCount = CountLabels(inQueryName); - for (domainStats = gDomainStatsList; domainStats; domainStats = domainStats->next) + for (stats = gDomainStatsList; stats; stats = stats->next) { isQueryInDomain = mDNSfalse; - if (strcmp(domainStats->domainStr, ".") == 0) + if (strcmp(stats->domain->cstr, ".") == 0) { // All queries are in the root domain. isQueryInDomain = mDNStrue; } else { - int skipCount; - const domainname * queryParentDomain; - - skipCount = queryLabelCount - domainStats->domainLabelCount; + skipCount = queryLabelCount - stats->domain->labelCount; if (skipCount >= 0) { - queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); - isQueryInDomain = SameDomainName(queryParentDomain, &domainStats->domain); + if (skipCount != skipCountLast) + { + queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); + skipCountLast = skipCount; + } + isQueryInDomain = SameDomainName(queryParentDomain, stats->domain->name); } } if (isQueryInDomain) { - stats = inForCellular ? &domainStats->statsCellular : &domainStats->stats; - UpdateDNSStats(stats, inAnswered, inSendCount, inLatencyMs); + DNSDomainStatsUpdate(stats, inType, inRR, inSendCount, inLatencyMs, inForCell); + } + } + +} + +//=========================================================================================================================== +// MetricsUpdateUDNSResolveStats +//=========================================================================================================================== + +mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell) +{ + ResolveStatsDomain * domain; + domainname hostname; + size_t hostnameLen; + mDNSBool isQueryInDomain; + int skipCount; + int skipCountLast = -1; + int queryLabelCount; + const domainname * queryParentDomain; + Response response; + + require_quiet((inRR->rrtype == kDNSType_A) || (inRR->rrtype == kDNSType_AAAA), exit); + require_quiet(inRR->rDNSServer, exit); + + queryLabelCount = CountLabels(inQueryName); + + for (domain = gResolveStatsList; domain; domain = domain->next) + { + isQueryInDomain = mDNSfalse; + skipCount = queryLabelCount - domain->domainInfo->labelCount; + if (skipCount >= 0) + { + if (skipCount != skipCountLast) + { + queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); + skipCountLast = skipCount; + } + isQueryInDomain = SameDomainName(queryParentDomain, domain->domainInfo->name); + } + if (!isQueryInDomain) continue; + + hostnameLen = (size_t)(queryParentDomain->c - inQueryName->c); + if (hostnameLen >= sizeof(hostname.c)) continue; + + memcpy(hostname.c, inQueryName->c, hostnameLen); + hostname.c[hostnameLen] = 0; + + if (inRR->RecordType == kDNSRecordTypePacketNegative) + { + response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_NegA : kResponseType_NegAAAA; + response.data = NULL; + } + else + { + response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_IPv4Addr : kResponseType_IPv6Addr; + response.data = (inRR->rrtype == kDNSType_A) ? inRR->rdata->u.ipv4.b : inRR->rdata->u.ipv6.b; + } + ResolveStatsDomainUpdate(domain, &hostname, &response, &inRR->rDNSServer->addr, inForCell); + } + +exit: + return; +} + +//=========================================================================================================================== +// LogMetrics +//=========================================================================================================================== + +mDNSexport void LogMetrics(void) +{ + DNSDomainStats * stats; + const ResolveStatsDomain * domain; + const ResolveStatsHostname * hostname; + const ResolveStatsDNSServer * server; + const ResolveStatsIPv4AddrSet * addrV4; + const ResolveStatsIPv6Addr * addrV6; + const ResolveStatsNegAAAASet * negV6; + int hostnameCount; + int i; + unsigned int serverID; + int serverObjCount = 0; + int hostnameObjCount = 0; + int addrObjCount = 0; + + LogMsgNoIdent("---- DNS query stats by domain -----"); + + for (stats = gDomainStatsList; stats; stats = stats->next) + { + if (!stats->nonCellular && !stats->cellular) + { + LogMsgNoIdent("No data for %s", stats->domain->cstr); + continue; + } + if (stats->nonCellular) LogDNSHistSet(stats->nonCellular, stats->domain->cstr, mDNSfalse); + if (stats->cellular) LogDNSHistSet(stats->cellular, stats->domain->cstr, mDNStrue); + } + + LogMsgNoIdent("---- DNS resolve stats by domain -----"); + + LogMsgNoIdent("Servers:"); + for (server = gResolveStatsServerList; server; server = server->next) + { + serverObjCount++; + LogMsgNoIdent(server->isAddrV6 ? "%2u: %s %.16a" : "%2u: %s %.4a", + server->id, server->isForCell ? " C" : "NC", server->addrBytes); + } + + for (domain = gResolveStatsList; domain; domain = domain->next) + { + hostnameCount = 0; + for (hostname = domain->hostnameList; hostname; hostname = hostname->next) { hostnameCount++; } + hostnameObjCount += hostnameCount; + + LogMsgNoIdent("%##s (%d hostname%s)", domain->domainInfo->name, hostnameCount, (hostnameCount == 1) ? "" : "s"); + + for (hostname = domain->hostnameList; hostname; hostname = hostname->next) + { + LogMsgNoIdent(" %##s", hostname->name); + for (serverID = 0; serverID < gResolveStatsNextServerID; ++serverID) + { + for (addrV4 = hostname->addrV4List; addrV4; addrV4 = addrV4->next) + { + if (serverID == 0) addrObjCount++; + for (i = 0; i < (int)countof(addrV4->counters); ++i) + { + const IPv4AddrCounter * counter; + + counter = &addrV4->counters[i]; + if (counter->count == 0) break; + if (counter->serverID == serverID) + { + if (counter->isNegative) + { + LogMsgNoIdent("%10u: %3u negative A", counter->serverID, counter->count); + } + else + { + LogMsgNoIdent("%10u: %3u %.4a", counter->serverID, counter->count, counter->addrBytes); + } + } + } + } + for (addrV6 = hostname->addrV6List; addrV6; addrV6 = addrV6->next) + { + if (serverID == 0) addrObjCount++; + if (addrV6->serverID == serverID) + { + LogMsgNoIdent("%10u: %3u %.16a", addrV6->serverID, addrV6->count, addrV6->addrBytes); + } + } + for (negV6 = hostname->negV6List; negV6; negV6 = negV6->next) + { + if (serverID == 0) addrObjCount++; + for (i = 0; i < (int)countof(negV6->counters); ++i) + { + const NegAAAACounter * counter; + + counter = &negV6->counters[i]; + if (counter->count == 0) break; + if (counter->serverID == serverID) + { + LogMsgNoIdent("%10u: %3u negative AAAA", counter->serverID, counter->count); + } + } + } + } + } + } + LogMsgNoIdent("Total object count: %3d (server %d hostname %d address %d)", + serverObjCount + hostnameObjCount + addrObjCount, serverObjCount, hostnameObjCount, addrObjCount); + + LogMsgNoIdent("---- Num of Services Registered -----"); + LogMsgNoIdent("Current_number_of_services_registered :[%d], Max_number_of_services_registered :[%d]", + curr_num_regservices, max_num_regservices); +} + +//=========================================================================================================================== +// DNSDomainStatsCreate +//=========================================================================================================================== + +mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats) +{ + mStatus err; + DNSDomainStats * obj; + + obj = (DNSDomainStats *)calloc(1, sizeof(*obj)); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + obj->domain = inDomain; + + *outStats = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// DNSDomainStatsFree +//=========================================================================================================================== + +mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats) +{ + if (inStats->nonCellular) + { + ForgetMem(&inStats->nonCellular->histAny); + ForgetMem(&inStats->nonCellular->histA); + ForgetMem(&inStats->nonCellular->histAAAA); + free(inStats->nonCellular); + inStats->nonCellular = NULL; + } + if (inStats->cellular) + { + ForgetMem(&inStats->cellular->histAny); + ForgetMem(&inStats->cellular->histA); + ForgetMem(&inStats->cellular->histAAAA); + free(inStats->cellular); + inStats->cellular = NULL; + } + free(inStats); +} + +//=========================================================================================================================== +// DNSDomainStatsFreeList +//=========================================================================================================================== + +mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList) +{ + DNSDomainStats * stats; + + while ((stats = inList) != NULL) + { + inList = stats->next; + DNSDomainStatsFree(stats); + } +} + +//=========================================================================================================================== +// DNSDomainStatsUpdate +//=========================================================================================================================== + +mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) +{ + mStatus err; + DNSHistSet ** p; + DNSHistSet * set; + DNSHist * histAny; + DNSHist * hist; + int i; + + require_action_quiet(inRR || (inQuerySendCount > 0), exit, err = mStatus_NoError); + + p = inForCell ? &inStats->cellular : &inStats->nonCellular; + if ((set = *p) == NULL) + { + set = (DNSHistSet *)calloc(1, sizeof(*set)); + require_action_quiet(set, exit, err = mStatus_NoMemoryErr); + *p = set; + } + if ((histAny = set->histAny) == NULL) + { + histAny = (DNSHist *)calloc(1, sizeof(*histAny)); + require_action_quiet(histAny, exit, err = mStatus_NoMemoryErr); + set->histAny = histAny; + } + if (inType == kDNSType_A) + { + if ((hist = set->histA) == NULL) + { + hist = (DNSHist *)calloc(1, sizeof(*hist)); + require_action_quiet(hist, exit, err = mStatus_NoMemoryErr); + set->histA = hist; + } + } + else if (inType == kDNSType_AAAA) + { + if ((hist = set->histAAAA) == NULL) + { + hist = (DNSHist *)calloc(1, sizeof(*hist)); + require_action_quiet(hist, exit, err = mStatus_NoMemoryErr); + set->histAAAA = hist; + } + } + else + { + hist = NULL; + } + + if (inRR) + { + uint16_t * sendCountBins; + uint16_t * latencyBins; + const mDNSBool isNegative = (inRR->RecordType == kDNSRecordTypePacketNegative); + + i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount); + + sendCountBins = isNegative ? histAny->negAnsweredQuerySendCountBins : histAny->answeredQuerySendCountBins; + increment_saturate(sendCountBins[i], UINT16_MAX); + if (hist) + { + sendCountBins = isNegative ? hist->negAnsweredQuerySendCountBins : hist->answeredQuerySendCountBins; + increment_saturate(sendCountBins[i], UINT16_MAX); + } + + if (inQuerySendCount > 0) + { + for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {} + latencyBins = isNegative ? histAny->negResponseLatencyBins : histAny->responseLatencyBins; + increment_saturate(latencyBins[i], UINT16_MAX); + if (hist) + { + latencyBins = isNegative ? hist->negResponseLatencyBins : hist->responseLatencyBins; + increment_saturate(latencyBins[i], UINT16_MAX); + } } } + else + { + i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount); + increment_saturate(histAny->unansweredQuerySendCountBins[i], UINT16_MAX); + if (hist) increment_saturate(hist->unansweredQuerySendCountBins[i], UINT16_MAX); + + for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {} + increment_saturate(histAny->unansweredQueryDurationBins[i], UINT16_MAX); + if (hist) increment_saturate(hist->unansweredQueryDurationBins[i], UINT16_MAX); + } + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsDomainCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain) +{ + mStatus err; + ResolveStatsDomain * obj; + + obj = (ResolveStatsDomain *)calloc(1, sizeof(*obj)); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + obj->domainInfo = inDomain; + + *outDomain = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsDomainFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain) +{ + ResolveStatsHostname * hostname; + + while ((hostname = inDomain->hostnameList) != NULL) + { + inDomain->hostnameList = hostname->next; + ResolveStatsHostnameFree(hostname); + } + free(inDomain); +} + +//=========================================================================================================================== +// ResolveStatsDomainUpdate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell) +{ + mStatus err; + ResolveStatsHostname ** p; + ResolveStatsHostname * hostname; + uint8_t serverID; + + for (p = &inDomain->hostnameList; (hostname = *p) != NULL; p = &hostname->next) + { + if (SameDomainName((domainname *)hostname->name, inHostname)) break; + } + + if (!hostname) + { + require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); + err = ResolveStatsHostnameCreate(inHostname, &hostname); + require_noerr_quiet(err, exit); + gResolveStatsObjCount++; + *p = hostname; + } + + err = ResolveStatsGetServerID(inDNSAddr, inForCell, &serverID); + require_noerr_quiet(err, exit); + + err = ResolveStatsHostnameUpdate(hostname, inResp, serverID); + require_noerr_quiet(err, exit); + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsHostnameCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname) +{ + mStatus err; + ResolveStatsHostname * obj; + size_t nameLen; + + nameLen = DomainNameLength(inName); + require_action_quiet(nameLen > 0, exit, err = mStatus_Invalid); + + obj = (ResolveStatsHostname *)calloc(1, sizeof(*obj) - 1 + nameLen); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + memcpy(obj->name, inName, nameLen); + + *outHostname = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsDomainCreateAWDVersion +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain) +{ + mStatus err; + AWDMDNSResponderResolveStatsDomain * domain; + ResolveStatsHostname * hostname; + AWDMDNSResponderResolveStatsHostname * awdHostname; + NSString * name; + + domain = [[AWDMDNSResponderResolveStatsDomainSoft alloc] init]; + require_action_quiet(domain, exit, err = mStatus_UnknownErr); + + name = [[NSString alloc] initWithUTF8String:inDomain->domainInfo->cstr]; + require_action_quiet(name, exit, err = mStatus_UnknownErr); + + domain.name = name; + [name release]; + name = nil; + + for (hostname = inDomain->hostnameList; hostname; hostname = hostname->next) + { + err = ResolveStatsHostnameCreateAWDVersion(hostname, &awdHostname); + require_noerr_quiet(err, exit); + + [domain addHostname:awdHostname]; + [awdHostname release]; + awdHostname = nil; + } + + *outDomain = domain; + domain = nil; + err = mStatus_NoError; + +exit: + [domain release]; + return (err); +} + +//=========================================================================================================================== +// ResolveStatsHostnameFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname) +{ + ResolveStatsIPv4AddrSet * addrV4; + ResolveStatsIPv6Addr * addrV6; + ResolveStatsNegAAAASet * negV6; + + while ((addrV4 = inHostname->addrV4List) != NULL) + { + inHostname->addrV4List = addrV4->next; + ResolveStatsIPv4AddrSetFree(addrV4); + } + while ((addrV6 = inHostname->addrV6List) != NULL) + { + inHostname->addrV6List = addrV6->next; + ResolveStatsIPv6AddressFree(addrV6); + } + while ((negV6 = inHostname->negV6List) != NULL) + { + inHostname->negV6List = negV6->next; + ResolveStatsNegAAAASetFree(negV6); + } + free(inHostname); +} + +//=========================================================================================================================== +// ResolveStatsHostnameUpdate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID) +{ + mStatus err; + + if ((inResp->type == kResponseType_IPv4Addr) || (inResp->type == kResponseType_NegA)) + { + ResolveStatsIPv4AddrSet ** p; + ResolveStatsIPv4AddrSet * addrV4; + int i; + IPv4AddrCounter * counter; + + for (p = &inHostname->addrV4List; (addrV4 = *p) != NULL; p = &addrV4->next) + { + for (i = 0; i < (int)countof(addrV4->counters); ++i) + { + counter = &addrV4->counters[i]; + if (counter->count == 0) break; + if (counter->serverID != inServerID) continue; + if (inResp->type == kResponseType_NegA) + { + if (counter->isNegative) break; + } + else + { + if (memcmp(counter->addrBytes, inResp->data, 4) == 0) break; + } + } + if (i < (int)countof(addrV4->counters)) break; + } + if (!addrV4) + { + require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); + err = ResolveStatsIPv4AddrSetCreate(&addrV4); + require_noerr_quiet(err, exit); + gResolveStatsObjCount++; + + *p = addrV4; + counter = &addrV4->counters[0]; + } + if (counter->count == 0) + { + counter->serverID = inServerID; + if (inResp->type == kResponseType_NegA) + { + counter->isNegative = 1; + } + else + { + counter->isNegative = 0; + memcpy(counter->addrBytes, inResp->data, 4); + } + } + increment_saturate(counter->count, UINT16_MAX); + err = mStatus_NoError; + } + else if (inResp->type == kResponseType_IPv6Addr) + { + ResolveStatsIPv6Addr ** p; + ResolveStatsIPv6Addr * addrV6; + + for (p = &inHostname->addrV6List; (addrV6 = *p) != NULL; p = &addrV6->next) + { + if ((addrV6->serverID == inServerID) && (memcmp(addrV6->addrBytes, inResp->data, 16) == 0)) break; + } + if (!addrV6) + { + require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); + err = ResolveStatsIPv6AddressCreate(inServerID, inResp->data, &addrV6); + require_noerr_quiet(err, exit); + gResolveStatsObjCount++; + + *p = addrV6; + } + increment_saturate(addrV6->count, UINT16_MAX); + err = mStatus_NoError; + } + else if (inResp->type == kResponseType_NegAAAA) + { + ResolveStatsNegAAAASet ** p; + ResolveStatsNegAAAASet * negV6; + int i; + NegAAAACounter * counter; + + for (p = &inHostname->negV6List; (negV6 = *p) != NULL; p = &negV6->next) + { + for (i = 0; i < (int)countof(negV6->counters); ++i) + { + counter = &negV6->counters[i]; + if ((counter->count == 0) || (counter->serverID == inServerID)) break; + } + if (i < (int)countof(negV6->counters)) break; + } + if (!negV6) + { + require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); + err = ResolveStatsNegAAAASetCreate(&negV6); + require_noerr_quiet(err, exit); + gResolveStatsObjCount++; + + *p = negV6; + counter = &negV6->counters[0]; + } + if (counter->count == 0) counter->serverID = inServerID; + increment_saturate(counter->count, UINT16_MAX); + err = mStatus_NoError; + } + else + { + err = mStatus_Invalid; + } + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsHostnameCreateAWDVersion +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname) +{ + mStatus err; + AWDMDNSResponderResolveStatsHostname * hostname; + NSString * name; + char nameBuf[MAX_ESCAPED_DOMAIN_NAME]; + const char * ptr; + ResolveStatsIPv4AddrSet * addrV4; + ResolveStatsIPv6Addr * addrV6; + ResolveStatsNegAAAASet * negV6; + AWDMDNSResponderResolveStatsResult * result = nil; + int i; + + hostname = [[AWDMDNSResponderResolveStatsHostnameSoft alloc] init]; + require_action_quiet(hostname, exit, err = mStatus_UnknownErr); + + ptr = ConvertDomainNameToCString((domainname *)inHostname->name, nameBuf); + require_action_quiet(ptr, exit, err = mStatus_UnknownErr); + + name = [[NSString alloc] initWithUTF8String:nameBuf]; + require_action_quiet(name, exit, err = mStatus_UnknownErr); + + hostname.name = name; + [name release]; + name = nil; + + for (addrV4 = inHostname->addrV4List; addrV4; addrV4 = addrV4->next) + { + for (i = 0; i < (int)countof(addrV4->counters); ++i) + { + const IPv4AddrCounter * counter; + NSData * addrBytes; + + counter = &addrV4->counters[i]; + if (counter->count == 0) break; + + result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; + require_action_quiet(result, exit, err = mStatus_UnknownErr); + + if (counter->isNegative) + { + result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegA; + } + else + { + addrBytes = [[NSData alloc] initWithBytes:counter->addrBytes length:4]; + require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); + + result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv4Addr; + result.data = addrBytes; + [addrBytes release]; + } + result.count = counter->count; + result.serverID = counter->serverID; + + [hostname addResult:result]; + [result release]; + result = nil; + } + } + + for (addrV6 = inHostname->addrV6List; addrV6; addrV6 = addrV6->next) + { + NSData * addrBytes; + + result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; + require_action_quiet(result, exit, err = mStatus_UnknownErr); + + addrBytes = [[NSData alloc] initWithBytes:addrV6->addrBytes length:16]; + require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); + + result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv6Addr; + result.count = addrV6->count; + result.serverID = addrV6->serverID; + result.data = addrBytes; + + [addrBytes release]; + + [hostname addResult:result]; + [result release]; + result = nil; + } + + for (negV6 = inHostname->negV6List; negV6; negV6 = negV6->next) + { + for (i = 0; i < (int)countof(negV6->counters); ++i) + { + const NegAAAACounter * counter; + + counter = &negV6->counters[i]; + if (counter->count == 0) break; + + result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; + require_action_quiet(result, exit, err = mStatus_UnknownErr); + + result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegAAAA; + result.count = counter->count; + result.serverID = counter->serverID; + + [hostname addResult:result]; + [result release]; + result = nil; + } + } + + *outHostname = hostname; + hostname = nil; + err = mStatus_NoError; + +exit: + [result release]; + [hostname release]; + return (err); +} + +//=========================================================================================================================== +// ResolveStatsDNSServerCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer) +{ + mStatus err; + ResolveStatsDNSServer * obj; + size_t addrLen; + + require_action_quiet((inAddr->type == mDNSAddrType_IPv4) || (inAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid); + + addrLen = (inAddr->type == mDNSAddrType_IPv4) ? 4 : 16; + obj = (ResolveStatsDNSServer *)calloc(1, sizeof(*obj) - 1 + addrLen); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + obj->isForCell = inForCell; + if (inAddr->type == mDNSAddrType_IPv4) + { + obj->isAddrV6 = mDNSfalse; + memcpy(obj->addrBytes, inAddr->ip.v4.b, addrLen); + } + else + { + obj->isAddrV6 = mDNStrue; + memcpy(obj->addrBytes, inAddr->ip.v6.b, addrLen); + } + + *outServer = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsDNSServerFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer) +{ + free(inServer); +} + +//=========================================================================================================================== +// ResolveStatsDNSServerCreateAWDVersion +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer) +{ + mStatus err; + AWDMDNSResponderResolveStatsDNSServer * server; + NSData * addrBytes = nil; + + server = [[AWDMDNSResponderResolveStatsDNSServerSoft alloc] init]; + require_action_quiet(server, exit, err = mStatus_UnknownErr); + + addrBytes = [[NSData alloc] initWithBytes:inServer->addrBytes length:(inServer->isAddrV6 ? 16 : 4)]; + require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); + + server.serverID = inServer->id; + server.address = addrBytes; + if (inServer->isForCell) + { + server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_Cellular; + } + else + { + server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_NonCellular; + } + + *outServer = server; + server = nil; + err = mStatus_NoError; + +exit: + [addrBytes release]; + [server release]; + return (err); +} + +//=========================================================================================================================== +// ResolveStatsIPv4AddrSetCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet) +{ + mStatus err; + ResolveStatsIPv4AddrSet * obj; + + obj = (ResolveStatsIPv4AddrSet *)calloc(1, sizeof(*obj)); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + *outSet = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsIPv4AddrSetFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet) +{ + free(inSet); +} + +//=========================================================================================================================== +// ResolveStatsIPv6AddressCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr) +{ + mStatus err; + ResolveStatsIPv6Addr * obj; + + obj = (ResolveStatsIPv6Addr *)calloc(1, sizeof(*obj)); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + obj->serverID = inServerID; + memcpy(obj->addrBytes, inAddrBytes, 16); + + *outAddr = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsIPv6AddressFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr) +{ + free(inAddr); +} + +//=========================================================================================================================== +// ResolveStatsNegAAAASetCreate +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet) +{ + mStatus err; + ResolveStatsNegAAAASet * obj; + + obj = (ResolveStatsNegAAAASet *)calloc(1, sizeof(*obj)); + require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + + *outSet = obj; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// ResolveStatsNegAAAASetFree +//=========================================================================================================================== + +mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet) +{ + free(inSet); +} + +//=========================================================================================================================== +// ResolveStatsGetServerID +//=========================================================================================================================== + +mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID) +{ + mStatus err; + ResolveStatsDNSServer ** p; + ResolveStatsDNSServer * server; + + require_action_quiet((inServerAddr->type == mDNSAddrType_IPv4) || (inServerAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid); + + for (p = &gResolveStatsServerList; (server = *p) != NULL; p = &server->next) + { + if ((inForCell && server->isForCell) || (!inForCell && !server->isForCell)) + { + if (inServerAddr->type == mDNSAddrType_IPv4) + { + if (!server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v4.b, 4) == 0)) break; + } + else + { + if (server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v6.b, 16) == 0)) break; + } + } + } + + if (!server) + { + require_action_quiet(gResolveStatsNextServerID <= UINT8_MAX, exit, err = mStatus_Refused); + require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); + err = ResolveStatsDNSServerCreate(inServerAddr, inForCell, &server); + require_noerr_quiet(err, exit); + gResolveStatsObjCount++; + + server->id = gResolveStatsNextServerID++; + server->next = gResolveStatsServerList; + gResolveStatsServerList = server; + } + else if (gResolveStatsServerList != server) + { + *p = server->next; + server->next = gResolveStatsServerList; + gResolveStatsServerList = server; + } + + *outServerID = server->id; + err = mStatus_NoError; + +exit: + return (err); } //=========================================================================================================================== // CreateDomainStatsList //=========================================================================================================================== -mDNSlocal mStatus CreateDomainStatsList(DNSDomainStatsRef *outList) +mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList) { mStatus err; - size_t i; - DNSDomainStatsRef domainStats; - DNSDomainStatsRef * p; - DNSDomainStatsRef list = NULL; + int i; + DNSDomainStats * stats; + DNSDomainStats ** p; + DNSDomainStats * list = NULL; p = &list; - for (i = 0; i < countof(kUDNSStatsDomains); ++i) + for (i = 0; i < (int)countof(kQueryStatsDomains); ++i) { - err = DNSDomainStatsCreate(kUDNSStatsDomains[i], &domainStats); + err = DNSDomainStatsCreate(&kQueryStatsDomains[i], &stats); require_noerr_quiet(err, exit); - *p = domainStats; - p = &domainStats->next; + *p = stats; + p = &stats->next; } *outList = list; @@ -238,28 +1440,62 @@ exit: } //=========================================================================================================================== -// UpdateDNSStats +// CreateResolveStatsList //=========================================================================================================================== -mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs) +mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList) { - size_t i; + mStatus err; + int i; + ResolveStatsDomain * domain; + ResolveStatsDomain ** p; + ResolveStatsDomain * list = NULL; - if (inAnswered) + p = &list; + for (i = 0; i < (int)countof(kResolveStatsDomains); ++i) { - i = (inQuerySendCount <= kUDNSStatsMaxQuerySendCount) ? inQuerySendCount : kUDNSStatsMaxQuerySendCount; - inStats->answeredQuerySendCountBins[i]++; + err = ResolveStatsDomainCreate(&kResolveStatsDomains[i], &domain); + require_noerr_quiet(err, exit); - if (inQuerySendCount > 0) - { - for (i = 0; (i < countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {} - inStats->responseLatencyBins[i]++; - } + *p = domain; + p = &domain->next; } - else if (inQuerySendCount > 0) + + *outList = list; + list = NULL; + +exit: + FreeResolveStatsList(list); + return (err); +} + +//=========================================================================================================================== +// FreeResolveStatsList +//=========================================================================================================================== + +mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList) +{ + ResolveStatsDomain * domain; + + while ((domain = inList) != NULL) { - i = (inQuerySendCount <= kUDNSStatsMaxQuerySendCount) ? inQuerySendCount : kUDNSStatsMaxQuerySendCount; - inStats->unansweredQuerySendCountBins[i]++; + inList = domain->next; + ResolveStatsDomainFree(domain); + } +} + +//=========================================================================================================================== +// FreeResolveStatsServerList +//=========================================================================================================================== + +mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList) +{ + ResolveStatsDNSServer * server; + + while ((server = inList) != NULL) + { + inList = server->next; + ResolveStatsDNSServerFree(server); } } @@ -267,16 +1503,51 @@ mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 in // SubmitAWDMetric //=========================================================================================================================== -mDNSlocal mStatus SubmitAWDMetric(void) +mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID) +{ + mStatus err = mStatus_NoError; + + switch (inMetricID) + { + case AWDMetricId_MDNSResponder_DNSStatistics: + err = SubmitAWDMetricQueryStats(); + break; + + case AWDMetricId_MDNSResponder_ResolveStats: + err = SubmitAWDMetricResolveStats(); + break; + + case AWDMetricId_MDNSResponder_ServicesStats: + [AWDMetricManagerSoft postMetricWithId:AWDMetricId_MDNSResponder_ServicesStats integerValue:max_num_regservices]; + KQueueLock(&mDNSStorage); + // reset the no of max services since we want to collect the max no of services registered per AWD submission period + max_num_regservices = curr_num_regservices; + KQueueUnlock(&mDNSStorage, "SubmitAWDSimpleMetricServiceStats"); + break; + + default: + err = mStatus_UnsupportedErr; + break; + } + + if (err) + LogMsg("SubmitAWDMetric for metric ID 0x%08X failed with error %d", inMetricID, err); + return (err); +} + +//=========================================================================================================================== +// SubmitAWDMetricQueryStats +//=========================================================================================================================== + +mDNSlocal mStatus SubmitAWDMetricQueryStats(void) { mStatus err; BOOL success; - DNSDomainStatsRef domainStats; - DNSDomainStatsRef newDomainStatsList; - DNSDomainStatsRef domainStatsList = NULL; + DNSDomainStats * stats; + DNSDomainStats * newDomainStatsList; + DNSDomainStats * domainStatsList = NULL; AWDMetricContainer * container = nil; AWDMDNSResponderDNSStatistics * metric = nil; - AWDDNSDomainStats * awdDomainStats = nil; err = CreateDomainStatsList(&newDomainStatsList); require_noerr_quiet(err, exit); @@ -285,7 +1556,7 @@ mDNSlocal mStatus SubmitAWDMetric(void) KQueueLock(&mDNSStorage); gDomainStatsList = newDomainStatsList; - KQueueUnlock(&mDNSStorage, "SubmitAWDMetric"); + KQueueUnlock(&mDNSStorage, "SubmitAWDMetricQueryStats"); container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSStatistics]; require_action_quiet(container, exit, err = mStatus_UnknownErr); @@ -293,30 +1564,28 @@ mDNSlocal mStatus SubmitAWDMetric(void) metric = [[AWDMDNSResponderDNSStatisticsSoft alloc] init]; require_action_quiet(metric, exit, err = mStatus_UnknownErr); - for (domainStats = domainStatsList; domainStats; domainStats = domainStats->next) + while ((stats = domainStatsList) != NULL) { - err = CreateAWDDNSDomainStats(&domainStats->stats, domainStats->domainStr, mDNSfalse, &awdDomainStats); - require_noerr_quiet(err, exit); - - [metric addStats:awdDomainStats]; - [awdDomainStats release]; - awdDomainStats = nil; - - err = CreateAWDDNSDomainStats(&domainStats->statsCellular, domainStats->domainStr, mDNStrue, &awdDomainStats); - require_noerr_quiet(err, exit); - - [metric addStats:awdDomainStats]; - [awdDomainStats release]; - awdDomainStats = nil; + if (stats->nonCellular) + { + err = AddAWDDNSDomainStats(metric, stats->nonCellular, stats->domain->cstr, mDNSfalse); + require_noerr_quiet(err, exit); + } + if (stats->cellular) + { + err = AddAWDDNSDomainStats(metric, stats->cellular, stats->domain->cstr, mDNStrue); + require_noerr_quiet(err, exit); + } + domainStatsList = stats->next; + DNSDomainStatsFree(stats); } container.metric = metric; success = [gAWDServerConnection submitMetric:container]; - LogMsg("SubmitAWDMetric: metric submission %s.", success ? "succeeded" : "failed" ); + LogMsg("SubmitAWDMetricQueryStats: metric submission %s.", success ? "succeeded" : "failed" ); err = success ? mStatus_NoError : mStatus_UnknownErr; exit: - [awdDomainStats release]; [metric release]; [container release]; DNSDomainStatsFreeList(domainStatsList); @@ -324,73 +1593,94 @@ exit: } //=========================================================================================================================== -// DNSDomainStatsCreate +// SubmitAWDMetricResolveStats //=========================================================================================================================== -mDNSlocal mStatus DNSDomainStatsCreate(const char *inDomain, DNSDomainStatsRef *outStats) +mDNSlocal mStatus SubmitAWDMetricResolveStats(void) { - mStatus err; - DNSDomainStatsRef obj; - mDNSu8 * ptr; + mStatus err; + ResolveStatsDomain * newResolveStatsList; + ResolveStatsDomain * domainList = NULL; + ResolveStatsDNSServer * serverList = NULL; + AWDMetricContainer * container = nil; + AWDMDNSResponderResolveStats * metric = nil; + ResolveStatsDNSServer * server; + ResolveStatsDomain * domain; + BOOL success; - obj = (DNSDomainStatsRef) calloc(1, sizeof(*obj)); - require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + err = CreateResolveStatsList(&newResolveStatsList); + require_noerr_quiet(err, exit); - obj->domainStr = strdup(inDomain); - require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); + domainList = gResolveStatsList; + serverList = gResolveStatsServerList; - // Initialize domainname for non-root domains. + KQueueLock(&mDNSStorage); + gResolveStatsList = newResolveStatsList; + gResolveStatsServerList = NULL; + gResolveStatsNextServerID = 0; + gResolveStatsObjCount = 0; + KQueueUnlock(&mDNSStorage, "SubmitAWDMetricResolveStats"); - if (strcmp(obj->domainStr, ".") != 0) - { - ptr = MakeDomainNameFromDNSNameString(&obj->domain, obj->domainStr); - require_action_quiet(ptr, exit, err = mStatus_Invalid); - obj->domainLabelCount = CountLabels(&obj->domain); - } + container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_ResolveStats]; + require_action_quiet(container, exit, err = mStatus_UnknownErr); - *outStats = obj; - obj = NULL; - err = mStatus_NoError; + metric = [[AWDMDNSResponderResolveStatsSoft alloc] init]; + require_action_quiet(metric, exit, err = mStatus_UnknownErr); -exit: - if (obj) DNSDomainStatsFree(obj); - return (err); -} + while ((server = serverList) != NULL) + { + AWDMDNSResponderResolveStatsDNSServer * awdServer; -//=========================================================================================================================== -// DNSDomainStatsFree -//=========================================================================================================================== + serverList = server->next; + err = ResolveStatsDNSServerCreateAWDVersion(server, &awdServer); + ResolveStatsDNSServerFree(server); + require_noerr_quiet(err, exit); -mDNSlocal void DNSDomainStatsFree(DNSDomainStatsRef inStats) -{ - if (inStats->domainStr) free(inStats->domainStr); - free(inStats); -} + [metric addServer:awdServer]; + [awdServer release]; + } -//=========================================================================================================================== -// DNSDomainStatsFreeList -//=========================================================================================================================== + while ((domain = domainList) != NULL) + { + AWDMDNSResponderResolveStatsDomain * awdDomain; -mDNSlocal void DNSDomainStatsFreeList(DNSDomainStatsRef inList) -{ - DNSDomainStatsRef stats; + domainList = domain->next; + err = ResolveStatsDomainCreateAWDVersion(domain, &awdDomain); + ResolveStatsDomainFree(domain); + require_noerr_quiet(err, exit); - while ((stats = inList) != NULL) - { - inList = stats->next; - DNSDomainStatsFree(stats); + [metric addDomain:awdDomain]; + [awdDomain release]; } + + container.metric = metric; + success = [gAWDServerConnection submitMetric:container]; + LogMsg("SubmitAWDMetricResolveStats: metric submission %s.", success ? "succeeded" : "failed" ); + err = success ? mStatus_NoError : mStatus_UnknownErr; + +exit: + [metric release]; + [container release]; + FreeResolveStatsList(domainList); + FreeResolveStatsServerList(serverList); + return (err); } //=========================================================================================================================== // CreateAWDDNSDomainStats //=========================================================================================================================== -mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomain, mDNSBool inIsCellType, AWDDNSDomainStats **outAWDStats) +mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats) { mStatus err; AWDDNSDomainStats * awdStats = nil; NSString * domain = nil; + uint32_t sendCountBins[kQueryStatsSendCountBinCount]; + uint32_t latencyBins[kQueryStatsLatencyBinCount]; + int i; + unsigned int totalAnswered; + unsigned int totalNegAnswered; + unsigned int totalUnanswered; awdStats = [[AWDDNSDomainStatsSoft alloc] init]; require_action_quiet(awdStats, exit, err = mStatus_UnknownErr); @@ -398,22 +1688,62 @@ mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomai domain = [[NSString alloc] initWithUTF8String:inDomain]; require_action_quiet(domain, exit, err = mStatus_UnknownErr); - awdStats.domain = domain; - awdStats.networkType = inIsCellType ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular; + awdStats.domain = domain; + awdStats.networkType = inForCell ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular; + awdStats.recordType = inType; + + totalAnswered = 0; + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + sendCountBins[i] = inHist->answeredQuerySendCountBins[i]; + totalAnswered += inHist->answeredQuerySendCountBins[i]; + } + [awdStats setAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; - [awdStats - setAnsweredQuerySendCounts: inStats->answeredQuerySendCountBins - count: (NSUInteger)countof(inStats->answeredQuerySendCountBins)]; + totalNegAnswered = 0; + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + sendCountBins[i] = inHist->negAnsweredQuerySendCountBins[i]; + totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i]; + } + [awdStats setNegAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; - [awdStats - setUnansweredQuerySendCounts: inStats->unansweredQuerySendCountBins - count: (NSUInteger)countof(inStats->unansweredQuerySendCountBins)]; + totalUnanswered = 0; + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + sendCountBins[i] = inHist->unansweredQuerySendCountBins[i]; + totalUnanswered += inHist->unansweredQuerySendCountBins[i]; + } + [awdStats setUnansweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; - [awdStats - setResponseLatencyMs: inStats->responseLatencyBins - count: (NSUInteger)countof(inStats->responseLatencyBins)]; + if (totalAnswered > inHist->answeredQuerySendCountBins[0]) + { + for (i = 0; i < kQueryStatsLatencyBinCount; ++i) + { + latencyBins[i] = inHist->responseLatencyBins[i]; + } + [awdStats setResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; + } + + if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0]) + { + for (i = 0; i < kQueryStatsLatencyBinCount; ++i) + { + latencyBins[i] = inHist->negResponseLatencyBins[i]; + } + [awdStats setNegResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; + } + + if (totalUnanswered > 0) + { + for (i = 0; i < kQueryStatsLatencyBinCount; ++i) + { + latencyBins[i] = inHist->unansweredQueryDurationBins[i]; + } + [awdStats setUnansweredQueryDurationMs:latencyBins count:kQueryStatsLatencyBinCount]; + } - *outAWDStats = awdStats; + *outStats = awdStats; awdStats = nil; err = mStatus_NoError; @@ -424,7 +1754,57 @@ exit: } //=========================================================================================================================== -// LogDNSStats +// AddAWDDNSDomainStats +//=========================================================================================================================== + +mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) +{ + mStatus err; + AWDDNSDomainStats * awdStats; + + if (inSet->histAny) + { + err = CreateAWDDNSDomainStats(inSet->histAny, inDomain, inForCell, AWDDNSDomainStats_RecordType_Any, &awdStats); + require_noerr_quiet(err, exit); + + [inMetric addStats:awdStats]; + [awdStats release]; + } + if (inSet->histA) + { + err = CreateAWDDNSDomainStats(inSet->histA, inDomain, inForCell, AWDDNSDomainStats_RecordType_A, &awdStats); + require_noerr_quiet(err, exit); + + [inMetric addStats:awdStats]; + [awdStats release]; + } + if (inSet->histAAAA) + { + err = CreateAWDDNSDomainStats(inSet->histAAAA, inDomain, inForCell, AWDDNSDomainStats_RecordType_AAAA, &awdStats); + require_noerr_quiet(err, exit); + + [inMetric addStats:awdStats]; + [awdStats release]; + } + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// LogDNSHistSet +//=========================================================================================================================== + +mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) +{ + if (inSet->histAny) LogDNSHist(inSet->histAny, inDomain, inForCell, "Any"); + if (inSet->histA) LogDNSHist(inSet->histA, inDomain, inForCell, "A"); + if (inSet->histAAAA) LogDNSHist(inSet->histAAAA, inDomain, inForCell, "AAAA"); +} + +//=========================================================================================================================== +// LogDNSHist //=========================================================================================================================== #define Percent(N, D) ((N) * 100) / (D), (((N) * 10000) / (D)) % 100 @@ -432,67 +1812,124 @@ exit: #define LogStat(LABEL, COUNT, ACCUMULATOR, TOTAL) \ LogMsgNoIdent("%s %5u " PercentFmt " " PercentFmt, (LABEL), (COUNT), Percent(COUNT, TOTAL), Percent(ACCUMULATOR, TOTAL)) -mDNSlocal void LogDNSStats(const DNSStats *inStats) +mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType) { - uint32_t total; - uint32_t totalUnanswered; - size_t i; - char label[16]; + unsigned int totalAnswered; + unsigned int totalNegAnswered; + unsigned int totalUnanswered; + int i; + + totalAnswered = 0; + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + totalAnswered += inHist->answeredQuerySendCountBins[i]; + } + + totalNegAnswered = 0; + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i]; + } totalUnanswered = 0; - for (i = 0; i < countof(inStats->unansweredQuerySendCountBins); ++i) + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) + { + totalUnanswered += inHist->unansweredQuerySendCountBins[i]; + } + + LogMsgNoIdent("Domain: %s (%s, %s)", inDomain, inForCell ? "C" : "NC", inType); + LogMsgNoIdent("Answered questions %4u", totalAnswered); + LogMsgNoIdent("Negatively answered questions %4u", totalNegAnswered); + LogMsgNoIdent("Unanswered questions %4u", totalUnanswered); + LogMsgNoIdent("-- Query send counts ---------"); + LogDNSHistSendCounts(inHist->answeredQuerySendCountBins); + LogMsgNoIdent("-- Query send counts (NAQs) --"); + LogDNSHistSendCounts(inHist->negAnsweredQuerySendCountBins); + + if (totalAnswered > inHist->answeredQuerySendCountBins[0]) + { + LogMsgNoIdent("--- Response times -----------"); + LogDNSHistLatencies(inHist->responseLatencyBins); + } + + if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0]) { - totalUnanswered += inStats->unansweredQuerySendCountBins[i]; + LogMsgNoIdent("--- Response times (NAQs) ----"); + LogDNSHistLatencies(inHist->negResponseLatencyBins); } + if (totalUnanswered > 0) + { + LogMsgNoIdent("--- Unanswered query times ---"); + LogDNSHistLatencies(inHist->unansweredQueryDurationBins); + } +} + +//=========================================================================================================================== +// LogDNSHistSendCounts +//=========================================================================================================================== + +mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]) +{ + uint32_t total; + char label[16]; + int i; + total = 0; - for (i = 0; i <= countof(inStats->answeredQuerySendCountBins); ++i) + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) { - total += inStats->answeredQuerySendCountBins[i]; + total += inSendCountBins[i]; } - LogMsgNoIdent("Answered questions %5u", total); - LogMsgNoIdent("Unanswered questions %5u", totalUnanswered); - LogMsgNoIdent("+++ Number of queries sent +++"); if (total > 0) { uint32_t accumulator = 0; - for (i = 0; i < countof(inStats->answeredQuerySendCountBins); ++i) + for (i = 0; i < kQueryStatsSendCountBinCount; ++i) { - uint32_t count; - const char * suffix; - - count = inStats->answeredQuerySendCountBins[i]; - accumulator += count; - suffix = (i < (countof(inStats->answeredQuerySendCountBins) - 1)) ? " " : "+"; - snprintf(label, sizeof(label), "%2d%s", (int)i, suffix); - LogStat(label, count, accumulator, total); + accumulator += inSendCountBins[i]; + if (i < (kQueryStatsSendCountBinCount - 1)) + { + snprintf(label, sizeof(label), "%2d ", i); + } + else + { + snprintf(label, sizeof(label), "%2d+", i); + } + LogStat(label, inSendCountBins[i], accumulator, total); + if (accumulator == total) break; } } else { LogMsgNoIdent("No data."); } +} + +//=========================================================================================================================== +// LogDNSHistLatencies +//=========================================================================================================================== + +mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]) +{ + uint32_t total; + int i; + char label[16]; total = 0; - for (i = 0; i < countof(inStats->responseLatencyBins); ++i) + for (i = 0; i < kQueryStatsLatencyBinCount; ++i) { - total += inStats->responseLatencyBins[i]; + total += inLatencyBins[i]; } - LogMsgNoIdent("+++++++ Response times +++++++"); if (total > 0) { uint32_t accumulator = 0; - for (i = 0; i < countof(inStats->responseLatencyBins); ++i) + for (i = 0; i < kQueryStatsLatencyBinCount; ++i) { - uint32_t count; - - count = inStats->responseLatencyBins[i]; - accumulator += count; - if (i < countof(kResponseLatencyMsLimits)) + accumulator += inLatencyBins[i]; + if (i < (int)countof(kResponseLatencyMsLimits)) { snprintf(label, sizeof(label), "< %5u ms", kResponseLatencyMsLimits[i]); } @@ -500,7 +1937,7 @@ mDNSlocal void LogDNSStats(const DNSStats *inStats) { snprintf(label, sizeof(label), "< ∞ ms"); } - LogStat(label, count, accumulator, total); + LogStat(label, inLatencyBins[i], accumulator, total); if (accumulator == total) break; } } @@ -511,21 +1948,63 @@ mDNSlocal void LogDNSStats(const DNSStats *inStats) } //=========================================================================================================================== -// LogMetrics +// ValidateDNSStatsDomains //=========================================================================================================================== -mDNSexport void LogMetrics(void) +#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) +#warning "Do not include ValidateDNSStatsDomains() in customer release!" +mDNSlocal void ValidateDNSStatsDomains(void) { - DNSDomainStatsRef domainStats; + int i; + const Domain * domain; + mDNSu8 * ptr; + domainname domainNameExpected; + int labelCountExpected; + mDNSBool domainNamesEqual; + mDNSBool failed = mDNSfalse; + + for (i = 0; i < countof(kQueryStatsDomains); ++i) + { + domain = &kQueryStatsDomains[i]; - LogMsgNoIdent("---- DNS stats by domain -----"); + if (strcmp(domain->cstr, ".") == 0) + { + domainNameExpected.c[0] = 0; + } + else + { + ptr = MakeDomainNameFromDNSNameString(&domainNameExpected, domain->cstr); + if (!ptr) + { + LogMsg("ValidateDNSStatsDomains: Failed to make domain name for \"%s\".", domain->cstr); + failed = mDNStrue; + goto exit; + } + } - for (domainStats = gDomainStatsList; domainStats; domainStats = domainStats->next) - { - LogMsgNoIdent("Domain: %s (non-cellular)", domainStats->domainStr); - LogDNSStats(&domainStats->stats); - LogMsgNoIdent("Domain: %s (cellular)", domainStats->domainStr); - LogDNSStats(&domainStats->statsCellular); + domainNamesEqual = SameDomainName(domain->name, &domainNameExpected); + labelCountExpected = CountLabels(&domainNameExpected); + if (domainNamesEqual && (domain->labelCount == labelCountExpected)) + { + LogMsg("ValidateDNSStatsDomains: \"%s\" passed.", domain->cstr); + } + else + { + if (!domainNamesEqual) + { + LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect domain name.", domain->cstr); + } + if (domain->labelCount != labelCountExpected) + { + LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect label count. Actual %d, expected %d.", + domain->cstr, domain->labelCount, labelCountExpected); + } + failed = mDNStrue; + } } + +exit: + if (failed) abort(); } +#endif #endif // TARGET_OS_EMBEDDED diff --git a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c index 0665103f..59a5cf4a 100644 --- a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c +++ b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c @@ -228,7 +228,9 @@ static void initPortRule( struct pfioc_rule * pr, int P2PPacketFilterAddBonjourRuleSet(const char * interfaceName, u_int32_t count, pfArray_t portArray, pfArray_t protocolArray ) { int result; - u_int32_t i, ticket, poolTicket; + u_int32_t i; + u_int32_t ticket = 0; + u_int32_t poolTicket = 0; int devFD = -1; char * anchorPath = MDNS_ANCHOR_PATH; @@ -278,7 +280,7 @@ int P2PPacketFilterClearBonjourRules() { int result; int pfDev = -1; - u_int32_t ticket; + u_int32_t ticket = 0; char * anchorPath = MDNS_ANCHOR_PATH; result = openPFDevice( &pfDev ); diff --git a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h index 904b43ba..23e5410b 100644 --- a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h +++ b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h @@ -20,7 +20,8 @@ #include "helpermsg-types.h" -enum { +enum +{ PF_SET_RULES, PF_CLEAR_RULES }; diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c index a2ab5464..43da5025 100644 --- a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c +++ b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c @@ -112,7 +112,7 @@ OSStatus InitConfigAuthority(void) CFSTR("Describes operation that requires user authorization")); require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); dict = CreateRightsDict(rightInfo); - require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo)); err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL, (CFBundleRef) NULL, (CFStringRef) NULL); @@ -128,7 +128,7 @@ OSStatus InitConfigAuthority(void) CFSTR("Describes operation that requires user authorization")); require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); dict = CreateRightsDict( rightInfo); - require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo)); err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL, (CFBundleRef) NULL, (CFStringRef) NULL); diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m index 26e3eaf0..ba5f64bf 100644 --- a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m +++ b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m @@ -333,8 +333,8 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query) currentHostName = [[NSString alloc] initWithString:@""]; } - CFRelease((CFDictionaryRef)origDict); - CFRelease(store); + if (origDict) CFRelease((CFDictionaryRef)origDict); + if (store) CFRelease(store); } diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c index efb41497..a279c983 100644 --- a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c +++ b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c @@ -75,7 +75,7 @@ OSStatus EnsureToolInstalled(void) { CFURLRef bundleURL; pid_t toolPID; - int status; + int status = 0; OSStatus err = noErr; const char *args[] = { kToolPath, "0", "V", NULL }; char toolSourcePath[PATH_MAX] = {}; @@ -98,8 +98,10 @@ OSStatus EnsureToolInstalled(void) if (bundleURL != NULL) { CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolSourcePath, sizeof toolSourcePath); - if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1); CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolInstallerPath, sizeof toolInstallerPath); + CFRelease(bundleURL); + + if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1); if (strlcat(toolInstallerPath, "/Contents/Resources/" kToolInstaller, sizeof toolInstallerPath) >= sizeof toolInstallerPath) return(-1); } else @@ -164,7 +166,7 @@ static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData) } commFD = fileno(tmpfile()); - sprintf(fileNum, "%d", commFD); + snprintf(fileNum, sizeof(fileNum), "%d", commFD); args[1] = fileNum; args[3] = subCmd; @@ -185,7 +187,7 @@ static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData) child = execTool(args); if (child > 0) { - int status; + int status = 0; waitpid(child, &status, 0); if (WIFEXITED(status)) err = WEXITSTATUS(status); diff --git a/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist b/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist new file mode 100644 index 00000000..6d403b52 --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DEFAULT-OPTIONS</key> + <dict> + <key>Default-Privacy-Setting</key> + <string>Public</string> + <key>Level</key> + <dict> + <key>Persist</key> + <string>Inherit</string> + <key>Enable</key> + <string>Inherit</string> + </dict> + </dict> +</dict> +</plist> + diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h b/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h index e0b65cce..f3b480ea 100644 --- a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h +++ b/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h @@ -1,5 +1,5 @@ /* -*- Mode: C; tab-width: 4 -*- - * + * * Copyright (c) 2015 Apple Inc. All rights reserved. */ @@ -29,4 +29,29 @@ */ DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid); +// Map the source port of the local UDP socket that was opened for sending the DNS query +// to the process ID of the application that triggered the DNS resolution. +// +/* DNSServiceGetPID() Parameters: + * + * srcport: Source port (in network byte order) of the UDP socket that was created by + * the daemon to send the DNS query on the wire. + * + * pid: Process ID of the application that started the name resolution which triggered + * the daemon to send the query on the wire. The value can be -1 if the srcport + * cannot be mapped. + * + * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning + * if the daemon is not running. The value of the pid is undefined if the return + * value has error. + */ +DNSServiceErrorType DNSSD_API DNSServiceGetPID +( + uint16_t srcport, + int32_t *pid +); + +#define kDNSServiceCompPrivateDNS "PrivateDNS" +#define kDNSServiceCompMulticastDNS "MulticastDNS" + #endif diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.c b/mDNSResponder/mDNSMacOSX/Private/dns_services.c index 794e2526..46e2a23a 100644 --- a/mDNSResponder/mDNSMacOSX/Private/dns_services.c +++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.c @@ -10,9 +10,7 @@ #include "dns_xpc.h" #include <xpc/xpc.h> #include <Block.h> -#include <syslog.h> - -#define LOG_NOW LOG_INFO +#include <os/log.h> //************************************************************************************************************* // Globals @@ -41,7 +39,7 @@ static void LogDebug(const char *prefix, xpc_object_t o) return; char *desc = xpc_copy_description(o); - syslog(LOG_NOW, "%s: %s", prefix, desc); + os_log_info(OS_LOG_DEFAULT, "%s: %s", prefix, desc); free(desc); } @@ -51,7 +49,7 @@ void DNSXRefDeAlloc(DNSXConnRef connRef) { if (connRef == NULL) { - syslog(LOG_WARNING, "dns_services DD: DNSXRefDeAlloc called with NULL DNSXConnRef"); + os_log(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef"); return; } @@ -63,18 +61,18 @@ void DNSXRefDeAlloc(DNSXConnRef connRef) dispatch_release(connRef->lib_q); connRef->lib_q = NULL; connRef->AppCallBack = NULL; - syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q"); + os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q"); dispatch_async((connRef)->client_q, ^{ dispatch_release(connRef->client_q); connRef->client_q = NULL; free(connRef); - syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef"); + os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef"); }); }); // DO NOT reference connRef after this comment, as it may have been freed - syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated connRef"); + os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef"); } @@ -83,7 +81,7 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg) { DNSXErrorType errx = kDNSX_NoError; - LogDebug("dns_services DD: SendMsgToServer Sending msg to Daemon", msg); + LogDebug("dns_services: SendMsgToServer Sending msg to Daemon", msg); xpc_connection_send_message_with_reply((connRef)->conn_ref, msg, (connRef)->lib_q, ^(xpc_object_t recv_msg) { @@ -91,13 +89,13 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg) if (type == XPC_TYPE_DICTIONARY) { - LogDebug("dns_services DD: SendMsgToServer Received reply msg from Daemon", recv_msg); + LogDebug("dns_services: SendMsgToServer Received reply msg from Daemon", recv_msg); uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply); if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL) { // If connRef is bad, do not schedule any callbacks to the client - syslog(LOG_WARNING, "dns_services DD: SendMsgToServer: connRef is BAD Daemon status code [%llu]", daemon_status); + os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: connRef is BAD Daemon status code [%llu]", daemon_status); } else { @@ -110,14 +108,16 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg) }); break; - case kDNSMsg_BadArg: + case kDNSMsg_Busy: + os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: DNS Proxy already in use"); dispatch_async((connRef)->client_q, ^{ if (connRef->AppCallBack != NULL) - ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_BadParam); + ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_Busy); }); break; default: + os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: Unknown error"); dispatch_async((connRef)->client_q, ^{ if (connRef->AppCallBack != NULL) ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_UnknownErr); @@ -128,9 +128,9 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg) } else { - syslog(LOG_WARNING, "dns_services DD: SendMsgToServer Received unexpected reply from daemon [%s]", + os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer Received unexpected reply from daemon [%s]", xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION)); - LogDebug("dns_services DD: SendMsgToServer Unexpected Reply contents", recv_msg); + LogDebug("dns_services: SendMsgToServer Unexpected Reply contents", recv_msg); } }); @@ -141,13 +141,16 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg) static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servname, dispatch_queue_t clientq, void *AppCallBack) { if (connRefOut == NULL) + { + os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() connRef cannot be NULL"); return kDNSX_BadParam; + } // Use a DNSXConnRef on the stack to be captured in the blocks below, rather than capturing the DNSXConnRef* owned by the client DNSXConnRef connRef = malloc(sizeof(struct _DNSXConnRef_t)); if (connRef == NULL) { - syslog(LOG_WARNING, "dns_services DD: InitConnection() No memory to allocate!"); + os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() No memory to allocate!"); return kDNSX_NoMem; } @@ -160,7 +163,7 @@ static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servnam if (connRef->conn_ref == NULL || connRef->lib_q == NULL) { - syslog(LOG_WARNING, "dns_services DD: InitConnection() conn_ref/lib_q is NULL"); + os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() conn_ref/lib_q is NULL"); if (connRef != NULL) free(connRef); return kDNSX_NoMem; @@ -171,12 +174,12 @@ static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servnam if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL) { // If connRef is bad, do not schedule any callbacks to the client - syslog(LOG_WARNING, "dns_services DD: InitConnection: connRef is BAD Unexpected Connection Error [%s]", + os_log(OS_LOG_DEFAULT, "dns_services: InitConnection: connRef is BAD Unexpected Connection Error [%s]", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); } else { - syslog(LOG_WARNING, "dns_services DD: InitConnection: Unexpected Connection Error [%s] Ping the client", + os_log(OS_LOG_DEFAULT, "dns_services: InitConnection: Unexpected Connection Error [%s] Ping the client", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); dispatch_async(connRef->client_q, ^{ if (connRef->AppCallBack != NULL) @@ -201,7 +204,7 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara // Sanity Checks if (connRef == NULL || callBack == NULL || clientq == NULL) { - syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter"); + os_log(OS_LOG_DEFAULT, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter"); return kDNSX_BadParam; } @@ -211,13 +214,13 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara errx = InitConnection(connRef, kDNSProxyService, clientq, callBack); if (errx) // On error InitConnection() leaves *connRef set to NULL { - syslog(LOG_WARNING, "dns_services DD: Since InitConnection() returned %d error returning w/o sending msg", errx); + os_log(OS_LOG_DEFAULT, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx); return errx; } } else // Client already has a connRef and this is not valid use for this SPI { - syslog(LOG_WARNING, "dns_services DD: Client already has a valid connRef! This is incorrect usage from the client"); + os_log(OS_LOG_DEFAULT, "dns_services: Client already has a valid connRef! This is incorrect usage from the client"); return kDNSX_BadParam; } @@ -225,7 +228,7 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); if (dict == NULL) { - syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy could not create the Msg Dict To Send!"); + os_log(OS_LOG_DEFAULT, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!"); DNSXRefDeAlloc(*connRef); return kDNSX_NoMem; } diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.h b/mDNSResponder/mDNSMacOSX/Private/dns_services.h index 25b911f1..34c68756 100644 --- a/mDNSResponder/mDNSMacOSX/Private/dns_services.h +++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.h @@ -22,7 +22,8 @@ typedef enum kDNSX_NoError = 0, kDNSX_UnknownErr = -65537, /* 0xFFFE FFFF */ kDNSX_NoMem = -65539, /* No Memory */ - kDNSX_BadParam = -65540, /* Client passes invalid arg/Bad use of SPI */ + kDNSX_BadParam = -65540, /* Client passed invalid arg */ + kDNSX_Busy = -65551, /* DNS Proxy already in use: incorrect use of SPI by client */ kDNSX_DaemonNotRunning = -65563 /* Daemon not running */ } DNSXErrorType; diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h b/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h index 4c961a84..bda2bf92 100644 --- a/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h +++ b/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h @@ -11,6 +11,7 @@ #define DNS_XPC_H #define kDNSProxyService "com.apple.mDNSResponder.dnsproxy" +#define kDNSCTLService "com.apple.mDNSResponder.dnsctl" #define kDNSProxyParameters "DNSProxyParameters" @@ -27,7 +28,34 @@ typedef enum { kDNSMsg_NoError = 0, - kDNSMsg_BadArg + kDNSMsg_Busy } DaemonReplyStatusCodes; +#define kDNSLogLevel "DNSLoggingVerbosity" + +typedef enum +{ + log_level1 = 1, // logging off + log_level2, // logging USR1 + log_level3, // logging USR2 + log_level4, // logging USR1/2 +} DNSLogLevels; + +#define kDNSStateInfo "DNSStateInfoLevels" + +typedef enum +{ + full_state = 1, // full state info of mDNSResponder (INFO) +} DNSStateInfo; + +#define kmDNSResponderTests "mDNSResponderTests" + +typedef enum +{ + test_helper_ipc = 1, // invokes mDNSResponder to send a test msg to mDNSResponderHelper + test_mDNS_log, // invokes mDNSResponder to log using different internal macros +} mDNSTestModes; + + + #endif // DNS_XPC_H diff --git a/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c new file mode 100644 index 00000000..9b3885e6 --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c @@ -0,0 +1,224 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015 Apple Inc. All rights reserved. + * + * dnsctl_server.c + * mDNSResponder + * + * XPC as an IPC mechanism to communicate with dnsctl. Open only to Apple OSX/iOS clients + */ + +#include "xpc_services.h" +#include "dns_xpc.h" + +#include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock +#include "helper.h" // mDNSResponderHelper tests +#include <xpc/xpc.h> + +// *************************************************************************** +// Globals +extern mDNS mDNSStorage; +static dispatch_queue_t dnsctlserver_queue = NULL; +// *************************************************************************** + +mDNSlocal void handle_logging(mDNSu32 log_level) +{ + KQueueLock(&mDNSStorage); + + switch (log_level) + { + case log_level1: + mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0; + LogMsg("USR1 Logging:[%s] USR2 Logging:[%s]", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level2: + mDNS_LoggingEnabled = 1; + LogMsg("USR1 Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level3: + mDNS_PacketLoggingEnabled = 1; + LogMsg("USR2 Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level4: + mDNS_LoggingEnabled = 1 ; + mDNS_PacketLoggingEnabled = 1; + LogMsg("USR1 Logging:%s USR2 Logging:%s", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + default: + mDNS_LoggingEnabled = 0 ; + mDNS_PacketLoggingEnabled = 0; + break; + } + UpdateDebugState(); + + KQueueUnlock(&mDNSStorage, "LogLevel changed"); +} + +mDNSlocal void handle_stateinfo(mDNSu32 state_level) +{ + KQueueLock(&mDNSStorage); + + switch (state_level) + { + case full_state: + INFOCallback(); + break; + + default: + INFOCallback(); + break; + } + + KQueueUnlock(&mDNSStorage, "StateInfo dumped"); +} + + +mDNSlocal void handle_test_mode(mDNSu32 test_mode) +{ + KQueueLock(&mDNSStorage); + + switch (test_mode) + { + case test_helper_ipc: + mDNSNotify("mDNSResponderHelperTest", "This is just a test message to mDNSResponderHelper. This is NOT an actual alert"); + break; + + case test_mDNS_log: + LogInfo("LogInfo: Should be logged at INFO level"); + LogOperation("LogOperation: Should be logged at INFO level"); + LogMsg("LogMsg: Should be logged at DEFAULT level"); + LogSPS("LogSPS: Should be logged at INFO level"); + break; + + default: + LogMsg("Unidentified Test mode: Please add this test"); + break; + } + + KQueueUnlock(&mDNSStorage, "Test Msg to mDNSResponderHelper"); +} + +mDNSlocal void handle_terminate() +{ + + LogInfo("handle_terminate: Client terminated connection."); + +} + +mDNSlocal void handle_requests(xpc_object_t req) +{ + mDNSu32 log_level, state_level, test_mode; + xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req); + + LogInfo("handle_requests: Handler for dnsctl requests"); + + xpc_object_t response = xpc_dictionary_create_reply(req); + + // Return Success Status to the client (essentially ACKing the request) + if (response) + { + xpc_dictionary_set_uint64(response, kDNSDaemonReply, kDNSMsg_NoError); + xpc_connection_send_message(remote_conn, response); + xpc_release(response); + } + else + { + LogMsg("handle_requests: Response Dictionary could not be created"); + return; + } + + // switch here based on dictionary + // to handle various different requests like logging, INFO snapshot, etc.. + if ((xpc_dictionary_get_uint64(req, kDNSLogLevel))) + { + log_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSLogLevel)); + handle_logging(log_level); + } + else if ((xpc_dictionary_get_uint64(req, kDNSStateInfo))) + { + state_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSStateInfo)); + handle_stateinfo(state_level); + } + else if ((xpc_dictionary_get_uint64(req, kmDNSResponderTests))) + { + test_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kmDNSResponderTests)); + handle_test_mode(test_mode); + } +} + +mDNSlocal void accept_client(xpc_connection_t conn) +{ + uid_t c_euid; + int c_pid; + c_euid = xpc_connection_get_euid(conn); + c_pid = xpc_connection_get_pid(conn); + + if (c_euid != 0 || !IsEntitled(conn, kDNSCTLService)) + { + LogMsg("accept_client: Client PID[%d] is missing Entitlement or is NOT running as root!", c_pid); + xpc_connection_cancel(conn); + return; + } + + xpc_retain(conn); + xpc_connection_set_target_queue(conn, dnsctlserver_queue); + xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg) + { + xpc_type_t type = xpc_get_type(req_msg); + + if (type == XPC_TYPE_DICTIONARY) + { + handle_requests(req_msg); + } + else // We hit this case ONLY if Client Terminated Connection OR Crashed + { + LogInfo("accept_client: Client %p teared down the connection", (void *) conn); + handle_terminate(); + xpc_release(conn); + } + }); + + xpc_connection_resume(conn); + +} + +mDNSexport void init_dnsctl_service(void) +{ + + xpc_connection_t dnsctl_listener = xpc_connection_create_mach_service(kDNSCTLService, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (!dnsctl_listener || xpc_get_type(dnsctl_listener) != XPC_TYPE_CONNECTION) + { + LogMsg("init_dnsctl_service: Error Creating XPC Listener for DNSCTL Server!"); + return; + } + + dnsctlserver_queue = dispatch_queue_create("com.apple.mDNSResponder.dnsctlserver_queue", NULL); + + xpc_connection_set_event_handler(dnsctl_listener, ^(xpc_object_t eventmsg) + { + xpc_type_t type = xpc_get_type(eventmsg); + + if (type == XPC_TYPE_CONNECTION) + { + LogInfo("init_dnsctl_service: New DNSCTL Client %p", eventmsg); + accept_client(eventmsg); + } + else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases + { + LogMsg("init_dnsctl_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION)); + } + else + { + LogMsg("init_dnsctl_service: Unknown EventMsg type"); + } + }); + + xpc_connection_resume(dnsctl_listener); +} + + + diff --git a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c index fb357806..4cad6ba0 100644 --- a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c +++ b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c @@ -15,8 +15,7 @@ #include "dnsproxy.h" // DNSProxyInit/ProxyUDPCallback/ProxyTCPCallback #include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock -#include <xpc/xpc.h> -#include <xpc/private.h> // xpc_connection_copy_entitlement_value +#include <xpc/private.h> // xpc_connection_copy_entitlement_value // *************************************************************************** // Globals @@ -87,10 +86,10 @@ mDNSlocal void handle_dps_request(xpc_object_t req) { LogMsg("handle_dps_request: A Client is already using DNS Proxy and your request cannot be handled at this time"); // Return Engaged Status to the client - xpc_object_t reply = xpc_dictionary_create(NULL, NULL, 0); + xpc_object_t reply = xpc_dictionary_create_reply(req); if (reply) { - xpc_dictionary_set_uint64(reply, kDNSDaemonReply, kDNSMsg_BadArg); + xpc_dictionary_set_uint64(reply, kDNSDaemonReply, kDNSMsg_Busy); xpc_connection_send_message(remote_conn, reply); xpc_release(reply); } @@ -138,7 +137,7 @@ mDNSlocal void handle_dps_request(xpc_object_t req) } // Verify Client's Entitlement -mDNSlocal mDNSBool IsEntitled(xpc_connection_t conn, const char *password) +mDNSexport mDNSBool IsEntitled(xpc_connection_t conn, const char *password) { mDNSBool entitled = mDNSfalse; xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password); @@ -157,7 +156,7 @@ mDNSlocal mDNSBool IsEntitled(xpc_connection_t conn, const char *password) } if (!entitled) - LogMsg("IsEntitled: DNSProxyService Client is missing Entitlement!"); + LogMsg("IsEntitled: Client is missing Entitlement!"); return entitled; } @@ -241,8 +240,10 @@ mDNSexport void xpc_server_init() { // Add XPC Services here init_dnsproxy_service(); + init_dnsctl_service(); } + #else // !UNICAST_DISABLED mDNSexport void xpc_server_init() diff --git a/mDNSResponder/mDNSMacOSX/Private/xpc_services.h b/mDNSResponder/mDNSMacOSX/Private/xpc_services.h index 50081bed..8d7c0433 100644 --- a/mDNSResponder/mDNSMacOSX/Private/xpc_services.h +++ b/mDNSResponder/mDNSMacOSX/Private/xpc_services.h @@ -14,8 +14,14 @@ #define XPC_SERVICES_H #include "mDNSEmbeddedAPI.h" +#include <xpc/xpc.h> extern void xpc_server_init(void); extern void xpcserver_info(mDNS *const m); +extern mDNSBool IsEntitled(xpc_connection_t conn, const char *password); +extern void init_dnsctl_service(void); + +extern void INFOCallback(void); + #endif // XPC_SERVICES_H diff --git a/mDNSResponder/mDNSMacOSX/SymptomReporter.c b/mDNSResponder/mDNSMacOSX/SymptomReporter.c index 39ce0d41..7dde2f5e 100644 --- a/mDNSResponder/mDNSMacOSX/SymptomReporter.c +++ b/mDNSResponder/mDNSMacOSX/SymptomReporter.c @@ -22,7 +22,16 @@ #include <stddef.h> #include <stdint.h> #include <sys/socket.h> +#include <AvailabilityMacros.h> +#include <TargetConditionals.h> + +#define TARGET_OS_MACOSX (TARGET_OS_MAC && !TARGET_OS_IPHONE) + +#if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200)) +#include <SymptomReporter/SymptomReporter.h> +#else #include <Symptoms/SymptomReporter.h> +#endif #define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101 #define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder" @@ -30,7 +39,7 @@ #define SYMPTOM_DNS_NO_REPLIES 0x00065001 #define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002 -static symptom_framework_t symptomReporter; +static symptom_framework_t symptomReporter = mDNSNULL; static symptom_framework_t (*symptom_framework_init_f)(symptom_ident_t id, const char *originator_string) = mDNSNULL; static symptom_t (*symptom_new_f)(symptom_framework_t framework, symptom_ident_t id) = mDNSNULL; static int (*symptom_set_additional_qualifier_f)(symptom_t symptom, uint32_t qualifier_type, size_t qualifier_len, void *qualifier_data) = mDNSNULL; @@ -39,53 +48,43 @@ static int (*symptom_send_f)(symptom_t symptom) = mDNSNULL; mDNSlocal mStatus SymptomReporterInitCheck(void) { mStatus err; - static mDNSBool isInitialized = mDNSfalse; + static mDNSBool triedInit = mDNSfalse; static void *symptomReporterLib = mDNSNULL; +#if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200)) + static const char path[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter"; +#else static const char path[] = "/System/Library/PrivateFrameworks/Symptoms.framework/Frameworks/SymptomReporter.framework/SymptomReporter"; +#endif - if (!isInitialized) + if (!triedInit) { + triedInit = mDNStrue; + + symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL); if (!symptomReporterLib) - { - symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL); - if (!symptomReporterLib) - goto exit; - } + goto exit; + symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init"); if (!symptom_framework_init_f) - { - symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init"); - if (!symptom_framework_init_f) - goto exit; - } + goto exit; + symptom_new_f = dlsym(symptomReporterLib, "symptom_new"); if (!symptom_new_f) - { - symptom_new_f = dlsym(symptomReporterLib, "symptom_new"); - if (!symptom_new_f) - goto exit; - } + goto exit; + symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier"); if (!symptom_set_additional_qualifier_f) - { - symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier"); - if (!symptom_set_additional_qualifier_f) - goto exit; - } + goto exit; + symptom_send_f = dlsym(symptomReporterLib, "symptom_send"); if (!symptom_send_f) - { - symptom_send_f = dlsym(symptomReporterLib, "symptom_send"); - if (!symptom_send_f) - goto exit; - } + goto exit; symptomReporter = symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID); - isInitialized = mDNStrue; } exit: - err = isInitialized ? mStatus_NoError : mStatus_NotInitializedErr; + err = symptomReporter ? mStatus_NoError : mStatus_NotInitializedErr; return err; } diff --git a/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist b/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist index e31b391f..86d7b777 100644 --- a/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist +++ b/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist @@ -6,8 +6,6 @@ <true/> <key>Label</key> <string>com.apple.dnsextd</string> - <key>OnDemand</key> - <false/> <key>ProgramArguments</key> <array> <string>/usr/sbin/dnsextd</string> diff --git a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist index 8f5a6408..881f8c9e 100644 --- a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist +++ b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist @@ -1,11 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.apple.mDNSResponder.reloaded</string> - <key>OnDemand</key> - <false/> <key>InitGroups</key> <false/> <key>UserName</key> @@ -18,10 +16,10 @@ </array> <key>MachServices</key> <dict> - <key>com.apple.mDNSResponder</key> + <key>com.apple.mDNSResponder.dnsproxy</key> + <true/> + <key>com.apple.mDNSResponder.dnsctl</key> <true/> - <key>com.apple.mDNSResponder.dnsproxy</key> - <true/> </dict> <key>Sockets</key> <dict> diff --git a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist index f1e3027b..91ed1da3 100644 --- a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist +++ b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist @@ -12,7 +12,7 @@ </array> <key>MachServices</key> <dict> - <key>com.apple.mDNSResponderHelper</key> + <key>com.apple.mDNSResponder_Helper</key> <true/> </dict> <key>POSIXSpawnType</key> diff --git a/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder b/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder deleted file mode 100644 index d07c99d0..00000000 --- a/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder +++ /dev/null @@ -1 +0,0 @@ -? [= LoggerID com.apple.networking.mDNSResponder] file /Library/Logs/CrashReporter/com.apple.networking.mDNSResponder.log rotate file_max=1M compress diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.h b/mDNSResponder/mDNSMacOSX/coreBLE.h new file mode 100644 index 00000000..cc00923a --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/coreBLE.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015-2016 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 _coreBLE_H_ +#define _coreBLE_H_ + +#include "BLE.h" + +@interface coreBLE : NSObject <CBCentralManagerDelegate, CBPeripheralManagerDelegate, CBPeripheralDelegate> + +- (id)init; +- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash; +- (void) stopBeacon; +- (void) updateScan:(bool) start; + +@end + +#endif /* _coreBLE_H_ */ diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.m b/mDNSResponder/mDNSMacOSX/coreBLE.m new file mode 100644 index 00000000..e764169a --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/coreBLE.m @@ -0,0 +1,371 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015-2016 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. + */ + +#include "mDNSEmbeddedAPI.h" +#include "DNSCommon.h" + +#import <Foundation/Foundation.h> +#import <CoreBluetooth/CoreBluetooth.h> +#import <CoreBluetooth/CoreBluetooth_Private.h> +#import "mDNSMacOSX.h" +#import "BLE.h" +#import "coreBLE.h" + +static coreBLE * coreBLEptr; + +// Call Bluetooth subsystem to start/stop the the Bonjour BLE beacon and +// beacon scanning based on the current browse and registration hashes. +void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash) +{ + if (coreBLEptr == 0) + coreBLEptr = [[coreBLE alloc] init]; + + LogInfo("updateBLEBeaconAndScan: browseHash = 0x%x, registeredHash = 0x%x", browseHash, registeredHash); + + [coreBLEptr advertiseBrowses:browseHash andRegistrations: registeredHash]; + [coreBLEptr updateScan:(browseHash || registeredHash)]; +} + +// Stop the current BLE beacon. +void stopBLEBeacon(void) +{ + if (coreBLEptr == 0) + { + LogInfo("stopBLEBeacon called before BLE scan initialized ??"); + return; + } + + LogInfo("stopBLEBeacon Stopping beacon"); + [coreBLEptr stopBeacon]; +} + +@implementation coreBLE +{ + CBCentralManager *_centralManager; + CBPeripheralManager *_peripheralManager; + + NSData *_currentlyAdvertisedData; + + // [_centralManager isScanning] is only avilable on iOS and not OSX, + // so track scanning state locally. + BOOL _isScanning; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; + _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; + _currentlyAdvertisedData = nil; + _isScanning = NO; + + if (_centralManager == nil || _peripheralManager == nil ) + { + LogMsg("coreBLE initialization failed!"); + } + else + { + LogInfo("coreBLE initialised"); + } + } + + return self; +} + +#define ADVERTISEMENTDATALENGTH 28 // 31 - 3 (3 bytes for flags) + +// TODO: +// DBDeviceTypeBonjour should eventually be added to the DBDeviceType definitions in WirelessProximity +// The Bluetooth team recommended using a value < 32 for prototyping, since 32 is the number of +// beacon types they can track in their duplicate beacon filtering logic. +#define DBDeviceTypeBonjour 26 + +// Beacon flags and version byte +#define BonjourBLEVersion 1 + +extern mDNS mDNSStorage; +extern mDNSInterfaceID AWDLInterfaceID; + +// Transmit the last beacon indicating we are no longer advertising or browsing any services for two seconds. +#define LastBeaconTime 2 + +- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash +{ + uint8_t advertisingData[ADVERTISEMENTDATALENGTH] = {0, 0xff, 0x4c, 0x00 }; + uint8_t advertisingLength = 4; + + // TODO: If we have been transmitting a beacon, we probably want to continue transmitting + // for a few seconds after both hashes are zero so that that any devices scanning + // can see the beacon indicating we have stopped all browses and advertisements. + + // Stop the beacon if there is no data to advertise. + if (browseHash == 0 && registeredHash == 0) + { + LogInfo("advertiseBrowses:andRegistrations Stopping beacon in %d seconds", LastBeaconTime); + if (mDNSStorage.NextBLEServiceTime) + LogInfo("advertiseBrowses:andRegistrations: NextBLEServiceTime already set ??"); + + mDNSStorage.NextBLEServiceTime = NonZeroTime(mDNS_TimeNow_NoLock(& mDNSStorage) + LastBeaconTime * mDNSPlatformOneSecond); + } + else + { + mDNSStorage.NextBLEServiceTime = 0; + } + + // The beacon type. + advertisingData[advertisingLength++] = DBDeviceTypeBonjour; + + // Flags and Version field + advertisingData[advertisingLength++] = BonjourBLEVersion; + + memcpy(& advertisingData[advertisingLength], & browseHash, sizeof(serviceHash_t)); + advertisingLength += sizeof(serviceHash_t); + memcpy(& advertisingData[advertisingLength], & registeredHash, sizeof(serviceHash_t)); + advertisingLength += sizeof(serviceHash_t); + + + // Add the MAC address of the awdl0 interface. Don't cache it since + // it can get updated periodically. + if (AWDLInterfaceID) + { + NetworkInterfaceInfoOSX *intf = IfindexToInterfaceInfoOSX(& mDNSStorage, AWDLInterfaceID); + if (intf) + memcpy(& advertisingData[advertisingLength], & intf->ifinfo.MAC, sizeof(mDNSEthAddr)); + else + memset( & advertisingData[advertisingLength], 0, sizeof(mDNSEthAddr)); + } + else + { + // just use zero if not avaiblable + memset( & advertisingData[advertisingLength], 0, sizeof(mDNSEthAddr)); + } + advertisingLength += sizeof(mDNSEthAddr); + + // Total length of data advertised, minus this lenght byte. + advertisingData[0] = (advertisingLength - 1); + + LogInfo("advertiseBrowses:andRegistrations advertisingLength = %d", advertisingLength); + + NSData* data = [NSData dataWithBytes:advertisingData length:advertisingLength]; + + if([_peripheralManager isAdvertising] && [data isEqualToData: _currentlyAdvertisedData]) + { + // No need to restart the advertisement if it is already active with the same data. + LogInfo("advertiseBrowses:andRegistrations: No change in advertised data"); + } + else + { + _currentlyAdvertisedData = data; + + if ([_peripheralManager isAdvertising]) + { + LogInfo("advertiseBrowses:andRegistrations: Stop current advertisement before restarting"); + [_peripheralManager stopAdvertising]; + } + LogInfo("advertiseBrowses:andRegistrations: Starting beacon"); + + [_peripheralManager startAdvertising:@{ CBAdvertisementDataAppleMfgData : _currentlyAdvertisedData, CBCentralManagerScanOptionIsPrivilegedDaemonKey : @YES, @"kCBAdvOptionUseFGInterval" : @YES }]; + } +} + +- (void) stopBeacon +{ + [_peripheralManager stopAdvertising]; +} + +- (void) updateScan:(bool) start +{ + if (_isScanning) + { + if (!start) + { + LogInfo("updateScan: stopping scan"); + [_centralManager stopScan]; + _isScanning = NO; + } + } + else + { + if (start) + { + LogInfo("updateScan: starting scan"); + + _isScanning = YES; + [_centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @NO }]; + } + } +} + +#pragma mark - CBCentralManagerDelegate protocol + +- (void)centralManagerDidUpdateState:(CBCentralManager *)central +{ + switch (central.state) { + case CBCentralManagerStateUnknown: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnknown"); + break; + + case CBCentralManagerStateResetting: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStateResetting"); + break; + + case CBCentralManagerStateUnsupported: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnsupported"); + break; + + case CBCentralManagerStateUnauthorized: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnauthorized"); + break; + + case CBCentralManagerStatePoweredOff: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOff"); + break; + + case CBCentralManagerStatePoweredOn: + LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOn"); + break; + + default: + LogInfo("centralManagerDidUpdateState: Unknown state ??"); + break; + } +} + +// offset of beacon type in recieved CBAdvertisementDataManufacturerDataKey bytes +#define beaconTypeByteIndex 2 + +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI +{ + (void) central; + (void) peripheral; + (void) RSSI; + + NSData *data = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]; + + if (!data) { + return; + } + + unsigned char *bytes = (unsigned char *)data.bytes; + + // Just parse the DBDeviceTypeBonjour beacons. + if (bytes[beaconTypeByteIndex] == DBDeviceTypeBonjour) + { + serviceHash_t browseHash, registeredHash; + mDNSEthAddr senderMAC; + unsigned char flagsAndVersion; + unsigned char *ptr; + +#if VERBOSE_BLE_DEBUG + LogInfo("didDiscoverPeripheral: received DBDeviceTypeBonjour beacon, length = %d", [data length]); + LogInfo("didDiscoverPeripheral: central = 0x%x, peripheral = 0x%x", central, peripheral); +#endif // VERBOSE_BLE_DEBUG + + // The DBDeviceTypeBonjour beacon bytes will be: + // x4C, 0x0, 0x2A, flags_and_version_byte,, browseHash, advertisingServices_hash_bytes, + // 6_bytes_of_sender_AWDL_MAC_address + + ptr = & bytes[beaconTypeByteIndex + 1]; + flagsAndVersion = *ptr++; + memcpy(& browseHash, ptr, sizeof(serviceHash_t)); + ptr += sizeof(serviceHash_t); + memcpy(& registeredHash, ptr, sizeof(serviceHash_t)); + ptr += sizeof(serviceHash_t); + memcpy(& senderMAC, ptr, sizeof(senderMAC)); + +#if VERBOSE_BLE_DEBUG + LogInfo("didDiscoverPeripheral: version = 0x%x, browseHash = 0x%x, registeredHash = 0x%x", + flagsAndVersion, browseHash, registeredHash); + LogInfo("didDiscoverPeripheral: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + senderMAC.b[0], senderMAC.b[1], senderMAC.b[2], senderMAC.b[3], senderMAC.b[4], senderMAC.b[5]); +#else + (void)flagsAndVersion; // Unused +#endif // VERBOSE_BLE_DEBUG + + responseReceived(browseHash, registeredHash, & senderMAC); + +#if VERBOSE_BLE_DEBUG + // Log every 4th package during debug + static int pkgsIn = 0; + + if (((pkgsIn++) & 3) == 0) + { + LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]); +// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[5], bytes[6], bytes[7], bytes[9], bytes[9]); +// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[10], bytes[11], bytes[12], bytes[13], bytes[14]); +// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[15], bytes[16], bytes[17], bytes[18], bytes[19]); + } +#endif // VERBOSE_BLE_DEBUG + + } +} + +#pragma mark - CBPeripheralManagerDelegate protocol + +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral +{ + + switch (peripheral.state) { + case CBPeripheralManagerStateUnknown: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnknown"); + break; + + case CBPeripheralManagerStateResetting: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateResetting"); + break; + + case CBPeripheralManagerStateUnsupported: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnsupported"); + break; + + case CBPeripheralManagerStateUnauthorized: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnauthorized"); + break; + + case CBPeripheralManagerStatePoweredOff: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOff"); + break; + + case CBPeripheralManagerStatePoweredOn: + LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOn"); + break; + + default: + LogInfo("peripheralManagerDidUpdateState: Unknown state ??"); + break; + } +} + +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error +{ + (void) peripheral; + + if (error) + { + const char * errorString = [[error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]; + LogInfo("peripheralManagerDidStartAdvertising: error = %s", errorString ? errorString: "unknown"); + } + else + { + LogInfo("peripheralManagerDidStartAdvertising:"); + } +} + +@end diff --git a/mDNSResponder/mDNSMacOSX/daemon.c b/mDNSResponder/mDNSMacOSX/daemon.c index c1cabb1a..f5478b57 100644 --- a/mDNSResponder/mDNSMacOSX/daemon.c +++ b/mDNSResponder/mDNSMacOSX/daemon.c @@ -30,14 +30,8 @@ #include <pthread.h> #include <sandbox.h> #include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h> -#include <asl.h> -#include <syslog.h> #include <err.h> #include <sysexits.h> -#include <bootstrap_priv.h> // for bootstrap_check_in() - -#include "DNSServiceDiscoveryRequestServer.h" -#include "DNSServiceDiscoveryReply.h" #include "uDNS.h" #include "DNSCommon.h" @@ -45,35 +39,30 @@ #include "uds_daemon.h" // Interface to the server side implementation of dns_sd.h #include "xpc_services.h" // Interface to XPC services - -#include "../mDNSMacOSX/DNSServiceDiscovery.h" #include "helper.h" #if TARGET_OS_EMBEDDED #include "Metrics.h" #endif -static aslclient log_client = NULL; -static aslmsg log_msg = NULL; - -// Used on iOS ONLY for reading mDNSResponder Managed Preferences Profile -#if TARGET_OS_EMBEDDED -#define kmDNSEnableLoggingStr CFSTR("EnableLogging") -#define kmDNSResponderPrefIDStr "com.apple.mDNSResponder.plist" -#define kmDNSResponderPrefID CFSTR(kmDNSResponderPrefIDStr) +#if APPLE_OSX_mDNSResponder +static os_log_t log_general = NULL; #endif // Used on OSX(10.11.x onwards) for manipulating mDNSResponder program arguments -#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED +#if APPLE_OSX_mDNSResponder // plist file to read the user's preferences -#define kProgramArguments CFSTR("/Library/Preferences/com.apple.mDNSResponder.plist") +#define kProgramArguments CFSTR("com.apple.mDNSResponder") // possible arguments for external customers -#define kDebugLogging CFSTR("DebugLogging") -#define kUnicastPacketLogging CFSTR("UnicastPacketLogging") -#define kAlwaysAppendSearchDomains CFSTR("AlwaysAppendSearchDomains") -#define kNoMulticastAdvertisements CFSTR("NoMulticastAdvertisements") -#define kStrictUnicastOrdering CFSTR("StrictUnicastOrdering") +#define kPreferencesKey_DebugLogging CFSTR("DebugLogging") +#define kPreferencesKey_UnicastPacketLogging CFSTR("UnicastPacketLogging") +#define kPreferencesKey_AlwaysAppendSearchDomains CFSTR("AlwaysAppendSearchDomains") +#define kPreferencesKey_NoMulticastAdvertisements CFSTR("NoMulticastAdvertisements") +#define kPreferencesKey_StrictUnicastOrdering CFSTR("StrictUnicastOrdering") +#define kPreferencesKey_OfferSleepProxyService CFSTR("OfferSleepProxyService") +#define kPreferencesKey_UseInternalSleepProxy CFSTR("UseInternalSleepProxy") +#define kPreferencesKey_EnableBLEBasedDiscovery CFSTR("EnableBLEBasedDiscovery") #endif //************************************************************************************************************* @@ -91,124 +80,21 @@ static mDNS_PlatformSupport PlatformStorage; static CacheEntity rrcachestorage[RR_CACHE_SIZE]; struct CompileTimeAssertionChecks_RR_CACHE_SIZE { char a[(RR_CACHE_SIZE >= 141) ? 1 : -1]; }; -static mach_port_t m_port = MACH_PORT_NULL; #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM mDNSlocal void PrepareForIdle(void *m_param); #else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM -static mach_port_t client_death_port = MACH_PORT_NULL; static mach_port_t signal_port = MACH_PORT_NULL; #endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM static dnssd_sock_t *launchd_fds = mDNSNULL; static size_t launchd_fds_count = 0; -// mDNS Mach Message Timeout, in milliseconds. -// We need this to be short enough that we don't deadlock the mDNSResponder if a client -// fails to service its mach message queue, but long enough to give a well-written -// client a chance to service its mach message queue without getting cut off. -// Empirically, 50ms seems to work, so we set the timeout to 250ms to give -// even extra-slow clients a fair chance before we cut them off. -#define MDNS_MM_TIMEOUT 250 - -static mDNSBool advertise = mDNS_Init_AdvertiseLocalAddresses; // By default, advertise addresses (& other records) via multicast +static mDNSBool NoMulticastAdvertisements = mDNSfalse; // By default, advertise addresses (& other records) via multicast extern mDNSBool StrictUnicastOrdering; extern mDNSBool AlwaysAppendSearchDomains; - -//************************************************************************************************************* -#if COMPILER_LIKES_PRAGMA_MARK -#pragma mark - -#pragma mark - Active client list structures -#endif - -typedef struct DNSServiceDomainEnumeration_struct DNSServiceDomainEnumeration; -struct DNSServiceDomainEnumeration_struct -{ - DNSServiceDomainEnumeration *next; - mach_port_t ClientMachPort; - DNSQuestion dom; // Question asking for domains - DNSQuestion def; // Question asking for default domain -}; - -typedef struct DNSServiceBrowserResult_struct DNSServiceBrowserResult; -struct DNSServiceBrowserResult_struct -{ - DNSServiceBrowserResult *next; - int resultType; - domainname result; -}; - -typedef struct DNSServiceBrowser_struct DNSServiceBrowser; - -typedef struct DNSServiceBrowserQuestion -{ - struct DNSServiceBrowserQuestion *next; - DNSQuestion q; - domainname domain; -} DNSServiceBrowserQuestion; - -struct DNSServiceBrowser_struct -{ - DNSServiceBrowser *next; - mach_port_t ClientMachPort; - DNSServiceBrowserQuestion *qlist; - DNSServiceBrowserResult *results; - mDNSs32 lastsuccess; - mDNSBool DefaultDomain; // was the browse started on an explicit domain? - domainname type; // registration type -}; - -typedef struct DNSServiceResolver_struct DNSServiceResolver; -struct DNSServiceResolver_struct -{ - DNSServiceResolver *next; - mach_port_t ClientMachPort; - ServiceInfoQuery q; - ServiceInfo i; - mDNSs32 ReportTime; -}; - -// A single registered service: ServiceRecordSet + bookkeeping -// Note that we duplicate some fields from parent DNSServiceRegistration object -// to facilitate cleanup, when instances and parent may be deallocated at different times. -typedef struct ServiceInstance -{ - struct ServiceInstance *next; - mach_port_t ClientMachPort; - mDNSBool autoname; // Set if this name is tied to the Computer Name - mDNSBool renameonmemfree; // Set if we just got a name conflict and now need to automatically pick a new name - domainlabel name; - domainname domain; - ServiceRecordSet srs; - // Don't add any fields after ServiceRecordSet. - // This is where the implicit extra space goes if we allocate an oversized ServiceRecordSet object -} ServiceInstance; - -// A client-created service. May reference several ServiceInstance objects if default -// settings cause registration in multiple domains. -typedef struct DNSServiceRegistration -{ - struct DNSServiceRegistration *next; - mach_port_t ClientMachPort; - mDNSBool DefaultDomain; - mDNSBool autoname; - size_t rdsize; - int NumSubTypes; - char regtype[MAX_ESCAPED_DOMAIN_NAME]; // for use in AllocateSubtypes - domainlabel name; // used only if autoname is false - domainname type; - mDNSIPPort port; - unsigned char txtinfo[1024]; - size_t txt_len; - uint32_t NextRef; - ServiceInstance *regs; -} DNSServiceRegistration; - -static DNSServiceDomainEnumeration *DNSServiceDomainEnumerationList = NULL; -static DNSServiceBrowser *DNSServiceBrowserList = NULL; -static DNSServiceResolver *DNSServiceResolverList = NULL; -static DNSServiceRegistration *DNSServiceRegistrationList = NULL; +extern mDNSBool EnableBLEBasedDiscovery; // We keep a list of client-supplied event sources in KQSocketEventSource records typedef struct KQSocketEventSource @@ -230,15 +116,12 @@ static KQSocketEventSource *gEventSources; char _malloc_options[] = "AXZ"; -mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion) +mDNSlocal void validatelists(mDNS *const m) { -#if TARGET_OS_WATCH +#if BONJOUR_ON_DEMAND mDNSu32 NumAllInterfaceRecords = 0; mDNSu32 NumAllInterfaceQuestions = 0; -#else - mDNSu32 NumAllInterfaceRecords = 1; - mDNSu32 NumAllInterfaceQuestions = 1; -#endif +#endif // BONJOUR_ON_DEMAND // Check local lists KQSocketEventSource *k; @@ -246,27 +129,6 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion) if (k->next == (KQSocketEventSource *)~0 || k->fd < 0) LogMemCorruption("gEventSources: %p is garbage (%d)", k, k->fd); - // Check Mach client lists - DNSServiceDomainEnumeration *e; - for (e = DNSServiceDomainEnumerationList; e; e=e->next) - if (e->next == (DNSServiceDomainEnumeration *)~0 || e->ClientMachPort == 0 || e->ClientMachPort == (mach_port_t) ~0) - LogMemCorruption("DNSServiceDomainEnumerationList: %p is garbage (%X)", e, e->ClientMachPort); - - DNSServiceBrowser *b; - for (b = DNSServiceBrowserList; b; b=b->next) - if (b->next == (DNSServiceBrowser *)~0 || b->ClientMachPort == 0 || b->ClientMachPort == (mach_port_t) ~0) - LogMemCorruption("DNSServiceBrowserList: %p is garbage (%X)", b, b->ClientMachPort); - - DNSServiceResolver *l; - for (l = DNSServiceResolverList; l; l=l->next) - if (l->next == (DNSServiceResolver *)~0 || l->ClientMachPort == 0 || l->ClientMachPort == (mach_port_t) ~0) - LogMemCorruption("DNSServiceResolverList: %p is garbage (%X)", l, l->ClientMachPort); - - DNSServiceRegistration *r; - for (r = DNSServiceRegistrationList; r; r=r->next) - if (r->next == (DNSServiceRegistration *)~0 || r->ClientMachPort == 0 || r->ClientMachPort == (mach_port_t) ~0) - LogMemCorruption("DNSServiceRegistrationList: %p is garbage (%X)", r, r->ClientMachPort); - // Check Unix Domain Socket client lists (uds_daemon.c) uds_validatelists(); @@ -279,14 +141,18 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion) if (rr->resrec.name != &rr->namestorage) LogMemCorruption("ResourceRecords list: %p name %p does not point to namestorage %p %##s", rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c); +#if BONJOUR_ON_DEMAND if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++; +#endif // BONJOUR_ON_DEMAND } for (rr = m->DuplicateRecords; rr; rr=rr->next) { if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF) LogMemCorruption("DuplicateRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType); +#if BONJOUR_ON_DEMAND if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++; +#endif // BONJOUR_ON_DEMAND } rr = m->NewLocalRecords; @@ -304,23 +170,25 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion) { if (q->next == (DNSQuestion*)~0 || q->ThisQInterval == (mDNSs32) ~0) LogMemCorruption("Questions list: %p is garbage (%lX %p)", q, q->ThisQInterval, q->next); - if (q->InterfaceID != mDNSInterface_LocalOnly && q->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(q->TargetQID)) + if (q->DuplicateOf && q->LocalSocket) + LogMemCorruption("Questions list: Duplicate Question %p should not have LocalSocket set %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); +#if BONJOUR_ON_DEMAND + if (!LocalOnlyOrP2PInterface(q->InterfaceID) && mDNSOpaque16IsZero(q->TargetQID)) NumAllInterfaceQuestions++; +#endif // BONJOUR_ON_DEMAND } - if (checkCRActiveQuestion) { - CacheGroup *cg; - CacheRecord *cr; - mDNSu32 slot; - FORALL_CACHERECORDS(slot, cg, cr) + CacheGroup *cg; + CacheRecord *cr; + mDNSu32 slot; + FORALL_CACHERECORDS(slot, cg, cr) + { + if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF) + LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType); + if (cr->CRActiveQuestion) { - if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF) - LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType); - if (cr->CRActiveQuestion) - { - for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break; - if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr)); - } + for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break; + if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr)); } } @@ -338,13 +206,13 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion) if (t->next == (ClientTunnel *)~0 || t->dstname.c[0] > 63) LogMemCorruption("m->TunnelClients: %p is garbage (%d)", t, t->dstname.c[0]); -#if TARGET_OS_WATCH +#if BONJOUR_ON_DEMAND if (m->NumAllInterfaceRecords != NumAllInterfaceRecords) LogMemCorruption("NumAllInterfaceRecords is %d should be %d", m->NumAllInterfaceRecords, NumAllInterfaceRecords); if (m->NumAllInterfaceQuestions != NumAllInterfaceQuestions) LogMemCorruption("NumAllInterfaceQuestions is %d should be %d", m->NumAllInterfaceQuestions, NumAllInterfaceQuestions); -#endif +#endif // BONJOUR_ON_DEMAND } mDNSexport void *mallocL(char *msg, unsigned int size) @@ -361,7 +229,7 @@ mDNSexport void *mallocL(char *msg, unsigned int size) mem[1] = size; //mDNSPlatformMemZero(&mem[2], size); memset(&mem[2], 0xFF, size); - validatelists(&mDNSStorage, true); + validatelists(&mDNSStorage); return(&mem[2]); } } @@ -379,7 +247,7 @@ mDNSexport void freeL(char *msg, void *x) else if (MACOSX_MDNS_MALLOC_DEBUGGING >= 2) LogMsg("free( %s : %ld @ %p)", msg, mem[1], &mem[2]); mem[0] = 0xDEADDEAD; memset(mem+2, 0xFF, mem[1]); - validatelists(&mDNSStorage, false); + validatelists(&mDNSStorage); free(mem); } } @@ -387,610 +255,6 @@ mDNSexport void freeL(char *msg, void *x) #endif //************************************************************************************************************* -#if COMPILER_LIKES_PRAGMA_MARK -#pragma mark - -#pragma mark - Mach client request handlers -#endif - -//************************************************************************************************************* -// Client Death Detection - -// This gets called after ALL constituent records of the Service Record Set have been deregistered -mDNSlocal void FreeServiceInstance(ServiceInstance *x) -{ - ServiceRecordSet *s = &x->srs; - ExtraResourceRecord *e = x->srs.Extras, *tmp; - - while (e) - { - e->r.RecordContext = e; - tmp = e; - e = e->next; - FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree); - } - - if (s->RR_TXT.resrec.rdata != &s->RR_TXT.rdatastorage) - freeL("TXT RData", s->RR_TXT.resrec.rdata); - - if (s->SubTypes) freeL("ServiceSubTypes", s->SubTypes); - freeL("ServiceInstance", x); -} - -// AbortClient finds whatever client is identified by the given Mach port, -// stops whatever operation that client was doing, and frees its memory. -// In the case of a service registration, the actual freeing may be deferred -// until we get the mStatus_MemFree message, if necessary -mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m) -{ - DNSServiceDomainEnumeration **e = &DNSServiceDomainEnumerationList; - DNSServiceBrowser **b = &DNSServiceBrowserList; - DNSServiceResolver **l = &DNSServiceResolverList; - DNSServiceRegistration **r = &DNSServiceRegistrationList; - - while (*e && (*e)->ClientMachPort != ClientMachPort) e = &(*e)->next; - if (*e) - { - DNSServiceDomainEnumeration *x = *e; - *e = (*e)->next; - if (m && m != x) - LogMsg("%5d: DNSServiceDomainEnumeration(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->dom.qname.c, m, x); - else LogOperation("%5d: DNSServiceDomainEnumeration(%##s) STOP", ClientMachPort, x->dom.qname.c); - mDNS_StopGetDomains(&mDNSStorage, &x->dom); - mDNS_StopGetDomains(&mDNSStorage, &x->def); - freeL("DNSServiceDomainEnumeration", x); - return; - } - - while (*b && (*b)->ClientMachPort != ClientMachPort) b = &(*b)->next; - if (*b) - { - DNSServiceBrowser *x = *b; - DNSServiceBrowserQuestion *freePtr, *qptr = x->qlist; - *b = (*b)->next; - while (qptr) - { - if (m && m != x) - LogMsg("%5d: DNSServiceBrowse(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x); - else LogOperation("%5d: DNSServiceBrowse(%##s) STOP", ClientMachPort, qptr->q.qname.c); - mDNS_StopBrowse(&mDNSStorage, &qptr->q); - freePtr = qptr; - qptr = qptr->next; - freeL("DNSServiceBrowserQuestion", freePtr); - } - while (x->results) - { - DNSServiceBrowserResult *t = x->results; - x->results = x->results->next; - freeL("DNSServiceBrowserResult", t); - } - freeL("DNSServiceBrowser", x); - return; - } - - while (*l && (*l)->ClientMachPort != ClientMachPort) l = &(*l)->next; - if (*l) - { - DNSServiceResolver *x = *l; - *l = (*l)->next; - if (m && m != x) - LogMsg("%5d: DNSServiceResolve(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x); - else LogOperation("%5d: DNSServiceResolve(%##s) STOP", ClientMachPort, x->i.name.c); - mDNS_StopResolveService(&mDNSStorage, &x->q); - freeL("DNSServiceResolver", x); - return; - } - - while (*r && (*r)->ClientMachPort != ClientMachPort) r = &(*r)->next; - if (*r) - { - ServiceInstance *si = NULL; - DNSServiceRegistration *x = *r; - *r = (*r)->next; - - si = x->regs; - while (si) - { - ServiceInstance *instance = si; - si = si->next; - instance->renameonmemfree = mDNSfalse; - if (m && m != x) LogMsg("%5d: DNSServiceRegistration(%##s, %u) STOP; WARNING m %p != x %p", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs), m, x); - else LogOperation("%5d: DNSServiceRegistration(%##s, %u) STOP", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs)); - - // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list, - // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory. - // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from - // the list, so we should go ahead and free the memory right now - if (mDNS_DeregisterService(&mDNSStorage, &instance->srs)) FreeServiceInstance(instance); // FreeServiceInstance invalidates pointer - } - x->regs = NULL; - freeL("DNSServiceRegistration", x); - return; - } - - LogMsg("%5d: died or deallocated, but no record of client can be found!", ClientMachPort); -} - -#define AbortBlockedClient(C,MSG,M) AbortClientWithLogMessage((C), "stopped accepting Mach messages", " (" MSG ")", (M)) - -mDNSlocal void AbortClientWithLogMessage(mach_port_t c, char *reason, char *msg, void *m) -{ - DNSServiceDomainEnumeration *e = DNSServiceDomainEnumerationList; - DNSServiceBrowser *b = DNSServiceBrowserList; - DNSServiceResolver *l = DNSServiceResolverList; - DNSServiceRegistration *r = DNSServiceRegistrationList; - DNSServiceBrowserQuestion *qptr; - - while (e && e->ClientMachPort != c) e = e->next; - while (b && b->ClientMachPort != c) b = b->next; - while (l && l->ClientMachPort != c) l = l->next; - while (r && r->ClientMachPort != c) r = r->next; - - if (e) LogMsg("%5d: DomainEnumeration(%##s) %s%s", c, e->dom.qname.c, reason, msg); - else if (b) - { - for (qptr = b->qlist; qptr; qptr = qptr->next) - LogMsg("%5d: Browser(%##s) %s%s", c, qptr->q.qname.c, reason, msg); - } - else if (l) LogMsg("%5d: Resolver(%##s) %s%s", c, l->i.name.c, reason, msg); - else if (r) - { - ServiceInstance *si; - for (si = r->regs; si; si = si->next) - LogMsg("%5d: Registration(%##s) %s%s", c, si->srs.RR_SRV.resrec.name->c, reason, msg); - } - else LogMsg("%5d: (%s) %s, but no record of client can be found!", c, reason, msg); - - AbortClient(c, m); -} - -mDNSlocal mDNSBool CheckForExistingClient(mach_port_t c) -{ - DNSServiceDomainEnumeration *e = DNSServiceDomainEnumerationList; - DNSServiceBrowser *b = DNSServiceBrowserList; - DNSServiceResolver *l = DNSServiceResolverList; - DNSServiceRegistration *r = DNSServiceRegistrationList; - DNSServiceBrowserQuestion *qptr; - - while (e && e->ClientMachPort != c) e = e->next; - while (b && b->ClientMachPort != c) b = b->next; - while (l && l->ClientMachPort != c) l = l->next; - while (r && r->ClientMachPort != c) r = r->next; - if (e) LogMsg("%5d: DomainEnumeration(%##s) already exists!", c, e->dom.qname.c); - if (b) - { - for (qptr = b->qlist; qptr; qptr = qptr->next) - LogMsg("%5d: Browser(%##s) already exists!", c, qptr->q.qname.c); - } - if (l) LogMsg("%5d: Resolver(%##s) already exists!", c, l->i.name.c); - if (r) LogMsg("%5d: Registration(%##s) already exists!", c, r->regs ? r->regs->srs.RR_SRV.resrec.name->c : NULL); - return(e || b || l || r); -} - -#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM - -mDNSlocal void ClientDeathCallback(CFMachPortRef unusedport, void *voidmsg, CFIndex size, void *info) -{ - KQueueLock(&mDNSStorage); - mach_msg_header_t *msg = (mach_msg_header_t *)voidmsg; - (void)unusedport; // Unused - (void)size; // Unused - (void)info; // Unused - if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) - { - const mach_dead_name_notification_t *const deathMessage = (mach_dead_name_notification_t *)msg; - AbortClient(deathMessage->not_port, NULL); - - /* Deallocate the send right that came in the dead name notification */ - mach_port_destroy(mach_task_self(), deathMessage->not_port); - } - KQueueUnlock(&mDNSStorage, "Mach AbortClient"); -} - -#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM - -mDNSlocal void EnableDeathNotificationForClient(mach_port_t ClientMachPort, void *m) -{ -#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM - dispatch_source_t mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, ClientMachPort, 0, dispatch_get_main_queue()); - if (mach_source == mDNSNULL) - { - AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m); - return; - } - dispatch_source_set_event_handler(mach_source, ^{ - mach_port_destroy(mach_task_self(), ClientMachPort); - }); - dispatch_resume(mach_source); -#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM - mach_port_t prev; - kern_return_t r = mach_port_request_notification(mach_task_self(), ClientMachPort, MACH_NOTIFY_DEAD_NAME, 0, - client_death_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev); - // If the port already died while we were thinking about it, then abort the operation right away - if (r != KERN_SUCCESS) - AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m); -#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM -} - -//************************************************************************************************************* -// Domain Enumeration - -mDNSlocal void DomainEnumFound(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) -{ - kern_return_t status; - char buffer[MAX_ESCAPED_DOMAIN_NAME]; - DNSServiceDomainEnumerationReplyResultType rt; - DNSServiceDomainEnumeration *x = (DNSServiceDomainEnumeration *)question->QuestionContext; - (void)m; // Unused - - debugf("DomainEnumFound: %##s PTR %##s", answer->name->c, answer->rdata->u.name.c); - if (answer->rrtype != kDNSType_PTR) return; - if (!x) { debugf("DomainEnumFound: DNSServiceDomainEnumeration is NULL"); return; } - - if (AddRecord) - { - if (question == &x->dom) rt = DNSServiceDomainEnumerationReplyAddDomain; - else rt = DNSServiceDomainEnumerationReplyAddDomainDefault; - } - else - { - if (question == &x->dom) rt = DNSServiceDomainEnumerationReplyRemoveDomain; - else return; - } - - LogOperation("%5d: DNSServiceDomainEnumeration(%##s) %##s %s", - x->ClientMachPort, x->dom.qname.c, answer->rdata->u.name.c, - !AddRecord ? "RemoveDomain" : - question == &x->dom ? "AddDomain" : "AddDomainDefault"); - - ConvertDomainNameToCString(&answer->rdata->u.name, buffer); - status = DNSServiceDomainEnumerationReply_rpc(x->ClientMachPort, rt, buffer, 0, MDNS_MM_TIMEOUT); - if (status == MACH_SEND_TIMED_OUT) - AbortBlockedClient(x->ClientMachPort, "enumeration", x); -} - -mDNSexport kern_return_t provide_DNSServiceDomainEnumerationCreate_rpc(mach_port_t unusedserver, mach_port_t client, - int regDom) -{ - // Check client parameter - (void)unusedserver; // Unused - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; } - - mDNS_DomainType dt1 = regDom ? mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse; - mDNS_DomainType dt2 = regDom ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault; - - // Allocate memory, and handle failure - DNSServiceDomainEnumeration *x = mallocL("DNSServiceDomainEnumeration", sizeof(*x)); - if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - - // Set up object, and link into list - x->ClientMachPort = client; - x->next = DNSServiceDomainEnumerationList; - DNSServiceDomainEnumerationList = x; - - verbosedebugf("%5d: Enumerate %s Domains", client, regDom ? "Registration" : "Browsing"); - - // Do the operation - err = mDNS_GetDomains(&mDNSStorage, &x->dom, dt1, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x); - if (!err) err = mDNS_GetDomains(&mDNSStorage, &x->def, dt2, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x); - if (err) { AbortClient(client, x); errormsg = "mDNS_GetDomains"; goto fail; } - - // Succeeded: Wrap up and return - LogOperation("%5d: DNSServiceDomainEnumeration(%##s) START", client, x->dom.qname.c); - EnableDeathNotificationForClient(client, x); - return(mStatus_NoError); - -fail: - LogMsg("%5d: DNSServiceDomainEnumeration(%d) failed: %s (%d)", client, regDom, errormsg, err); - return(err); -} - -//************************************************************************************************************* -// Browse for services - -mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) -{ - (void)m; // Unused - - if (answer->rrtype != kDNSType_PTR) - { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; } - - domainlabel name; - domainname type, domain; - if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain)) - { - LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer", - answer->name->c, answer->rdata->u.name.c); - return; - } - - DNSServiceBrowserResult *x = mallocL("DNSServiceBrowserResult", sizeof(*x)); - if (!x) { LogMsg("FoundInstance: Failed to allocate memory for result %##s", answer->rdata->u.name.c); return; } - - verbosedebugf("FoundInstance: %s %##s", AddRecord ? "Add" : "Rmv", answer->rdata->u.name.c); - AssignDomainName(&x->result, &answer->rdata->u.name); - if (AddRecord) - x->resultType = DNSServiceBrowserReplyAddInstance; - else x->resultType = DNSServiceBrowserReplyRemoveInstance; - x->next = NULL; - - DNSServiceBrowser *browser = (DNSServiceBrowser *)question->QuestionContext; - DNSServiceBrowserResult **p = &browser->results; - while (*p) p = &(*p)->next; - *p = x; - - LogOperation("%5d: DNSServiceBrowse(%##s, %s) RESULT %s %s", - browser->ClientMachPort, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer)); -} - -mDNSlocal mStatus AddDomainToBrowser(DNSServiceBrowser *browser, const domainname *d) -{ - mStatus err = mStatus_NoError; - DNSServiceBrowserQuestion *ptr, *question = NULL; - - for (ptr = browser->qlist; ptr; ptr = ptr->next) - { - if (SameDomainName(&ptr->q.qname, d)) - { debugf("Domain %##s already contained in browser", d->c); return mStatus_AlreadyRegistered; } - } - - question = mallocL("DNSServiceBrowserQuestion", sizeof(DNSServiceBrowserQuestion)); - if (!question) { LogMsg("Error: malloc"); return mStatus_NoMemoryErr; } - AssignDomainName(&question->domain, d); - question->next = browser->qlist; - LogOperation("%5d: DNSServiceBrowse(%##s%##s) START", browser->ClientMachPort, browser->type.c, d->c); - err = mDNS_StartBrowse(&mDNSStorage, &question->q, &browser->type, d, mDNSNULL, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse, FoundInstance, browser); - if (!err) - browser->qlist = question; - else - { - LogMsg("Error: AddDomainToBrowser: mDNS_StartBrowse %d", err); - freeL("DNSServiceBrowserQuestion", question); - } - return err; -} - -mDNSexport void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add) -{ - DNSServiceBrowser *ptr; - for (ptr = DNSServiceBrowserList; ptr; ptr = ptr->next) - { - if (ptr->DefaultDomain) - { - if (add) - { - mStatus err = AddDomainToBrowser(ptr, d); - if (err && err != mStatus_AlreadyRegistered) LogMsg("Default browse in domain %##s for client %5d failed. Continuing", d, ptr->ClientMachPort); - } - else - { - DNSServiceBrowserQuestion **q = &ptr->qlist; - while (*q) - { - if (SameDomainName(&(*q)->domain, d)) - { - DNSServiceBrowserQuestion *rem = *q; - *q = (*q)->next; - mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q); - freeL("DNSServiceBrowserQuestion", rem); - return; - } - q = &(*q)->next; - } - LogMsg("Requested removal of default domain %##s not in client %5d's list", d->c, ptr->ClientMachPort); - } - } - } -} - -mDNSexport kern_return_t provide_DNSServiceBrowserCreate_rpc(mach_port_t unusedserver, mach_port_t client, - DNSCString regtype, DNSCString domain) -{ - // Check client parameter - (void)unusedserver; // Unused - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; } - - // Check other parameters - domainname t, d; - t.c[0] = 0; - mDNSs32 NumSubTypes = ChopSubTypes(regtype, mDNSNULL); // Note: Modifies regtype string to remove trailing subtypes - if (NumSubTypes < 0 || NumSubTypes > 1) { errormsg = "Bad Service SubType"; goto badparam; } - if (NumSubTypes == 1 && !AppendDNSNameString(&t, regtype + strlen(regtype) + 1)) - { errormsg = "Bad Service SubType"; goto badparam; } - if (!regtype[0] || !AppendDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; } - domainname temp; - if (!MakeDomainNameFromDNSNameString(&temp, regtype)) { errormsg = "Illegal regtype"; goto badparam; } - if (temp.c[0] > 15 && (!domain || domain[0] == 0)) domain = "local."; // For over-long service types, we only allow domain "local" - - // Allocate memory, and handle failure - DNSServiceBrowser *x = mallocL("DNSServiceBrowser", sizeof(*x)); - if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - - // Set up object, and link into list - AssignDomainName(&x->type, &t); - x->ClientMachPort = client; - x->results = NULL; - x->lastsuccess = 0; - x->qlist = NULL; - x->next = DNSServiceBrowserList; - DNSServiceBrowserList = x; - - if (domain[0]) - { - // Start browser for an explicit domain - x->DefaultDomain = mDNSfalse; - if (!MakeDomainNameFromDNSNameString(&d, domain)) { errormsg = "Illegal domain"; goto badparam; } - err = AddDomainToBrowser(x, &d); - if (err) { AbortClient(client, x); errormsg = "AddDomainToBrowser"; goto fail; } - } - else - { - DNameListElem *sdPtr; - // Start browser on all domains - x->DefaultDomain = mDNStrue; - if (!AutoBrowseDomains) { AbortClient(client, x); errormsg = "GetSearchDomainList"; goto fail; } - for (sdPtr = AutoBrowseDomains; sdPtr; sdPtr = sdPtr->next) - { - err = AddDomainToBrowser(x, &sdPtr->name); - if (err) - { - // only terminally bail if .local fails - if (!SameDomainName(&localdomain, &sdPtr->name)) - LogMsg("Default browse in domain %##s failed. Continuing", sdPtr->name.c); - else { AbortClient(client, x); errormsg = "AddDomainToBrowser"; goto fail; } - } - } - } - - // Succeeded: Wrap up and return - EnableDeathNotificationForClient(client, x); - return(mStatus_NoError); - -badparam: - err = mStatus_BadParamErr; -fail: - LogMsg("%5d: DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%d)", client, regtype, domain, errormsg, err); - return(err); -} - -//************************************************************************************************************* -// Resolve Service Info - -mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query) -{ - kern_return_t status; - DNSServiceResolver *x = (DNSServiceResolver *)query->ServiceInfoQueryContext; - NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(m, query->info->InterfaceID); - if (query->info->InterfaceID == mDNSInterface_LocalOnly || query->info->InterfaceID == mDNSInterface_P2P) ifx = mDNSNULL; - struct sockaddr_storage interface; - struct sockaddr_storage address; - char cstring[1024]; - int i, pstrlen = query->info->TXTinfo[0]; - (void)m; // Unused - - //debugf("FoundInstanceInfo %.4a %.4a %##s", &query->info->InterfaceAddr, &query->info->ip, &query->info->name); - - if (query->info->TXTlen > sizeof(cstring)) return; - - mDNSPlatformMemZero(&interface, sizeof(interface)); - mDNSPlatformMemZero(&address, sizeof(address)); - - if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv4) - { - struct sockaddr_in *s = (struct sockaddr_in*)&interface; - s->sin_len = sizeof(*s); - s->sin_family = AF_INET; - s->sin_port = 0; - s->sin_addr.s_addr = ifx->ifinfo.ip.ip.v4.NotAnInteger; - } - else if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv6) - { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&interface; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_flowinfo = 0; - sin6->sin6_port = 0; - sin6->sin6_addr = *(struct in6_addr*)&ifx->ifinfo.ip.ip.v6; - sin6->sin6_scope_id = ifx->scope_id; - } - - if (query->info->ip.type == mDNSAddrType_IPv4) - { - struct sockaddr_in *s = (struct sockaddr_in*)&address; - s->sin_len = sizeof(*s); - s->sin_family = AF_INET; - s->sin_port = query->info->port.NotAnInteger; - s->sin_addr.s_addr = query->info->ip.ip.v4.NotAnInteger; - } - else - { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&address; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = query->info->port.NotAnInteger; - sin6->sin6_flowinfo = 0; - sin6->sin6_addr = *(struct in6_addr*)&query->info->ip.ip.v6; - sin6->sin6_scope_id = ifx ? ifx->scope_id : 0; - } - - // The OS X DNSServiceResolverResolve() API is defined using a C-string, - // but the mDNS_StartResolveService() call actually returns a packed block of P-strings. - // Hence we have to convert the P-string(s) to a C-string before returning the result to the client. - // ASCII-1 characters are used in the C-string as boundary markers, - // to indicate the boundaries between the original constituent P-strings. - for (i=1; i<query->info->TXTlen; i++) - { - if (--pstrlen >= 0) - cstring[i-1] = query->info->TXTinfo[i]; - else - { - cstring[i-1] = 1; - pstrlen = query->info->TXTinfo[i]; - } - } - cstring[i-1] = 0; // Put the terminating NULL on the end - - LogOperation("%5d: DNSServiceResolver(%##s) -> %#a:%u", x->ClientMachPort, - x->i.name.c, &query->info->ip, mDNSVal16(query->info->port)); - status = DNSServiceResolverReply_rpc(x->ClientMachPort, - (char*)&interface, (char*)&address, cstring, 0, MDNS_MM_TIMEOUT); - if (status == MACH_SEND_TIMED_OUT) - AbortBlockedClient(x->ClientMachPort, "resolve", x); -} - -mDNSexport kern_return_t provide_DNSServiceResolverResolve_rpc(mach_port_t unusedserver, mach_port_t client, - DNSCString name, DNSCString regtype, DNSCString domain) -{ - // Check client parameter - (void)unusedserver; // Unused - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; } - - // Check other parameters - domainlabel n; - domainname t, d, srv; - if (!name[0] || !MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; } - if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } - if (!domain[0] || !MakeDomainNameFromDNSNameString(&d, domain)) { errormsg = "Bad Domain"; goto badparam; } - if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } - - // Allocate memory, and handle failure - DNSServiceResolver *x = mallocL("DNSServiceResolver", sizeof(*x)); - if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - - // Set up object, and link into list - x->ClientMachPort = client; - x->i.InterfaceID = mDNSInterface_Any; - x->i.name = srv; - x->ReportTime = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond); - x->next = DNSServiceResolverList; - DNSServiceResolverList = x; - - // Do the operation - LogOperation("%5d: DNSServiceResolve(%##s) START", client, x->i.name.c); - err = mDNS_StartResolveService(&mDNSStorage, &x->q, &x->i, FoundInstanceInfo, x); - if (err) { AbortClient(client, x); errormsg = "mDNS_StartResolveService"; goto fail; } - - // Succeeded: Wrap up and return - EnableDeathNotificationForClient(client, x); - return(mStatus_NoError); - -badparam: - err = mStatus_BadParamErr; -fail: - LogMsg("%5d: DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%d)", client, name, regtype, domain, errormsg, err); - return(err); -} - -//************************************************************************************************************* // Registration mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay) @@ -998,274 +262,6 @@ mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay) m->p->NotifyUser = NonZeroTime(m->timenow + delay); } -mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result) -{ - ServiceInstance *si = (ServiceInstance*)srs->ServiceContext; - - if (result == mStatus_NoError) - { - kern_return_t status; - LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Registered", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs)); - status = DNSServiceRegistrationReply_rpc(si->ClientMachPort, result, MDNS_MM_TIMEOUT); - if (status == MACH_SEND_TIMED_OUT) - AbortBlockedClient(si->ClientMachPort, "registration success", si); - if (si->autoname && CountPeerRegistrations(m, srs) == 0) - RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately - } - - else if (result == mStatus_NameConflict) - { - LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Conflict", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs)); - // Note: By the time we get the mStatus_NameConflict message, the service is already deregistered - // and the memory is free, so we don't have to wait for an mStatus_MemFree message as well. - if (si->autoname && CountPeerRegistrations(m, srs) == 0) - { - // On conflict for an autoname service, rename and reregister *all* autoname services - IncrementLabelSuffix(&m->nicelabel, mDNStrue); - mDNS_ConfigChanged(m); - } - else if (si->autoname) - { - mDNS_RenameAndReregisterService(m, srs, mDNSNULL); - return; - } - else - { - // If we get a name conflict, we tell the client about it, and then they are expected to dispose - // of their registration in the usual way (which we will catch via client death notification). - // If the Mach queue is full, we forcibly abort the client immediately. - kern_return_t status = DNSServiceRegistrationReply_rpc(si->ClientMachPort, result, MDNS_MM_TIMEOUT); - if (status == MACH_SEND_TIMED_OUT) - AbortBlockedClient(si->ClientMachPort, "registration conflict", NULL); - } - } - - else if (result == mStatus_MemFree) - { - if (si->renameonmemfree) // We intentionally terminated registration so we could re-register with new name - { - debugf("RegCallback renaming %#s to %#s", si->name.c, m->nicelabel.c); - si->renameonmemfree = mDNSfalse; - si->name = m->nicelabel; - mDNS_RenameAndReregisterService(m, srs, &si->name); - } - else - { - // SANITY CHECK: make sure service instance is no longer in any ServiceRegistration's list - DNSServiceRegistration *r; - for (r = DNSServiceRegistrationList; r; r = r->next) - { - ServiceInstance **sp = &r->regs; - while (*sp) - { - if (*sp == si) { LogMsg("RegCallback: %##s Still in list; removing", srs->RR_SRV.resrec.name->c); *sp = (*sp)->next; break; } - sp = &(*sp)->next; - } - } - // END SANITY CHECK - FreeServiceInstance(si); - } - } - - else if (result != mStatus_NATTraversal) - LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %d", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs), result); -} - -mDNSlocal mStatus AddServiceInstance(DNSServiceRegistration *x, const domainname *domain) -{ - mStatus err = 0; - ServiceInstance *si = NULL; - AuthRecord *SubTypes = NULL; - - for (si = x->regs; si; si = si->next) - { - if (SameDomainName(&si->domain, domain)) - { LogMsg("Requested addition of domain %##s already in list", domain->c); return mStatus_AlreadyRegistered; } - } - - SubTypes = AllocateSubTypes(x->NumSubTypes, x->regtype, mDNSNULL); - if (x->NumSubTypes && !SubTypes) return mStatus_NoMemoryErr; - - si = mallocL("ServiceInstance", sizeof(*si) - sizeof(RDataBody) + x->rdsize); - if (!si) return mStatus_NoMemoryErr; - - si->ClientMachPort = x->ClientMachPort; - si->renameonmemfree = mDNSfalse; - si->autoname = x->autoname; - si->name = x->autoname ? mDNSStorage.nicelabel : x->name; - si->domain = *domain; - si->srs.AnonData = mDNSNULL; - - err = mDNS_RegisterService(&mDNSStorage, &si->srs, &si->name, &x->type, domain, NULL, - x->port, x->txtinfo, x->txt_len, SubTypes, x->NumSubTypes, mDNSInterface_Any, RegCallback, si, 0); - if (!err) - { - si->next = x->regs; - x->regs = si; - } - else - { - LogMsg("Error %d for registration of service in domain %##s", err, domain->c); - freeL("ServiceInstance", si); - } - return err; -} - -mDNSexport void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add) -{ - DNSServiceRegistration *reg; - - for (reg = DNSServiceRegistrationList; reg; reg = reg->next) - { - if (reg->DefaultDomain) - { - if (add) - AddServiceInstance(reg, d); - else - { - ServiceInstance **si = ®->regs; - while (*si) - { - if (SameDomainName(&(*si)->domain, d)) - { - ServiceInstance *s = *si; - *si = (*si)->next; - if (mDNS_DeregisterService(&mDNSStorage, &s->srs)) FreeServiceInstance(s); // only free memory synchronously on error - break; - } - si = &(*si)->next; - } - if (!si) debugf("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort); // normal if registration failed - } - } - } -} - -mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t unusedserver, mach_port_t client, - DNSCString name, DNSCString regtype, DNSCString domain, IPPort IpPort, DNSCString txtRecord) -{ - (void)unusedserver; // Unused - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - - // older versions of this code passed the port via mach IPC as an int. - // we continue to pass it as 4 bytes to maintain binary compatibility, - // but now ensure that the network byte order is preserved by using a struct - mDNSIPPort port; - port.b[0] = IpPort.bytes[2]; - port.b[1] = IpPort.bytes[3]; - - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; } - - // Check for sub-types after the service type - size_t reglen = strlen(regtype) + 1; - if (reglen > MAX_ESCAPED_DOMAIN_NAME) { errormsg = "reglen too long"; goto badparam; } - mDNSs32 NumSubTypes = ChopSubTypes(regtype, mDNSNULL); // Note: Modifies regtype string to remove trailing subtypes - if (NumSubTypes < 0) { errormsg = "Bad Service SubType"; goto badparam; } - - // Check other parameters - domainlabel n; - domainname t, d; - domainname srv; - if (!name[0]) n = mDNSStorage.nicelabel; - else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; } - if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } - if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Bad Domain"; goto badparam; } - if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } - - unsigned char txtinfo[1024] = ""; - unsigned int data_len = 0; - unsigned int size = sizeof(RDataBody); - unsigned char *pstring = &txtinfo[data_len]; - char *ptr = txtRecord; - - // The OS X DNSServiceRegistrationCreate() API is defined using a C-string, - // but the mDNS_RegisterService() call actually requires a packed block of P-strings. - // Hence we have to convert the C-string to a P-string. - // ASCII-1 characters are allowed in the C-string as boundary markers, - // so that a single C-string can be used to represent one or more P-strings. - while (*ptr) - { - if (++data_len >= sizeof(txtinfo)) { errormsg = "TXT record too long"; goto badtxt; } - if (*ptr == 1) // If this is our boundary marker, start a new P-string - { - pstring = &txtinfo[data_len]; - pstring[0] = 0; - ptr++; - } - else - { - if (pstring[0] == 255) { errormsg = "TXT record invalid (component longer than 255)"; goto badtxt; } - pstring[++pstring[0]] = *ptr++; - } - } - - data_len++; - if (size < data_len) - size = data_len; - - // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with - // a port number of zero. When two instances of the protected client are allowed to run on one - // machine, we don't want to see misleading "Bogus client" messages in syslog and the console. - if (!mDNSIPPortIsZero(port)) - { - int count = CountExistingRegistrations(&srv, port); - if (count) - LogMsg("%5d: Client application registered %d identical instances of service %##s port %u.", - client, count+1, srv.c, mDNSVal16(port)); - } - - // Allocate memory, and handle failure - DNSServiceRegistration *x = mallocL("DNSServiceRegistration", sizeof(*x)); - if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - mDNSPlatformMemZero(x, sizeof(*x)); - - // Set up object, and link into list - x->ClientMachPort = client; - x->DefaultDomain = !domain[0]; - x->autoname = (!name[0]); - x->rdsize = size; - x->NumSubTypes = NumSubTypes; - memcpy(x->regtype, regtype, reglen); - x->name = n; - x->type = t; - x->port = port; - memcpy(x->txtinfo, txtinfo, 1024); - x->txt_len = data_len; - x->NextRef = 0; - x->regs = NULL; - - x->next = DNSServiceRegistrationList; - DNSServiceRegistrationList = x; - - LogOperation("%5d: DNSServiceRegistration(\"%s\", \"%s\", \"%s\", %u) START", - x->ClientMachPort, name, regtype, domain, mDNSVal16(port)); - - err = AddServiceInstance(x, &d); - if (err) { AbortClient(client, x); errormsg = "mDNS_RegisterService"; goto fail; } // bail if .local (or explicit domain) fails - - if (x->DefaultDomain) - { - DNameListElem *p; - for (p = AutoRegistrationDomains; p; p = p->next) - AddServiceInstance(x, &p->name); - } - - // Succeeded: Wrap up and return - EnableDeathNotificationForClient(client, x); - return(mStatus_NoError); - -badtxt: - LogMsg("%5d: TXT record: %.100s...", client, txtRecord); -badparam: - err = mStatus_BadParamErr; -fail: - LogMsg("%5d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", %d) failed: %s (%d)", - client, name, regtype, domain, mDNSVal16(port), errormsg, err); - return(err); -} - mDNSlocal void mDNSPreferencesSetNames(mDNS *const m, int key, domainlabel *old, domainlabel *new) { domainlabel *prevold, *prevnew; @@ -1367,234 +363,11 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result) mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel); mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel); - // First we check our list of old Mach-based registered services, to see if any need to be updated to a new name - DNSServiceRegistration *r; - for (r = DNSServiceRegistrationList; r; r=r->next) - if (r->autoname) - { - ServiceInstance *si; - for (si = r->regs; si; si = si->next) - { - if (!SameDomainLabelCS(si->name.c, m->nicelabel.c)) - { - debugf("NetworkChanged renaming %##s to %#s", si->srs.RR_SRV.resrec.name->c, m->nicelabel.c); - si->renameonmemfree = mDNStrue; - if (mDNS_DeregisterService_drt(m, &si->srs, mDNS_Dereg_rapid)) - RegCallback(m, &si->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately - } - } - } - // Then we call into the UDS daemon code, to let it do the same udsserver_handle_configchange(m); } } -//************************************************************************************************************* -// Add / Update / Remove records from existing Registration - -mDNSexport kern_return_t provide_DNSServiceRegistrationAddRecord_rpc(mach_port_t unusedserver, mach_port_t client, - int type, const char *data, mach_msg_type_number_t data_len, uint32_t ttl, natural_t *reference) -{ - // Check client parameter - uint32_t id; - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - DNSServiceRegistration *x = DNSServiceRegistrationList; - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - ServiceInstance *si; - size_t size; - (void)unusedserver; // Unused - while (x && x->ClientMachPort != client) x = x->next; - if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; } - - // Check other parameters - if (data_len > 8192) { err = mStatus_BadParamErr; errormsg = "data_len > 8K"; goto fail; } - if (data_len > sizeof(RDataBody)) size = data_len; - else size = sizeof(RDataBody); - - id = x->NextRef++; - *reference = (natural_t)id; - for (si = x->regs; si; si = si->next) - { - // Allocate memory, and handle failure - ExtraResourceRecord *extra = mallocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + size); - if (!extra) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - - // Fill in type, length, and data of new record - extra->r.resrec.rrtype = type; - extra->r.rdatastorage.MaxRDLength = size; - extra->r.resrec.rdlength = data_len; - memcpy(&extra->r.rdatastorage.u.data, data, data_len); - - // Do the operation - LogOperation("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) REF %p", - client, si->srs.RR_SRV.resrec.name->c, type, data_len, extra); - err = mDNS_AddRecordToService(&mDNSStorage, &si->srs, extra, &extra->r.rdatastorage, ttl, 0); - - if (err) - { - freeL("Extra Resource Record", extra); - errormsg = "mDNS_AddRecordToService"; - goto fail; - } - - extra->ClientID = id; - } - - return mStatus_NoError; - -fail: - LogMsg("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) failed: %s (%d)", client, x ? x->name.c : (mDNSu8*)"\x8" "«NULL»", type, data_len, errormsg, err); - return mStatus_UnknownErr; -} - -mDNSlocal void UpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen) -{ - (void)m; // Unused - (void)OldRDLen; // Unused - if (OldRData != &rr->rdatastorage) - freeL("Old RData", OldRData); -} - -mDNSlocal mStatus UpdateRecord(ServiceRecordSet *srs, mach_port_t client, AuthRecord *rr, const char *data, mach_msg_type_number_t data_len, uint32_t ttl) -{ - // Check client parameter - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - const domainname *name = (const domainname *)""; - - name = srs->RR_SRV.resrec.name; - - unsigned int size = sizeof(RDataBody); - if (size < data_len) - size = data_len; - - // Allocate memory, and handle failure - RData *newrdata = mallocL("RData", sizeof(*newrdata) - sizeof(RDataBody) + size); - if (!newrdata) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - - // Fill in new length, and data - newrdata->MaxRDLength = size; - memcpy(&newrdata->u, data, data_len); - - // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, - // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s". - // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. - if (rr->resrec.rrtype == kDNSType_TXT && data_len == 0) { data_len = 1; newrdata->u.txt.c[0] = 0; } - - // Do the operation - LogOperation("%5d: DNSServiceRegistrationUpdateRecord(%##s, new length %d)", - client, srs->RR_SRV.resrec.name->c, data_len); - - err = mDNS_Update(&mDNSStorage, rr, ttl, data_len, newrdata, UpdateCallback); - if (err) - { - errormsg = "mDNS_Update"; - freeL("RData", newrdata); - goto fail; - } - return(mStatus_NoError); - -fail: - LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %d) failed: %s (%d)", client, name->c, data_len, errormsg, err); - return(err); -} - -mDNSexport kern_return_t provide_DNSServiceRegistrationUpdateRecord_rpc(mach_port_t unusedserver, mach_port_t client, - natural_t reference, const char *data, mach_msg_type_number_t data_len, uint32_t ttl) -{ - // Check client parameter - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - const domainname *name = (const domainname *)""; - ServiceInstance *si; - - (void)unusedserver; // unused - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - DNSServiceRegistration *x = DNSServiceRegistrationList; - while (x && x->ClientMachPort != client) x = x->next; - if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; } - - // Check other parameters - if (data_len > 8192) { err = mStatus_BadParamErr; errormsg = "data_len > 8K"; goto fail; } - - for (si = x->regs; si; si = si->next) - { - AuthRecord *r = NULL; - - // Find the record we're updating. NULL reference means update the primary TXT record - if (!reference) r = &si->srs.RR_TXT; - else - { - ExtraResourceRecord *ptr; - for (ptr = si->srs.Extras; ptr; ptr = ptr->next) - { - if ((natural_t)ptr->ClientID == reference) - { r = &ptr->r; break; } - } - if (!r) { err = mStatus_BadReferenceErr; errormsg = "No such record"; goto fail; } - } - err = UpdateRecord(&si->srs, client, r, data, data_len, ttl); - if (err) goto fail; //!!!KRS this will cause failures for non-local defaults! - } - - return mStatus_NoError; - -fail: - LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %X, %d) failed: %s (%d)", client, name->c, reference, data_len, errormsg, err); - return(err); -} - -mDNSlocal mStatus RemoveRecord(ServiceRecordSet *srs, ExtraResourceRecord *extra, mach_port_t client) -{ - const domainname *const name = srs->RR_SRV.resrec.name; - mStatus err = mStatus_NoError; - - // Do the operation - LogOperation("%5d: DNSServiceRegistrationRemoveRecord(%##s)", client, srs->RR_SRV.resrec.name->c); - - err = mDNS_RemoveRecordFromService(&mDNSStorage, srs, extra, FreeExtraRR, extra); - if (err) LogMsg("%5d: DNSServiceRegistrationRemoveRecord (%##s) failed: %d", client, name->c, err); - - return err; -} - -mDNSexport kern_return_t provide_DNSServiceRegistrationRemoveRecord_rpc(mach_port_t unusedserver, mach_port_t client, - natural_t reference) -{ - // Check client parameter - (void)unusedserver; // Unused - mStatus err = mStatus_NoError; - const char *errormsg = "Unknown"; - if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; } - DNSServiceRegistration *x = DNSServiceRegistrationList; - ServiceInstance *si; - - while (x && x->ClientMachPort != client) x = x->next; - if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; } - - for (si = x->regs; si; si = si->next) - { - ExtraResourceRecord *e; - for (e = si->srs.Extras; e; e = e->next) - { - if ((natural_t)e->ClientID == reference) - { - err = RemoveRecord(&si->srs, e, client); - if (err) { errormsg = "RemoveRecord failed"; goto fail; } - break; - } - } - if (!e) { err = mStatus_BadReferenceErr; errormsg = "No such reference"; goto fail; } - } - - return mStatus_NoError; - -fail: - LogMsg("%5d: DNSServiceRegistrationRemoveRecord(%X) failed: %s (%d)", client, reference, errormsg, err); - return(err); -} //************************************************************************************************************* #if COMPILER_LIKES_PRAGMA_MARK @@ -1607,16 +380,6 @@ mDNSlocal void ExitCallback(int sig) (void)sig; // Unused LogMsg("%s stopping", mDNSResponderVersionString); - debugf("ExitCallback: Aborting MIG clients"); - while (DNSServiceDomainEnumerationList) - AbortClient(DNSServiceDomainEnumerationList->ClientMachPort, DNSServiceDomainEnumerationList); - while (DNSServiceBrowserList) - AbortClient(DNSServiceBrowserList->ClientMachPort, DNSServiceBrowserList); - while (DNSServiceResolverList) - AbortClient(DNSServiceResolverList->ClientMachPort, DNSServiceResolverList); - while (DNSServiceRegistrationList) - AbortClient(DNSServiceRegistrationList->ClientMachPort, DNSServiceRegistrationList); - if (udsserver_exit() < 0) LogMsg("ExitCallback: udsserver_exit failed"); @@ -1626,99 +389,6 @@ mDNSlocal void ExitCallback(int sig) #ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM -mDNSlocal void DNSserverCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) -{ - mig_reply_error_t *request = msg; - mig_reply_error_t *reply; - mach_msg_return_t mr; - int options; - (void)port; // Unused - (void)size; // Unused - (void)info; // Unused - - KQueueLock(&mDNSStorage); - - /* allocate a reply buffer */ - reply = CFAllocatorAllocate(NULL, provide_DNSServiceDiscoveryRequest_subsystem.maxsize, 0); - - /* call the MiG server routine */ - (void) DNSServiceDiscoveryRequest_server(&request->Head, &reply->Head); - - if (!(reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (reply->RetCode != KERN_SUCCESS)) - { - if (reply->RetCode == MIG_NO_REPLY) - { - /* - * This return code is a little tricky -- it appears that the - * demux routine found an error of some sort, but since that - * error would not normally get returned either to the local - * user or the remote one, we pretend it's ok. - */ - CFAllocatorDeallocate(NULL, reply); - goto done; - } - - /* - * destroy any out-of-line data in the request buffer but don't destroy - * the reply port right (since we need that to send an error message). - */ - request->Head.msgh_remote_port = MACH_PORT_NULL; - mach_msg_destroy(&request->Head); - } - - if (reply->Head.msgh_remote_port == MACH_PORT_NULL) - { - /* no reply port, so destroy the reply */ - if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) - mach_msg_destroy(&reply->Head); - CFAllocatorDeallocate(NULL, reply); - goto done; - } - - /* - * send reply. - * - * We don't want to block indefinitely because the client - * isn't receiving messages from the reply port. - * If we have a send-once right for the reply port, then - * this isn't a concern because the send won't block. - * If we have a send right, we need to use MACH_SEND_TIMEOUT. - * To avoid falling off the kernel's fast RPC path unnecessarily, - * we only supply MACH_SEND_TIMEOUT when absolutely necessary. - */ - - options = MACH_SEND_MSG; - if (MACH_MSGH_BITS_REMOTE(reply->Head.msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE) - options |= MACH_SEND_TIMEOUT; - - mr = mach_msg(&reply->Head, /* msg */ - options, /* option */ - reply->Head.msgh_size, /* send_size */ - 0, /* rcv_size */ - MACH_PORT_NULL, /* rcv_name */ - MACH_MSG_TIMEOUT_NONE, /* timeout */ - MACH_PORT_NULL); /* notify */ - - /* Has a message error occurred? */ - switch (mr) - { - case MACH_SEND_INVALID_DEST: - case MACH_SEND_TIMED_OUT: - /* the reply can't be delivered, so destroy it */ - mach_msg_destroy(&reply->Head); - break; - - default: - /* Includes success case. */ - break; - } - - CFAllocatorDeallocate(NULL, reply); - -done: - KQueueUnlock(&mDNSStorage, "Mach client event"); -} - // Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit mDNSlocal void HandleSIG(int sig) { @@ -1744,7 +414,7 @@ mDNSlocal void HandleSIG(int sig) #endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM -mDNSlocal void INFOCallback(void) +mDNSexport void INFOCallback(void) { mDNSs32 utc = mDNSPlatformUTC(); const mDNSs32 now = mDNS_TimeNow(&mDNSStorage); @@ -1752,11 +422,6 @@ mDNSlocal void INFOCallback(void) DNSServer *s; McastResolver *mr; - // Create LoggerID(Key)->com.apple.networking.mDNSResponder(Value) pair when SIGINFO is received. - // This key-value pair is used as a condition by syslogd to Log to com.apple.networking.mDNSResponder.log file - // present in /etc/asl/com.apple.networking.mDNSResponder. - asl_set(log_msg, "LoggerID", "com.apple.networking.mDNSResponder"); - LogMsg("---- BEGIN STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers); udsserver_info(&mDNSStorage); @@ -1821,14 +486,10 @@ mDNSlocal void INFOCallback(void) for (s = mDNSStorage.DNSServers; s; s = s->next) { NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(&mDNSStorage, s->interface); - LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s %s", + LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s", s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port), s->penaltyTime ? s->penaltyTime - mDNS_TimeNow(&mDNSStorage) : 0, DNSScopeToString(s->scoped), s->timeout, s->resGroupID, - s->teststate == DNSServer_Untested ? "(Untested)" : - s->teststate == DNSServer_Passed ? "" : - s->teststate == DNSServer_Failed ? "(Failed)" : - s->teststate == DNSServer_Disabled ? "(Disabled)" : "(Unknown state)", s->req_A ? "v4" : "!v4", s->req_AAAA ? "v6" : "!v6", s->cellIntf ? "cell" : "!cell", @@ -1848,75 +509,40 @@ mDNSlocal void INFOCallback(void) LogMsgNoIdent("Mcast Resolver %##s timeout %u", mr->domain.c, mr->timeout); } + LogMsgNoIdent("------------ Hostnames -------------"); + if (!mDNSStorage.Hostnames) LogMsgNoIdent("<None>"); + else + { + HostnameInfo *hi; + for (hi = mDNSStorage.Hostnames; hi; hi = hi->next) + { + LogMsgNoIdent("%##s v4 %d %s", hi->fqdn.c, hi->arv4.state, ARDisplayString(&mDNSStorage, &hi->arv4)); + LogMsgNoIdent("%##s v6 %d %s", hi->fqdn.c, hi->arv6.state, ARDisplayString(&mDNSStorage, &hi->arv6)); + } + } + + LogMsgNoIdent("--------------- FQDN ---------------"); + if (!mDNSStorage.FQDN.c[0]) LogMsgNoIdent("<None>"); + else + { + LogMsgNoIdent("%##s", mDNSStorage.FQDN.c); + } + #if TARGET_OS_EMBEDDED LogMetrics(); #endif LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now); LogMsg("---- END STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers); - - // If logging is disabled, only then clear the key we set at the top of this func - if (!mDNS_LoggingEnabled) - asl_unset(log_msg, "LoggerID"); } -mDNSlocal void DebugSetFilter() -{ - if (!log_client) - return; - - // When USR1 is turned on, we log only the LOG_WARNING and LOG_NOTICE messages by default. - // The user has to manually do "syslog -c mDNSResponder -i" to get the LOG_INFO messages - // also to be logged. Most of the times, we need the INFO level messages for debugging. - // Hence, we set the filter to INFO level when USR1 logging is turned on to avoid - // having the user to do this extra step manually. - - if (mDNS_LoggingEnabled) - { - asl_set_filter(log_client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO)); - asl_set(log_msg, "LoggerID", "com.apple.networking.mDNSResponder"); - // Create LoggerID(Key)->com.apple.networking.mDNSResponder(Value) pair when USR1 Logging is Enabled. - // This key-value pair is used as a condition by syslogd to Log to com.apple.networking.mDNSResponder.log file - // present in /etc/asl/com.apple.networking.mDNSResponder. - } - else - { - asl_set_filter(log_client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_ERR)); - asl_unset(log_msg, "LoggerID"); - // Clear the key-value pair when USR1 Logging is Disabled, as we do not want to log to - // com.apple.networking.mDNSResponder.log file in this case. - } -} mDNSexport void mDNSPlatformLogToFile(int log_level, const char *buffer) { - int asl_level = ASL_LEVEL_ERR; - - if (!log_client) - { - syslog(log_level, "%s", buffer); - return; - } - switch (log_level) - { - case LOG_ERR: - asl_level = ASL_LEVEL_ERR; - break; - case LOG_WARNING: - asl_level = ASL_LEVEL_WARNING; - break; - case LOG_NOTICE: - asl_level = ASL_LEVEL_NOTICE; - break; - case LOG_INFO: - asl_level = ASL_LEVEL_INFO; - break; - case LOG_DEBUG: - asl_level = ASL_LEVEL_DEBUG; - break; - default: - break; - } - asl_log(log_client, log_msg, asl_level, "%s", buffer); + if (!log_general) + os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in init_logging()"); + else + os_log_with_type(log_general, log_level, "%s", buffer); + } // Writes the state out to the dynamic store and also affects the ASL filter level @@ -1970,35 +596,9 @@ mDNSexport void UpdateDebugState() CFRelease(numZero); mDNSDynamicStoreSetConfig(kmDNSDebugState, mDNSNULL, dict); CFRelease(dict); - // If we turned off USR1 logging, we need to reset the filter - DebugSetFilter(); -} -#if TARGET_OS_EMBEDDED -mDNSlocal void Prefschanged() -{ - mDNSBool mDNSProf_installed; - LogMsg("Prefschanged: mDNSResponder Managed Preferences have changed"); - mDNSProf_installed = GetmDNSManagedPref(kmDNSEnableLoggingStr); - dispatch_async(dispatch_get_main_queue(), - ^{ - if (mDNSProf_installed) - { - mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 1; - } - else - { - LogMsg("Prefschanged: mDNSDebugProfile is uninstalled -> Turning OFF USR1/USR2 Logging with SIGINFO o/p"); - INFOCallback(); - mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0; - } - UpdateDebugState(); - // If Logging Enabled: Start Logging to com.apple.networking.mDNSResponder.log (has to be LogInfo) - LogInfo("Prefschanged: mDNSDebugProfile is installed -> Turned ON USR1/USR2 Logging"); - }); - return; } -#endif //TARGET_OS_EMBEDDED + #ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM @@ -2031,15 +631,26 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void case SIGINT: case SIGTERM: ExitCallback(msg_header->msgh_id); break; case SIGINFO: INFOCallback(); break; - case SIGUSR1: mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1; + case SIGUSR1: +#if APPLE_OSX_mDNSResponder + mDNS_LoggingEnabled = 1; + LogMsg("SIGUSR1: Logging %s on Apple Platforms", mDNS_LoggingEnabled ? "Enabled" : "Disabled"); +#else + mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1; LogMsg("SIGUSR1: Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled"); +#endif WatchDogReportingThreshold = mDNS_LoggingEnabled ? 50 : 250; UpdateDebugState(); - // If Logging Enabled: Start Logging to com.apple.networking.mDNSResponder.log - LogInfo("USR1 Logging Enabled: Start Logging to mDNSResponder Log file"); + LogInfo("USR1 Logging Enabled"); break; - case SIGUSR2: mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1; + case SIGUSR2: +#if APPLE_OSX_mDNSResponder + mDNS_PacketLoggingEnabled = 1; + LogMsg("SIGUSR2: Packet Logging %s on Apple Platforms", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); +#else + mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1; LogMsg("SIGUSR2: Packet Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); +#endif mDNS_McastTracingEnabled = (mDNS_PacketLoggingEnabled && mDNS_McastLoggingEnabled) ? mDNStrue : mDNSfalse; LogInfo("SIGUSR2: Multicast Tracing is %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled"); UpdateDebugState(); @@ -2065,37 +676,24 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void mDNSlocal kern_return_t mDNSDaemonInitialize(void) { mStatus err; - CFMachPortRef s_port; - CFRunLoopSourceRef s_rls; - CFRunLoopSourceRef d_rls; - - s_port = CFMachPortCreateWithPort(NULL, m_port, DNSserverCallback, NULL, NULL); - CFMachPortRef d_port = CFMachPortCreate(NULL, ClientDeathCallback, NULL, NULL); err = mDNS_Init(&mDNSStorage, &PlatformStorage, rrcachestorage, RR_CACHE_SIZE, - advertise, + !NoMulticastAdvertisements, mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext); - if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); } - - client_death_port = CFMachPortGetPort(d_port); - - s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0); - CFRunLoopAddSource(PlatformStorage.CFRunLoop, s_rls, kCFRunLoopDefaultMode); - CFRelease(s_rls); - - d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0); - CFRunLoopAddSource(PlatformStorage.CFRunLoop, d_rls, kCFRunLoopDefaultMode); - CFRelease(d_rls); + if (err) + { + LogMsg("Daemon start: mDNS_Init failed %d", err); + return(err); + } CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL); CFRunLoopSourceRef i_rls = CFMachPortCreateRunLoopSource(NULL, i_port, 0); signal_port = CFMachPortGetPort(i_port); - CFRunLoopAddSource(PlatformStorage.CFRunLoop, i_rls, kCFRunLoopDefaultMode); + CFRunLoopAddSource(CFRunLoopGetMain(), i_rls, kCFRunLoopDefaultMode); CFRelease(i_rls); - - if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port); + return(err); } @@ -2162,28 +760,21 @@ mDNSlocal void mDNSSetupSignal(dispatch_queue_t queue, int sig) } } -// On 10.2 the MachServerName is DNSServiceDiscoveryServer -// On 10.3 and later, the MachServerName is com.apple.mDNSResponder mDNSlocal kern_return_t mDNSDaemonInitialize(void) { mStatus err; - dispatch_source_t mach_source; dispatch_queue_t queue = dispatch_get_main_queue(); err = mDNS_Init(&mDNSStorage, &PlatformStorage, rrcachestorage, RR_CACHE_SIZE, - advertise, + !NoMulticastAdvertisements, mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext); - if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); } - - mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, m_port, 0, queue); - if (mach_source == mDNSNULL) {LogMsg("mDNSDaemonInitialize: Error creating source for m_port"); return -1;} - dispatch_source_set_event_handler(mach_source, ^{ - dispatch_mig_server(mach_source, sizeof(union __RequestUnion__DNSServiceDiscoveryReply_subsystem), - DNSServiceDiscoveryRequest_server); - }); - dispatch_resume(mach_source); + if (err) + { + LogMsg("Daemon start: mDNS_Init failed %d", err); + return(err); + } mDNSSetupSignal(queue, SIGHUP); mDNSSetupSignal(queue, SIGINT); @@ -2215,7 +806,6 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void) LogMsg("DaemonIntialize done successfully"); - if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port); return(err); } @@ -2245,7 +835,11 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m) // we then systematically lose our own looped-back packets. if (m->NetworkChanged && now - m->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m); - if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0) { m->p->RequestReSleep = 0; mDNSPowerRequest(0, 0); } + if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0) + { + m->p->RequestReSleep = 0; + mDNSPowerRequest(0, 0); + } // 3. Call mDNS_Execute() to let mDNSCore do what it needs to do mDNSs32 nextevent = mDNS_Execute(m); @@ -2262,61 +856,7 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m) if (nextevent - m->p->RequestReSleep > 0) nextevent = m->p->RequestReSleep; - // 4. Deliver any waiting browse messages to clients - DNSServiceBrowser *b = DNSServiceBrowserList; - - while (b) - { - // Note: Need to advance b to the next element BEFORE we call DeliverInstance(), because in the - // event that the client Mach queue overflows, DeliverInstance() will call AbortBlockedClient() - // and that will cause the DNSServiceBrowser object's memory to be freed before it returns - DNSServiceBrowser *x = b; - b = b->next; - if (x->results) // Try to deliver the list of results - { - while (x->results) - { - DNSServiceBrowserResult *const r = x->results; - domainlabel name; - domainname type, domain; - DeconstructServiceName(&r->result, &name, &type, &domain); // Don't need to check result; already validated in FoundInstance() - char cname[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL. - char ctype[MAX_ESCAPED_DOMAIN_NAME]; - char cdom [MAX_ESCAPED_DOMAIN_NAME]; - ConvertDomainLabelToCString_unescaped(&name, cname); - ConvertDomainNameToCString(&type, ctype); - ConvertDomainNameToCString(&domain, cdom); - DNSServiceDiscoveryReplyFlags flags = (r->next) ? DNSServiceDiscoverReplyFlagsMoreComing : 0; - kern_return_t status = DNSServiceBrowserReply_rpc(x->ClientMachPort, r->resultType, cname, ctype, cdom, flags, 1); - // If we failed to send the mach message, try again in one second - if (status == MACH_SEND_TIMED_OUT) - { - if (nextevent - now > mDNSPlatformOneSecond) - nextevent = now + mDNSPlatformOneSecond; - break; - } - else - { - x->lastsuccess = now; - x->results = x->results->next; - freeL("DNSServiceBrowserResult", r); - } - } - // If this client hasn't read a single message in the last 60 seconds, abort it - if (now - x->lastsuccess >= 60 * mDNSPlatformOneSecond) - AbortBlockedClient(x->ClientMachPort, "browse", x); - } - } - - DNSServiceResolver *l; - for (l = DNSServiceResolverList; l; l=l->next) - if (l->ReportTime && now - l->ReportTime >= 0) - { - l->ReportTime = 0; - LogMsgNoIdent("Client application bug: DNSServiceResolver(%##s) active for over two minutes. " - "This places considerable burden on the network.", l->i.name.c); - } - + if (m->p->NotifyUser) { if (m->p->NotifyUser - now < 0) @@ -2488,7 +1028,8 @@ mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now) // so we should put it back to sleep. To avoid frustrating the user, we always request at least // 60 seconds sleep, so if they immediately re-wake the system within seconds of it going to sleep, // we then shouldn't hit our 30-second window, and we won't attempt to re-sleep the machine. - if (interval < 60) interval = 60; + if (interval < 60) + interval = 60; result = mDNSPowerRequest(1, interval); @@ -2683,7 +1224,7 @@ mDNSlocal void * KQueueLoop(void *m_param) LogInfo("WARNING: Idle task took %dms to complete", end - start); #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 - validatelists(m, true); + validatelists(m); #endif mDNSs32 now = mDNS_TimeNow(m); @@ -2810,44 +1351,109 @@ mDNSlocal void * KQueueLoop(void *m_param) #endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM -mDNSlocal void LaunchdCheckin(void) +mDNSlocal size_t LaunchdCheckin(void) { // Ask launchd for our socket int result = launch_activate_socket("Listeners", &launchd_fds, &launchd_fds_count); if (result != 0) { LogMsg("launch_activate_socket() failed errno %d (%s)", errno, strerror(errno)); } + return launchd_fds_count; +} + + +extern int sandbox_init(const char *profile, uint64_t flags, char **errorbuf) __attribute__((weak_import)); + +#if APPLE_OSX_mDNSResponder +mDNSlocal mDNSBool PreferencesGetValueBool(CFStringRef key, mDNSBool defaultValue) +{ + CFBooleanRef boolean; + mDNSBool result = defaultValue; + + boolean = CFPreferencesCopyAppValue(key, kProgramArguments); + if (boolean) + { + if (CFGetTypeID(boolean) == CFBooleanGetTypeID()) + result = CFBooleanGetValue(boolean) ? mDNStrue : mDNSfalse; + CFRelease(boolean); + } + + return result; } -static mach_port_t RegisterMachService(const char *service_name) +mDNSlocal int PreferencesGetValueInt(CFStringRef key, int defaultValue) { - mach_port_t port = MACH_PORT_NULL; - kern_return_t kr; - - if (KERN_SUCCESS != (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port))) - { - LogMsg("RegisterMachService: %d %X %s", kr, kr, mach_error_string(kr)); - return MACH_PORT_NULL; - } - - if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) - { - LogMsg("RegisterMachService: %d %X %s", kr, kr, mach_error_string(kr)); - mach_port_deallocate(mach_task_self(), port); - return MACH_PORT_NULL; - } - - return port; + CFNumberRef number; + int numberValue; + int result = defaultValue; + + number = CFPreferencesCopyAppValue(key, kProgramArguments); + if (number) + { + if ((CFGetTypeID(number) == CFNumberGetTypeID()) && CFNumberGetValue(number, kCFNumberIntType, &numberValue)) + result = numberValue; + CFRelease(number); + } + + return result; } +#endif -extern int sandbox_init(const char *profile, uint64_t flags, char **errorbuf) __attribute__((weak_import)); +mDNSlocal void SandboxProcess(void) +{ + // Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb +#if MDNS_NO_SANDBOX + LogMsg("Note: Compiled without Apple Sandbox support"); +#else // MDNS_NO_SANDBOX + if (!sandbox_init) + LogMsg("Note: Running without Apple Sandbox support (not available on this OS)"); + else + { + char *sandbox_msg; + uint64_t sandbox_flags = SANDBOX_NAMED; + + (void)confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0); + + int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg); + if (sandbox_err) + { + LogMsg("WARNING: sandbox_init error %s", sandbox_msg); + // If we have errors in the sandbox during development, to prevent + // exiting, uncomment the following line. + //sandbox_free_error(sandbox_msg); + + errx(EX_OSERR, "sandbox_init() failed: %s", sandbox_msg); + } + else LogInfo("Now running under Apple Sandbox restrictions"); + } +#endif // MDNS_NO_SANDBOX +} + +#if APPLE_OSX_mDNSResponder +mDNSlocal void init_logging(void) +{ + log_general = os_log_create("com.apple.mDNSResponder", "AllINFO"); + + if (!log_general) + { + // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category + os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponder"); + } +} +#endif mDNSexport int main(int argc, char **argv) { int i; kern_return_t status; - log_client = asl_open(NULL, "mDNSResponder", 0); - log_msg = asl_new(ASL_TYPE_MSG); - +#if DEBUG + bool useDebugSocket = mDNSfalse; + bool useSandbox = mDNStrue; +#endif + +#if APPLE_OSX_mDNSResponder + init_logging(); +#endif + mDNSMacOSXSystemBuildNumber(NULL); LogMsg("%s starting %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers); @@ -2872,7 +1478,7 @@ mDNSexport int main(int argc, char **argv) for (i=1; i<argc; i++) { if (!strcasecmp(argv[i], "-d" )) mDNS_DebugMode = mDNStrue; - if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) advertise = mDNS_Init_DontAdvertiseLocalAddresses; + if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) NoMulticastAdvertisements = mDNStrue; if (!strcasecmp(argv[i], "-DisableSleepProxyClient" )) DisableSleepProxyClient = mDNStrue; if (!strcasecmp(argv[i], "-DebugLogging" )) mDNS_LoggingEnabled = mDNStrue; if (!strcasecmp(argv[i], "-UnicastPacketLogging" )) mDNS_PacketLoggingEnabled = mDNStrue; @@ -2882,10 +1488,14 @@ mDNSexport int main(int argc, char **argv) UseInternalSleepProxy = (i+1<argc && mDNSIsDigit(argv[i+1][0]) && argv[i+1][1]==0) ? atoi(argv[++i]) : 1; if (!strcasecmp(argv[i], "-StrictUnicastOrdering" )) StrictUnicastOrdering = mDNStrue; if (!strcasecmp(argv[i], "-AlwaysAppendSearchDomains")) AlwaysAppendSearchDomains = mDNStrue; +#if DEBUG + if (!strcasecmp(argv[i], "-UseDebugSocket")) useDebugSocket = mDNStrue; + if (!strcasecmp(argv[i], "-NoSandbox")) useSandbox = mDNSfalse; +#endif } -#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED +#if APPLE_OSX_mDNSResponder /* Reads the external user's program arguments for mDNSResponder starting 10.11.x(El Capitan) on OSX. The options for external user are: DebugLogging, UnicastPacketLogging, NoMulticastAdvertisements, StrictUnicastOrdering and AlwaysAppendSearchDomains @@ -2904,51 +1514,27 @@ mDNSexport int main(int argc, char **argv) 1] sudo defaults read /Library/Preferences/com.apple.mDNSResponder.plist */ - CFBooleanRef enabled = NULL; - - enabled = CFPreferencesCopyValue(kDebugLogging, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - if (enabled != NULL) - { - if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled)) - mDNS_LoggingEnabled = mDNStrue; - CFRelease(enabled); - } - - enabled = CFPreferencesCopyValue(kUnicastPacketLogging, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - if (enabled != NULL) - { - if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled)) - mDNS_PacketLoggingEnabled = mDNStrue; - CFRelease(enabled); - } - - enabled = CFPreferencesCopyValue(kNoMulticastAdvertisements, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - if (enabled != NULL) - { - if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled)) - advertise = mDNS_Init_DontAdvertiseLocalAddresses; - CFRelease(enabled); - } - - enabled = CFPreferencesCopyValue(kStrictUnicastOrdering, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - if (enabled != NULL) - { - if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled)) - StrictUnicastOrdering = mDNStrue; - CFRelease(enabled); - } - - enabled = CFPreferencesCopyValue(kAlwaysAppendSearchDomains, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - if (enabled != NULL) - { - if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled)) - AlwaysAppendSearchDomains = mDNStrue; - CFRelease(enabled); - } + +// Currently on Fuji/Whitetail releases we are keeping the logging always enabled. +// Hence mDNS_LoggingEnabled and mDNS_PacketLoggingEnabled is set to true below by default. +#if 0 + mDNS_LoggingEnabled = PreferencesGetValueBool(kPreferencesKey_DebugLogging, mDNS_LoggingEnabled); + mDNS_PacketLoggingEnabled = PreferencesGetValueBool(kPreferencesKey_UnicastPacketLogging, mDNS_PacketLoggingEnabled); +#endif + + mDNS_LoggingEnabled = mDNStrue; + mDNS_PacketLoggingEnabled = mDNStrue; + + NoMulticastAdvertisements = PreferencesGetValueBool(kPreferencesKey_NoMulticastAdvertisements, NoMulticastAdvertisements); + StrictUnicastOrdering = PreferencesGetValueBool(kPreferencesKey_StrictUnicastOrdering, StrictUnicastOrdering); + AlwaysAppendSearchDomains = PreferencesGetValueBool(kPreferencesKey_AlwaysAppendSearchDomains, AlwaysAppendSearchDomains); + OfferSleepProxyService = PreferencesGetValueInt(kPreferencesKey_OfferSleepProxyService, OfferSleepProxyService); + UseInternalSleepProxy = PreferencesGetValueInt(kPreferencesKey_UseInternalSleepProxy, UseInternalSleepProxy); + EnableBLEBasedDiscovery = PreferencesGetValueBool(kPreferencesKey_EnableBLEBasedDiscovery, EnableBLEBasedDiscovery); #endif // Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure - if (!advertise) + if (NoMulticastAdvertisements) LogMsg("-NoMulticastAdvertisements is set: Administratively prohibiting multicast advertisements"); if (AlwaysAppendSearchDomains) LogMsg("-AlwaysAppendSearchDomains is set"); @@ -2972,7 +1558,16 @@ mDNSexport int main(int argc, char **argv) mDNSStorage.p = &PlatformStorage; // Make sure mDNSStorage.p is set up, because validatelists uses it // Need to Start XPC Server Before LaunchdCheckin() (Reason: rdar11023750) xpc_server_init(); +#if DEBUG + if (!useDebugSocket) { + if (LaunchdCheckin() == 0) + useDebugSocket = mDNStrue; + } + if (useDebugSocket) + SetDebugBoundPath(); +#else LaunchdCheckin(); +#endif #ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM @@ -2997,40 +1592,10 @@ mDNSexport int main(int argc, char **argv) #endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM - // Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb -#if MDNS_NO_SANDBOX - LogMsg("Note: Compiled without Apple Sandbox support"); -#else // MDNS_NO_SANDBOX - if (!sandbox_init) - LogMsg("Note: Running without Apple Sandbox support (not available on this OS)"); - else - { - char *sandbox_msg; - uint64_t sandbox_flags = SANDBOX_NAMED; - - (void)confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0); - - int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg); - if (sandbox_err) - { - LogMsg("WARNING: sandbox_init error %s", sandbox_msg); - // If we have errors in the sandbox during development, to prevent - // exiting, uncomment the following line. - //sandbox_free_error(sandbox_msg); - - errx(EX_OSERR, "sandbox_init() failed: %s", sandbox_msg); - } - else LogInfo("Now running under Apple Sandbox restrictions"); - } -#endif // MDNS_NO_SANDBOX - - m_port = RegisterMachService(kmDNSResponderServName); - // We should ALWAYS receive our Mach port from RegisterMachService() but sanity check before initializing daemon - if (m_port == MACH_PORT_NULL) - { - LogMsg("! MACH PORT IS NULL ! bootstrap_checkin failed to give a mach port"); - return -1; - } +#if DEBUG + if (useSandbox) +#endif + SandboxProcess(); #if TARGET_OS_EMBEDDED status = MetricsInit(); @@ -3043,13 +1608,6 @@ mDNSexport int main(int argc, char **argv) status = udsserver_init(launchd_fds, launchd_fds_count); if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; } -#if TARGET_OS_EMBEDDED - _scprefs_observer_watch(scprefs_observer_type_global, kmDNSResponderPrefIDStr, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - Prefschanged(); - }); -#endif - mDNSMacOSXNetworkChanged(&mDNSStorage); UpdateDebugState(); diff --git a/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist b/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist index fb9c3a30..d724352a 100644 --- a/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist +++ b/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist @@ -4,5 +4,7 @@ <dict> <key>com.apple.mDNSResponder.dnsproxy</key> <true/> + <key>com.apple.mDNSResponder.dnsctl</key> + <true/> </dict> </plist> diff --git a/mDNSResponder/mDNSMacOSX/helper-error.h b/mDNSResponder/mDNSMacOSX/helper-error.h deleted file mode 100644 index 6465b734..00000000 --- a/mDNSResponder/mDNSMacOSX/helper-error.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2007-2013 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. - */ - -ERROR(kmDNSHelperCommunicationFailed, "Mach communication failed") -ERROR(kmDNSHelperNotAuthorized, "Not authorized") -ERROR(kmDNSHelperCreationFailed, "Object creation failed") -ERROR(kmDNSHelperInvalidPList, "Invalid property list") -ERROR(kmDNSHelperInvalidNameKey, "Invalid name key") -ERROR(kmDNSHelperInvalidConfigKey, "Invalid configuration key") -ERROR(kmDNSHelperTypeError, "Object was not of expected type") -ERROR(kmDNSHelperPreferencesFailed, "Could not create preferences session") -ERROR(kmDNSHelperPreferencesLockFailed, "Could not lock preferences") -ERROR(kmDNSHelperPreferencesSetFailed, "Could not update preferences") -ERROR(kmDNSHelperKeychainCopyDefaultFailed, "Could not copy keychain default") -ERROR(kmDNSHelperKeychainSearchCreationFailed, "Could not create keychain search") -ERROR(kmDNSHelperPListWriteFailed, "Could not write property list to stream") -ERROR(kmDNSHelperResultTooLarge, "Result too large") -ERROR(kmDNSHelperInterfaceCreationFailed, "Could not create auto-tunnel interface") -ERROR(kmDNSHelperInterfaceDeletionFailed, "Could not delete auto-tunnel interface") -ERROR(kmDNSHelperInvalidInterfaceState, "Invalid interface state requested") -ERROR(kmDNSHelperInvalidServerState, "Invalid server state requested") -ERROR(kmDNSHelperRacoonConfigCreationFailed, "Could not create racoon configuration file") -ERROR(kmDNSHelperRacoonStartFailed, "Could not start racoon") -ERROR(kmDNSHelperRacoonNotificationFailed, "Could not notify racoon") -ERROR(kmDNSHelperInvalidTunnelSetKeysOperation, "Invalid tunnel setkey operation requested") -ERROR(kmDNSHelperInvalidNetworkAddress, "Invalid network address") -ERROR(kmDNSHelperRouteAdditionFailed, "Could not add route") -ERROR(kmDNSHelperRouteDeletionFailed, "Could not remove route") -ERROR(kmDNSHelperRoutingSocketCreationFailed, "Could not create routing socket") -ERROR(kmDNSHelperDatagramSocketCreationFailed, "Could not create datagram socket") -ERROR(kmDNSHelperIPsecPolicyCreationFailed, "Could not create IPsec policy") -ERROR(kmDNSHelperIPsecPolicySetFailed, "Could not set IPsec policy") -ERROR(kmDNSHelperIPsecRemoveSAFailed, "Could not remove IPsec SA") -ERROR(kmDNSHelperIPsecPolicySocketCreationFailed, "Could not create IPsec policy socket") -ERROR(kmDNSHelperIPsecDisabled, "IPSec support was not compiled in to the helper") diff --git a/mDNSResponder/mDNSMacOSX/helper-main.c b/mDNSResponder/mDNSMacOSX/helper-main.c index 5e4d9481..9c61e48c 100644 --- a/mDNSResponder/mDNSMacOSX/helper-main.c +++ b/mDNSResponder/mDNSMacOSX/helper-main.c @@ -24,7 +24,6 @@ #include <mach/mach.h> #include <mach/mach_error.h> #include <servers/bootstrap.h> -#include <asl.h> #include <launch.h> #include <pwd.h> #include <pthread.h> @@ -37,8 +36,7 @@ #include <Security/Security.h> #include "helper.h" #include "helper-server.h" -#include "helpermsg.h" -#include "helpermsgServer.h" +#include <xpc/private.h> #if TARGET_OS_EMBEDDED #define NO_SECURITYFRAMEWORK 1 @@ -50,14 +48,11 @@ #define launch_data_get_machport launch_data_get_fd #endif -union max_msg_size -{ - union __RequestUnion__proxy_helper_subsystem req; - union __ReplyUnion__proxy_helper_subsystem rep; -}; -static const mach_msg_size_t MAX_MSG_SIZE = sizeof(union max_msg_size) + MAX_TRAILER_SIZE; -static aslclient logclient = NULL; +int mDNSHelperLogEnabled = 0; +os_log_t log_handle = NULL; + +static dispatch_queue_t xpc_queue = NULL; static int opt_debug; static pthread_t idletimer_thread; @@ -67,45 +62,24 @@ unsigned long actualidle = 3600; CFRunLoopRef gRunLoop = NULL; CFRunLoopTimerRef gTimer = NULL; -mach_port_t gPort = MACH_PORT_NULL; - -static void helplogv(int level, const char *fmt, va_list ap) -{ - if (NULL == logclient) { vfprintf(stderr, fmt, ap); fflush(stderr); } - else asl_vlog(logclient, NULL, level, fmt, ap); -} - -void helplog(int level, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - helplogv(level, fmt, ap); - va_end(ap); -} - -// for safe_vproc -void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *fmt, ...) -{ - (void)logLevel; - va_list ap; - va_start(ap, fmt); - // safe_vproc only calls LogMsg, so assume logLevel maps to ASL_LEVEL_ERR - helplog(ASL_LEVEL_ERR, fmt, ap); - va_end(ap); -} static void handle_sigterm(int sig) { - // debug("entry sig=%d", sig); Can't use syslog from within a signal handler + // os_log_debug(log_handle,"entry sig=%d", sig); Can't use syslog from within a signal handler assert(sig == SIGTERM); - (void)proxy_mDNSExit(gPort); + helper_exit(); } static void initialize_logging(void) { - logclient = asl_open(NULL, "mDNSResponderHelper", (opt_debug ? ASL_OPT_STDERR : 0)); - if (NULL == logclient) { fprintf(stderr, "Could not initialize ASL logging.\n"); fflush(stderr); return; } - if (opt_debug) asl_set_filter(logclient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); + log_handle = os_log_create("com.apple.mDNSResponderHelper", "INFO"); + + if (!log_handle) + { + // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category + os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponderHelper"); + } + } static void initialize_id(void) @@ -116,23 +90,29 @@ static void initialize_id(void) hardcode.pw_uid = 65; hardcode.pw_gid = 65; - if (!pwd) { helplog(ASL_LEVEL_ERR, "Could not find account name `%s'. I will only help root.", login); return; } + if (!pwd) + { + os_log(log_handle, "Could not find account name `%s'. I will only help root.", login); + return; + } mDNSResponderUID = pwd->pw_uid; mDNSResponderGID = pwd->pw_gid; } static void diediedie(CFRunLoopTimerRef timer, void *context) { - debug("entry %p %p %d", timer, context, actualidle); + os_log_info(log_handle, "entry %p %p %lu", timer, context, actualidle); + assert(gTimer == timer); - helplog(ASL_LEVEL_INFO, "mDNSResponder exiting after %d seconds", actualidle); + os_log_info(log_handle, "mDNSResponderHelper exiting after [%lu] seconds", actualidle); + if (actualidle) - (void)proxy_mDNSExit(gPort); + helper_exit(); } void pause_idle_timer(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); assert(gTimer); assert(gRunLoop); CFRunLoopRemoveTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode); @@ -140,7 +120,7 @@ void pause_idle_timer(void) void unpause_idle_timer(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); assert(gRunLoop); assert(gTimer); CFRunLoopAddTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode); @@ -148,21 +128,21 @@ void unpause_idle_timer(void) void update_idle_timer(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); assert(gTimer); CFRunLoopTimerSetNextFireDate(gTimer, CFAbsoluteTimeGetCurrent() + actualidle); } static void *idletimer(void *context) { - debug("entry context=%p", context); - gRunLoop = CFRunLoopGetCurrent(); + os_log_debug(log_handle,"entry context=%p", context); + gRunLoop = CFRunLoopGetMain(); unpause_idle_timer(); for (;;) { - debug("Running CFRunLoop"); + // os_log_debug(log_handle,"Running CFRunLoop"); CFRunLoopRun(); sleep(1); } @@ -174,106 +154,504 @@ static int initialize_timer() { gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL); int err = 0; + os_log_info(log_handle, "mDNSResponderHelper initialize_timer() started"); - debug("entry"); if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL))) - helplog(ASL_LEVEL_ERR, "Could not start idletimer thread: %s", strerror(err)); + os_log(log_handle, "Could not start idletimer thread: %s", strerror(err)); return err; } -static mach_port_t register_service(const char *service_name) +/* + Reads the user's program arguments for mDNSResponderHelper + For now we have only one option: mDNSHelperDebugLogging which is used to turn on mDNSResponderHelperLogging + + To turn ON mDNSResponderHelper Verbose Logging, + 1] sudo defaults write /Library/Preferences/com.apple.mDNSResponderHelper.plist mDNSHelperDebugLogging -bool YES + 2] sudo reboot + + To turn OFF mDNSResponderHelper Logging, + 1] sudo defaults delete /Library/Preferences/com.apple.mDNSResponderHelper.plist + + To view the current options set, + 1] plutil -p /Library/Preferences/com.apple.mDNSResponderHelper.plist + OR + 1] sudo defaults read /Library/Preferences/com.apple.mDNSResponderHelper.plist +*/ + +static mDNSBool HelperPrefsGetValueBool(CFStringRef key, mDNSBool defaultVal) +{ + CFBooleanRef boolean; + mDNSBool result = defaultVal; + + boolean = CFPreferencesCopyAppValue(key, kmDNSHelperProgramArgs); + if (boolean) + { + if (CFGetTypeID(boolean) == CFBooleanGetTypeID()) + result = CFBooleanGetValue(boolean) ? mDNStrue : mDNSfalse; + CFRelease(boolean); + } + + return result; +} + + +// Verify Client's Entitlement +static mDNSBool check_entitlement(xpc_connection_t conn, const char *password) +{ + mDNSBool entitled = mDNSfalse; + xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password); + + if (ent) + { + if (xpc_get_type(ent) == XPC_TYPE_BOOL && xpc_bool_get_value(ent)) + { + entitled = mDNStrue; + } + xpc_release(ent); + } + else + { + os_log(log_handle, "client entitlement is NULL"); + } + + if (!entitled) + os_log(log_handle, "entitlement check failed -> client is missing entitlement!"); + + return entitled; +} + + +static void handle_request(xpc_object_t req) { - mach_port_t port = MACH_PORT_NULL; - kern_return_t kr; + mDNSu32 helper_mode = 0; + int error_code = 0; + + xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req); + xpc_object_t response = xpc_dictionary_create_reply(req); + + // switch here based on dictionary to handle different requests from mDNSResponder + if ((xpc_dictionary_get_uint64(req, kHelperMode))) + { + os_log_info(log_handle, "Getting mDNSResponder request mode"); + helper_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kHelperMode)); + } + + switch (helper_mode) + { + case bpf_request: + { + os_log_info(log_handle, "Calling new RequestBPF()"); + RequestBPF(); + break; + } + + case set_name: + { + const char *old_name; + const char *new_name; + int pref_key = 0; + + pref_key = (int)(xpc_dictionary_get_uint64(req, kPrefsNameKey)); + old_name = xpc_dictionary_get_string(req, kPrefsOldName); + new_name = xpc_dictionary_get_string(req, kPrefsNewName); + + os_log_info(log_handle, "Calling new SetName() oldname: %s newname: %s key:%d", old_name, new_name, pref_key); + PreferencesSetName(pref_key, old_name, new_name); + break; + } + + case p2p_packetfilter: + { + pfArray_t pfports; + pfArray_t pfprotocols; + const char *if_name; + uint32_t cmd; + uint32_t count; + + cmd = xpc_dictionary_get_uint64(req, "pf_opcode"); + if_name = xpc_dictionary_get_string(req, "pf_ifname"); + count = xpc_dictionary_get_uint64(req, "pf_count"); + + pfports[0] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port0"); + pfports[1] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port1"); + pfports[2] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port2"); + pfports[3] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port3"); + + pfprotocols[0] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol0"); + pfprotocols[1] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol1"); + pfprotocols[2] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol2"); + pfprotocols[3] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol3"); + + os_log_info(log_handle,"Calling new PacketFilterControl()"); + PacketFilterControl(cmd, if_name, count, pfports, pfprotocols); + break; + } + + case user_notify: + { + const char *title; + const char *msg; + title = xpc_dictionary_get_string(req, "notify_title"); + msg = xpc_dictionary_get_string(req, "notify_msg"); + + os_log_info(log_handle,"Calling new UserNotify() title:%s msg:%s", title, msg); + UserNotify(title, msg); + break; + } + + case power_req: + { + int key, interval; + key = xpc_dictionary_get_uint64(req, "powerreq_key"); + interval = xpc_dictionary_get_uint64(req, "powerreq_interval"); + + os_log_info(log_handle,"Calling new PowerRequest() key[%d] interval[%d]", key, interval); + PowerRequest(key, interval, &error_code); + break; + } + + case send_wakepkt: + { + const char *ether_addr; + const char *ip_addr; + int iteration; + unsigned int if_id; + + if_id = (unsigned int)xpc_dictionary_get_uint64(req, "interface_index"); + ether_addr = xpc_dictionary_get_string(req, "ethernet_address"); + ip_addr = xpc_dictionary_get_string(req, "ip_address"); + iteration = (int)xpc_dictionary_get_uint64(req, "swp_iteration"); + + os_log_info(log_handle, "Calling new SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]", + ether_addr, ip_addr, if_id, iteration); + SendWakeupPacket(if_id, ether_addr, ip_addr, iteration); + break; + } + + case set_localaddr_cacheentry: + { + int if_index, family; + + if_index = xpc_dictionary_get_uint64(req, "slace_ifindex"); + family = xpc_dictionary_get_uint64(req, "slace_family"); + + const uint8_t* ip = xpc_dictionary_get_data(req, "slace_ip", NULL); + const uint8_t* eth = xpc_dictionary_get_data(req, "slace_eth", NULL); + + os_log_info(log_handle, "Calling new SetLocalAddressCacheEntry() if_index[%d] family[%d] ", if_index, family); + + SetLocalAddressCacheEntry(if_index, family, ip, eth, &error_code); + + /* + static int v6addr_to_string(const v6addr_t addr, char *buf, size_t buflen) + { + if (NULL == inet_ntop(AF_INET6, addr, buf, buflen)) + { + os_log(log_handle, "inet_ntop failed: %s", strerror(errno)); + return -1; + } + else + { + return 0; + } + } + + ethaddr_t eth = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } ; + const uint8_t* slace_ip = NULL; + v6addr_t addr_ipv6; + size_t ip_len; + slace_ip = xpc_dictionary_get_data(req, "slace_ip", &ip_len); + if (slace_ip && (ip_len == sizeof(v6addr_t))) + { + os_log(log_handle, "mDNSResponderHelper: doing memcpy()"); + memcpy(&addr_ipv6, slace_ip, ip_len); + } + char test_ipv6_str[46]; + v6addr_to_string(addr_ipv6, test_ipv6_str, sizeof(test_ipv6_str)); + os_log(log_handle, "mDNSResponderHelper: handle_request: set_localaddr_cacheentry: test_ipv6_str is %s", test_ipv6_str); + */ + + break; + } + + case send_keepalive: + { + uint16_t lport, rport, win; + uint32_t seq, ack; + + lport = xpc_dictionary_get_uint64(req, "send_keepalive_lport"); + rport = xpc_dictionary_get_uint64(req, "send_keepalive_rport"); + seq = xpc_dictionary_get_uint64(req, "send_keepalive_seq"); + ack = xpc_dictionary_get_uint64(req, "send_keepalive_ack"); + win = xpc_dictionary_get_uint64(req, "send_keepalive_win"); + + const uint8_t* sadd6 = xpc_dictionary_get_data(req, "send_keepalive_sadd", NULL); + const uint8_t* dadd6 = xpc_dictionary_get_data(req, "send_keepalive_dadd", NULL); + + os_log_info(log_handle, "helper-main: handle_request: send_keepalive: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]", + lport, rport, seq, ack, win); + + SendKeepalive(sadd6, dadd6, lport, rport, seq, ack, win); + break; + } + + case retreive_tcpinfo: + { + uint16_t lport, rport; + int family; + uint32_t seq, ack; + uint16_t win; + int32_t intfid; + + lport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_lport"); + rport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_rport"); + family = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_family"); + + const uint8_t* laddr = xpc_dictionary_get_data(req, "retreive_tcpinfo_laddr", NULL); + const uint8_t* raddr = xpc_dictionary_get_data(req, "retreive_tcpinfo_raddr", NULL); + + os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: lport is[%d] rport is[%d] family is [%d]", + lport, rport, family); + + RetrieveTCPInfo(family, laddr, lport, raddr, rport, &seq, &ack, &win, &intfid, &error_code); + + if (response) + { + xpc_dictionary_set_uint64(response, "retreive_tcpinfo_seq", seq); + xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ack", ack); + xpc_dictionary_set_uint64(response, "retreive_tcpinfo_win", win); + xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ifid", intfid); + } + + os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: seq is[%d] ack is[%d] win is [%d] intfid is [%d]", + seq, ack, win, intfid); + + break; + } + + case autotunnel_setkeys: + { + uint16_t lport, rport; + int replace_del; + const char *fqdnstr; + + lport = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_lport"); + rport = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_rport"); + replace_del = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_repdel"); + + const uint8_t* local_inner = xpc_dictionary_get_data(req, "autotunnelsetkeys_localinner", NULL); + const uint8_t* local_outer = xpc_dictionary_get_data(req, "autotunnelsetkeys_localouter", NULL); + const uint8_t* remote_inner = xpc_dictionary_get_data(req, "autotunnelsetkeys_remoteinner", NULL); + const uint8_t* remote_outer = xpc_dictionary_get_data(req, "autotunnelsetkeys_remoteouter", NULL); + + fqdnstr = xpc_dictionary_get_string(req, "autotunnelsetkeys_fqdnStr"); + + os_log_info(log_handle, "helper-main: handle_request: autotunnel_setkeys: lport is[%d] rport is[%d] replace_del is [%d]", + lport, rport, replace_del); + + + HelperAutoTunnelSetKeys(replace_del, local_inner, local_outer, lport, remote_inner, remote_outer, rport, fqdnstr, &error_code); - if (KERN_SUCCESS != (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port))) + break; + } + + + case keychain_getsecrets: + { + unsigned int num_sec = 0; + unsigned long secrets = 0; + unsigned int sec_cnt = 0; + + os_log_info(log_handle,"Calling new KeyChainGetSecrets()"); + + KeychainGetSecrets(&num_sec, &secrets, &sec_cnt, &error_code); + + if (response) + { + xpc_dictionary_set_uint64(response, "keychain_num_secrets", num_sec); + xpc_dictionary_set_data(response, "keychain_secrets", (void *)secrets, sec_cnt); + xpc_dictionary_set_uint64(response, "keychain_secrets_count", sec_cnt); + } + + os_log_info(log_handle,"helper-main: handle_request: keychain_getsecrets: num_secrets is %d, secrets is %lu, secrets_Cnt is %d", + num_sec, secrets, sec_cnt); + + if (secrets) + vm_deallocate(mach_task_self(), secrets, sec_cnt); + + break; + } + + default: + { + os_log(log_handle, "handle_request: Unrecognized mode!"); + error_code = kHelperErr_UndefinedMode; + break; + } + } + + // Return Response Status back to the client (essentially ACKing the request) + if (response) { - helplog(ASL_LEVEL_ERR, "bootstrap_check_in: %d %X %s", kr, kr, mach_error_string(kr)); - return MACH_PORT_NULL; + xpc_dictionary_set_uint64(response, kHelperReplyStatus, kHelperReply_ACK); + xpc_dictionary_set_int64(response, kHelperErrCode, error_code); + xpc_connection_send_message(remote_conn, response); + xpc_release(response); } + else + { + os_log(log_handle, "handle_requests: Response Dictionary could not be created!"); + return; + } + +} + +static void accept_client(xpc_connection_t conn) +{ + int c_pid = xpc_connection_get_pid(conn); - if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) + if (!(check_entitlement(conn, kHelperService))) { - helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr)); - mach_port_deallocate(mach_task_self(), port); - return MACH_PORT_NULL; + os_log(log_handle, "accept_client: Helper Client PID[%d] is missing Entitlement. Cancelling connection", c_pid); + xpc_connection_cancel(conn); + return; } + + xpc_retain(conn); + xpc_connection_set_target_queue(conn, xpc_queue); + xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg) + { + xpc_type_t type = xpc_get_type(req_msg); + + if (type == XPC_TYPE_DICTIONARY) + { + os_log_info(log_handle,"accept_client:conn:[%p] client[%d](mDNSResponder) requesting service", (void *) conn, c_pid); + handle_request(req_msg); + } + else // We hit this case ONLY if Client Terminated Connection OR Crashed + { + os_log(log_handle, "accept_client:conn:[%p] client[%d](mDNSResponder) teared down the connection (OR Crashed)", (void *) conn, c_pid); + // handle_termination(); + xpc_release(conn); + } + }); + + xpc_connection_resume(conn); +} + - return port; +static void init_helper_service(const char *service_name) +{ + + xpc_connection_t xpc_listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (!xpc_listener || xpc_get_type(xpc_listener) != XPC_TYPE_CONNECTION) + { + os_log(log_handle, "init_helper_service: Error Creating XPC Listener for mDNSResponderHelperService !!"); + return; + } + + os_log_info(log_handle,"init_helper_service: XPC Listener for mDNSResponderHelperService Listening"); + + xpc_queue = dispatch_queue_create("com.apple.mDNSHelper.service_queue", NULL); + + xpc_connection_set_event_handler(xpc_listener, ^(xpc_object_t eventmsg) + { + xpc_type_t type = xpc_get_type(eventmsg); + + if (type == XPC_TYPE_CONNECTION) + { + os_log_info(log_handle,"init_helper_service: new mDNSResponderHelper Client %p", eventmsg); + accept_client(eventmsg); + } + else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases below + { + os_log(log_handle, "init_helper_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION)); + return; + } + else + { + os_log(log_handle, "init_helper_service: Unknown EventMsg type"); + return; + } + }); + + xpc_connection_resume(xpc_listener); } + int main(int ac, char *av[]) { char *p = NULL; - kern_return_t kr = KERN_FAILURE; long n; int ch; - mach_msg_header_t hdr; while ((ch = getopt(ac, av, "dt:")) != -1) + { switch (ch) { - case 'd': opt_debug = 1; break; - case 't': - n = strtol(optarg, &p, 0); - if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0) - { fprintf(stderr, "Invalid idle timeout: %s\n", optarg); exit(EXIT_FAILURE); } - maxidle = n; - break; - case '?': - default: - fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n"); - exit(EXIT_FAILURE); + case 'd': + opt_debug = 1; + break; + case 't': + n = strtol(optarg, &p, 0); + if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0) + { + fprintf(stderr, "Invalid idle timeout: %s\n", optarg); + exit(EXIT_FAILURE); + } + maxidle = n; + break; + case '?': + default: + fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n"); + exit(EXIT_FAILURE); } + } ac -= optind; av += optind; (void)ac; // Unused (void)av; // Unused initialize_logging(); - helplog(ASL_LEVEL_INFO, "Starting"); initialize_id(); + mDNSHelperLogEnabled = HelperPrefsGetValueBool(kPreferencesKey_mDNSHelperLog, mDNSHelperLogEnabled); + +// Currently on Fuji/Whitetail releases we are keeping the logging always enabled. +// Hence mDNSHelperLogEnabled is set to true below by default. + mDNSHelperLogEnabled = 1; + + os_log_info(log_handle,"mDNSResponderHelper Starting to run"); + #ifndef NO_SECURITYFRAMEWORK // We should normally be running as a system daemon. However, that might not be the case in some scenarios (e.g. debugging). // Explicitly ensure that our Keychain operations utilize the system domain. - if (opt_debug) SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (opt_debug) + SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); #endif - gPort = register_service(kmDNSHelperServiceName); - if (!gPort) - exit(EXIT_FAILURE); - if (maxidle) actualidle = maxidle; + if (maxidle) + actualidle = maxidle; signal(SIGTERM, handle_sigterm); - if (initialize_timer()) exit(EXIT_FAILURE); - for (n=0; n<100000; n++) if (!gRunLoop) usleep(100); + if (initialize_timer()) + exit(EXIT_FAILURE); + for (n=0; n<100000; n++) + if (!gRunLoop) + usleep(100); + if (!gRunLoop) { - helplog(ASL_LEVEL_ERR, "gRunLoop not set after waiting"); + os_log(log_handle, "gRunLoop not set after waiting"); exit(EXIT_FAILURE); } - for(;;) - { - hdr.msgh_bits = 0; - hdr.msgh_local_port = gPort; - hdr.msgh_remote_port = MACH_PORT_NULL; - hdr.msgh_size = sizeof(hdr); - hdr.msgh_id = 0; - kr = mach_msg(&hdr, MACH_RCV_LARGE | MACH_RCV_MSG, 0, hdr.msgh_size, gPort, 0, 0); - if (MACH_RCV_TOO_LARGE != kr) - helplog(ASL_LEVEL_ERR, "main MACH_RCV_MSG error: %d %X %s", kr, kr, mach_error_string(kr)); - - kr = mach_msg_server_once(helper_server, MAX_MSG_SIZE, gPort, - MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)); - if (KERN_SUCCESS != kr) - { helplog(ASL_LEVEL_ERR, "mach_msg_server: %d %X %s", kr, kr, mach_error_string(kr)); exit(EXIT_FAILURE); } - - } - exit(EXIT_SUCCESS); + init_helper_service(kHelperService); + os_log_info(log_handle,"mDNSResponderHelper is now running"); + dispatch_main(); + } // Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion diff --git a/mDNSResponder/mDNSMacOSX/helper-server.h b/mDNSResponder/mDNSMacOSX/helper-server.h index eb0e6ae1..8a342748 100644 --- a/mDNSResponder/mDNSMacOSX/helper-server.h +++ b/mDNSResponder/mDNSMacOSX/helper-server.h @@ -18,14 +18,11 @@ #ifndef H_HELPER_SERVER_H #define H_HELPER_SERVER_H -extern void helplog(int, const char *, ...); extern void pause_idle_timer(void); extern void unpause_idle_timer(void); extern void update_idle_timer(void); extern uid_t mDNSResponderUID; extern uid_t mDNSResponderGID; extern CFRunLoopRef gRunLoop; -#define debug(...) debug_(__func__, __VA_ARGS__) -extern void debug_(const char *func, const char *fmt, ...); #endif /* H_HELPER_SERVER_H */ diff --git a/mDNSResponder/mDNSMacOSX/helper-stubs.c b/mDNSResponder/mDNSMacOSX/helper-stubs.c index e08f5050..a1e804fd 100644 --- a/mDNSResponder/mDNSMacOSX/helper-stubs.c +++ b/mDNSResponder/mDNSMacOSX/helper-stubs.c @@ -23,9 +23,10 @@ #include <CoreFoundation/CoreFoundation.h> #include "mDNSDebug.h" #include "helper.h" -#include "helpermsg.h" #include <dispatch/dispatch.h> #include <arpa/inet.h> +#include <xpc/private.h> +#include <Block.h> // // Implementation Notes about the HelperQueue: @@ -40,67 +41,176 @@ // an argument to the function, the blocks can reference them as they are passed in as pointers. But care should // be taken to copy them locally as they may cease to exist when the function returns. // + + +//************************************************************************************************************* +// Globals static dispatch_queue_t HelperQueue; +static xpc_connection_t helper_xpc_conn = NULL; + +static int64_t maxwait_secs = 5LL; + +#define mDNSHELPER_DEBUG LogOperation -#define ERROR(x, y) y, -static const char *errorstring[] = +//************************************************************************************************************* +// Utility Functions + +static void LogDebug(const char *prefix, xpc_object_t o) { - #include "helper-error.h" - NULL -}; -#undef ERROR + char *desc = xpc_copy_description(o); + mDNSHELPER_DEBUG("LogDebug %s: %s", prefix, desc); + free(desc); +} -mDNSexport mStatus mDNSHelperInit() +//************************************************************************************************************* +// XPC Funcs: +//************************************************************************************************************* + + +mDNSlocal void Init_Connection(const char *servname) { - HelperQueue = dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL); - if (HelperQueue == NULL) + helper_xpc_conn = xpc_connection_create_mach_service(servname, HelperQueue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); + + xpc_connection_set_event_handler(helper_xpc_conn, ^(xpc_object_t event) { - LogMsg("dispatch_queue_create: Helper queue NULL"); - return mStatus_NoMemoryErr; - } - return mStatus_NoError; + mDNSHELPER_DEBUG("Init_Connection xpc: [%s] \n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + }); + + xpc_connection_resume(helper_xpc_conn); } -static mach_port_t getHelperPort(int retry) +mDNSlocal int SendDict_ToServer(xpc_object_t msg) { - static mach_port_t port = MACH_PORT_NULL; - if (retry) port = MACH_PORT_NULL; - if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port)) - LogMsg("%s: cannot contact helper", __func__); - return port; + __block int errorcode = kHelperErr_NoResponse; + + LogDebug("SendDict_ToServer Sending msg to Daemon", msg); + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + dispatch_retain(sem); // for the block below + + xpc_connection_send_message_with_reply(helper_xpc_conn, msg, HelperQueue, ^(xpc_object_t recv_msg) + { + xpc_type_t type = xpc_get_type(recv_msg); + + if (type == XPC_TYPE_DICTIONARY) + { + LogDebug("SendDict_ToServer Received reply msg from Daemon", recv_msg); + uint64_t reply_status = xpc_dictionary_get_uint64(recv_msg, kHelperReplyStatus); + errorcode = xpc_dictionary_get_int64(recv_msg, kHelperErrCode); + + switch (reply_status) + { + case kHelperReply_ACK: + mDNSHELPER_DEBUG("NoError: successful reply"); + break; + default: + LogMsg("default: Unexpected reply from Helper"); + break; + } + } + else + { + LogMsg("SendDict_ToServer Received unexpected reply from daemon [%s]", + xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION)); + LogDebug("SendDict_ToServer Unexpected Reply contents", recv_msg); + } + + dispatch_semaphore_signal(sem); + dispatch_release(sem); + + }); + + if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (maxwait_secs * NSEC_PER_SEC))) != 0) + LogMsg("SendDict_ToServer: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait"); + + dispatch_release(sem); + + mDNSHELPER_DEBUG("SendDict_ToServer returning with errorcode[%d]", errorcode); + + return errorcode; } -const char *mDNSHelperError(int err) +mDNSlocal xpc_object_t SendDict_GetReply(xpc_object_t msg) { - static const char *p = "<unknown error>"; - if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err) - p = errorstring[err - mDNSHelperErrorBase - 1]; - return p; + // Create empty dictionary + __block xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + if (!dict) return NULL; + xpc_retain(dict); + + LogDebug("SendDict_GetReply Sending msg to Daemon", msg); + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + dispatch_retain(sem); // for the block below + + xpc_connection_send_message_with_reply(helper_xpc_conn, msg, HelperQueue, ^(xpc_object_t recv_msg) + { + xpc_type_t type = xpc_get_type(recv_msg); + + if (type == XPC_TYPE_DICTIONARY) + { + LogDebug("SendDict_GetReply Received reply msg from Daemon", recv_msg); + uint64_t reply_status = xpc_dictionary_get_uint64(recv_msg, kHelperReplyStatus); + + switch (reply_status) + { + case kHelperReply_ACK: + mDNSHELPER_DEBUG("NoError: successful reply"); + break; + default: + LogMsg("default: Unexpected reply from Helper"); + break; + } + // Copy result into dict reply + xpc_dictionary_apply(recv_msg, ^bool(const char *key, xpc_object_t value) + { + xpc_dictionary_set_value(dict, key, value); + return true; + }); + } + else + { + LogMsg("SendDict_GetReply Received unexpected reply from daemon [%s]", + xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION)); + LogDebug("SendDict_GetReply Unexpected Reply contents", recv_msg); + } + + dispatch_semaphore_signal(sem); + dispatch_release(sem); + xpc_release(dict); + + }); + + if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (maxwait_secs * NSEC_PER_SEC))) != 0) + { + LogMsg("SendDict_GetReply: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait"); + xpc_release(dict); + dispatch_release(sem); + + return NULL; + } + + dispatch_release(sem); + + return dict; } -/* Ugly but handy. */ -// We don't bother reporting kIOReturnNotReady because that error code occurs in "normal" operation -// and doesn't indicate anything unexpected that needs to be investigated +//************************************************************************************************************** -#define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \ - for (;;) \ +mDNSexport mStatus mDNSHelperInit() +{ + HelperQueue = dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL); + if (HelperQueue == NULL) { -#define MACHRETRYLOOP_END(kr, retry, err, fin) \ - if (KERN_SUCCESS == (kr)) break; \ - else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue; \ - else \ - { \ - (err) = kmDNSHelperCommunicationFailed; \ - LogMsg("%s: Mach communication failed: %d %X %s", __func__, kr, kr, mach_error_string(kr)); \ - goto fin; \ - } \ - } \ - if (0 != (err) && kIOReturnNotReady != (err)) \ - { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; } + LogMsg("dispatch_queue_create: Helper queue NULL"); + return mStatus_NoMemoryErr; + } + return mStatus_NoError; +} void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new) { - struct { + struct + { char oldname[MAX_DOMAIN_LABEL+1]; char newname[MAX_DOMAIN_LABEL+1]; } names; @@ -109,250 +219,272 @@ void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new) mDNSPlatformMemZero(names.newname, MAX_DOMAIN_LABEL + 1); ConvertDomainLabelToCString_unescaped(old, names.oldname); - if (new) ConvertDomainLabelToCString_unescaped(new, names.newname); - dispatch_async(HelperQueue, ^{ - - kern_return_t kr = KERN_FAILURE; - int retry = 0; - int err = 0; - - LogInfo("%s: oldname %s newname %s", __func__, names.oldname, names.newname); - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, names.oldname, names.newname); - MACHRETRYLOOP_END(kr, retry, err, fin); - -fin: - (void)err; - }); + + if (new) + ConvertDomainLabelToCString_unescaped(new, names.newname); + + + mDNSHELPER_DEBUG("mDNSPreferencesSetName: XPC IPC Test oldname %s newname %s", names.oldname, names.newname); + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, set_name); + + xpc_dictionary_set_uint64(dict, kPrefsNameKey, key); + xpc_dictionary_set_string(dict, kPrefsOldName, names.oldname); + xpc_dictionary_set_string(dict, kPrefsNewName, names.newname); + + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + } -void mDNSRequestBPF(void) +void mDNSRequestBPF() { - dispatch_async(HelperQueue, ^{ - - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - LogInfo("%s: BPF", __func__); - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSRequestBPF(getHelperPort(retry)); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - (void)err; - }); + mDNSHELPER_DEBUG("mDNSRequestBPF: Using XPC IPC"); + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, bpf_request); + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + } int mDNSPowerRequest(int key, int interval) { - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSPowerRequest(getHelperPort(retry), key, interval, &err); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - return err; + int err_code = kHelperErr_NotConnected; + + mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC calling out to Helper key is [%d] interval is [%d]", key, interval); + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, power_req); + xpc_dictionary_set_uint64(dict, "powerreq_key", key); + xpc_dictionary_set_uint64(dict, "powerreq_interval", interval); + + err_code = SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + + mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC returning error_code %d", err_code); + return err_code; } int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth) { - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSSetLocalAddressCacheEntry(getHelperPort(retry), ifindex, family, (uint8_t*)ip, (uint8_t*)eth, &err); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - return err; + int err_code = kHelperErr_NotConnected; + + mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC calling out to Helper: ifindex is [%d] family is [%d]", ifindex, family); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, set_localaddr_cacheentry); + + xpc_dictionary_set_uint64(dict, "slace_ifindex", ifindex); + xpc_dictionary_set_uint64(dict, "slace_family", family); + + xpc_dictionary_set_data(dict, "slace_ip", (uint8_t*)ip, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "slace_eth", (uint8_t*)eth, sizeof(ethaddr_t)); + + err_code = SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + + mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC returning error_code %d", err_code); + return err_code; } + void mDNSNotify(const char *title, const char *msg) // Both strings are UTF-8 text { - char *titleCopy = NULL; - char *msgCopy = NULL; - - if (title) - { - // Don’t try to call mDNSPlatformMem* routines here, because they call validatelists, - // which calls back into mDNSNotify, resulting an infinite loop until stack space is exhausted - int len = strlen(title); - titleCopy = malloc(len + 1); - if (!titleCopy) - { - LogMsg("mDNSNotify: titleCopy NULL for %s", msg); - return; - } - memcpy(titleCopy, title, len); - titleCopy[len] = 0; - } - if (msg) - { - int len = strlen(msg); - msgCopy = malloc(len + 1); - if (!msgCopy) - { - LogMsg("mDNSNotify: msgCopy NULL for %s", msg); - return; - } - memcpy(msgCopy, msg, len); - msgCopy[len] = 0; - } - - dispatch_async(HelperQueue, ^{ - - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - - LogInfo("%s: title %s, msg %s", __func__, titleCopy, msgCopy); + mDNSHELPER_DEBUG("mDNSNotify() calling out to Helper XPC IPC title[%s] msg[%s]", title, msg); - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSNotify(getHelperPort(retry), titleCopy, msgCopy); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - // Don’t try to call mDNSPlatformMem* routines here, because they call validatelists, - // which calls back into mDNSNotify, resulting an infinite loop until stack space is exhausted - free(titleCopy); - free(msgCopy); - (void)err; - }); + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, user_notify); + + xpc_dictionary_set_string(dict, "notify_title", title); + xpc_dictionary_set_string(dict, "notify_msg", msg); + + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + } + int mDNSKeychainGetSecrets(CFArrayRef *result) { + CFPropertyListRef plist = NULL; CFDataRef bytes = NULL; - kern_return_t kr = KERN_FAILURE; unsigned int numsecrets = 0; - vm_offset_t secrets = 0; - mach_msg_type_number_t secretsCnt = 0; - int retry = 0, err = 0; - - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, &secrets, &secretsCnt, &err); - MACHRETRYLOOP_END(kr, retry, err, fin); + unsigned int secretsCnt = 0; + int error_code = kHelperErr_NotConnected; + xpc_object_t reply_dict = NULL; + const void *sec = NULL; + size_t secrets_size = 0; + + mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper"); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, keychain_getsecrets); - if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)secrets, secretsCnt, kCFAllocatorNull))) + reply_dict = SendDict_GetReply(dict); + + if (reply_dict != NULL) { - err = kmDNSHelperCreationFailed; - LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__); + numsecrets = xpc_dictionary_get_uint64(reply_dict, "keychain_num_secrets"); + sec = xpc_dictionary_get_data(reply_dict, "keychain_secrets", &secrets_size); + secretsCnt = xpc_dictionary_get_uint64(reply_dict, "keychain_secrets_count"); + error_code = xpc_dictionary_get_int64(reply_dict, kHelperErrCode); + } + + mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper: numsecrets is %d, secretsCnt is %d error_code is %d secret_size is %d", + numsecrets, secretsCnt, error_code, secrets_size); + + if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)sec, secretsCnt, kCFAllocatorNull))) + { + error_code = kHelperErr_ApiErr; + LogMsg("mDNSKeychainGetSecrets: CFDataCreateWithBytesNoCopy failed"); goto fin; } + if (NULL == (plist = CFPropertyListCreateWithData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL, NULL))) { - err = kmDNSHelperInvalidPList; - LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__); + error_code = kHelperErr_ApiErr; + LogMsg("mDNSKeychainGetSecrets: CFPropertyListCreateFromXMLData failed"); goto fin; } + if (CFArrayGetTypeID() != CFGetTypeID(plist)) { - err = kmDNSHelperTypeError; - LogMsg("%s: Unexpected result type", __func__); + error_code = kHelperErr_ApiErr; + LogMsg("mDNSKeychainGetSecrets: Unexpected result type"); CFRelease(plist); plist = NULL; goto fin; } + *result = (CFArrayRef)plist; - + + fin: - if (bytes) CFRelease(bytes); - if (secrets) vm_deallocate(mach_task_self(), secrets, secretsCnt); - return err; + if (bytes) + CFRelease(bytes); + if (dict) + xpc_release(dict); + if (reply_dict) + xpc_release(reply_dict); + + dict = NULL; + reply_dict = NULL; + + return error_code; } -void mDNSConfigureServer(int updown, const char *const prefix, const domainname *const fqdn) -{ - struct - { - // Assume the prefix is no larger than 10 chars - char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10]; - } name; - - mDNSPlatformMemZero(name.fqdnStr, MAX_DOMAIN_LABEL + 10); - - if (fqdn) - { - mDNSPlatformStrCopy(name.fqdnStr, prefix); - ConvertDomainNameToCString(fqdn, name.fqdnStr + mDNSPlatformStrLen(prefix)); - } - - dispatch_async(HelperQueue, ^{ - - kern_return_t kr = KERN_SUCCESS; - int retry = 0, err = 0; - - LogInfo("%s: fqdnStr %s", __func__, name.fqdnStr); - - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, name.fqdnStr); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - (void)err; - - }); -} int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner, v6addr_t local_outer, short local_port, v6addr_t remote_inner, v6addr_t remote_outer, short remote_port, const char* const prefix, const domainname *const fqdn) { - kern_return_t kr = KERN_SUCCESS; - int retry = 0, err = 0; + + int err_code = kHelperErr_NotConnected; + + mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper. Parameters are repdel[%d], lport[%d], rport[%d], prefix[%s], fqdn[%##s]", + replacedelete, local_port, remote_port, prefix, fqdn->c); + + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + char buf3[INET6_ADDRSTRLEN]; + char buf4[INET6_ADDRSTRLEN]; + + buf1[0] = 0; + buf2[0] = 0; + buf3[0] = 0; + buf4[0] = 0; + + inet_ntop(AF_INET6, local_inner, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, local_outer, buf2, sizeof(buf2)); + inet_ntop(AF_INET6, remote_inner, buf3, sizeof(buf3)); + inet_ntop(AF_INET6, remote_outer, buf4, sizeof(buf4)); + char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10] = { 0 }; // Assume the prefix is no larger than 10 chars if (fqdn) { mDNSPlatformStrCopy(fqdnStr, prefix); ConvertDomainNameToCString(fqdn, fqdnStr + mDNSPlatformStrLen(prefix)); } - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - return err; -} + + mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper: Parameters are local_inner is %s, local_outeris %s, remote_inner is %s, remote_outer is %s", + buf1, buf2, buf3, buf4); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, autotunnel_setkeys); + + xpc_dictionary_set_data(dict, "autotunnelsetkeys_localinner", (uint8_t*)local_inner, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "autotunnelsetkeys_localouter", (uint8_t*)local_outer, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "autotunnelsetkeys_remoteinner", (uint8_t*)remote_inner, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "autotunnelsetkeys_remoteouter", (uint8_t*)remote_outer, sizeof(v6addr_t)); + + xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_lport", local_port); + xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_rport", remote_port); + xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_repdel", replacedelete); -void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration) -{ - char *ip_addr_copy = NULL; - char *eth_addr_copy = NULL; + // xpc_dictionary_set_string(dict, "autotunnelsetkeys_prefix", prefix); + xpc_dictionary_set_string(dict, "autotunnelsetkeys_fqdnStr", fqdnStr); + + err_code = SendDict_ToServer(dict); + + xpc_release(dict); + dict = NULL; - if (eth_addr) - { - int len = strlen(eth_addr); - eth_addr_copy = mDNSPlatformMemAllocate(len + 1); - if (!eth_addr_copy) - { - LogMsg("mDNSSendWakeupPacket: eth_addr_copy NULL for %s", eth_addr); - return; - } - mDNSPlatformMemCopy(eth_addr_copy, eth_addr, len); - eth_addr_copy[len] = 0; - } - if (ip_addr) - { - int len = strlen(ip_addr); - ip_addr_copy = mDNSPlatformMemAllocate(len + 1); - if (!ip_addr_copy) - { - LogMsg("mDNSSendWakeupPacket: ip_addr_copy NULL for %s", ip_addr); - return; - } - mDNSPlatformMemCopy(ip_addr_copy, ip_addr, len); - ip_addr_copy[len] = 0; - } - dispatch_async(HelperQueue, ^{ + mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC returning error_code %d", err_code); + + mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: this should NOT be done in mDNSResponder/Helper. For future we shall be using <rdar://problem/13792729>"); + return err_code; +} - kern_return_t kr = KERN_SUCCESS; - int retry = 0, err = 0; +void mDNSSendWakeupPacket(unsigned int ifid, char *eth_addr, char *ip_addr, int iteration) +{ + // (void) ip_addr; // unused + // (void) iteration; // unused - LogInfo("%s: Entered ethernet address %s, ip address %s", __func__, eth_addr_copy, ip_addr_copy); + mDNSHELPER_DEBUG("mDNSSendWakeupPacket: Entered ethernet address[%s],ip_address[%s], interface_id[%d], iteration[%d]", + eth_addr, ip_addr, ifid, iteration); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, send_wakepkt); + + xpc_dictionary_set_uint64(dict, "interface_index", ifid); + xpc_dictionary_set_string(dict, "ethernet_address", eth_addr); + xpc_dictionary_set_string(dict, "ip_address", ip_addr); + xpc_dictionary_set_uint64(dict, "swp_iteration", iteration); + + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSSendWakeupPacket(getHelperPort(retry), ifid, eth_addr_copy, ip_addr_copy, iteration); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - if (eth_addr_copy) - mDNSPlatformMemFree(eth_addr_copy); - if (ip_addr_copy) - mDNSPlatformMemFree(ip_addr_copy); - (void) err; - }); } void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray) @@ -362,138 +494,127 @@ void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pf pfArray_t portArray; pfArray_t protocolArray; } pfa; - char *ifnameCopy = NULL; mDNSPlatformMemCopy(pfa.portArray, portArray, sizeof(pfArray_t)); mDNSPlatformMemCopy(pfa.protocolArray, protocolArray, sizeof(pfArray_t)); - if (ifname) - { - int len = strlen(ifname); - ifnameCopy = mDNSPlatformMemAllocate(len + 1); - if (!ifnameCopy) - { - LogMsg("mDNSPacketFilterControl: ifnameCopy NULL"); - return; - } - mDNSPlatformMemCopy(ifnameCopy, ifname, len); - ifnameCopy[len] = 0; - } - dispatch_async(HelperQueue, ^{ - kern_return_t kr = KERN_SUCCESS; - int retry = 0, err = 0; - - LogInfo("%s, ifname %s", __func__, ifnameCopy); + mDNSHELPER_DEBUG("mDNSPacketFilterControl: XPC IPC, ifname %s", ifname); + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, p2p_packetfilter); + + xpc_dictionary_set_uint64(dict, "pf_opcode", command); + if (ifname) + xpc_dictionary_set_string(dict, "pf_ifname", ifname); + xpc_dictionary_set_uint64(dict, "pf_count", count); - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSPacketFilterControl(getHelperPort(retry), command, ifnameCopy, count, (uint16_t *)pfa.portArray, (uint16_t *)pfa.protocolArray); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - if (ifnameCopy) - mDNSPlatformMemFree(ifnameCopy); - (void) err; - }); + xpc_dictionary_set_uint64(dict, "pf_port0", pfa.portArray[0]); + xpc_dictionary_set_uint64(dict, "pf_port1", pfa.portArray[1]); + xpc_dictionary_set_uint64(dict, "pf_port2", pfa.portArray[2]); + xpc_dictionary_set_uint64(dict, "pf_port3", pfa.portArray[3]); + + xpc_dictionary_set_uint64(dict, "pf_protocol0", pfa.protocolArray[0]); + xpc_dictionary_set_uint64(dict, "pf_protocol1", pfa.protocolArray[1]); + xpc_dictionary_set_uint64(dict, "pf_protocol2", pfa.protocolArray[2]); + xpc_dictionary_set_uint64(dict, "pf_protocol3", pfa.protocolArray[3]); + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + + mDNSHELPER_DEBUG("mDNSPacketFilterControl: portArray0[%d] portArray1[%d] portArray2[%d] portArray3[%d] protocolArray0[%d] protocolArray1[%d] protocolArray2[%d] protocolArray3[%d]", + pfa.portArray[0], pfa.portArray[1], pfa.portArray[2], pfa.portArray[3], pfa.protocolArray[0], pfa.protocolArray[1], pfa.protocolArray[2], pfa.protocolArray[3]); + } -void mDNSSendKeepalive(v6addr_t sadd, v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win) +void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win) { - struct - { - v6addr_t sadd; - v6addr_t dadd; - } addr; - - mDNSPlatformMemCopy(addr.sadd, sadd, sizeof(v6addr_t)); - mDNSPlatformMemCopy(addr.dadd, dadd, sizeof(v6addr_t)); - - dispatch_async(HelperQueue, ^{ - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - char buf1[INET6_ADDRSTRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - buf1[0] = 0; - buf2[0] = 0; - - inet_ntop(AF_INET6, addr.sadd, buf1, sizeof(buf1)); - inet_ntop(AF_INET6, addr.dadd, buf2, sizeof(buf2)); - LogInfo("%s: sadd is %s, dadd is %s", __func__, buf1, buf2); - - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSSendKeepalive(getHelperPort(retry), (uint8_t *)addr.sadd, (uint8_t *)addr.dadd, lport, rport, seq, ack, win); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - (void) err; - }); + mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]", + lport, rport, seq, ack, win); + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + buf1[0] = 0; + buf2[0] = 0; + + inet_ntop(AF_INET6, sadd, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, dadd, buf2, sizeof(buf2)); + mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: sadd is %s, dadd is %s", buf1, buf2); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, send_keepalive); + + xpc_dictionary_set_data(dict, "send_keepalive_sadd", (uint8_t*)sadd, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "send_keepalive_dadd", (uint8_t*)dadd, sizeof(v6addr_t)); + + xpc_dictionary_set_uint64(dict, "send_keepalive_lport", lport); + xpc_dictionary_set_uint64(dict, "send_keepalive_rport", rport); + xpc_dictionary_set_uint64(dict, "send_keepalive_seq", seq); + xpc_dictionary_set_uint64(dict, "send_keepalive_ack", ack); + xpc_dictionary_set_uint64(dict, "send_keepalive_win", win); + + SendDict_ToServer(dict); + xpc_release(dict); + dict = NULL; + } int mDNSRetrieveTCPInfo(int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid) { - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSRetrieveTCPInfo(getHelperPort(retry), family, (uint8_t *)laddr, lport, (uint8_t *)raddr, rport, seq, ack, win, intfid); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - return err; -} - -void mDNSGetRemoteMAC(mDNS *const m, int family, v6addr_t raddr) -{ - struct { - v6addr_t addr; - } dst; - - mDNSPlatformMemCopy(dst.addr, raddr, sizeof(v6addr_t)); - dispatch_async(HelperQueue, ^{ - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - ethaddr_t eth; - IPAddressMACMapping *addrMapping; - - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSGetRemoteMAC(getHelperPort(retry), family, (uint8_t *)dst.addr, eth); - MACHRETRYLOOP_END(kr, retry, err, fin); - // If the call to get the remote MAC address succeeds, allocate and copy - // the values and schedule a task to update the MAC address in the TCP Keepalive record. - if (kr == KERN_SUCCESS) - { - addrMapping = mDNSPlatformMemAllocate(sizeof(IPAddressMACMapping)); - snprintf(addrMapping->ethaddr, sizeof(addrMapping->ethaddr), "%02x:%02x:%02x:%02x:%02x:%02x", - eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); - if (family == AF_INET) - { - addrMapping->ipaddr.type = mDNSAddrType_IPv4; - mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v4.b, dst.addr, sizeof(v6addr_t)); - } - else - { - addrMapping->ipaddr.type = mDNSAddrType_IPv6; - mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v6.b, dst.addr, sizeof(v6addr_t)); - } - mDNSPlatformDispatchAsync(m, addrMapping, UpdateRMACCallback); - } -fin: - (void) err; - }); - -} - -void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname) -{ - struct { - v6addr_t saddr; - } addr; - mDNSPlatformMemCopy(addr.saddr, spsaddr, sizeof(v6addr_t)); - - dispatch_async(HelperQueue, ^{ - kern_return_t kr = KERN_FAILURE; - int retry = 0, err = 0; - MACHRETRYLOOP_BEGIN(kr, retry, err, fin); - kr = proxy_mDNSStoreSPSMACAddress(getHelperPort(retry), family, (uint8_t *)addr.saddr, ifname); - MACHRETRYLOOP_END(kr, retry, err, fin); -fin: - (void)err; - }); + int error_code = kHelperErr_NotConnected; + xpc_object_t reply_dict = NULL; + + mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] family is[%d]", + lport, rport, family); + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + buf1[0] = 0; + buf2[0] = 0; + + inet_ntop(AF_INET6, laddr, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, raddr, buf2, sizeof(buf2)); + mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo:: Using XPC IPC calling out to Helper: laddr is %s, raddr is %s", buf1, buf2); + + Init_Connection(kHelperService); + + // Create Dictionary To Send + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(dict, kHelperMode, retreive_tcpinfo); + + xpc_dictionary_set_data(dict, "retreive_tcpinfo_laddr", (uint8_t*)laddr, sizeof(v6addr_t)); + xpc_dictionary_set_data(dict, "retreive_tcpinfo_raddr", (uint8_t*)raddr, sizeof(v6addr_t)); + + xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_family", family); + xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_lport", lport); + xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_rport", rport); + + reply_dict = SendDict_GetReply(dict); + + if (reply_dict != NULL) + { + *seq = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_seq"); + *ack = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_ack"); + *win = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_win"); + *intfid = (int32_t)xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_ifid"); + error_code = xpc_dictionary_get_int64(reply_dict, kHelperErrCode); + } + + mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: seq is %d, ack is %d, win is %d, intfid is %d, error is %d", + *seq, *ack, *win, *intfid, error_code); + + if (dict) + xpc_release(dict); + if (reply_dict) + xpc_release(reply_dict); + dict = NULL; + reply_dict = NULL; + + return error_code; } diff --git a/mDNSResponder/mDNSMacOSX/helper.c b/mDNSResponder/mDNSMacOSX/helper.c index 7cf0e523..f5b4f3b2 100644 --- a/mDNSResponder/mDNSMacOSX/helper.c +++ b/mDNSResponder/mDNSMacOSX/helper.c @@ -30,7 +30,6 @@ #include <sys/ioctl.h> #include <sys/param.h> #include <sys/socket.h> -#include <asl.h> #include <ctype.h> #include <dirent.h> #include <errno.h> @@ -53,9 +52,7 @@ #include "dnssd_ipc.h" #include "libpfkey.h" #include "helper.h" -#include "helpermsgServer.h" #include "helper-server.h" -#include "ipsec_options.h" #include "P2PPacketFilter.h" #include <netinet/ip.h> @@ -71,6 +68,7 @@ #ifndef MDNS_NO_IPSEC #define MDNS_NO_IPSEC 1 #endif + #define NO_CFUSERNOTIFICATION 1 #define NO_SECURITYFRAMEWORK 1 #endif @@ -81,79 +79,51 @@ typedef struct sadb_x_policy *ipsec_policy_t; -unsigned short InetChecksum(unsigned short *ptr,int nbytes); -unsigned long in_cksum(unsigned short *ptr,int nbytes); -void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6); - uid_t mDNSResponderUID; gid_t mDNSResponderGID; -void -debug_(const char *func, const char *fmt, ...) -{ - char buf[2048]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - helplog(ASL_LEVEL_DEBUG, "%s: %s", func, buf); -} - -static int -authorized(audit_token_t *token) +void helper_exit() { - int ok = 0; - pid_t pid = (pid_t)-1; - uid_t euid = (uid_t)-1; - - audit_token_to_au32(*token, NULL, &euid, NULL, NULL, NULL, &pid, NULL, - NULL); - ok = (euid == mDNSResponderUID || euid == 0); - if (!ok) - helplog(ASL_LEVEL_NOTICE, - "Unauthorized access by euid=%lu pid=%lu", - (unsigned long)euid, (unsigned long)pid); - return ok; -} - -kern_return_t -do_mDNSExit(__unused mach_port_t port, audit_token_t token) -{ - debug("entry"); - if (!authorized(&token)) - goto fin; - helplog(ASL_LEVEL_INFO, "exit"); + os_log_info(log_handle,"mDNSResponderHelper exiting"); exit(0); - -fin: - debug("fin"); - return KERN_SUCCESS; } -kern_return_t do_mDNSRequestBPF(__unused mach_port_t port, audit_token_t token) +mDNSexport void RequestBPF() { - if (!authorized(&token)) return KERN_SUCCESS; DNSServiceRef ref; + DNSServiceErrorType err = ConnectToServer(&ref, 0, send_bpf, NULL, NULL, NULL); - if (err) { helplog(ASL_LEVEL_ERR, "do_mDNSRequestBPF: ConnectToServer %d", err); return err; } - + if (err) + { + os_log(log_handle, "RequestBPF: ConnectToServer %d", err); + return; + } + char *ptr; size_t len = sizeof(DNSServiceFlags); ipc_msg_hdr *hdr = create_hdr(send_bpf, &len, &ptr, 0, ref); - if (!hdr) { DNSServiceRefDeallocate(ref); return kDNSServiceErr_NoMemory; } + if (!hdr) + { + os_log(log_handle, "RequestBPF: No mem to allocate"); + DNSServiceRefDeallocate(ref); + return; + } + put_flags(0, &ptr); deliver_request(hdr, ref); // Will free hdr for us DNSServiceRefDeallocate(ref); update_idle_timer(); - return KERN_SUCCESS; + + os_log_info(log_handle,"RequestBPF: Successful"); } -kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interval, int *err, audit_token_t token) -{ - *err = -1; - if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; } +void PowerRequest(int key, int interval, int *err) +{ + *err = kHelperErr_DefaultErr; + + os_log_info(log_handle,"PowerRequest: key %d interval %d, err %d", key, interval, *err); + CFArrayRef events = IOPMCopyScheduledPowerEvents(); if (events) { @@ -168,19 +138,26 @@ kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interv CFDateRef EventTime = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTimeKey)); CFStringRef EventType = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTypeKey)); IOReturn result = IOPMCancelScheduledPowerEvent(EventTime, id, EventType); - //helplog(ASL_LEVEL_ERR, "Deleting old event %s"); - if (result) helplog(ASL_LEVEL_ERR, "IOPMCancelScheduledPowerEvent %d failed %d", i, result); + //os_log(log_handle, "Deleting old event %s"); + if (result) + os_log(log_handle, "IOPMCancelScheduledPowerEvent %d failed %d", i, result); } } CFRelease(events); } - - if (key < 0) // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above) - *err = 0; + + if (key < 0) // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above) + { + *err = kHelperErr_NoErr; + } else if (key == 0) // mDNSPowerRequest(0, 0) means "sleep now" { IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL)); - if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSleepSystem %d", r); } + if (r) + { + usleep(100000); + os_log_info(log_handle, "IOPMSleepSystem %d", r); + } *err = r; } else if (key > 0) @@ -189,48 +166,51 @@ kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interv if (wakeTime) { CFMutableDictionaryRef scheduleDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventTimeKey), wakeTime); CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventAppNameKey), CFSTR("mDNSResponderHelper")); CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventTypeKey), key ? CFSTR(kIOPMAutoWake) : CFSTR(kIOPMAutoSleep)); - + IOReturn r = IOPMRequestSysWake(scheduleDict); if (r) { usleep(100000); - helplog(ASL_LEVEL_ERR, "IOPMRequestSysWake(%d) %d %x", interval, r, r); + os_log_info(log_handle, "IOPMRequestSysWake(%d) %d %x", interval, r, r); } *err = r; CFRelease(wakeTime); CFRelease(scheduleDict); } } -fin: + update_idle_timer(); - return KERN_SUCCESS; } -kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int ifindex, int family, v6addr_t ip, ethaddr_t eth, int *err, audit_token_t token) +void SetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err) { - #define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X" - #define IPv6FMTARGS ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15] - #if 0 + +#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X" +#define IPv6FMTARGS ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15] + if (family == 4) - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X", - ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + { + os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X", + ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + } else - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X", - ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); - #endif - - *err = -1; - if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; } - + { + os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X", + ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + } + + *err = kHelperErr_DefaultErr; + static int s = -1, seq = 0; if (s < 0) { s = socket(PF_ROUTE, SOCK_RAW, 0); - if (s < 0) helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno)); + if (s < 0) + os_log(log_handle, "SetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno)); } if (s >= 0) @@ -241,7 +221,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if { struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg; memset(&rtmsg, 0, sizeof(rtmsg)); - + rtmsg.hdr.rtm_msglen = sizeof(rtmsg); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_type = RTM_ADD; @@ -254,7 +234,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if rtmsg.hdr.rtm_use = 0; rtmsg.hdr.rtm_inits = RTV_EXPIRE; rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30; - + rtmsg.dst.sin_len = sizeof(rtmsg.dst); rtmsg.dst.sin_family = AF_INET; rtmsg.dst.sin_port = 0; @@ -262,7 +242,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if rtmsg.dst.sin_srcaddr.s_addr = 0; rtmsg.dst.sin_tos = 0; rtmsg.dst.sin_other = 0; - + rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl); rtmsg.sdl.sdl_family = AF_LINK; rtmsg.sdl.sdl_index = ifindex; @@ -270,26 +250,26 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if rtmsg.sdl.sdl_nlen = 0; rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN; rtmsg.sdl.sdl_slen = 0; - + // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h) memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t)); - + int len = write(s, (char *)&rtmsg, sizeof(rtmsg)); if (len < 0) - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)", + os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)", sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno)); len = read(s, (char *)&rtmsg, sizeof(rtmsg)); if (len < 0 || rtmsg.hdr.rtm_errno) - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d", + os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d", sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno); - - *err = 0; + + *err = kHelperErr_NoErr; } else { struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg; memset(&rtmsg, 0, sizeof(rtmsg)); - + rtmsg.hdr.rtm_msglen = sizeof(rtmsg); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_type = RTM_ADD; @@ -302,14 +282,14 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if rtmsg.hdr.rtm_use = 0; rtmsg.hdr.rtm_inits = RTV_EXPIRE; rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30; - + rtmsg.dst.sin6_len = sizeof(rtmsg.dst); rtmsg.dst.sin6_family = AF_INET6; rtmsg.dst.sin6_port = 0; rtmsg.dst.sin6_flowinfo = 0; rtmsg.dst.sin6_addr = *(struct in6_addr*)ip; rtmsg.dst.sin6_scope_id = ifindex; - + rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl); rtmsg.sdl.sdl_family = AF_LINK; rtmsg.sdl.sdl_index = ifindex; @@ -317,36 +297,33 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if rtmsg.sdl.sdl_nlen = 0; rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN; rtmsg.sdl.sdl_slen = 0; - + // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h) memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t)); - + int len = write(s, (char *)&rtmsg, sizeof(rtmsg)); if (len < 0) - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)", + os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)", sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno)); len = read(s, (char *)&rtmsg, sizeof(rtmsg)); if (len < 0 || rtmsg.hdr.rtm_errno) - helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d", + os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d", sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno); - - *err = 0; + + *err = kHelperErr_NoErr; } - } - -fin: + update_idle_timer(); - return KERN_SUCCESS; } -kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const char *msg, audit_token_t token) -{ - if (!authorized(&token)) return KERN_SUCCESS; +void UserNotify(const char *title, const char *msg) +{ + #ifndef NO_CFUSERNOTIFICATION static const char footer[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses" - " or on debugging builds with ForceAlerts set — i.e. only at Apple — not on customer machines.)"; + " or on debugging builds with ForceAlerts set — i.e. only at Apple — not on customer machines.)"; CFStringRef alertHeader = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); CFStringRef alertBody = CFStringCreateWithCString(NULL, msg, kCFStringEncodingUTF8); CFStringRef alertFooter = CFStringCreateWithCString(NULL, footer, kCFStringEncodingUTF8); @@ -354,18 +331,19 @@ kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const CFRelease(alertBody); CFRelease(alertFooter); int err = CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL); - if (err) helplog(ASL_LEVEL_ERR, "CFUserNotificationDisplayNotice returned %d", err); + if (err) + os_log(log_handle, "CFUserNotificationDisplayNotice returned %d", err); CFRelease(alertHeader); CFRelease(alertMessage); #else (void)title; (void)msg; #endif /* NO_CFUSERNOTIFICATION */ - + update_idle_timer(); - return KERN_SUCCESS; } + char usercompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name the user saw char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the user saw char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences @@ -386,9 +364,9 @@ static CFRunLoopSourceRef gNotificationRLS = NULL; static void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) { - debug("entry"); + os_log_debug(log_handle,"entry"); (void)responseFlags; // Unused - if (userNotification != gNotification) helplog(ASL_LEVEL_ERR, "NotificationCallBackDismissed: Wrong CFUserNotificationRef"); + if (userNotification != gNotification) os_log(log_handle, "NotificationCallBackDismissed: Wrong CFUserNotificationRef"); if (gNotificationRLS) { // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread. @@ -416,7 +394,7 @@ static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef s CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!dictionary) return; - debug("entry"); + os_log_debug(log_handle,"entry"); CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header); CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext); @@ -430,13 +408,13 @@ static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef s { SInt32 error; gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary); - if (!gNotification || error) { helplog(ASL_LEVEL_ERR, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; } + if (!gNotification || error) { os_log(log_handle, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; } gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0); - if (!gNotificationRLS) { helplog(ASL_LEVEL_ERR,"ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; } + if (!gNotificationRLS) { os_log(log_handle, "ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; } // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread. // We need to explicitly specify the desired CFRunLoop to which we want to add this event source. CFRunLoopAddSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode); - debug("gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS); + os_log_debug(log_handle,"gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS); pause_idle_timer(); } @@ -454,9 +432,13 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn // arbitrary computer name the user may choose, this exact text (with zero-width non-breaking space added) // can never be one that occurs in the Localizable.strings translation file. if (!cfoldname) - helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for old=%s", newname); + { + os_log(log_handle, "Could not construct CFStrings for old=%s", newname); + } else if (newname && !cfnewname) - helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for new=%s", newname); + { + os_log(log_handle, "Could not construct CFStrings for new=%s", newname); + } else { const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfoldname, suffix); @@ -465,11 +447,17 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn alertHeader = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); if (!s1) - helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for old=%s", oldname); + { + os_log(log_handle, "Could not construct secondary CFString for old=%s", oldname); + } else if (cfnewname && !s2) - helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for new=%s", newname); + { + os_log(log_handle, "Could not construct secondary CFString for new=%s", newname); + } else if (!alertHeader) - helplog(ASL_LEVEL_ERR, "Could not construct CFArray for notification"); + { + os_log(log_handle, "Could not construct CFArray for notification"); + } else { // Make sure someone is logged in. We don't want this popping up over the login window @@ -490,7 +478,9 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn CFArrayAppendValue(alertHeader, CFSTR(".")); } else + { CFArrayAppendValue(alertHeader, CFSTR("All attempts to find an available name by adding a number to the name were also unsuccessful.")); + } } CFRelease(userName); } @@ -508,7 +498,7 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn static void update_notification(void) { #ifndef NO_CFUSERNOTIFICATION - debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname); + os_log_debug(log_handle,"entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname); if (!CFS_OQ) { // Note: The "\xEF\xBB\xBF" byte sequence (U+FEFF) in the CFS_Format string is the UTF-8 encoding of the zero-width non-breaking space character. @@ -539,7 +529,7 @@ static void update_notification(void) { if (gNotificationRLS) { - debug("canceling notification %p", gNotification); + os_log_debug(log_handle,"canceling notification %p", gNotification); CFUserNotificationCancel(gNotification); unpause_idle_timer(); } @@ -569,8 +559,7 @@ static void update_notification(void) #endif } -kern_return_t -do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, const char* new, audit_token_t token) +void PreferencesSetName(int key, const char* old, const char* new) { SCPreferencesRef session = NULL; Boolean ok = FALSE; @@ -579,37 +568,37 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c char* user = NULL; char* last = NULL; Boolean needUpdate = FALSE; - - debug("entry %s old=%s new=%s", key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new); - if (!authorized(&token)) goto fin; - + + os_log_info(log_handle,"PreferencesSetName: entry %s old=%s new=%s", + key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new); + switch ((enum mDNSPreferencesSetNameKey)key) { - case kmDNSComputerName: - user = usercompname; - last = lastcompname; - break; - case kmDNSLocalHostName: - user = userhostname; - last = lasthostname; - break; - default: - debug("unrecognized key: %d", key); - goto fin; + case kmDNSComputerName: + user = usercompname; + last = lastcompname; + break; + case kmDNSLocalHostName: + user = userhostname; + last = lasthostname; + break; + default: + os_log(log_handle, "PreferencesSetName: unrecognized key: %d", key); + goto fin; } - + if (!last) { - helplog(ASL_LEVEL_ERR, "%s: no last ptr", __func__); + os_log(log_handle, "PreferencesSetName: no last ptr"); goto fin; } - + if (!user) { - helplog(ASL_LEVEL_ERR, "%s: no user ptr", __func__); + os_log(log_handle, "PreferencesSetName:: no user ptr"); goto fin; } - + if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1)) { // old and new are same means the config changed i.e, the user has set something in the preferences pane. @@ -634,7 +623,7 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c needUpdate = TRUE; } } - + // If we are not showing the dialogue, we need to remember the first "old" value so that // we maintain the same through the lifetime of the dialogue. Subsequent conflicts don't // update the "old" value. @@ -643,57 +632,66 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c strncpy(user, old, MAX_DOMAIN_LABEL); needUpdate = TRUE; } - + if (!new[0]) // we've given up trying to construct a name that doesn't conflict goto fin; - + cfstr = CFStringCreateWithCString(NULL, new, kCFStringEncodingUTF8); - - session = SCPreferencesCreate(NULL, CFSTR(kmDNSHelperServiceName), NULL); - + + session = SCPreferencesCreate(NULL, CFSTR(kHelperService), NULL); + if (cfstr == NULL || session == NULL) { - debug("SCPreferencesCreate failed"); + os_log(log_handle, "PreferencesSetName: SCPreferencesCreate failed"); goto fin; } if (!SCPreferencesLock(session, 0)) { - debug("lock failed"); + os_log(log_handle,"PreferencesSetName: lock failed"); goto fin; } locked = TRUE; - + switch ((enum mDNSPreferencesSetNameKey)key) { - case kmDNSComputerName: - { - // We want to write the new Computer Name to System Preferences, without disturbing the user-selected - // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising. - // Note that this encoding is not used for the computer name, but since both are set by the same call, - // we need to take care to set the name without changing the character set. - CFStringEncoding encoding = kCFStringEncodingUTF8; - CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding); - if (unused) { CFRelease(unused); unused = NULL; } - else encoding = kCFStringEncodingUTF8; - - ok = SCPreferencesSetComputerName(session, cfstr, encoding); - } - break; - case kmDNSLocalHostName: - ok = SCPreferencesSetLocalHostName(session, cfstr); - break; - default: - break; - } - + case kmDNSComputerName: + { + // We want to write the new Computer Name to System Preferences, without disturbing the user-selected + // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising. + // Note that this encoding is not used for the computer name, but since both are set by the same call, + // we need to take care to set the name without changing the character set. + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding); + if (unused) + { + CFRelease(unused); + unused = NULL; + } + else + { + encoding = kCFStringEncodingUTF8; + } + + ok = SCPreferencesSetComputerName(session, cfstr, encoding); + } + break; + + case kmDNSLocalHostName: + ok = SCPreferencesSetLocalHostName(session, cfstr); + break; + + default: + break; + } + if (!ok || !SCPreferencesCommitChanges(session) || !SCPreferencesApplyChanges(session)) { - debug("SCPreferences update failed"); + os_log(log_handle, "PreferencesSetName: SCPreferences update failed"); goto fin; } - debug("succeeded"); - + os_log_info(log_handle,"PreferencesSetName: succeeded"); + fin: if (NULL != cfstr) CFRelease(cfstr); @@ -704,10 +702,12 @@ fin: CFRelease(session); } update_idle_timer(); - if (needUpdate) update_notification(); - return KERN_SUCCESS; + if (needUpdate) + update_notification(); + } + enum DNSKeyFormat { formatNotDNSKey, formatDdnsTypeItem, formatDnsPrefixedServiceItem, formatBtmmPrefixedServiceItem @@ -725,8 +725,7 @@ static const char dnsprefix[] = "dns:"; static const char ddns[] = "ddns"; static const char ddnsrev[] = "sndd"; -static enum DNSKeyFormat -getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp) +static enum DNSKeyFormat getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp) { static UInt32 tags[4] = { @@ -741,13 +740,11 @@ getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp) Boolean malformed = FALSE; OSStatus status = noErr; int i = 0; - + *attributesp = NULL; - if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, - &attributeInfo, NULL, &attributes, NULL, NULL))) + if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, &attributeInfo, NULL, &attributes, NULL, NULL))) { - debug("SecKeychainItemCopyAttributesAndData %d - skipping", - status); + os_log_info(log_handle,"getDNSKeyFormat: SecKeychainItemCopyAttributesAndData %d - skipping", status); goto skip; } if (attributeInfo.count != attributes->count) @@ -757,137 +754,127 @@ getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp) malformed = TRUE; if (malformed) { - debug( - "malformed result from SecKeychainItemCopyAttributesAndData - skipping"); + os_log(log_handle, "getDNSKeyFormat: malformed result from SecKeychainItemCopyAttributesAndData - skipping"); goto skip; } + + os_log_info(log_handle,"getDNSKeyFormat: entry (\"%.*s\", \"%.*s\", \"%.*s\")", + (int)attributes->attr[0].length, attributes->attr[0].data, + (int)attributes->attr[1].length, attributes->attr[1].data, + (int)attributes->attr[2].length, attributes->attr[2].data); - debug("entry (\"%.*s\", \"%.*s\", \"%.*s\")", - (int)attributes->attr[0].length, attributes->attr[0].data, - (int)attributes->attr[1].length, attributes->attr[1].data, - (int)attributes->attr[2].length, attributes->attr[2].data); if (attributes->attr[1].length >= MAX_ESCAPED_DOMAIN_NAME + sizeof(dnsprefix)-1) { - debug("kSecServiceItemAttr too long (%u) - skipping", + os_log(log_handle, "getDNSKeyFormat: kSecServiceItemAttr too long (%u) - skipping", (unsigned int)attributes->attr[1].length); goto skip; } if (attributes->attr[2].length >= MAX_ESCAPED_DOMAIN_NAME) { - debug("kSecAccountItemAttr too long (%u) - skipping", + os_log(log_handle, "getDNSKeyFormat: kSecAccountItemAttr too long (%u) - skipping", (unsigned int)attributes->attr[2].length); goto skip; } - if (attributes->attr[1].length >= sizeof(dnsprefix)-1 && - 0 == strncasecmp(attributes->attr[1].data, dnsprefix, - sizeof(dnsprefix)-1)) + if (attributes->attr[1].length >= sizeof(dnsprefix)-1 && 0 == strncasecmp(attributes->attr[1].data, dnsprefix, sizeof(dnsprefix)-1)) format = formatDnsPrefixedServiceItem; - else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 && - 0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1)) + else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 && 0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1)) format = formatBtmmPrefixedServiceItem; - else if (attributes->attr[0].length == sizeof(ddns)-1 && - 0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1)) + else if (attributes->attr[0].length == sizeof(ddns)-1 && 0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1)) format = formatDdnsTypeItem; - else if (attributes->attr[0].length == sizeof(ddnsrev)-1 && - 0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1)) + else if (attributes->attr[0].length == sizeof(ddnsrev)-1 && 0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1)) format = formatDdnsTypeItem; else { - debug("uninterested in this entry"); + os_log_info(log_handle,"getDNSKeyFormat: uninterested in this entry"); goto skip; } + *attributesp = attributes; - debug("accepting this entry"); + os_log_info(log_handle,"getDNSKeyFormat: accepting this entry"); return format; - + skip: SecKeychainItemFreeAttributesAndData(attributes, NULL); return formatNotDNSKey; } // Insert the attributes as defined by mDNSKeyChainAttributes -static CFPropertyListRef -getKeychainItemInfo(SecKeychainItemRef item, - SecKeychainAttributeList *attributes, enum DNSKeyFormat format) +static CFPropertyListRef copyKeychainItemInfo(SecKeychainItemRef item, SecKeychainAttributeList *attributes, enum DNSKeyFormat format) { CFMutableArrayRef entry = NULL; CFDataRef data = NULL; OSStatus status = noErr; UInt32 keylen = 0; void *keyp = 0; - - if (NULL == (entry = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks))) + + if (NULL == (entry = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks))) { - debug("CFArrayCreateMutable failed"); + os_log(log_handle, "copyKeychainItemInfo: CFArrayCreateMutable failed"); goto error; } - + // Insert the Account attribute (kmDNSKcWhere) switch ((enum DNSKeyFormat)format) { - case formatDdnsTypeItem: - data = CFDataCreate(kCFAllocatorDefault, - attributes->attr[1].data, attributes->attr[1].length); - break; - case formatDnsPrefixedServiceItem: - case formatBtmmPrefixedServiceItem: - data = CFDataCreate(kCFAllocatorDefault, - attributes->attr[1].data, attributes->attr[1].length); - break; - default: - assert("unknown DNSKeyFormat value"); - break; + case formatDdnsTypeItem: + data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length); + break; + case formatDnsPrefixedServiceItem: + case formatBtmmPrefixedServiceItem: + data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length); + break; + default: + os_log(log_handle, "copyKeychainItemInfo: unknown DNSKeyFormat value"); + break; } if (NULL == data) { - debug("CFDataCreate for attr[1] failed"); + os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[1] failed"); goto error; } CFArrayAppendValue(entry, data); CFRelease(data); - + // Insert the Where attribute (kmDNSKcAccount) - if (NULL == (data = CFDataCreate(kCFAllocatorDefault, - attributes->attr[2].data, attributes->attr[2].length))) + if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[2].data, attributes->attr[2].length))) { - debug("CFDataCreate for attr[2] failed"); + os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[2] failed"); goto error; } + CFArrayAppendValue(entry, data); CFRelease(data); - + // Insert the Key attribute (kmDNSKcKey) - if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL, - NULL, NULL, &keylen, &keyp))) + if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL, NULL, NULL, &keylen, &keyp))) { - debug("could not retrieve key for \"%.*s\": %d", - (int)attributes->attr[1].length, attributes->attr[1].data, - status); + os_log(log_handle, "copyKeychainItemInfo: could not retrieve key for \"%.*s\": %d", + (int)attributes->attr[1].length, attributes->attr[1].data, status); goto error; } + data = CFDataCreate(kCFAllocatorDefault, keyp, keylen); SecKeychainItemFreeAttributesAndData(NULL, keyp); if (NULL == data) { - debug("CFDataCreate for keyp failed"); + os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for keyp failed"); goto error; } CFArrayAppendValue(entry, data); CFRelease(data); - + // Insert the Name attribute (kmDNSKcName) - if (NULL == (data = CFDataCreate(kCFAllocatorDefault, - attributes->attr[3].data, attributes->attr[3].length))) + if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[3].data, attributes->attr[3].length))) { - debug("CFDataCreate for attr[3] failed"); + os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[3] failed"); goto error; } + CFArrayAppendValue(entry, data); CFRelease(data); return entry; - + error: if (NULL != entry) CFRelease(entry); @@ -895,10 +882,7 @@ error: } #endif -kern_return_t -do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *numsecrets, - __unused vm_offset_t *secrets, __unused mach_msg_type_number_t *secretsCnt, __unused int *err, - __unused audit_token_t token) +void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err) { #ifndef NO_SECURITYFRAMEWORK CFWriteStreamRef stream = NULL; @@ -911,43 +895,34 @@ do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *nums SecKeychainAttributeList *attributes = NULL; enum DNSKeyFormat format; OSStatus status = 0; - - debug("entry"); - *err = 0; + + os_log_info(log_handle,"KeychainGetSecrets: entry"); + *err = kHelperErr_NoErr; *numsecrets = 0; *secrets = (vm_offset_t)NULL; - if (!authorized(&token)) - { - *err = kmDNSHelperNotAuthorized; - goto fin; - } - if (NULL == (keys = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks))) + + if (NULL == (keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks))) { - debug("CFArrayCreateMutable failed"); - *err = kmDNSHelperCreationFailed; + os_log(log_handle, "KeychainGetSecrets: CFArrayCreateMutable failed"); + *err = kHelperErr_ApiErr; goto fin; } if (noErr != (status = SecKeychainCopyDefault(&skc))) { - *err = kmDNSHelperKeychainCopyDefaultFailed; + *err = kHelperErr_ApiErr; goto fin; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if (noErr != (status = SecKeychainSearchCreateFromAttributes(skc, kSecGenericPasswordItemClass, NULL, &search))) { - *err = kmDNSHelperKeychainSearchCreationFailed; + *err = kHelperErr_ApiErr; goto fin; } - for (status = SecKeychainSearchCopyNext(search, &item); - noErr == status; - status = SecKeychainSearchCopyNext(search, &item)) + for (status = SecKeychainSearchCopyNext(search, &item); noErr == status; status = SecKeychainSearchCopyNext(search, &item)) { - if (formatNotDNSKey != (format = getDNSKeyFormat(item, - &attributes)) && - NULL != (entry = getKeychainItemInfo(item, attributes, - format))) + if (formatNotDNSKey != (format = getDNSKeyFormat(item, &attributes)) && + NULL != (entry = copyKeychainItemInfo(item, attributes, format))) { CFArrayAppendValue(keys, entry); CFRelease(entry); @@ -957,41 +932,41 @@ do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *nums } #pragma clang diagnostic pop if (errSecItemNotFound != status) - helplog(ASL_LEVEL_ERR, "%s: SecKeychainSearchCopyNext failed: %d", - __func__, status); - if (NULL == (stream = - CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, - kCFAllocatorDefault))) - { - *err = kmDNSHelperCreationFailed; - debug("CFWriteStreamCreateWithAllocatedBuffers failed"); + os_log(log_handle, "KeychainGetSecrets: SecKeychainSearchCopyNext failed: %d", status); + + if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, kCFAllocatorDefault))) + { + *err = kHelperErr_ApiErr; + os_log(log_handle, "KeychainGetSecrets:CFWriteStreamCreateWithAllocatedBuffers failed"); goto fin; } + CFWriteStreamOpen(stream); - if (0 == CFPropertyListWrite(keys, stream, - kCFPropertyListBinaryFormat_v1_0, 0, NULL)) + if (0 == CFPropertyListWrite(keys, stream, kCFPropertyListBinaryFormat_v1_0, 0, NULL)) { - *err = kmDNSHelperPListWriteFailed; - debug("CFPropertyListWriteToStream failed"); + *err = kHelperErr_ApiErr; + os_log(log_handle, "KeychainGetSecrets:CFPropertyListWriteToStream failed"); goto fin; } - result = CFWriteStreamCopyProperty(stream, - kCFStreamPropertyDataWritten); - if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets, - CFDataGetLength(result), VM_FLAGS_ANYWHERE)) + result = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten); + + if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets, CFDataGetLength(result), VM_FLAGS_ANYWHERE)) { - *err = kmDNSHelperCreationFailed; - debug("vm_allocate failed"); + *err = kHelperErr_ApiErr; + os_log(log_handle, "KeychainGetSecrets: vm_allocate failed"); goto fin; } - CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)), - (void *)*secrets); + + CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)), (void *)*secrets); *secretsCnt = CFDataGetLength(result); *numsecrets = CFArrayGetCount(keys); - debug("succeeded"); - + + os_log_info(log_handle,"KeychainGetSecrets: succeeded"); + fin: - debug("returning %u secrets", *numsecrets); + os_log_info(log_handle,"KeychainGetSecrets: returning numsecrets[%u] secrets[%lu] secrets addr[%p] secretscount[%u]", + *numsecrets, *secrets, secrets, *secretsCnt); + if (NULL != stream) { CFWriteStreamClose(stream); @@ -1006,395 +981,610 @@ fin: if (NULL != skc) CFRelease(skc); update_idle_timer(); - return KERN_SUCCESS; + + *err = KERN_SUCCESS; + #else - return KERN_FAILURE; + + *err = KERN_FAILURE; + #endif + } -#ifndef MDNS_NO_IPSEC -typedef enum _mDNSTunnelPolicyWhich -{ - kmDNSTunnelPolicySetup, - kmDNSTunnelPolicyTeardown, - kmDNSTunnelPolicyGenerate -} mDNSTunnelPolicyWhich; - -// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel -// kmDNSNoTunnel is used for other Policy types -typedef enum _mDNSTunnelType -{ - kmDNSNoTunnel, - kmDNSIPv6IPv4Tunnel, - kmDNSIPv6IPv6Tunnel -} mDNSTunnelType; - -static const uint8_t kWholeV6Mask = 128; - -#endif /* ifndef MDNS_NO_IPSEC */ - -#ifndef MDNS_NO_IPSEC - -static const char g_racoon_config_dir[] = "/var/run/racoon/"; -static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/"; CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; -// Major version 6 is 10.2.x (Jaguar) -// Major version 7 is 10.3.x (Panther) -// Major version 8 is 10.4.x (Tiger) -// Major version 9 is 10.5.x (Leopard) -// Major version 10 is 10.6.x (SnowLeopard) -// Major version 11 is 10.7.x (Lion) -// Major version 12 is 10.8.x (MountainLion) -// Major version 13 is 10.9.x (Mavericks) -// Major version 14 is 10.10.x (Yosemite) -// Major version 15 is 10.11.x (ElCapitan) -static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out) + +void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration) { - int major = 0, minor = 0; - char letter = 0, buildver[256]="<Unknown>"; - CFDictionaryRef vers = _CFCopySystemVersionDictionary(); - if (vers) + int bpf_fd, i, j; + struct ifreq ifr; + char ifname[IFNAMSIZ]; + char packet[512]; + char *ptr = packet; + char bpf_device[12]; + struct ether_addr *ea; + // (void) ip_addr; // unused + // (void) iteration; // unused + + os_log_info(log_handle,"SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]", + eth_addr, ip_addr, ifid, iteration); + + if (if_indextoname(ifid, ifname) == NULL) { - CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey); - if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8); - sscanf(buildver, "%d%c%d", &major, &letter, &minor); - CFRelease(vers); + os_log(log_handle, "SendWakeupPacket: invalid interface index %u", ifid); + return; } - else - helplog(ASL_LEVEL_NOTICE, "_CFCopySystemVersionDictionary failed"); + + ea = ether_aton(eth_addr); + if (ea == NULL) + { + os_log(log_handle, "SendWakeupPacket: invalid ethernet address %s", eth_addr); + return; + } + + for (i = 0; i < 100; i++) + { + snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i); + bpf_fd = open(bpf_device, O_RDWR, 0); + + if (bpf_fd == -1) + continue; + else + break; + } + + if (bpf_fd == -1) + { + os_log(log_handle, "SendWakeupPacket: cannot find a bpf device"); + return; + } + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + + if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0) + { + os_log(log_handle, "SendWakeupPacket: BIOCSETIF failed %s", strerror(errno)); + return; + } + + // 0x00 Destination address + for (i=0; i<6; i++) + *ptr++ = ea->octet[i]; + + // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, + // BPF will fill in the real interface address for us) + for (i=0; i<6; i++) + *ptr++ = 0; + + // 0x0C Ethertype (0x0842) + *ptr++ = 0x08; + *ptr++ = 0x42; + + // 0x0E Wakeup sync sequence + for (i=0; i<6; i++) + *ptr++ = 0xFF; + + // 0x14 Wakeup data + for (j=0; j<16; j++) + for (i=0; i<6; i++) + *ptr++ = ea->octet[i]; + + // 0x74 Password + for (i=0; i<6; i++) + *ptr++ = 0; + + if (write(bpf_fd, packet, ptr - packet) < 0) + { + os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno)); + return; + } + os_log(log_handle, "SendWakeupPacket: sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr); + + // Send a broadcast one to handle ethernet switches that don't flood forward packets with + // unknown mac addresses. + for (i=0; i<6; i++) + packet[i] = 0xFF; + + if (write(bpf_fd, packet, ptr - packet) < 0) + { + os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno)); + return; + } + os_log(log_handle, "SendWakeupPacket: sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr); + + close(bpf_fd); - if (!major) { major=10; letter = 'A'; minor = 190; helplog(ASL_LEVEL_NOTICE, "Note: No Major Build Version number found; assuming 10A190"); } - if (letter_out) *letter_out = letter; - if (minor_out) *minor_out = minor; - return(major); } -static int UseOldRacoon() -{ - static int g_oldRacoon = -1; - if (g_oldRacoon == -1) +// Open the specified port for protocol in the P2P firewall. +void PacketFilterControl(uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray) +{ + int error; + + os_log_info(log_handle,"PacketFilterControl: command %d ifname %s, count %d", + command, ifname, count); + os_log_info(log_handle,"PacketFilterControl: portArray0[%d] portArray1[%d] portArray2[%d] portArray3[%d] protocolArray0[%d] protocolArray1[%d] protocolArray2[%d] protocolArray3[%d]", portArray[0], portArray[1], portArray[2], portArray[3], protocolArray[0], protocolArray[1], protocolArray[2], protocolArray[3]); + + switch (command) { - char letter = 0; - int minor = 0; - g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10); - debug("%s", g_oldRacoon ? "old" : "new"); + case PF_SET_RULES: + error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray); + if (error) + os_log(log_handle, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error)); + break; + + case PF_CLEAR_RULES: + error = P2PPacketFilterClearBonjourRules(); + if (error) + os_log(log_handle, "P2PPacketFilterClearBonjourRules failed %s", strerror(error)); + break; + + default: + os_log(log_handle, "PacketFilterControl: invalid command %d", command); + break; } - return g_oldRacoon; -} - -static int RacoonSignal() -{ - return UseOldRacoon() ? SIGHUP : SIGUSR1; } -static const char* GetRacoonConfigDir() +static unsigned long in_cksum(unsigned short *ptr, int nbytes) { - return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir; + unsigned long sum; + u_short oddbyte; + + /* + * Our algorithm is simple, using a 32-bit accumulator (sum), + * we add sequential 16-bit words to it, and at the end, fold back + * all the carry bits from the top 16 bits into the lower 16 bits. + */ + sum = 0; + while (nbytes > 1) + { + sum += *ptr++; + nbytes -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nbytes == 1) + { + /* make sure top half is zero */ + oddbyte = 0; + + /* one byte only */ + *((u_char *)&oddbyte) = *(u_char *)ptr; + sum += oddbyte; + } + /* Add back carry outs from top 16 bits to low 16 bits. */ + sum = (sum >> 16) + (sum & 0xffff); + + /* add carry */ + sum += (sum >> 16); + + return sum; } -static const char* GetOldRacoonConfigDir() +static unsigned short InetChecksum(unsigned short *ptr, int nbytes) { - return UseOldRacoon() ? NULL : g_racoon_config_dir_old; + unsigned long sum; + + sum = in_cksum(ptr, nbytes); + return (unsigned short)~sum; } -static const char racoon_config_file[] = "anonymous.conf"; -static const char racoon_config_file_orig[] = "anonymous.conf.orig"; - -static const char configHeader[] = "# BackToMyMac\n"; - -static int IsFamiliarRacoonConfiguration(const char* racoon_config_path) +static void TCPCheckSum(int af, struct tcphdr *t, int tcplen, const v6addr_t sadd6, const v6addr_t dadd6) { - int fd = open(racoon_config_path, O_RDONLY); - debug("entry %s", racoon_config_path); - if (0 > fd) + unsigned long sum = 0; + unsigned short *ptr; + + /* TCP header checksum */ + sum = in_cksum((unsigned short *)t, tcplen); + + if (af == AF_INET) { - helplog(ASL_LEVEL_NOTICE, "open \"%s\" failed: %s", racoon_config_path, strerror(errno)); - return 0; + /* Pseudo header */ + ptr = (unsigned short *)sadd6; + sum += *ptr++; + sum += *ptr++; + ptr = (unsigned short *)dadd6; + sum += *ptr++; + sum += *ptr++; } - else + else if (af == AF_INET6) { - char header[sizeof(configHeader)] = {0}; - ssize_t bytesRead = read(fd, header, sizeof(header)-1); - close(fd); - if (bytesRead != sizeof(header)-1) return 0; - return (0 == memcmp(header, configHeader, sizeof(header)-1)); + /* Pseudo header */ + ptr = (unsigned short *)sadd6; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + ptr = (unsigned short *)dadd6; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; + sum += *ptr++; } + + sum += htons(tcplen); + sum += htons(IPPROTO_TCP); + + while (sum >> 16) + sum = (sum >> 16) + (sum & 0xFFFF); + + t->th_sum = ~sum; + } -static void -revertAnonymousRacoonConfiguration(const char* dir) +void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win) { - if (!dir) return; - - debug("entry %s", dir); - - char racoon_config_path[64]; - strlcpy(racoon_config_path, dir, sizeof(racoon_config_path)); - strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path)); + +#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X" +#define IPv6FMTSARGS sadd6[0], sadd6[1], sadd6[2], sadd6[3], sadd6[4], sadd6[5], sadd6[6], sadd6[7], sadd6[8], sadd6[9], sadd6[10], sadd6[11], sadd6[12], sadd6[13], sadd6[14], sadd6[15] +#define IPv6FMTDARGS dadd6[0], dadd6[1], dadd6[2], dadd6[3], dadd6[4], dadd6[5], dadd6[6], dadd6[7], dadd6[8], dadd6[9], dadd6[10], dadd6[11], dadd6[12], dadd6[13], dadd6[14], dadd6[15] - struct stat s; - int ret = stat(racoon_config_path, &s); - debug("stat(%s): %d errno=%d", racoon_config_path, ret, errno); - if (ret == 0) + os_log_info(log_handle, "SendKeepalive: "IPv6FMTSTRING" :space: "IPv6FMTSTRING"", + IPv6FMTSARGS, IPv6FMTDARGS); + + struct packet4 { - if (IsFamiliarRacoonConfiguration(racoon_config_path)) - { - helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path); - unlink(racoon_config_path); - } - else + struct ip ip; + struct tcphdr tcp; + } packet4; + struct packet6 + { + struct tcphdr tcp; + } packet6; + int sock, on; + struct tcphdr *t; + int af; + struct sockaddr_storage ss_to; + struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to; + struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to; + void *packet; + ssize_t packetlen; + char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct msghdr msghdr; + struct iovec iov; + ssize_t len; + + os_log_info(log_handle,"SendKeepalive invoked: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]", + lport, rport, seq, ack, win); + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + buf1[0] = 0; + buf2[0] = 0; + + inet_ntop(AF_INET6, sadd6, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, dadd6, buf2, sizeof(buf2)); + + os_log_info(log_handle,"SendKeepalive invoked: sadd6 is %s, dadd6 is %s", buf1, buf2); + + // all the incoming arguments are in network order + if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0)) + { + af = AF_INET; + memset(&packet4, 0, sizeof (packet4)); + + /* Fill in all the IP header information - should be in host order*/ + packet4.ip.ip_v = 4; /* 4-bit Version */ + packet4.ip.ip_hl = 5; /* 4-bit Header Length */ + packet4.ip.ip_tos = 0; /* 8-bit Type of service */ + packet4.ip.ip_len = 40; /* 16-bit Total length */ + packet4.ip.ip_id = 9864; /* 16-bit ID field */ + packet4.ip.ip_off = 0; /* 13-bit Fragment offset */ + packet4.ip.ip_ttl = 63; /* 8-bit Time To Live */ + packet4.ip.ip_p = IPPROTO_TCP; /* 8-bit Protocol */ + packet4.ip.ip_sum = 0; /* 16-bit Header checksum (below) */ + memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4); + memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4); + + /* IP header checksum */ + packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20); + t = &packet4.tcp; + packet = &packet4; + packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20) + } + else + { + af = AF_INET6; + memset(&packet6, 0, sizeof (packet6)); + t = &packet6.tcp; + packet = &packet6; + // We don't send IPv6 header, hence just the TCP header len (20) + packetlen = 20; + } + + /* Fill in all the TCP header information */ + t->th_sport = lport; /* 16-bit Source port number */ + t->th_dport = rport; /* 16-bit Destination port */ + t->th_seq = seq; /* 32-bit Sequence Number */ + t->th_ack = ack; /* 32-bit Acknowledgement Number */ + t->th_off = 5; /* Data offset */ + t->th_flags = TH_ACK; + t->th_win = win; + t->th_sum = 0; /* 16-bit checksum (below) */ + t->th_urp = 0; /* 16-bit urgent offset */ + + TCPCheckSum(af, t, 20, sadd6, dadd6); + + /* Open up a RAW socket */ + if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0) + { + os_log(log_handle, "SendKeepalive: socket %s", strerror(errno)); + return; + } + + if (af == AF_INET) + { + on = 1; + if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on))) { - helplog(ASL_LEVEL_NOTICE, "\"%s\" does not look familiar, leaving in place", racoon_config_path); + close(sock); + os_log(log_handle, "SendKeepalive: setsockopt %s", strerror(errno)); return; } + + memset(sin_to, 0, sizeof(struct sockaddr_in)); + sin_to->sin_len = sizeof(struct sockaddr_in); + sin_to->sin_family = AF_INET; + memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr)); + sin_to->sin_port = rport; + + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + } - else if (errno != ENOENT) + else { - helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno)); - return; + struct cmsghdr *ctl; + + memset(sin6_to, 0, sizeof(struct sockaddr_in6)); + sin6_to->sin6_len = sizeof(struct sockaddr_in6); + sin6_to->sin6_family = AF_INET6; + memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr)); + + sin6_to->sin6_port = rport; + sin6_to->sin6_flowinfo = 0; + + + msghdr.msg_control = ctlbuf; + msghdr.msg_controllen = sizeof(ctlbuf); + ctl = CMSG_FIRSTHDR(&msghdr); + ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + ctl->cmsg_level = IPPROTO_IPV6; + ctl->cmsg_type = IPV6_PKTINFO; + struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl); + memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr)); + pktinfo->ipi6_ifindex = 0; } - - char racoon_config_path_orig[64]; - strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig)); - strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig)); - - ret = stat(racoon_config_path_orig, &s); - debug("stat(%s): %d errno=%d", racoon_config_path_orig, ret, errno); - if (ret == 0) + + msghdr.msg_name = (struct sockaddr *)&ss_to; + msghdr.msg_namelen = ss_to.ss_len; + iov.iov_base = packet; + iov.iov_len = packetlen; + msghdr.msg_iov = &iov; + msghdr.msg_iovlen = 1; + msghdr.msg_flags = 0; + +again: + len = sendmsg(sock, &msghdr, 0); + if (len == -1) { - if (0 > rename(racoon_config_path_orig, racoon_config_path)) - helplog(ASL_LEVEL_NOTICE, "rename \"%s\" \"%s\" failed: %s", racoon_config_path_orig, racoon_config_path, strerror(errno)); - else - debug("reverted \"%s\" to \"%s\"", racoon_config_path_orig, racoon_config_path); + if (errno == EINTR) + goto again; } - else if (errno != ENOENT) + + if (len != packetlen) { - helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path_orig, strerror(errno)); - return; + os_log(log_handle, "SendKeepalive: sendmsg failed %s", strerror(errno)); } -} + else + { + char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN]; + + inet_ntop(af, (void *)sadd6, source, sizeof(source)); + inet_ntop(af, (void *)dadd6, dest, sizeof(dest)); + + os_log(log_handle, "SendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u", + source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win)); + + } + close(sock); -static void -moveAsideAnonymousRacoonConfiguration(const char* dir) -{ - if (!dir) return; +} - debug("entry %s", dir); - char racoon_config_path[64]; - strlcpy(racoon_config_path, dir, sizeof(racoon_config_path)); - strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path)); +void RetrieveTCPInfo(int family, const v6addr_t laddr, uint16_t lport, const v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, int *err) +{ + + struct tcp_info ti; + struct info_tuple itpl; + int mib[4]; + unsigned int miblen; + size_t len; + size_t sz; + + memset(&itpl, 0, sizeof(struct info_tuple)); + memset(&ti, 0, sizeof(struct tcp_info)); + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + buf1[0] = 0; + buf2[0] = 0; + + inet_ntop(AF_INET6, laddr, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, raddr, buf2, sizeof(buf2)); + + os_log_info(log_handle, "RetrieveTCPInfo invoked: laddr is %s, raddr is %s", buf1, buf2); + + os_log_info(log_handle,"RetrieveTCPInfo invoked: lport is[%d] rport is[%d] family is [%d]", + lport, rport, family); - struct stat s; - int ret = stat(racoon_config_path, &s); - if (ret == 0) + if (family == AF_INET) { - if (IsFamiliarRacoonConfiguration(racoon_config_path)) - { - helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path); - unlink(racoon_config_path); - } - else - { - char racoon_config_path_orig[64]; - strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig)); - strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig)); - if (0 > rename(racoon_config_path, racoon_config_path_orig)) // If we didn't write it, move it to the side so it can be reverted later - helplog(ASL_LEVEL_NOTICE, "rename \"%s\" to \"%s\" failed: %s", racoon_config_path, racoon_config_path_orig, strerror(errno)); - else - debug("successfully renamed \"%s\" to \"%s\"", racoon_config_path, racoon_config_path_orig); - } + memcpy(&itpl.itpl_local_sin.sin_addr, laddr, sizeof(struct in_addr)); + memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr)); + itpl.itpl_local_sin.sin_port = lport; + itpl.itpl_remote_sin.sin_port = rport; + itpl.itpl_local_sin.sin_family = AF_INET; + itpl.itpl_remote_sin.sin_family = AF_INET; } - else if (errno != ENOENT) + else { - helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno)); - return; + memcpy(&itpl.itpl_local_sin6.sin6_addr, laddr, sizeof(struct in6_addr)); + memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr)); + itpl.itpl_local_sin6.sin6_port = lport; + itpl.itpl_remote_sin6.sin6_port = rport; + itpl.itpl_local_sin6.sin6_family = AF_INET6; + itpl.itpl_remote_sin6.sin6_family = AF_INET6; } -} - -static int -ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir) -{ - struct stat s; - int ret = stat(racoon_config_dir, &s); - if (ret != 0) + itpl.itpl_proto = IPPROTO_TCP; + sz = sizeof(mib)/sizeof(mib[0]); + if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1) { - if (errno != ENOENT) - { - helplog(ASL_LEVEL_ERR, "stat of \"%s\" failed (%d): %s", - racoon_config_dir, ret, strerror(errno)); - return -1; - } - else - { - ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - if (ret != 0) - { - helplog(ASL_LEVEL_ERR, "mkdir \"%s\" failed: %s", - racoon_config_dir, strerror(errno)); - return -1; - } - else - helplog(ASL_LEVEL_INFO, "created directory \"%s\"", racoon_config_dir); - } + os_log(log_handle, "RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno)); + *err = errno; } - else if (!(s.st_mode & S_IFDIR)) + miblen = (unsigned int)sz; + len = sizeof(struct tcp_info); + if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1) { - helplog(ASL_LEVEL_ERR, "\"%s\" is not a directory!", - racoon_config_dir); - return -1; + os_log(log_handle, "RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno)); + *err = errno; } - - return 0; + + *seq = ti.tcpi_snd_nxt - 1; + *ack = ti.tcpi_rcv_nxt; + *win = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale; + *intfid = ti.tcpi_last_outif; + *err = KERN_SUCCESS; + } -static int -createAnonymousRacoonConfiguration(const char *fqdn) -{ - static const char config1[] = - "remote anonymous {\n" - " exchange_mode aggressive;\n" - " doi ipsec_doi;\n" - " situation identity_only;\n" - " verify_identifier off;\n" - " generate_policy on;\n" - " shared_secret keychain_by_id \""; - static const char config2[] = - "\";\n" - " nonce_size 16;\n" - " lifetime time 15 min;\n" - " initial_contact on;\n" - " support_proxy on;\n" - " nat_traversal force;\n" - " proposal_check claim;\n" - " proposal {\n" - " encryption_algorithm aes;\n" - " hash_algorithm sha256;\n" - " authentication_method pre_shared_key;\n" - " dh_group 2;\n" - " lifetime time 15 min;\n" - " }\n" - " proposal {\n" - " encryption_algorithm aes;\n" - " hash_algorithm sha1;\n" - " authentication_method pre_shared_key;\n" - " dh_group 2;\n" - " lifetime time 15 min;\n" - " }\n" - "}\n\n" - "sainfo anonymous { \n" - " pfs_group 2;\n" - " lifetime time 10 min;\n" - " encryption_algorithm aes;\n" - " authentication_algorithm hmac_sha256,hmac_sha1;\n" - " compression_algorithm deflate;\n" - "}\n"; - char tmp_config_path[64]; - char racoon_config_path[64]; - const char* const racoon_config_dir = GetRacoonConfigDir(); - const char* const racoon_config_dir_old = GetOldRacoonConfigDir(); - int fd = -1; - - debug("entry"); - - if (0 > ensureExistenceOfRacoonConfigDir(racoon_config_dir)) - return -1; - - strlcpy(tmp_config_path, racoon_config_dir, sizeof(tmp_config_path)); - strlcat(tmp_config_path, "tmp.XXXXXX", sizeof(tmp_config_path)); +#ifndef MDNS_NO_IPSEC - fd = mkstemp(tmp_config_path); +static const char configHeader[] = "# BackToMyMac\n"; +static const char g_racoon_config_dir[] = "/var/run/racoon/"; +static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/"; - if (0 > fd) +static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out) +{ + int major = 0, minor = 0; + char letter = 0, buildver[256]="<Unknown>"; + CFDictionaryRef vers = _CFCopySystemVersionDictionary(); + if (vers) { - helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s", - tmp_config_path, strerror(errno)); - return -1; + CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey); + if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8); + sscanf(buildver, "%d%c%d", &major, &letter, &minor); + CFRelease(vers); } - write(fd, configHeader, sizeof(configHeader)-1); - write(fd, config1, sizeof(config1)-1); - write(fd, fqdn, strlen(fqdn)); - write(fd, config2, sizeof(config2)-1); - close(fd); - - strlcpy(racoon_config_path, racoon_config_dir, sizeof(racoon_config_path)); - strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path)); - - moveAsideAnonymousRacoonConfiguration(racoon_config_dir_old); - moveAsideAnonymousRacoonConfiguration(racoon_config_dir); + else + os_log_info(log_handle, "_CFCopySystemVersionDictionary failed"); + + if (!major) { major=16; letter = 'A'; minor = 300; os_log_info(log_handle, "Note: No Major Build Version number found; assuming 16A300"); } + if (letter_out) *letter_out = letter; + if (minor_out) *minor_out = minor; + return(major); +} - if (0 > rename(tmp_config_path, racoon_config_path)) +static int UseOldRacoon() +{ + static int g_oldRacoon = -1; + + if (g_oldRacoon == -1) { - unlink(tmp_config_path); - helplog(ASL_LEVEL_ERR, "rename \"%s\" \"%s\" failed: %s", - tmp_config_path, racoon_config_path, strerror(errno)); - revertAnonymousRacoonConfiguration(racoon_config_dir_old); - revertAnonymousRacoonConfiguration(racoon_config_dir); - return -1; + char letter = 0; + int minor = 0; + g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10); + os_log_debug(log_handle, "%s", g_oldRacoon ? "old" : "new"); } + + return g_oldRacoon; +} - debug("successfully renamed \"%s\" \"%s\"", tmp_config_path, racoon_config_path); - return 0; +static int RacoonSignal() +{ + return UseOldRacoon() ? SIGHUP : SIGUSR1; } -static int -notifyRacoon(void) +static int notifyRacoon(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); static const char racoon_pid_path[] = "/var/run/racoon.pid"; char buf[] = "18446744073709551615"; /* largest 64-bit integer */ char *p = NULL; ssize_t n = 0; unsigned long m = 0; int fd = open(racoon_pid_path, O_RDONLY); - + if (0 > fd) { - debug("open \"%s\" failed, and that's OK: %s", racoon_pid_path, + os_log_debug(log_handle,"open \"%s\" failed, and that's OK: %s", racoon_pid_path, strerror(errno)); - return kmDNSHelperRacoonNotificationFailed; + return kHelperErr_RacoonNotificationFailed; } n = read(fd, buf, sizeof(buf)-1); close(fd); if (1 > n) { - debug("read of \"%s\" failed: %s", racoon_pid_path, + os_log_debug(log_handle,"read of \"%s\" failed: %s", racoon_pid_path, n == 0 ? "empty file" : strerror(errno)); - return kmDNSHelperRacoonNotificationFailed; + return kHelperErr_RacoonNotificationFailed; } buf[n] = '\0'; m = strtoul(buf, &p, 10); if (*p != '\0' && !isspace(*p)) { - debug("invalid PID \"%s\" (around '%c')", buf, *p); - return kmDNSHelperRacoonNotificationFailed; + os_log_debug(log_handle,"invalid PID \"%s\" (around '%c')", buf, *p); + return kHelperErr_RacoonNotificationFailed; } if (2 > m) { - debug("refusing to kill PID %lu", m); - return kmDNSHelperRacoonNotificationFailed; + os_log_debug(log_handle,"refusing to kill PID %lu", m); + return kHelperErr_RacoonNotificationFailed; } if (0 != kill(m, RacoonSignal())) { - debug("Could not signal racoon (%lu): %s", m, strerror(errno)); - return kmDNSHelperRacoonNotificationFailed; + os_log_debug(log_handle,"Could not signal racoon (%lu): %s", m, strerror(errno)); + return kHelperErr_RacoonNotificationFailed; } - debug("Sent racoon (%lu) signal %d", m, RacoonSignal()); + + os_log_debug(log_handle, "Sent racoon (%lu) signal %d", m, RacoonSignal()); return 0; } -static void -closefds(int from) +static const char* GetRacoonConfigDir() +{ + return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir; +} +/* +static const char* GetOldRacoonConfigDir() +{ + return UseOldRacoon() ? NULL : g_racoon_config_dir_old; +} +*/ + +static void closefds(int from) { int fd = 0; struct dirent entry, *entryp = NULL; DIR *dirp = opendir("/dev/fd"); - + if (dirp == NULL) { /* fall back to the erroneous getdtablesize method */ @@ -1411,60 +1601,59 @@ closefds(int from) closedir(dirp); } -static int -startRacoonOld(void) + +static int startRacoonOld(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); char * const racoon_args[] = { "/usr/sbin/racoon", "-e", NULL }; ssize_t n = 0; pid_t pid = 0; int status = 0; - + if (0 == (pid = fork())) { closefds(0); execve(racoon_args[0], racoon_args, NULL); - helplog(ASL_LEVEL_ERR, "execve of \"%s\" failed: %s", + os_log_info(log_handle, "execve of \"%s\" failed: %s", racoon_args[0], strerror(errno)); exit(2); } - helplog(ASL_LEVEL_NOTICE, "racoon (pid=%lu) started", + os_log_info(log_handle,"racoon (pid=%lu) started", (unsigned long)pid); n = waitpid(pid, &status, 0); if (-1 == n) { - helplog(ASL_LEVEL_ERR, "Unexpected waitpid failure: %s", + os_log(log_handle, "Unexpected waitpid failure: %s", strerror(errno)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } else if (pid != n) { - helplog(ASL_LEVEL_ERR, "Unexpected waitpid return value %d", - (int)n); - return kmDNSHelperRacoonStartFailed; + os_log(log_handle, "Unexpected waitpid return value %d", (int)n); + return kHelperErr_RacoonStartFailed; } else if (WIFSIGNALED(status)) { - helplog(ASL_LEVEL_ERR, + os_log(log_handle, "racoon (pid=%lu) terminated due to signal %d", (unsigned long)pid, WTERMSIG(status)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } else if (WIFSTOPPED(status)) { - helplog(ASL_LEVEL_ERR, + os_log(log_handle, "racoon (pid=%lu) has stopped due to signal %d", (unsigned long)pid, WSTOPSIG(status)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } else if (0 != WEXITSTATUS(status)) { - helplog(ASL_LEVEL_ERR, + os_log(log_handle, "racoon (pid=%lu) exited with status %d", (unsigned long)pid, WEXITSTATUS(status)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } - debug("racoon (pid=%lu) daemonized normally", (unsigned long)pid); + os_log_debug(log_handle, "racoon (pid=%lu) daemonized normally", (unsigned long)pid); return 0; } @@ -1480,18 +1669,17 @@ typedef struct vpnctl_hdr_struct u_int16_t len; } vpnctl_hdr; -static int -startRacoon(void) +static int startRacoon(void) { - debug("entry"); + os_log_debug(log_handle,"entry"); int fd = socket(PF_UNIX, SOCK_STREAM, 0); if (0 > fd) { - helplog(ASL_LEVEL_ERR, "Could not create endpoint for racoon control socket: %d %s", + os_log(log_handle,"Could not create endpoint for racoon control socket: %d %s", errno, strerror(errno)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } - + struct sockaddr_un saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sun_family = AF_UNIX; @@ -1501,52 +1689,50 @@ startRacoon(void) int result = connect(fd, (struct sockaddr*) &saddr, saddr.sun_len); if (0 > result) { - helplog(ASL_LEVEL_ERR, "Could not connect racoon control socket %s: %d %s", + os_log(log_handle, "Could not connect racoon control socket %s: %d %s", racoon_control_sock_path, errno, strerror(errno)); - return kmDNSHelperRacoonStartFailed; + return kHelperErr_RacoonStartFailed; } - + u_int32_t btmm_cookie = 0x4d4d5442; vpnctl_hdr h = { htons(VPNCTL_CMD_PING), 0, btmm_cookie, 0, 0, 0 }; size_t bytes = 0; ssize_t ret = 0; - + while (bytes < sizeof(vpnctl_hdr)) { ret = write(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes); if (ret == -1) { - helplog(ASL_LEVEL_ERR, "Could not write to racoon control socket: %d %s", - errno, strerror(errno)); - return kmDNSHelperRacoonStartFailed; + os_log(log_handle, "Could not write to racoon control socket: %d %s", errno, strerror(errno)); + return kHelperErr_RacoonStartFailed; } bytes += ret; } - + int nfds = fd + 1; fd_set fds; int counter = 0; struct timeval tv; bytes = 0; h.cookie = 0; - + for (counter = 0; counter < 100; counter++) { FD_ZERO(&fds); FD_SET(fd, &fds); tv = (struct timeval){ 0, 10000 }; // 10 milliseconds * 100 iterations = 1 second max wait time - + result = select(nfds, &fds, (fd_set*)NULL, (fd_set*)NULL, &tv); if (result > 0) { if (FD_ISSET(fd, &fds)) { ret = read(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes); - + if (ret == -1) { - helplog(ASL_LEVEL_ERR, "Could not read from racoon control socket: %d %s", - strerror(errno)); + os_log(log_handle,"Could not read from racoon control socket: %d %s", errno, strerror(errno)); break; } bytes += ret; @@ -1554,72 +1740,53 @@ startRacoon(void) } else { - debug("select returned but fd_isset not on expected fd\n"); + os_log_debug(log_handle, "select returned but fd_isset not on expected fd"); } } else if (result < 0) { - debug("select returned %d errno %d %s\n", result, errno, strerror(errno)); + os_log_debug(log_handle, "select returned %d errno %d %s", result, errno, strerror(errno)); if (errno != EINTR) break; } } - + close(fd); - - if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie) return kmDNSHelperRacoonStartFailed; - - debug("racoon started"); + + if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie) + return kHelperErr_RacoonStartFailed; + + os_log_debug(log_handle, "racoon started"); return 0; } -static int -kickRacoon(void) +static int kickRacoon(void) { if ( 0 == notifyRacoon() ) return 0; return UseOldRacoon() ? startRacoonOld() : startRacoon(); } -#endif /* ndef MDNS_NO_IPSEC */ - -int -do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *fqdn, audit_token_t token) +typedef enum _mDNSTunnelPolicyWhich { -#ifndef MDNS_NO_IPSEC - debug("entry"); - if (!authorized(&token)) goto fin; - - switch ((enum mDNSUpDown)updown) - { - case kmDNSUp: - if (0 != createAnonymousRacoonConfiguration(fqdn)) goto fin; - break; - case kmDNSDown: - revertAnonymousRacoonConfiguration(GetOldRacoonConfigDir()); - revertAnonymousRacoonConfiguration(GetRacoonConfigDir()); - break; - default: - goto fin; - } - - if (0 != kickRacoon()) - goto fin; - debug("succeeded"); + kmDNSTunnelPolicySetup, + kmDNSTunnelPolicyTeardown, + kmDNSTunnelPolicyGenerate +} mDNSTunnelPolicyWhich; -fin: -#else - (void)port; (void)updown; (void)fqdn; (void)token; -#endif - update_idle_timer(); - return KERN_SUCCESS; -} +// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel +// kmDNSNoTunnel is used for other Policy types +typedef enum _mDNSTunnelType +{ + kmDNSNoTunnel, + kmDNSIPv6IPv4Tunnel, + kmDNSIPv6IPv6Tunnel +} mDNSTunnelType; -#ifndef MDNS_NO_IPSEC +static const uint8_t kWholeV6Mask = 128; static unsigned int routeSeq = 1; -static int -setupTunnelRoute(v6addr_t local, v6addr_t remote) +static int setupTunnelRoute(const v6addr_t local, const v6addr_t remote) { struct { @@ -1629,14 +1796,15 @@ setupTunnelRoute(v6addr_t local, v6addr_t remote) } msg; int err = 0; int s = -1; - + if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET))) { - helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s", - strerror(errno)); - err = kmDNSHelperRoutingSocketCreationFailed; + os_log(log_handle,"socket(PF_ROUTE, ...) failed: %s", strerror(errno)); + + err = kHelperErr_RoutingSocketCreationFailed; goto fin; } + memset(&msg, 0, sizeof(msg)); msg.hdr.rtm_msglen = sizeof(msg); msg.hdr.rtm_type = RTM_ADD; @@ -1647,36 +1815,35 @@ setupTunnelRoute(v6addr_t local, v6addr_t remote) msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; msg.hdr.rtm_inits = RTV_MTU; msg.hdr.rtm_rmx.rmx_mtu = 1280; - + msg.dst.sin6_len = sizeof(msg.dst); msg.dst.sin6_family = AF_INET6; memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr)); - + msg.gtwy.sin6_len = sizeof(msg.gtwy); msg.gtwy.sin6_family = AF_INET6; memcpy(&msg.gtwy.sin6_addr, local, sizeof(msg.gtwy.sin6_addr)); - + /* send message, ignore error when route already exists */ if (0 > write(s, &msg, msg.hdr.rtm_msglen)) { int errno_ = errno; - - debug("write to routing socket failed: %s", strerror(errno_)); + + os_log_info(log_handle,"write to routing socket failed: %s", strerror(errno_)); if (EEXIST != errno_) { - err = kmDNSHelperRouteAdditionFailed; + err = kHelperErr_RouteAdditionFailed; goto fin; } } - + fin: if (0 <= s) close(s); return err; } -static int -teardownTunnelRoute(v6addr_t remote) +static int teardownTunnelRoute(const v6addr_t remote) { struct { @@ -1685,75 +1852,113 @@ teardownTunnelRoute(v6addr_t remote) } msg; int err = 0; int s = -1; - + if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET))) { - helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s", - strerror(errno)); - err = kmDNSHelperRoutingSocketCreationFailed; + os_log(log_handle, "socket(PF_ROUTE, ...) failed: %s", strerror(errno)); + err = kHelperErr_RoutingSocketCreationFailed; goto fin; } memset(&msg, 0, sizeof(msg)); - + msg.hdr.rtm_msglen = sizeof(msg); msg.hdr.rtm_type = RTM_DELETE; msg.hdr.rtm_version = RTM_VERSION; msg.hdr.rtm_seq = routeSeq++; msg.hdr.rtm_addrs = RTA_DST; - + msg.dst.sin6_len = sizeof(msg.dst); msg.dst.sin6_family = AF_INET6; memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr)); if (0 > write(s, &msg, msg.hdr.rtm_msglen)) { int errno_ = errno; - - debug("write to routing socket failed: %s", strerror(errno_)); + + os_log_debug(log_handle,"write to routing socket failed: %s", strerror(errno_)); + if (ESRCH != errno_) { - err = kmDNSHelperRouteDeletionFailed; + err = kHelperErr_RouteDeletionFailed; goto fin; } } - + fin: if (0 <= s) close(s); return err; } -static int -v4addr_to_string(v4addr_t addr, char *buf, size_t buflen) +static int v4addr_to_string(v4addr_t addr, char *buf, size_t buflen) { if (NULL == inet_ntop(AF_INET, addr, buf, buflen)) { - helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", - strerror(errno)); - return kmDNSHelperInvalidNetworkAddress; + os_log(log_handle, "v4addr_to_string() inet_ntop failed: %s", strerror(errno)); + return kHelperErr_InvalidNetworkAddress; } else + { return 0; + } } -static int -v6addr_to_string(v6addr_t addr, char *buf, size_t buflen) +static int v6addr_to_string(const v6addr_t addr, char *buf, size_t buflen) { if (NULL == inet_ntop(AF_INET6, addr, buf, buflen)) { - helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", - strerror(errno)); - return kmDNSHelperInvalidNetworkAddress; + os_log(log_handle, "v6addr_to_string inet_ntop failed: %s", strerror(errno)); + return kHelperErr_InvalidNetworkAddress; } else + { return 0; + } +} + +static int ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir) +{ + struct stat s; + int ret = stat(racoon_config_dir, &s); + if (ret != 0) + { + if (errno != ENOENT) + { + os_log(log_handle, "stat of \"%s\" failed (%d): %s", + racoon_config_dir, ret, strerror(errno)); + return -1; + } + else + { + ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + if (ret != 0) + { + os_log(log_handle, "mkdir \"%s\" failed: %s", + racoon_config_dir, strerror(errno)); + return -1; + } + else + { + os_log_info(log_handle, "created directory \"%s\"", racoon_config_dir); + } + } + } + else if (!(s.st_mode & S_IFDIR)) + { + os_log(log_handle, "\"%s\" is not a directory!", + racoon_config_dir); + return -1; + } + + return 0; } + + /* Caller owns object returned in `policy' */ -static int -generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in, +static int generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in, v4addr_t src, uint16_t src_port, v4addr_t dst, uint16_t dst_port, - v6addr_t src6, v6addr_t dst6, + const v6addr_t src6, const v6addr_t dst6, ipsec_policy_t *policy, size_t *len) { char srcs[INET_ADDRSTRLEN], dsts[INET_ADDRSTRLEN]; @@ -1762,132 +1967,134 @@ generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in, char *inOut = in ? "in" : "out"; ssize_t n = 0; int err = 0; - + *policy = NULL; *len = 0; - + switch (which) { - case kmDNSTunnelPolicySetup: - if (type == kmDNSIPv6IPv4Tunnel) - { - if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs)))) - goto fin; - if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts)))) - goto fin; - n = snprintf(buf, sizeof(buf), - "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require", - inOut, srcs, src_port, dsts, dst_port); - } - else if (type == kmDNSIPv6IPv6Tunnel) - { - if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6)))) - goto fin; - if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6)))) - goto fin; - n = snprintf(buf, sizeof(buf), - "%s ipsec esp/tunnel/%s-%s/require", - inOut, srcs6, dsts6); - } - break; - case kmDNSTunnelPolicyTeardown: - n = strlcpy(buf, inOut, sizeof(buf)); - break; - case kmDNSTunnelPolicyGenerate: - n = snprintf(buf, sizeof(buf), "%s generate", inOut); - break; - default: - err = kmDNSHelperIPsecPolicyCreationFailed; - goto fin; + case kmDNSTunnelPolicySetup: + if (type == kmDNSIPv6IPv4Tunnel) + { + if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs)))) + goto fin; + if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts)))) + goto fin; + n = snprintf(buf, sizeof(buf), + "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require", + inOut, srcs, src_port, dsts, dst_port); + } + else if (type == kmDNSIPv6IPv6Tunnel) + { + if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6)))) + goto fin; + if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6)))) + goto fin; + n = snprintf(buf, sizeof(buf), + "%s ipsec esp/tunnel/%s-%s/require", + inOut, srcs6, dsts6); + } + break; + case kmDNSTunnelPolicyTeardown: + n = strlcpy(buf, inOut, sizeof(buf)); + break; + case kmDNSTunnelPolicyGenerate: + n = snprintf(buf, sizeof(buf), "%s generate", inOut); + break; + default: + err = kHelperErr_IPsecPolicyCreationFailed; + goto fin; } - + if (n >= (int)sizeof(buf)) { - err = kmDNSHelperResultTooLarge; + err = kHelperErr_ResultTooLarge; goto fin; } - - debug("policy=\"%s\"", buf); + + os_log_info(log_handle, "policy=\"%s\"", buf); + if (NULL == (*policy = (ipsec_policy_t)ipsec_set_policy(buf, n))) { - helplog(ASL_LEVEL_ERR, - "Could not create IPsec policy from \"%s\"", buf); - err = kmDNSHelperIPsecPolicyCreationFailed; + os_log_info(log_handle, "Could not create IPsec policy from \"%s\"", buf); + err = kHelperErr_IPsecPolicyCreationFailed; goto fin; } *len = ((ipsec_policy_t)(*policy))->sadb_x_policy_len * 8; - + fin: return err; } -static int -sendPolicy(int s, int setup, +static int sendPolicy(int s, int setup, struct sockaddr *src, uint8_t src_bits, struct sockaddr *dst, uint8_t dst_bits, ipsec_policy_t policy, size_t len) { static unsigned int policySeq = 0; int err = 0; - - debug("entry, setup=%d", setup); + + os_log_debug(log_handle, "entry, setup=%d", setup); + if (setup) err = pfkey_send_spdadd(s, src, src_bits, dst, dst_bits, -1, (char *)policy, len, policySeq++); else err = pfkey_send_spddelete(s, src, src_bits, dst, dst_bits, -1, (char *)policy, len, policySeq++); + if (0 > err) { - helplog(ASL_LEVEL_ERR, "Could not set IPsec policy: %s", - ipsec_strerror()); - err = kmDNSHelperIPsecPolicySetFailed; + os_log(log_handle, "Could not set IPsec policy: %s", ipsec_strerror()); + err = kHelperErr_IPsecPolicySetFailed; goto fin; } else + { err = 0; - debug("succeeded"); - + } + + os_log_debug(log_handle, "succeeded"); + fin: return err; } -static int -removeSA(int s, struct sockaddr *src, struct sockaddr *dst) +static int removeSA(int s, struct sockaddr *src, struct sockaddr *dst) { int err = 0; - - debug("entry"); + + os_log_debug(log_handle, "entry"); + err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, src, dst); if (0 > err) { - helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror()); - err = kmDNSHelperIPsecRemoveSAFailed; + os_log(log_handle, "Could not remove IPsec SA: %s", ipsec_strerror()); + err = kHelperErr_IPsecRemoveSAFailed; goto fin; } err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, dst, src); if (0 > err) { - helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror()); - err = kmDNSHelperIPsecRemoveSAFailed; + os_log(log_handle, "Could not remove IPsec SA: %s", ipsec_strerror()); + err = kHelperErr_IPsecRemoveSAFailed; goto fin; } else err = 0; - - debug("succeeded"); - + + os_log_debug(log_handle, "succeeded"); + fin: return err; } -static int -doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, - v6addr_t loc_inner, uint8_t loc_bits, +static int doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, + const v6addr_t loc_inner, uint8_t loc_bits, v4addr_t loc_outer, uint16_t loc_port, - v6addr_t rmt_inner, uint8_t rmt_bits, + const v6addr_t rmt_inner, uint8_t rmt_bits, v4addr_t rmt_outer, uint16_t rmt_port, - v6addr_t loc_outer6, v6addr_t rmt_outer6) + const v6addr_t loc_outer6, const v6addr_t rmt_outer6) { struct sockaddr_in6 sin6_loc; struct sockaddr_in6 sin6_rmt; @@ -1895,47 +2102,48 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, size_t len = 0; int s = -1; int err = 0; - - debug("entry"); + + os_log_debug(log_handle,"entry"); if (0 > (s = pfkey_open())) { - helplog(ASL_LEVEL_ERR, - "Could not create IPsec policy socket: %s", - ipsec_strerror()); - err = kmDNSHelperIPsecPolicySocketCreationFailed; + os_log(log_handle, "Could not create IPsec policy socket: %s", ipsec_strerror()); + err = kHelperErr_IPsecPolicySocketCreationFailed; goto fin; } - + memset(&sin6_loc, 0, sizeof(sin6_loc)); sin6_loc.sin6_len = sizeof(sin6_loc); sin6_loc.sin6_family = AF_INET6; sin6_loc.sin6_port = htons(0); memcpy(&sin6_loc.sin6_addr, loc_inner, sizeof(sin6_loc.sin6_addr)); - + memset(&sin6_rmt, 0, sizeof(sin6_rmt)); sin6_rmt.sin6_len = sizeof(sin6_rmt); sin6_rmt.sin6_family = AF_INET6; sin6_rmt.sin6_port = htons(0); memcpy(&sin6_rmt.sin6_addr, rmt_inner, sizeof(sin6_rmt.sin6_addr)); - + int setup = which != kmDNSTunnelPolicyTeardown; - + if (0 != (err = generateTunnelPolicy(which, type, 1, rmt_outer, rmt_port, loc_outer, loc_port, rmt_outer6, loc_outer6, &policy, &len))) goto fin; + if (0 != (err = sendPolicy(s, setup, (struct sockaddr *)&sin6_rmt, rmt_bits, (struct sockaddr *)&sin6_loc, loc_bits, policy, len))) goto fin; + if (NULL != policy) { free(policy); policy = NULL; } + if (0 != (err = generateTunnelPolicy(which, type, 0, loc_outer, loc_port, rmt_outer, rmt_port, @@ -1947,7 +2155,7 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, (struct sockaddr *)&sin6_rmt, rmt_bits, policy, len))) goto fin; - + if (which == kmDNSTunnelPolicyTeardown) { if (rmt_port) // Outer tunnel is IPv4 @@ -1960,7 +2168,7 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, sin_loc.sin_len = sizeof(sin_loc); sin_loc.sin_family = AF_INET; memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr)); - + memset(&sin_rmt, 0, sizeof(sin_rmt)); sin_rmt.sin_len = sizeof(sin_rmt); sin_rmt.sin_family = AF_INET; @@ -1975,12 +2183,12 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, { struct sockaddr_in6 sin6_lo; struct sockaddr_in6 sin6_rm; - + memset(&sin6_lo, 0, sizeof(sin6_lo)); sin6_lo.sin6_len = sizeof(sin6_lo); sin6_lo.sin6_family = AF_INET6; memcpy(&sin6_lo.sin6_addr, loc_outer6, sizeof(sin6_lo.sin6_addr)); - + memset(&sin6_rm, 0, sizeof(sin6_rm)); sin6_rm.sin6_len = sizeof(sin6_rm); sin6_rm.sin6_family = AF_INET6; @@ -1990,10 +2198,9 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, } } } - - - debug("succeeded"); - + + os_log_debug(log_handle,"succeeded"); + fin: if (s >= 0) pfkey_close(s); @@ -2004,104 +2211,117 @@ fin: #endif /* ndef MDNS_NO_IPSEC */ -int -do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete, - v6addr_t loc_inner, v6addr_t loc_outer6, uint16_t loc_port, - v6addr_t rmt_inner, v6addr_t rmt_outer6, uint16_t rmt_port, - const char *id, int *err, audit_token_t token) +int HelperAutoTunnelSetKeys(int replacedelete, const v6addr_t loc_inner, const v6addr_t loc_outer6, uint16_t loc_port, const v6addr_t rmt_inner, + const v6addr_t rmt_outer6, uint16_t rmt_port, const char *id, int *err) { #ifndef MDNS_NO_IPSEC static const char config[] = - "%s" - "remote %s [%u] {\n" - " disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n" - " exchange_mode aggressive;\n" - " doi ipsec_doi;\n" - " situation identity_only;\n" - " verify_identifier off;\n" - " generate_policy on;\n" - " my_identifier user_fqdn \"%s\";\n" - " shared_secret keychain \"%s\";\n" - " nonce_size 16;\n" - " lifetime time 15 min;\n" - " initial_contact on;\n" - " support_proxy on;\n" - " nat_traversal force;\n" - " proposal_check claim;\n" - " proposal {\n" - " encryption_algorithm aes;\n" - " hash_algorithm sha256;\n" - " authentication_method pre_shared_key;\n" - " dh_group 2;\n" - " lifetime time 15 min;\n" - " }\n" - " proposal {\n" - " encryption_algorithm aes;\n" - " hash_algorithm sha1;\n" - " authentication_method pre_shared_key;\n" - " dh_group 2;\n" - " lifetime time 15 min;\n" - " }\n" - "}\n\n" - "sainfo address %s any address %s any {\n" - " pfs_group 2;\n" - " lifetime time 10 min;\n" - " encryption_algorithm aes;\n" - " authentication_algorithm hmac_sha256,hmac_sha1;\n" - " compression_algorithm deflate;\n" - "}\n\n" - "sainfo address %s any address %s any {\n" - " pfs_group 2;\n" - " lifetime time 10 min;\n" - " encryption_algorithm aes;\n" - " authentication_algorithm hmac_sha256,hmac_sha1;\n" - " compression_algorithm deflate;\n" - "}\n"; + "%s" + "remote %s [%u] {\n" + " disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n" + " exchange_mode aggressive;\n" + " doi ipsec_doi;\n" + " situation identity_only;\n" + " verify_identifier off;\n" + " generate_policy on;\n" + " my_identifier user_fqdn \"%s\";\n" + " shared_secret keychain \"%s\";\n" + " nonce_size 16;\n" + " lifetime time 15 min;\n" + " initial_contact on;\n" + " support_proxy on;\n" + " nat_traversal force;\n" + " proposal_check claim;\n" + " proposal {\n" + " encryption_algorithm aes;\n" + " hash_algorithm sha256;\n" + " authentication_method pre_shared_key;\n" + " dh_group 2;\n" + " lifetime time 15 min;\n" + " }\n" + " proposal {\n" + " encryption_algorithm aes;\n" + " hash_algorithm sha1;\n" + " authentication_method pre_shared_key;\n" + " dh_group 2;\n" + " lifetime time 15 min;\n" + " }\n" + "}\n\n" + "sainfo address %s any address %s any {\n" + " pfs_group 2;\n" + " lifetime time 10 min;\n" + " encryption_algorithm aes;\n" + " authentication_algorithm hmac_sha256,hmac_sha1;\n" + " compression_algorithm deflate;\n" + "}\n\n" + "sainfo address %s any address %s any {\n" + " pfs_group 2;\n" + " lifetime time 10 min;\n" + " encryption_algorithm aes;\n" + " authentication_algorithm hmac_sha256,hmac_sha1;\n" + " compression_algorithm deflate;\n" + "}\n"; char path[PATH_MAX] = ""; char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN], lo6[INET6_ADDRSTRLEN], - ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN]; + ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN]; FILE *fp = NULL; int fd = -1; char tmp_path[PATH_MAX] = ""; v4addr_t loc_outer, rmt_outer; - - debug("entry"); - *err = 0; - if (!authorized(&token)) - { - *err = kmDNSHelperNotAuthorized; - goto fin; - } + + os_log_debug(log_handle,"HelperAutoTunnelSetKeys: entry"); + *err = kHelperErr_NoErr; + + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + char buf3[INET6_ADDRSTRLEN]; + char buf4[INET6_ADDRSTRLEN]; + + buf1[0] = 0; + buf2[0] = 0; + buf3[0] = 0; + buf4[0] = 0; + + inet_ntop(AF_INET6, loc_inner, buf1, sizeof(buf1)); + inet_ntop(AF_INET6, loc_outer6, buf2, sizeof(buf2)); + inet_ntop(AF_INET6, rmt_inner, buf3, sizeof(buf3)); + inet_ntop(AF_INET6, rmt_outer6, buf4, sizeof(buf4)); + + os_log_info(log_handle, "HelperAutoTunnelSetKeys: Parameters are local_inner is %s, local_outer is %s, remote_inner is %s, remote_outer is %s id is %s", + buf1, buf2, buf3, buf4, id); + switch ((enum mDNSAutoTunnelSetKeysReplaceDelete)replacedelete) { - case kmDNSAutoTunnelSetKeysReplace: - case kmDNSAutoTunnelSetKeysDelete: - break; - default: - *err = kmDNSHelperInvalidTunnelSetKeysOperation; - goto fin; + case kmDNSAutoTunnelSetKeysReplace: + case kmDNSAutoTunnelSetKeysDelete: + break; + default: + *err = kHelperErr_InvalidTunnelSetKeysOperation; + goto fin; } - + if (0 != (*err = v6addr_to_string(loc_inner, li, sizeof(li)))) goto fin; if (0 != (*err = v6addr_to_string(rmt_inner, ri, sizeof(ri)))) goto fin; - - debug("loc_inner=%s rmt_inner=%s", li, ri); + + os_log_debug(log_handle, "loc_inner=%s rmt_inner=%s", li, ri); + if (!rmt_port) { loc_outer[0] = loc_outer[1] = loc_outer[2] = loc_outer[3] = 0; rmt_outer[0] = rmt_outer[1] = rmt_outer[2] = rmt_outer[3] = 0; - + if (0 != (*err = v6addr_to_string(loc_outer6, lo6, sizeof(lo6)))) goto fin; if (0 != (*err = v6addr_to_string(rmt_outer6, ro6, sizeof(ro6)))) goto fin; - debug("IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6); - if ((int)sizeof(path) <= snprintf(path, sizeof(path), - "%s%s.conf", GetRacoonConfigDir(), ro6)) + + os_log_debug(log_handle, "IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6); + + if ((int)sizeof(path) <= snprintf(path, sizeof(path), "%s%s.conf", GetRacoonConfigDir(), ro6)) { - *err = kmDNSHelperResultTooLarge; + *err = kHelperErr_ResultTooLarge; goto fin; } } @@ -2111,77 +2331,71 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete, loc_outer[1] = loc_outer6[1]; loc_outer[2] = loc_outer6[2]; loc_outer[3] = loc_outer6[3]; - + rmt_outer[0] = rmt_outer6[0]; rmt_outer[1] = rmt_outer6[1]; rmt_outer[2] = rmt_outer6[2]; rmt_outer[3] = rmt_outer6[3]; - + if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo)))) goto fin; if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro)))) goto fin; - debug("IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u", - lo, loc_port, ro, rmt_port); - - if ((int)sizeof(path) <= snprintf(path, sizeof(path), - "%s%s.%u.conf", GetRacoonConfigDir(), ro, - rmt_port)) + + os_log_debug(log_handle, "IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u", + lo, loc_port, ro, rmt_port); + + if ((int)sizeof(path) <= snprintf(path, sizeof(path), "%s%s.%u.conf", GetRacoonConfigDir(), ro, rmt_port)) { - *err = kmDNSHelperResultTooLarge; + *err = kHelperErr_ResultTooLarge; goto fin; } } - - - + if (kmDNSAutoTunnelSetKeysReplace == replacedelete) { if (0 > ensureExistenceOfRacoonConfigDir(GetRacoonConfigDir())) { - *err = kmDNSHelperRacoonConfigCreationFailed; + *err = kHelperErr_RacoonConfigCreationFailed; goto fin; } if ((int)sizeof(tmp_path) <= snprintf(tmp_path, sizeof(tmp_path), "%s.XXXXXX", path)) { - *err = kmDNSHelperResultTooLarge; + *err = kHelperErr_ResultTooLarge; goto fin; } if (0 > (fd = mkstemp(tmp_path))) { - helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s", - tmp_path, strerror(errno)); - *err = kmDNSHelperRacoonConfigCreationFailed; + os_log(log_handle, "mkstemp \"%s\" failed: %s", tmp_path, strerror(errno)); + *err = kHelperErr_RacoonConfigCreationFailed; goto fin; } if (NULL == (fp = fdopen(fd, "w"))) { - helplog(ASL_LEVEL_ERR, "fdopen: %s", - strerror(errno)); - *err = kmDNSHelperRacoonConfigCreationFailed; + os_log(log_handle, "fdopen: %s", strerror(errno)); + *err = kHelperErr_RacoonConfigCreationFailed; goto fin; } + fd = -1; fprintf(fp, config, configHeader, (!rmt_port ? ro6 : ro), rmt_port, id, id, ri, li, li, ri); fclose(fp); fp = NULL; + if (0 > rename(tmp_path, path)) { - helplog(ASL_LEVEL_ERR, - "rename \"%s\" \"%s\" failed: %s", - tmp_path, path, strerror(errno)); - *err = kmDNSHelperRacoonConfigCreationFailed; + os_log(log_handle, "rename \"%s\" \"%s\" failed: %s", tmp_path, path, strerror(errno)); + *err = kHelperErr_RacoonConfigCreationFailed; goto fin; } } else { if (0 != unlink(path)) - debug("unlink \"%s\" failed: %s", path, - strerror(errno)); + os_log_debug(log_handle, "unlink \"%s\" failed: %s", path, strerror(errno)); } - + if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel, loc_inner, kWholeV6Mask, loc_outer, loc_port, rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6))) @@ -2191,19 +2405,20 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete, loc_inner, kWholeV6Mask, loc_outer, loc_port, rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6))) goto fin; - + if (0 != (*err = teardownTunnelRoute(rmt_inner))) goto fin; + if (kmDNSAutoTunnelSetKeysReplace == replacedelete && 0 != (*err = setupTunnelRoute(loc_inner, rmt_inner))) goto fin; - + if (kmDNSAutoTunnelSetKeysReplace == replacedelete && 0 != (*err = kickRacoon())) goto fin; - - debug("succeeded"); - + + os_log_debug(log_handle, "succeeded"); + fin: if (NULL != fp) fclose(fp); @@ -2212,709 +2427,14 @@ fin: unlink(tmp_path); #else (void)replacedelete; (void)loc_inner; (void)loc_outer6; (void)loc_port; (void)rmt_inner; - (void)rmt_outer6; (void)rmt_port; (void)id; (void)token; - - *err = kmDNSHelperIPsecDisabled; + (void)rmt_outer6; (void)rmt_port; (void)id; + + *err = kHelperErr_IPsecDisabled; #endif /* MDNS_NO_IPSEC */ update_idle_timer(); return KERN_SUCCESS; } -kern_return_t -do_mDNSSendWakeupPacket(__unused mach_port_t port, unsigned ifid, const char *eth_addr, const char *ip_addr, int iteration, audit_token_t token) -{ - int bpf_fd, i, j; - struct ifreq ifr; - char ifname[IFNAMSIZ]; - char packet[512]; - char *ptr = packet; - char bpf_device[12]; - struct ether_addr *ea; - (void) ip_addr; // unused - (void) iteration; // unused - (void) token; // unused - - if (if_indextoname(ifid, ifname) == NULL) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid interface index %u", ifid); - return errno; - } - - ea = ether_aton(eth_addr); - if (ea == NULL) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid ethernet address %s", eth_addr); - return errno; - } - - for (i = 0; i < 100; i++) - { - snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i); - bpf_fd = open(bpf_device, O_RDWR, 0); - if (bpf_fd == -1) - continue; - else break; - } - - if (bpf_fd == -1) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket cannot find a bpf device"); - return ENXIO; - } - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - - if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket BIOCSETIF failed %s", strerror(errno)); - return errno; - } - - // 0x00 Destination address - for (i=0; i<6; i++) *ptr++ = ea->octet[i]; - - // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) - for (i=0; i<6; i++) *ptr++ = 0; - - // 0x0C Ethertype (0x0842) - *ptr++ = 0x08; - *ptr++ = 0x42; - - // 0x0E Wakeup sync sequence - for (i=0; i<6; i++) *ptr++ = 0xFF; - - // 0x14 Wakeup data - for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = ea->octet[i]; - - // 0x74 Password - for (i=0; i<6; i++) *ptr++ = 0; - - if (write(bpf_fd, packet, ptr - packet) < 0) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno)); - return errno; - } - helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr); - // Send a broadcast one to handle ethernet switches that don't flood forward packets with - // unknown mac addresses. - for (i=0; i<6; i++) packet[i] = 0xFF; - if (write(bpf_fd, packet, ptr - packet) < 0) - { - helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno)); - return errno; - } - helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr); - close(bpf_fd); - return KERN_SUCCESS; -} - -// Open the specified port for protocol in the P2P firewall. -kern_return_t -do_mDNSPacketFilterControl(__unused mach_port_t port, uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray, audit_token_t token) -{ - (void) token; // unused - int error; - kern_return_t result = KERN_SUCCESS; - - helplog(ASL_LEVEL_INFO, "do_mDNSPacketFilterControl: command %d ifname %s, count %d", - command, ifname, count); - - switch (command) - { - case PF_SET_RULES: - error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray); - if (error) - { - helplog(ASL_LEVEL_ERR, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error)); - result = KERN_FAILURE; - } - break; - - case PF_CLEAR_RULES: - error = P2PPacketFilterClearBonjourRules(); - if (error) - { - helplog(ASL_LEVEL_ERR, "P2PPacketFilterClearBonjourRules failed %s", strerror(error)); - result = KERN_FAILURE; - } - break; - - default: - helplog(ASL_LEVEL_ERR, "do_mDNSPacketFilterControl: invalid command %d", command); - result = KERN_INVALID_ARGUMENT; - break; - } - - return result; -} - -unsigned long -in_cksum(unsigned short *ptr,int nbytes) -{ - unsigned long sum; - u_short oddbyte; - - /* - * Our algorithm is simple, using a 32-bit accumulator (sum), - * we add sequential 16-bit words to it, and at the end, fold back - * all the carry bits from the top 16 bits into the lower 16 bits. - */ - sum = 0; - while (nbytes > 1) - { - sum += *ptr++; - nbytes -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nbytes == 1) - { - /* make sure top half is zero */ - oddbyte = 0; - - /* one byte only */ - *((u_char *)&oddbyte) = *(u_char *)ptr; - sum += oddbyte; - } - /* Add back carry outs from top 16 bits to low 16 bits. */ - sum = (sum >> 16) + (sum & 0xffff); - - /* add carry */ - sum += (sum >> 16); - - return sum; -} - -unsigned short -InetChecksum(unsigned short *ptr,int nbytes) -{ - unsigned long sum; - - sum = in_cksum(ptr, nbytes); - return (unsigned short)~sum; -} - -void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6) -{ - unsigned long sum = 0; - unsigned short *ptr; - - /* TCP header checksum */ - sum = in_cksum((unsigned short *)t, tcplen); - - if (af == AF_INET) - { - /* Pseudo header */ - ptr = (unsigned short *)sadd6; - sum += *ptr++; - sum += *ptr++; - ptr = (unsigned short *)dadd6; - sum += *ptr++; - sum += *ptr++; - } - else if (af == AF_INET6) - { - /* Pseudo header */ - ptr = (unsigned short *)sadd6; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - ptr = (unsigned short *)dadd6; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - sum += *ptr++; - } - - sum += htons(tcplen); - sum += htons(IPPROTO_TCP); - - while (sum >> 16) - sum = (sum >> 16) + (sum & 0xFFFF); - - t->th_sum = ~sum; - -} - -kern_return_t do_mDNSSendKeepalive(__unused mach_port_t port, v6addr_t sadd6, v6addr_t dadd6, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win, audit_token_t token) -{ - struct packet4 { - struct ip ip; - struct tcphdr tcp; - } packet4; - struct packet6 { - struct tcphdr tcp; - } packet6; - int sock, on; - struct tcphdr *t; - int af; - struct sockaddr_storage ss_to; - struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to; - struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to; - void *packet; - ssize_t packetlen; - char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; - struct msghdr msghdr; - struct iovec iov; - ssize_t len; - - if (!authorized(&token)) - { - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Not authorized"); - return kmDNSHelperNotAuthorized; - } - - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: called"); - - // all the incoming arguments are in network order - if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0)) - { - af = AF_INET; - memset(&packet4, 0, sizeof (packet4)); - - /* Fill in all the IP header information - should be in host order*/ - packet4.ip.ip_v = 4; /* 4-bit Version */ - packet4.ip.ip_hl = 5; /* 4-bit Header Length */ - packet4.ip.ip_tos = 0; /* 8-bit Type of service */ - packet4.ip.ip_len = 40; /* 16-bit Total length */ - packet4.ip.ip_id = 9864; /* 16-bit ID field */ - packet4.ip.ip_off = 0; /* 13-bit Fragment offset */ - packet4.ip.ip_ttl = 63; /* 8-bit Time To Live */ - packet4.ip.ip_p = IPPROTO_TCP; /* 8-bit Protocol */ - packet4.ip.ip_sum = 0; /* 16-bit Header checksum (below) */ - memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4); - memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4); - - /* IP header checksum */ - packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20); - t = &packet4.tcp; - packet = &packet4; - packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20) - } - else - { - af = AF_INET6; - memset(&packet6, 0, sizeof (packet6)); - t = &packet6.tcp; - packet = &packet6; - // We don't send IPv6 header, hence just the TCP header len (20) - packetlen = 20; - } - - /* Fill in all the TCP header information */ - t->th_sport = lport; /* 16-bit Source port number */ - t->th_dport = rport; /* 16-bit Destination port */ - t->th_seq = seq; /* 32-bit Sequence Number */ - t->th_ack = ack; /* 32-bit Acknowledgement Number */ - t->th_off = 5; /* Data offset */ - t->th_flags = TH_ACK; - t->th_win = win; - t->th_sum = 0; /* 16-bit checksum (below) */ - t->th_urp = 0; /* 16-bit urgent offset */ - - TCPCheckSum(af, t, 20, sadd6, dadd6); - - /* Open up a RAW socket */ - if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0) - { - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: socket %s", strerror(errno)); - return errno; - } - - - if (af == AF_INET) - { - on = 1; - if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on))) - { - close(sock); - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: setsockopt %s", strerror(errno)); - return errno; - } - - memset(sin_to, 0, sizeof(struct sockaddr_in)); - sin_to->sin_len = sizeof(struct sockaddr_in); - sin_to->sin_family = AF_INET; - memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr)); - sin_to->sin_port = rport; - - msghdr.msg_control = NULL; - msghdr.msg_controllen = 0; - - } - else - { - struct cmsghdr *ctl; - - memset(sin6_to, 0, sizeof(struct sockaddr_in6)); - sin6_to->sin6_len = sizeof(struct sockaddr_in6); - sin6_to->sin6_family = AF_INET6; - memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr)); - - sin6_to->sin6_port = rport; - sin6_to->sin6_flowinfo = 0; - - - msghdr.msg_control = ctlbuf; - msghdr.msg_controllen = sizeof(ctlbuf); - ctl = CMSG_FIRSTHDR(&msghdr); - ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - ctl->cmsg_level = IPPROTO_IPV6; - ctl->cmsg_type = IPV6_PKTINFO; - struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl); - memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr)); - pktinfo->ipi6_ifindex = 0; - } - - msghdr.msg_name = (struct sockaddr *)&ss_to; - msghdr.msg_namelen = ss_to.ss_len; - iov.iov_base = packet; - iov.iov_len = packetlen; - msghdr.msg_iov = &iov; - msghdr.msg_iovlen = 1; - msghdr.msg_flags = 0; -again: - len = sendmsg(sock, &msghdr, 0); - if (len == -1) - { - if (errno == EINTR) - goto again; - } - - if (len != packetlen) - { - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: sendmsg failed %s", strerror(errno)); - } - else - { - char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN]; - - inet_ntop(af, (void *)sadd6, source, sizeof(source)); - inet_ntop(af, (void *)dadd6, dest, sizeof(dest)); - - helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u", source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win)); - - } - close(sock); - return KERN_SUCCESS; -} - -kern_return_t do_mDNSRetrieveTCPInfo(__unused mach_port_t port, int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport, - uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, audit_token_t token) -{ - struct tcp_info ti; - struct info_tuple itpl; - int mib[4]; - unsigned int miblen; - size_t len; - size_t sz; - - memset(&itpl, 0, sizeof(struct info_tuple)); - memset(&ti, 0, sizeof(struct tcp_info)); - - if (!authorized(&token)) - { - helplog(ASL_LEVEL_ERR, "mDNSRetrieveTCPInfo: Not authorized"); - return kmDNSHelperNotAuthorized; - } - - if (family == AF_INET) - { - memcpy(&itpl.itpl_local_sin.sin_addr, laddr, sizeof(struct in_addr)); - memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr)); - itpl.itpl_local_sin.sin_port = lport; - itpl.itpl_remote_sin.sin_port = rport; - itpl.itpl_local_sin.sin_family = AF_INET; - itpl.itpl_remote_sin.sin_family = AF_INET; - } - else - { - memcpy(&itpl.itpl_local_sin6.sin6_addr, laddr, sizeof(struct in6_addr)); - memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr)); - itpl.itpl_local_sin6.sin6_port = lport; - itpl.itpl_remote_sin6.sin6_port = rport; - itpl.itpl_local_sin6.sin6_family = AF_INET6; - itpl.itpl_remote_sin6.sin6_family = AF_INET6; - } - itpl.itpl_proto = IPPROTO_TCP; - sz = sizeof(mib)/sizeof(mib[0]); - if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1) - { - helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno)); - return errno; - } - miblen = (unsigned int)sz; - len = sizeof(struct tcp_info); - if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1) - { - helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno)); - return errno; - } - - *seq = ti.tcpi_snd_nxt - 1; - *ack = ti.tcpi_rcv_nxt; - *win = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale; - *intfid = ti.tcpi_last_outif; - return KERN_SUCCESS; -} - -static int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth) -{ - struct - { - struct rt_msghdr m_rtm; - char m_space[512]; - } m_rtmsg; - - struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); - char *cp = m_rtmsg.m_space; - int seq = 6367, sock, rlen, i; - struct sockaddr_in *sin = NULL; - struct sockaddr_in6 *sin6 = NULL; - struct sockaddr_dl *sdl = NULL; - struct sockaddr_storage sins; - struct sockaddr_dl sdl_m; - -#define NEXTADDR(w, s, len) \ - if (rtm->rtm_addrs & (w)) \ - { \ - bcopy((char *)s, cp, len); \ - cp += len; \ - } - - bzero(&sins, sizeof(struct sockaddr_storage)); - bzero(&sdl_m, sizeof(struct sockaddr_dl)); - bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); - - sock = socket(PF_ROUTE, SOCK_RAW, 0); - if (sock < 0) - { - helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Can not open the socket - %s", strerror(errno)); - return errno; - } - - rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY; - rtm->rtm_type = RTM_GET; - rtm->rtm_flags = 0; - rtm->rtm_version = RTM_VERSION; - rtm->rtm_seq = ++seq; - - sdl_m.sdl_len = sizeof(sdl_m); - sdl_m.sdl_family = AF_LINK; - if (family == AF_INET) - { - sin = (struct sockaddr_in*)&sins; - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr)); - NEXTADDR(RTA_DST, sin, sin->sin_len); - } - else if (family == AF_INET6) - { - sin6 = (struct sockaddr_in6 *)&sins; - sin6->sin6_len = sizeof(struct sockaddr_in6); - sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr)); - NEXTADDR(RTA_DST, sin6, sin6->sin6_len); - } - NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len); - rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg; - - if (write(sock, (char *)&m_rtmsg, rlen) < 0) - { - helplog(ASL_LEVEL_INFO, "do_mDNSGetRemoteMAC: writing to routing socket: %s", strerror(errno)); - close(sock); - return errno; - } - - do - { - rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg)); - } - while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid())); - - if (rlen < 0) - helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: Read from routing socket failed"); - - if (family == AF_INET) - { - sin = (struct sockaddr_in *) (rtm + 1); - sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin); - } - else if (family == AF_INET6) - { - sin6 = (struct sockaddr_in6 *) (rtm +1); - sdl = (struct sockaddr_dl *) (sin6->sin6_len + (char *) sin6); - } - if (!sdl) - { - helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sdl is NULL for family %d", family); - close(sock); - return -1; - } - // If the address is not on the local net, we get the IP address of the gateway. - // We would have to repeat the process to get the MAC address of the gateway - *gfamily = sdl->sdl_family; - if (sdl->sdl_family == AF_INET) - { - if (sin) - { - struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin); - memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr)); - } - else - { - helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sin is NULL"); - } - close(sock); - return -1; - } - else if (sdl->sdl_family == AF_INET6) - { - if (sin6) - { - struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6); - memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr)); - } - else - { - helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sin6 is NULL"); - } - close(sock); - return -1; - } - - unsigned char *ptr = (unsigned char *)LLADDR(sdl); - for (i = 0; i < ETHER_ADDR_LEN; i++) - (eth)[i] = *(ptr +i); - - close(sock); - return KERN_SUCCESS; -} - -kern_return_t do_mDNSGetRemoteMAC(__unused mach_port_t port, int family, v6addr_t raddr, ethaddr_t eth, audit_token_t token) -{ - int ret = 0; - v6addr_t gateway; - int gfamily; - int count = 0; - - if (!authorized(&token)) - { - helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Not authorized"); - return kmDNSHelperNotAuthorized; - } - - do - { - ret = getMACAddress(family, raddr, gateway, &gfamily, eth); - if (ret == -1) - { - memcpy(raddr, gateway, sizeof(family)); - family = gfamily; - count++; - } - } - while ((ret == -1) && (count < 5)); - return ret; -} - - -kern_return_t do_mDNSStoreSPSMACAddress(__unused mach_port_t port, int family, v6addr_t spsaddr, const char *ifname, audit_token_t token) -{ - ethaddr_t eth; - char spsip[INET6_ADDRSTRLEN]; - int ret = 0; - CFStringRef sckey = NULL; - SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL); - SCDynamicStoreRef ipstore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL); - CFMutableDictionaryRef dict = NULL; - CFStringRef entityname = NULL; - CFDictionaryRef ipdict = NULL; - CFArrayRef addrs = NULL; - - if (!authorized(&token)) - { - helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Not authorized"); - return kmDNSHelperNotAuthorized; - } - - if ((store == NULL) || (ipstore == NULL)) - { - helplog(ASL_LEVEL_ERR, "Unable to access SC Dynamic Store"); - return KERN_FAILURE; - } - - // Get the MAC address of the Sleep Proxy Server - memset(eth, 0, sizeof(eth)); - ret = do_mDNSGetRemoteMAC(port, family, spsaddr, eth, token); - if (ret != KERN_SUCCESS) - { - helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Failed to determine the MAC address"); - goto fin; - } - - // Create/Update the dynamic store entry for the specified interface - sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress"); - dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!dict) - { - helplog(ASL_LEVEL_ERR, "SPSCreateDict: Could not create CFDictionary dict"); - ret = KERN_FAILURE; - goto fin; - } - - CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); - CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr); - if (NULL != macaddr) CFRelease(macaddr); - - if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip))) - { - helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", strerror(errno)); - ret = kmDNSHelperInvalidNetworkAddress; - goto fin; - } - - CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8); - CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr); - if (NULL != ipaddr) CFRelease(ipaddr); - - // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup - if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL) - { - if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL) - { - if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL) - { - addrs = CFRetain(addrs); - CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs); - } - } - } - SCDynamicStoreSetValue(store, sckey, dict); - -fin: - if (store) CFRelease(store); - if (ipstore) CFRelease(ipstore); - if (sckey) CFRelease(sckey); - if (dict) CFRelease(dict); - if (ipdict) CFRelease(ipdict); - if (entityname) CFRelease(entityname); - if (addrs) CFRelease(addrs); - - update_idle_timer(); - return ret; -} diff --git a/mDNSResponder/mDNSMacOSX/helper.h b/mDNSResponder/mDNSMacOSX/helper.h index 04332eff..eedf7380 100644 --- a/mDNSResponder/mDNSMacOSX/helper.h +++ b/mDNSResponder/mDNSMacOSX/helper.h @@ -18,7 +18,71 @@ #ifndef H_HELPER_H #define H_HELPER_H -#define kmDNSHelperServiceName "com.apple.mDNSResponderHelper" +#include <os/log.h> + +#define kHelperService "com.apple.mDNSResponder_Helper" + +#define kmDNSHelperProgramArgs CFSTR("com.apple.mDNSResponderHelper") +#define kPreferencesKey_mDNSHelperLog CFSTR("mDNSHelperDebugLogging") + +#define kHelperMode "HelperMode" +#define kHelperReplyStatus "HelperReplyStatusToClient" +#define kHelperErrCode "HelperErrorCodefromCall" + +#define kPrefsNameKey "PreferencesNameKey" +#define kPrefsOldName "PreferencesOldName" +#define kPrefsNewName "PreferencesNewName" + +extern int mDNSHelperLogEnabled; + +extern os_log_t log_handle; + +typedef enum +{ + bpf_request = 1, + set_name = 2, + p2p_packetfilter = 3, + user_notify = 4, + power_req = 5, + send_wakepkt = 6, + set_localaddr_cacheentry = 7, + send_keepalive = 8, + retreive_tcpinfo = 9, + keychain_getsecrets = 10, + autotunnel_setkeys = 11, + request_other, +} HelperModes; + +typedef enum +{ + kHelperReply_ACK = 0, +} HelperReplyStatusCodes; + + +typedef enum +{ + kHelperErr_NoErr = 0, + kHelperErr_DefaultErr = -1, + kHelperErr_NotConnected = -2, + kHelperErr_NoResponse = -3, + kHelperErr_UndefinedMode = -4, + kHelperErr_ApiErr = -5, + kHelperErr_InvalidTunnelSetKeysOperation = -6, + kHelperErr_InvalidNetworkAddress = -7, + kHelperErr_ResultTooLarge = -8, + kHelperErr_RacoonConfigCreationFailed = -9, + kHelperErr_IPsecPolicySocketCreationFailed = -10, + kHelperErr_IPsecPolicyCreationFailed = -11, + kHelperErr_IPsecPolicySetFailed = -12, + kHelperErr_IPsecRemoveSAFailed = -13, + kHelperErr_IPsecDisabled = -14, + kHelperErr_RoutingSocketCreationFailed = -15, + kHelperErr_RouteDeletionFailed = -16, + kHelperErr_RouteAdditionFailed = -17, + kHelperErr_RacoonStartFailed = -18, + kHelperErr_RacoonNotificationFailed = -19, +} HelperErrorCodes; + enum mDNSPreferencesSetNameKey { @@ -38,6 +102,7 @@ enum mDNSAutoTunnelSetKeysReplaceDelete kmDNSAutoTunnelSetKeysDelete }; + // helper parses the system keychain and returns the information to mDNSResponder. // It returns four attributes. Attributes are defined after how they show up in // keychain access utility (the actual attribute name to retrieve these are different). @@ -49,36 +114,40 @@ enum mDNSKeyChainAttributes kmDNSKcName // Name }; -#define ERROR(x, y) x, -enum mDNSHelperErrors -{ - mDNSHelperErrorBase = 2300, - #include "helper-error.h" - mDNSHelperErrorEnd -}; -#undef ERROR - #include "mDNSEmbeddedAPI.h" #include "helpermsg-types.h" extern const char *mDNSHelperError(int errornum); extern mStatus mDNSHelperInit(void); + + extern void mDNSRequestBPF(void); extern int mDNSPowerRequest(int key, int interval); extern int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth); extern void mDNSNotify(const char *title, const char *msg); // Both strings are UTF-8 text extern void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new); extern int mDNSKeychainGetSecrets(CFArrayRef *secrets); -extern void mDNSConfigureServer(int updown, const char *const prefix, const domainname *const fqdn); extern int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner, v6addr_t local_outer, short local_port, v6addr_t remote_inner, v6addr_t remote_outer, short remote_port, const char *const prefix, const domainname *const fqdn); extern void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration); extern void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray); -extern void mDNSSendKeepalive(v6addr_t sadd, v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win); +extern void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win); extern int mDNSRetrieveTCPInfo(int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid); -extern void mDNSGetRemoteMAC(mDNS *const m, int family, v6addr_t raddr); -extern void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname); + +extern void RequestBPF(void); +extern void PreferencesSetName(int key, const char* old, const char* new); +extern void PacketFilterControl(uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray); +extern void UserNotify(const char *title, const char *msg); // Both strings are UTF-8 text +extern void PowerRequest(int key, int interval, int *error); +extern void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration); +extern void SetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err); +extern void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win); +extern void RetrieveTCPInfo(int family, const v6addr_t laddr, uint16_t lport, const v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, int *err); +extern void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err); +extern int HelperAutoTunnelSetKeys(int replacedelete, const v6addr_t loc_inner, const v6addr_t loc_outer6, uint16_t loc_port, const v6addr_t rmt_inner, + const v6addr_t rmt_outer6, uint16_t rmt_port, const char *id, int *err); +extern void helper_exit(void); #endif /* H_HELPER_H */ diff --git a/mDNSResponder/mDNSMacOSX/helpermsg-types.h b/mDNSResponder/mDNSMacOSX/helpermsg-types.h index 88411800..689b249e 100644 --- a/mDNSResponder/mDNSMacOSX/helpermsg-types.h +++ b/mDNSResponder/mDNSMacOSX/helpermsg-types.h @@ -24,7 +24,7 @@ typedef uint8_t ethaddr_t[ 6]; typedef uint8_t v6addr_t [16]; typedef const char *string_t; -#define PFPortArraySize 16 +#define PFPortArraySize 4 typedef uint16_t pfArray_t [PFPortArraySize]; #endif /* H_HELPERMSG_TYPES_H */ diff --git a/mDNSResponder/mDNSMacOSX/helpermsg.defs b/mDNSResponder/mDNSMacOSX/helpermsg.defs deleted file mode 100644 index 35239967..00000000 --- a/mDNSResponder/mDNSMacOSX/helpermsg.defs +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2007-2013 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. - */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -import "helpermsg-types.h"; - -type v4addr_t = array [ 4] of uint8_t; -type ethaddr_t = array [ 6] of uint8_t; -type v6addr_t = array [16] of uint8_t; -type string_t = c_string[*:1024]; - -// Mig doesn't generate the output file if I use the constant PFPortArraySize below -type pfArray_t = array [16] of uint16_t; - -subsystem helper 1833193043; -serverprefix do_; -userprefix proxy_; - -simpleroutine mDNSExit( port : mach_port_t; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSRequestBPF( port : mach_port_t; - ServerAuditToken token : audit_token_t); - -routine mDNSPowerRequest( port : mach_port_t; - key : int; - interval : int; - out err : int; - ServerAuditToken token : audit_token_t); - -routine mDNSSetLocalAddressCacheEntry( - port : mach_port_t; - ifindex : int; - family : int; - ip : v6addr_t; - eth : ethaddr_t; - out err : int; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSNotify( port : mach_port_t; - title : string_t; - msg : string_t; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSPreferencesSetName( - port : mach_port_t; - key : int; - old : string_t; - new : string_t; - ServerAuditToken token : audit_token_t); - -routine mDNSKeychainGetSecrets( port : mach_port_t; - out numsecrets : unsigned; - out secrets : pointer_t; - out err : int; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSConfigureServer( - port : mach_port_t; - updown : int; - id : string_t; - ServerAuditToken token : audit_token_t); - -routine mDNSAutoTunnelSetKeys( port : mach_port_t; - replacedelete : int; - local_inner : v6addr_t; - local_outer : v6addr_t; - local_port : uint16_t; /* Port expressed as a numeric integer value */ - remote_inner : v6addr_t; - remote_outer : v6addr_t; - remote_port : uint16_t; /* Port expressed as a numeric integer value */ - id : string_t; - out err : int; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSSendWakeupPacket( - port : mach_port_t; - ifid : unsigned; - eth_addr : string_t; - ip_addr : string_t; - iteration : int; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSPacketFilterControl( - port : mach_port_t; - command : uint32_t; - ifname : string_t; - arraySize : uint32_t; - portArray : pfArray_t; - protocolArray : pfArray_t; - ServerAuditToken token : audit_token_t); - - -simpleroutine mDNSSendKeepalive( port : mach_port_t; - sadd : v6addr_t; - dadd : v6addr_t; - lport : uint16_t; - rport : uint16_t; - seq : unsigned; - ack : unsigned; - win : uint16_t; - ServerAuditToken token : audit_token_t); - -routine mDNSRetrieveTCPInfo( - port : mach_port_t; - family : int; - laddr : v6addr_t; - lport : uint16_t; - raddr : v6addr_t; - rport : uint16_t; - out seq : uint32_t; - out ack : uint32_t; - out win : uint16_t; - out intfid : int32_t; - ServerAuditToken token : audit_token_t); - -routine mDNSGetRemoteMAC( port : mach_port_t; - family : int; - raddr : v6addr_t; - out eth : ethaddr_t; - ServerAuditToken token : audit_token_t); - -simpleroutine mDNSStoreSPSMACAddress( port : mach_port_t; - family : int; - spsaddr : v6addr_t; - ifname : string_t; - ServerAuditToken token : audit_token_t); diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c index deae0d1a..c57eddda 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2015 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 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. @@ -29,6 +29,7 @@ #include "uDNS.h" #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform #include "dns_sd.h" // For mDNSInterface_LocalOnly etc. +#include "dns_sd_private.h" #include "PlatformCommon.h" #include "uds_daemon.h" #include "CryptoSupport.h" @@ -60,7 +61,7 @@ #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below #include <netinet/ip.h> // For IPTOS_LOWDELAY etc. -#include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc. +#include <netinet6/in6_var.h> // For IN6_IFF_TENTATIVE etc. #include <netinet/tcp.h> @@ -100,6 +101,8 @@ #include <AWACS.h> #include <ne_session.h> // for ne_session_set_socket_attributes() #if !NO_D2D +#include "BLE.h" + D2DStatus D2DInitialize(CFRunLoopRef runLoop, D2DServiceCallback serviceCallback, void* userData) __attribute__((weak_import)); D2DStatus D2DRetain(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import)); D2DStatus D2DStopAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import)); @@ -111,6 +114,9 @@ void D2DStartResolvingPairOnTransport(const Byte *key, const size_t keySize, con void D2DStopResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import)); D2DStatus D2DTerminate() __attribute__((weak_import)); +void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize); +void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize); + #endif // ! NO_D2D #else @@ -132,7 +138,7 @@ D2DStatus D2DTerminate() __attribute__((weak_import)); #define DARK_WAKE_TIME 16 // Time we hold an idle sleep assertion for maintenance after a wake notification // cache the InterfaceID of the AWDL interface -static mDNSInterfaceID AWDLInterfaceID; +mDNSInterfaceID AWDLInterfaceID; // *************************************************************************** // Globals @@ -176,9 +182,6 @@ mDNSexport int WatchDogReportingThreshold = 250; dispatch_queue_t SSLqueue; -//To prevent blocking the main queue, all writes to DynamicStore happen on the DynamicStoreQueue -static dispatch_queue_t DynamicStoreQueue; - #if TARGET_OS_EMBEDDED #define kmDNSResponderManagedPrefsID CFSTR("/Library/Managed Preferences/mobile/com.apple.mDNSResponder.plist") #endif @@ -243,6 +246,26 @@ mDNSexport void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface) } } +// If record would have been advertised to the D2D plugin layer, stop that advertisement. +mDNSexport void D2D_stop_advertising_record(AuthRecord *ar) +{ + DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType); + if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags)) + { + external_stop_advertising_service(&ar->resrec, flags); + } +} + +// If record should be advertised to the D2D plugin layer, start that advertisement. +mDNSexport void D2D_start_advertising_record(AuthRecord *ar) +{ + DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType); + if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags)) + { + external_start_advertising_service(&ar->resrec, flags); + } +} + // Name compression items for fake packet version number 1 static const mDNSu8 compression_packet_v1 = 0x01; @@ -304,65 +327,6 @@ mDNSlocal void DomainnameToLower(const domainname * const in, domainname * const out->c[ptr-start] = *ptr; } -mDNSlocal mStatus DNSNameCompressionParseBytes(mDNS *const m, const mDNSu8 *const lhs, const mDNSu16 lhs_len, const mDNSu8 *const rhs, const mDNSu16 rhs_len, AuthRecord *rr) -{ - if (mDNS_LoggingEnabled) - { - LogInfo("%s", __func__); - LogInfo(" Static Bytes: (%d bytes)", compression_lhs - (mDNSu8*)&compression_base_msg); - PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg); - } - - mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet - - // Check to make sure we're not going to go past the end of the DNSMessage data - // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH - if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr; - - // Copy the LHS onto our fake wire packet - mDNSPlatformMemCopy(ptr, lhs, lhs_len); - ptr += lhs_len - 1; - - // Check the 'fake packet' version number, to ensure that we know how to decompress this data - if (*ptr != compression_packet_v1) return mStatus_Incompatible; - - // two bytes of CLASS - ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet); - - // four bytes of TTL - ptr = putVal32(ptr, 120); - - // Copy the RHS length into the RDLENGTH of our fake wire packet - ptr = putVal16(ptr, rhs_len); - - // Copy the RHS onto our fake wire packet - mDNSPlatformMemCopy(ptr, rhs, rhs_len); - ptr += rhs_len; - - if (mDNS_LoggingEnabled) - { - LogInfo(" Our Bytes (%d bytes): ", ptr - compression_lhs); - PrintHex(compression_lhs, ptr - compression_lhs); - } - - ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec); - if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative) - { LogMsg("DNSNameCompressionParseBytes: failed to get large RR"); m->rec.r.resrec.RecordType = 0; return mStatus_UnknownErr; } - else LogInfo("DNSNameCompressionParseBytes: got rr: %s", CRDisplayString(m, &m->rec.r)); - - mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL); - AssignDomainName(&rr->namestorage, &m->rec.namestorage); - rr->resrec.rdlength = m->rec.r.resrec.rdlength; - rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength; - mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength); - rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); - SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us - - m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use - - return mStatus_NoError; -} - mDNSlocal mDNSu8 * DNSNameCompressionBuildLHS(const domainname* typeDomain, DNS_TypeValues qtype) { mDNSu8 *ptr = putDomainNameAsLabels(&compression_base_msg, compression_lhs, compression_limit, typeDomain); @@ -459,8 +423,8 @@ mDNSlocal void xD2DClearCache(const domainname *regType, DNS_TypeValues qtype) { if ((ptr->ar.resrec.rrtype == qtype) && SameDomainName(&ptr->ar.namestorage, regType)) { - mDNS_Deregister(&mDNSStorage, &ptr->ar); LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", ARDisplayString(&mDNSStorage, &ptr->ar)); + mDNS_Deregister(&mDNSStorage, &ptr->ar); } } } @@ -498,11 +462,12 @@ mDNSlocal void D2DBrowseListRetain(const domainname *const name, mDNSu16 type) LogInfo("D2DBrowseListRetain: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount); } -mDNSlocal void D2DBrowseListRelease(const domainname *const name, mDNSu16 type) +// Returns true if found in list, false otherwise +mDNSlocal bool D2DBrowseListRelease(const domainname *const name, mDNSu16 type) { D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type); - if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return; } + if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return false; } (*ptr)->refCount -= 1; @@ -514,35 +479,125 @@ mDNSlocal void D2DBrowseListRelease(const domainname *const name, mDNSu16 type) *ptr = (*ptr)->next; mDNSPlatformMemFree(tmp); } + return true; } -mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, AuthRecord *rr) +mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, D2DRecordListElem **D2DListp) { - if (*(lhs + (lhs_len - 1)) == compression_packet_v1) - return DNSNameCompressionParseBytes(m, lhs, lhs_len, rhs, rhs_len, rr); - else + // Sanity check that key array (lhs) has one domain name, followed by the record type and single byte D2D + // plugin protocol version number. + // Note, we don't have a DNSMessage pointer at this point, so just pass in the lhs value as the lower bound + // of the input bytes we are processing. skipDomainName() does not try to follow name compression pointers, + // so it is safe to pass it the key byte array since it will stop parsing the DNS name and return a pointer + // to the byte after the first name compression pointer it encounters. + const mDNSu8 *keyp = skipDomainName((const DNSMessage *const) lhs, lhs, lhs + lhs_len); + + // There should be 3 bytes remaining in a valid key, + // two for the DNS record type, and one for the D2D protocol version number. + if (keyp == NULL || (keyp + 3 != (lhs + lhs_len))) + { + LogInfo("xD2DParse: Could not parse DNS name in key"); return mStatus_Incompatible; + } + keyp += 2; // point to D2D compression packet format version byte + if (*keyp != compression_packet_v1) + { + LogInfo("xD2DParse: Invalid D2D packet version: %d", *keyp); + return mStatus_Incompatible; + } + + if (mDNS_LoggingEnabled) + { + LogInfo("%s", __func__); + LogInfo(" Static Bytes: (%d bytes)", compression_lhs - (mDNSu8*)&compression_base_msg); + PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg); + } + + mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet + + // Check to make sure we're not going to go past the end of the DNSMessage data + // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH + if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr; + + // Copy the LHS onto our fake wire packet + mDNSPlatformMemCopy(ptr, lhs, lhs_len); + ptr += lhs_len - 1; + + // Check the 'fake packet' version number, to ensure that we know how to decompress this data + if (*ptr != compression_packet_v1) return mStatus_Incompatible; + + // two bytes of CLASS + ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet); + + // four bytes of TTL + ptr = putVal32(ptr, 120); + + // Copy the RHS length into the RDLENGTH of our fake wire packet + ptr = putVal16(ptr, rhs_len); + + // Copy the RHS onto our fake wire packet + mDNSPlatformMemCopy(ptr, rhs, rhs_len); + ptr += rhs_len; + + if (mDNS_LoggingEnabled) + { + LogInfo(" Our Bytes (%d bytes): ", ptr - compression_lhs); + PrintHex(compression_lhs, ptr - compression_lhs); + } + + ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec); + if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative) + { + LogMsg("xD2DParse: failed to get large RR"); + m->rec.r.resrec.RecordType = 0; + return mStatus_UnknownErr; + } + else + { + LogInfo("xD2DParse: got rr: %s", CRDisplayString(m, &m->rec.r)); + } + + *D2DListp = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (m->rec.r.resrec.rdlength <= sizeof(RDataBody) ? 0 : m->rec.r.resrec.rdlength - sizeof(RDataBody))); + if (!*D2DListp) return mStatus_NoMemoryErr; + + AuthRecord *rr = &(*D2DListp)->ar; + mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL); + AssignDomainName(&rr->namestorage, &m->rec.namestorage); + rr->resrec.rdlength = m->rec.r.resrec.rdlength; + rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength; + mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength); + rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); + SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us + + m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use + + return mStatus_NoError; } -mDNSlocal void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize) +mDNSexport void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize) { if (result == kD2DSuccess) { if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DAddToCache: NULL Byte * passed in or length == 0"); return; } mStatus err; - D2DRecordListElem *ptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData))); - - if (ptr == NULL) { LogMsg("xD2DAddToCache: memory allocation failure"); return; } + D2DRecordListElem *ptr = NULL; - err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr->ar); + err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr); if (err) { LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err); PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize); - mDNSPlatformMemFree(ptr); + if (ptr) + mDNSPlatformMemFree(ptr); return; } + + // If the record was created based on a BLE beacon, update the interface index to indicate + // this and thus match BLE specific queries. + if (transportType == D2DBLETransport) + ptr->ar.resrec.InterfaceID = mDNSInterface_BLE; + err = mDNS_Register(m, &ptr->ar); if (err) { @@ -564,17 +619,17 @@ mDNSlocal void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstanc mDNSlocal D2DRecordListElem * xD2DFindInList(mDNS *const m, const Byte *const key, const size_t keySize, const Byte *const value, const size_t valueSize) { D2DRecordListElem *ptr = D2DRecords; - D2DRecordListElem *arptr; + D2DRecordListElem *arptr = NULL; if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; } - arptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData))); - if (arptr == NULL) { LogMsg("xD2DFindInList: memory allocation failure"); return NULL; } - - if (xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr->ar) != mStatus_NoError) + mStatus err = xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr); + if (err) { - LogMsg("xD2DFindInList: xD2DParse failed for key: %p (%u) value: %p (%u)", key, keySize, value, valueSize); - mDNSPlatformMemFree(arptr); + LogMsg("xD2DFindInList: xD2DParse returned error: %d", err); + PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize); + if (arptr) + mDNSPlatformMemFree(arptr); return NULL; } @@ -589,7 +644,7 @@ mDNSlocal D2DRecordListElem * xD2DFindInList(mDNS *const m, const Byte *const ke return ptr; } -mDNSlocal void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize) +mDNSexport void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize) { (void)transportType; // We don't care about this, yet. (void)instanceHandle; // We don't care about this, yet. @@ -777,23 +832,45 @@ mDNSlocal D2DTransportType xD2DInterfaceToTransportType(mDNSInterfaceID Interfac return D2DTransportMax; } -mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags) +// Similar to callExternalHelpers(), but without the checks for the BLE specific interface or flags. +// It's assumed that the domain was already verified to be .local once we are at this level. +mDNSlocal mDNSBool callInternalHelpers(mDNSInterfaceID InterfaceID, DNSServiceFlags flags) { - domainname lower; + if ( ((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL))) + || mDNSPlatformInterfaceIsD2D(InterfaceID)) + return mDNStrue; + else + return mDNSfalse; +} - if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA) +mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q) +{ + // BLE support currently not handled by a D2D plugin + if (applyToBLE(InterfaceID, flags)) { - LogInfo("external_start_browsing_for_service: ignoring address record"); - return; + domainname lower; + + DomainnameToLower(typeDomain, &lower); + // pass in the key and keySize + mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype); + start_BLE_browse(q, &lower, qtype, flags, compression_lhs, end - compression_lhs); } + if (callInternalHelpers(InterfaceID, flags)) + internal_start_browsing_for_service(InterfaceID, typeDomain, qtype, flags); +} + +mDNSexport void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags) +{ + domainname lower; + DomainnameToLower(typeDomain, &lower); if (!D2DBrowseListRefCount(&lower, qtype)) { D2DTransportType transportType, excludedTransport; - LogInfo("external_start_browsing_for_service: Starting browse for: %##s %s", lower.c, DNSTypeName(qtype)); + LogInfo("%s: Starting browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype)); mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype); PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0); @@ -817,22 +894,34 @@ mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags) { - domainname lower; - - if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA) + // BLE support currently not handled by a D2D plugin + if (applyToBLE(InterfaceID, flags)) { - LogInfo("external_stop_browsing_for_service: ignoring address record"); - return; + domainname lower; + + // If this is the last instance of this browse, clear any cached records recieved for it. + // We are not guaranteed to get a D2DServiceLost event for all key, value pairs cached over BLE. + DomainnameToLower(typeDomain, &lower); + if (stop_BLE_browse(&lower, qtype, flags)) + xD2DClearCache(&lower, qtype); } + if (callInternalHelpers(InterfaceID, flags)) + internal_stop_browsing_for_service(InterfaceID, typeDomain, qtype, flags); +} + +mDNSexport void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags) +{ + domainname lower; + DomainnameToLower(typeDomain, &lower); - D2DBrowseListRelease(&lower, qtype); - if (!D2DBrowseListRefCount(&lower, qtype)) + // If found in list and this is the last reference to this browse, remove the key from the D2D plugins. + if (D2DBrowseListRelease(&lower, qtype) && !D2DBrowseListRefCount(&lower, qtype)) { D2DTransportType transportType, excludedTransport; - LogInfo("external_stop_browsing_for_service: Stopping browse for: %##s %s", lower.c, DNSTypeName(qtype)); + LogInfo("%s: Stopping browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype)); mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype); PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0); @@ -860,13 +949,24 @@ mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { + // Note, start_BLE_advertise() is currently called directly from external_start_advertising_helper() since + // it needs to pass the ServiceRecordSet so that we can promote the record advertisements to AWDL + // when we see the corresponding browse indication over BLE. + + if (callInternalHelpers(resourceRecord->InterfaceID, flags)) + internal_start_advertising_service(resourceRecord, flags); +} + +mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) +{ domainname lower; mDNSu8 *rhs = NULL; mDNSu8 *end = NULL; D2DTransportType transportType, excludedTransport; DomainnameToLower(resourceRecord->name, &lower); - LogInfo("external_start_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord)); + LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord)); + // For SRV records, update packet filter if p2p interface already exists, otherwise, // if will be updated when we get the KEV_DL_IF_ATTACHED event for the interface. if (resourceRecord->rrtype == kDNSType_SRV) @@ -894,14 +994,30 @@ mDNSexport void external_start_advertising_service(const ResourceRecord *const r mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { + // BLE support currently not handled by a D2D plugin + if (applyToBLE(resourceRecord->InterfaceID, flags)) + { + domainname lower; + + DomainnameToLower(resourceRecord->name, &lower); + stop_BLE_advertise(&lower, resourceRecord->rrtype, flags); + } + + if (callInternalHelpers(resourceRecord->InterfaceID, flags)) + internal_stop_advertising_service(resourceRecord, flags); +} + +mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) +{ domainname lower; mDNSu8 *rhs = NULL; mDNSu8 *end = NULL; D2DTransportType transportType, excludedTransport; DomainnameToLower(resourceRecord->name, &lower); - LogInfo("external_stop_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord)); + LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord)); + // For SRV records, update packet filter if p2p interface already exists, otherwise, // For SRV records, update packet filter to to remove this port from list if (resourceRecord->rrtype == kDNSType_SRV) mDNSUpdatePacketFilter(resourceRecord); @@ -969,8 +1085,8 @@ mDNSexport void external_start_resolving_service(mDNSInterfaceID InterfaceID, co if (AWDL_used && AWDLInterfaceID) { LogInfo("external_start_resolving_service: browse for TXT and SRV over AWDL"); - external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0); - external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0); + external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0, 0); + external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0, 0); } } @@ -1022,7 +1138,12 @@ mDNSexport void external_stop_resolving_service(mDNSInterfaceID InterfaceID, con #elif APPLE_OSX_mDNSResponder -mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;} +mDNSexport void internal_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags } +mDNSexport void internal_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;} +mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;} +mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;} + +mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags; (void)q } mDNSexport void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;} mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;} mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;} @@ -1046,14 +1167,12 @@ mDNSexport void external_stop_resolving_service(const domainname *const fqdn, DN // to run up the user's bill sending multicast traffic over a link where there's only a single device at the // other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway. -// We also don't want to use multicast on *any* physical interface on very constrained devices. -#if 0 -#define MulticastInterface(i) ((i)->ifa_flags & IFF_LOOPBACK) -#elif TARGET_OS_WATCH -#define MulticastInterface(i) ((i)->m->NumAllInterfaceRecords + (i)->m->NumAllInterfaceQuestions > 0 && ((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT)) +#if BONJOUR_ON_DEMAND +#define MulticastInterface(i) ((i)->m->BonjourEnabled && ((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT)) #else #define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT)) #endif +#define SPSInterface(i) ((i)->ifinfo.McastTxRx && !((i)->ifa_flags & IFF_LOOPBACK) && !(i)->D2DInterface) mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text { @@ -1065,7 +1184,8 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both for (i = mDNSStorage.p->InterfaceList; i; i = i->next) if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17) break; - if (!i) return; // If not at Apple, don't show the alert + if (!i) + return; // If not at Apple, don't show the alert } #endif @@ -1075,12 +1195,20 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both // If we display our alert early in the boot process, then it vanishes once the desktop appears. // To avoid this, we don't try to display alerts in the first three minutes after boot. if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) - { LogMsg("Suppressing notification early in boot: %d", mDNSPlatformRawTime()); return; } + { + LogMsg("Suppressing notification early in boot: %d", mDNSPlatformRawTime()); + return; + } #ifndef NO_CFUSERNOTIFICATION static int notifyCount = 0; // To guard against excessive display of warning notifications - if (notifyCount < 5) { notifyCount++; mDNSNotify(title, msg); } + if (notifyCount < 5) + { + notifyCount++; + mDNSNotify(title, msg); + } #endif /* NO_CFUSERNOTIFICATION */ + } // Write a syslog message and display an alert, then if ForceAlerts is set, generate a stack trace @@ -1249,10 +1377,11 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert subkeyCopy[len] = 0; } - dispatch_async(DynamicStoreQueue, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ CFWriteStreamRef stream = NULL; CFDataRef bytes = NULL; CFIndex ret; + KQueueLock(&mDNSStorage); if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL))) { @@ -1274,7 +1403,6 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert CFWriteStreamClose(stream); CFRelease(stream); stream = NULL; - LogInfo("mDNSDynamicStoreSetConfig: key %d subkey %s", key, subkeyCopy); DynamicStoreWrite(key, subkeyCopy ? subkeyCopy : "", (uintptr_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes)); END: @@ -1288,6 +1416,8 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert CFRelease(bytes); if (subkeyCopy) mDNSPlatformMemFree(subkeyCopy); + + KQueueUnlock(&mDNSStorage, "mDNSDynamicStoreSetConfig"); }); } @@ -1303,50 +1433,6 @@ mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const return(NULL); } -#if TARGET_OS_EMBEDDED -mDNSlocal SCPreferencesRef mDNSManagedPrefsGet(void) -{ - SCPreferencesRef smDNSManagedPrefs = NULL; - smDNSManagedPrefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("mDNSManagedPrefs"), kmDNSResponderManagedPrefsID); - - return (smDNSManagedPrefs); -} - -mDNSlocal mDNSBool GetmDNSManagedPrefKeyVal(SCPreferencesRef prefs, CFStringRef key) -{ - mDNSBool val = mDNSfalse; - CFBooleanRef val_cf = NULL; - - if (prefs != NULL) - { - val_cf = SCPreferencesGetValue(prefs, key); - if (isA_CFBoolean(val_cf) != NULL) - val = CFBooleanGetValue(val_cf); //When mDNSResponder-Debug-profile is Installed - else - val = mDNSfalse; //When mDNSResponder-Debug-profile is Uninstalled - } - else - { - LogMsg("GetmDNSManagedPrefKeyVal: mDNSManagedPrefs are NULL!"); - val = mDNSfalse; - } - return (val); -} - -mDNSexport mDNSBool GetmDNSManagedPref(CFStringRef key) -{ - SCPreferencesRef managed = NULL; - mDNSBool ret_value; - - managed = mDNSManagedPrefsGet(); - ret_value = GetmDNSManagedPrefKeyVal(managed, key); - - if (managed) - CFRelease(managed); - return (ret_value); -} -#endif //TARGET_OS_EMBEDDED - mDNSlocal int myIfIndexToName(u_short ifindex, char *name) { struct ifaddrs *ifa; @@ -1373,6 +1459,7 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const { if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly); if (ifindex == kDNSServiceInterfaceIndexP2P ) return(mDNSInterface_P2P); + if (ifindex == kDNSServiceInterfaceIndexBLE ) return(mDNSInterface_BLE); if (ifindex == kDNSServiceInterfaceIndexAny ) return(mDNSNULL); NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex); @@ -1393,9 +1480,11 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange) { NetworkInterfaceInfoOSX *i; + if (id == mDNSInterface_Any ) return(0); if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly); + if (id == mDNSInterface_Unicast ) return(0); if (id == mDNSInterface_P2P ) return(kDNSServiceInterfaceIndexP2P); - if (id == mDNSInterface_Any ) return(0); + if (id == mDNSInterface_BLE ) return(kDNSServiceInterfaceIndexBLE); mDNSu32 scope_id = (mDNSu32)(uintptr_t)id; @@ -1727,62 +1816,74 @@ mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass) (void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class)); } -mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q) +mDNSlocal int mDNSPlatformGetSocktFd(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType) { - if (src) + if (transType == mDNSTransport_UDP) + { + UDPSocket* sock = (UDPSocket*) sockCxt; + return (addrType == mDNSAddrType_IPv4) ? sock->ss.sktv4 : sock->ss.sktv6; + } + else if (transType == mDNSTransport_TCP) { - int s; - char unenc_name[MAX_ESCAPED_DOMAIN_NAME]; - ConvertDomainNameToCString(&q->qname, unenc_name); + TCPSocket* sock = (TCPSocket*) sockCxt; + return (addrType == mDNSAddrType_IPv4) ? sock->ss.sktv4 : sock->ss.sktv6; + } + else + { + LogInfo("mDNSPlatformGetSocktFd: invalid transport %d", transType); + return kInvalidSocketRef; + } +} - if (dst->type == mDNSAddrType_IPv4) - s = src->ss.sktv4; - else - s = src->ss.sktv6; +mDNSexport void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType, DNSQuestion *q) +{ + int sockfd; + char unenc_name[MAX_ESCAPED_DOMAIN_NAME]; - if (q->pid) - { - if (setsockopt(s, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1) - LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid); - } - else - { - if (setsockopt(s, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1) - LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate UUID failed %s", strerror(errno)); - } - - // set the domain on the UDP socket - if (!(ne_session_set_socket_attributes(s, unenc_name, NULL))) - LogInfo("mDNSPlatformSetuDNSSocktOpt: ne_session_set_socket_attributes()-> setting domain failed for %s", unenc_name); + // verify passed-in arguments exist and that sockfd is valid + if (q == mDNSNULL || sockCxt == mDNSNULL || (sockfd = mDNSPlatformGetSocktFd(sockCxt, transType, addrType)) < 0) + return; -#if defined(SO_NOWAKEFROMSLEEP) - int nowake = 1; - if (setsockopt(s, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1) - LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno)); -#endif - - if (q->DenyOnCellInterface || q->DenyOnExpInterface) - { + if (q->pid) + { + if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1) + LogMsg("mDNSPlatformSetSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid); + } + else + { + if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1) + LogMsg("mDNSPlatformSetSocktOpt: Delegate UUID failed %s", strerror(errno)); + } + + // set the domain on the socket + ConvertDomainNameToCString(&q->qname, unenc_name); + if (!(ne_session_set_socket_attributes(sockfd, unenc_name, NULL))) + LogInfo("mDNSPlatformSetSocktOpt: ne_session_set_socket_attributes()-> setting domain failed for %s", unenc_name); + + int nowake = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1) + LogInfo("mDNSPlatformSetSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno)); + + if ((q->flags & kDNSServiceFlagsDenyCellular) || (q->flags & kDNSServiceFlagsDenyExpensive)) + { #if defined(SO_RESTRICT_DENY_CELLULAR) - if (q->DenyOnCellInterface) - { - int restrictions = 0; - restrictions = SO_RESTRICT_DENY_CELLULAR; - if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1) - LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno)); - } + if (q->flags & kDNSServiceFlagsDenyCellular) + { + int restrictions = 0; + restrictions = SO_RESTRICT_DENY_CELLULAR; + if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1) + LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno)); + } #endif #if defined(SO_RESTRICT_DENY_EXPENSIVE) - if (q->DenyOnExpInterface) - { - int restrictions = 0; - restrictions = SO_RESTRICT_DENY_EXPENSIVE; - if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1) - LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno)); - } + if (q->flags & kDNSServiceFlagsDenyExpensive) + { + int restrictions = 0; + restrictions = SO_RESTRICT_DENY_EXPENSIVE; + if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1) + LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno)); + } #endif - } - } } @@ -1938,7 +2039,10 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms LogInfo("mDNSPlatformSendUDP -> sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu", s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow)); if (!mDNSAddressIsAllDNSLinkGroup(dst)) - if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr); + { + if (errno == EHOSTUNREACH) return(mStatus_HostUnreachErr); + if (errno == EHOSTDOWN || errno == ENETDOWN || errno == ENETUNREACH) return(mStatus_TransientErr); + } // Don't report EHOSTUNREACH in the first three minutes after boot // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>) // but this means that sometimes it starts before configd has finished setting up the multicast routing entries. @@ -1962,14 +2066,6 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms result = mStatus_UnknownErr; } -#ifdef IP_BOUND_IF - if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst)) - { - static const mDNSu32 ifindex = 0; - setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)); - } -#endif - return(result); } @@ -2089,33 +2185,6 @@ mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr) return(mDNSInterface_Any); } -// This is a stupid hack and we should get rid of it. -// The chance of there being a second unicast UDP packet already waiting in the kernel before we’ve -// finished processing the previous one is virtually nil, and will only happen by luck on very rare -// occasions when running on a machine with a fast network connection and a slow or busy processor. -// The idea that we’d rely for correctness on this random chance event occurring is ridiculous. -// -- SC -mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src) -{ - // We should have a DNSMessage header followed by the question and an answer - // which also includes a CNAME (that's when this function is called). To keep it - // simple, we expect at least the size of DNSMessage header(12) and size of "A" - // record (14 bytes). - char buffer[26]; - int ret; - - (void) m; - - if (!src) - return mDNSfalse; - - ret = recv(src->ss.sktv4, buffer, sizeof(buffer), MSG_PEEK); - if (ret > 0) - return mDNStrue; - else - return mDNSfalse; -} - mDNSexport void myKQSocketCallBack(int s1, short filter, void *context) { KQSocketSet *const ss = (KQSocketSet *)context; @@ -2133,7 +2202,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context) while (!closed) { - mDNSAddr senderAddr, destAddr; + mDNSAddr senderAddr, destAddr = zeroAddr; mDNSIPPort senderPort; struct sockaddr_storage from; size_t fromlen = sizeof(from); @@ -2680,16 +2749,16 @@ mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort addr.sin_family = AF_INET; addr.sin_port = port->NotAnInteger; err = bind(skt, (struct sockaddr*) &addr, sizeof(addr)); - if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); close(skt); return err; } // Receive interface identifiers err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)); - if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); close(skt); return err; } mDNSPlatformMemZero(&addr, sizeof(addr)); socklen_t len = sizeof(addr); err = getsockname(skt, (struct sockaddr*) &addr, &len); - if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); close(skt); return err; } port->NotAnInteger = addr.sin_port; } @@ -2701,16 +2770,16 @@ mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort addr6.sin6_family = AF_INET6; addr6.sin6_port = port->NotAnInteger; err = bind(skt, (struct sockaddr*) &addr6, sizeof(addr6)); - if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); close(skt); return err; } // We want to receive destination addresses and receive interface identifiers err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); - if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); close(skt); return err; } mDNSPlatformMemZero(&addr6, sizeof(addr6)); socklen_t len = sizeof(addr6); err = getsockname(skt, (struct sockaddr *) &addr6, &len); - if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); return err; } + if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); close(skt); return err; } port->NotAnInteger = addr6.sin6_port; @@ -3106,6 +3175,14 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; } } + // Don't want to wake from sleep for inbound packets on the mDNS sockets + if (mDNSSameIPPort(port, MulticastDNSPort)) + { + int nowake = 1; + if (setsockopt(skt, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1) + LogInfo("SetupSocket: SO_NOWAKEFROMSLEEP failed %s", strerror(errno)); + } + if (sa_family == AF_INET) { // We want to receive destination addresses @@ -3140,7 +3217,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa else if (sa_family == AF_INET6) { // NAT-PMP Announcements make no sense on IPv6, and we don't support IPv6 for PCP, so bail early w/o error - if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort;return mStatus_NoError; } + if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort; close(skt); return mStatus_NoError; } // We want to receive destination addresses and receive interface identifiers err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); @@ -3329,7 +3406,7 @@ mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i) // Note: MUST NOT close() the underlying native BSD sockets. // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them. - CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode); + CFRunLoopRemoveSource(CFRunLoopGetMain(), i->BPF_rls, kCFRunLoopDefaultMode); CFRelease(i->BPF_rls); CFSocketInvalidate(i->BPF_cfs); CFRelease(i->BPF_cfs); @@ -3407,34 +3484,374 @@ mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIP mDNSSendKeepalive(sadd->ip.v6.b, dadd->ip.v6.b, lport->NotAnInteger, rport->NotAnInteger, seq, ack, win); } -mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void) +mDNSexport mStatus mDNSPlatformClearSPSData(void) { - CFStringRef entityname = NULL; + CFStringRef spsAddress = NULL; + CFStringRef ownerOPTRec = NULL; - if ((entityname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress"))) + if ((spsAddress = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress"))) { - if (SCDynamicStoreRemoveValue(NULL, entityname) == false) - LogSPS("mDNSPlatformClearSPSMACAddr: Unable to remove key"); + if (SCDynamicStoreRemoveValue(NULL, spsAddress) == false) + LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy address key"); } - if (entityname) - CFRelease(entityname); + if((ownerOPTRec = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyOPTRecord"))) + { + if (SCDynamicStoreRemoveValue(NULL, ownerOPTRec) == false) + LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy owner option record key"); + } + + if (spsAddress) CFRelease(spsAddress); + if (ownerOPTRec) CFRelease(ownerOPTRec); return KERN_SUCCESS; } +mDNSlocal int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth) +{ + struct + { + struct rt_msghdr m_rtm; + char m_space[512]; + } m_rtmsg; + + struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); + char *cp = m_rtmsg.m_space; + int seq = 6367, sock, rlen, i; + struct sockaddr_in *sin = NULL; + struct sockaddr_in6 *sin6 = NULL; + struct sockaddr_dl *sdl = NULL; + struct sockaddr_storage sins; + struct sockaddr_dl sdl_m; + +#define NEXTADDR(w, s, len) \ +if (rtm->rtm_addrs & (w)) \ +{ \ +bcopy((char *)s, cp, len); \ +cp += len; \ +} + + bzero(&sins, sizeof(struct sockaddr_storage)); + bzero(&sdl_m, sizeof(struct sockaddr_dl)); + bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); + + sock = socket(PF_ROUTE, SOCK_RAW, 0); + if (sock < 0) + { + LogMsg("getMACAddress: Can not open the socket - %s", strerror(errno)); + return errno; + } + + rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY; + rtm->rtm_type = RTM_GET; + rtm->rtm_flags = 0; + rtm->rtm_version = RTM_VERSION; + rtm->rtm_seq = ++seq; + + sdl_m.sdl_len = sizeof(sdl_m); + sdl_m.sdl_family = AF_LINK; + if (family == AF_INET) + { + sin = (struct sockaddr_in*)&sins; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr)); + NEXTADDR(RTA_DST, sin, sin->sin_len); + } + else if (family == AF_INET6) + { + sin6 = (struct sockaddr_in6 *)&sins; + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr)); + NEXTADDR(RTA_DST, sin6, sin6->sin6_len); + } + NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len); + rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg; + + if (write(sock, (char *)&m_rtmsg, rlen) < 0) + { + LogMsg("getMACAddress: writing to routing socket: %s", strerror(errno)); + close(sock); + return errno; + } + + do + { + rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg)); + } + while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid())); + + if (rlen < 0) + LogMsg("getMACAddress: Read from routing socket failed"); + + if (family == AF_INET) + { + sin = (struct sockaddr_in *) (rtm + 1); + sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin); + } + else if (family == AF_INET6) + { + sin6 = (struct sockaddr_in6 *) (rtm +1); + sdl = (struct sockaddr_dl *) (sin6->sin6_len + (char *) sin6); + } + + if (!sdl) + { + LogMsg("getMACAddress: sdl is NULL for family %d", family); + close(sock); + return -1; + } + + // If the address is not on the local net, we get the IP address of the gateway. + // We would have to repeat the process to get the MAC address of the gateway + *gfamily = sdl->sdl_family; + if (sdl->sdl_family == AF_INET) + { + if (sin) + { + struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin); + memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr)); + } + else + { + LogMsg("getMACAddress: sin is NULL"); + } + close(sock); + return -1; + } + else if (sdl->sdl_family == AF_INET6) + { + if (sin6) + { + struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6); + memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr)); + } + else + { + LogMsg("getMACAddress: sin6 is NULL"); + } + close(sock); + return -1; + } + + unsigned char *ptr = (unsigned char *)LLADDR(sdl); + for (i = 0; i < ETHER_ADDR_LEN; i++) + (eth)[i] = *(ptr +i); + + close(sock); + + return KERN_SUCCESS; +} + +mDNSlocal int GetRemoteMacinternal(int family, v6addr_t raddr, ethaddr_t eth) +{ + int ret = 0; + v6addr_t gateway; + int gfamily = 0; + int count = 0; + + do + { + ret = getMACAddress(family, raddr, gateway, &gfamily, eth); + if (ret == -1) + { + memcpy(raddr, gateway, sizeof(family)); + family = gfamily; + count++; + } + } + while ((ret == -1) && (count < 5)); + return ret; +} + +mDNSlocal int StoreSPSMACAddressinternal(int family, v6addr_t spsaddr, const char *ifname) +{ + ethaddr_t eth; + char spsip[INET6_ADDRSTRLEN]; + int ret = 0; + CFStringRef sckey = NULL; + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL); + SCDynamicStoreRef ipstore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL); + CFMutableDictionaryRef dict = NULL; + CFStringRef entityname = NULL; + CFDictionaryRef ipdict = NULL; + CFArrayRef addrs = NULL; + + if ((store == NULL) || (ipstore == NULL)) + { + LogMsg("StoreSPSMACAddressinternal: Unable to accesss SC Dynamic Store"); + ret = -1; + goto fin; + } + + // Get the MAC address of the Sleep Proxy Server + memset(eth, 0, sizeof(eth)); + ret = GetRemoteMacinternal(family, spsaddr, eth); + if (ret != 0) + { + LogMsg("StoreSPSMACAddressinternal: Failed to determine the MAC address"); + goto fin; + } + + // Create/Update the dynamic store entry for the specified interface + sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress"); + dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!dict) + { + LogMsg("StoreSPSMACAddressinternal: SPSCreateDict() Could not create CFDictionary dict"); + ret = -1; + goto fin; + } + + CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr); + if (NULL != macaddr) + CFRelease(macaddr); + + if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip))) + { + LogMsg("StoreSPSMACAddressinternal: inet_ntop failed: %s", strerror(errno)); + ret = -1; + goto fin; + } + + CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8); + CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr); + if (NULL != ipaddr) + CFRelease(ipaddr); + + // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup + if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL) + { + if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL) + { + if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL) + { + addrs = CFRetain(addrs); + CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs); + } + } + } + SCDynamicStoreSetValue(store, sckey, dict); + +fin: + if (store) CFRelease(store); + if (ipstore) CFRelease(ipstore); + if (sckey) CFRelease(sckey); + if (dict) CFRelease(dict); + if (ipdict) CFRelease(ipdict); + if (entityname) CFRelease(entityname); + if (addrs) CFRelease(addrs); + + return ret; +} + +mDNSlocal void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname) +{ + struct + { + v6addr_t saddr; + } addr; + int err = 0; + + mDNSPlatformMemCopy(addr.saddr, spsaddr, sizeof(v6addr_t)); + + err = StoreSPSMACAddressinternal(family, (uint8_t *)addr.saddr, ifname); + if (err != 0) + LogMsg("mDNSStoreSPSMACAddress : failed"); +} + mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname) { int family = (spsaddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6; - LogSPS("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname); + + LogInfo("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname); mDNSStoreSPSMACAddress(family, spsaddr->ip.v6.b, ifname); + return KERN_SUCCESS; } + +mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage* msg, int length) +{ + int ret = 0; + CFStringRef sckey = NULL; + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreOwnerOPTRecord"), NULL, NULL); + CFMutableDictionaryRef dict = NULL; + + if (store == NULL) + { + LogMsg("mDNSPlatformStoreOwnerOptRecord: Unable to accesss SC Dynamic Store"); + ret = -1; + goto fin; + } + + // Create/Update the dynamic store entry for the specified interface + sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyOPTRecord"); + dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!dict) + { + LogMsg("mDNSPlatformStoreOwnerOptRecord: Could not create CFDictionary dictionary to store OPT Record"); + ret =-1; + goto fin; + } + + CFDataRef optRec = NULL; + optRec = CFDataCreate(NULL, (const uint8_t *)msg, (CFIndex)length); + CFDictionarySetValue(dict, CFSTR("OwnerOPTRecord"), optRec); + if (NULL != optRec) CFRelease(optRec); + + SCDynamicStoreSetValue(store, sckey, dict); + +fin: + if (NULL != store) CFRelease(store); + if (NULL != sckey) CFRelease(sckey); + if (NULL != dict) CFRelease(dict); + return ret; +} + +mDNSlocal void mDNSGet_RemoteMAC(mDNS *const m, int family, v6addr_t raddr) +{ + ethaddr_t eth; + IPAddressMACMapping *addrMapping; + int kr = KERN_FAILURE; + struct + { + v6addr_t addr; + } dst; + + mDNSPlatformMemCopy(dst.addr, raddr, sizeof(v6addr_t)); + + kr = GetRemoteMacinternal(family, (uint8_t *)dst.addr, eth); + + // If the call to get the remote MAC address succeeds, allocate and copy + // the values and schedule a task to update the MAC address in the TCP Keepalive record. + if (kr == 0) + { + addrMapping = mDNSPlatformMemAllocate(sizeof(IPAddressMACMapping)); + snprintf(addrMapping->ethaddr, sizeof(addrMapping->ethaddr), "%02x:%02x:%02x:%02x:%02x:%02x", + eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + if (family == AF_INET) + { + addrMapping->ipaddr.type = mDNSAddrType_IPv4; + mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v4.b, raddr, sizeof(v6addr_t)); + } + else + { + addrMapping->ipaddr.type = mDNSAddrType_IPv6; + mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v6.b, raddr, sizeof(v6addr_t)); + } + UpdateRMAC(m, addrMapping); + } +} + mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr) { int family = (raddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6; - - mDNSGetRemoteMAC(m, family, raddr->ip.v6.b); + + LogInfo("mDNSPlatformGetRemoteMacAddr calling mDNSGet_RemoteMAC"); + mDNSGet_RemoteMAC(m, family, raddr->ip.v6.b); + return KERN_SUCCESS; } @@ -3485,7 +3902,7 @@ mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID NetworkInterfaceInfoOSX *x; // Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also. - for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break; + for (x = m->p->InterfaceList; x; x = x->next) if ((x->ifinfo.InterfaceID == InterfaceID) && (x->BPF_fd >= 0)) break; if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; } @@ -3711,7 +4128,7 @@ mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd) i->BPF_fd = fd; i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext); i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0); - CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode); + CFRunLoopAddSource(CFRunLoopGetMain(), i->BPF_rls, kCFRunLoopDefaultMode); #endif mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID); } @@ -3999,8 +4416,8 @@ mDNSlocal mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf) mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i) { - if (!MulticastInterface(i) ) return(mDNSfalse); // We only use Sleep Proxy Service on multicast-capable interfaces - if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse); // except loopback + // We only use Sleep Proxy Service on multicast-capable interfaces, except loopback and D2D. + if (!SPSInterface(i)) return(mDNSfalse); // If the interface supports TCPKeepalive, it is capable of waking up for a magic packet // This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability @@ -4140,6 +4557,7 @@ exit: // Return true if the interface is associate to a CarPlay hosted SSID. mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name) { + static WiFiManagerClientRef manager = NULL; mDNSBool rvalue = mDNSfalse; if (!MobileWiFiLibLoad()) @@ -4148,10 +4566,15 @@ mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name) // If we have associated with a CarPlay hosted SSID, then use the same // optimizations that are used if an interface has the IFEF_DIRECTLINK flag set. - WiFiManagerClientRef manager; + // Get one WiFiManagerClientRef to use for all calls. + if (manager == NULL) + manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal); - manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal); - if (manager != NULL) + if (manager == NULL) + { + LogInfo("IsCarPlaySSID: WiFiManagerClientCreate() failed!"); + } + else { CFArrayRef devices; @@ -4174,7 +4597,6 @@ mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name) } CFRelease(devices); } - CFRelease(manager); } return rvalue; @@ -4263,6 +4685,8 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad i->ifinfo.Loopback = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse; i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue; + // Setting DirectLink indicates we can do the optimization of skipping the probe phase + // for the interface address records since they should be unique. if (eflags & IFEF_DIRECTLINK) i->ifinfo.DirectLink = mDNStrue; else @@ -4281,6 +4705,7 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad // Bonjour requests over the AWDL interface. i->ifinfo.SupportsUnicastMDNSResponse = mDNSfalse; AWDLInterfaceID = i->ifinfo.InterfaceID; + i->ifinfo.DirectLink = mDNStrue; LogInfo("AddInterfaceToList: AWDLInterfaceID = %d", (int) AWDLInterfaceID); } else @@ -4555,7 +4980,7 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut else if (llqStatus == mStatus_NoSuchRecord) { status = llqStatus; - mDNS_snprintf(buffer, sizeof(buffer), llqBuffer); + mDNS_snprintf(buffer, sizeof(buffer), "%s", llqBuffer); } else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT)) { @@ -4582,7 +5007,7 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut else { status = llqStatus; - mDNS_snprintf(buffer, sizeof(buffer), llqBuffer); + mDNS_snprintf(buffer, sizeof(buffer), "%s", llqBuffer); LogInfo("UpdateAutoTunnelDomainStatus: LLQ Status %d, %s", status, buffer); } @@ -4649,8 +5074,7 @@ mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m) // Determine whether we if (info != AnonymousRacoonConfig) { AnonymousRacoonConfig = info; - // Create or revert configuration file, and start (or SIGHUP) Racoon - (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? btmmprefix : mDNSNULL, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL); + LogInfo("UpdateAnonymousRacoonConfig need not be done in mDNSResponder"); } } @@ -5388,8 +5812,6 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q) p->q.ForceMCast = mDNSfalse; p->q.ReturnIntermed = mDNStrue; p->q.SuppressUnusable = mDNSfalse; - p->q.DenyOnCellInterface = mDNSfalse; - p->q.DenyOnExpInterface = mDNSfalse; p->q.SearchListIndex = 0; p->q.AppendSearchDomains = 0; p->q.RetryWithSearchDomains = mDNSfalse; @@ -5507,7 +5929,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6); } - if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY))) + if (!(ifru_flags6 & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY))) { if (ifa->ifa_flags & IFF_LOOPBACK) { @@ -5634,6 +6056,9 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc) { NetworkInterfaceInfoOSX *i; int count = 0; + + // Recalculate SuppressProbes time based on the current set of active interfaces. + m->SuppressProbes = 0; for (i = m->p->InterfaceList; i; i = i->next) if (i->Exists) { @@ -5687,8 +6112,8 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc) if (!n->McastTxRx) { debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip); -#if TARGET_OS_WATCH - // We join the Bonjour multicast group on the watch only when a client request is active, +#if TARGET_OS_EMBEDDED + // We join the Bonjour multicast group on Apple embedded platforms ONLY when a client request is active, // so we leave the multicast group here to clear any residual group membership. if (i->sa_family == AF_INET) { @@ -5719,7 +6144,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc) LogMsg("setsockopt - IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface); } } -#endif // TARGET_OS_WATCH +#endif // TARGET_OS_EMBEDDED } else { @@ -5963,21 +6388,38 @@ mDNSexport const char *DNSScopeToString(mDNSu32 scope) } } -mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interface, mDNSu32 scope, MD5_CTX *sdc) +mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interfaceId, mDNSu32 scope, MD5_CTX *sdc, uint64_t generation) { const char *scopeString = DNSScopeToString(scope); int j; + domainname d; + + if (scope == kScopeNone) + interfaceId = mDNSInterface_Any; - if (scope != kScopeNone) + if (scope == kScopeNone || scope == kScopeInterfaceID) { - LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for Interface %p", scopeString, interface); - return; + for (j = 0; j < resolver->n_search; j++) + { + if (MakeDomainNameFromDNSNameString(&d, resolver->search[j]) != NULL) + { + static char interface_buf[32]; + mDNS_snprintf(interface_buf, sizeof(interface_buf), "for interface %s", InterfaceNameForID(m, interfaceId)); + LogInfo("ConfigSearchDomains: (%s) configuring search domain %s %s (generation= %llu)", scopeString, + resolver->search[j], (interfaceId == mDNSInterface_Any) ? "" : interface_buf, generation); + UpdateSearchDomainHash(m, sdc, resolver->search[j], interfaceId); + mDNS_AddSearchDomain_CString(resolver->search[j], interfaceId); + } + else + { + LogInfo("ConfigSearchDomains: An invalid search domain was detected for %s domain %s n_nameserver %d, (generation= %llu)", + DNSScopeToString(scope), resolver->domain, resolver->n_nameserver, generation); + } + } } - for (j = 0; j < resolver->n_search; j++) + else { - LogInfo("ConfigSearchDomains: (%s) configuring search list %s", scopeString, resolver->search[j]); - UpdateSearchDomainHash(m, sdc, resolver->search[j], NULL); - mDNS_AddSearchDomain_CString(resolver->search[j], NULL); + LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for interface %s", scopeString, InterfaceNameForID(m,interfaceId)); } } @@ -6140,7 +6582,8 @@ mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scop if (setsearch) { - ConfigSearchDomains(m, resolver[i], interface, scope, sdc); + ConfigSearchDomains(m, resolver[i], interface, scope, sdc, config->generation); + // Parse other scoped resolvers for search lists if (!setservers) continue; @@ -6522,9 +6965,8 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, } else { - LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu", config->n_resolver, config->generation); - // SameDomainName check below is to fix <rdar://problem/18059009> Dynamic DNS hostname changes not noticed - if (m->p->LastConfigGeneration == config->generation && (!fqdn || (SameDomainName(fqdn, &m->FQDN)))) + LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu, last %llu", config->n_resolver, config->generation, m->p->LastConfigGeneration); + if (m->p->LastConfigGeneration == config->generation) { LogInfo("mDNSPlatformSetDNSConfig: generation number %llu same, not processing", config->generation); dns_configuration_free(config); @@ -6855,7 +7297,7 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m) else LogInfo("UpdateBTMMRelayConnection: Not calling AWS_Disconnect"); } } -#else +#elif !TARGET_OS_EMBEDDED mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m) { (void) m; // Unused @@ -6863,12 +7305,14 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m) } #endif // ! NO_AWACS +#if !TARGET_OS_EMBEDDED mDNSlocal void ProcessConndConfigChanges(mDNS *const m); +#endif #endif // APPLE_OSX_mDNSResponder // MUST be called holding the lock -mDNSexport void SetDomainSecrets(mDNS *m) +mDNSlocal void SetDomainSecrets_internal(mDNS *m) { #ifdef NO_SECURITYFRAMEWORK (void) m; @@ -7134,6 +7578,15 @@ mDNSexport void SetDomainSecrets(mDNS *m) #endif /* NO_SECURITYFRAMEWORK */ } +mDNSexport void SetDomainSecrets(mDNS *m) +{ +#if DEBUG + // Don't get secrets for BTMM if running in debug mode + if (!IsDebugSocketInUse()) +#endif + SetDomainSecrets_internal(m); +} + mDNSlocal void SetLocalDomains(void) { CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -7303,6 +7756,7 @@ mDNSlocal void UpdateSPSStatus(mDNS *const m, DNSQuestion *question, const Resou CFRelease(ifname); } +#if !TARGET_OS_EMBEDDED mDNSlocal mDNSs32 GetSystemSleepTimerSetting(void) { mDNSs32 val = -1; @@ -7365,6 +7819,7 @@ mDNSlocal void SetSPS(mDNS *const m) mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures); } +#endif // !TARGET_OS_EMBEDDED // The definitions below should eventually come from some externally-supplied header file. // However, since these definitions can't really be changed without breaking binary compatibility, @@ -7396,14 +7851,28 @@ typedef struct mDNSlocal mDNSu16 GetPortArray(mDNS *const m, int trans, mDNSIPPort *portarray) { const domainlabel *const tp = (trans == mDNSTransport_UDP) ? (const domainlabel *)"\x4_udp" : (const domainlabel *)"\x4_tcp"; - int count = 0; + int count = 0; + AuthRecord *rr; for (rr = m->ResourceRecords; rr; rr=rr->next) + { if (rr->resrec.rrtype == kDNSType_SRV && SameDomainLabel(ThirdLabel(rr->resrec.name)->c, tp->c)) { - if (portarray) portarray[count] = rr->resrec.rdata->u.srv.port; - count++; + if (!portarray) + count++; + else + { + int i; + for (i = 0; i < count; i++) + if (mDNSSameIPPort(portarray[i], rr->resrec.rdata->u.srv.port)) + break; + + // Add it into the port list only if it not already present in the list + if (i >= count) + portarray[count++] = rr->resrec.rdata->u.srv.port; + } } + } // If Back to My Mac is on, also wake for packets to the IPSEC UDP port (4500) if (trans == mDNSTransport_UDP && m->AutoTunnelNAT.clientContext) @@ -7546,7 +8015,7 @@ mDNSexport mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf) { if(!UseInternalSleepProxy) { - LogSPS("SupportsInNICProxy: Internal Sleep Proxy is disabled"); + LogMsg("SupportsInNICProxy: Internal Sleep Proxy is disabled"); return mDNSfalse; } return CheckInterfaceSupport(intf, mDNS_IOREG_KEY); @@ -7607,10 +8076,10 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const cmd.numRRRecords = CountProxyRecords(m, &cmd.rrBufferSize, intf, TCPKAOnly, supportsTCPKA); cmd.compression = sizeof(DNSMessageHeader); - DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize); - cmd.rrRecords.ptr = mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr)); - cmd.udpPorts.ptr = mallocL("mDNSOffloadCmd udpPorts", cmd.numUDPPorts * sizeof(mDNSIPPort)); - cmd.tcpPorts.ptr = mallocL("mDNSOffloadCmd tcpPorts", cmd.numTCPPorts * sizeof(mDNSIPPort)); + DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize); + cmd.rrRecords.ptr = cmd.numRRRecords ? mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr)) : NULL; + cmd.udpPorts.ptr = cmd.numUDPPorts ? mallocL("mDNSOffloadCmd udpPorts" , cmd.numUDPPorts * sizeof(mDNSIPPort)) : NULL; + cmd.tcpPorts.ptr = cmd.numTCPPorts ? mallocL("mDNSOffloadCmd tcpPorts" , cmd.numTCPPorts * sizeof(mDNSIPPort)) : NULL; LogSPS("ActivateLocalProxy: msg %p %d RR %p %d, UDP %p %d, TCP %p %d", msg, cmd.rrBufferSize, @@ -7618,23 +8087,15 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const cmd.udpPorts.ptr, cmd.numUDPPorts, cmd.tcpPorts.ptr, cmd.numTCPPorts); - if (!msg || !cmd.rrRecords.ptr || !cmd.udpPorts.ptr || !cmd.tcpPorts.ptr) - LogMsg("ActivateLocalProxy: Failed to allocate memory: msg %p %d RR %p %d, UDP %p %d, TCP %p %d", - msg, cmd.rrBufferSize, - cmd.rrRecords.ptr, cmd.numRRRecords, - cmd.udpPorts.ptr, cmd.numUDPPorts, - cmd.tcpPorts.ptr, cmd.numTCPPorts); - else - { - GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA); - GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr); - GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr); - char outputData[2]; - size_t outputDataSize = sizeof(outputData); - kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize); - LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr); - if (kr == KERN_SUCCESS) result = mStatus_NoError; - } + if (msg && cmd.rrRecords.ptr) GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA); + if (cmd.udpPorts.ptr) cmd.numUDPPorts = GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr); + if (cmd.tcpPorts.ptr) cmd.numTCPPorts = GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr); + + char outputData[2]; + size_t outputDataSize = sizeof(outputData); + kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize); + LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr); + if (kr == KERN_SUCCESS) result = mStatus_NoError; if (cmd.tcpPorts.ptr) freeL("mDNSOffloadCmd udpPorts", cmd.tcpPorts.ptr); if (cmd.udpPorts.ptr) freeL("mDNSOffloadCmd tcpPorts", cmd.udpPorts.ptr); @@ -7683,10 +8144,15 @@ mDNSlocal mDNSu8 SystemWakeForNetworkAccess(void) mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void) { mDNSs32 val = 0; - GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val); + // PrioritizeNetworkReachabilityOverSleep has been deprecated. + // GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val); + // Statically set the PrioritizeNetworkReachabilityOverSleep value to 1 for AppleTV + if (IsAppleTV()) + val = 1; return val != 0 ? mDNStrue : mDNSfalse; } + #if APPLE_OSX_mDNSResponder // When sleeping, we always ensure that the _autotunnel6 record (if connected to RR relay) // gets deregistered, so that older peers are forced to connect over direct UDP instead of @@ -7744,6 +8210,7 @@ mDNSexport void RemoveAutoTunnel6Record(mDNS *const m) UpdateAutoTunnel6Record(m, info); } +#if !TARGET_OS_EMBEDDED mDNSlocal mDNSBool IPv6AddressIsOnInterface(mDNSv6Addr ipv6Addr, char *ifname) { struct ifaddrs *ifa; @@ -7978,6 +8445,7 @@ mDNSlocal void ProcessConndConfigChanges(mDNS *const m) // If awacsd crashes or exits for some reason, restart it UpdateBTMMRelayConnection(m); } +#endif // !TARGET_OS_EMBEDDED #endif /* APPLE_OSX_mDNSResponder */ mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m) @@ -8027,11 +8495,11 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m) m->NetworkChanged ? "" : " (no scheduled configuration change)"); m->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it - // If we have any NOTREADY IPv6 addresses, wait until they've finished configuring + // If we have *any* TENTATIVE IPv6 addresses, wait until they've finished configuring int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0); if (InfoSocket > 0) { - mDNSBool notready = mDNSfalse; + mDNSBool tentative = mDNSfalse; struct ifaddrs *ifa = myGetIfAddrs(1); while (ifa) { @@ -8046,25 +8514,29 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m) // We can expect that an IN6_IFF_TENTATIVE address will shortly become ready, // but an IN6_IFF_DUPLICATED address may not. if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1) + { if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) { LogInfo("*** Network Configuration Change *** IPv6 address %.16a TENTATIVE, will retry", &ifr6.ifr_addr.sin6_addr); - notready = mDNStrue; + tentative = mDNStrue; + // no need to check other interfaces if we already found out that one interface is TENTATIVE + break; } + } } ifa = ifa->ifa_next; } close(InfoSocket); - if (notready) + if (tentative) { mDNS_Lock(m); SetNetworkChanged(m, mDNSPlatformOneSecond / 2); mDNS_Unlock(m); return; } - LogInfo("*** Network Configuration Change *** No IPv6 address NOTREADY, will continue"); + LogInfo("*** Network Configuration Change *** No IPv6 address TENTATIVE, will continue"); } - + mDNSs32 utc = mDNSPlatformUTC(); m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess(); m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN(); @@ -8073,7 +8545,7 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m) ClearInactiveInterfaces(m, utc); SetupActiveInterfaces(m, utc); -#if APPLE_OSX_mDNSResponder +#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED mDNS_Lock(m); ProcessConndConfigChanges(m); @@ -8129,14 +8601,19 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m) NetworkInterfaceInfoOSX *i; for (i = m->p->InterfaceList; i; i = i->next) { - if (!m->SPSSocket) // Not being Sleep Proxy Server; close any open BPF fds + if (!m->SPSSocket) // Not being Sleep Proxy Server; close any open BPF fds { - if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0) CloseBPF(i); + if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0) + CloseBPF(i); } - else // else, we're Sleep Proxy Server; open BPF fds + else // else, we're Sleep Proxy Server; open BPF fds { - if (i->Exists && i->Registered == i && i->ifinfo.McastTxRx && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1) - { LogSPS("%s requesting BPF", i->ifinfo.ifname); i->BPF_fd = -2; mDNSRequestBPF(); } + if (i->Exists && (i->Registered == i) && SPSInterface(i) && i->BPF_fd == -1) + { + LogMsg("%s mDNSMacOSXNetworkChanged: requesting BPF", i->ifinfo.ifname); + i->BPF_fd = -2; + mDNSRequestBPF(); + } } } @@ -8411,6 +8888,8 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info) mDNS *const m = (mDNS *const)info; (void)store; + KQueueLock(m); // serialize with KQueueLoop() + LogInfo("DynamicStoreReconnected: Reconnected"); // State:/Network/MulticastDNS @@ -8429,15 +8908,14 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info) mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray); #if APPLE_OSX_mDNSResponder - mDNS_Lock(m); // State:/Network/BackToMyMac UpdateAutoTunnelDomainStatuses(m); - mDNS_Unlock(m); // State:/Network/Interface/en0/SleepProxyServers if (spsStatusDict) CFDictionaryApplyFunction(spsStatusDict, RefreshSPSStatus, NULL); #endif + KQueueUnlock(m, "DynamicStoreReconnected"); } mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m) @@ -8474,7 +8952,7 @@ mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m) #else m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; } - CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode); + CFRunLoopAddSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode); #endif SCDynamicStoreSetDisconnectCallBack(store, DynamicStoreReconnected); m->p->Store = store; @@ -8521,7 +8999,7 @@ mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const Reso continue; } - LogInfo("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr)); + LogMsg("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr)); portArray[count] = rr->resrec.rdata->u.srv.port.NotAnInteger; @@ -8529,13 +9007,21 @@ mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const Reso p = rr->resrec.name->c; // Skip to App Protocol - if (p[0]) p += 1 + p[0]; + if (p[0]) + p += 1 + p[0]; // Skip to Transport Protocol - if (p[0]) p += 1 + p[0]; + if (p[0]) + p += 1 + p[0]; - if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocolArray[count] = IPPROTO_TCP; - else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocolArray[count] = IPPROTO_UDP; + if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) + { + protocolArray[count] = IPPROTO_TCP; + } + else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) + { + protocolArray[count] = IPPROTO_UDP; + } else { LogMsg("mDNSSetPacketFilterRules: could not determine transport protocol of service"); @@ -8651,12 +9137,8 @@ mDNSlocal mDNSBool allZeroSSTH(struct opaque_presence_indication *op) return mDNStrue; } -// mDNS_Reconfirm_internal() adds 33% to this interval, so the records should -// be removed in 4 seconds. -#define kAWDLReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 3) - // Mark records from this peer for deletion from the cache. -mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap) +mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap, bool purgeNow) { mDNSu32 slot; CacheGroup *cg; @@ -8680,7 +9162,11 @@ mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr { LogInfo("removeCachedPeerRecords: %s %##s marking for deletion", DNSTypeName(cr->resrec.rrtype), cr->resrec.name->c); - mDNS_Reconfirm_internal(m, cr, kAWDLReconfirmTime); + + if (purgeNow) + mDNS_PurgeCacheResourceRecord(m, cr); + else + mDNS_Reconfirm_internal(m, cr, 0); // use default minimum reconfirm time } } } @@ -8705,8 +9191,8 @@ mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p) peerAddr.type = mDNSAddrType_IPv6; peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr; - LogInfo("nodePresence: ssth is all zeroes, delete cached records from this peer"); - removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr); + LogInfo("nodePresence: ssth is all zeroes, reconfirm cached records for this peer"); + removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, false); } } @@ -8724,8 +9210,8 @@ mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p) peerAddr.type = mDNSAddrType_IPv6; peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr; - LogInfo("nodeAbsence: delete cached records from this peer"); - removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr); + LogInfo("nodeAbsence: immediately purge cached records from this peer"); + removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, true); } mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context) @@ -8922,25 +9408,20 @@ mDNSlocal void PowerOn(mDNS *const m) { mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake; - // Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities. - // This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc. - // We will clear this assertion as soon as we think the mainenance activities are done. - mDNSPlatformPreventSleep(m, DARK_WAKE_TIME, "mDNSResponder:maintenance"); - if (m->p->WakeAtUTC) { long utc = mDNSPlatformUTC(); mDNSPowerRequest(-1,-1); // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake if (m->p->WakeAtUTC - utc > 30) - { + { LogSPS("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc); } - else if (utc - m->p->WakeAtUTC > 30) + else if (utc - m->p->WakeAtUTC > 30) { LogSPS("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC); } else if (IsAppleTV()) - { + { LogSPS("PowerChanged PowerOn %d seconds late, device is an AppleTV running iOS so not re-sleeping", utc - m->p->WakeAtUTC); } else @@ -8949,6 +9430,12 @@ mDNSlocal void PowerOn(mDNS *const m) m->p->RequestReSleep = mDNS_TimeNow(m) + 20 * mDNSPlatformOneSecond; } } + + // Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities. + // This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc. + // We will clear this assertion as soon as we think the mainenance activities are done. + mDNSPlatformPreventSleep(m, DARK_WAKE_TIME, "mDNSResponder:maintenance"); + } mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument) @@ -8969,7 +9456,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m); break; case kIOMessageSystemWillNotPowerOff: LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260 - case kIOMessageCanSystemSleep: LogSPS("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270 + case kIOMessageCanSystemSleep: LogSPS("PowerChanged kIOMessageCanSystemSleep"); break; // E0000270 case kIOMessageSystemWillSleep: LogSPS("PowerChanged kIOMessageSystemWillSleep"); // E0000280 mDNSCoreMachineSleep(m, true); break; @@ -9004,8 +9491,11 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag default: LogSPS("PowerChanged unknown message %X", messageType); break; } - if (messageType == kIOMessageSystemWillSleep) m->p->SleepCookie = (long)messageArgument; - else IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument); + if ((messageType == kIOMessageSystemWillSleep) || (messageType== kIOMessageCanSystemSleep)) + { + m->p->SleepCookie = (long)messageArgument; + IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument); + } KQueueUnlock(m, "PowerChanged Sleep/Wake"); } @@ -9329,93 +9819,77 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t // We might have some extra white spaces at the end for the common case of "1.2.3.4 somehost". // When we parse again below, EtchHostsParseOneName would return -1 and we will end up // doing the right thing. + if (!MakeDomainNameFromDNSNameString(&first, name1)) { LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1); freeaddrinfo(gairesults); return; } + mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth); + + // /etc/hosts alias discussion: + // // If the /etc/hosts has an entry like this // - // 1.2.3.4 sun star bright + // ip_address cname [aliases...] + // 1.2.3.4 sun star bright // // star and bright are aliases (gethostbyname h_alias should point to these) and sun is the canonical // name (getaddrinfo ai_cannonname and gethostbyname h_name points to "sun") // // To achieve this, we need to add the entry like this: // - // star CNAME bright - // bright CNAME sun // sun A 1.2.3.4 + // star CNAME sun + // bright CNAME sun // - // We store the first name we parsed in "first". Then we parse additional names adding CNAME records - // till we reach the end. When we reach the end, we wrap around and add one final CNAME with the last - // entry and the first entry. Finally, we add the Address (A/AAAA) record. + // We store the first name we parsed in "first" and add the address (A/AAAA) record. + // Then we parse additional names adding CNAME records till we reach the end. + aliasIndex = 0; - while (i <= length) + while (i < length) { - // Parse a name. If there are no names, we need to know whether we - // parsed CNAMEs before or not. If we parsed CNAMEs before, then we - // add a CNAME with the last name and the first name. Otherwise, this - // is same as the common case above where the line has just one name - // but with trailing white spaces. + // Continue to parse additional aliases until we reach end of the line and + // for each "alias" parsed, add a CNAME record where "alias" points to the first "name". + // See also /etc/hosts alias discussion above + i = EtcHostsParseOneName(i + 1, length, buffer, &name2); + if (name2) { + if ((aliasIndex) && (*buffer == *name2)) + break; // break out of the loop if we wrap around + if (!MakeDomainNameFromDNSNameString(&name2d, name2)) { LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name2); freeaddrinfo(gairesults); return; } - aliasIndex++; - } - else if (!aliasIndex) - { - // We have never parsed any aliases. This case happens if there - // is just one name and some extra white spaces at the end. - LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c); - break; - } - else - { - // We have parsed at least one alias before and we reached the end of the line. - // Setup a CNAME for the last name with "first" name as its RDATA - name2d.c[0] = 0; - AssignDomainName(&name2d, &first); - } - - // Don't add a CNAME for the first alias we parse (see the example above). - // As we parse more, we might discover that there are no more aliases, in - // which case we would have set "name2d" to "first" above. We need to add - // the CNAME in that case. - - if (aliasIndex > 1 || SameDomainName(&name2d, &first)) - { // Ignore if it points to itself - if (!SameDomainName(&name1d, &name2d)) + if (!SameDomainName(&first, &name2d)) { - if (!mDNSMacOSXCreateEtcHostsEntry(m, &name1d, mDNSNULL, &name2d, ifname, auth)) + if (!mDNSMacOSXCreateEtcHostsEntry(m, &name2d, mDNSNULL, &first, ifname, auth)) { freeaddrinfo(gairesults); return; } } else - LogMsg("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names name1 %##s, name2 %##s", name1d.c, name2d.c); + { + LogInfo("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names first %##s, name2 %##s", first.c, name2d.c); + } + aliasIndex++; + } + else if (!aliasIndex) + { + // We have never parsed any aliases. This case happens if there + // is just one name and some extra white spaces at the end. + LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c); + break; } - - // If we have already wrapped around, we just need to add the A/AAAA record alone - // which is done below - if (SameDomainName(&name2d, &first)) break; - - // Remember the current name so that we can set the CNAME record if we parse one - // more name - name1d.c[0] = 0; - AssignDomainName(&name1d, &name2d); } - // Added all the CNAMEs if any, add the "A/AAAA" record - mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth); } freeaddrinfo(gairesults); } @@ -9813,9 +10287,9 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m) if (!EtcHostsDeleteOldEntries(m, &newhosts, mDNStrue)) { LogInfo("mDNSMacOSXUpdateEtcHosts: No work"); + FreeNewHosts(&newhosts); mDNS_Unlock(m); KQueueUnlock(m, "/etc/hosts changed"); - FreeNewHosts(&newhosts); return; } } @@ -9838,10 +10312,9 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m) // is called back where we do the Registration of the record. This results in RMV followed by ADD which // looks normal. mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts); + FreeNewHosts(&newhosts); mDNS_Unlock(m); - KQueueUnlock(m, "/etc/hosts changed"); - FreeNewHosts(&newhosts); } #if COMPILER_LIKES_PRAGMA_MARK @@ -9988,7 +10461,6 @@ mDNSlocal void SetupLocalHostRecords(mDNS *const m) mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) { mStatus err; - m->p->CFRunLoop = CFRunLoopGetCurrent(); char HINFO_SWstring[256] = ""; mDNSMacOSXSystemBuildNumber(HINFO_SWstring); @@ -9997,13 +10469,6 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) if (err) return err; - DynamicStoreQueue = dispatch_queue_create("com.apple.mDNSResponder.DynamicStoreQueue", NULL); - if (DynamicStoreQueue == NULL) - { - LogMsg("dispatch_queue_create: DynamicStoreQueue NULL!"); - return mStatus_NoMemoryErr; - } - // Store mDNSResponder Platform if (OSXVers) { @@ -10170,7 +10635,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) IOPMConnectionSetDispatchQueue(c, dispatch_get_main_queue()); LogInfo("IOPMConnectionSetDispatchQueue is now running"); #else - iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetMain(), kCFRunLoopDefaultMode); if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr); LogInfo("IOPMConnectionScheduleWithRunLoop is now running"); #endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */ @@ -10187,7 +10652,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue()); #else - CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode); + CFRunLoopAddSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode); #endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */ } } @@ -10252,7 +10717,7 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m) // We only initialize if mDNSCore successfully initialized. if (D2DInitialize) { - D2DStatus ds = D2DInitialize(m->p->CFRunLoop, xD2DServiceCallback, m) ; + D2DStatus ds = D2DInitialize(CFRunLoopGetMain(), xD2DServiceCallback, m) ; if (ds != kD2DSuccess) LogMsg("D2DInitialiize failed: %d", ds); else @@ -10272,7 +10737,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL); #else - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode); + CFRunLoopRemoveSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode); #endif // According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call // to IORegisterForSystemPower creates *three* objects that need to be disposed individually: @@ -10288,7 +10753,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL)) LogMsg("mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed"); #else - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode); + CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(m->p->StoreRLS); CFRelease(m->p->StoreRLS); m->p->StoreRLS = NULL; @@ -10299,7 +10764,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) if (m->p->PMRLS) { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode); + CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->PMRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(m->p->PMRLS); CFRelease(m->p->PMRLS); m->p->PMRLS = NULL; @@ -10338,8 +10803,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) if (AnonymousRacoonConfig) { AnonymousRacoonConfig = mDNSNULL; - LogInfo("mDNSPlatformClose: Deconfiguring autotunnel"); - (void)mDNSConfigureServer(kmDNSDown, mDNSNULL, mDNSNULL); + LogInfo("mDNSPlatformClose: Deconfiguring autotunnel need not be done in mDNSResponder"); } #endif // APPLE_OSX_mDNSResponder } @@ -10416,8 +10880,9 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void) // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves mDNSexport void mDNSPlatformLock (const mDNS *const m) { (void)m; } mDNSexport void mDNSPlatformUnlock (const mDNS *const m) { (void)m; } -mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src) { strcpy((char *)dst, (char *)src); } -mDNSexport mDNSu32 mDNSPlatformStrLen ( const void *src) { return(strlen((char*)src)); } +mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src) { strcpy((char *)dst, (const char *)src); } +mDNSexport mDNSu32 mDNSPlatformStrLCopy( void *dst, const void *src, mDNSu32 dstlen) { return (strlcpy((char *)dst, (const char *)src, dstlen)); } +mDNSexport mDNSu32 mDNSPlatformStrLen ( const void *src) { return(strlen((const char*)src)); } mDNSexport void mDNSPlatformMemCopy( void *dst, const void *src, mDNSu32 len) { memcpy(dst, src, len); } mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len) == 0); } mDNSexport int mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len)); } @@ -10513,6 +10978,11 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID) if (InterfaceID == mDNSInterface_P2P) return mDNStrue; + // mDNSInterface_BLE not considered a D2D interface for the purpose of this + // routine, since it's not implemented via a D2D plugin. + if (InterfaceID == mDNSInterface_BLE) + return mDNSfalse; + if ( (InterfaceID == mDNSInterface_Any) || (InterfaceID == mDNSInterfaceMark) || (InterfaceID == mDNSInterface_LocalOnly) @@ -10536,18 +11006,18 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID) // Filter records send over P2P (D2D) type interfaces // Note that the terms P2P and D2D are used synonymously in the current code and comments. -mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf) +mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID) { // For an explicit match to a valid interface ID, return true. - if (rr->resrec.InterfaceID == intf->InterfaceID) + if (rr->resrec.InterfaceID == InterfaceID) return mDNStrue; // Only filtering records for D2D type interfaces, return true for all other interface types. - if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID)) + if (!mDNSPlatformInterfaceIsD2D(InterfaceID)) return mDNStrue; // If it's an AWDL interface the record must be explicitly marked to include AWDL. - if (intf->InterfaceID == AWDLInterfaceID) + if (InterfaceID == AWDLInterfaceID) { if (rr->ARType == AuthRecordAnyIncludeAWDL || rr->ARType == AuthRecordAnyIncludeAWDLandP2P) return mDNStrue; @@ -10600,11 +11070,7 @@ mDNSexport mDNSBool mDNSPlatformValidRecordForQuestion(const ResourceRecord *c return mDNStrue; if ((rr->InterfaceID == AWDLInterfaceID) && !(q->flags & kDNSServiceFlagsIncludeAWDL)) - { - LogInfo("mDNSPlatformValidRecordForQuestion: Record recieved over AWDL not returned for %s %##s query", - DNSTypeName(q->qtype), q->qname.c); return mDNSfalse; - } return mDNStrue; } diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h index 56c0902a..20f7a321 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h +++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h @@ -31,6 +31,7 @@ extern "C" { #include "mDNSEmbeddedAPI.h" // for domain name structure #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 @@ -41,9 +42,7 @@ extern "C" { #if TARGET_OS_EMBEDDED #define NO_SECURITYFRAMEWORK 1 #define NO_CFUSERNOTIFICATION 1 -#include <MobileGestalt.h> // for IsAppleTV() -#include <SystemConfiguration/scprefs_observer.h> // for _scprefs_observer_watch() -extern mDNSBool GetmDNSManagedPref(CFStringRef key); +#include <MobileGestalt.h> // for IsAppleTV() #endif #ifndef NO_SECURITYFRAMEWORK @@ -51,8 +50,6 @@ extern mDNSBool GetmDNSManagedPref(CFStringRef key); #include <Security/Security.h> #endif /* NO_SECURITYFRAMEWORK */ -#define kmDNSResponderServName "com.apple.mDNSResponder" - enum mDNSDynamicStoreSetConfigKey { kmDNSMulticastConfig = 1, @@ -177,7 +174,6 @@ struct mDNS_PlatformSupport_struct mDNSs32 HostNameConflict; // Time we experienced conflict on our link-local host name mDNSs32 KeyChainTimer; - CFRunLoopRef CFRunLoop; SCDynamicStoreRef Store; CFRunLoopSourceRef StoreRLS; CFRunLoopSourceRef PMRLS; diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist index 8f7f77d9..ef23e4b6 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist +++ b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist @@ -10,6 +10,8 @@ <true/> <key>com.apple.private.SCNetworkConnection-proxy-user</key> <true/> + <key>com.apple.mDNSResponder_Helper</key> + <true/> <key>com.apple.private.network.reserved-port</key> <true/> <key>com.apple.SystemConfiguration.SCDynamicStore-write-access</key> @@ -24,5 +26,11 @@ <true/> <key>com.apple.private.network.awdl.restricted</key> <true/> + <key>com.apple.BTServer.allowRestrictedServices</key> + <true/> + <key>com.apple.BTServer.appleMfgDataAdvertising</key> + <true/> + <key>com.apple.BTServer.appleMfgDataScanner</key> + <true/> </dict> </plist> diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb index 5c8eedd7..30747491 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb +++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb @@ -50,10 +50,12 @@ (global-name "com.apple.CoreServices.coreservicesd") (global-name "com.apple.coreservices.quarantine-resolver") (global-name "com.apple.distributed_notifications.2") + (global-name "com.apple.distributed_notifications@1v3") (global-name "com.apple.lsd.mapdb") (global-name "com.apple.ocspd") (global-name "com.apple.PowerManagement.control") (global-name "com.apple.mDNSResponderHelper") + (global-name "com.apple.mDNSResponder_Helper") (global-name "com.apple.SecurityServer") (global-name "com.apple.SystemConfiguration.configd") (global-name "com.apple.SystemConfiguration.SCNetworkReachability") @@ -110,7 +112,11 @@ (literal "/Library/Security/Trust Settings/Admin.plist") (regex #"^/Library/Preferences/com\.apple\.security\.") (literal "/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist") - (literal "/private/var/preferences/SystemConfiguration/preferences.plist")) + (literal "/private/var/preferences/SystemConfiguration/preferences.plist") + (subpath "/System/Library/Preferences/Logging") + (subpath "/AppleInternal/Library/Preferences/Logging") + (subpath "/Library/Preferences/Logging")) + ; For MAC Address (allow system-info (info-type "net.link.addr")) @@ -122,12 +128,6 @@ (deny file-read-data (regex #"^/Library/Keychains/") (with no-log)) (allow file-read-data (literal "/Library/Keychains/System.keychain")) -; Access to mDNSResponder Managed Preferences profile -; instead of using (mobile-preferences-read "com.apple.mDNSResponder") we use the lines below for OSX compatibility -(allow file-read* (literal "/private/var/Managed Preferences/mobile")) -(allow file-read* (literal "/private/var/Library/Preferences/")) -(allow file-read* (literal "/Library/Managed Preferences")) -(allow file-read* (literal "/private/var/Managed Preferences/mobile/com.apple.mDNSResponder.plist")) ; Our Module Directory Services cache (allow file-read-data diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj index ef2fecbd..3e6c3fd7 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj +++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj @@ -103,21 +103,12 @@ 215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; }; 215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; }; 215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; }; - 215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; - 215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - 215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; 215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; }; 215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; }; 215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; }; - 215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; - 215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - 215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; 215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; }; 215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; }; 215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; }; - 215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; - 215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - 215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; 216D9ACE1720C9F5008066E1 /* uDNSPathEvalulation.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* uDNSPathEvalulation.c */; }; 218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; }; 218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; }; @@ -133,15 +124,22 @@ 21F51DC11B3541940070B05C /* com.apple.mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */; }; 21F51DC31B3541F50070B05C /* com.apple.mDNSResponderHelper.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */; }; 21F51DC51B3542210070B05C /* com.apple.dnsextd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */; }; + 222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */; }; + 222A3C6A1C1B7777003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 222A3C6B1C1B7778003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 222A3C6C1C1B7779003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 222A3C6D1C1B777A003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 222A3C6E1C1B777B003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 222A3C6F1C1B777C003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; }; + 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2243AE381C90AECF0079023E /* CoreBluetooth.framework */; }; + 22448EA31C90A7BE004F25CC /* BLE.c in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA11C90A7B5004F25CC /* BLE.c */; }; + 22448EA41C90A7CB004F25CC /* BLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA21C90A7B5004F25CC /* BLE.h */; }; + 22448EA71C90A837004F25CC /* coreBLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA51C90A82D004F25CC /* coreBLE.h */; }; + 227687F31C90AD580019382D /* coreBLE.m in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA61C90A82D004F25CC /* coreBLE.m */; }; 2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; }; - 2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Client, Server, ); COMPILER_FLAGS = "-Wno-error"; }; }; 2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; }; - 2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; }; 2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; }; 2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; }; - 2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; }; - 2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; }; - 2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; }; 2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; }; 2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; }; 2E4D9B050C38C19500480551 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; }; @@ -152,35 +150,39 @@ 2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; }; 2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; }; 2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; }; - 2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; }; 2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; }; 2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; }; 2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; }; 2EDC5E730C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; }; 2EDC5E750C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; }; + 371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */; }; + 371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */; }; + 373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3732020F1BAB4349007DE806 /* DNSMessageTest.c */; }; + 3771F67D1BA387DD0072355E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9351BA386E70092AC61 /* main.c */; }; + 37DDE9331BA383D30092AC61 /* unittest.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9271BA3825C0092AC61 /* unittest.c */; }; + 37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; }; 4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */; }; 4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */; }; 4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */; }; 4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */; }; 4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */; }; + 729DF4601CD40630005ECF70 /* com.apple.mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */; }; 72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72FB545A166D5F960090B2D9 /* dnsctl.c */; }; 8415A6571897109000BDBA26 /* libdns_services.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8415A6561897109000BDBA26 /* libdns_services.dylib */; }; - 8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */; }; + 8417375C1B967D37000CD5C2 /* dnsctl_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */; }; 848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; }; 848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; }; 848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; }; 84C5B33C166553F100C324A8 /* dns_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 84C5B339166553AF00C324A8 /* dns_services.c */; }; 84F4C090188F050200D1E1DE /* dns_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F4C08F188F04CF00D1E1DE /* dns_services.h */; settings = {ATTRIBUTES = (Private, ); }; }; BD03E88D1AD31278005E8A81 /* SymptomReporter.c in Sources */ = {isa = PBXBuildFile; fileRef = BD03E88C1AD31278005E8A81 /* SymptomReporter.c */; }; - BD2806081C40775600455151 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD2806071C40775600455151 /* Foundation.framework */; }; - BD64FE9C1C40762F0040EAB3 /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BD64FE9A1C40762F0040EAB3 /* Metrics.h */; }; - BD64FE9D1C40762F0040EAB3 /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BD64FE9B1C40762F0040EAB3 /* Metrics.m */; }; + BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; }; + BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; }; + BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA3F0871C48DB6D0054FB4B /* Metrics.h */; }; + BDA3F08F1C48DCA50054FB4B /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BDA3F0881C48DB6D0054FB4B /* Metrics.m */; }; BDA9A7881B3A924C00523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; }; BDA9A7891B3A92A500523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; }; D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; }; - D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; }; - D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; }; D284BE580ADD80740027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; }; D284BE590ADD80740027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; }; D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; }; @@ -216,7 +218,6 @@ D284BED20ADD80A20027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; }; D284BED50ADD80A20027CCDF /* dnsextd.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */; }; D284BEDE0ADD80A70027CCDF /* ddnswriteconfig.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */; }; - D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFFB0DB407B43D2700B88D48 /* Foundation.framework */; }; D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; }; D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; }; D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; }; @@ -241,23 +242,15 @@ D284BF040ADD80B00027CCDF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF2609FA07B4433800CE10E5 /* Cocoa.framework */; }; D284BF050ADD80B00027CCDF /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */; }; D284BF060ADD80B00027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; }; + FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FF3C72A91CE3E62200CDF81E /* libicucore.dylib */; }; FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; }; FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; }; FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; }; FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; }; FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; }; FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; }; - FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; - FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; - FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; }; FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; }; FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; }; - FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; }; - FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; - FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; - FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; }; FFD52A9E1AF858DD00CAD3EC /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; }; FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; }; FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; }; @@ -528,10 +521,10 @@ 8418673D15AB8BFF00BB7F70 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = /private/etc/asl/; + dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( - 8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */, + 729DF4601CD40630005ECF70 /* com.apple.mDNSResponder.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -610,17 +603,35 @@ 21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.dnsextd.plist; sourceTree = "<group>"; }; 21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponderHelper.plist; sourceTree = "<group>"; }; 21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponder.plist; sourceTree = "<group>"; }; - 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = helpermsg.defs; sourceTree = "<group>"; }; + 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; }; + 222A3C571C1B743B003A6FFD /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; }; + 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; }; + 2243AE381C90AECF0079023E /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; + 22448EA11C90A7B5004F25CC /* BLE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BLE.c; sourceTree = "<group>"; }; + 22448EA21C90A7B5004F25CC /* BLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLE.h; sourceTree = "<group>"; }; + 22448EA51C90A82D004F25CC /* coreBLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreBLE.h; sourceTree = "<group>"; }; + 22448EA61C90A82D004F25CC /* coreBLE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = coreBLE.m; sourceTree = "<group>"; }; 2E0405F00C31955500F13B59 /* mDNSResponderHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponderHelper; sourceTree = BUILT_PRODUCTS_DIR; }; 2E0405F40C3195F700F13B59 /* helper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = helper.c; sourceTree = "<group>"; }; 2E0406140C3197CB00F13B59 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; }; 2E0406CA0C31E9AD00F13B59 /* helper-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "helper-main.c"; sourceTree = "<group>"; }; - 2E35528F0C3A95C100CA1CB7 /* helper-error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-error.h"; sourceTree = "<group>"; }; 2E8165F60C59835F00485EB2 /* libipsec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipsec.dylib; path = /usr/lib/libipsec.dylib; sourceTree = "<absolute>"; }; 2E96A5250C39BE480087C4D2 /* helper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = "<group>"; }; 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "helper-stubs.c"; sourceTree = "<group>"; }; 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "helpermsg-types.h"; sourceTree = "<group>"; }; 2EDC5E720C39EA640092701B /* helper-server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-server.h"; sourceTree = "<group>"; }; + 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = InterfaceTest.c; path = ../unittests/InterfaceTest.c; sourceTree = "<group>"; }; + 371D0FBB1BF545FA00E5DB26 /* InterfaceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InterfaceTest.h; path = ../unittests/InterfaceTest.h; sourceTree = "<group>"; }; + 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ResourceRecordTest.c; path = ../unittests/ResourceRecordTest.c; sourceTree = "<group>"; }; + 371D0FBE1BF666EB00E5DB26 /* ResourceRecordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResourceRecordTest.h; path = ../unittests/ResourceRecordTest.h; sourceTree = "<group>"; }; + 3732020F1BAB4349007DE806 /* DNSMessageTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSMessageTest.c; path = ../unittests/DNSMessageTest.c; sourceTree = "<group>"; }; + 373202111BAB63E8007DE806 /* DNSMessageTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DNSMessageTest.h; path = ../unittests/DNSMessageTest.h; sourceTree = "<group>"; }; + 37AF802A1BF699AF00D657F6 /* DomainNameTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DomainNameTest.c; path = ../unittests/DomainNameTest.c; sourceTree = "<group>"; }; + 37AF802B1BF699AF00D657F6 /* DomainNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DomainNameTest.h; path = ../unittests/DomainNameTest.h; sourceTree = "<group>"; }; + 37DDE9271BA3825C0092AC61 /* unittest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unittest.c; path = ../unittests/unittest.c; sourceTree = "<group>"; }; + 37DDE9281BA382670092AC61 /* unittest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unittest.h; path = ../unittests/unittest.h; sourceTree = "<group>"; }; + 37DDE92D1BA383610092AC61 /* unittests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unittests; sourceTree = BUILT_PRODUCTS_DIR; }; + 37DDE9351BA386E70092AC61 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../unittests/main.c; sourceTree = "<group>"; }; 4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uds_daemon.h; path = ../mDNSShared/uds_daemon.h; sourceTree = SOURCE_ROOT; }; 4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DeviceToDeviceManager.framework; path = /System/Library/PrivateFrameworks/DeviceToDeviceManager.framework; sourceTree = "<absolute>"; }; 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = mDNSResponder.txt; sourceTree = "<group>"; }; @@ -635,12 +646,10 @@ 654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSEmbeddedAPI.h; path = ../mDNSCore/mDNSEmbeddedAPI.h; sourceTree = "<group>"; }; 654BE65002B63B93000001D1 /* mDNSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSDebug.h; path = ../mDNSCore/mDNSDebug.h; sourceTree = "<group>"; }; 65713D46025A293200000109 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; }; - 6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; }; - 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; }; - 6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; }; - 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; }; - 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryReply.defs; sourceTree = "<group>"; }; - 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryRequest.defs; sourceTree = "<group>"; }; + 6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; + 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; + 6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; + 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = com.apple.mDNSResponder.plist; path = Private/com.apple.mDNSResponder.plist; sourceTree = "<group>"; }; 72FB545A166D5F960090B2D9 /* dnsctl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dnsctl.c; path = ../Clients/dnsctl.c; sourceTree = "<group>"; }; 72FB545F166D5FB00090B2D9 /* dnsctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsctl; sourceTree = BUILT_PRODUCTS_DIR; }; 7F18A9F60587CEF6001880B3 /* DNSCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSCommon.c; path = ../mDNSCore/DNSCommon.c; sourceTree = SOURCE_ROOT; }; @@ -649,8 +658,7 @@ 7F869685066EE02400D2A2DC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; }; 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LegacyNATTraversal.c; sourceTree = SOURCE_ROOT; }; 8415A6561897109000BDBA26 /* libdns_services.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libdns_services.dylib; path = /usr/lib/libdns_services.dylib; sourceTree = "<absolute>"; }; - 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.networking.mDNSResponder; sourceTree = "<group>"; }; - 8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = mDNSResponderLogging.mobileconfig; sourceTree = "<group>"; }; + 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsctl_server.c; path = Private/dnsctl_server.c; sourceTree = "<group>"; }; 848DA5C6165477E000D2E8B4 /* xpc_services.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xpc_services.c; path = Private/xpc_services.c; sourceTree = "<group>"; }; 848DA5C9165477EB00D2E8B4 /* xpc_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xpc_services.h; path = Private/xpc_services.h; sourceTree = "<group>"; }; 848DA5D516547F7200D2E8B4 /* dns_xpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_xpc.h; path = Private/dns_xpc.h; sourceTree = "<group>"; }; @@ -658,10 +666,9 @@ 84C5B339166553AF00C324A8 /* dns_services.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dns_services.c; path = Private/dns_services.c; sourceTree = "<group>"; }; 84F4C08F188F04CF00D1E1DE /* dns_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_services.h; path = Private/dns_services.h; sourceTree = "<group>"; }; BD03E88C1AD31278005E8A81 /* SymptomReporter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SymptomReporter.c; sourceTree = "<group>"; }; - BD2806071C40775600455151 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - BD64FE9A1C40762F0040EAB3 /* Metrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metrics.h; sourceTree = "<group>"; }; - BD64FE9B1C40762F0040EAB3 /* Metrics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Metrics.m; sourceTree = "<group>"; }; - BD64FE9E1C4076B40040EAB3 /* WirelessDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WirelessDiagnostics.framework; path = System/Library/PrivateFrameworks/WirelessDiagnostics.framework; sourceTree = SDKROOT; }; + BDA3F0871C48DB6D0054FB4B /* Metrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metrics.h; sourceTree = "<group>"; }; + BDA3F0881C48DB6D0054FB4B /* Metrics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Metrics.m; sourceTree = "<group>"; }; + BDA3F0891C48DB910054FB4B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; BDA9A7871B3A923600523835 /* dns_sd_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dns_sd_private.h; path = Private/dns_sd_private.h; sourceTree = "<group>"; }; D284BE730ADD80740027CCDF /* mDNSResponder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder; sourceTree = BUILT_PRODUCTS_DIR; }; D284BEB00ADD80920027CCDF /* dns-sd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "dns-sd"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -685,14 +692,14 @@ DB2CC4680662DFF500335AB3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = "<absolute>"; }; DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSDebug.c; path = ../mDNSShared/mDNSDebug.c; sourceTree = SOURCE_ROOT; }; DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GenLinkedList.c; path = ../mDNSShared/GenLinkedList.c; sourceTree = SOURCE_ROOT; }; - F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; }; + F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; usesTabs = 0; }; F5E11B5A04A28126019798ED /* dnssd_ipc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_ipc.c; path = ../mDNSShared/dnssd_ipc.c; sourceTree = SOURCE_ROOT; }; F5E11B5B04A28126019798ED /* dnssd_ipc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssd_ipc.h; path = ../mDNSShared/dnssd_ipc.h; sourceTree = SOURCE_ROOT; }; FF08480607CEB8E800AE6769 /* inprogress.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = inprogress.tiff; path = PreferencePane/Artwork/inprogress.tiff; sourceTree = SOURCE_ROOT; }; FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; name = dnsextd_lexer.l; path = ../mDNSShared/dnsextd_lexer.l; sourceTree = SOURCE_ROOT; }; FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; name = dnsextd_parser.y; path = ../mDNSShared/dnsextd_parser.y; sourceTree = SOURCE_ROOT; }; FF1C919D07021D77001048AB /* dns-sd.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "dns-sd.1"; path = "../mDNSShared/dns-sd.1"; sourceTree = SOURCE_ROOT; }; - FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; }; + FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; usesTabs = 0; }; FF25794606C9A8BF00376F7B /* dnsextd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsextd.c; path = ../mDNSShared/dnsextd.c; sourceTree = SOURCE_ROOT; }; FF2609FA07B4433800CE10E5 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = "<absolute>"; }; @@ -710,14 +717,13 @@ FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDRecordRegistrar.java; path = ../mDNSShared/Java/DNSSDRecordRegistrar.java; sourceTree = SOURCE_ROOT; }; FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = RegisterRecordListener.java; path = ../mDNSShared/Java/RegisterRecordListener.java; sourceTree = SOURCE_ROOT; }; FF354EB108516C63007C00E1 /* installtool */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = installtool; path = PreferencePane/installtool; sourceTree = SOURCE_ROOT; }; + FF3C72A91CE3E62200CDF81E /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.Internal.sdk/usr/lib/libicucore.dylib; sourceTree = DEVELOPER_DIR; }; FF485D5105632E0000130380 /* mDNSResponder.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mDNSResponder.8; path = ../mDNSShared/mDNSResponder.8; sourceTree = SOURCE_ROOT; }; FF5852100DD27BD300862BDF /* ClientCommon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ClientCommon.c; path = ../Clients/ClientCommon.c; sourceTree = SOURCE_ROOT; }; FF85880B0BD599F40080D89F /* mDNSResponder.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponder.sb; sourceTree = SOURCE_ROOT; }; FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_debug.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_profile.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; }; - FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; }; - FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; }; + FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; usesTabs = 0; }; FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; FFCB6D73075D539900B8AF62 /* PlatformCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PlatformCommon.c; path = ../mDNSShared/PlatformCommon.c; sourceTree = SOURCE_ROOT; }; FFE6935007C2CA7F00283007 /* ConfigurationAuthority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigurationAuthority.h; path = PreferencePane/ConfigurationAuthority.h; sourceTree = SOURCE_ROOT; }; @@ -730,7 +736,6 @@ FFFB0DAD07B43CBA00B88D48 /* PrivilegedOperations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PrivilegedOperations.c; sourceTree = "<group>"; }; FFFB0DAE07B43CBA00B88D48 /* ConfigurationAuthority.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ConfigurationAuthority.c; sourceTree = "<group>"; }; FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ddnswriteconfig.m; sourceTree = "<group>"; }; - FFFB0DB407B43D2700B88D48 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; FFFF8F800C3307AC00722979 /* dnsextd.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dnsextd.conf; path = ../mDNSShared/dnsextd.conf; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -776,6 +781,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 37DDE92A1BA383610092AC61 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 72FB545C166D5FB00090B2D9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -795,8 +807,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */, D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */, - BD2806081C40775600455151 /* Foundation.framework in Frameworks */, + FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */, + BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */, D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */, D284BE680ADD80740027CCDF /* Security.framework in Frameworks */, D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */, @@ -835,7 +849,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */, + BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */, D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */, D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */, D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */, @@ -881,14 +895,16 @@ 08FB7794FE84155DC02AAC07 /* mDNSResponder */ = { isa = PBXGroup; children = ( + 2243AE381C90AECF0079023E /* CoreBluetooth.framework */, + 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */, 08FB7795FE84155DC02AAC07 /* mDNS Server Sources */, 6575FC1F022EB78C00000109 /* Command-Line Clients */, 213FB20912028902002B3A08 /* Bonjour Events Plugin */, - 6575FBFE022EAFA800000109 /* MIG files */, DB2CC4420662DCE500335AB3 /* Java Support */, FFFB0DA407B43BED00B88D48 /* PreferencePane */, 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, 19C28FBDFE9D53C911CA2CBB /* Products */, + 37DDE9241BA382280092AC61 /* Unit Tests */, ); name = mDNSResponder; sourceTree = "<group>"; @@ -896,12 +912,18 @@ 08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = { isa = PBXGroup; children = ( + 22448EA51C90A82D004F25CC /* coreBLE.h */, + 22448EA61C90A82D004F25CC /* coreBLE.m */, + 22448EA11C90A7B5004F25CC /* BLE.c */, + 22448EA21C90A7B5004F25CC /* BLE.h */, + 222A3C571C1B743B003A6FFD /* DNSServiceDiscovery.h */, + 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */, + 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */, 21DD8FBD161E9A250033C8F8 /* anonymous.c */, 21DD8FBE161E9A250033C8F8 /* anonymous.h */, 21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */, 21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */, 21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */, - 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */, 21A57F4A145B2AE100939099 /* CryptoAlg.c */, 21A57F4B145B2AE100939099 /* CryptoAlg.h */, 21A57F51145B2B1400939099 /* CryptoSupport.c */, @@ -930,11 +952,8 @@ 2124FA2F1471E9B50021D7BB /* dnssec.h */, 21070E5D16486B9000A69507 /* DNSSECSupport.c */, 21070E5E16486B9000A69507 /* DNSSECSupport.h */, - FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */, - FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */, DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */, 4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */, - 2E35528F0C3A95C100CA1CB7 /* helper-error.h */, 2E0406CA0C31E9AD00F13B59 /* helper-main.c */, 2EDC5E720C39EA640092701B /* helper-server.h */, 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */, @@ -955,9 +974,8 @@ FF85880B0BD599F40080D89F /* mDNSResponder.sb */, 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */, 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */, - 8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */, - BD64FE9A1C40762F0040EAB3 /* Metrics.h */, - BD64FE9B1C40762F0040EAB3 /* Metrics.m */, + BDA3F0871C48DB6D0054FB4B /* Metrics.h */, + BDA3F0881C48DB6D0054FB4B /* Metrics.m */, 2124FA321471E9DE0021D7BB /* nsec.c */, 2124FA2B1471E98C0021D7BB /* nsec.h */, 2127A47515C3C7B900A857FC /* nsec3.c */, @@ -971,6 +989,7 @@ 216D9ACD1720C9F5008066E1 /* uDNSPathEvalulation.c */, F525E72804AA167501F1CF4D /* uds_daemon.c */, 4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */, + 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */, 848DA5C6165477E000D2E8B4 /* xpc_services.c */, 848DA5C9165477EB00D2E8B4 /* xpc_services.h */, ); @@ -983,19 +1002,18 @@ FF2609FA07B4433800CE10E5 /* Cocoa.framework */, 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */, 4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */, - FFFB0DB407B43D2700B88D48 /* Foundation.framework */, - BD2806071C40775600455151 /* Foundation.framework */, + BDA3F0891C48DB910054FB4B /* Foundation.framework */, 00CA213D02786FC30CCA2C71 /* IOKit.framework */, DB2CC4680662DFF500335AB3 /* JavaVM.framework */, 2E0406140C3197CB00F13B59 /* libbsm.dylib */, 8415A6561897109000BDBA26 /* libdns_services.dylib */, 2E8165F60C59835F00485EB2 /* libipsec.dylib */, 219D5541149ED645004464AE /* libxml2.dylib */, + FF3C72A91CE3E62200CDF81E /* libicucore.dylib */, FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */, 7F869685066EE02400D2A2DC /* Security.framework */, 65713D46025A293200000109 /* SystemConfiguration.framework */, 21F432971134AA6800581B69 /* WebFilterDNS.framework */, - BD64FE9E1C4076B40040EAB3 /* WirelessDiagnostics.framework */, ); name = "External Frameworks and Libraries"; sourceTree = "<group>"; @@ -1019,6 +1037,7 @@ FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */, D284BE730ADD80740027CCDF /* mDNSResponder */, 2E0405F00C31955500F13B59 /* mDNSResponderHelper */, + 37DDE92D1BA383610092AC61 /* unittests */, ); name = Products; sourceTree = "<group>"; @@ -1032,15 +1051,22 @@ name = "Bonjour Events Plugin"; sourceTree = "<group>"; }; - 6575FBFE022EAFA800000109 /* MIG files */ = { + 37DDE9241BA382280092AC61 /* Unit Tests */ = { isa = PBXGroup; children = ( - 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */, - 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */, - 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */, - 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */, - ); - name = "MIG files"; + 37AF802A1BF699AF00D657F6 /* DomainNameTest.c */, + 37AF802B1BF699AF00D657F6 /* DomainNameTest.h */, + 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */, + 371D0FBE1BF666EB00E5DB26 /* ResourceRecordTest.h */, + 373202111BAB63E8007DE806 /* DNSMessageTest.h */, + 3732020F1BAB4349007DE806 /* DNSMessageTest.c */, + 37DDE9351BA386E70092AC61 /* main.c */, + 37DDE9271BA3825C0092AC61 /* unittest.c */, + 37DDE9281BA382670092AC61 /* unittest.h */, + 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */, + 371D0FBB1BF545FA00E5DB26 /* InterfaceTest.h */, + ); + name = "Unit Tests"; sourceTree = "<group>"; }; 6575FC1F022EB78C00000109 /* Command-Line Clients */ = { @@ -1142,7 +1168,6 @@ files = ( 2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */, 2EDC5E730C39EA640092701B /* helper-server.h in Headers */, - 2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */, 2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */, 2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */, 2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */, @@ -1162,12 +1187,9 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - BD64FE9C1C40762F0040EAB3 /* Metrics.h in Headers */, - D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */, D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */, 2E96A5260C39BE480087C4D2 /* helper.h in Headers */, 2EDC5E750C39EA640092701B /* helper-server.h in Headers */, - 2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */, 2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */, 21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */, 21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */, @@ -1175,9 +1197,13 @@ 2124FA301471E9B50021D7BB /* dnssec.h in Headers */, 218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */, 2127A47915C3C7B900A857FC /* nsec3.h in Headers */, + 222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */, 21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */, 21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */, 848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */, + BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */, + 22448EA71C90A837004F25CC /* coreBLE.h in Headers */, + 22448EA41C90A7CB004F25CC /* BLE.h in Headers */, 848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1200,7 +1226,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */, 2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */, FFD52A9E1AF858DD00CAD3EC /* CryptoAlg.h in Headers */, ); @@ -1352,6 +1377,23 @@ productReference = 2E0405F00C31955500F13B59 /* mDNSResponderHelper */; productType = "com.apple.product-type.tool"; }; + 37DDE92C1BA383610092AC61 /* unittests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 37DDE9311BA383610092AC61 /* Build configuration list for PBXNativeTarget "unittests" */; + buildPhases = ( + 37DDE9291BA383610092AC61 /* Sources */, + 37DDE92A1BA383610092AC61 /* Frameworks */, + 37DDE9341BA384000092AC61 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = unittests; + productName = unittests; + productReference = 37DDE92D1BA383610092AC61 /* unittests */; + productType = "com.apple.product-type.tool"; + }; 72FB545E166D5FB00090B2D9 /* dnsctl */ = { isa = PBXNativeTarget; buildConfigurationList = 72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */; @@ -1572,6 +1614,11 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0700; + TargetAttributes = { + 37DDE92C1BA383610092AC61 = { + CreatedOnToolsVersion = 7.0; + }; + }; }; buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */; compatibilityVersion = "Xcode 3.2"; @@ -1610,6 +1657,7 @@ 84C5B3341665529800C324A8 /* dns_services */, D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */, 4AE471670EAFF81900A6C5AD /* dns_sd.jar */, + 37DDE92C1BA383610092AC61 /* unittests */, ); }; /* End PBXProject section */ @@ -1683,7 +1731,22 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = "/bin/bash -e -x"; - shellScript = "DSTROOT=${DSTROOT}\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"\n\nif [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n DSTROOT=${DSTROOT}\n mkdir -p \"$DSTROOT/usr/local/include\"\n sed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSMacOSX/Private/dns_services.h\" > \"$DSTROOT/usr/local/include/dns_services.h\"\n exit 0\nfi\n\nif [[ \"${PLATFORM_NAME}\" =~ \"simulator\" ]]; then\n ln -s libsystem_dnssd.dylib ${DSTROOT}${INSTALL_PATH}/libsystem_sim_dnssd.dylib\nfi\n"; + shellScript = "DSTROOT=${DSTROOT}\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"\n\nif [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n exit 0\nfi\n\nif [[ \"${PLATFORM_NAME}\" =~ \"simulator\" ]]; then\n ln -s libsystem_dnssd.dylib ${DSTROOT}${INSTALL_PATH}/libsystem_sim_dnssd.dylib\nfi\n"; + }; + 37DDE9341BA384000092AC61 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(TARGET_BUILD_DIR)/$(TARGET_NAME)", + ); + outputPaths = ( + "$(TARGET_BUILD_DIR)/unittest_success", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd \"$TARGET_BUILD_DIR\"\n./\"$TARGET_NAME\"\n# touch unittest_success\nif [ ! -f unittest_success ] ; then exit -1; fi"; }; 4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */ = { isa = PBXShellScriptBuildPhase; @@ -1738,10 +1801,8 @@ files = ( 215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */, 215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */, + 222A3C6A1C1B7777003A6FFD /* DNSServiceDiscovery.c in Sources */, 215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */, - 215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */, - 215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */, - 215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1751,10 +1812,8 @@ files = ( 215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */, 215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */, + 222A3C6B1C1B7778003A6FFD /* DNSServiceDiscovery.c in Sources */, 215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */, - 215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */, - 215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */, - 215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1764,10 +1823,8 @@ files = ( 215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */, 215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */, + 222A3C6C1C1B7779003A6FFD /* DNSServiceDiscovery.c in Sources */, 215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */, - 215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */, - 215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */, - 215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1776,13 +1833,25 @@ buildActionMask = 2147483647; files = ( 2E0405F50C3195F700F13B59 /* helper.c in Sources */, - 2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */, 2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */, 2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */, 4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; + 37DDE9291BA383610092AC61 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */, + 37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */, + 371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */, + 373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */, + 3771F67D1BA387DD0072355E /* main.c in Sources */, + 37DDE9331BA383D30092AC61 /* unittest.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 72FB545B166D5FB00090B2D9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1803,26 +1872,25 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */, - D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */, + 227687F31C90AD580019382D /* coreBLE.m in Sources */, D284BE580ADD80740027CCDF /* mDNS.c in Sources */, D284BE590ADD80740027CCDF /* uDNS.c in Sources */, D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */, D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */, D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */, D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */, + 22448EA31C90A7BE004F25CC /* BLE.c in Sources */, D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */, D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */, D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */, + BDA3F08F1C48DCA50054FB4B /* Metrics.m in Sources */, D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */, D284BE630ADD80740027CCDF /* daemon.c in Sources */, - 2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */, 2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */, 21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */, 21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */, 2124FA331471E9DE0021D7BB /* nsec.c in Sources */, 213BDC6D147319F400000896 /* dnssec.c in Sources */, - BD64FE9D1C40762F0040EAB3 /* Metrics.m in Sources */, 218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */, 21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */, 216D9ACE1720C9F5008066E1 /* uDNSPathEvalulation.c in Sources */, @@ -1831,6 +1899,7 @@ 21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */, 21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */, 848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */, + 8417375C1B967D37000CD5C2 /* dnsctl_server.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1865,7 +1934,6 @@ D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */, D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */, D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */, - 2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */, 2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1895,10 +1963,8 @@ files = ( FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */, FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */, + 222A3C6E1C1B777B003A6FFD /* DNSServiceDiscovery.c in Sources */, FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */, - FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */, - FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */, - FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1908,10 +1974,8 @@ files = ( FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */, FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */, + 222A3C6F1C1B777C003A6FFD /* DNSServiceDiscovery.c in Sources */, FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */, - FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */, - FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */, - FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1921,10 +1985,8 @@ files = ( FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */, FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */, + 222A3C6D1C1B777A003A6FFD /* DNSServiceDiscovery.c in Sources */, FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */, - FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */, - FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */, - FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2070,15 +2132,238 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 03067D740C83A3CB0022BE1F /* Development */ = { + 03067D740C83A3CB0022BE1F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_OPTIMIZATION_LEVEL = s; PRODUCT_NAME = "Build Some"; }; - name = Development; + name = Release; + }; + 0C419F121BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/Debug"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)/Debug"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__APPLE_USE_RFC_3542=1", + "_DNS_SD_LIBDISPATCH=1", + "APPLE_OSX_mDNSResponder=1", + "__MigTypeCheck=1", + "mDNSResponderVersion=${MVERS}", + _LEGACY_NAT_TRAVERSAL_, + "_BUILDING_XCODE_PROJECT_=1", + "DEBUG=1", + "BONJOUR_ON_DEMAND=1", + "USE_LIBIDN=1", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + MVERS = "\"(Engineering Build)\""; + OTHER_CFLAGS = ( + "-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS", + "-fwrapv", + ); + SDKROOT = macosx.internal; + STRIP_INSTALLED_PRODUCT = NO; + STRIP_STYLE = debugging; + SUPPORTED_PLATFORMS = "macosx iphoneos"; + WARNING_CFLAGS = ( + "-W", + "-Wall", + "-Wmissing-prototypes", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + "-Wshadow", + "-Wno-format", + "-Wformat-security", + ); + YACC_GENERATED_FILE_STEM = Standard; + }; + name = Debug; + }; + 0C419F131BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "Build All"; + }; + name = Debug; + }; + 0C419F141BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "Build Some"; + }; + name = Debug; + }; + 0C419F151BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "Build All"; + }; + name = Debug; + }; + 0C419F161BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES; + "APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES; + "APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES; + CODE_SIGN_ENTITLEMENTS = "mDNSResponder-entitlements.plist"; + CODE_SIGN_IDENTITY = "-"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = NO; + HEADER_SEARCH_PATHS = ( + "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders", + ../mDNSShared, + "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders", + "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers", + "${CONFIGURATION_TEMP_DIR}", + "$(SDKROOT)/usr/include/libxml2", + "$(SDKROOT)/usr/local/include/", + ); + INSTALL_PATH = /usr/sbin; + LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\""; + MACOSX_DEPLOYMENT_TARGET = 10.10; + ORDER_FILE = "${SRCROOT}/mDNSResponder.order"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "-weak_framework", + DeviceToDeviceManager, + "-lMobileGestalt", + ); + "OTHER_LDFLAGS[sdk=macosx*][arch=*]" = ( + "-lAWACS", + "-weak_framework", + WebFilterDNS, + "-weak_framework", + DeviceToDeviceManager, + ); + "PLIST_FILE_OUTPUT_FORMAT[sdk=appletvos*]" = binary; + "PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary; + "PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary; + PRODUCT_NAME = mDNSResponder; + PROVISIONING_PROFILE = ""; + }; + name = Debug; + }; + 0C419F171BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES; + "APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES; + "APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES; + CODE_SIGN_ENTITLEMENTS = "helper-entitlements.plist"; + CODE_SIGN_IDENTITY = "-"; + HEADER_SEARCH_PATHS = ( + "${CONFIGURATION_TEMP_DIR}", + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + "$(SDKROOT)/usr/local/include", + ); + INSTALL_PATH = /usr/sbin; + LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\""; + MACOSX_DEPLOYMENT_TARGET = 10.10; + OTHER_LDFLAGS = "-lipsec"; + "PLIST_FILE_OUTPUT_FORMAT[sdk=appletvos*]" = binary; + "PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary; + "PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary; + PRODUCT_NAME = mDNSResponderHelper; + PROVISIONING_PROFILE = ""; + }; + name = Debug; + }; + 0C419F181BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + ../mDNSShared, + "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders", + ); + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "dns-sd"; + }; + name = Debug; }; - 213FB21A12028A7B002B3A08 /* Development */ = { + 0C419F191BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "dnsctl-entitlements.plist"; + CODE_SIGN_IDENTITY = "-"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_STRICT_ALIASING = YES; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/local/bin; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = macosx; + }; + name = Debug; + }; + 0C419F1A1BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders", + "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers", + "${CONFIGURATION_TEMP_DIR}", + /System/Library/Frameworks/System.Framework/PrivateHeaders, + ); + INSTALL_PATH = /usr/sbin; + LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\""; + MACOSX_DEPLOYMENT_TARGET = 10.10; + OTHER_CFLAGS = "-UAPPLE_OSX_mDNSResponder"; + PRODUCT_NAME = dnsextd; + }; + name = Debug; + }; + 0C419F1B1BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "/Library/Application Support/Bonjour"; + MACOSX_DEPLOYMENT_TARGET = 10.6; + OTHER_LDFLAGS = "-Wl,-pie"; + PRODUCT_NAME = ddnswriteconfig; + }; + name = Debug; + }; + 0C419F1C1BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_ENABLE_OBJC_GC = supported; + INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist"; + INSTALL_PATH = /AppleInternal/Library/PreferencePanes; + MACOSX_DEPLOYMENT_TARGET = 10.6; + PRODUCT_NAME = Bonjour; + WRAPPER_EXTENSION = prefPane; + }; + name = Debug; + }; + 0C419F1D1BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -2090,25 +2375,30 @@ PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = plugin; }; - name = Development; + name = Debug; }; - 2141DCF9123FFB5D0086D23E /* Development */ = { + 0C419F1E1BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_OPTIMIZATION_LEVEL = 0; PRODUCT_NAME = SystemLibraries; }; - name = Development; + name = Debug; }; - 2141DD0C123FFC7F0086D23E /* Development */ = { + 0C419F1F1BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_OPTIMIZATION_LEVEL = s; PRODUCT_NAME = SystemLibrariesStatic; }; - name = Development; + name = Debug; + }; + 0C419F201BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = SystemLibrariesDynamic; + }; + name = Debug; }; - 2141DD1E123FFCDB0086D23E /* Development */ = { + 0C419F211BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2122,9 +2412,9 @@ PRODUCT_NAME = dns_sd; "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; }; - name = Development; + name = Debug; }; - 2141DD25123FFD100086D23E /* Development */ = { + 0C419F221BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2136,9 +2426,9 @@ PRODUCT_NAME = dns_sd_debug; "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; }; - name = Development; + name = Debug; }; - 2141DD2B123FFD2C0086D23E /* Development */ = { + 0C419F231BA20DF600A70FF7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; @@ -2152,15 +2442,247 @@ PRODUCT_NAME = dns_sd_profile; "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; }; - name = Development; + name = Debug; }; - 2E0405F20C31955500F13B59 /* Development */ = { + 0C419F241BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; + EXECUTABLE_EXTENSION = dylib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALLHDRS_COPY_PHASE = YES; + INSTALLHDRS_SCRIPT_PHASE = YES; + INSTALL_PATH = /usr/lib/system; + INTERPOSITION_SIM_SUFFIX = ""; + "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim; + LINK_WITH_STANDARD_LIBRARIES = NO; + OTHER_LDFLAGS = ( + "-Wl,-umbrella,System", + "-L/usr/lib/system", + "-ldyld", + "-lcompiler_rt", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread", + "-lsystem_malloc", + "-lsystem_c", + "-lsystem_blocks", + "-ldispatch", + "-llaunch", + "-lsystem_asl", + ); + PRODUCT_NAME = libsystem_dnssd; + }; + name = Debug; + }; + 0C419F251BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; + EXECUTABLE_EXTENSION = dylib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALL_PATH = /usr/lib/system; + INTERPOSITION_SIM_SUFFIX = ""; + "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim; + LINK_WITH_STANDARD_LIBRARIES = NO; + OTHER_LDFLAGS = ( + "-Wl,-umbrella,System", + "-L/usr/lib/system", + "-ldyld", + "-lcompiler_rt", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread", + "-lsystem_malloc", + "-lsystem_c", + "-lsystem_blocks", + "-ldispatch", + "-llaunch", + "-lsystem_asl", + ); + PRODUCT_NAME = libsystem_dnssd_debug; + }; + name = Debug; + }; + 0C419F261BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; + EXECUTABLE_EXTENSION = dylib; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + GENERATE_PROFILING_CODE = YES; + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALL_PATH = /usr/lib/system; + INTERPOSITION_SIM_SUFFIX = ""; + "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim; + LINK_WITH_STANDARD_LIBRARIES = NO; + OTHER_LDFLAGS = ( + "-Wl,-umbrella,System", + "-L/usr/lib/system", + "-ldyld", + "-lcompiler_rt", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform", + "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread", + "-lsystem_malloc", + "-lsystem_c", + "-lsystem_blocks", + "-ldispatch", + "-llaunch", + "-lsystem_asl", + ); + PRODUCT_NAME = libsystem_dnssd_profile; + }; + name = Debug; + }; + 0C419F271BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/lib; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 0C419F281BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + EXECUTABLE_EXTENSION = jnilib; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + HEADER_SEARCH_PATHS = ( + ../mDNSShared, + "${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers", + "${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers", + "${PROJECT_DERIVED_FILE_DIR}", + ); + INSTALL_PATH = /usr/lib/java; + LIBRARY_STYLE = DYNAMIC; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = libjdns_sd; + }; + name = Debug; + }; + 0C419F291BA20DF600A70FF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = dns_sd.jar; + }; + name = Debug; + }; + 213FB21A12028A7B002B3A08 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUNDLE_LOADER = /usr/libexec/UserEventAgent; + CODE_SIGN_IDENTITY = "-"; + INFOPLIST_FILE = "BonjourEvents-Info.plist"; + INSTALL_PATH = /System/Library/UserEventPlugins/; + PRODUCT_NAME = BonjourEvents; + PROVISIONING_PROFILE = ""; + WRAPPER_EXTENSION = plugin; + }; + name = Release; + }; + 2141DCF9123FFB5D0086D23E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = SystemLibraries; + }; + name = Release; + }; + 2141DD0C123FFC7F0086D23E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = SystemLibrariesStatic; + }; + name = Release; + }; + 2141DD1E123FFCDB0086D23E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALLHDRS_COPY_PHASE = YES; + INSTALLHDRS_SCRIPT_PHASE = YES; + INSTALL_PATH = /usr/local/lib/system; + PRODUCT_NAME = dns_sd; + "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; + }; + name = Release; + }; + 2141DD25123FFD100086D23E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALL_PATH = /usr/local/lib/system; + PRODUCT_NAME = dns_sd_debug; + "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; + }; + name = Release; + }; + 2141DD2B123FFD2C0086D23E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "__DARWIN_NON_CANCELABLE=1", + ); + GENERATE_PROFILING_CODE = YES; + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/"; + INSTALL_PATH = /usr/local/lib/system; + PRODUCT_NAME = dns_sd_profile; + "SKIP_INSTALL[sdk=iphonesimulator*]" = YES; + }; + name = Release; + }; + 2E0405F20C31955500F13B59 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES; "APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES; "APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES; - "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "helper-entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "helper-entitlements.plist"; CODE_SIGN_IDENTITY = "-"; HEADER_SEARCH_PATHS = ( "${CONFIGURATION_TEMP_DIR}", @@ -2177,17 +2699,81 @@ PRODUCT_NAME = mDNSResponderHelper; PROVISIONING_PROFILE = ""; }; - name = Development; + name = Release; }; - 4AE471680EAFF81900A6C5AD /* Development */ = { + 37AF80271BF6997A00D657F6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_OPTIMIZATION_LEVEL = 0; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; PRODUCT_NAME = dns_sd.jar; }; + name = Release; + }; + 37AF80281BF6997A00D657F6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + PRODUCT_NAME = unittests; + }; + name = Release; + }; + 37AF80291BF6997A00D657F6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = unittests; + }; + name = Debug; + }; + 37DDE9321BA383610092AC61 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_CONSTANT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = NO; + CLANG_WARN_ENUM_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_INT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = NO; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + STRIP_INSTALLED_PRODUCT = NO; + }; name = Development; }; - 72FB5466166D5FB00090B2D9 /* Development */ = { + 72FB5466166D5FB00090B2D9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -2203,7 +2789,6 @@ CODE_SIGN_IDENTITY = "-"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -2220,9 +2805,9 @@ PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; - name = Development; + name = Release; }; - 84C5B3371665529800C324A8 /* Development */ = { + 84C5B3371665529800C324A8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -2233,7 +2818,6 @@ EXECUTABLE_PREFIX = lib; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -2249,20 +2833,20 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; }; - name = Development; + name = Release; }; - D284BE290ADD78180027CCDF /* Development */ = { + D284BE290ADD78180027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "Build All"; }; - name = Development; + name = Release; }; - D284BE2C0ADD78180027CCDF /* Development */ = { + D284BE2C0ADD78180027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/Release"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)/Release"; COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2273,6 +2857,8 @@ "mDNSResponderVersion=${MVERS}", _LEGACY_NAT_TRAVERSAL_, "_BUILDING_XCODE_PROJECT_=1", + "BONJOUR_ON_DEMAND=1", + "USE_LIBIDN=1", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = NO; @@ -2290,12 +2876,14 @@ "-Wno-four-char-constants", "-Wno-unknown-pragmas", "-Wshadow", + "-Wno-format", + "-Wformat-security", ); YACC_GENERATED_FILE_STEM = Standard; }; - name = Development; + name = Release; }; - D284BE6E0ADD80740027CCDF /* Development */ = { + D284BE6E0ADD80740027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES; @@ -2340,11 +2928,10 @@ "PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary; PRODUCT_NAME = mDNSResponder; PROVISIONING_PROFILE = ""; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; }; - name = Development; + name = Release; }; - D284BEAE0ADD80920027CCDF /* Development */ = { + D284BEAE0ADD80920027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { HEADER_SEARCH_PATHS = ( @@ -2354,9 +2941,9 @@ INSTALL_PATH = /usr/bin; PRODUCT_NAME = "dns-sd"; }; - name = Development; + name = Release; }; - D284BEBC0ADD809A0027CCDF /* Development */ = { + D284BEBC0ADD809A0027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_COMPATIBILITY_VERSION = 1; @@ -2372,14 +2959,11 @@ INSTALL_PATH = /usr/lib/java; LIBRARY_STYLE = DYNAMIC; MACH_O_TYPE = mh_dylib; - OTHER_CFLAGS = ""; - OTHER_LIBTOOL_FLAGS = ""; PRODUCT_NAME = libjdns_sd; - SECTORDER_FLAGS = ""; }; - name = Development; + name = Release; }; - D284BED70ADD80A20027CCDF /* Development */ = { + D284BED70ADD80A20027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { HEADER_SEARCH_PATHS = ( @@ -2394,9 +2978,9 @@ OTHER_CFLAGS = "-UAPPLE_OSX_mDNSResponder"; PRODUCT_NAME = dnsextd; }; - name = Development; + name = Release; }; - D284BEE60ADD80A70027CCDF /* Development */ = { + D284BEE60ADD80A70027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { INSTALL_PATH = "/Library/Application Support/Bonjour"; @@ -2404,23 +2988,21 @@ OTHER_LDFLAGS = "-Wl,-pie"; PRODUCT_NAME = ddnswriteconfig; }; - name = Development; + name = Release; }; - D284BF090ADD80B00027CCDF /* Development */ = { + D284BF090ADD80B00027CCDF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_ENABLE_OBJC_GC = supported; - GCC_SYMBOLS_PRIVATE_EXTERN = NO; INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist"; INSTALL_PATH = /AppleInternal/Library/PreferencePanes; MACOSX_DEPLOYMENT_TARGET = 10.6; - OTHER_LDFLAGS = "-twolevel_namespace"; PRODUCT_NAME = Bonjour; WRAPPER_EXTENSION = prefPane; }; - name = Development; + name = Release; }; - FFA572380AF18F1C0055A0F1 /* Development */ = { + FFA572380AF18F1C0055A0F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; @@ -2451,9 +3033,9 @@ ); PRODUCT_NAME = libsystem_dnssd_debug; }; - name = Development; + name = Release; }; - FFA572440AF18F450055A0F1 /* Development */ = { + FFA572440AF18F450055A0F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; @@ -2486,23 +3068,23 @@ ); PRODUCT_NAME = libsystem_dnssd_profile; }; - name = Development; + name = Release; }; - FFA5726F0AF191200055A0F1 /* Development */ = { + FFA5726F0AF191200055A0F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = SystemLibrariesDynamic; }; - name = Development; + name = Release; }; - FFB7657F0AEED99D00583A2C /* Development */ = { + FFB7657F0AEED99D00583A2C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "Build All"; }; - name = Development; + name = Release; }; - FFB7658A0AEED9FB00583A2C /* Development */ = { + FFB7658A0AEED9FB00583A2C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)"; @@ -2535,7 +3117,7 @@ ); PRODUCT_NAME = libsystem_dnssd; }; - name = Development; + name = Release; }; /* End XCBuildConfiguration section */ @@ -2543,63 +3125,81 @@ 03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */ = { isa = XCConfigurationList; buildConfigurations = ( - 03067D740C83A3CB0022BE1F /* Development */, + 03067D740C83A3CB0022BE1F /* Release */, + 0C419F141BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */ = { isa = XCConfigurationList; buildConfigurations = ( - 213FB21A12028A7B002B3A08 /* Development */, + 213FB21A12028A7B002B3A08 /* Release */, + 0C419F1D1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2141DCF9123FFB5D0086D23E /* Development */, + 2141DCF9123FFB5D0086D23E /* Release */, + 0C419F1E1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2141DD0C123FFC7F0086D23E /* Development */, + 2141DD0C123FFC7F0086D23E /* Release */, + 0C419F1F1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2141DD1E123FFCDB0086D23E /* Development */, + 2141DD1E123FFCDB0086D23E /* Release */, + 0C419F211BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2141DD25123FFD100086D23E /* Development */, + 2141DD25123FFD100086D23E /* Release */, + 0C419F221BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2141DD2B123FFD2C0086D23E /* Development */, + 2141DD2B123FFD2C0086D23E /* Release */, + 0C419F231BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2E0405F20C31955500F13B59 /* Development */, + 2E0405F20C31955500F13B59 /* Release */, + 0C419F171BA20DF600A70FF7 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 37DDE9311BA383610092AC61 /* Build configuration list for PBXNativeTarget "unittests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 37DDE9321BA383610092AC61 /* Development */, + 37AF80281BF6997A00D657F6 /* Release */, + 37AF80291BF6997A00D657F6 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Development; @@ -2607,130 +3207,146 @@ 4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4AE471680EAFF81900A6C5AD /* Development */, + 0C419F291BA20DF600A70FF7 /* Debug */, + 37AF80271BF6997A00D657F6 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */ = { isa = XCConfigurationList; buildConfigurations = ( - 72FB5466166D5FB00090B2D9 /* Development */, + 72FB5466166D5FB00090B2D9 /* Release */, + 0C419F191BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; 84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */ = { isa = XCConfigurationList; buildConfigurations = ( - 84C5B3371665529800C324A8 /* Development */, + 84C5B3371665529800C324A8 /* Release */, + 0C419F271BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BE290ADD78180027CCDF /* Development */, + D284BE290ADD78180027CCDF /* Release */, + 0C419F131BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BE2C0ADD78180027CCDF /* Development */, + D284BE2C0ADD78180027CCDF /* Release */, + 0C419F121BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BE6E0ADD80740027CCDF /* Development */, + D284BE6E0ADD80740027CCDF /* Release */, + 0C419F161BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BEAE0ADD80920027CCDF /* Development */, + D284BEAE0ADD80920027CCDF /* Release */, + 0C419F181BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BEBC0ADD809A0027CCDF /* Development */, + D284BEBC0ADD809A0027CCDF /* Release */, + 0C419F281BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BED70ADD80A20027CCDF /* Development */, + D284BED70ADD80A20027CCDF /* Release */, + 0C419F1A1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BEE60ADD80A70027CCDF /* Development */, + D284BEE60ADD80A70027CCDF /* Release */, + 0C419F1B1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */ = { isa = XCConfigurationList; buildConfigurations = ( - D284BF090ADD80B00027CCDF /* Development */, + D284BF090ADD80B00027CCDF /* Release */, + 0C419F1C1BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */ = { isa = XCConfigurationList; buildConfigurations = ( - FFA572380AF18F1C0055A0F1 /* Development */, + FFA572380AF18F1C0055A0F1 /* Release */, + 0C419F251BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */ = { isa = XCConfigurationList; buildConfigurations = ( - FFA572440AF18F450055A0F1 /* Development */, + FFA572440AF18F450055A0F1 /* Release */, + 0C419F261BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */ = { isa = XCConfigurationList; buildConfigurations = ( - FFA5726F0AF191200055A0F1 /* Development */, + FFA5726F0AF191200055A0F1 /* Release */, + 0C419F201BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */ = { isa = XCConfigurationList; buildConfigurations = ( - FFB7657F0AEED99D00583A2C /* Development */, + FFB7657F0AEED99D00583A2C /* Release */, + 0C419F151BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */ = { isa = XCConfigurationList; buildConfigurations = ( - FFB7658A0AEED9FB00583A2C /* Development */, + FFB7658A0AEED9FB00583A2C /* Release */, + 0C419F241BA20DF600A70FF7 /* Debug */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Development; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme new file mode 100644 index 00000000..6bc511e5 --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0710" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "FFB7657B0AEED96B00583A2C" + BuildableName = "Build All" + BlueprintName = "Build All" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + </Testables> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Development" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "FFB7657B0AEED96B00583A2C" + BuildableName = "Build All" + BlueprintName = "Build All" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Development" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "FFB7657B0AEED96B00583A2C" + BuildableName = "Build All" + BlueprintName = "Build All" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </MacroExpansion> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Development" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme new file mode 100644 index 00000000..7ba2fe06 --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0710" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "D284BE500ADD80740027CCDF" + BuildableName = "mDNSResponder" + BlueprintName = "mDNSResponder" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + </Testables> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "D284BE500ADD80740027CCDF" + BuildableName = "mDNSResponder" + BlueprintName = "mDNSResponder" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "D284BE500ADD80740027CCDF" + BuildableName = "mDNSResponder" + BlueprintName = "mDNSResponder" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + <CommandLineArguments> + <CommandLineArgument + argument = "-d -NoSandbox -UseDebugSocket" + isEnabled = "YES"> + </CommandLineArgument> + <CommandLineArgument + argument = "-DebugLogging" + isEnabled = "YES"> + </CommandLineArgument> + </CommandLineArguments> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Development" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "D284BE500ADD80740027CCDF" + BuildableName = "mDNSResponder" + BlueprintName = "mDNSResponder" + ReferencedContainer = "container:mDNSResponder.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Development" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig b/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig deleted file mode 100644 index 34ec0d9a..00000000 --- a/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>PayloadIdentifier</key> - <string>com.apple.mDNSResponder</string> - <key>PayloadUUID</key> - <string>6D0962E1-558A-44FB-8FE0-1F4F0BD157F4</string> - <key>PayloadDescription</key> - <string>Turns on mDNSResponder Debug Logging</string> - <key>PayloadDisplayName</key> - <string>mDNSResponder Debug Logging</string> - <key>PayloadOrganization</key> - <string>Apple, Inc</string> - <key>PayloadType</key> - <string>Configuration</string> - <key>PayloadVersion</key> - <integer>2</integer> - - <key>ConsentText</key> - <dict> - <key>en</key> - <string>English consent text</string> - <key>jp</key> - <string>Japanese consent text</string> - <key>default</key> - <string>Default consent text - used if none of the other languages match</string> - </dict> - - <key>PayloadContent</key> - <array> - <dict> - <key>PayloadUUID</key> - <string>6D0962E1-558A-44FB-8FE0-1F4F0BD157F4</string> - <key>PayloadIdentifier</key> - <string>com.apple.defaults.1</string> - <key>PayloadType</key> - <string>com.apple.defaults.managed</string> - <key>PayloadVersion</key> - <integer>1</integer> - <key>PayloadContent</key> - <array> - <dict> - <key>DefaultsDomainName</key> - <string>com.apple.mDNSResponder</string> - <key>DefaultsData</key> - <dict> - <key>EnableLogging</key> - <true/> - </dict> - </dict> - </array> - </dict> - </array> -</dict> -</plist> - diff --git a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c index 1314584d..cc0d0bae 100644 --- a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c +++ b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c @@ -20,7 +20,7 @@ #include <network/private.h> //Gets the DNSPolicy from NW PATH EVALUATOR -mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked) +mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked) { (void) m; q->ServiceID = -1; // initialize the ServiceID to default value of -1 @@ -28,7 +28,7 @@ mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDN // Return for non-unicast DNS queries, invalid pid, if NWPathEvaluation is already done by the client, or NWPathEvaluation not available on this OS if (mDNSOpaque16IsZero(q->TargetQID) || (q->pid < 0) || (q->flags & kDNSServiceFlagsPathEvaluationDone) || !nw_endpoint_create_host) { - *isCellBlocked = mDNSfalse; + *isBlocked = mDNSfalse; return; } @@ -142,10 +142,10 @@ mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDN } } - if (isUUIDSet && TARGET_OS_IPHONE && nw_path_get_status(path) == nw_path_status_unsatisfied && nw_path_get_reason(path) == nw_path_reason_policy_drop) - *isCellBlocked = mDNStrue; + if (isUUIDSet && (nw_path_get_status(path) == nw_path_status_unsatisfied) && (nw_path_get_reason(path) == nw_path_reason_policy_drop)) + *isBlocked = mDNStrue; else - *isCellBlocked = mDNSfalse; + *isBlocked = mDNSfalse; if (path != NULL) network_release(path); |