Home | History | Annotate | Line # | Download | only in mDNSShared
      1 /*
      2  * Copyright (c) 2003-2024 Apple Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     https://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #if defined(_WIN32)
     18 #include <process.h>
     19 #define usleep(X) Sleep(((X)+999)/1000)
     20 #else
     21 #include <fcntl.h>
     22 #include <errno.h>
     23 #include <sys/ioctl.h>
     24 #include <sys/param.h>
     25 #include <sys/types.h>
     26 #include <sys/time.h>
     27 #include <sys/resource.h>
     28 #endif
     29 
     30 #include <stdlib.h>
     31 #include <stdio.h>
     32 
     33 #include "mDNSEmbeddedAPI.h"
     34 #include "DNSCommon.h"
     35 #include "uDNS.h"
     36 #include "uds_daemon.h"
     37 #include "dns_sd_internal.h"
     38 
     39 // Apple-specific functionality, not required for other platforms
     40 
     41 #ifdef LOCAL_PEEREPID
     42 #include <sys/un.h>         // for LOCAL_PEEREPID
     43 #include <sys/socket.h>     // for getsockopt
     44 #endif //LOCAL_PEEREPID
     45 
     46 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
     47 #include "D2D.h"
     48 #endif
     49 
     50 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
     51 #include "cf_support.h"
     52 #include "mDNSMacOSX.h"
     53 #include <os/feature_private.h>
     54 #endif
     55 
     56 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
     57 #include <mdns/signed_result.h>
     58 #include <mdns/system.h>
     59 #endif
     60 
     61 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
     62 #include "QuerierSupport.h"
     63 #endif
     64 
     65 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
     66 #include "dnssd_server.h"
     67 #endif
     68 
     69 #if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
     70 #include "discover_resolver.h"
     71 #endif
     72 
     73 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
     74 #include "resolved_cache.h"
     75 #endif
     76 
     77 #if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
     78 #include "dns_sd_internal.h"
     79 #endif
     80 
     81 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
     82 #include "cf_support.h"
     83 #include "misc_utilities.h"
     84 #include "system_utilities.h"
     85 #endif
     86 
     87 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
     88 #include <mdns/powerlog.h>
     89 #endif
     90 
     91 #include "mdns_strict.h"
     92 
     93 // User IDs 0-500 are system-wide processes, not actual users in the usual sense
     94 // User IDs for real user accounts start at 501 and count up from there
     95 #define SystemUID(X) ((X) <= 500)
     96 
     97 // ***************************************************************************
     98 // MARK: - Globals
     99 
    100 // globals
    101 mDNSexport mDNS mDNSStorage;
    102 mDNSexport const char ProgramName[] = "mDNSResponder";
    103 
    104 #if defined(USE_TCP_LOOPBACK)
    105 static char* boundPath = NULL;
    106 #else
    107 static char* boundPath = MDNS_UDS_SERVERPATH;
    108 #endif
    109 #if DEBUG
    110 #define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder"
    111 #endif
    112 static dnssd_sock_t listenfd = dnssd_InvalidSocket;
    113 static request_state *all_requests = NULL;
    114 mDNSlocal void set_peer_pid(request_state *request);
    115 mDNSlocal mDNSu32 request_state_get_duration(const request_state *request);
    116 mDNSlocal mDNSBool requestShouldLogName(request_state *request);
    117 mDNSlocal mDNSBool requestShouldLogFullRequestInfo(request_state *request);
    118 mDNSlocal void LogMcastClientInfo(request_state *req);
    119 mDNSlocal void GetMcastClients(request_state *req);
    120 mDNSlocal mStatus update_record(AuthRecord *ar, mDNSu16 rdlen, const mDNSu8 *rdata, mDNSu32 ttl,
    121     const mDNSBool *external_advertise, mDNSu32 request_id);
    122 static mDNSu32 mcount;     // tracks the current active mcast operations for McastLogging
    123 static mDNSu32 i_mcount;   // sets mcount when McastLogging is enabled(PROF signal is sent)
    124 static mDNSu32 n_mrecords; // tracks the current active mcast records for McastLogging
    125 static mDNSu32 n_mquests;  // tracks the current active mcast questions for McastLogging
    126 
    127 
    128 // Note asymmetry here between registration and browsing.
    129 // For service registrations we only automatically register in domains that explicitly appear in local configuration data
    130 // (so AutoRegistrationDomains could equally well be called SCPrefRegDomains)
    131 // For service browsing we also learn automatic browsing domains from the network, so for that case we have:
    132 // 1. SCPrefBrowseDomains (local configuration data)
    133 // 2. LocalDomainEnumRecords (locally-generated local-only PTR records -- equivalent to slElem->AuthRecs in uDNS.c)
    134 // 3. AutoBrowseDomains, which is populated by tracking add/rmv events in AutomaticBrowseDomainChange, the callback function for our mDNS_GetDomains call.
    135 // By creating and removing our own LocalDomainEnumRecords, we trigger AutomaticBrowseDomainChange callbacks just like domains learned from the network would.
    136 
    137 mDNSexport DNameListElem *AutoRegistrationDomains;  // Domains where we automatically register for empty-string registrations
    138 
    139 static DNameListElem *SCPrefBrowseDomains;          // List of automatic browsing domains read from SCPreferences for "empty string" browsing
    140 static ARListElem    *LocalDomainEnumRecords;       // List of locally-generated PTR records to augment those we learn from the network
    141 mDNSexport DNameListElem *AutoBrowseDomains;        // List created from those local-only PTR records plus records we get from the network
    142 
    143 #define MSG_PAD_BYTES 5     // pad message buffer (read from client) with n zero'd bytes to guarantee
    144                             // n get_string() calls w/o buffer overrun
    145 // initialization, setup/teardown functions
    146 
    147 // If a platform specifies its own PID file name, we use that
    148 #ifndef NO_PID_FILE
    149     #ifndef PID_FILE
    150     #define PID_FILE "/var/run/mDNSResponder.pid"
    151     #endif
    152 #endif
    153 
    154 #ifndef NORETURN_ATTRIBUTE
    155 #if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))
    156 #define NORETURN_ATTRIBUTE __attribute__((noreturn))
    157 #else
    158 #define NORETURN_ATTRIBUTE
    159 #endif
    160 #endif
    161 
    162 //======================================================================================================================
    163 // MARK: - Log macro for request state logging.
    164 
    165 #define UDS_LOG_CLIENT_REQUEST_WITH_DURATION(CATEGORY, LEVEL, REQUEST, LOG_DURATION, FORMAT, ...)   \
    166     do                                                                                              \
    167     {                                                                                               \
    168         if (LOG_DURATION)                                                                           \
    169         {                                                                                           \
    170             LogRedact(CATEGORY, LEVEL, FORMAT ", duration: " PUB_TIME_DUR,                          \
    171                 ##__VA_ARGS__, request_state_get_duration(REQUEST));                                \
    172         }                                                                                           \
    173         else                                                                                        \
    174         {                                                                                           \
    175             LogRedact(CATEGORY, LEVEL, FORMAT, ##__VA_ARGS__);                                      \
    176         }                                                                                           \
    177     }                                                                                               \
    178     while(0)
    179 
    180 #define UDS_LOG_CLIENT_REQUEST_WITH_NAME_HASH_DURATION(CATEGORY, LEVEL, NAME_FOR_NAME_HASH, REQUEST,    \
    181             LOG_DURATION, FORMAT, ...)                                                                  \
    182     do                                                                                                  \
    183     {                                                                                                   \
    184         if ((void *)(NAME_FOR_NAME_HASH) != NULL)                                                       \
    185         {                                                                                               \
    186             UDS_LOG_CLIENT_REQUEST_WITH_DURATION(CATEGORY, LEVEL, (REQUEST), LOG_DURATION,              \
    187                 FORMAT "name hash: %x", ##__VA_ARGS__, mDNS_DomainNameFNV1aHash(NAME_FOR_NAME_HASH));   \
    188         }                                                                                               \
    189         else                                                                                            \
    190         {                                                                                               \
    191             UDS_LOG_CLIENT_REQUEST_WITH_DURATION(CATEGORY, LEVEL, (REQUEST), LOG_DURATION,              \
    192                 FORMAT, ##__VA_ARGS__);                                                                 \
    193         }                                                                                               \
    194     }                                                                                                   \
    195     while(0)
    196 
    197 #define UDS_LOG_CLIENT_REQUEST(CATEGORY, LEVEL, OPERATION_STR, NAME_FOR_NAME_HASH, REQUEST, LOG_DURATION,   \
    198             FORMAT, ...)                                                                                    \
    199     do                                                                                                      \
    200     {                                                                                                       \
    201         if (requestShouldLogFullRequestInfo(REQUEST))                                                       \
    202         {                                                                                                   \
    203             UDS_LOG_CLIENT_REQUEST_WITH_NAME_HASH_DURATION(                                                 \
    204                 CATEGORY, LEVEL, (NAME_FOR_NAME_HASH), (REQUEST), (LOG_DURATION),                           \
    205                 "[R%u] " OPERATION_STR " -- "                                                               \
    206                 FORMAT ", flags: 0x%X, interface index: %d, client pid: %d (" PUB_S "), ",                  \
    207                 (REQUEST)->request_id, ##__VA_ARGS__, (REQUEST)->flags, (REQUEST)->interfaceIndex,          \
    208                 (REQUEST)->process_id, (REQUEST)->pid_name);                                                \
    209         }                                                                                                   \
    210         else                                                                                                \
    211         {                                                                                                   \
    212             UDS_LOG_CLIENT_REQUEST_WITH_NAME_HASH_DURATION(                                                 \
    213                 CATEGORY, LEVEL, (NAME_FOR_NAME_HASH), (REQUEST), (LOG_DURATION),                           \
    214                 "[R%u] " OPERATION_STR " -- ", (REQUEST)->request_id);                                      \
    215         }                                                                                                   \
    216     }                                                                                                       \
    217     while(0)
    218 
    219 #define UDS_LOG_CLIENT_REQUEST_WITH_DNSSEC_INFO(CATEGORY, LEVEL, OPERATION_STR, NAME_FOR_NAME_HASH, REQUEST,    \
    220             LOG_DURATION, DNSSEC_ENABLED, FORMAT, ...)                                                          \
    221     do                                                                                                          \
    222     {                                                                                                           \
    223         if (DNSSEC_ENABLED)                                                                                     \
    224         {                                                                                                       \
    225             UDS_LOG_CLIENT_REQUEST(CATEGORY, LEVEL, OPERATION_STR, NAME_FOR_NAME_HASH, REQUEST, LOG_DURATION,   \
    226                 FORMAT ", DNSSEC enabled", ##__VA_ARGS__);                                                      \
    227         }                                                                                                       \
    228         else                                                                                                    \
    229         {                                                                                                       \
    230             UDS_LOG_CLIENT_REQUEST(CATEGORY, LEVEL, OPERATION_STR, NAME_FOR_NAME_HASH, REQUEST, LOG_DURATION,   \
    231                 FORMAT, ##__VA_ARGS__);                                                                         \
    232         }                                                                                                       \
    233     }                                                                                                           \
    234     while (mDNSfalse)
    235 
    236 //======================================================================================================================
    237 // MARK: - Log macro for query record result event logging.
    238 
    239 #define UDS_LOG_RDATA_WITH_RID_QID(CATEGORY, LEVEL, RID, QID, RR_PTR, FORMAT, ...)                                  \
    240     do                                                                                                              \
    241     {                                                                                                               \
    242         if ((QID) != 0)                                                                                             \
    243         {                                                                                                           \
    244             MDNS_CORE_LOG_RDATA(CATEGORY, LEVEL, RR_PTR, "[R%u->Q%u] " FORMAT ", ", (RID), (QID), ##__VA_ARGS__);   \
    245         }                                                                                                           \
    246         else                                                                                                        \
    247         {                                                                                                           \
    248             MDNS_CORE_LOG_RDATA(CATEGORY, LEVEL, RR_PTR, "[R%u->mDNSQ] " FORMAT ", ", (RID), ##__VA_ARGS__);        \
    249         }                                                                                                           \
    250     }                                                                                                               \
    251     while(0)
    252 
    253 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
    254     #define UDS_LOG_RDATA_WITH_RID_QID_DNSSEC(CATEGORY, LEVEL, RID, QID, RR_PTR, FORMAT, ...)               \
    255         do                                                                                                  \
    256         {                                                                                                   \
    257             const dnssec_result_t _dnssec_result = resource_record_get_validation_result(RR_PTR);           \
    258             if (_dnssec_result == dnssec_indeterminate)                                                     \
    259             {                                                                                               \
    260                 UDS_LOG_RDATA_WITH_RID_QID(CATEGORY, LEVEL, (RID), (QID), RR_PTR, FORMAT, ##__VA_ARGS__);   \
    261             }                                                                                               \
    262             else                                                                                            \
    263             {                                                                                               \
    264                 UDS_LOG_RDATA_WITH_RID_QID(CATEGORY, LEVEL, (RID), (QID), RR_PTR,                           \
    265                     FORMAT ", dnssec: " PUB_DNSSEC_RESULT, ##__VA_ARGS__, _dnssec_result);                  \
    266             }                                                                                               \
    267         }                                                                                                   \
    268         while(0)
    269 #else
    270     #define UDS_LOG_RDATA_WITH_RID_QID_DNSSEC UDS_LOG_RDATA_WITH_RID_QID
    271 #endif
    272 
    273 #define UDS_LOG_ANSWER_EVENT_WITH_FORMAT(CATEGORY, LEVEL, RID, QID, RR_PTR, EXPIRED, FORMAT, ...)       \
    274     UDS_LOG_RDATA_WITH_RID_QID_DNSSEC(CATEGORY, LEVEL, RID, QID, RR_PTR, EXPIRED, FORMAT, ##__VA_ARGS__)
    275 
    276 #define UDS_LOG_ANSWER_EVENT(CATEGORY, LEVEL, REQUEST_PTR, Q_PTR, RR_PTR, EXPIRED, REQUEST_DESP, QC_RESULT)         \
    277     do {                                                                                                            \
    278         const mDNSu32 __ifIndex = mDNSPlatformInterfaceIndexfromInterfaceID(m, (RR_PTR)->InterfaceID, mDNSfalse);   \
    279         const mDNSu32 __nameHash = mDNS_DomainNameFNV1aHash(&question->qname);                                      \
    280         if (requestShouldLogName(REQUEST_PTR))                                                                      \
    281         {                                                                                                           \
    282             UDS_LOG_ANSWER_EVENT_WITH_FORMAT(CATEGORY, LEVEL,                                                       \
    283                 (REQUEST_PTR)->request_id, mDNSVal16((Q_PTR)->TargetQID), RR_PTR,                                   \
    284                 REQUEST_DESP " -- event: " PUB_ADD_RMV ", expired: " PUB_BOOL ", ifindex: %d, "                     \
    285                 "name: " PRI_DM_NAME " (%x)", ADD_RMV_U_PARAM(QC_RESULT), BOOL_PARAM(EXPIRED), __ifIndex,           \
    286                 DM_NAME_PARAM(&(Q_PTR)->qname), __nameHash);                                                        \
    287         }                                                                                                           \
    288         else                                                                                                        \
    289         {                                                                                                           \
    290             UDS_LOG_ANSWER_EVENT_WITH_FORMAT(CATEGORY, LEVEL,                                                       \
    291                 (REQUEST_PTR)->request_id, mDNSVal16((Q_PTR)->TargetQID), RR_PTR,                                   \
    292                 REQUEST_DESP " -- event: " PUB_ADD_RMV ", expired: " PUB_BOOL ", ifindex: %d, name hash: %x",       \
    293                 ADD_RMV_U_PARAM(QC_RESULT), BOOL_PARAM(EXPIRED), __ifIndex, __nameHash);                            \
    294         }                                                                                                           \
    295     } while (0)
    296 
    297 // ***************************************************************************
    298 // MARK: - General Utility Functions
    299 
    300 #define uds_log_error(FMT, ...) LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, FMT, __VA_ARGS__)
    301 
    302 mDNSlocal mDNSu32 GetNewRequestID(void)
    303 {
    304 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
    305     return dnssd_server_get_new_request_id();
    306 #else
    307     static mDNSu32 s_last_id = 0;
    308     return ++s_last_id;
    309 #endif
    310 }
    311 
    312 NORETURN_ATTRIBUTE
    313 mDNSlocal void FatalError(char *errmsg)
    314 {
    315     LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
    316     abort();
    317 }
    318 
    319 mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l)
    320 {
    321     mDNSu32 ret;
    322     uint8_t *data = (uint8_t *)&ret;
    323     put_uint32(l, &data);
    324     return ret;
    325 }
    326 
    327 // hack to search-replace perror's to LogMsg's
    328 mDNSlocal void my_perror(char *errmsg)
    329 {
    330     LogMsg("%s: %d (%s)", errmsg, dnssd_errno, dnssd_strerror(dnssd_errno));
    331 }
    332 
    333 // Throttled version of my_perror: Logs once every 250 msgs
    334 mDNSlocal void my_throttled_perror(char *err_msg)
    335 {
    336     static int uds_throttle_count = 0;
    337     if ((uds_throttle_count++ % 250) == 0)
    338         my_perror(err_msg);
    339 }
    340 
    341 // LogMcastQuestion/LogMcastQ should be called after the DNSQuestion struct is initialized(especially for q->TargetQID)
    342 // Hence all calls are made after mDNS_StartQuery()/mDNS_StopQuery()/mDNS_StopBrowse() is called.
    343 mDNSlocal void LogMcastQuestion(const DNSQuestion *const q, request_state *req, q_state status)
    344 {
    345     if (mDNSOpaque16IsZero(q->TargetQID)) // Check for Mcast Query
    346     {
    347         mDNSBool mflag = mDNSfalse;
    348         if (status == q_start)
    349         {
    350             if (++mcount == 1)
    351                 mflag = mDNStrue;
    352         }
    353         else
    354         {
    355             mcount--;
    356         }
    357         LogMcast("%s: %##s  (%s) (%s)  Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype),
    358                  q->InterfaceID == mDNSInterface_LocalOnly ? "lo" :
    359                  q->InterfaceID == mDNSInterface_P2P ? "p2p" :
    360                  q->InterfaceID == mDNSInterface_BLE ? "BLE" :
    361                  q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(&mDNSStorage, q->InterfaceID),
    362                  req->process_id, req->pid_name);
    363         LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
    364     }
    365     return;
    366 }
    367 
    368 // LogMcastService/LogMcastS should be called after the AuthRecord struct is initialized
    369 // Hence all calls are made after mDNS_Register()/ just before mDNS_Deregister()
    370 mDNSlocal void LogMcastService(const AuthRecord *const ar, request_state *req, reg_state status)
    371 {
    372     if (!AuthRecord_uDNS(ar)) // Check for Mcast Service
    373     {
    374         mDNSBool mflag = mDNSfalse;
    375         if (status == reg_start)
    376         {
    377             if (++mcount == 1)
    378                 mflag = mDNStrue;
    379         }
    380         else
    381         {
    382             mcount--;
    383         }
    384         LogMcast("%s: %##s  (%s)  (%s)  Client(%d)[%s]", status ? "+Service" : "-Service", ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype),
    385                  ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" :
    386                  ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" :
    387                  ar->resrec.InterfaceID == mDNSInterface_BLE ? "BLE" :
    388                  ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID),
    389                  req->process_id, req->pid_name);
    390         LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
    391     }
    392     return;
    393 }
    394 
    395 // For complete Mcast State Log, pass mDNStrue to mstatelog in LogMcastStateInfo()
    396 mDNSexport void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog)
    397 {
    398     mDNS *const m = &mDNSStorage;
    399     if (!mstatelog)
    400     {
    401         if (!all_requests)
    402         {
    403             LogMcastNoIdent("<None>");
    404         }
    405         else
    406         {
    407             request_state *req, *r;
    408             for (req = all_requests; req; req=req->next)
    409             {
    410                 if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
    411                 {
    412                     for (r = all_requests; r && r != req; r=r->next)
    413                         if (r == req->primary)
    414                             goto foundpar;
    415                 }
    416                 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
    417                 GetMcastClients(req);
    418     foundpar:;
    419             }
    420             LogMcastNoIdent("--- MCAST RECORDS COUNT[%d] MCAST QUESTIONS COUNT[%d] ---", n_mrecords, n_mquests);
    421             n_mrecords = n_mquests = 0; // Reset the values
    422         }
    423     }
    424     else
    425     {
    426         static mDNSs32 i_mpktnum;
    427         i_mcount = 0;
    428         if (start)
    429             mcount = 0;
    430         // mcount is initialized to 0 when the PROF signal is sent since mcount could have
    431         // wrong value if MulticastLogging is disabled and then re-enabled
    432         LogMcastNoIdent("--- START MCAST STATE LOG ---");
    433         if (!all_requests)
    434         {
    435             mcount = 0;
    436             LogMcastNoIdent("<None>");
    437         }
    438         else
    439         {
    440             request_state *req, *r;
    441             for (req = all_requests; req; req=req->next)
    442             {
    443                 if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
    444                 {
    445                     for (r = all_requests; r && r != req; r=r->next)
    446                         if (r == req->primary)
    447                             goto foundparent;
    448                     LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req->sd);
    449                 }
    450                 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
    451                 LogMcastClientInfo(req);
    452     foundparent:;
    453             }
    454             if(!mcount) // To initially set mcount
    455                 mcount = i_mcount;
    456         }
    457         if (mcount == 0)
    458         {
    459             i_mpktnum = m->MPktNum;
    460             LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount, i_mpktnum);
    461         }
    462         if (mflag)
    463             LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum));
    464         LogMcastNoIdent("--- END MCAST STATE LOG ---");
    465     }
    466 }
    467 
    468 mDNSlocal void abort_request(request_state *req)
    469 {
    470     if (req->terminate == (req_termination_fn) ~0)
    471     {
    472         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
    473                   "[R%d] abort_request: ERROR: Attempt to abort operation %p with req->terminate %p", req->request_id, req, req->terminate);
    474         return;
    475     }
    476 
    477     // First stop whatever mDNSCore operation we were doing
    478     // If this is actually a shared connection operation, then its req->terminate function will scan
    479     // the all_requests list and terminate any subbordinate operations sharing this file descriptor
    480     if (req->terminate) req->terminate(req);
    481 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
    482     if (req->custom_service_id != 0)
    483     {
    484         Querier_DeregisterCustomDNSService(req->custom_service_id);
    485         req->custom_service_id = 0;
    486     }
    487 #endif
    488 
    489     if (!dnssd_SocketValid(req->sd))
    490     {
    491         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
    492                   "[R%d] abort_request: ERROR: Attempt to abort operation %p with invalid fd %d", req->request_id, req, req->sd);
    493         return;
    494     }
    495 
    496     // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
    497     if (!req->primary)
    498     {
    499         if (req->errsd != req->sd)
    500         {
    501             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
    502                       "[R%d] Removing FD %d and closing errsd %d", req->request_id, req->sd, req->errsd);
    503         }
    504         else
    505         {
    506             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
    507                       "[R%d] Removing FD %d", req->request_id, req->sd);
    508         }
    509         udsSupportRemoveFDFromEventLoop(req->sd, req->platform_data);       // Note: This also closes file descriptor req->sd for us
    510         if (req->errsd != req->sd) { dnssd_close(req->errsd); req->errsd = req->sd; }
    511 
    512         while (req->replies)    // free pending replies
    513         {
    514             reply_state *ptr = req->replies;
    515             req->replies = req->replies->next;
    516             freeL("reply_state (abort)", ptr);
    517         }
    518     }
    519 
    520     // Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
    521 #if MDNS_MALLOC_DEBUGGING
    522     // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MDNS_MALLOC_DEBUGGING uses
    523     // for detecting when the memory for an object is inadvertently freed while the object is still on some list
    524 #ifdef WIN32
    525 #error This will not work on Windows, look at IsValidSocket in mDNSShared/CommonServices.h to see why
    526 #endif
    527     req->sd = req->errsd = -2;
    528 #else
    529     req->sd = req->errsd = dnssd_InvalidSocket;
    530 #endif
    531     // We also set req->terminate to a bogus value so we know if abort_request() gets called again for this request
    532     req->terminate = (req_termination_fn) ~0;
    533 }
    534 
    535 #if DEBUG
    536 mDNSexport void SetDebugBoundPath(void)
    537 {
    538 #if !defined(USE_TCP_LOOPBACK)
    539     boundPath = MDNS_UDS_SERVERPATH_DEBUG;
    540 #endif
    541 }
    542 
    543 mDNSexport int IsDebugSocketInUse(void)
    544 {
    545 #if !defined(USE_TCP_LOOPBACK)
    546     return !strcmp(boundPath, MDNS_UDS_SERVERPATH_DEBUG);
    547 #else
    548     return mDNSfalse;
    549 #endif
    550 }
    551 #endif
    552 
    553 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
    554 mDNSlocal dispatch_queue_t _get_trust_results_dispatch_queue(void)
    555 {
    556     static dispatch_once_t  once    = 0;
    557     static dispatch_queue_t queue   = NULL;
    558 
    559     dispatch_once(&once, ^{
    560         dispatch_queue_attr_t const attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
    561         queue = dispatch_queue_create("com.apple.mDNSResponder.trust_results-queue", attr);
    562     });
    563     return queue;
    564 }
    565 
    566 mDNSlocal mDNSBool _prepare_trusts_for_request(request_state * const request)
    567 {
    568     if (request->trusts == NULL)
    569     {
    570         request->trusts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &mdns_cfarray_callbacks);
    571         if (!request->trusts)
    572         {
    573             return mDNSfalse;
    574         }
    575     }
    576     return mDNStrue;
    577 }
    578 
    579 #define mdns_trusts_forget_with_invalidation(PTR) \
    580     do                                            \
    581     {                                             \
    582         if (*(PTR))                               \
    583         {                                         \
    584             (void)mdns_cfarray_enumerate(*(PTR),  \
    585             ^ bool (mdns_trust_t trust)           \
    586             {                                     \
    587                 mdns_trust_invalidate(trust);     \
    588                 return true;                      \
    589             });                                   \
    590             mdns_cf_forget((PTR));                \
    591         }                                         \
    592     } while(0)
    593 #endif
    594 
    595 mDNSlocal void resolve_result_finalize(request_resolve *resolve);
    596 #define resolve_result_forget(PTR)              \
    597     do                                          \
    598     {                                           \
    599         if (*(PTR))                             \
    600         {                                       \
    601             resolve_result_finalize(*(PTR));    \
    602             *(PTR) = NULL;                      \
    603         }                                       \
    604     } while(0)
    605 
    606 mDNSlocal void request_state_forget(request_state **const ptr)
    607 {
    608     request_state *req = *ptr;
    609     mdns_require_return(req);
    610 
    611     freeL("request_enumeration/request_state_forget", req->enumeration);
    612     freeL("request_servicereg/request_state_forget", req->servicereg);
    613 
    614     resolve_result_forget(&req->resolve);
    615 
    616     freeL("QueryRecordClientRequest/request_state_forget", req->queryrecord);
    617     freeL("request_browse/request_state_forget", req->browse);
    618     freeL("request_port_mapping/request_state_forget", req->pm);
    619     freeL("GetAddrInfoClientRequest/request_state_forget", req->addrinfo);
    620 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
    621     mdns_forget(&req->peer_token);
    622 #endif
    623 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
    624     mdns_trusts_forget_with_invalidation(&req->trusts);
    625 #endif
    626 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
    627     mdns_forget(&req->signed_obj);
    628 #endif
    629     freeL("request_state/request_state_forget", req);
    630     *ptr = mDNSNULL;
    631 }
    632 
    633 mDNSlocal void AbortUnlinkAndFree(request_state *req)
    634 {
    635     request_state **p = &all_requests;
    636     abort_request(req);
    637     while (*p && *p != req) p=&(*p)->next;
    638     if (*p)
    639     {
    640         *p = req->next;
    641         request_state_forget(&req);
    642     }
    643     else
    644     {
    645         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req);
    646     }
    647 }
    648 
    649 mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, request_state *const request)
    650 {
    651     reply_state *reply;
    652 
    653     if ((unsigned)datalen < sizeof(reply_hdr))
    654     {
    655         LogMsg("ERROR: create_reply - data length less than length of required fields");
    656         return NULL;
    657     }
    658 
    659     reply = (reply_state *) callocL("reply_state", sizeof(reply_state) + datalen - sizeof(reply_hdr));
    660     if (!reply) FatalError("ERROR: calloc");
    661 
    662     reply->next     = mDNSNULL;
    663     reply->totallen = (mDNSu32)datalen + sizeof(ipc_msg_hdr);
    664     reply->nwritten = 0;
    665 
    666     reply->mhdr->version        = VERSION;
    667     reply->mhdr->datalen        = (mDNSu32)datalen;
    668     reply->mhdr->ipc_flags      = 0;
    669     reply->mhdr->op             = op;
    670     reply->mhdr->client_context = request->hdr.client_context;
    671     reply->mhdr->reg_index      = 0;
    672 
    673     return reply;
    674 }
    675 
    676 // Append a reply to the list in a request object
    677 // If our request is sharing a connection, then we append our reply_state onto the primary's list
    678 // If the request does not want asynchronous replies, then the reply is freed instead of being appended to any list.
    679 mDNSlocal void append_reply(request_state *req, reply_state *rep)
    680 {
    681     request_state *r;
    682     reply_state **ptr;
    683 
    684     if (req->no_reply)
    685     {
    686         freeL("reply_state/append_reply", rep);
    687         return;
    688     }
    689 
    690     r = req->primary ? req->primary : req;
    691     ptr = &r->replies;
    692     while (*ptr) ptr = &(*ptr)->next;
    693     *ptr = rep;
    694     rep->next = NULL;
    695 }
    696 
    697 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
    698 mDNSlocal const uint8_t * _get_signed_data_tlvs(request_state *const request, size_t *const out_length)
    699 {
    700     const mDNSu8 *data = NULL;
    701     if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
    702     {
    703         const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
    704         const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
    705         DNSServiceValidationPolicy policy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_POLICY, mDNSNULL);
    706         if (policy == kDNSServiceValidationPolicyRequired)
    707         {
    708             request->sign_result = mDNStrue;
    709             size_t len;
    710             data = get_tlv(start, end, IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA, &len);
    711             if (out_length)
    712             {
    713                 *out_length = len;
    714             }
    715         }
    716     }
    717     return data;
    718 }
    719 
    720 mDNSlocal mStatus get_signed_result_flags_tlvs(request_state *const request)
    721 {
    722     // No data is expected in this case
    723     (void)_get_signed_data_tlvs(request, NULL);
    724     return mStatus_NoError;
    725 }
    726 
    727 mDNSlocal mStatus get_signed_browse_tlvs(request_state *const request)
    728 {
    729     size_t len = 0;
    730     const mDNSu8 * const data = _get_signed_data_tlvs(request, &len);
    731     if (request->sign_result)
    732     {
    733         if (!data)
    734         {
    735             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_browse_tlvs data invalid");
    736             return mStatus_Invalid;
    737         }
    738 
    739         OSStatus err;
    740         mdns_signed_browse_result_t signed_obj = mdns_signed_browse_result_create_from_data(data, len, &err);
    741         if (!signed_obj || err != 0)
    742         {
    743             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_browse_tlvs len %ld data invalid %ld", len,
    744                 (long)err);
    745             return mStatus_Invalid;
    746         }
    747 
    748         request->signed_obj = mdns_signed_result_upcast(signed_obj);
    749     }
    750     return mStatus_NoError;
    751 }
    752 
    753 mDNSlocal mStatus get_signed_resolve_tlvs(request_state *const request)
    754 {
    755     size_t len = 0;
    756     const mDNSu8 * const data = _get_signed_data_tlvs(request, &len);
    757     if (request->sign_result)
    758     {
    759         if (!data)
    760         {
    761             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_resolve_tlvs data invalid");
    762             return mStatus_Invalid;
    763         }
    764 
    765         OSStatus err;
    766         mdns_signed_resolve_result_t signed_obj = mdns_signed_resolve_result_create_from_data(data, len, &err);
    767         if (!signed_obj || err != 0)
    768         {
    769             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_resolve_tlvs len %ld data invalid %ld", len,
    770                 (long)err);
    771             return mStatus_Invalid;
    772         }
    773 
    774         request->signed_obj = mdns_signed_result_upcast(signed_obj);
    775     }
    776     return mStatus_NoError;
    777 }
    778 
    779 mDNSlocal void put_signed_result_tlvs(const uint8_t *data, uint16_t length, ipc_msg_hdr * const hdr,
    780     uint8_t ** const ptr, const uint8_t * const limit)
    781 {
    782     put_tlv(IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA, length, data, ptr, limit);
    783     hdr->ipc_flags |= IPC_FLAGS_TRAILING_TLVS;
    784 }
    785 #endif
    786 
    787 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
    788 mDNSlocal void get_tracker_info_tlvs(request_state *const request)
    789 {
    790     if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
    791     {
    792         const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
    793         const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
    794         uint32_t result = get_tlv_uint32(start, end, IPC_TLV_TYPE_GET_TRACKER_STR, mDNSNULL);
    795         request->addTrackerInfo = (result != 0) ? mDNStrue : mDNSfalse;
    796     }
    797 }
    798 
    799 mDNSlocal void put_tracker_hostname_tlvs(const char * hostname, ipc_msg_hdr * const hdr, uint8_t ** const ptr,
    800     const uint8_t * const limit)
    801 {
    802     put_tlv_string(IPC_TLV_TYPE_SERVICE_ATTR_TRACKER_STR, hostname, ptr, limit, NULL);
    803     hdr->ipc_flags |= IPC_FLAGS_TRAILING_TLVS;
    804 }
    805 #endif
    806 
    807 // Generates a response message giving name, type, domain, plus interface index,
    808 // suitable for a browse result or service registration result.
    809 // On successful completion rep is set to point to a malloc'd reply_state struct
    810 mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const mDNSInterfaceID id,
    811                                       request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
    812 {
    813     domainlabel name;
    814     domainname type, dom;
    815     *rep = NULL;
    816     if (servicename && !DeconstructServiceName(servicename, &name, &type, &dom))
    817         return kDNSServiceErr_Invalid;
    818     else
    819     {
    820         char namestr[MAX_DOMAIN_LABEL+1];
    821         char typestr[MAX_ESCAPED_DOMAIN_NAME];
    822         char domstr [MAX_ESCAPED_DOMAIN_NAME];
    823         size_t len;
    824         uint8_t *data;
    825 
    826         if (servicename)
    827         {
    828             ConvertDomainLabelToCString_unescaped(&name, namestr);
    829             ConvertDomainNameToCString(&type, typestr);
    830             ConvertDomainNameToCString(&dom, domstr);
    831         }
    832         else
    833         {
    834             namestr[0] = 0;
    835             typestr[0] = 0;
    836             domstr[0] = 0;
    837         }
    838 
    839         mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse);
    840 
    841         // Calculate reply data length
    842         len = sizeof(DNSServiceFlags);
    843         len += sizeof(mDNSu32);  // if index
    844         len += sizeof(DNSServiceErrorType);
    845         len += (strlen(namestr) + 1);
    846         len += (strlen(typestr) + 1);
    847         len += (strlen(domstr) + 1);
    848 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
    849         mdns_signed_browse_result_t signed_result = NULL;
    850         const uint8_t *signed_data = NULL;
    851         uint16_t signed_data_length = 0;
    852         if (request->sign_result && servicename)
    853         {
    854             OSStatus error;
    855             signed_result = mdns_signed_browse_result_create(servicename->c, interface_index, &error);
    856             if (!signed_result || error != 0)
    857             {
    858                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "GenerateBrowseReply signed_browse failed %ld",
    859                     (long)error);
    860             }
    861             else
    862             {
    863                 size_t temp_size = 0;
    864                 const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
    865                 if (temp_size <= UINT16_MAX)
    866                 {
    867                     signed_data = temp_data;
    868                     signed_data_length = (uint16_t)temp_size;
    869                     len += get_required_tlv_length(signed_data_length);
    870                 }
    871             }
    872         }
    873 #endif
    874 
    875         // Build reply header
    876         *rep = create_reply(op, len, request);
    877         (*rep)->rhdr->flags = dnssd_htonl(flags);
    878         (*rep)->rhdr->ifi   = dnssd_htonl(interface_index);
    879         (*rep)->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
    880 
    881         // Build reply body
    882         data = (uint8_t *)&(*rep)->rhdr[1];
    883         put_string(namestr, &data);
    884         put_string(typestr, &data);
    885         put_string(domstr, &data);
    886 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
    887         if (signed_data)
    888         {
    889             put_signed_result_tlvs(signed_data, signed_data_length, (*rep)->mhdr, &data, data+len);
    890         }
    891         mdns_forget(&signed_result);
    892 #endif
    893 
    894         return mStatus_NoError;
    895     }
    896 }
    897 
    898 mDNSlocal void GenerateBrowseReply(const domainname *const servicename, const mDNSInterfaceID id,
    899                                               request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
    900 {
    901     char namestr[MAX_DOMAIN_LABEL+1];
    902     char typestr[MAX_ESCAPED_DOMAIN_NAME];
    903     static const char domstr[] = ".";
    904     size_t len;
    905     uint8_t *data;
    906 
    907     *rep = NULL;
    908 
    909     if (servicename)
    910     {
    911         // 1. Put first label in namestr
    912         ConvertDomainLabelToCString_unescaped((const domainlabel *)servicename, namestr);
    913 
    914         // 2. Put second label and "local" into typestr
    915         mDNS_snprintf(typestr, sizeof(typestr), "%#s.local.", SecondLabel(servicename));
    916     }
    917     else
    918     {
    919         namestr[0] = 0;
    920         typestr[0] = 0;
    921     }
    922 
    923     // Calculate reply data length
    924     len = sizeof(DNSServiceFlags);
    925     len += sizeof(mDNSu32);  // if index
    926     len += sizeof(DNSServiceErrorType);
    927     len += (strlen(namestr) + 1);
    928     len += (strlen(typestr) + 1);
    929     len += (strlen(domstr) + 1);
    930 
    931     // Build reply header
    932     *rep = create_reply(op, len, request);
    933     (*rep)->rhdr->flags = dnssd_htonl(flags);
    934     (*rep)->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
    935     (*rep)->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
    936 
    937     // Build reply body
    938     data = (uint8_t *)&(*rep)->rhdr[1];
    939     put_string(namestr, &data);
    940     put_string(typestr, &data);
    941     put_string(domstr, &data);
    942 }
    943 
    944 // get IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP & IPC_TLV_TYPE_SERVICE_ATTR_HOST_KEY_HASH values
    945 // The timestamp is a number of seconds in the past, and is unsigned.
    946 mDNSlocal mDNSBool get_service_attr_tsr_params(const request_state *const request, mDNSu32 *const outTimestamp,
    947     mDNSu32 *const outHostkeyHash)
    948 {
    949     if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS) &&
    950         outTimestamp && outHostkeyHash)
    951     {
    952         mDNSs32 error;
    953         const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
    954         const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
    955         mDNSu32 value = (mDNSu32)get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP, &error);
    956         *outTimestamp = value;
    957         if (error) return mDNSfalse;
    958 
    959         value = (mDNSu32)get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_HOST_KEY_HASH, &error);
    960         *outHostkeyHash = value;
    961         if (error) return mDNSfalse;
    962         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
    963             "get_service_attr_tsr_params timestamp %u hostkeyHash %u", *outTimestamp, *outHostkeyHash);
    964         return mDNStrue;
    965     }
    966     return mDNSfalse;
    967 }
    968 
    969 // Returns a resource record (allocated w/ malloc) containing the data found in an IPC message
    970 // Data must be in the following format: flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional) ttl
    971 // (ttl only extracted/set if ttl argument is non-zero). Returns NULL for a bad-parameter error
    972 mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, int validate_flags)
    973 {
    974     DNSServiceFlags flags  = get_flags(&request->msgptr, request->msgend);
    975     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
    976     char name[MAX_ESCAPED_DOMAIN_NAME];
    977     int str_err = get_string(&request->msgptr, request->msgend, name, sizeof(name));
    978     mDNSu16 type  = get_uint16(&request->msgptr, request->msgend);
    979     mDNSu16 class = get_uint16(&request->msgptr, request->msgend);
    980     mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
    981     const mDNSu8 *const rdata = get_rdata(&request->msgptr, request->msgend, rdlen);
    982     mDNSu32 ttl   = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
    983     size_t rdcapacity;
    984     AuthRecord *rr;
    985     mDNSInterfaceID InterfaceID;
    986     AuthRecType artype;
    987     mDNSu8 recordType;
    988 
    989     request->flags = flags;
    990     request->interfaceIndex = interfaceIndex;
    991 
    992     if (str_err) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL; }
    993     if (!request->msgptr) { LogMsg("Error reading Resource Record from client"); return NULL; }
    994 
    995     if (validate_flags &&
    996         !((flags & kDNSServiceFlagsShared) == kDNSServiceFlagsShared) &&
    997         !((flags & kDNSServiceFlagsUnique) == kDNSServiceFlagsUnique) &&
    998         !((flags & kDNSServiceFlagsKnownUnique) == kDNSServiceFlagsKnownUnique))
    999     {
   1000         LogMsg("ERROR: Bad resource record flags (must be one of either kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique)");
   1001         return NULL;
   1002     }
   1003     InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   1004 
   1005     // The registration is scoped to a specific interface index, but the interface is not currently on our list.
   1006     if ((InterfaceID == mDNSInterface_Any) && (interfaceIndex != kDNSServiceInterfaceIndexAny))
   1007     {
   1008         // On Apple platforms, an interface's mDNSInterfaceID is equal to its index. Using an interface index that isn't
   1009         // currently valid will cause the registration to take place as soon as it becomes valid. On other platforms,
   1010         // mDNSInterfaceID is actually a pointer to a platform-specific interface object, but we don't know what the pointer
   1011         // for the interface index will be ahead of time. For now, just return NULL to indicate an error condition since the
   1012         // interface index is invalid. Otherwise, the registration would be performed on all interfaces.
   1013         return NULL;
   1014     }
   1015     rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
   1016     rr = (AuthRecord *) callocL("AuthRecord/read_rr_from_ipc_msg", sizeof(*rr) - sizeof(RDataBody) + rdcapacity);
   1017     if (!rr) FatalError("ERROR: calloc");
   1018 
   1019     if (InterfaceID == mDNSInterface_LocalOnly)
   1020         artype = AuthRecordLocalOnly;
   1021     else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
   1022         artype = AuthRecordP2P;
   1023     else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
   1024             && (flags & kDNSServiceFlagsIncludeAWDL))
   1025         artype = AuthRecordAnyIncludeAWDLandP2P;
   1026     else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
   1027         artype = AuthRecordAnyIncludeP2P;
   1028     else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL))
   1029         artype = AuthRecordAnyIncludeAWDL;
   1030     else
   1031         artype = AuthRecordAny;
   1032 
   1033     if (flags & kDNSServiceFlagsShared)
   1034         recordType = (mDNSu8) kDNSRecordTypeShared;
   1035     else if (flags & kDNSServiceFlagsKnownUnique)
   1036         recordType = (mDNSu8) kDNSRecordTypeKnownUnique;
   1037     else
   1038         recordType = (mDNSu8) kDNSRecordTypeUnique;
   1039 
   1040     mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, type, 0, recordType, artype, mDNSNULL, mDNSNULL);
   1041 
   1042     if (!MakeDomainNameFromDNSNameString(&rr->namestorage, name))
   1043     {
   1044         LogMsg("ERROR: bad name: %s", name);
   1045         freeL("AuthRecord/read_rr_from_ipc_msg", rr);
   1046         return NULL;
   1047     }
   1048 
   1049     if (flags & kDNSServiceFlagsAllowRemoteQuery) rr->AllowRemoteQuery = mDNStrue;
   1050     rr->resrec.rrclass = class;
   1051     rr->resrec.rdlength = rdlen;
   1052     rr->resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
   1053     if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr->resrec, rdlen))
   1054     {
   1055         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   1056             "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
   1057             request->request_id, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(type));
   1058         freeL("AuthRecord/read_rr_from_ipc_msg", rr);
   1059         return NULL;
   1060     }
   1061     if (GetTTL) rr->resrec.rroriginalttl = ttl;
   1062     rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
   1063     SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
   1064     return rr;
   1065 }
   1066 
   1067 mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
   1068 {
   1069     domainlabel n;
   1070     domainname d, t;
   1071 
   1072     if (!MakeDomainLabelFromLiteralString(&n, name)) return -1;
   1073     if (!MakeDomainNameFromDNSNameString(&t, regtype)) return -1;
   1074     if (!MakeDomainNameFromDNSNameString(&d, domain)) return -1;
   1075     if (!ConstructServiceName(srv, &n, &t, &d)) return -1;
   1076     return 0;
   1077 }
   1078 
   1079 mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, const size_t len)
   1080 {
   1081     const ssize_t n = send(s, ptr, len, 0);
   1082     // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a small write for us
   1083     // (four bytes for a typical error code return, 12 bytes for DNSServiceGetProperty(DaemonVersion)).
   1084     // If it does fail, we don't attempt to handle this failure, but we do log it so we know something is wrong.
   1085     if ((n < 0) || (((size_t)n) < len))
   1086     {
   1087         LogMsg("ERROR: send_all(%d) wrote %ld of %lu errno %d (%s)",
   1088             s, (long)n, (unsigned long)len, dnssd_errno, dnssd_strerror(dnssd_errno));
   1089     }
   1090 }
   1091 
   1092 #if 0
   1093 mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const domainname * const d, const DNameListElem * const doms)
   1094 {
   1095     const DNameListElem   *delem = mDNSNULL;
   1096     int bestDelta   = -1;                           // the delta of the best match, lower is better
   1097     int dLabels     = 0;
   1098     mDNSBool allow       = mDNSfalse;
   1099 
   1100     if (SystemUID(request->uid)) return mDNStrue;
   1101 
   1102     dLabels = CountLabels(d);
   1103     for (delem = doms; delem; delem = delem->next)
   1104     {
   1105         if (delem->uid)
   1106         {
   1107             int delemLabels = CountLabels(&delem->name);
   1108             int delta       = dLabels - delemLabels;
   1109             if ((bestDelta == -1 || delta <= bestDelta) && SameDomainName(&delem->name, SkipLeadingLabels(d, delta)))
   1110             {
   1111                 bestDelta = delta;
   1112                 allow = (allow || (delem->uid == request->uid));
   1113             }
   1114         }
   1115     }
   1116 
   1117     return bestDelta == -1 ? mDNStrue : allow;
   1118 }
   1119 #endif
   1120 
   1121 // ***************************************************************************
   1122 // MARK: - external helpers
   1123 
   1124 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1125 mDNSlocal void external_start_advertising_helper(service_instance *const instance)
   1126 {
   1127     AuthRecord *st = instance->subtypes;
   1128     ExtraResourceRecord *e;
   1129     mDNSu32 i;
   1130     const pid_t requestPID = instance->request->process_id;
   1131 
   1132     const request_servicereg *const servicereg = instance->request->servicereg;
   1133     if (mDNSIPPortIsZero(servicereg->port))
   1134     {
   1135         LogInfo("external_start_advertising_helper: Not registering service with port number zero");
   1136         return;
   1137     }
   1138 
   1139     if (instance->external_advertise) LogMsg("external_start_advertising_helper: external_advertise already set!");
   1140 
   1141     for (i = 0; i < servicereg->num_subtypes; i++)
   1142         external_start_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
   1143 
   1144     external_start_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
   1145     external_start_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
   1146     external_start_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
   1147 
   1148     for (e = instance->srs.Extras; e; e = e->next)
   1149         external_start_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
   1150 
   1151     instance->external_advertise = mDNStrue;
   1152 }
   1153 
   1154 mDNSlocal void external_stop_advertising_helper(service_instance *const instance)
   1155 {
   1156     AuthRecord *st = instance->subtypes;
   1157     ExtraResourceRecord *e;
   1158     mDNSu32 i;
   1159 
   1160     if (!instance->external_advertise) return;
   1161 
   1162     LogInfo("external_stop_advertising_helper: calling external_stop_advertising_service");
   1163 
   1164     if (instance->request)
   1165     {
   1166         const pid_t requestPID = instance->request->process_id;
   1167         for (i = 0; i < instance->request->servicereg->num_subtypes; i++)
   1168         {
   1169             external_stop_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
   1170         }
   1171 
   1172         external_stop_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
   1173         external_stop_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
   1174         external_stop_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
   1175 
   1176         for (e = instance->srs.Extras; e; e = e->next)
   1177         {
   1178             external_stop_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
   1179         }
   1180     }
   1181 
   1182     instance->external_advertise = mDNSfalse;
   1183 }
   1184 #endif  // MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1185 
   1186 // ***************************************************************************
   1187 // MARK: - DNSServiceRegister
   1188 
   1189 mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
   1190 {
   1191     ExtraResourceRecord *extra = (ExtraResourceRecord *)rr->RecordContext;
   1192     (void)m;  // Unused
   1193 
   1194     if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
   1195 
   1196     LogInfo("     FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
   1197 
   1198     if (rr->resrec.rdata != &rr->rdatastorage)
   1199         freeL("Extra RData", rr->resrec.rdata);
   1200     freeL("ExtraResourceRecord/FreeExtraRR", extra);
   1201 }
   1202 
   1203 mDNSlocal void unlink_and_free_service_instance(service_instance *srv)
   1204 {
   1205     ExtraResourceRecord *e = srv->srs.Extras, *tmp;
   1206 
   1207 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1208     external_stop_advertising_helper(srv);
   1209 #endif
   1210 
   1211     // clear pointers from parent struct
   1212     if (srv->request)
   1213     {
   1214         service_instance **p = &srv->request->servicereg->instances;
   1215         while (*p)
   1216         {
   1217             if (*p == srv) { *p = (*p)->next; break; }
   1218             p = &(*p)->next;
   1219         }
   1220     }
   1221 
   1222     while (e)
   1223     {
   1224         e->r.RecordContext = e;
   1225         tmp = e;
   1226         e = e->next;
   1227         FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree);
   1228     }
   1229 
   1230     if (srv->srs.RR_TXT.resrec.rdata != &srv->srs.RR_TXT.rdatastorage)
   1231         freeL("TXT RData", srv->srs.RR_TXT.resrec.rdata);
   1232 
   1233     if (srv->subtypes)
   1234     {
   1235         freeL("ServiceSubTypes", srv->subtypes);
   1236         srv->subtypes = NULL;
   1237     }
   1238     freeL("service_instance", srv);
   1239 }
   1240 
   1241 // Count how many other service records we have locally with the same name, but different rdata.
   1242 // For auto-named services, we can have at most one per machine -- if we allowed two auto-named services of
   1243 // the same type on the same machine, we'd get into an infinite autoimmune-response loop of continuous renaming.
   1244 mDNSexport int CountPeerRegistrations(ServiceRecordSet *const srs)
   1245 {
   1246     int count = 0;
   1247     ResourceRecord *r = &srs->RR_SRV.resrec;
   1248     AuthRecord *rr;
   1249 
   1250     for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
   1251         if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r))
   1252             count++;
   1253 
   1254     verbosedebugf("%d peer registrations for %##s", count, r->name->c);
   1255     return(count);
   1256 }
   1257 
   1258 mDNSexport int CountExistingRegistrations(domainname *srv, mDNSIPPort port)
   1259 {
   1260     int count = 0;
   1261     AuthRecord *rr;
   1262     for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
   1263         if (rr->resrec.rrtype == kDNSType_SRV &&
   1264             mDNSSameIPPort(rr->resrec.rdata->u.srv.port, port) &&
   1265             SameDomainName(rr->resrec.name, srv))
   1266             count++;
   1267     return(count);
   1268 }
   1269 
   1270 mDNSlocal void SendServiceRemovalNotification(ServiceRecordSet *const srs)
   1271 {
   1272     reply_state *rep;
   1273     service_instance *instance = srs->ServiceContext;
   1274     if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, 0, mStatus_NoError) != mStatus_NoError)
   1275         LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
   1276     else { append_reply(instance->request, rep); instance->clientnotified = mDNSfalse; }
   1277 }
   1278 
   1279 // service registration callback performs three duties - frees memory for deregistered services,
   1280 // handles name conflicts, and delivers completed registration information to the client
   1281 mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
   1282 {
   1283     mStatus err;
   1284     mDNSBool SuppressError = mDNSfalse;
   1285     reply_state         *rep;
   1286     (void)m; // Unused
   1287 
   1288     if (!srs)
   1289     {
   1290         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "regservice_callback: srs is NULL %d", result);
   1291         return;
   1292     }
   1293 
   1294     service_instance *const instance = srs->ServiceContext;
   1295     if (!instance)
   1296     {
   1297         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "regservice_callback: srs->ServiceContext is NULL %d", result);
   1298         return;
   1299     }
   1300 
   1301     // don't send errors up to client for wide-area, empty-string registrations
   1302     if (instance->request &&
   1303         instance->request->servicereg->default_domain &&
   1304         !instance->default_local)
   1305         SuppressError = mDNStrue;
   1306 
   1307     if (mDNS_LoggingEnabled)
   1308     {
   1309         const char *result_description;
   1310         char description[32]; // 32-byte is enough for holding "suppressed error -2147483648\0"
   1311         mDNSu32 request_id = instance->request ? instance->request->request_id : 0;
   1312         switch (result) {
   1313             case mStatus_NoError:
   1314                 result_description = "REGISTERED";
   1315                 break;
   1316             case mStatus_MemFree:
   1317                 result_description = "DEREGISTERED";
   1318                 break;
   1319             case mStatus_NameConflict:
   1320                 result_description = "NAME CONFLICT";
   1321                 break;
   1322             default:
   1323                 mDNS_snprintf(description, sizeof(description), "%s %d", SuppressError ? "suppressed error" : "CALLBACK", result);
   1324                 result_description = description;
   1325                 break;
   1326         }
   1327 
   1328         const mDNSu32 srv_name_hash = mDNS_NonCryptoHash(mDNSNonCryptoHash_FNV1a, srs->RR_SRV.resrec.name->c,
   1329             DomainNameLength(srs->RR_SRV.resrec.name));
   1330 
   1331         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1332             "[R%u] DNSServiceRegister(" PRI_DM_NAME " (%x), %u) %s",
   1333             request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name), srv_name_hash,
   1334             mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), result_description);
   1335     }
   1336 
   1337     if (!instance->request && result != mStatus_MemFree)
   1338     {
   1339         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: instance->request is NULL %d", result);
   1340         return;
   1341     }
   1342     if (result == mStatus_NoError)
   1343     {
   1344         const request_servicereg *const servicereg = instance->request->servicereg;
   1345         if (servicereg->allowremotequery)
   1346         {
   1347             ExtraResourceRecord *e;
   1348             srs->RR_ADV.AllowRemoteQuery = mDNStrue;
   1349             srs->RR_PTR.AllowRemoteQuery = mDNStrue;
   1350             srs->RR_SRV.AllowRemoteQuery = mDNStrue;
   1351             srs->RR_TXT.AllowRemoteQuery = mDNStrue;
   1352             for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
   1353         }
   1354 
   1355         if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
   1356             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
   1357         else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
   1358 
   1359 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1360         if (callExternalHelpers(servicereg->InterfaceID, &instance->domain, instance->request->flags))
   1361         {
   1362             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: calling external_start_advertising_helper()", instance->request->request_id);
   1363             external_start_advertising_helper(instance);
   1364         }
   1365 #endif
   1366         if (servicereg->autoname && CountPeerRegistrations(srs) == 0)
   1367             RecordUpdatedNiceLabel(0);   // Successfully got new name, tell user immediately
   1368     }
   1369     else if (result == mStatus_MemFree)
   1370     {
   1371         if (instance->request && instance->renameonmemfree)
   1372         {
   1373 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1374             external_stop_advertising_helper(instance);
   1375 #endif
   1376             instance->renameonmemfree = 0;
   1377             err = mDNS_RenameAndReregisterService(m, srs, &instance->request->servicereg->name);
   1378             if (err)
   1379                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] ERROR: regservice_callback - RenameAndReregisterService returned %d", instance->request->request_id, err);
   1380             // error should never happen - safest to log and continue
   1381         }
   1382         else
   1383             unlink_and_free_service_instance(instance);
   1384     }
   1385     else if (result == mStatus_NameConflict)
   1386     {
   1387         const request_servicereg *const servicereg = instance->request->servicereg;
   1388         if (servicereg->autorename)
   1389         {
   1390 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1391             external_stop_advertising_helper(instance);
   1392 #endif
   1393             if (servicereg->autoname && CountPeerRegistrations(srs) == 0)
   1394             {
   1395                 // On conflict for an autoname service, rename and reregister *all* autoname services
   1396                 IncrementLabelSuffix(&m->nicelabel, mDNStrue);
   1397                 mDNS_ConfigChanged(m);  // Will call back into udsserver_handle_configchange()
   1398             }
   1399             else    // On conflict for a non-autoname service, rename and reregister just that one service
   1400             {
   1401                 if (instance->clientnotified) SendServiceRemovalNotification(srs);
   1402                 mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
   1403             }
   1404         }
   1405         else
   1406         {
   1407             if (!SuppressError)
   1408             {
   1409                 if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
   1410                     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
   1411                 else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
   1412             }
   1413             unlink_and_free_service_instance(instance);
   1414         }
   1415     }
   1416     else        // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
   1417     {
   1418         if (!SuppressError)
   1419         {
   1420             if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
   1421                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
   1422             else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
   1423         }
   1424     }
   1425 }
   1426 
   1427 mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result)
   1428 {
   1429     (void)m; // Unused
   1430     if (!rr->RecordContext)     // parent struct already freed by termination callback
   1431     {
   1432         if (result == mStatus_NoError)
   1433         {
   1434             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Error: regrecord_callback: successful registration of orphaned record " PRI_S, ARDisplayString(m, rr));
   1435         }
   1436         else
   1437         {
   1438             if (result != mStatus_MemFree)
   1439                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "regrecord_callback: error %d received after parent termination", result);
   1440 
   1441             // We come here when the record is being deregistered either from DNSServiceRemoveRecord or connection_termination.
   1442             // If the record has been updated, we need to free the rdata. Every time we call mDNS_Update, it calls update_callback
   1443             // with the old rdata (so that we can free it) and stores the new rdata in "rr->resrec.rdata". This means, we need
   1444             // to free the latest rdata for which the update_callback was never called with.
   1445             if (rr->resrec.rdata != &rr->rdatastorage) freeL("RData/regrecord_callback", rr->resrec.rdata);
   1446             freeL("AuthRecord/regrecord_callback", rr);
   1447         }
   1448     }
   1449     else
   1450     {
   1451         registered_record_entry *re = rr->RecordContext;
   1452         request_state *request = re->request;
   1453 
   1454         if (mDNS_LoggingEnabled)
   1455         {
   1456             const char *result_description;
   1457             char description[16]; // 16-byte is enough for holding -2147483648\0
   1458             switch (result) {
   1459                 case mStatus_NoError:
   1460                     result_description = "REGISTERED";
   1461                     break;
   1462                 case mStatus_MemFree:
   1463                     result_description = "DEREGISTERED";
   1464                     break;
   1465                 case mStatus_NameConflict:
   1466                     result_description = "NAME CONFLICT";
   1467                     break;
   1468                 default:
   1469                     mDNS_snprintf(description, sizeof(description), "%d", result);
   1470                     result_description = description;
   1471                     break;
   1472             }
   1473 
   1474             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegisterRecord(%u " PRI_S ")" PUB_S,
   1475                       request->request_id, re->key, RRDisplayString(m, &rr->resrec), result_description);
   1476         }
   1477 
   1478         if (result != mStatus_MemFree)
   1479         {
   1480             const size_t len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
   1481             reply_state *reply = create_reply(reg_record_reply_op, len, request);
   1482             reply->mhdr->client_context = re->regrec_client_context;
   1483             reply->rhdr->flags = dnssd_htonl(0);
   1484             reply->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, rr->resrec.InterfaceID, mDNSfalse));
   1485             reply->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)result);
   1486             append_reply(request, reply);
   1487         }
   1488 
   1489         if (result)
   1490         {
   1491             // If this is a callback to a keepalive record, do not free it.
   1492             if (result == mStatus_BadStateErr)
   1493             {
   1494                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1495                           "[R%u] regrecord_callback: Callback with error code mStatus_BadStateErr - not freeing the record.", request->request_id);
   1496             }
   1497             else
   1498             {
   1499                 // unlink from list, free memory
   1500                 registered_record_entry **ptr = &request->reg_recs;
   1501                 while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
   1502                 if (!*ptr)
   1503                 {
   1504                     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1505                               "[R%u] regrecord_callback - record not in list!", request->request_id);
   1506                     return;
   1507                 }
   1508                 *ptr = (*ptr)->next;
   1509                 freeL("registered_record_entry AuthRecord regrecord_callback", re->rr);
   1510                 freeL("registered_record_entry regrecord_callback", re);
   1511              }
   1512         }
   1513         else
   1514         {
   1515             if (re->external_advertise)
   1516             {
   1517                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1518                           "[R%u] regrecord_callback: external_advertise already set!", request->request_id);
   1519             }
   1520 
   1521 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1522             if (callExternalHelpers(re->origInterfaceID, &rr->namestorage, request->flags))
   1523             {
   1524                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1525                           "[R%u] regrecord_callback: calling external_start_advertising_service", request->request_id);
   1526                 external_start_advertising_service(&rr->resrec, request->flags, request->process_id);
   1527                 re->external_advertise = mDNStrue;
   1528             }
   1529 #endif
   1530         }
   1531     }
   1532 }
   1533 
   1534 // set_peer_pid() is called after mem is allocated for each new request in NewRequest()
   1535 // This accounts for 2 places (connect_callback, request_callback)
   1536 mDNSlocal void set_peer_pid(request_state *request)
   1537 {
   1538     request->pid_name[0] = '\0';
   1539     request->process_id  = -1;
   1540 #ifdef LOCAL_PEEREPID
   1541     pid_t           p    = (pid_t) -1;
   1542     socklen_t       len  = sizeof(p);
   1543     if (request->sd < 0)
   1544         return;
   1545     // to extract the effective pid value
   1546     if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &p, &len) != 0)
   1547         return;
   1548     debugf("set_peer_pid: Client PEEREPID is %d", p);
   1549     request->process_id = p;
   1550 #else   // !LOCAL_PEEREPID
   1551     LogInfo("set_peer_pid: Not Supported on this version of OS");
   1552     if (request->sd < 0)
   1553         return;
   1554 #endif  // LOCAL_PEEREPID
   1555 }
   1556 
   1557 mDNSlocal mDNSu32 request_state_get_duration(const request_state *const request)
   1558 {
   1559     return (mDNSu32)(mDNSPlatformContinuousTimeSeconds() - request->request_start_time_secs);
   1560 }
   1561 
   1562 #define kRequestLogNamePeriodSecs (5 * MDNS_SECONDS_PER_MINUTE)
   1563 
   1564 mDNSlocal mDNSBool requestShouldLogName(request_state *const request)
   1565 {
   1566     const mDNSs32 lastFullLogTimeSecs = request->last_full_log_time_secs;
   1567     const mDNSs32 nowTimeSecs = mDNSPlatformContinuousTimeSeconds();
   1568     const mDNSBool logName =
   1569         ((lastFullLogTimeSecs == 0) || ((nowTimeSecs - lastFullLogTimeSecs) >= kRequestLogNamePeriodSecs));;
   1570     if (logName)
   1571     {
   1572         request->last_full_log_time_secs = nowTimeSecs;
   1573     }
   1574     return logName;
   1575 }
   1576 
   1577 #define kRequestLogFullRequestInfoPeriodSecs (5 * MDNS_SECONDS_PER_MINUTE)
   1578 
   1579 mDNSlocal mDNSBool requestShouldLogFullRequestInfo(request_state *const request)
   1580 {
   1581     const mDNSs32 lastFullQInfoTimeSecs = request->request_start_time_secs;
   1582     const mDNSs32 nowTimeSecs = mDNSPlatformContinuousTimeSeconds();
   1583     mDNSBool logFullRInfo;
   1584     if (lastFullQInfoTimeSecs == 0)
   1585     {
   1586         request->request_start_time_secs = mDNSPlatformContinuousTimeSeconds();
   1587         logFullRInfo = mDNStrue;
   1588     }
   1589     else
   1590     {
   1591         logFullRInfo = ((nowTimeSecs - lastFullQInfoTimeSecs) >= kRequestLogFullRequestInfoPeriodSecs);
   1592     }
   1593     if (logFullRInfo)
   1594     {
   1595         request->last_full_log_time_secs = nowTimeSecs;
   1596     }
   1597     return logFullRInfo;
   1598 }
   1599 
   1600 mDNSlocal void connection_termination(request_state *request)
   1601 {
   1602     // When terminating a shared connection, we need to scan the all_requests list
   1603     // and terminate any subbordinate operations sharing this file descriptor
   1604     request_state **req = &all_requests;
   1605 
   1606     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   1607            "[R%d] DNSServiceCreateConnection STOP PID[%d](" PUB_S ")",
   1608            request->request_id, request->process_id, request->pid_name);
   1609 
   1610     while (*req)
   1611     {
   1612         if ((*req)->primary == request)
   1613         {
   1614             // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
   1615             request_state *tmp = *req;
   1616             if (tmp->primary == tmp) LogMsg("connection_termination ERROR (*req)->primary == *req for %p %d",                  tmp, tmp->sd);
   1617             if (tmp->replies) LogMsg("connection_termination ERROR How can subordinate req %p %d have replies queued?", tmp, tmp->sd);
   1618             abort_request(tmp);
   1619             *req = tmp->next;
   1620             request_state_forget(&tmp);
   1621         }
   1622         else
   1623             req = &(*req)->next;
   1624     }
   1625 
   1626     while (request->reg_recs)
   1627     {
   1628         registered_record_entry *ptr = request->reg_recs;
   1629         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1630                "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") STOP PID[%d](" PUB_S ") -- duration: " PUB_TIME_DUR,
   1631                request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ptr->rr->resrec), request->process_id,
   1632                request->pid_name, request_state_get_duration(request));
   1633         request->reg_recs = request->reg_recs->next;
   1634         ptr->rr->RecordContext = NULL;
   1635         if (ptr->external_advertise)
   1636         {
   1637             ptr->external_advertise = mDNSfalse;
   1638 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   1639             external_stop_advertising_service(&ptr->rr->resrec, request->flags, request->process_id);
   1640 #endif
   1641         }
   1642         LogMcastS(ptr->rr, request, reg_stop);
   1643 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   1644         if (ptr->powerlog_start_time != 0)
   1645         {
   1646             const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   1647             mdns_powerlog_register_record_stop(request->pid_name, ptr->powerlog_start_time, usesAWDL);
   1648         }
   1649 #endif
   1650         mDNS_Deregister(&mDNSStorage, ptr->rr);     // Will free ptr->rr for us
   1651         freeL("registered_record_entry/connection_termination", ptr);
   1652     }
   1653 }
   1654 
   1655 mDNSlocal void handle_cancel_request(request_state *request)
   1656 {
   1657     request_state **req = &all_requests;
   1658     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%d] Cancel %08X %08X",
   1659            request->request_id, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
   1660     while (*req)
   1661     {
   1662         if ((*req)->primary == request &&
   1663             (*req)->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
   1664             (*req)->hdr.client_context.u32[1] == request->hdr.client_context.u32[1])
   1665         {
   1666             // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
   1667             request_state *tmp = *req;
   1668             abort_request(tmp);
   1669             *req = tmp->next;
   1670             request_state_forget(&tmp);
   1671         }
   1672         else
   1673             req = &(*req)->next;
   1674     }
   1675 }
   1676 
   1677 mDNSlocal mStatus _handle_regrecord_request_start(request_state *request, AuthRecord * rr)
   1678 {
   1679     mStatus err;
   1680     registered_record_entry *re;
   1681     // Don't allow non-local domains to be regsitered as LocalOnly. Allowing this would permit
   1682     // clients to register records such as www.bigbank.com A w.x.y.z to redirect Safari.
   1683     if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly && !IsLocalDomain(rr->resrec.name) &&
   1684         rr->resrec.rrclass == kDNSClass_IN && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA ||
   1685                                                rr->resrec.rrtype == kDNSType_CNAME))
   1686     {
   1687         freeL("AuthRecord/handle_regrecord_request", rr);
   1688         return (mStatus_BadParamErr);
   1689     }
   1690     // allocate registration entry, link into list
   1691     re = (registered_record_entry *) callocL("registered_record_entry", sizeof(*re));
   1692     if (!re) FatalError("ERROR: calloc");
   1693     re->key                   = request->hdr.reg_index;
   1694     re->rr                    = rr;
   1695     re->regrec_client_context = request->hdr.client_context;
   1696     re->request               = request;
   1697     re->external_advertise    = mDNSfalse;
   1698     rr->RecordContext         = re;
   1699     rr->RecordCallback        = regrecord_callback;
   1700     rr->ForceMCast            = ((request->flags & kDNSServiceFlagsForceMulticast) != 0);
   1701 
   1702     re->origInterfaceID = rr->resrec.InterfaceID;
   1703     if (rr->resrec.InterfaceID == mDNSInterface_P2P)
   1704         rr->resrec.InterfaceID = mDNSInterface_Any;
   1705 #if 0
   1706     if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError);
   1707 #endif
   1708     if (rr->resrec.rroriginalttl == 0)
   1709         rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
   1710 
   1711     const ResourceRecord *const record = &rr->resrec;
   1712     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1713         "DNSServiceRegisterRecord START",
   1714         record->name, request, mDNSfalse, "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE,
   1715         DM_NAME_PARAM_NONNULL(record->name), DNS_TYPE_PARAM(record->rrtype));
   1716 
   1717     err = mDNS_Register(&mDNSStorage, rr);
   1718     if (err)
   1719     {
   1720         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   1721                "[R%d] DNSServiceRegisterRecord(0x%X, %d," PRI_S ") ERROR (%d)",
   1722                request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &rr->resrec), err);
   1723         freeL("registered_record_entry", re);
   1724         freeL("registered_record_entry/AuthRecord", rr);
   1725     }
   1726     else
   1727     {
   1728 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   1729         if ((rr->resrec.InterfaceID != mDNSInterface_LocalOnly) && IsLocalDomain(rr->resrec.name))
   1730         {
   1731             const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   1732             re->powerlog_start_time = mdns_powerlog_register_record_start(request->pid_name, usesAWDL);
   1733         }
   1734 #endif
   1735         LogMcastS(rr, request, reg_start);
   1736         re->next = request->reg_recs;
   1737         request->reg_recs = re;
   1738     }
   1739     return err;
   1740 }
   1741 
   1742 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   1743 
   1744 mDNSlocal void _return_regrecord_request_error(request_state *request, mStatus error)
   1745 {
   1746     reply_state *rep;
   1747     if (GenerateNTDResponse(NULL, 0, request, &rep, reg_record_reply_op, 0, error) != mStatus_NoError)
   1748     {
   1749         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "[R%u] DNSServiceRegisterRecord _return_regrecord_request_error: error(%d)", request->request_id, error);
   1750     }
   1751     else
   1752     {
   1753         append_reply(request, rep);
   1754     }
   1755 }
   1756 
   1757 mDNSlocal mStatus _handle_regrecord_request_with_trust(request_state *request, AuthRecord * rr)
   1758 {
   1759     mStatus err;
   1760     if (!request->peer_token)
   1761     {
   1762         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_WARNING, "[R%u] _handle_regrecord_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   1763         err = _handle_regrecord_request_start(request, rr);
   1764     }
   1765     else
   1766     {
   1767         const char *service_ptr = NULL;
   1768         char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
   1769         domainlabel name;
   1770         domainname type, domain;
   1771         bool good = DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
   1772         if (good)
   1773         {
   1774             ConvertDomainNameToCString(&type, type_str);
   1775             service_ptr = type_str;
   1776         }
   1777 
   1778         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   1779         mdns_trust_flags_t flags = mdns_trust_flags_none;
   1780         mdns_trust_status_t status = mdns_trust_check_bonjour(*token, service_ptr, &flags);
   1781         switch (status)
   1782         {
   1783             case mdns_trust_status_denied:
   1784             case mdns_trust_status_pending:
   1785             {
   1786                 if (!_prepare_trusts_for_request(request))
   1787                 {
   1788                     freeL("AuthRecord/_handle_regrecord_request_with_trust", rr);
   1789                     err = mStatus_NoMemoryErr;
   1790                     goto exit;
   1791                 }
   1792                 mdns_trust_t trust = mdns_trust_create(*token, service_ptr, flags);
   1793                 if (!trust)
   1794                 {
   1795                     freeL("AuthRecord/_handle_regrecord_request_with_trust", rr);
   1796                     err = mStatus_NoMemoryErr;
   1797                     goto exit;
   1798                 }
   1799                 mdns_trust_set_context(trust, rr);
   1800                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   1801                 {
   1802                     freeL("AuthRecord/_handle_regrecord_request_with_trust finalizer", ref);
   1803                 });
   1804                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   1805                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   1806                 {
   1807                     if (event == mdns_trust_event_result)
   1808                     {
   1809                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   1810                         KQueueLock();
   1811                         AuthRecord * _rr =  mdns_trust_get_context(trust);
   1812                         if (_rr)
   1813                         {
   1814                             if (!error)
   1815                             {
   1816                                 mdns_trust_set_context(trust, NULL); // _handle_regrecord_request_start handles free
   1817                                 error = _handle_regrecord_request_start(request, _rr);
   1818                                 // No context means the request was canceled before we got here
   1819                             }
   1820                             if (error) // (not else if) Always check for error result
   1821                             {
   1822                                 _return_regrecord_request_error(request, error);
   1823                             }
   1824                         }
   1825                         KQueueUnlock("_handle_regrecord_request_with_trust");
   1826                     }
   1827                 });
   1828                 CFArrayAppendValue(request->trusts, trust);
   1829                 mdns_release(trust);
   1830                 mdns_trust_activate(trust);
   1831                 err = mStatus_NoError;
   1832                 break;
   1833             }
   1834 
   1835             case mdns_trust_status_no_entitlement:
   1836                 err = mStatus_NoAuth;
   1837                 break;
   1838 
   1839             case mdns_trust_status_granted:
   1840                 err = _handle_regrecord_request_start(request, rr);
   1841                 break;
   1842 
   1843             MDNS_COVERED_SWITCH_DEFAULT:
   1844                 err = mStatus_UnknownErr;
   1845         }
   1846      }
   1847 exit:
   1848     return err;
   1849 }
   1850 #endif // TRUST_ENFORCEMENT
   1851 
   1852 // Add a TSR record when DNSServiceRegisterRecordWithAttribute is called with timestamp set correctly
   1853 mDNSlocal mStatus regRecordAddTSRRecord(request_state *const request, AuthRecord *const rr, const mDNSs32 tsrTimestamp,
   1854     const mDNSu32 tsrHostkeyHash)
   1855 {
   1856     mStatus err = mStatus_NoError;
   1857     size_t rdcapacity = sizeof(RDataBody2);
   1858     AuthRecord *ar = (AuthRecord *) callocL("AuthRecord/regRecordAddTSRRecord", sizeof(*ar) - sizeof(RDataBody) + rdcapacity);
   1859     if (!ar)
   1860     {
   1861         FatalError("ERROR: calloc");
   1862     }
   1863     mDNS_SetupResourceRecord(ar, mDNSNULL, rr->resrec.InterfaceID, kDNSType_OPT, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
   1864     AssignDomainName(&ar->namestorage, rr->resrec.name);
   1865     ar->resrec.rrclass          = NormalMaxDNSMessageData;
   1866     ar->resrec.namehash         = rr->resrec.namehash;
   1867     ar->resrec.rdlength         = DNSOpt_TSRData_Space;
   1868     ar->resrec.rdestimate       = DNSOpt_TSRData_Space;
   1869     rdataOPT * const rdata = &ar->resrec.rdata->u.opt[0];
   1870     rdata->opt                  = kDNSOpt_TSR;
   1871     rdata->optlen               = DNSOpt_TSRData_Space - 4;
   1872     rdata->u.tsr.timeStamp      = tsrTimestamp;
   1873     rdata->u.tsr.hostkeyHash    = tsrHostkeyHash;
   1874     rdata->u.tsr.recIndex       = 0;
   1875     ar->RecordCallback          = regrecord_callback;
   1876     SetNewRData(&ar->resrec, mDNSNULL, 0);  // Sets ar->rdatahash for us
   1877     ar->ForceMCast = ((request->flags & kDNSServiceFlagsForceMulticast) != 0);
   1878     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%d] regRecordAddTSRRecord(0x%X, %d, " PRI_S ") START PID[%d](" PUB_S ")",
   1879               request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ar->resrec),
   1880               request->process_id, request->pid_name);
   1881 
   1882     err = mDNS_Register(&mDNSStorage, ar);
   1883     if (err)
   1884     {
   1885         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%d] regRecordAddTSRRecord(0x%X, %d," PRI_S ") ERROR (%d)",
   1886                   request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ar->resrec), err);
   1887         freeL("registered_record_entry/AuthRecord", ar);
   1888     }
   1889     else
   1890     {
   1891         LogMcastS(ar, request, reg_start);
   1892         ar->RRSet = (uintptr_t)request->sd;
   1893     }
   1894     return err;
   1895 }
   1896 
   1897 mDNSlocal mStatus updateTSRRecord(const request_state *const request, AuthRecord *const tsr, const mDNSs32 tsrTimestamp,
   1898     const mDNSu32 tsrHostkeyHash)
   1899 {
   1900     mStatus err = mStatus_NoError;
   1901     RDataBody2 *const rdb = (RDataBody2 *)tsr->resrec.rdata->u.data;
   1902     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "TSR timestamp - name: " PRI_DM_NAME ", new: %d  old: %d",
   1903               DM_NAME_PARAM(tsr->resrec.name), tsrTimestamp, rdb->tsr_value);
   1904     if (tsrTimestamp - rdb->opt[0].u.tsr.timeStamp > 0)
   1905     {
   1906         mDNSu32 optlen = DNSOpt_TSRData_Space - 4;
   1907         mDNSu32 uTimestamp = (mDNSu32)tsrTimestamp;
   1908         const mDNSu8 rdataOpt[DNSOpt_TSRData_Space] = {
   1909             (kDNSOpt_TSR >> 8) & 0xFF,          kDNSOpt_TSR & 0xFF,
   1910             (optlen >> 8) & 0xFF,               optlen & 0xFF,
   1911             (uTimestamp >> 24) & 0xFF,          (uTimestamp >> 16) & 0xFF,
   1912             (uTimestamp >> 8) & 0xFF,           uTimestamp & 0xFF,
   1913             (tsrHostkeyHash >> 24) & 0xFF,      (tsrHostkeyHash >> 16) & 0xFF,
   1914             (tsrHostkeyHash >> 8) & 0xFF,       tsrHostkeyHash & 0xFF,
   1915             0,                                  0 };
   1916         err = update_record(tsr, sizeof(rdataOpt), rdataOpt, kHostNameTTL, mDNSNULL, request->request_id);
   1917     }
   1918     return err;
   1919 }
   1920 
   1921 mDNSlocal mDNSBool conflictWithAuthRecords(mDNS *const m, const AuthRecord *const rr)
   1922 {
   1923     const AuthRecord *rp = m->ResourceRecords;
   1924     const uintptr_t s1 = rr->RRSet ? rr->RRSet : (uintptr_t)rr;
   1925 
   1926     while (rp)
   1927     {
   1928         const uintptr_t s2 = rp->RRSet ? rp->RRSet : (uintptr_t)rp;
   1929         if (rp->resrec.rrtype != kDNSType_OPT && s1 != s2 &&
   1930             SameResourceRecordNameClassInterface(rp, rr) &&
   1931             !IdenticalSameNameRecord(&rp->resrec, &rr->resrec) &&
   1932             (rr->resrec.RecordType & kDNSRecordTypeUniqueMask || rp->resrec.RecordType & kDNSRecordTypeUniqueMask))
   1933         {
   1934             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Conflict with " PRI_S " (%p), InterfaceID %p",
   1935                       ARDisplayString(&mDNSStorage, rp), rp, rp->resrec.InterfaceID);
   1936             return mDNStrue;
   1937         }
   1938         else
   1939         {
   1940             rp = rp->next;
   1941         }
   1942     }
   1943     return mDNSfalse;
   1944 }
   1945 
   1946 mDNSlocal mDNSBool conflictWithCacheRecordsOrFlush(mDNS *const m, const mDNSu32 namehash, const domainname *const name,
   1947     const mDNSs32 validatedTSRTimestamp, const mDNSu32 tsrHostkeyHash)
   1948 {
   1949     // Check for a matching TSR in the record cache.
   1950     // If it is newer (eTSRCheckWin) then exit with true (conflict)
   1951     // Otherwise, always clear the matching record cache entries.
   1952     const CacheGroup *cg = CacheGroupForName(m, namehash, name);
   1953     if (cg)
   1954     {
   1955         CacheRecord *cacheTSR = mDNSGetTSRForCacheGroup(cg);
   1956         if (cacheTSR)
   1957         {
   1958             const TSROptData newTSR = {validatedTSRTimestamp, tsrHostkeyHash, 0};
   1959             eTSRCheckResult tsrResult = CheckTSRForResourceRecord(&newTSR, &cacheTSR->resrec);
   1960             if (tsrResult == eTSRCheckWin)
   1961             {
   1962                 return mDNStrue; // Existing TSR in cache is newer
   1963             }
   1964         }
   1965         // Flush cache for name since a TSR is authoritive for all Interfaces
   1966         CacheRecord *cr;
   1967         for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
   1968         {
   1969             mDNS_PurgeCacheResourceRecord(m, cr);
   1970             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG,
   1971                 "conflictWithCacheRecordsOrFlush - new TSR, flushing interface %d " PRI_S,
   1972                 (int)IIDPrintable(cr->resrec.InterfaceID), CRDisplayString(m, cr));
   1973         }
   1974     }
   1975     return mDNSfalse;
   1976 }
   1977 
   1978 mDNSlocal mStatus handle_regrecord_request(request_state *request)
   1979 {
   1980     mStatus err = mStatus_BadParamErr;
   1981     AuthRecord *rr;
   1982 
   1983     if (request->terminate != connection_termination)
   1984     { LogMsg("%3d: DNSServiceRegisterRecord(not a shared connection ref)", request->sd); return(err); }
   1985 
   1986     rr = read_rr_from_ipc_msg(request, 1, 1);
   1987     mDNSu32 tsrTimestamp = 0, tsrHostkeyHash;
   1988     const mDNSBool foundTSRParams = get_service_attr_tsr_params(request, &tsrTimestamp, &tsrHostkeyHash);
   1989     mDNSs32 timestampContinuous = 0;
   1990     AuthRecord *currentTSR = mDNSNULL;
   1991     if (rr)
   1992     {
   1993         if (foundTSRParams && !getValidContinousTSRTime(&timestampContinuous, tsrTimestamp))
   1994         {
   1995             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "tsrTimestamp[%u] out of range (%u) on TSR for " PRI_DM_NAME "",
   1996                       tsrTimestamp, MaxTimeSinceReceived, DM_NAME_PARAM(rr->resrec.name));
   1997             return mStatus_BadParamErr;
   1998         }
   1999         currentTSR = mDNSGetTSRForAuthRecord(&mDNSStorage, rr);
   2000         rr->RRSet = (uintptr_t)request->sd;
   2001         if ((currentTSR || foundTSRParams) && conflictWithAuthRecords(&mDNSStorage, rr))
   2002         {
   2003             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "handle_regrecord_request: Name conflict " PRI_S " (%p), InterfaceID %p",
   2004                       ARDisplayString(&mDNSStorage, rr), rr, rr->resrec.InterfaceID);
   2005             freeL("AuthRecord/handle_regrecord_request", rr);
   2006             return mStatus_NameConflict;
   2007         }
   2008         const mDNSs32 validatedTSRTimestamp = (mDNSs32)tsrTimestamp;
   2009         if (foundTSRParams &&
   2010             conflictWithCacheRecordsOrFlush(&mDNSStorage, rr->resrec.namehash, rr->resrec.name, validatedTSRTimestamp, tsrHostkeyHash))
   2011         {
   2012             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2013                 "handle_regrecord_request: TSR Stale Data, record cache is newer " PRI_DM_NAME " InterfaceID %p",
   2014                 DM_NAME_PARAM(rr->resrec.name), rr->resrec.InterfaceID);
   2015             freeL("AuthRecord/handle_regrecord_request", rr);
   2016             return mStatus_StaleData;
   2017         }
   2018 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   2019         if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
   2020             IsLocalDomain(rr->resrec.name))
   2021         {
   2022             err = _handle_regrecord_request_with_trust(request, rr);
   2023         }
   2024         else
   2025         {
   2026             err = _handle_regrecord_request_start(request, rr);
   2027         }
   2028 #else
   2029         err = _handle_regrecord_request_start(request, rr);
   2030 #endif
   2031     }
   2032     if (!err && foundTSRParams)
   2033     {
   2034         if (currentTSR)
   2035         {
   2036             err = updateTSRRecord(request, currentTSR, timestampContinuous, tsrHostkeyHash);
   2037         }
   2038         else
   2039         {
   2040             err = regRecordAddTSRRecord(request, rr, timestampContinuous, tsrHostkeyHash);
   2041         }
   2042         if (!err)
   2043         {
   2044             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2045                       "handle_regrecord_request: TSR record added with timestampContinuous %d tsrTimestamp %d tsrHostkeyHash %x",
   2046                       timestampContinuous, tsrTimestamp, tsrHostkeyHash);
   2047         }
   2048         else
   2049         {
   2050             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   2051                       "handle_regrecord_request: Failed to add TSR record with error %d", err);
   2052             registered_record_entry *re = rr->RecordContext;
   2053             // unlink rr from list, free memory
   2054             registered_record_entry **ptr = &request->reg_recs;
   2055             while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
   2056             if (!*ptr)
   2057             {
   2058                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   2059                           "[R%u] handle_regrecord_request - record not in list!", request->request_id);
   2060             }
   2061             else
   2062             {
   2063                 *ptr = (*ptr)->next;
   2064                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "[R%u] handle_regrecord_request: TSR fail, removing " PRI_S " (%p), InterfaceID %p",
   2065                           request->request_id, ARDisplayString(&mDNSStorage, rr), rr, rr->resrec.InterfaceID);
   2066                 rr->RecordContext = NULL;
   2067                 mDNS_Deregister(&mDNSStorage, rr);     // Will free rr for us; we're responsible for freeing re
   2068                 freeL("registered_record_entry handle_regrecord_request", re);
   2069             }
   2070         }
   2071     }
   2072 
   2073     return(err);
   2074 }
   2075 
   2076 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
   2077 
   2078 mDNSlocal void regservice_termination_callback(request_state *const request)
   2079 {
   2080     if (!request)
   2081     {
   2082         LogMsg("regservice_termination_callback context is NULL");
   2083         return;
   2084     }
   2085     request_servicereg *const servicereg = request->servicereg;
   2086     while (servicereg->instances)
   2087     {
   2088         service_instance *p = servicereg->instances;
   2089         servicereg->instances = servicereg->instances->next;
   2090         // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
   2091         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%d] DNSServiceRegister(" PRI_DM_NAME " (%x), %u) STOP PID[%d](" PUB_S ") -- duration: " PUB_TIME_DUR,
   2092                request->request_id, DM_NAME_PARAM(p->srs.RR_SRV.resrec.name),
   2093                mDNS_NonCryptoHash(mDNSNonCryptoHash_FNV1a, p->srs.RR_SRV.resrec.name->c, DomainNameLength(p->srs.RR_SRV.resrec.name)),
   2094                mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port), request->process_id, request->pid_name,
   2095                request_state_get_duration(request));
   2096 
   2097         const ResourceRecord *const srv_rr = &p->srs.RR_SRV.resrec;
   2098         UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "DNSServiceRegister STOP",
   2099             SkipLeadingLabels(srv_rr->name, 1), request, mDNStrue, "SRV name: " PRI_DM_NAME " (%x), port: %u",
   2100             DM_NAME_PARAM(srv_rr->name), mDNS_DomainNameFNV1aHash(srv_rr->name), mDNSVal16(srv_rr->rdata->u.srv.port));
   2101 
   2102 
   2103 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2104         external_stop_advertising_helper(p);
   2105 #endif
   2106 
   2107         // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
   2108         // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
   2109         // servicereg->instances as we work our way through the list, implicitly cutting one element at a time
   2110         // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
   2111         // because by then we might have already freed p
   2112         p->request = NULL;
   2113         LogMcastS(&p->srs.RR_SRV, request, reg_stop);
   2114         if (mDNS_DeregisterService(&mDNSStorage, &p->srs))
   2115         {
   2116             unlink_and_free_service_instance(p);
   2117             // Don't touch service_instance *p after this -- it's likely to have been freed already
   2118         }
   2119     #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   2120         if (request->powerlog_start_time != 0)
   2121         {
   2122             const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   2123             mdns_powerlog_service_register_stop(request->pid_name, request->powerlog_start_time, usesAWDL);
   2124             request->powerlog_start_time = 0;
   2125         }
   2126     #endif
   2127     }
   2128     if (servicereg->txtdata)
   2129     {
   2130         freeL("service_info txtdata", servicereg->txtdata);
   2131         servicereg->txtdata = NULL;
   2132     }
   2133     if (servicereg->autoname)
   2134     {
   2135         // Clear autoname before calling UpdateDeviceInfoRecord() so it doesn't mistakenly include this in its count of active autoname registrations
   2136         servicereg->autoname = mDNSfalse;
   2137         UpdateDeviceInfoRecord(&mDNSStorage);
   2138     }
   2139 }
   2140 
   2141 mDNSlocal request_state *LocateSubordinateRequest(request_state *request)
   2142 {
   2143     request_state *req;
   2144     for (req = all_requests; req; req = req->next)
   2145         if (req->primary == request &&
   2146             req->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
   2147             req->hdr.client_context.u32[1] == request->hdr.client_context.u32[1]) return(req);
   2148     return(request);
   2149 }
   2150 
   2151 mDNSlocal mStatus add_record_to_service(request_state *const request, service_instance *const instance, const mDNSu16 rrtype,
   2152     const mDNSu16 rdlen, const mDNSu8 *const rdata, const mDNSu32 ttl)
   2153 {
   2154     ServiceRecordSet *srs = &instance->srs;
   2155     mStatus result;
   2156     const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
   2157     ExtraResourceRecord *extra = (ExtraResourceRecord *)callocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + rdcapacity);
   2158     if (!extra) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
   2159 
   2160     extra->r.resrec.rrtype = rrtype;
   2161     extra->r.resrec.rdata = &extra->r.rdatastorage;
   2162     extra->r.resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
   2163     extra->r.resrec.rdlength = rdlen;
   2164     const request_servicereg *const servicereg = request->servicereg;
   2165     if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &extra->r.resrec, rdlen))
   2166     {
   2167         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   2168             "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
   2169             request->request_id, DM_NAME_PARAM(servicereg->instances ?
   2170             servicereg->instances->srs.RR_SRV.resrec.name : mDNSNULL), DNSTypeName(rrtype));
   2171         freeL("ExtraResourceRecord/add_record_to_service", extra);
   2172         return mStatus_BadParamErr;
   2173     }
   2174     SetNewRData(&extra->r.resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
   2175     // use InterfaceID value from DNSServiceRegister() call that created the original service
   2176     extra->r.resrec.InterfaceID = servicereg->InterfaceID;
   2177 
   2178     result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, request->flags);
   2179     if (result)
   2180     {
   2181         freeL("ExtraResourceRecord/add_record_to_service", extra);
   2182         return result;
   2183     }
   2184     LogMcastS(&srs->RR_PTR, request, reg_start);
   2185 
   2186     extra->ClientID = request->hdr.reg_index;
   2187 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2188     if (   instance->external_advertise
   2189            && callExternalHelpers(servicereg->InterfaceID, &instance->domain, request->flags))
   2190     {
   2191         LogInfo("add_record_to_service: calling external_start_advertising_service");
   2192         external_start_advertising_service(&extra->r.resrec, request->flags, request->process_id);
   2193     }
   2194 #endif
   2195     return result;
   2196 }
   2197 
   2198 mDNSlocal mStatus handle_add_request(request_state *request)
   2199 {
   2200     service_instance *i;
   2201     mStatus result = mStatus_UnknownErr;
   2202     DNSServiceFlags flags  = get_flags (&request->msgptr, request->msgend);
   2203     mDNSu16 rrtype = get_uint16(&request->msgptr, request->msgend);
   2204     mDNSu16 rdlen  = get_uint16(&request->msgptr, request->msgend);
   2205     const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
   2206     mDNSu32 ttl    = get_uint32(&request->msgptr, request->msgend);
   2207     if (!ttl) ttl = DefaultTTLforRRType(rrtype);
   2208     (void)flags; // Unused
   2209 
   2210     if (!request->msgptr)
   2211     {
   2212         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2213                "[R%d] DNSServiceAddRecord(unreadable parameters)", request->request_id);
   2214         return(mStatus_BadParamErr);
   2215     }
   2216 
   2217     // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
   2218     if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
   2219 
   2220     if (request->terminate != regservice_termination_callback)
   2221     {
   2222         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2223                "[R%d] DNSServiceAddRecord(not a registered service ref)", request->request_id);
   2224         return(mStatus_BadParamErr);
   2225     }
   2226 
   2227     // For a service registered with zero port, don't allow adding records. This mostly happens due to a bug
   2228     // in the application. See radar://9165807.
   2229     const request_servicereg *const servicereg = request->servicereg;
   2230     if (mDNSIPPortIsZero(servicereg->port))
   2231     {
   2232         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2233                "[R%d] DNSServiceAddRecord: adding record to a service registered with zero port", request->request_id);
   2234         return(mStatus_BadParamErr);
   2235     }
   2236     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2237            "[R%d] DNSServiceAddRecord(%X, " PRI_DM_NAME ", " PUB_S ", %d) PID[%d](" PUB_S ")",
   2238            request->request_id, flags,
   2239            DM_NAME_PARAM((servicereg->instances) ? (servicereg->instances->srs.RR_SRV.resrec.name) : mDNSNULL),
   2240            DNSTypeName(rrtype), rdlen, request->process_id, request->pid_name);
   2241 
   2242     for (i = servicereg->instances; i; i = i->next)
   2243     {
   2244         result = add_record_to_service(request, i, rrtype, rdlen, rdata, ttl);
   2245         if (result && i->default_local) break;
   2246         else result = mStatus_NoError;  // suppress non-local default errors
   2247     }
   2248 
   2249     return(result);
   2250 }
   2251 
   2252 mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd, mDNSu16 oldrdlen)
   2253 {
   2254     mDNSBool external_advertise = (rr->UpdateContext) ? *((mDNSBool *)rr->UpdateContext) : mDNSfalse;
   2255     (void)m; // Unused
   2256 
   2257     // There are three cases.
   2258     //
   2259     // 1. We have updated the primary TXT record of the service
   2260     // 2. We have updated the TXT record that was added to the service using DNSServiceAddRecord
   2261     // 3. We have updated the TXT record that was registered using DNSServiceRegisterRecord
   2262     //
   2263     // external_advertise is set if we have advertised at least once during the initial addition
   2264     // of the record in all of the three cases above. We should have checked for InterfaceID/LocalDomain
   2265     // checks during the first time and hence we don't do any checks here
   2266     if (external_advertise)
   2267     {
   2268         ResourceRecord ext = rr->resrec;
   2269 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2270         DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(rr->ARType);
   2271 #endif
   2272 
   2273         if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
   2274         SetNewRData(&ext, oldrd, oldrdlen);
   2275 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2276         external_stop_advertising_service(&ext, flags, 0);
   2277         LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "update_callback: calling external_start_advertising_service");
   2278         external_start_advertising_service(&rr->resrec, flags, 0);
   2279 #endif
   2280     }
   2281 exit:
   2282     if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
   2283 }
   2284 
   2285 mDNSlocal mStatus update_record(AuthRecord *ar, mDNSu16 rdlen, const mDNSu8 *const rdata, mDNSu32 ttl,
   2286     const mDNSBool *const external_advertise, const mDNSu32 request_id)
   2287 {
   2288     ResourceRecord rr;
   2289     mStatus result;
   2290     const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
   2291     RData *newrd = (RData *) callocL("RData/update_record", sizeof(*newrd) - sizeof(RDataBody) + rdcapacity);
   2292     if (!newrd) FatalError("ERROR: calloc");
   2293     mDNSPlatformMemZero(&rr, (mDNSu32)sizeof(rr));
   2294     rr.name     = ar->resrec.name;
   2295     rr.rrtype   = ar->resrec.rrtype;
   2296     rr.rrclass  = ar->resrec.rrclass;
   2297     rr.rdata    = newrd;
   2298     rr.rdata->MaxRDLength = (mDNSu16)rdcapacity;
   2299     rr.rdlength = rdlen;
   2300     if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr, rdlen))
   2301     {
   2302         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   2303             "[R%u] update_record: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
   2304             request_id, DM_NAME_PARAM(rr.name), DNSTypeName(rr.rrtype));
   2305         freeL("RData/update_record", newrd);
   2306         return mStatus_BadParamErr;
   2307     }
   2308     rdlen = GetRDLength(&rr, mDNSfalse);
   2309     // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
   2310     // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
   2311     // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
   2312     if (ar->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
   2313 
   2314     if (external_advertise) ar->UpdateContext = (void *)external_advertise;
   2315 
   2316     result = mDNS_Update(&mDNSStorage, ar, ttl, rdlen, newrd, update_callback);
   2317     if (result) { LogMsg("update_record: Error %d for %s", (int)result, ARDisplayString(&mDNSStorage, ar)); freeL("RData/update_record", newrd); }
   2318     return result;
   2319 }
   2320 
   2321 mDNSlocal mStatus handle_tsr_update_request(const request_state *const request, const AuthRecord *const rr,
   2322     const mDNSu32 tsrTimestamp, const mDNSu32 tsrHostkeyHash)
   2323 {
   2324     mStatus result = mStatus_NoError;
   2325     AuthRecord *currentTSR = mDNSGetTSRForAuthRecord(&mDNSStorage, rr);
   2326     mDNSs32 timestampContinuous;
   2327     if (!getValidContinousTSRTime(&timestampContinuous, tsrTimestamp))
   2328     {
   2329         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "tsrTimestamp[%u] out of range (%u) on TSR for " PRI_DM_NAME "",
   2330                   tsrTimestamp, MaxTimeSinceReceived, DM_NAME_PARAM(rr->resrec.name));
   2331         result = mStatus_BadParamErr;
   2332         goto end;
   2333     }
   2334     if (currentTSR)
   2335     {
   2336         result = updateTSRRecord(request, currentTSR, timestampContinuous, tsrHostkeyHash);
   2337     }
   2338     else
   2339     {
   2340        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "No existing TSR for " PRI_DM_NAME "", DM_NAME_PARAM(rr->resrec.name));
   2341        result = mStatus_BadReferenceErr;
   2342        goto end;
   2343     }
   2344 
   2345 end:
   2346     return result;
   2347 }
   2348 
   2349 mDNSlocal mStatus handle_update_request(request_state *request)
   2350 {
   2351     const ipc_msg_hdr *const hdr = &request->hdr;
   2352     mStatus result = mStatus_BadReferenceErr;
   2353     service_instance *i;
   2354     AuthRecord *rr = NULL;
   2355 
   2356     // get the message data
   2357     DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend);  // flags unused
   2358     mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
   2359     const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
   2360     mDNSu32 ttl   = get_uint32(&request->msgptr, request->msgend);
   2361     (void)flags; // Unused
   2362 
   2363     if (!request->msgptr)
   2364     {
   2365         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2366                "[R%d] DNSServiceUpdateRecord(unreadable parameters)", request->request_id);
   2367         return(mStatus_BadParamErr);
   2368     }
   2369 
   2370     mDNSu32 tsrTimestamp, tsrHostkeyHash;
   2371     const mDNSBool foundTSRParams = get_service_attr_tsr_params(request, &tsrTimestamp, &tsrHostkeyHash);
   2372     if (foundTSRParams)
   2373     {
   2374         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2375             "[R%u] DNSServiceUpdateRecord foundTSRParams tsrTimestamp[%u] hostkeyHash[%x]",
   2376             request->request_id, tsrTimestamp, tsrHostkeyHash);
   2377     }
   2378 
   2379     // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
   2380     if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
   2381 
   2382     if (request->terminate == connection_termination)
   2383     {
   2384         // update an individually registered record
   2385         for (const registered_record_entry *reptr = request->reg_recs; reptr; reptr = reptr->next)
   2386         {
   2387             if (reptr->key == hdr->reg_index)
   2388             {
   2389                 if (foundTSRParams)
   2390                 {
   2391                     result = handle_tsr_update_request(request, reptr->rr, tsrTimestamp, tsrHostkeyHash);
   2392                 }
   2393                 else
   2394                 {
   2395                     result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise, request->request_id);
   2396                 }
   2397                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2398                     "[R%u] DNSServiceUpdateRecord(" PRI_DM_NAME ", " PUB_S PUB_S ") PID[%d](" PUB_S ")",
   2399                     request->request_id, DM_NAME_PARAM(reptr->rr->resrec.name),
   2400                     reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>", foundTSRParams ? " & TSR" : "",
   2401                     request->process_id, request->pid_name);
   2402                 goto end;
   2403             }
   2404         }
   2405         result = mStatus_BadReferenceErr;
   2406         goto end;
   2407     }
   2408 
   2409     if (request->terminate != regservice_termination_callback)
   2410     {
   2411         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2412                "[R%d] DNSServiceUpdateRecord(not a registered service ref)", request->request_id);
   2413         return(mStatus_BadParamErr);
   2414     }
   2415 
   2416     // For a service registered with zero port, only SRV record is initialized. Don't allow any updates.
   2417     request_servicereg *servicereg = request->servicereg;
   2418     if (mDNSIPPortIsZero(servicereg->port))
   2419     {
   2420         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2421                "[R%d] DNSServiceUpdateRecord: updating the record of a service registered with zero port", request->request_id);
   2422         return(mStatus_BadParamErr);
   2423     }
   2424 
   2425     // update the saved off TXT data for the service
   2426     if (!foundTSRParams && hdr->reg_index == TXT_RECORD_INDEX)
   2427     {
   2428         if (servicereg->txtdata)
   2429         { freeL("service_info txtdata", servicereg->txtdata); servicereg->txtdata = NULL; }
   2430         if (rdlen > 0)
   2431         {
   2432             servicereg->txtdata = mallocL("service_info txtdata", rdlen);
   2433             if (!servicereg->txtdata) FatalError("ERROR: handle_update_request - malloc");
   2434             mDNSPlatformMemCopy(servicereg->txtdata, rdata, rdlen);
   2435         }
   2436         servicereg->txtlen = rdlen;
   2437     }
   2438 
   2439     // update a record from a service record set
   2440     for (i = servicereg->instances; i; i = i->next)
   2441     {
   2442         if (hdr->reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
   2443         else
   2444         {
   2445             ExtraResourceRecord *e;
   2446             for (e = i->srs.Extras; e; e = e->next)
   2447                 if (e->ClientID == hdr->reg_index) { rr = &e->r; break; }
   2448         }
   2449 
   2450         if (!rr) { result = mStatus_BadReferenceErr; goto end; }
   2451         if (foundTSRParams)
   2452         {
   2453             result = handle_tsr_update_request(request, rr, tsrTimestamp, tsrHostkeyHash);
   2454             goto end;
   2455         }
   2456         else
   2457         {
   2458             result = update_record(rr, rdlen, rdata, ttl, &i->external_advertise, request->request_id);
   2459         }
   2460         if (result && i->default_local) goto end;
   2461         else result = mStatus_NoError;  // suppress non-local default errors
   2462     }
   2463 
   2464 end:
   2465     if (request->terminate == regservice_termination_callback)
   2466     {
   2467         servicereg = request->servicereg;
   2468         const domainname *const srvName =
   2469             (servicereg->instances ? servicereg->instances->srs.RR_SRV.resrec.name : mDNSNULL);
   2470         const mDNSu32 nameHash =
   2471             (srvName ? mDNS_NonCryptoHash(mDNSNonCryptoHash_FNV1a, srvName->c, DomainNameLength(srvName)) : 0);
   2472         const uint16_t rrType = (rr ? rr->resrec.rrtype : 0);
   2473         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2474             "[R%u] DNSServiceUpdateRecord(" PRI_DM_NAME " (%x), " PUB_DNS_TYPE ") UPDATE PID[%d](%s)",
   2475             request->request_id, DM_NAME_PARAM(srvName), nameHash, DNS_TYPE_PARAM(rrType),
   2476             request->process_id, request->pid_name);
   2477     }
   2478     return(result);
   2479 }
   2480 
   2481 // remove a resource record registered via DNSServiceRegisterRecord()
   2482 mDNSlocal mStatus remove_record(request_state *request)
   2483 {
   2484     mStatus err = mStatus_UnknownErr;
   2485     registered_record_entry *e, **ptr = &request->reg_recs;
   2486 
   2487     while (*ptr && (*ptr)->key != request->hdr.reg_index) ptr = &(*ptr)->next;
   2488     if (!*ptr) { LogMsg("%3d: DNSServiceRemoveRecord(%u) not found", request->sd, request->hdr.reg_index); return mStatus_BadReferenceErr; }
   2489     e = *ptr;
   2490     *ptr = e->next; // unlink
   2491 
   2492     LogOperation("%3d: DNSServiceRemoveRecord(%u %s)  PID[%d](%s)",
   2493                 request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec), request->process_id, request->pid_name);
   2494     e->rr->RecordContext = NULL;
   2495     if (e->external_advertise)
   2496     {
   2497 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2498         external_stop_advertising_service(&e->rr->resrec, request->flags, request->process_id);
   2499 #endif
   2500         e->external_advertise = mDNSfalse;
   2501     }
   2502     LogMcastS(e->rr, request, reg_stop);
   2503 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   2504     if (e->powerlog_start_time != 0)
   2505     {
   2506         const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   2507         mdns_powerlog_register_record_stop(request->pid_name, e->powerlog_start_time, usesAWDL);
   2508     }
   2509 #endif
   2510     err = mDNS_Deregister(&mDNSStorage, e->rr);     // Will free e->rr for us; we're responsible for freeing e
   2511     if (err)
   2512     {
   2513         LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err);
   2514         freeL("registered_record_entry AuthRecord remove_record", e->rr);
   2515     }
   2516     freeL("registered_record_entry remove_record", e);
   2517     return err;
   2518 }
   2519 
   2520 mDNSlocal mStatus remove_extra(const request_state *const request, service_instance *const serv, mDNSu16 *const rrtype)
   2521 {
   2522     mStatus err = mStatus_BadReferenceErr;
   2523     ExtraResourceRecord *ptr;
   2524 
   2525     for (ptr = serv->srs.Extras; ptr; ptr = ptr->next)
   2526     {
   2527         if (ptr->ClientID == request->hdr.reg_index) // found match
   2528         {
   2529             *rrtype = ptr->r.resrec.rrtype;
   2530 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   2531             if (serv->external_advertise)
   2532             {
   2533                 external_stop_advertising_service(&ptr->r.resrec, request->flags, request->process_id);
   2534             }
   2535 #endif
   2536             err = mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
   2537             break;
   2538         }
   2539     }
   2540     return err;
   2541 }
   2542 
   2543 mDNSlocal mStatus handle_removerecord_request(request_state *request)
   2544 {
   2545     mStatus err = mStatus_BadReferenceErr;
   2546     get_flags(&request->msgptr, request->msgend);   // flags unused
   2547 
   2548     if (!request->msgptr)
   2549     {
   2550         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2551                "[R%d] DNSServiceRemoveRecord(unreadable parameters)", request->request_id);
   2552         return(mStatus_BadParamErr);
   2553     }
   2554 
   2555     // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
   2556     if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
   2557 
   2558     // LocateSubordinateRequest returns the connection it was passed if the request is not referring to a
   2559     // subordinate request. In this case, if request->terminate == connection_terminate, that means that this
   2560     // is a connection created with DNSServiceCreateConnection, and so the remove would have to apply to a
   2561     // record added with DNSServiceRegisterRecord. We can remove this using remove_record.
   2562     if (request->terminate == connection_termination)
   2563         err = remove_record(request);
   2564 
   2565     // Otherwise, the only type of request object to which DNSServiceRemoveRecord could apply is one that
   2566     // was created with DNSServiceRegister, which is indicated by request->terminate == regservice_termination_callback.
   2567     // So if that's not the case, the request is invalid.
   2568     else if (request->terminate != regservice_termination_callback)
   2569     {
   2570         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2571                   "[R%d] DNSServiceRemoveRecord(not a registered service ref)", request->request_id);
   2572         return(mStatus_BadParamErr);
   2573     }
   2574     else
   2575     {
   2576         service_instance *i;
   2577         mDNSu16 rrtype = 0;
   2578         // In this case request is a request created with DNSServiceRegister, and there may be more than one
   2579         // instance if there is more than one default registration domain, so we have to iterate across the
   2580         // instances and remove the record from each instance individually, if it is present.
   2581         const request_servicereg *const servicereg = request->servicereg;
   2582         for (i = servicereg->instances; i; i = i->next)
   2583         {
   2584             err = remove_extra(request, i, &rrtype);
   2585             if (err && i->default_local) break;
   2586             else err = mStatus_NoError;  // suppress non-local default errors
   2587         }
   2588         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2589                   "[R%d] DNSServiceRemoveRecord(" PRI_DM_NAME ", " PUB_S ") PID[%d](" PUB_S "): %d",
   2590                   request->request_id,
   2591                   DM_NAME_PARAM(servicereg->instances ? servicereg->instances->srs.RR_SRV.resrec.name : mDNSNULL),
   2592                   rrtype ? DNSTypeName(rrtype) : "<NONE>", request->process_id, request->pid_name, err);
   2593     }
   2594 
   2595     return(err);
   2596 }
   2597 
   2598 // If there's a comma followed by another character,
   2599 // FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character.
   2600 // Otherwise, it returns a pointer to the final nul at the end of the string
   2601 mDNSlocal char *FindFirstSubType(char *p)
   2602 {
   2603     while (*p)
   2604     {
   2605         if (p[0] == '\\' && p[1])
   2606         {
   2607              p += 2;
   2608         }
   2609         else if (p[0] == ',' && p[1])
   2610         {
   2611             *p++ = 0;
   2612             return(p);
   2613         }
   2614         else
   2615         {
   2616             p++;
   2617         }
   2618     }
   2619     return(p);
   2620 }
   2621 
   2622 // If there's a comma followed by another character,
   2623 // FindNextSubType overwrites the comma with a nul and returns the pointer to the next character.
   2624 // If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL
   2625 // Otherwise, it returns a pointer to the final nul at the end of the string
   2626 mDNSlocal char *FindNextSubType(char *p)
   2627 {
   2628     while (*p)
   2629     {
   2630         if (p[0] == '\\' && p[1])       // If escape character
   2631             p += 2;                     // ignore following character
   2632         else if (p[0] == ',')           // If we found a comma
   2633         {
   2634             if (p[1]) *p++ = 0;
   2635             return(p);
   2636         }
   2637         else if (p[0] == '.')
   2638             return(mDNSNULL);
   2639         else p++;
   2640     }
   2641     return(p);
   2642 }
   2643 
   2644 // Returns -1 if illegal subtype found
   2645 mDNSlocal mDNSs32 ChopSubTypes(char *regtype)
   2646 {
   2647     mDNSs32 NumSubTypes = 0;
   2648     char *stp = FindFirstSubType(regtype);
   2649     while (stp && *stp)                 // If we found a comma...
   2650     {
   2651         if (*stp == ',') return(-1);
   2652         NumSubTypes++;
   2653         stp = FindNextSubType(stp);
   2654     }
   2655     if (!stp) return(-1);
   2656     return(NumSubTypes);
   2657 }
   2658 
   2659 mDNSlocal mStatus AllocateSubTypes(mDNSu32 NumSubTypes, char *p, AuthRecord **subtypes)
   2660 {
   2661     AuthRecord *st = mDNSNULL;
   2662     if (NumSubTypes)
   2663     {
   2664         mDNSu32 i;
   2665         st = (AuthRecord *) callocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord));
   2666         if (!st) return(mStatus_NoMemoryErr);
   2667         for (i = 0; i < NumSubTypes; i++)
   2668         {
   2669             mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
   2670             while (*p) p++;
   2671             p++;
   2672             if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p))
   2673             {
   2674                 freeL("ServiceSubTypes", st);
   2675                 return(mStatus_BadParamErr);
   2676             }
   2677         }
   2678     }
   2679     *subtypes = st;
   2680     return(mStatus_NoError);
   2681 }
   2682 
   2683 mDNSlocal mStatus register_service_instance(request_state *const request, const domainname *const domain)
   2684 {
   2685     service_instance **ptr, *instance;
   2686     request_servicereg *const servicereg = request->servicereg;
   2687     size_t extra_size = (servicereg->txtlen > sizeof(RDataBody)) ? (servicereg->txtlen - sizeof(RDataBody)) : 0;
   2688     const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
   2689     mStatus result;
   2690     mDNSInterfaceID interfaceID = servicereg->InterfaceID;
   2691     mDNSu32 tsrTimestamp, tsrHostkeyHash;
   2692     const mDNSBool foundTSRParams = get_service_attr_tsr_params(request, &tsrTimestamp, &tsrHostkeyHash);
   2693     mDNSs32 timestampContinuous = 0;
   2694 
   2695     if (foundTSRParams)
   2696     {
   2697         mDNSs32 validatedTSRTimestamp;
   2698         mDNSu32 namehash;
   2699         domainname full_hostname;
   2700 
   2701         if(!getValidContinousTSRTime(&timestampContinuous, tsrTimestamp))
   2702         {
   2703             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   2704                 "tsrTimestamp[%u] out of range (%u) on TSR", tsrTimestamp, MaxTimeSinceReceived);
   2705             return mStatus_BadParamErr;
   2706         }
   2707         validatedTSRTimestamp = (mDNSs32)tsrTimestamp;
   2708         ConstructServiceName(&full_hostname, &servicereg->name, &servicereg->type, domain);
   2709         namehash = DomainNameHashValue(&full_hostname);
   2710         if (conflictWithCacheRecordsOrFlush(&mDNSStorage, namehash, &full_hostname, validatedTSRTimestamp, tsrHostkeyHash))
   2711         {
   2712             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2713                 "register_service_instance: TSR Stale Data, record cache is newer " PRI_DM_NAME " InterfaceID %p",
   2714                 DM_NAME_PARAM(&full_hostname), interfaceID);
   2715             return mStatus_StaleData;
   2716         }
   2717     }
   2718 
   2719     // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS)
   2720     // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast
   2721     // registrations scoped to a specific interface, so for the automatic domains we add we must *not* specify an interface.
   2722     // (Specifying an interface with an apparently wide-area domain (i.e. something other than "local")
   2723     // currently forces the registration to use mDNS multicast despite the apparently wide-area domain.)
   2724     if (servicereg->default_domain && !DomainIsLocal) interfaceID = mDNSInterface_Any;
   2725 
   2726     for (ptr = &servicereg->instances; *ptr; ptr = &(*ptr)->next)
   2727     {
   2728         if (SameDomainName(&(*ptr)->domain, domain))
   2729         {
   2730             LogMsg("register_service_instance: domain %##s already registered for %#s.%##s",
   2731                    domain->c, &servicereg->name, &servicereg->type);
   2732             return mStatus_AlreadyRegistered;
   2733         }
   2734     }
   2735 
   2736     instance = (service_instance *) callocL("service_instance", sizeof(*instance) + extra_size);
   2737     if (!instance) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
   2738 
   2739     instance->next                          = mDNSNULL;
   2740     instance->request                       = request;
   2741     instance->renameonmemfree               = 0;
   2742     instance->clientnotified                = mDNSfalse;
   2743     instance->default_local                 = (servicereg->default_domain && DomainIsLocal);
   2744     instance->external_advertise            = mDNSfalse;
   2745     AssignDomainName(&instance->domain, domain);
   2746 
   2747     result = AllocateSubTypes(servicereg->num_subtypes, servicereg->type_as_string, &instance->subtypes);
   2748 
   2749     if (result)
   2750     {
   2751         unlink_and_free_service_instance(instance);
   2752         instance = NULL;
   2753         if (result == mStatus_NoMemoryErr)
   2754         {
   2755             FatalError("ERROR: malloc");
   2756         }
   2757         else
   2758         {
   2759             return result;
   2760         }
   2761     }
   2762 
   2763     result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
   2764                                   &servicereg->name, &servicereg->type, domain,
   2765                                   servicereg->host.c[0] ? &servicereg->host : NULL,
   2766                                   servicereg->port,
   2767                                   mDNSNULL, servicereg->txtdata, servicereg->txtlen,
   2768                                   instance->subtypes, servicereg->num_subtypes,
   2769                                   interfaceID, regservice_callback, instance, request->flags);
   2770 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   2771     if (!result && (request->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) && DomainIsLocal)
   2772     {
   2773         const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   2774         request->powerlog_start_time = mdns_powerlog_service_register_start(request->pid_name, usesAWDL);
   2775     }
   2776 #endif
   2777     if (!result && foundTSRParams)
   2778     {
   2779         AuthRecord *currentTSR = mDNSGetTSRForAuthRecord(&mDNSStorage, &instance->srs.RR_SRV);
   2780 
   2781         if (currentTSR)
   2782         {
   2783             result = updateTSRRecord(request, currentTSR, timestampContinuous, tsrHostkeyHash);
   2784         }
   2785         else
   2786         {
   2787             // tsr timestamp in memory is absolute time of receipt
   2788             mDNSu32 optlen = DNSOpt_TSRData_Space - 4;
   2789             mDNSu32 uTimestamp = (mDNSu32)timestampContinuous;
   2790             const mDNSu8 rdataOpt[DNSOpt_TSRData_Space] = {
   2791                 (kDNSOpt_TSR >> 8) & 0xFF,          kDNSOpt_TSR & 0xFF,
   2792                 (optlen >> 8) & 0xFF,               optlen & 0xFF,
   2793                 (uTimestamp >> 24) & 0xFF,          (uTimestamp >> 16) & 0xFF,
   2794                 (uTimestamp >> 8) & 0xFF,           uTimestamp & 0xFF,
   2795                 (tsrHostkeyHash >> 24) & 0xFF,      (tsrHostkeyHash >> 16) & 0xFF,
   2796                 (tsrHostkeyHash >> 8) & 0xFF,       tsrHostkeyHash & 0xFF,
   2797                 0,                                  0 };
   2798             result = add_record_to_service(request, instance, kDNSType_OPT, sizeof(rdataOpt), rdataOpt, kHostNameTTL);
   2799         }
   2800         if (!result)
   2801         {
   2802             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "TSR record added with tsrTimestamp %d", timestampContinuous);
   2803         }
   2804         else
   2805         {
   2806             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Failed to add TSR record with tsrTimestamp %u error %d",
   2807                       tsrTimestamp, result);
   2808         }
   2809     }
   2810 
   2811     if (!result)
   2812     {
   2813         *ptr = instance;        // Append this to the end of our servicereg->instances list
   2814 
   2815         // [R14] DNSServiceRegister result -- event: ADDED, SRV name: p001-ari0v37kf5o6d._dnssd-dp._tcp.local.(261cb2cf), port: 853, PTR name hash: 78e1c9c8
   2816         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   2817             "[R%u] DNSServiceRegister result -- event: ADDED, SRV name: " PRI_DM_NAME " (%x), port: %u, PTR name hash: %x",
   2818             request->request_id, DM_NAME_PARAM(instance->srs.RR_SRV.resrec.name),
   2819             mDNS_DomainNameFNV1aHash(instance->srs.RR_SRV.resrec.name), mDNSVal16(servicereg->port),
   2820             mDNS_DomainNameFNV1aHash(instance->srs.RR_PTR.resrec.name));
   2821 
   2822         LogMcastS(&instance->srs.RR_SRV, request, reg_start);
   2823     }
   2824     else
   2825     {
   2826         LogMsg("register_service_instance %#s.%##s%##s error %d",
   2827                &servicereg->name, &servicereg->type, domain->c, result);
   2828         unlink_and_free_service_instance(instance);
   2829     }
   2830 
   2831     return result;
   2832 }
   2833 
   2834 mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d, const mDNSBool add)
   2835 {
   2836     request_state *request;
   2837 
   2838     LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c);
   2839     for (request = all_requests; request; request = request->next)
   2840     {
   2841         request_servicereg *const servicereg = request->servicereg;
   2842         if (request->terminate != regservice_termination_callback) continue;
   2843         if (!servicereg->default_domain) continue;
   2844         if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
   2845         {
   2846             service_instance **ptr = &servicereg->instances;
   2847             while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
   2848             if (add)
   2849             {
   2850                 // If we don't already have this domain in our list for this registration, add it now
   2851                 if (!*ptr) register_service_instance(request, &d->name);
   2852                 else debugf("udsserver_default_reg_domain_changed %##s already in list, not re-adding", &d->name);
   2853             }
   2854             else
   2855             {
   2856                 // Normally we should not fail to find the specified instance
   2857                 // One case where this can happen is if a uDNS update fails for some reason,
   2858                 // and regservice_callback then calls unlink_and_free_service_instance and disposes of that instance.
   2859                 if (!*ptr)
   2860                     LogMsg("udsserver_default_reg_domain_changed domain %##s not found for service %#s type %s",
   2861                            &d->name, servicereg->name.c, servicereg->type_as_string);
   2862                 else
   2863                 {
   2864                     DNameListElem *p;
   2865                     for (p = AutoRegistrationDomains; p; p=p->next)
   2866                         if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
   2867                             if (SameDomainName(&d->name, &p->name)) break;
   2868                     if (p) debugf("udsserver_default_reg_domain_changed %##s still in list, not removing", &d->name);
   2869                     else
   2870                     {
   2871                         mStatus err;
   2872                         service_instance *si = *ptr;
   2873                         *ptr = si->next;
   2874                         if (si->clientnotified) SendServiceRemovalNotification(&si->srs); // Do this *before* clearing si->request backpointer
   2875                         // Now that we've cut this service_instance from the list, we MUST clear the si->request backpointer.
   2876                         // Otherwise what can happen is this: While our mDNS_DeregisterService is in the
   2877                         // process of completing asynchronously, the client cancels the entire operation, so
   2878                         // regservice_termination_callback then runs through the whole list deregistering each
   2879                         // instance, clearing the backpointers, and then disposing the parent request_state object.
   2880                         // However, because this service_instance isn't in the list any more, regservice_termination_callback
   2881                         // has no way to find it and clear its backpointer, and then when our mDNS_DeregisterService finally
   2882                         // completes later with a mStatus_MemFree message, it calls unlink_and_free_service_instance() with
   2883                         // a service_instance with a stale si->request backpointer pointing to memory that's already been freed.
   2884                         si->request = NULL;
   2885                         err = mDNS_DeregisterService(&mDNSStorage, &si->srs);
   2886                         if (err) { LogMsg("udsserver_default_reg_domain_changed err %d", err); unlink_and_free_service_instance(si); }
   2887                     }
   2888                 }
   2889             }
   2890         }
   2891     }
   2892 }
   2893 
   2894 // Returns true if the interfaceIndex value matches one of the pre-defined
   2895 // special values listed in the switch statement below.
   2896 mDNSlocal mDNSBool PreDefinedInterfaceIndex(mDNSu32 interfaceIndex)
   2897 {
   2898     switch(interfaceIndex)
   2899     {
   2900         case kDNSServiceInterfaceIndexAny:
   2901         case kDNSServiceInterfaceIndexLocalOnly:
   2902         case kDNSServiceInterfaceIndexUnicast:
   2903         case kDNSServiceInterfaceIndexP2P:
   2904         case kDNSServiceInterfaceIndexBLE:
   2905             return mDNStrue;
   2906         default:
   2907             return mDNSfalse;
   2908     }
   2909 }
   2910 
   2911 mDNSlocal mStatus _handle_regservice_request_start(request_state *const request, const domainname *const d)
   2912 {
   2913     mStatus err;
   2914 
   2915     request->terminate = regservice_termination_callback;
   2916     err = register_service_instance(request, d);
   2917 
   2918 #if 0
   2919     err = AuthorizedDomain(request, d, AutoRegistrationDomains) ? register_service_instance(request, d) : mStatus_NoError;
   2920 #endif
   2921     if (!err)
   2922     {
   2923         const request_servicereg *const servicereg = request->servicereg;
   2924         if (servicereg->autoname) UpdateDeviceInfoRecord(&mDNSStorage);
   2925 
   2926         if (servicereg->default_domain)
   2927         {
   2928             DNameListElem *ptr;
   2929             // Note that we don't report errors for non-local, non-explicit domains
   2930             for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
   2931                 if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
   2932                     register_service_instance(request, &ptr->name);
   2933         }
   2934     }
   2935     return err;
   2936 }
   2937 
   2938 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   2939 
   2940 mDNSlocal void _return_regservice_request_error(request_state *const request, const mStatus error)
   2941 {
   2942     request_servicereg *const servicereg = request->servicereg;
   2943     if (servicereg->txtdata)
   2944     {
   2945         freeL("service_info txtdata", servicereg->txtdata);
   2946         servicereg->txtdata = NULL;
   2947     }
   2948 
   2949     reply_state *rep;
   2950     if (GenerateNTDResponse(NULL, 0, request, &rep, reg_service_reply_op, 0, error) != mStatus_NoError)
   2951     {
   2952         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegister _return_regservice_request_error: error(%d)", request->request_id, error);
   2953     }
   2954     else
   2955     {
   2956         append_reply(request, rep);
   2957     }
   2958 }
   2959 
   2960 mDNSlocal mStatus _handle_regservice_request_with_trust(request_state *const request, const domainname *const d)
   2961 {
   2962     mStatus err;
   2963     if (!request->peer_token)
   2964     {
   2965         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_regservice_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   2966         err = _handle_regservice_request_start(request, d);
   2967     }
   2968     else
   2969     {
   2970         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   2971         mdns_trust_flags_t flags = mdns_trust_flags_none;
   2972         const request_servicereg *const servicereg = request->servicereg;
   2973         mdns_trust_status_t status = mdns_trust_check_register_service(*token, servicereg->type_as_string, &flags);
   2974         switch (status) {
   2975             case mdns_trust_status_denied:
   2976             case mdns_trust_status_pending:
   2977             {
   2978                 if (!_prepare_trusts_for_request(request))
   2979                 {
   2980                     err = mStatus_NoMemoryErr;
   2981                     goto exit;
   2982                 }
   2983                 mdns_trust_t trust = mdns_trust_create(*token, servicereg->type_as_string, flags);
   2984                 if (!trust)
   2985                 {
   2986                     err = mStatus_NoMemoryErr;
   2987                     goto exit;
   2988                 }
   2989                 void * context = mallocL("context/_handle_regservice_request_with_trust", sizeof(domainname));
   2990                 if (!context)
   2991                 {
   2992                     my_perror("ERROR: mallocL context/_handle_regservice_request_with_trust");
   2993                     mdns_release(trust);
   2994                     err = mStatus_NoMemoryErr;
   2995                     goto exit;
   2996                 }
   2997                 memcpy(context, d, sizeof(domainname));
   2998                 mdns_trust_set_context(trust, context);
   2999                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   3000                 {
   3001                     freeL("context/_handle_regservice_request_with_trust finalizer", ref);
   3002                 });
   3003                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   3004                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   3005                 {
   3006                     if (event == mdns_trust_event_result)
   3007                     {
   3008                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   3009                         KQueueLock();
   3010                         const domainname * _d = mdns_trust_get_context(trust);
   3011                         if (_d)
   3012                         {
   3013                             if (!error)
   3014                             {
   3015                                 error = _handle_regservice_request_start(request, _d);
   3016                                 // No context means the request was canceled before we got here
   3017                             }
   3018                             if (error) // (not else if) Always check for error result
   3019                             {
   3020                                 _return_regservice_request_error(request, error);
   3021                             }
   3022                         }
   3023                         KQueueUnlock("_register_service_instance_with_trust");
   3024                     }
   3025                 });
   3026                 CFArrayAppendValue(request->trusts, trust);
   3027                 mdns_release(trust);
   3028                 mdns_trust_activate(trust);
   3029                 err = mStatus_NoError;
   3030                 break;
   3031             }
   3032 
   3033             case mdns_trust_status_no_entitlement:
   3034                 err = mStatus_NoAuth;
   3035                 break;
   3036 
   3037             case mdns_trust_status_granted:
   3038                 err = _handle_regservice_request_start(request, d);
   3039                 break;
   3040 
   3041             MDNS_COVERED_SWITCH_DEFAULT:
   3042                 err = mStatus_UnknownErr;
   3043         }
   3044     }
   3045 exit:
   3046     return err;
   3047 }
   3048 #endif // TRUST_ENFORCEMENT
   3049 
   3050 mDNSlocal mStatus handle_regservice_request(request_state *const request)
   3051 {
   3052     char name[256]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes
   3053     char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
   3054     char type_as_string[MAX_ESCAPED_DOMAIN_NAME];  // Note that this service type may include a trailing list of subtypes
   3055     domainname d, srv;
   3056     mStatus err;
   3057     const uint8_t *msgTXTData;
   3058 
   3059     DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
   3060     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   3061     mDNSInterfaceID InterfaceID;
   3062     mDNSs32 subtypeCount;
   3063 
   3064     if (!request->servicereg)
   3065     {
   3066         request->servicereg = (request_servicereg *)callocL("request_servicereg", sizeof(*request->servicereg));
   3067         mdns_require_action_quiet(request->servicereg, exit, err = mStatus_NoMemoryErr; uds_log_error(
   3068             "[R%u] Failed to allocate memory for service registration request", request->request_id));
   3069     }
   3070     // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the
   3071     // kDNSServiceFlagsIncludeP2P flag set.
   3072     if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
   3073     {
   3074         LogOperation("handle_regservice_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
   3075         flags |= kDNSServiceFlagsIncludeP2P;
   3076         interfaceIndex = kDNSServiceInterfaceIndexAny;
   3077     }
   3078 
   3079     InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   3080 
   3081     // The registration is scoped to a specific interface index, but the
   3082     // interface is not currently in our list.
   3083     if (interfaceIndex && !InterfaceID)
   3084     {
   3085         // If it's one of the specially defined inteface index values, just return an error.
   3086         if (PreDefinedInterfaceIndex(interfaceIndex))
   3087         {
   3088             LogInfo("handle_regservice_request: bad interfaceIndex %d", interfaceIndex);
   3089             return(mStatus_BadParamErr);
   3090         }
   3091 
   3092         // Otherwise, use the specified interface index value and the registration will
   3093         // be applied to that interface when it comes up.
   3094         InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
   3095         LogInfo("handle_regservice_request: registration pending for interface index %d", interfaceIndex);
   3096     }
   3097 
   3098     if (get_string(&request->msgptr, request->msgend, name,           sizeof(name          )) < 0 ||
   3099         get_string(&request->msgptr, request->msgend, type_as_string, sizeof(type_as_string)) < 0 ||
   3100         get_string(&request->msgptr, request->msgend, domain,         sizeof(domain        )) < 0 ||
   3101         get_string(&request->msgptr, request->msgend, host,           sizeof(host          )) < 0)
   3102     { LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
   3103 
   3104     request->flags = flags;
   3105     request->interfaceIndex = interfaceIndex;
   3106     request_servicereg *const servicereg = request->servicereg;
   3107     servicereg->InterfaceID = InterfaceID;
   3108     servicereg->instances = NULL;
   3109     servicereg->txtlen  = 0;
   3110     servicereg->txtdata = NULL;
   3111     mDNSPlatformStrLCopy(servicereg->type_as_string, type_as_string, sizeof(servicereg->type_as_string));
   3112 
   3113     if (request->msgptr + 2 > request->msgend) request->msgptr = NULL;
   3114     else
   3115     {
   3116         servicereg->port.b[0] = *request->msgptr++;
   3117         servicereg->port.b[1] = *request->msgptr++;
   3118     }
   3119 
   3120     servicereg->txtlen = get_uint16(&request->msgptr, request->msgend);
   3121     msgTXTData = get_rdata(&request->msgptr, request->msgend, servicereg->txtlen);
   3122 
   3123     if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
   3124 
   3125     if (servicereg->txtlen)
   3126     {
   3127         servicereg->txtdata = mallocL("service_info txtdata", servicereg->txtlen);
   3128         if (!servicereg->txtdata) FatalError("ERROR: handle_regservice_request - malloc");
   3129         mDNSPlatformMemCopy(servicereg->txtdata, msgTXTData, servicereg->txtlen);
   3130     }
   3131 
   3132     // Check for sub-types after the service type
   3133     subtypeCount = ChopSubTypes(servicereg->type_as_string);    // Note: Modifies regtype string to remove trailing subtypes
   3134     if (subtypeCount < 0)
   3135     {
   3136         LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", servicereg->type_as_string);
   3137         goto bad_param;
   3138     }
   3139     servicereg->num_subtypes = (mDNSu32)subtypeCount;
   3140 
   3141     // Don't try to construct "domainname t" until *after* ChopSubTypes has worked its magic
   3142     if (!*servicereg->type_as_string || !MakeDomainNameFromDNSNameString(&servicereg->type, servicereg->type_as_string))
   3143     { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", servicereg->type_as_string); goto bad_param; }
   3144 
   3145     if (!name[0])
   3146     {
   3147         servicereg->name = mDNSStorage.nicelabel;
   3148         servicereg->autoname = mDNStrue;
   3149     }
   3150     else
   3151     {
   3152         // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
   3153         if ((flags & kDNSServiceFlagsNoAutoRename) == 0)
   3154         {
   3155             const mDNSu32 newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL);
   3156             name[newlen] = 0;
   3157         }
   3158         if (!MakeDomainLabelFromLiteralString(&servicereg->name, name))
   3159         { LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; }
   3160         servicereg->autoname = mDNSfalse;
   3161     }
   3162 
   3163     if (*domain)
   3164     {
   3165         servicereg->default_domain = mDNSfalse;
   3166         if (!MakeDomainNameFromDNSNameString(&d, domain))
   3167         { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); goto bad_param; }
   3168     }
   3169     else
   3170     {
   3171         servicereg->default_domain = mDNStrue;
   3172         MakeDomainNameFromDNSNameString(&d, "local.");
   3173     }
   3174 
   3175     if (!ConstructServiceName(&srv, &servicereg->name, &servicereg->type, &d))
   3176     {
   3177         LogMsg("ERROR: handle_regservice_request - Couldn't ConstructServiceName from, %#s %##s %##s",
   3178                servicereg->name.c, servicereg->type.c, d.c); goto bad_param;
   3179     }
   3180 
   3181     if (!MakeDomainNameFromDNSNameString(&servicereg->host, host))
   3182     { LogMsg("ERROR: handle_regservice_request - host bad %s", host); goto bad_param; }
   3183     servicereg->autorename       = (flags & kDNSServiceFlagsNoAutoRename    ) == 0;
   3184     servicereg->allowremotequery = (flags & kDNSServiceFlagsAllowRemoteQuery) != 0;
   3185 
   3186     // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with
   3187     // a port number of zero. When two instances of the protected client are allowed to run on one
   3188     // machine, we don't want to see misleading "Bogus client" messages in syslog and the console.
   3189     if (!mDNSIPPortIsZero(servicereg->port))
   3190     {
   3191         int count = CountExistingRegistrations(&srv, servicereg->port);
   3192         if (count)
   3193             LogMsg("Client application[%d](%s) registered %d identical instances of service %##s port %u.", request->process_id,
   3194                    request->pid_name, count+1, srv.c, mDNSVal16(servicereg->port));
   3195     }
   3196 
   3197     domainname ptr_name;
   3198     ConstructServiceName(&ptr_name, &servicereg->name, &servicereg->type, &d);
   3199     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "DNSServiceRegister START", &ptr_name, request,
   3200         mDNSfalse, "service type: " PRI_DM_NAME ", domain: " PRI_DM_NAME ", port: %u",
   3201         DM_NAME_PARAM(&servicereg->type), DM_NAME_PARAM(&d), mDNSVal16(servicereg->port));
   3202 
   3203     // We need to unconditionally set request->terminate, because even if we didn't successfully
   3204     // start any registrations right now, subsequent configuration changes may cause successful
   3205     // registrations to be added, and we'll need to cancel them before freeing this memory.
   3206     // We also need to set request->terminate first, before adding additional service instances,
   3207     // because the udsserver_validatelists uses the request->terminate function pointer to determine
   3208     // what kind of request this is, and therefore what kind of list validation is required.
   3209     request->terminate = NULL;
   3210 
   3211 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   3212     if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
   3213         (servicereg->default_domain || IsLocalDomain(&d)))
   3214     {
   3215         err = _handle_regservice_request_with_trust(request, &d);
   3216         if (err == mStatus_NoAuth && servicereg->txtdata)
   3217         {
   3218             freeL("service_info txtdata", servicereg->txtdata);
   3219             servicereg->txtdata = NULL;
   3220         }
   3221     }
   3222     else
   3223     {
   3224         err = _handle_regservice_request_start(request, &d);
   3225     }
   3226 #else
   3227     err = _handle_regservice_request_start(request, &d);
   3228 #endif
   3229 
   3230 exit:
   3231     return(err);
   3232 
   3233 bad_param:
   3234     freeL("handle_regservice_request (txtdata)", servicereg->txtdata);
   3235     servicereg->txtdata = NULL;
   3236     return mStatus_BadParamErr;
   3237 }
   3238 
   3239 // ***************************************************************************
   3240 // MARK: - DNSServiceBrowse
   3241 
   3242 mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
   3243 {
   3244     DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : 0;
   3245     request_state *req = question->QuestionContext;
   3246     reply_state *rep;
   3247     const mDNSBool isMDNSQuestion = mDNSOpaque16IsZero(question->TargetQID);
   3248     (void)m; // Unused
   3249 
   3250     if (answer->rrtype != kDNSType_PTR)
   3251     { LogMsg("%3d: FoundInstance: Should not be called with rrtype %d (not a PTR record)", req->sd, answer->rrtype); return; }
   3252 
   3253     if (mDNSOpaque16IsZero(question->TargetQID) && (question->BrowseThreshold > 0) && (question->CurrentAnswers >= question->BrowseThreshold))
   3254     {
   3255         flags |= kDNSServiceFlagsThresholdReached;
   3256     }
   3257 
   3258     // if returning a negative answer, then use question's name in reply
   3259     if (answer->RecordType == kDNSRecordTypePacketNegative)
   3260     {
   3261         GenerateBrowseReply(&question->qname, answer->InterfaceID, req, &rep, browse_reply_op, flags, kDNSServiceErr_NoSuchRecord);
   3262         goto validReply;
   3263     }
   3264 
   3265     if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
   3266     {
   3267         if (SameDomainName(&req->browse->regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
   3268         {
   3269             // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
   3270             // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
   3271             GenerateBrowseReply(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
   3272             goto validReply;
   3273         }
   3274 
   3275         LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
   3276                req->sd, answer->name->c, answer->rdata->u.name.c);
   3277         return;
   3278     }
   3279 
   3280 validReply:
   3281     UDS_LOG_ANSWER_EVENT(isMDNSQuestion ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   3282         req, question, answer, mDNSfalse, "DNSServiceBrowse result", AddRecord);
   3283 
   3284     append_reply(req, rep);
   3285 }
   3286 
   3287 mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req)
   3288 {
   3289     q->euid = req->uid;
   3290     // The policy is either based on pid or UUID. Pass a zero pid
   3291     // to the "core" if the UUID is valid. If we always pass the pid,
   3292     // then the "core" needs to determine whether the uuid is valid
   3293     // by examining all the 16 bytes at the time of the policy
   3294     // check and also when setting the delegate socket option. Also, it
   3295     // requires that we zero out the uuid wherever the question is
   3296     // initialized to make sure that it is not interpreted as valid.
   3297     // To prevent these intrusive changes, just pass a zero pid to indicate
   3298     // that pid is not valid when uuid is valid. In future if we need the
   3299     // pid in the question, we will reevaluate this strategy.
   3300     if (req->validUUID)
   3301     {
   3302         mDNSPlatformMemCopy(q->uuid, req->uuid, UUID_SIZE);
   3303         q->pid = 0;
   3304     }
   3305     else
   3306     {
   3307         q->pid = req->process_id;
   3308     }
   3309 
   3310     //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
   3311 }
   3312 
   3313 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
   3314 mDNSlocal CFArrayRef _get_unicast_discovery_dns_services(request_state *info)
   3315 {
   3316     CFArrayRef result = NULL;
   3317     CFMutableArrayRef defArray = NULL;
   3318     mdns_require_action_quiet(info->peer_token, exit, uds_log_error(
   3319         "[R%u] No peer audit token to get unicast discovery IP addresses", info->request_id));
   3320 
   3321     defArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &mdns_cfarray_callbacks);
   3322     require_quiet(defArray, exit);
   3323 
   3324     const audit_token_t *const token = mdns_audit_token_get_token(info->peer_token);
   3325     util_device_media_access_unicast_addr_enumerate(token,
   3326     ^bool(uint8_t family, uint8_t *addr, uint32_t ifindex)
   3327     {
   3328         mdns_dns_service_definition_t definition = NULL;
   3329         require_quiet(addr, exit);
   3330 
   3331         definition = mdns_dns_service_definition_create();
   3332         require_quiet(definition, exit);
   3333 
   3334         mdns_address_t serverAddr;
   3335         if (family == AF_INET) {
   3336             uint32_t ipv4_addr;
   3337             memcpy(&ipv4_addr, addr, sizeof(ipv4_addr));
   3338             serverAddr = mdns_address_create_ipv4(ipv4_addr, mDNSVal16(MulticastDNSPort));
   3339         } else if (family == AF_INET6) {
   3340             uint8_t ipv6_addr[16];
   3341             memcpy(&ipv6_addr, addr, sizeof(ipv6_addr));
   3342             serverAddr = mdns_address_create_ipv6(ipv6_addr, mDNSVal16(MulticastDNSPort), ifindex);
   3343         } else {
   3344             serverAddr = NULL;
   3345         }
   3346         require_quiet(serverAddr, exit);
   3347 
   3348         OSStatus err = mdns_dns_service_definition_append_server_address(definition, serverAddr);
   3349         mdns_forget(&serverAddr);
   3350         require_noerr(err, exit);
   3351 
   3352         mdns_dns_service_definition_set_interface_index(definition, ifindex, true);
   3353 
   3354         CFArrayAppendValue(defArray, definition);
   3355 
   3356     exit:
   3357         mdns_forget(&definition);
   3358         return true;
   3359     });
   3360 
   3361     result = defArray;
   3362     defArray = NULL;
   3363 
   3364 exit:
   3365     STRICT_DISPOSE_CF_OBJECT(defArray);
   3366     return result;
   3367 }
   3368 #endif
   3369 
   3370 mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d)
   3371 {
   3372     browser_t *b, *p;
   3373 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
   3374     __block mStatus err;
   3375 #else
   3376     mStatus err;
   3377 #endif
   3378 
   3379     request_browse *const browse = info->browse;
   3380     for (p = browse->browsers; p; p = p->next)
   3381     {
   3382         if (SameDomainName(&p->domain, d))
   3383         { debugf("add_domain_to_browser %##s already in list", d->c); return mStatus_AlreadyRegistered; }
   3384     }
   3385 
   3386 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
   3387     if (info->sign_result && SameDomainName(d, &localdomain))
   3388     {
   3389         CFArrayRef definitions = _get_unicast_discovery_dns_services(info);
   3390         if (definitions)
   3391         {
   3392             err = mStatus_NoError;
   3393             mdns_cfarray_enumerate(definitions,
   3394             ^ bool (const mdns_dns_service_definition_t definition)
   3395             {
   3396                 const uint32_t ifIndex = mdns_dns_service_definition_get_interface_index(definition);
   3397                 mdns_address_t addr = mdns_dns_service_definition_get_first_address(definition);
   3398                 if (!addr)
   3399                 {
   3400                     return true;
   3401                 }
   3402                 browser_t *ubrowse = (browser_t *) callocL("browser_t", sizeof(*ubrowse));
   3403                 if (!ubrowse)
   3404                 {
   3405                     err = mStatus_NoMemoryErr;
   3406                     return false;
   3407                 }
   3408                 AssignDomainName(&ubrowse->domain, d);
   3409                 SetQuestionPolicy(&ubrowse->q, info);
   3410                 ubrowse->q.request_id = info->request_id; // This browse request is started on behalf of the original browse request.
   3411                 ubrowse->q.UnicastMDNSResolver = mDNSAddr_from_sockaddr(mdns_address_get_sockaddr(addr));
   3412                 mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, ifIndex);
   3413                 err = mDNS_StartBrowse(&mDNSStorage, &ubrowse->q, &browse->regtype, d, InterfaceID, info->flags,
   3414                                         mDNSfalse, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, mDNSNULL, info);
   3415                 if (err)
   3416                 {
   3417                     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   3418                         "[R%u] mDNS_StartBrowse returned error (UNICAST_DISCOVERY) -- "
   3419                         "error: %d, type: " PRI_DM_NAME ", domain: " PRI_DM_NAME,
   3420                         info->request_id, err, DM_NAME_PARAM(&browse->regtype), DM_NAME_PARAM(d));
   3421                     freeL("browser_t/add_domain_to_browser", ubrowse);
   3422                 }
   3423                 else
   3424                 {
   3425                     ubrowse->next = browse->browsers;
   3426                     browse->browsers = ubrowse;
   3427                     LogMcastQ(&ubrowse->q, info, q_start);
   3428                 }
   3429                 return true;
   3430             });
   3431             STRICT_DISPOSE_CF_OBJECT(definitions);
   3432             if (err != mStatus_NoError) return err;
   3433         }
   3434     }
   3435 #endif
   3436 
   3437     b = (browser_t *) callocL("browser_t", sizeof(*b));
   3438     if (!b) return mStatus_NoMemoryErr;
   3439     AssignDomainName(&b->domain, d);
   3440     SetQuestionPolicy(&b->q, info);
   3441     b->q.request_id = info->request_id; // This browse request is started on behalf of the original browse request.
   3442     err = mDNS_StartBrowse(&mDNSStorage, &b->q, &browse->regtype, d, browse->interface_id, info->flags,
   3443         browse->ForceMCast, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, info);
   3444     if (err)
   3445     {
   3446         LogMsg("mDNS_StartBrowse returned %d for type %##s domain %##s", err, browse->regtype.c, d->c);
   3447         freeL("browser_t/add_domain_to_browser", b);
   3448     }
   3449     else
   3450     {
   3451         b->next = browse->browsers;
   3452         browse->browsers = b;
   3453 
   3454 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   3455         if ((info->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) && SameDomainName(d, &localdomain))
   3456         {
   3457             const mDNSBool usesAWDL = ClientRequestUsesAWDL(info->interfaceIndex, info->flags);
   3458             info->powerlog_start_time = mdns_powerlog_browse_start(info->pid_name, usesAWDL);
   3459         }
   3460 #endif
   3461         LogMcastQ(&b->q, info, q_start);
   3462 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   3463         if (callExternalHelpers(browse->interface_id, &b->domain, info->flags))
   3464         {
   3465             domainname tmp;
   3466             ConstructServiceName(&tmp, NULL, &browse->regtype, &b->domain);
   3467             LogDebug("add_domain_to_browser: calling external_start_browsing_for_service()");
   3468             external_start_browsing_for_service(browse->interface_id, &tmp, kDNSType_PTR, info->flags, info->process_id);
   3469         }
   3470 #endif
   3471     }
   3472     return err;
   3473 }
   3474 
   3475 mDNSlocal void browse_termination_callback(request_state *info)
   3476 {
   3477     request_browse *const browse = info->browse;
   3478     if (browse->default_domain)
   3479     {
   3480         UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   3481             "DNSServiceBrowse Cancel domain enumeration for WAB and mDNS", mDNSNULL, info, mDNStrue, "");
   3482         // Stop the domain enumeration queries to discover the WAB legacy browse domains
   3483         uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
   3484 
   3485     #if !TARGET_OS_WATCH // Disable the domain enumeration on watch.
   3486         // Stop the domain enumeration queries to discover the automatic browse domains on the local network.
   3487         mDNS_StopDomainEnumeration(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowseAutomatic);
   3488     #endif
   3489     }
   3490     while (browse->browsers)
   3491     {
   3492         browser_t *ptr = browse->browsers;
   3493 
   3494 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   3495         if (callExternalHelpers(ptr->q.InterfaceID, &ptr->domain, ptr->q.flags))
   3496         {
   3497             domainname tmp;
   3498             ConstructServiceName(&tmp, NULL, &browse->regtype, &ptr->domain);
   3499             external_stop_browsing_for_service(ptr->q.InterfaceID, &tmp, kDNSType_PTR, ptr->q.flags, info->process_id);
   3500         }
   3501 #endif
   3502 
   3503         UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "DNSServiceBrowse STOP", &ptr->q.qname,
   3504             info, mDNStrue, "service name: " PRI_DM_NAME, DM_NAME_PARAM(&ptr->q.qname));
   3505 
   3506         browse->browsers = ptr->next;
   3507         mDNS_StopBrowse(&mDNSStorage, &ptr->q);  // no need to error-check result
   3508         LogMcastQ(&ptr->q, info, q_stop);
   3509         freeL("browser_t/browse_termination_callback", ptr);
   3510     }
   3511 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   3512     if (info->powerlog_start_time != 0)
   3513     {
   3514         const mDNSBool usesAWDL = ClientRequestUsesAWDL(info->interfaceIndex, info->flags);
   3515         mdns_powerlog_browse_stop(info->pid_name, info->powerlog_start_time, usesAWDL);
   3516         info->powerlog_start_time = 0;
   3517     }
   3518 #endif
   3519 }
   3520 
   3521 mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *const d, const mDNSBool add)
   3522 {
   3523     request_state *request;
   3524     debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c);
   3525 
   3526     for (request = all_requests; request; request = request->next)
   3527     {
   3528         if (request->terminate != browse_termination_callback) continue;    // Not a browse operation
   3529         if (!request->browse->default_domain) continue;                   // Not an auto-browse operation
   3530         if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
   3531         {
   3532             browser_t **ptr = &request->browse->browsers;
   3533             while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
   3534             if (add)
   3535             {
   3536                 // If we don't already have this domain in our list for this browse operation, add it now
   3537                 if (!*ptr) add_domain_to_browser(request, &d->name);
   3538                 else debugf("udsserver_automatic_browse_domain_changed %##s already in list, not re-adding", &d->name);
   3539             }
   3540             else
   3541             {
   3542                 if (!*ptr) LogMsg("udsserver_automatic_browse_domain_changed ERROR %##s not found", &d->name);
   3543                 else
   3544                 {
   3545                     DNameListElem *p;
   3546                     for (p = AutoBrowseDomains; p; p=p->next)
   3547                         if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
   3548                             if (SameDomainName(&d->name, &p->name)) break;
   3549                     if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
   3550                     else
   3551                     {
   3552                         browser_t *rem = *ptr;
   3553                         *ptr = (*ptr)->next;
   3554                         mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
   3555                         freeL("browser_t/udsserver_automatic_browse_domain_changed", rem);
   3556                     }
   3557                 }
   3558             }
   3559         }
   3560     }
   3561 }
   3562 
   3563 mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
   3564 {
   3565     (void)m;  // unused
   3566     if (result == mStatus_MemFree)
   3567     {
   3568         // On shutdown, mDNS_Close automatically deregisters all records
   3569         // Since in this case no one has called DeregisterLocalOnlyDomainEnumPTR to cut the record
   3570         // from the LocalDomainEnumRecords list, we do this here before we free the memory.
   3571         // (This should actually no longer be necessary, now that we do the proper cleanup in
   3572         // udsserver_exit. To confirm this, we'll log an error message if we do find a record that
   3573         // hasn't been cut from the list yet. If these messages don't appear, we can delete this code.)
   3574         ARListElem **ptr = &LocalDomainEnumRecords;
   3575         while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
   3576         if (*ptr)
   3577         {
   3578             *ptr = (*ptr)->next;
   3579             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "FreeARElemCallback: Have to cut " PRI_S, ARDisplayString(m, rr));
   3580         }
   3581         mDNSPlatformMemFree(rr->RecordContext);
   3582     }
   3583 }
   3584 
   3585 // RegisterLocalOnlyDomainEnumPTR and DeregisterLocalOnlyDomainEnumPTR largely duplicate code in
   3586 // "FoundDomain" in uDNS.c for creating and destroying these special mDNSInterface_LocalOnly records.
   3587 // We may want to turn the common code into a subroutine.
   3588 
   3589 mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
   3590 {
   3591     // allocate/register legacy and non-legacy _browse PTR record
   3592     mStatus err;
   3593     ARListElem *ptr = (ARListElem *) mDNSPlatformMemAllocateClear(sizeof(*ptr));
   3594 
   3595     debugf("Incrementing %s refcount for %##s",
   3596            (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
   3597            (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
   3598            (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
   3599 
   3600     mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, ptr);
   3601     MakeDomainNameFromDNSNameString(&ptr->ar.namestorage, mDNS_DomainTypeNames[type]);
   3602     AppendDNSNameString            (&ptr->ar.namestorage, "local");
   3603     AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
   3604     err = mDNS_Register(m, &ptr->ar);
   3605     if (err)
   3606     {
   3607         LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
   3608         mDNSPlatformMemFree(ptr);
   3609     }
   3610     else
   3611     {
   3612         ptr->next = LocalDomainEnumRecords;
   3613         LocalDomainEnumRecords = ptr;
   3614     }
   3615 }
   3616 
   3617 mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
   3618 {
   3619     DeregisterLocalOnlyDomainEnumPTR_Internal(m, d, type, mDNSfalse);
   3620 }
   3621 
   3622 mDNSexport void DeregisterLocalOnlyDomainEnumPTR_Internal(mDNS *const m, const domainname *const d, const int type,
   3623     const mDNSBool LockHeld)
   3624 {
   3625     ARListElem **ptr = &LocalDomainEnumRecords;
   3626     domainname lhs; // left-hand side of PTR, for comparison
   3627 
   3628     debugf("Decrementing %s refcount for %##s",
   3629            (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
   3630            (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
   3631            (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
   3632 
   3633     MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
   3634     AppendDNSNameString            (&lhs, "local");
   3635 
   3636     while (*ptr)
   3637     {
   3638         if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
   3639         {
   3640             ARListElem *rem = *ptr;
   3641             *ptr = (*ptr)->next;
   3642             if (LockHeld)
   3643             {
   3644                 mDNS_Deregister_internal(m, &rem->ar, mDNS_Dereg_normal);
   3645             }
   3646             else
   3647             {
   3648                 mDNS_Deregister(m, &rem->ar);
   3649             }
   3650             return;
   3651         }
   3652         else ptr = &(*ptr)->next;
   3653     }
   3654 }
   3655 
   3656 mDNSlocal DNameListElem * FindDNameListElem(const mDNSu32 uid, const domainname *const name, DNameListElem *domains)
   3657 {
   3658     DNameListElem *domain = NULL;
   3659     for (domain = domains; domain != NULL; domain = domain->next)
   3660     {
   3661         if (SameDomainName(name, &domain->name) && domain->uid == uid)
   3662         {
   3663             break;
   3664         }
   3665     }
   3666 
   3667     return domain;
   3668 }
   3669 
   3670 mDNSlocal void AddAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
   3671 {
   3672     DNameListElem *new = FindDNameListElem(uid, name, AutoBrowseDomains);
   3673     if (new != NULL)
   3674     {
   3675         return;
   3676     }
   3677 
   3678     new = (DNameListElem *) mDNSPlatformMemAllocateClear(sizeof(*new));
   3679     if (new == NULL)
   3680     {
   3681         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "mDNSPlatformMemAllocateClear failed");
   3682         return;
   3683     }
   3684 
   3685     AssignDomainName(&new->name, name);
   3686     new->uid = uid;
   3687     new->next = AutoBrowseDomains;
   3688     AutoBrowseDomains = new;
   3689     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Automatic browsing domain is added - "
   3690         "domain name: " PRI_DM_NAME ", uid: %u", DM_NAME_PARAM(name), uid);
   3691 
   3692     udsserver_automatic_browse_domain_changed(new, mDNStrue);
   3693 }
   3694 
   3695 mDNSlocal void RmvAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
   3696 {
   3697     DNameListElem **p = &AutoBrowseDomains;
   3698     while (*p && (!SameDomainName(&(*p)->name, name) || (*p)->uid != uid)) p = &(*p)->next;
   3699     if (!*p) LogMsg("RmvAutoBrowseDomain: Got remove event for domain %##s not in list", name->c);
   3700     else
   3701     {
   3702         DNameListElem *ptr = *p;
   3703         *p = ptr->next;
   3704         udsserver_automatic_browse_domain_changed(ptr, mDNSfalse);
   3705         mDNSPlatformMemFree(ptr);
   3706         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Automatic browsing domain is removed - "
   3707             "domain name: " PRI_DM_NAME ", uid: %u", DM_NAME_PARAM(name), uid);
   3708     }
   3709 }
   3710 
   3711 mDNSlocal void SetPrefsBrowseDomains(mDNS *m, DNameListElem *browseDomains, mDNSBool add)
   3712 {
   3713     DNameListElem *d;
   3714     for (d = browseDomains; d; d = d->next)
   3715     {
   3716         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   3717             "SetPrefsBrowseDomains is adding/removing domain for Browsing and Automatic Browsing domains - "
   3718             "domain name: " PRI_DM_NAME ", uid: %u, result: " PUB_S, DM_NAME_PARAM(&d->name), d->uid,
   3719             add ? "add" : "remove");
   3720         if (add)
   3721         {
   3722             RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
   3723             // This AddAutoBrowseDomain() is a little bit different with the one in AutomaticBrowseDomainChange(),
   3724             // AutomaticBrowseDomainChange() adds automatic browsing domains with uid 0. Then the added domains can be
   3725             // used by any other browse requests. However, AppendDNameListElem() will also append DNameListElem into
   3726             // browseDomains list with uid == 0, which means the AddAutoBrowseDomain() below will:
   3727             // 1. Add domain with uid == 0, which will add duplicate domains into list.
   3728             // 2. Add domain with uid != 0, which is the valid case we want to handle here.
   3729             // When uid == 0, we should call RegisterLocalOnlyDomainEnumPTR() instead of AddAutoBrowseDomain().
   3730             if (d->uid != 0)
   3731             {
   3732                 // The automatic browsing domain is added on behave of the user, which means only the same user that
   3733                 // registers the record should be able to browse under this domain. All the browse requests started by
   3734                 // other user(different uid) should not see this browsing domain.
   3735                 AddAutoBrowseDomain(d->uid, &d->name);
   3736             }
   3737             else
   3738             {
   3739                 // Notify AutomaticBrowseDomainChange() to call AddAutoBrowseDomain(0, &d->name); after checking for
   3740                 // duplicates.
   3741                 RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowseAutomatic);
   3742             }
   3743         }
   3744         else
   3745         {
   3746             DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
   3747             if (d->uid != 0)
   3748             {
   3749                 RmvAutoBrowseDomain(d->uid, &d->name);
   3750             }
   3751             else
   3752             {
   3753                 // Notify AutomaticBrowseDomainChange() to call RmvAutoBrowseDomain(0, &d->name); after checking
   3754                 // for duplicates.
   3755                 DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowseAutomatic);
   3756             }
   3757         }
   3758     }
   3759 }
   3760 
   3761 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
   3762 {
   3763     (void)m; // unused
   3764 }
   3765 
   3766 mDNSexport void udsserver_handle_configchange(mDNS *const m)
   3767 {
   3768     request_state *req;
   3769     service_instance *ptr;
   3770     DNameListElem *RegDomains = NULL;
   3771     DNameListElem *BrowseDomains = NULL;
   3772     DNameListElem *p;
   3773 
   3774     UpdateDeviceInfoRecord(m);
   3775 
   3776     // For autoname services, see if the default service name has changed, necessitating an automatic update
   3777     for (req = all_requests; req; req = req->next)
   3778     {
   3779         if (req->terminate == regservice_termination_callback)
   3780         {
   3781             request_servicereg *const servicereg = req->servicereg;
   3782             if (servicereg->autoname && !SameDomainLabelCS(servicereg->name.c, m->nicelabel.c))
   3783             {
   3784                 servicereg->name = m->nicelabel;
   3785                 for (ptr = servicereg->instances; ptr; ptr = ptr->next)
   3786                 {
   3787                     ptr->renameonmemfree = 1;
   3788                     if (ptr->clientnotified) SendServiceRemovalNotification(&ptr->srs);
   3789                     LogInfo("udsserver_handle_configchange: Calling deregister for Service %##s", ptr->srs.RR_PTR.resrec.name->c);
   3790                     if (mDNS_DeregisterService_drt(m, &ptr->srs, mDNS_Dereg_rapid))
   3791                         regservice_callback(m, &ptr->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
   3792                 }
   3793             }
   3794         }
   3795     }
   3796     // Let the platform layer get the current DNS information
   3797     mDNS_Lock(m);
   3798     mDNSPlatformSetDNSConfig(mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains, mDNSfalse);
   3799     mDNS_Unlock(m);
   3800 
   3801     // Any automatic registration domains are also implicitly automatic browsing domains
   3802     if (RegDomains) SetPrefsBrowseDomains(m, RegDomains, mDNStrue);                             // Add the new list first
   3803     if (AutoRegistrationDomains) SetPrefsBrowseDomains(m, AutoRegistrationDomains, mDNSfalse);  // Then clear the old list
   3804 
   3805     // Add any new domains not already in our AutoRegistrationDomains list
   3806     for (p=RegDomains; p; p=p->next)
   3807     {
   3808         DNameListElem **pp = &AutoRegistrationDomains;
   3809         while (*pp && ((*pp)->uid != p->uid || !SameDomainName(&(*pp)->name, &p->name))) pp = &(*pp)->next;
   3810         if (!*pp)       // If not found in our existing list, this is a new default registration domain
   3811         {
   3812             RegisterLocalOnlyDomainEnumPTR(m, &p->name, mDNS_DomainTypeRegistration);
   3813             udsserver_default_reg_domain_changed(p, mDNStrue);
   3814         }
   3815         else            // else found same domainname in both old and new lists, so no change, just delete old copy
   3816         {
   3817             DNameListElem *del = *pp;
   3818             *pp = (*pp)->next;
   3819             mDNSPlatformMemFree(del);
   3820         }
   3821     }
   3822 
   3823     // Delete any domains in our old AutoRegistrationDomains list that are now gone
   3824     while (AutoRegistrationDomains)
   3825     {
   3826         DNameListElem *del = AutoRegistrationDomains;
   3827         AutoRegistrationDomains = AutoRegistrationDomains->next;        // Cut record from list FIRST,
   3828         DeregisterLocalOnlyDomainEnumPTR(m, &del->name, mDNS_DomainTypeRegistration);
   3829         udsserver_default_reg_domain_changed(del, mDNSfalse);           // before calling udsserver_default_reg_domain_changed()
   3830         mDNSPlatformMemFree(del);
   3831     }
   3832 
   3833     // Now we have our new updated automatic registration domain list
   3834     AutoRegistrationDomains = RegDomains;
   3835 
   3836     // Add new browse domains to internal list
   3837     if (BrowseDomains) SetPrefsBrowseDomains(m, BrowseDomains, mDNStrue);
   3838 
   3839     // Remove old browse domains from internal list
   3840     if (SCPrefBrowseDomains)
   3841     {
   3842         SetPrefsBrowseDomains(m, SCPrefBrowseDomains, mDNSfalse);
   3843         while (SCPrefBrowseDomains)
   3844         {
   3845             DNameListElem *fptr = SCPrefBrowseDomains;
   3846             SCPrefBrowseDomains = SCPrefBrowseDomains->next;
   3847             mDNSPlatformMemFree(fptr);
   3848         }
   3849     }
   3850 
   3851     // Replace the old browse domains array with the new array
   3852     SCPrefBrowseDomains = BrowseDomains;
   3853 }
   3854 
   3855 mDNSexport void FoundNonLocalOnlyAutomaticBrowseDomain(mDNS *const m, DNSQuestion *const q,
   3856     const ResourceRecord *const answer, const QC_result add_record)
   3857 {
   3858     (void)q; // unused
   3859     // Only accepts response from network.
   3860     if (answer->InterfaceID == mDNSInterface_BLE || answer->InterfaceID == mDNSInterface_P2P
   3861         || answer->InterfaceID == mDNSInterface_LocalOnly)
   3862     {
   3863         goto exit;
   3864     }
   3865     if (add_record != QC_add && add_record != QC_rmv)
   3866     {
   3867         goto exit;
   3868     }
   3869     if (answer->RecordType == kDNSRecordTypePacketNegative)
   3870     {
   3871         goto exit;
   3872     }
   3873 
   3874     const domainname *const name = &answer->rdata->u.name;
   3875 
   3876     if (add_record)
   3877     {
   3878         RegisterLocalOnlyDomainEnumPTR(m, name, mDNS_DomainTypeBrowseAutomatic);
   3879 
   3880         mDNS_AddDomainDiscoveredForDomainEnumeration(m, &localdomain, mDNS_DomainTypeBrowseAutomatic, name);
   3881     }
   3882     else
   3883     {
   3884         DeregisterLocalOnlyDomainEnumPTR(m, name, mDNS_DomainTypeBrowseAutomatic);
   3885 
   3886         mDNS_RemoveDomainDiscoveredForDomainEnumeration(m, &localdomain, mDNS_DomainTypeBrowseAutomatic, name);
   3887     }
   3888 
   3889     const char *const if_name = InterfaceNameForID(m, answer->InterfaceID);
   3890     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Automatic browsing domain discovered via network - "
   3891         "change: " PUB_S ", interface name: " PUB_S ", browsing domain: " PRI_DM_NAME,
   3892         add_record == QC_add ? "added" : "removed", if_name, DM_NAME_PARAM(name));
   3893 
   3894 exit:
   3895     return;
   3896 }
   3897 
   3898 mDNSlocal void AutomaticBrowseDomainChange(mDNS *const m, DNSQuestion *q, const ResourceRecord *const answer,
   3899     QC_result AddRecord)
   3900 {
   3901     (void)m; // unused
   3902     (void)q; // unused
   3903 
   3904     const mDNSBool ignored = (answer->InterfaceID == mDNSInterface_Any);
   3905     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Automatic browsing domain changes - "
   3906         "name: " PRI_DM_NAME ", event: " PUB_S ", interface ID: %p" PUB_S, DM_NAME_PARAM(&answer->rdata->u.name),
   3907         AddRecord == QC_add ? "adding" : "removing", answer->InterfaceID, ignored ? ", ignored." : ".");
   3908 
   3909     if (ignored)
   3910     {
   3911         return;
   3912     }
   3913 
   3914     if (AddRecord) AddAutoBrowseDomain(0, &answer->rdata->u.name);
   3915     else RmvAutoBrowseDomain(0, &answer->rdata->u.name);
   3916 
   3917 #if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
   3918     // We also start the local DNS resolver discovery if the automatic browsing domain discovered is a unicast domain
   3919     // where we can do discovery via Do53.
   3920     if (!IsRootDomain(Do53_UNICAST_DISCOVERY_DOMAIN) &&
   3921         SameDomainName(&answer->rdata->u.name, Do53_UNICAST_DISCOVERY_DOMAIN))
   3922     {
   3923         // AutomaticBrowseDomainChange() is called as a callback function where the mDNS_Lock is dropped, to start the
   3924         // resolver discovery process, we need to grab the mDNS_Lock again.
   3925         if (AddRecord == QC_add) {
   3926             resolver_discovery_add(Do53_UNICAST_DISCOVERY_DOMAIN, mDNStrue);
   3927         } else {
   3928             resolver_discovery_remove(Do53_UNICAST_DISCOVERY_DOMAIN, mDNStrue);
   3929         }
   3930     }
   3931 #endif
   3932 }
   3933 
   3934 mDNSlocal mStatus _handle_browse_request_start(request_state *request, const char *domain)
   3935 {
   3936     domainname d;
   3937     mStatus err = mStatus_NoError;
   3938 
   3939     request->terminate = browse_termination_callback;
   3940 
   3941     if (domain[0])
   3942     {
   3943         if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
   3944         err = add_domain_to_browser(request, &d);
   3945     }
   3946     else
   3947     {
   3948         DNameListElem *sdom;
   3949         for (sdom = AutoBrowseDomains; sdom; sdom = sdom->next)
   3950             if (!sdom->uid || SystemUID(request->uid) || request->uid == sdom->uid)
   3951             {
   3952                 err = add_domain_to_browser(request, &sdom->name);
   3953                 if (err)
   3954                 {
   3955                     if (SameDomainName(&sdom->name, &localdomain)) break;
   3956                     else err = mStatus_NoError;  // suppress errors for non-local "default" domains
   3957                 }
   3958             }
   3959     }
   3960 
   3961     return(err);
   3962 }
   3963 
   3964 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   3965 
   3966 mDNSlocal void _return_browse_request_error(request_state *request, mStatus error)
   3967 {
   3968     reply_state *rep;
   3969 
   3970     GenerateBrowseReply(NULL, 0, request, &rep, browse_reply_op, 0, error);
   3971 
   3972     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   3973            "[R%d] DNSServiceBrowse _return_browse_request_error: error (%d)", request->request_id, error);
   3974 
   3975     append_reply(request, rep);
   3976 }
   3977 
   3978 mDNSlocal mStatus _handle_browse_request_with_trust(request_state *request, const char * domain)
   3979 {
   3980     mStatus err;
   3981     if (!request->peer_token)
   3982     {
   3983         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_WARNING, "[R%u] _handle_browse_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   3984         err = _handle_browse_request_start(request, domain);
   3985     }
   3986     else
   3987     {
   3988         char typestr[MAX_ESCAPED_DOMAIN_NAME];
   3989         typestr[0] = 0;
   3990         domainlabel dName;
   3991         domainname dType, dDomain;
   3992         const request_browse *const browse = request->browse;
   3993         if (DeconstructServiceName(&browse->regtype, &dName, &dType, &dDomain))
   3994         {
   3995             ConvertDomainNameToCString(&dType, typestr);
   3996         }
   3997         else
   3998         {
   3999             ConvertDomainNameToCString(&browse->regtype, typestr);
   4000         }
   4001 
   4002         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   4003         mdns_trust_flags_t flags = mdns_trust_flags_none;
   4004         mdns_trust_status_t status = mdns_trust_check_bonjour(*token, typestr, &flags);
   4005 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4006         if ((flags & mdns_trust_flags_system_privileged) != mdns_trust_flags_system_privileged)
   4007         {
   4008             request->sign_result = mDNSfalse; // Reset this flag if not system privileged
   4009         }
   4010         if ((flags & mdns_trust_flags_media_discovery_entitlement) == mdns_trust_flags_media_discovery_entitlement)
   4011         {
   4012             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG,
   4013                 "[R%u] _handle_browse_request_with_trust: has media discovery entitlement", request->request_id);
   4014             request->sign_result = mDNStrue; // Always sign results for media discovery entitlement
   4015         }
   4016 #endif
   4017         switch (status)
   4018         {
   4019             case mdns_trust_status_denied:
   4020             case mdns_trust_status_pending:
   4021             {
   4022                 if (!_prepare_trusts_for_request(request))
   4023                 {
   4024                     err = mStatus_NoMemoryErr;
   4025                     goto exit;
   4026                 }
   4027                 mdns_trust_t trust = mdns_trust_create(*token, typestr, flags);
   4028                 if (!trust )
   4029                 {
   4030                     err = mStatus_NoMemoryErr;
   4031                     goto exit;
   4032                 }
   4033 
   4034                 size_t len = strlen(domain) + 1;
   4035                 void * context = mallocL("context/_handle_browse_request_with_trust", len);
   4036                 if (!context)
   4037                 {
   4038                     my_perror("ERROR: mallocL context/_handle_browse_request_with_trust");
   4039                     mdns_release(trust);
   4040                     err = mStatus_NoMemoryErr;
   4041                     goto exit;
   4042                 }
   4043                 memcpy(context, domain, len);
   4044                 mdns_trust_set_context(trust, context);
   4045                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   4046                 {
   4047                     freeL("context/_handle_browse_request_with_trust finalizer", ref);
   4048                 });
   4049                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   4050                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   4051                 {
   4052                     if (event == mdns_trust_event_result)
   4053                     {
   4054                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   4055                         KQueueLock();
   4056                         const char * _domain = mdns_trust_get_context(trust);
   4057                         if (_domain)
   4058                         {
   4059                             if (!error)
   4060                             {
   4061                                 error = _handle_browse_request_start(request, _domain);
   4062                                 // No context means the request was canceled before we got here
   4063                             }
   4064                             if (error) // (not else if) Always check for error result
   4065                             {
   4066                                 _return_browse_request_error(request, error);
   4067                             }
   4068                         }
   4069                         KQueueUnlock("_handle_browse_request_with_trust");
   4070                     }
   4071                 });
   4072                 CFArrayAppendValue(request->trusts, trust);
   4073                 mdns_release(trust);
   4074                 mdns_trust_activate(trust);
   4075                 err = mStatus_NoError;
   4076                 break;
   4077             }
   4078 
   4079             case mdns_trust_status_no_entitlement:
   4080                 err = mStatus_NoAuth;
   4081                 break;
   4082 
   4083             case mdns_trust_status_granted:
   4084                 err = _handle_browse_request_start(request, domain);
   4085                 break;
   4086 
   4087             MDNS_COVERED_SWITCH_DEFAULT:
   4088                 err = mStatus_UnknownErr;
   4089         }
   4090     }
   4091 exit:
   4092     return err;
   4093 }
   4094 #endif // TRUST_ENFORCEMENT
   4095 
   4096 mDNSlocal mStatus handle_browse_request(request_state *request)
   4097 {
   4098     // Note that regtype may include a trailing subtype
   4099     char regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
   4100     domainname typedn, temp;
   4101     mDNSs32 NumSubTypes;
   4102     mStatus err = mStatus_NoError;
   4103 
   4104     if (!request->browse)
   4105     {
   4106         request->browse = (request_browse *)callocL("request_browse", sizeof(*request->browse));
   4107         mdns_require_action_quiet(request->browse, exit, err = mStatus_NoMemoryErr; uds_log_error(
   4108             "[R%u] Failed to allocate memory for browse request", request->request_id));
   4109     }
   4110     DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
   4111     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   4112     mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   4113 
   4114     // The browse is scoped to a specific interface index, but the
   4115     // interface is not currently in our list.
   4116     if (interfaceIndex && !InterfaceID)
   4117     {
   4118         // If it's one of the specially defined inteface index values, just return an error.
   4119         if (PreDefinedInterfaceIndex(interfaceIndex))
   4120         {
   4121             LogInfo("handle_browse_request: bad interfaceIndex %d", interfaceIndex);
   4122             return(mStatus_BadParamErr);
   4123         }
   4124 
   4125         // Otherwise, use the specified interface index value and the browse will
   4126         // be applied to that interface when it comes up.
   4127         InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
   4128         LogInfo("handle_browse_request: browse pending for interface index %d", interfaceIndex);
   4129     }
   4130 
   4131     if (get_string(&request->msgptr, request->msgend, regtype, sizeof(regtype)) < 0 ||
   4132         get_string(&request->msgptr, request->msgend, domain,  sizeof(domain )) < 0) return(mStatus_BadParamErr);
   4133 
   4134     if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
   4135 
   4136 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4137     err = get_signed_result_flags_tlvs(request);
   4138     if (err) { LogMsg("%3d: handle_browse_request err reading Validation TLVS", request->sd); return(err); }
   4139 #endif
   4140 
   4141     request->flags = flags;
   4142     request->interfaceIndex = interfaceIndex;
   4143     typedn.c[0] = 0;
   4144     NumSubTypes = ChopSubTypes(regtype);    // Note: Modifies regtype string to remove trailing subtypes
   4145     if (NumSubTypes < 0 || NumSubTypes > 1)
   4146         return(mStatus_BadParamErr);
   4147     if (NumSubTypes == 1)
   4148     {
   4149         if (!AppendDNSNameString(&typedn, regtype + strlen(regtype) + 1))
   4150             return(mStatus_BadParamErr);
   4151     }
   4152 
   4153     if (!regtype[0] || !AppendDNSNameString(&typedn, regtype)) return(mStatus_BadParamErr);
   4154 
   4155     if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr);
   4156     // For over-long service types, we only allow domain "local"
   4157     if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain));
   4158 
   4159     // Set up browse info
   4160     request_browse *const browse = request->browse;
   4161     browse->ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
   4162     browse->interface_id = InterfaceID;
   4163     AssignDomainName(&browse->regtype, &typedn);
   4164     browse->default_domain = !domain[0];
   4165     browse->browsers = NULL;
   4166 
   4167     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   4168         "DNSServiceBrowse START", mDNSNULL, request, mDNSfalse, "service type: " PRI_DM_NAME ", domain: " PRI_S,
   4169         DM_NAME_PARAM(&browse->regtype), domain);
   4170 
   4171     if (browse->default_domain)
   4172     {
   4173         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%u] DNSServiceBrowse Start domain enumeration for WAB and mDNS "
   4174             "PID[%d](" PUB_S ")", request->request_id, request->process_id, request->pid_name);
   4175         // Start the domain enumeration queries to discover the WAB browse domains
   4176         uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
   4177 
   4178     #if !TARGET_OS_WATCH // Disable the domain enumeration on watch.
   4179         // Start the domain enumeration queries to discover the automatic browse domains on the local network.
   4180         mDNS_StartDomainEnumeration(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowseAutomatic);
   4181     #endif
   4182     }
   4183     // We need to unconditionally set request->terminate, because even if we didn't successfully
   4184     // start any browses right now, subsequent configuration changes may cause successful
   4185     // browses to be added, and we'll need to cancel them before freeing this memory.
   4186     request->terminate = NULL;
   4187 
   4188 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   4189     domainname d;
   4190     if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
   4191 
   4192     if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
   4193         (browse->default_domain || IsLocalDomain(&d) || browse->ForceMCast))
   4194     {
   4195         err = _handle_browse_request_with_trust(request, domain);
   4196     }
   4197     else
   4198     {
   4199         err = _handle_browse_request_start(request, domain);
   4200     }
   4201 #else
   4202     err = _handle_browse_request_start(request, domain);
   4203 #endif
   4204 
   4205 exit:
   4206     return(err);
   4207 }
   4208 
   4209 // ***************************************************************************
   4210 // MARK: - DNSServiceResolve
   4211 
   4212 mDNSlocal void resolve_termination_callback(request_state *request)
   4213 {
   4214     request_resolve *const resolve = request->resolve;
   4215 
   4216     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   4217         "DNSServiceResolve STOP",
   4218         &resolve->qtxt.qname, request, mDNStrue, "SRV name: " PRI_DM_NAME, DM_NAME_PARAM_NONNULL(&resolve->qtxt.qname));
   4219 
   4220     mDNS_StopQuery(&mDNSStorage, &resolve->qtxt);
   4221     mDNS_StopQuery(&mDNSStorage, &resolve->qsrv);
   4222     LogMcastQ(&resolve->qsrv, request, q_stop);
   4223 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   4224     if (resolve->external_advertise)
   4225     {
   4226         external_stop_resolving_service(resolve->qsrv.InterfaceID, &resolve->qsrv.qname, request->flags, request->process_id);
   4227     }
   4228 #endif
   4229 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   4230     if (request->powerlog_start_time != 0)
   4231     {
   4232         const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   4233         mdns_powerlog_resolve_stop(request->pid_name, request->powerlog_start_time, usesAWDL);
   4234         request->powerlog_start_time = 0;
   4235     }
   4236 #endif
   4237 }
   4238 
   4239 typedef struct {
   4240     char            regtype[MAX_ESCAPED_DOMAIN_NAME];
   4241     domainname      fqdn;
   4242     mDNSInterfaceID InterfaceID;
   4243 } _resolve_start_params_t;
   4244 
   4245 mDNSlocal mStatus _handle_resolve_request_start(request_state *const request, const _resolve_start_params_t *const params)
   4246 {
   4247     mStatus err;
   4248 
   4249     request_resolve *const resolve = request->resolve;
   4250     err = mDNS_StartQuery(&mDNSStorage, &resolve->qsrv);
   4251 
   4252     if (!err)
   4253     {
   4254         err = mDNS_StartQuery(&mDNSStorage, &resolve->qtxt);
   4255         if (err)
   4256         {
   4257             mDNS_StopQuery(&mDNSStorage, &resolve->qsrv);
   4258         }
   4259         else
   4260         {
   4261             request->terminate = resolve_termination_callback;
   4262         #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   4263             if ((request->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) && IsLocalDomain(&params->fqdn))
   4264             {
   4265                 const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   4266                 request->powerlog_start_time = mdns_powerlog_resolve_start(request->pid_name, usesAWDL);
   4267             }
   4268         #endif
   4269             LogMcastQ(&resolve->qsrv, request, q_start);
   4270         #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
   4271             if (callExternalHelpers(params->InterfaceID, &params->fqdn, request->flags))
   4272             {
   4273                 resolve->external_advertise    = mDNStrue;
   4274                 LogInfo("handle_resolve_request: calling external_start_resolving_service()");
   4275                 external_start_resolving_service(params->InterfaceID, &params->fqdn, request->flags, request->process_id);
   4276             }
   4277         #else
   4278             (void)params;
   4279         #endif
   4280         }
   4281     }
   4282     return err;
   4283 }
   4284 
   4285 mDNSlocal void resolve_result_forget_srv(request_resolve *const resolve)
   4286 {
   4287     mDNSPlatformMemForget(&resolve->srv_target_name);
   4288     resolve->srv_port = zeroIPPort;
   4289     resolve->srv_negative = mDNSfalse;
   4290 }
   4291 
   4292 mDNSlocal void resolve_result_forget_txt(request_resolve *const resolve)
   4293 {
   4294     mDNSPlatformMemForget(&resolve->txt_rdata);
   4295     resolve->txt_rdlength = 0;
   4296     resolve->txt_negative = mDNSfalse;
   4297 }
   4298 
   4299 mDNSlocal void resolve_result_finalize(request_resolve *resolve)
   4300 {
   4301     mDNSPlatformMemForget(&resolve->srv_target_name);
   4302     mDNSPlatformMemForget(&resolve->txt_rdata);
   4303     freeL("request_resolve/request_state_forget", resolve);
   4304 }
   4305 
   4306 mDNSlocal mDNSBool resolve_result_is_complete(const request_resolve *const resolve)
   4307 {
   4308     // Positive and negative answers are both considered "completed responses"
   4309     const mDNSBool got_srv = (resolve->srv_negative || resolve->srv_target_name);
   4310     const mDNSBool got_txt = (resolve->txt_negative || resolve->txt_rdata);
   4311     const mDNSBool response_completes = (got_srv && got_txt);
   4312     return response_completes;
   4313 }
   4314 
   4315 mDNSlocal void resolve_result_save_answer(request_resolve *const resolve, const ResourceRecord *const answer,
   4316     const QC_result add_record)
   4317 {
   4318     const mDNSu16 rrtype = answer->rrtype;
   4319 
   4320     // If the record is being removed, in this case, only positive answer will be removed.
   4321     if (!add_record)
   4322     {
   4323         // Clear any positive rdata we held previously
   4324         if (rrtype == kDNSType_SRV)
   4325         {
   4326             resolve_result_forget_srv(resolve);
   4327         }
   4328         else
   4329         {
   4330             resolve_result_forget_txt(resolve);
   4331         }
   4332 
   4333         // For resolve request, we do not deliver remove event to the client.
   4334         return;
   4335     }
   4336 
   4337     // The answer is newly added.
   4338     const mDNSBool negative_answer = (answer->RecordType == kDNSRecordTypePacketNegative);
   4339     if (rrtype == kDNSType_SRV)
   4340     {
   4341         mDNSPlatformMemForget(&resolve->srv_target_name);
   4342         if (negative_answer)
   4343         {
   4344             resolve->srv_port = zeroIPPort;
   4345             resolve->srv_negative = mDNStrue;
   4346         }
   4347         else
   4348         {
   4349             // Copy the target name and port number from the rdata of the SRV record.
   4350             const domainname *const target_name = &answer->rdata->u.srv.target;
   4351             const mDNSu16 target_name_length = DomainNameLength(target_name);
   4352             mdns_require_return(target_name_length > 0);
   4353 
   4354             resolve->srv_target_name = mDNSPlatformMemAllocateClear(target_name_length);
   4355             mdns_require_return(resolve->srv_target_name);
   4356 
   4357             AssignDomainName(resolve->srv_target_name, target_name);
   4358             resolve->srv_port = answer->rdata->u.srv.port;
   4359             resolve->srv_negative = mDNSfalse;
   4360         }
   4361     }
   4362     else
   4363     {
   4364         mDNSPlatformMemForget(&resolve->txt_rdata);
   4365         if (negative_answer)
   4366         {
   4367             resolve->txt_rdlength = 0;
   4368             resolve->txt_negative = mDNStrue;
   4369         }
   4370         else
   4371         {
   4372             // Copy the rdata of TXT record directly.
   4373             const mDNSu8 *const txt_rdata = answer->rdata->u.data;
   4374             const mDNSu16 txt_rdlength = answer->rdlength;
   4375 
   4376             // MAX(1, txt_rdlength) ensures that resolve->txt_rdata is non-null, when the TXT record rdata length is 0,
   4377             // thus allowing the 0-length TXT to be identified as a positive record.
   4378             // In theory, TXT record should contain "One or more <character-string>s." according to:
   4379             // [TXT RDATA format](https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.14)
   4380             // Here we allow mDNSResponder to return TXT record with a 0 data length.
   4381             resolve->txt_rdata = mDNSPlatformMemAllocateClear(MAX(1, txt_rdlength));
   4382             mdns_require_return(resolve->txt_rdata);
   4383 
   4384             mDNSPlatformMemCopy(resolve->txt_rdata, txt_rdata, txt_rdlength);
   4385             resolve->txt_rdlength = txt_rdlength;
   4386             resolve->txt_negative = mDNSfalse;
   4387         }
   4388     }
   4389 }
   4390 
   4391 mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
   4392 {
   4393     size_t len = 0;
   4394     char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME] = "0";
   4395     uint8_t *data;
   4396     reply_state *rep;
   4397     (void)m; // Unused
   4398 
   4399     request_state *const req = question->QuestionContext;
   4400     const mDNSu32 name_hash = mDNS_DomainNameFNV1aHash(&question->qname);
   4401 
   4402     const mDNSBool isMDNSQuestion = mDNSOpaque16IsZero(question->TargetQID);
   4403     UDS_LOG_ANSWER_EVENT(isMDNSQuestion ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   4404         req, question, answer, mDNSfalse, "DNSServiceResolve result", AddRecord);
   4405 
   4406     const mDNSu16 rrtype = answer->rrtype;
   4407     mdns_require_return((rrtype == kDNSType_SRV) || (rrtype == kDNSType_TXT));
   4408 
   4409     request_resolve *const resolve = req->resolve;
   4410     resolve_result_save_answer(resolve, answer, AddRecord);
   4411     if (!resolve_result_is_complete(resolve))
   4412     {
   4413         // Wait until we have both SRV record and TXT record(either positive or negative).
   4414         return;
   4415     }
   4416 
   4417     // 4 cases:
   4418     // SRV positive, TXT positive -> kDNSServiceErr_NoError
   4419     // SRV negative, TXT positive -> kDNSServiceErr_NoSuchRecord
   4420     // SRV positive, TXT negative -> kDNSServiceErr_NoError
   4421     // SRV negative, TXT negative -> kDNSServiceErr_NoSuchRecord
   4422     // The intuition here is that having positive SRV or not decides whether we are able to use the service.
   4423     // The TXT record only provides auxiliary information about the service.
   4424     const DNSServiceErrorType error = ((resolve->srv_negative) ? kDNSServiceErr_NoSuchRecord : kDNSServiceErr_NoError);
   4425 
   4426     ConvertDomainNameToCString(answer->name, fullname);
   4427 
   4428     // Prepare the data to be returned to the client.
   4429     mDNSu32 target_name_hash = 0;
   4430     if (!resolve->srv_negative)
   4431     {
   4432         const domainname *const srv_target = resolve->srv_target_name;
   4433         const mDNSu16 srv_target_len = DomainNameLength(srv_target);
   4434         ConvertDomainNameToCString(srv_target, target);
   4435         target_name_hash = mDNS_NonCryptoHash(mDNSNonCryptoHash_FNV1a, srv_target->c, srv_target_len);
   4436     }
   4437 
   4438     // We need to return SRV target name, SRV port number and TXT rdata to the client.
   4439     // Set them to the empty data filled with 0 initially.
   4440     const mDNSu8 temp_empty_data[1] = {0};
   4441     const mDNSu8 *srv_target_data = temp_empty_data;
   4442     mDNSIPPort srv_port = {0};
   4443     const mDNSu8 *txt_rdata = temp_empty_data;
   4444     mDNSu16 txt_rdlength = 0;
   4445 
   4446     // If SRV or TXT record is positive, set the pointer to the rdata we have copied before.
   4447     if (!resolve->srv_negative)
   4448     {
   4449         srv_target_data = resolve->srv_target_name->c;
   4450         srv_port = resolve->srv_port;
   4451     }
   4452     if (!resolve->txt_negative)
   4453     {
   4454         txt_rdata = resolve->txt_rdata;
   4455         txt_rdlength = resolve->txt_rdlength;
   4456     }
   4457 
   4458     mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse);
   4459     // calculate reply length
   4460     len += sizeof(DNSServiceFlags);
   4461     len += sizeof(mDNSu32);  // interface index
   4462     len += sizeof(DNSServiceErrorType);
   4463     len += strlen(fullname) + 1;
   4464     len += strlen(target) + 1;
   4465     len += 2 * sizeof(mDNSu16);  // port, txtLen
   4466     len += txt_rdlength;
   4467 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4468     mdns_signed_resolve_result_t signed_result = NULL;
   4469     const uint8_t *signed_data = NULL;
   4470     uint16_t signed_data_length = 0;
   4471     if (req->sign_result && req->signed_obj && AddRecord)
   4472     {
   4473         OSStatus err;
   4474         mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(req->signed_obj);
   4475         if (!browseResult)
   4476         {
   4477             err = mStatus_Invalid;
   4478             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   4479                 "[R%u->Q%u] resolve_result_callback mdns_signed_resolve_result_downcast failed",
   4480                 req->request_id, mDNSVal16(question->TargetQID));
   4481         }
   4482         else
   4483         {
   4484             // If the SRV record is negative, then we will sign rdata filled with zeros.
   4485             signed_result = mdns_signed_resolve_result_create(browseResult, srv_target_data, srv_port.NotAnInteger,
   4486                 interface_index, txt_rdata, txt_rdlength, &err);
   4487         }
   4488         if (!signed_result || err != 0)
   4489         {
   4490             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   4491                 "[R%u->Q%u] resolve_result_callback signed_resolve failed %ld", req->request_id,
   4492                 mDNSVal16(question->TargetQID), (long)err);
   4493         }
   4494         else
   4495         {
   4496             size_t temp_size = 0;
   4497             const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
   4498             if (temp_size <= UINT16_MAX)
   4499             {
   4500                 signed_data = temp_data;
   4501                 signed_data_length = (uint16_t)temp_size;
   4502                 len += get_required_tlv_length(signed_data_length);
   4503             }
   4504         }
   4505     }
   4506 #else
   4507     // To suppress the unused variable warning when `MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)` is disabled.
   4508     (void)srv_target_data;
   4509 #endif
   4510 
   4511     // allocate/init reply header
   4512     rep = create_reply(resolve_reply_op, len, req);
   4513     rep->rhdr->flags = dnssd_htonl(0);
   4514     rep->rhdr->ifi   = dnssd_htonl(interface_index);
   4515     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
   4516 
   4517     data = (uint8_t *)&rep->rhdr[1];
   4518 
   4519     // write reply data to message
   4520     put_string(fullname, &data);
   4521     put_string(target, &data);
   4522     *data++ = srv_port.b[0];
   4523     *data++ = srv_port.b[1];
   4524     put_uint16(txt_rdlength, &data);
   4525     put_rdata(txt_rdlength, txt_rdata, &data);
   4526 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4527     if (signed_data)
   4528     {
   4529         put_signed_result_tlvs(signed_data, signed_data_length, rep->mhdr, &data, data+len);
   4530     }
   4531     mdns_forget(&signed_result);
   4532 #endif
   4533 
   4534     if (error == kDNSServiceErr_NoError)
   4535     {
   4536         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   4537             "[R%d->Q%d] DNSServiceResolve(" PRI_S " (%x)) RESULT   " PRI_S " (%x):%d",
   4538             req->request_id, mDNSVal16(question->TargetQID), fullname, name_hash, target, target_name_hash,
   4539             mDNSVal16(srv_port));
   4540     }
   4541     else
   4542     {
   4543         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   4544             "[R%d->Q%d] DNSServiceResolve(" PRI_S " (%x)) NoSuchRecord",
   4545             req->request_id, mDNSVal16(question->TargetQID), fullname, name_hash);
   4546     }
   4547     append_reply(req, rep);
   4548 }
   4549 
   4550 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   4551 
   4552 mDNSlocal void _return_resolve_request_error(request_state * request, mStatus error)
   4553 {
   4554     size_t len;
   4555     char * emptystr = "\0";
   4556     uint8_t *data;
   4557     reply_state *rep;
   4558 
   4559     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   4560        "[R%u] DNSServiceResolve _return_resolve_request_error: error(%d)", request->request_id, error);
   4561 
   4562     // calculate reply length
   4563     len = sizeof(DNSServiceFlags);
   4564     len += sizeof(mDNSu32);  // interface index
   4565     len += sizeof(DNSServiceErrorType);
   4566     len += 2; // name, target
   4567     len += 2 * sizeof(mDNSu16);  // port, txtLen
   4568     len += 0; //req->u.resolve.txt->rdlength;
   4569 
   4570     rep = create_reply(resolve_reply_op, len, request);
   4571 
   4572     rep->rhdr->flags = 0;
   4573     rep->rhdr->ifi   = 0;
   4574     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
   4575 
   4576     data = (uint8_t *)&rep->rhdr[1];
   4577 
   4578     // write reply data to message
   4579     put_string(emptystr, &data); // name
   4580     put_string(emptystr, &data); // target
   4581     put_uint16(0,        &data); // port
   4582     put_uint16(0,        &data); // txtLen
   4583 
   4584     append_reply(request, rep);
   4585 }
   4586 
   4587 mDNSlocal mStatus _handle_resolve_request_with_trust(request_state *request, const _resolve_start_params_t * const params)
   4588 {
   4589     mStatus err;
   4590     if (!request->peer_token)
   4591     {
   4592         LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_WARNING, "[R%u] _handle_resolve_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   4593         err = _handle_resolve_request_start(request, params);
   4594     }
   4595     else
   4596     {
   4597         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   4598         mdns_trust_flags_t flags = mdns_trust_flags_none;
   4599         mdns_trust_status_t status = mdns_trust_check_bonjour(*token, params->regtype, &flags);
   4600         switch (status)
   4601         {
   4602             case mdns_trust_status_denied:
   4603             case mdns_trust_status_pending:
   4604             {
   4605                 if (!_prepare_trusts_for_request(request))
   4606                 {
   4607                     err = mStatus_NoMemoryErr;
   4608                     goto exit;
   4609                 }
   4610                 mdns_trust_t trust = mdns_trust_create(*token, params->regtype, flags);
   4611                 if (!trust )
   4612                 {
   4613                     err = mStatus_NoMemoryErr;
   4614                     goto exit;
   4615                 }
   4616 
   4617                 void * context = mallocL("context/_handle_resolve_request_with_trust", sizeof(_resolve_start_params_t));
   4618                 if (!context)
   4619                 {
   4620                     my_perror("ERROR: mallocL context/_handle_resolve_request_with_trust");
   4621                     mdns_release(trust);
   4622                     err = mStatus_NoMemoryErr;
   4623                     goto exit;
   4624                 }
   4625                 memcpy(context, params, sizeof(_resolve_start_params_t));
   4626                 mdns_trust_set_context(trust, context);
   4627                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   4628                 {
   4629                     freeL("context/_handle_resolve_request_with_trust finalizer", ref);
   4630                 });
   4631                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   4632                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   4633                 {
   4634                     if (event == mdns_trust_event_result)
   4635                     {
   4636                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   4637                         KQueueLock();
   4638                         _resolve_start_params_t * _params =  mdns_trust_get_context(trust);
   4639                         if (_params)
   4640                         {
   4641                             if (!error)
   4642                             {
   4643                                 error = _handle_resolve_request_start(request, _params);
   4644                                 // No context means the request was canceled before we got here
   4645                             }
   4646                             if (error) // (not else if) Always check for error result
   4647                             {
   4648                                 _return_resolve_request_error(request, error);
   4649                             }
   4650                         }
   4651                         KQueueUnlock("_handle_resolve_request_with_trust");
   4652                     }
   4653                 });
   4654                 CFArrayAppendValue(request->trusts, trust);
   4655                 mdns_release(trust);
   4656                 mdns_trust_activate(trust);
   4657                 err = mStatus_NoError;
   4658                 break;
   4659             }
   4660 
   4661             case mdns_trust_status_no_entitlement:
   4662                 err = mStatus_NoAuth;
   4663                 break;
   4664 
   4665             case mdns_trust_status_granted:
   4666                 err = _handle_resolve_request_start(request, params);
   4667                 break;
   4668 
   4669             MDNS_COVERED_SWITCH_DEFAULT:
   4670                 err = mStatus_UnknownErr;
   4671         }
   4672     }
   4673 exit:
   4674     return err;
   4675 }
   4676 #endif // TRUST_ENFORCEMENT
   4677 
   4678 mDNSlocal mStatus handle_resolve_request(request_state *request)
   4679 {
   4680     char name[256], domain[MAX_ESCAPED_DOMAIN_NAME];
   4681     _resolve_start_params_t params;
   4682     mStatus err;
   4683 
   4684     if (!request->resolve)
   4685     {
   4686         request->resolve = (request_resolve *)callocL("request_resolve", sizeof(*request->resolve));
   4687         mdns_require_action_quiet(request->resolve, exit, err = mStatus_NoMemoryErr; uds_log_error(
   4688             "[R%u] Failed to allocate memory for resolve request", request->request_id));
   4689     }
   4690     // extract the data from the message
   4691     DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
   4692     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   4693 
   4694     // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
   4695     // flag set so that the resolve will run over P2P interfaces that are not yet created.
   4696     if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
   4697     {
   4698         LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
   4699         flags |= kDNSServiceFlagsIncludeP2P;
   4700         interfaceIndex = kDNSServiceInterfaceIndexAny;
   4701     }
   4702 
   4703     params.InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   4704 
   4705     // The operation is scoped to a specific interface index, but the
   4706     // interface is not currently in our list.
   4707     if (interfaceIndex && !params.InterfaceID)
   4708     {
   4709         // If it's one of the specially defined inteface index values, just return an error.
   4710         if (PreDefinedInterfaceIndex(interfaceIndex))
   4711         {
   4712             LogInfo("handle_resolve_request: bad interfaceIndex %d", interfaceIndex);
   4713             return(mStatus_BadParamErr);
   4714         }
   4715 
   4716         // Otherwise, use the specified interface index value and the operation will
   4717         // be applied to that interface when it comes up.
   4718         params.InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
   4719         LogInfo("handle_resolve_request: resolve pending for interface index %d", interfaceIndex);
   4720     }
   4721 
   4722     if (get_string(&request->msgptr, request->msgend, name,           sizeof(name   )) < 0 ||
   4723         get_string(&request->msgptr, request->msgend, params.regtype, sizeof(params.regtype)) < 0 ||
   4724         get_string(&request->msgptr, request->msgend, domain,         sizeof(domain )) < 0)
   4725     { LogMsg("ERROR: handle_resolve_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
   4726 
   4727     if (!request->msgptr) { LogMsg("%3d: DNSServiceResolve(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
   4728 
   4729 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4730     err = get_signed_browse_tlvs(request);
   4731     if (err) { LogMsg("%3d: handle_resolve_request err reading Validation TLVS", request->sd); return(err); }
   4732 #endif
   4733 
   4734     if (build_domainname_from_strings(&params.fqdn, name, params.regtype, domain) < 0)
   4735     { LogMsg("ERROR: handle_resolve_request bad %s %s %s", name, params.regtype, domain); return(mStatus_BadParamErr); }
   4736 
   4737     request->flags = flags;
   4738     request->interfaceIndex = interfaceIndex;
   4739 
   4740     // format questions
   4741     request_resolve *const resolve = request->resolve;
   4742     resolve->qsrv.InterfaceID      = params.InterfaceID;
   4743     resolve->qsrv.flags            = flags;
   4744     AssignDomainName(&resolve->qsrv.qname, &params.fqdn);
   4745     resolve->qsrv.qtype            = kDNSType_SRV;
   4746     resolve->qsrv.qclass           = kDNSClass_IN;
   4747     resolve->qsrv.LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
   4748     resolve->qsrv.ExpectUnique     = mDNStrue;
   4749     resolve->qsrv.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
   4750     resolve->qsrv.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
   4751     resolve->qsrv.SuppressUnusable = mDNSfalse;
   4752     resolve->qsrv.AppendSearchDomains = 0;
   4753     resolve->qsrv.TimeoutQuestion  = 0;
   4754     resolve->qsrv.WakeOnResolve    = (flags & kDNSServiceFlagsWakeOnResolve) != 0;
   4755     resolve->qsrv.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
   4756     resolve->qsrv.ProxyQuestion    = 0;
   4757     resolve->qsrv.pid              = request->process_id;
   4758     resolve->qsrv.euid             = request->uid;
   4759     resolve->qsrv.QuestionCallback = resolve_result_callback;
   4760     resolve->qsrv.QuestionContext  = request;
   4761 
   4762     resolve->qtxt.InterfaceID      = params.InterfaceID;
   4763     resolve->qtxt.flags            = flags;
   4764     AssignDomainName(&resolve->qtxt.qname, &params.fqdn);
   4765     resolve->qtxt.qtype            = kDNSType_TXT;
   4766     resolve->qtxt.qclass           = kDNSClass_IN;
   4767     resolve->qtxt.LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
   4768     resolve->qtxt.ExpectUnique     = mDNStrue;
   4769     resolve->qtxt.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
   4770     resolve->qtxt.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
   4771     resolve->qtxt.SuppressUnusable = mDNSfalse;
   4772     resolve->qtxt.AppendSearchDomains = 0;
   4773     resolve->qtxt.TimeoutQuestion  = 0;
   4774     resolve->qtxt.WakeOnResolve    = 0;
   4775     resolve->qtxt.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
   4776     resolve->qtxt.ProxyQuestion    = 0;
   4777     resolve->qtxt.pid              = request->process_id;
   4778     resolve->qtxt.euid             = request->uid;
   4779     resolve->qtxt.QuestionCallback = resolve_result_callback;
   4780     resolve->qtxt.QuestionContext  = request;
   4781 
   4782     resolve->ReportTime            = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
   4783 
   4784     resolve->external_advertise    = mDNSfalse;
   4785 
   4786 #if 0
   4787     if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains)) return(mStatus_NoError);
   4788 #endif
   4789 
   4790     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "DNSServiceResolve START",
   4791         &resolve->qsrv.qname, request, mDNSfalse, "SRV name: " PRI_DM_NAME, DM_NAME_PARAM(&resolve->qsrv.qname));
   4792 
   4793     request->terminate = NULL;
   4794 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   4795     mDNSBool trust_check_done = mDNSfalse;
   4796 #endif
   4797 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4798     if (request->signed_obj)
   4799     {
   4800         mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(request->signed_obj);
   4801         if (browseResult &&
   4802             mdns_signed_browse_result_contains(browseResult, params.fqdn.c, interfaceIndex))
   4803         {
   4804             if (mdns_system_is_signed_result_uuid_valid(mdns_signed_result_get_uuid(browseResult)))
   4805             {
   4806                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG,
   4807                        "[R%d] DNSServiceResolve: Allowing signed result",
   4808                           request->request_id);
   4809 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   4810                 trust_check_done = mDNStrue;
   4811 #endif
   4812             }
   4813             else
   4814             {
   4815                 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   4816                        "[R%d] DNSServiceResolve: Signed result UUID revoked.",
   4817                           request->request_id);
   4818                 return mStatus_PolicyDenied;
   4819             }
   4820         }
   4821         else
   4822         {
   4823             LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
   4824                 "[R%d] DNSServiceResolve: Signed result does not cover service: " PRI_DM_NAME ", ifindex: %u.",
   4825                 request->request_id, DM_NAME_PARAM(&resolve->qsrv.qname), interfaceIndex);
   4826             request->sign_result = mDNSfalse;
   4827             mdns_forget(&request->signed_obj);
   4828         }
   4829     }
   4830 #endif
   4831 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   4832     domainname d;
   4833     if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
   4834 
   4835     if (!trust_check_done                                   &&
   4836         os_feature_enabled(mDNSResponder, bonjour_privacy)  &&
   4837         (IsLocalDomain(&d) || resolve->qsrv.ForceMCast))
   4838     {
   4839         err = _handle_resolve_request_with_trust(request, &params);
   4840     }
   4841     else
   4842     {
   4843         err = _handle_resolve_request_start(request, &params);
   4844     }
   4845 #else
   4846     err = _handle_resolve_request_start(request, &params);
   4847 #endif
   4848 
   4849 exit:
   4850     return(err);
   4851 }
   4852 
   4853 // ***************************************************************************
   4854 // MARK: - DNSServiceQueryRecord
   4855 
   4856 mDNSlocal void queryrecord_result_reply(mDNS *const m, DNSQuestion *const question, const ResourceRecord *const answer,
   4857     const mDNSBool expired, const QC_result AddRecord, const DNSServiceErrorType error, void *const context)
   4858 {
   4859     char name[MAX_ESCAPED_DOMAIN_NAME];
   4860     size_t len;
   4861     DNSServiceFlags flags = 0;
   4862     reply_state *rep;
   4863     uint8_t *data;
   4864     request_state *req = (request_state *)context;
   4865 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
   4866     bool addTrackerState = (resolved_cache_is_enabled() && AddRecord &&
   4867                             ((answer->rrtype == kDNSType_A) || (answer->rrtype == kDNSType_AAAA)));
   4868 #endif
   4869 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
   4870     const char *tracker_hostname = NULL;
   4871     if (addTrackerState && req->addTrackerInfo)
   4872     {
   4873         if (resolved_cache_get_tracker_state(question, &tracker_hostname, NULL, NULL, NULL) == tracker_state_known_tracker &&
   4874             !tracker_hostname)
   4875         {
   4876             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   4877                 "[R%u->Q%u] queryrecord_result_reply NULL tracker hostname",
   4878                 req->request_id, mDNSVal16(question->TargetQID));
   4879         }
   4880     }
   4881 #endif
   4882     ConvertDomainNameToCString(answer->name, name);
   4883 
   4884 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   4885     if (dns_question_is_dnssec_requestor(question))
   4886     {
   4887         flags |= dns_service_flags_init_with_dnssec_result(question, answer);
   4888     }
   4889 #endif
   4890 
   4891     const mDNSBool isMDNSQuestion = mDNSOpaque16IsZero(question->TargetQID);
   4892     if (req->hdr.op == query_request)
   4893     {
   4894         UDS_LOG_ANSWER_EVENT(isMDNSQuestion ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   4895             req, question, answer, expired, "DNSServiceQueryRecord result", AddRecord);
   4896     }
   4897     else
   4898     {
   4899         UDS_LOG_ANSWER_EVENT(isMDNSQuestion ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   4900             req, question, answer, expired, "DNSServiceGetAddrInfo result", AddRecord);
   4901     }
   4902 
   4903     // Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the
   4904     // InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions
   4905     // to be stopped and started including  *this* one. Normally the InterfaceID is valid. But when we
   4906     // are using the /etc/hosts entries to answer a question, the InterfaceID may not be known to the
   4907     // mDNS core . Eventually, we should remove the calls to "NetworkChanged" in
   4908     // mDNSPlatformInterfaceIndexfromInterfaceID when it can't find InterfaceID as ResourceRecords
   4909     // should not have existed to answer this question if the corresponding interface is not valid.
   4910     mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue);
   4911     len = sizeof(DNSServiceFlags);  // calculate reply data length
   4912     len += sizeof(mDNSu32);     // interface index
   4913     len += sizeof(DNSServiceErrorType);
   4914     len += strlen(name) + 1;
   4915     len += 3 * sizeof(mDNSu16); // type, class, rdlen
   4916     len += answer->rdlength;
   4917     len += sizeof(mDNSu32);     // TTL
   4918 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   4919     mdns_signed_result_t signed_result = NULL;
   4920     const uint8_t *signed_data = NULL;
   4921     uint16_t signed_data_length = 0;
   4922     if (req->sign_result && req->signed_obj && AddRecord &&
   4923         (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA || answer->rrtype == kDNSType_TXT))
   4924     {
   4925         OSStatus err = 0;
   4926         if (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA)
   4927         {
   4928             mdns_signed_hostname_result_t hostnameResult = NULL;
   4929             mdns_signed_resolve_result_t resolveResult = mdns_signed_resolve_result_downcast(req->signed_obj);
   4930             if (!resolveResult)
   4931             {
   4932                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   4933                     "[R%u->Q%u] queryrecord_result_reply mdns_signed_resolve_result_downcast failed",
   4934                     req->request_id, mDNSVal16(question->TargetQID));
   4935             }
   4936             else
   4937             {
   4938                 if (answer->rrtype == kDNSType_AAAA)
   4939                 {
   4940                     hostnameResult = mdns_signed_hostname_result_create_ipv6(resolveResult, answer->rdata->u.data,
   4941                         interface_index, &err);
   4942                 }
   4943                 else if (answer->rrtype == kDNSType_A)
   4944                 {
   4945                     hostnameResult = mdns_signed_hostname_result_create_ipv4(resolveResult, answer->rdata->u.data, &err);
   4946                 }
   4947 
   4948                 if (hostnameResult)
   4949                 {
   4950                     signed_result = mdns_signed_result_upcast(hostnameResult);
   4951                 }
   4952             }
   4953         }
   4954         else if (answer->rrtype == kDNSType_TXT)
   4955         {
   4956             mdns_signed_browse_result_t newBrowseResult = NULL;
   4957             mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(req->signed_obj);
   4958             if (!browseResult)
   4959             {
   4960                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   4961                     "[R%u->Q%u] queryrecord_result_reply mdns_signed_browse_result_downcast failed",
   4962                     req->request_id, mDNSVal16(question->TargetQID));
   4963             }
   4964             else
   4965             {
   4966                 newBrowseResult = mdns_signed_browse_result_create_txt_variant(browseResult, interface_index,
   4967                     answer->rdata->u.data, answer->rdlength, &err);
   4968                 if (newBrowseResult)
   4969                 {
   4970                     signed_result = mdns_signed_result_upcast(newBrowseResult);
   4971                 }
   4972             }
   4973         }
   4974         if (!signed_result || err != 0)
   4975         {
   4976             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[R%u->Q%u] queryrecord_result_reply signed_result failed %ld",
   4977                 req->request_id, mDNSVal16(question->TargetQID), (long)err);
   4978         }
   4979         else
   4980         {
   4981             size_t temp_size = 0;
   4982             const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
   4983             if (temp_size <= UINT16_MAX)
   4984             {
   4985                 signed_data = temp_data;
   4986                 signed_data_length = (uint16_t)temp_size;
   4987                 len += get_required_tlv_length(signed_data_length);
   4988             }
   4989         }
   4990     }
   4991 #endif
   4992 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
   4993     if (tracker_hostname)
   4994     {
   4995         len += get_required_tlv_string_length(tracker_hostname);
   4996     }
   4997 #endif
   4998 
   4999     rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req);
   5000 
   5001     if (AddRecord)
   5002         flags |= kDNSServiceFlagsAdd;
   5003     if (expired)
   5004         flags |= kDNSServiceFlagsExpiredAnswer;
   5005     if (!question->InitialCacheMiss)
   5006         flags |= kDNSServiceFlagAnsweredFromCache;
   5007 
   5008     rep->rhdr->flags = dnssd_htonl(flags);
   5009     rep->rhdr->ifi   = dnssd_htonl(interface_index);
   5010     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
   5011 
   5012     data = (uint8_t *)&rep->rhdr[1];
   5013 
   5014     put_string(name,             &data);
   5015     put_uint16(answer->rrtype,   &data);
   5016     put_uint16(answer->rrclass,  &data);
   5017     put_uint16(answer->rdlength, &data);
   5018     // We need to use putRData here instead of the crude put_rdata function, because the crude put_rdata
   5019     // function just does a blind memory copy without regard to structures that may have holes in them.
   5020     if (answer->rdlength)
   5021         if (!putRData(mDNSNULL, (mDNSu8 *)data, (mDNSu8 *)rep->rhdr + len, answer))
   5022             LogMsg("queryrecord_result_reply putRData failed %d", (mDNSu8 *)rep->rhdr + len - (mDNSu8 *)data);
   5023     data += answer->rdlength;
   5024     put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
   5025 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   5026     if (signed_data)
   5027     {
   5028         put_signed_result_tlvs(signed_data, signed_data_length, rep->mhdr, &data, data+len);
   5029     }
   5030     mdns_forget(&signed_result);
   5031 #endif
   5032 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
   5033     if (tracker_hostname)
   5034     {
   5035         put_tracker_hostname_tlvs(tracker_hostname, rep->mhdr, &data, data + len);
   5036         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%u->Q%u] queryrecord_result_reply add tracker " PRI_S,
   5037             req->request_id, mDNSVal16(question->TargetQID), tracker_hostname);
   5038     }
   5039 #endif
   5040 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
   5041     if (addTrackerState)
   5042     {
   5043         resolved_cache_update_tracking(question);
   5044     }
   5045 #endif
   5046     append_reply(req, rep);
   5047 }
   5048 
   5049 mDNSlocal void queryrecord_termination_callback(request_state *request)
   5050 {
   5051     const domainname *const qname = QueryRecordClientRequestGetQName(request->queryrecord);
   5052     const mDNSBool localDomain = IsLocalDomain(qname);
   5053 
   5054     const mDNSu16 qtype = QueryRecordClientRequestGetType(request->queryrecord);
   5055     UDS_LOG_CLIENT_REQUEST(localDomain ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5056         "DNSServiceQueryRecord STOP", qname, request, mDNStrue, "qname: " PRI_DM_NAME ", qtype: " PUB_DNS_TYPE,
   5057         DM_NAME_PARAM_NONNULL(qname), DNS_TYPE_PARAM(qtype));
   5058 
   5059     QueryRecordClientRequestStop(request->queryrecord);
   5060 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   5061     if (request->powerlog_start_time != 0)
   5062     {
   5063         const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   5064         mdns_powerlog_query_record_stop(request->pid_name, request->powerlog_start_time, usesAWDL);
   5065         request->powerlog_start_time = 0;
   5066     }
   5067 #endif
   5068 }
   5069 
   5070 typedef struct
   5071 {
   5072     QueryRecordClientRequestParams cr;
   5073     char qname[MAX_ESCAPED_DOMAIN_NAME];
   5074     mDNSu8 resolverUUID[MDNS_UUID_SIZE];
   5075 } uds_queryrecord_params_t;
   5076 
   5077 static void _uds_queryrecord_params_init(uds_queryrecord_params_t *const params)
   5078 {
   5079     mDNSPlatformMemZero(params, (mDNSu32)sizeof(*params));
   5080     QueryRecordClientRequestParamsInit(&params->cr);
   5081     params->cr.qnameStr = params->qname;
   5082 }
   5083 
   5084 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5085 static void _uds_queryrecord_params_copy(uds_queryrecord_params_t *const dst, const uds_queryrecord_params_t *const src)
   5086 {
   5087 	*dst = *src;
   5088     // Be careful when copying pointers. Each parameters object should point to its own buffers.
   5089     dst->cr.qnameStr = dst->qname;
   5090 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   5091     if (src->cr.resolverUUID)
   5092     {
   5093         dst->cr.resolverUUID = dst->resolverUUID;
   5094     }
   5095 #endif
   5096 }
   5097 #endif
   5098 
   5099 mDNSlocal mStatus _handle_queryrecord_request_start(request_state *request, const uds_queryrecord_params_t *const params)
   5100 {
   5101     request->terminate = queryrecord_termination_callback;
   5102     QueryRecordClientRequest *queryrecord = request->queryrecord;
   5103     const mStatus err = QueryRecordClientRequestStart(queryrecord, &params->cr, queryrecord_result_reply, request);
   5104 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   5105     if (!err)
   5106     {
   5107         const domainname *const qname = QueryRecordClientRequestGetQName(queryrecord);
   5108         if ((request->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) && IsLocalDomain(qname))
   5109         {
   5110             const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   5111             request->powerlog_start_time = mdns_powerlog_query_record_start(request->pid_name, usesAWDL);
   5112         }
   5113     }
   5114 #endif
   5115     return err;
   5116 }
   5117 
   5118 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5119 
   5120 mDNSlocal void _return_queryrecord_request_error(request_state * request, mStatus error)
   5121 {
   5122     size_t len;
   5123     char * emptystr = "\0";
   5124     uint8_t *data;
   5125     reply_state *rep;
   5126 
   5127     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5128        "[R%u] DNSService" PUB_S " _return_queryrecord_request_error: error(%d)",
   5129        request->request_id, request->hdr.op == query_request ? "QueryRecord" : "GetAddrInfo", error);
   5130 
   5131     len = sizeof(DNSServiceFlags);  // calculate reply data length
   5132     len += sizeof(mDNSu32);     // interface index
   5133     len += sizeof(DNSServiceErrorType);
   5134     len += strlen(emptystr) + 1;
   5135     len += 3 * sizeof(mDNSu16); // type, class, rdlen
   5136     len += 0;//answer->rdlength;
   5137     len += sizeof(mDNSu32);     // TTL
   5138 
   5139     rep = create_reply(request->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, request);
   5140 
   5141     rep->rhdr->flags = 0;
   5142     rep->rhdr->ifi   = 0;
   5143     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
   5144 
   5145     data = (uint8_t *)&rep->rhdr[1];
   5146 
   5147     put_string(emptystr,    &data);
   5148     put_uint16(0,           &data);
   5149     put_uint16(0,           &data);
   5150     put_uint16(0,           &data);
   5151     data += 0;
   5152     put_uint32(0,           &data);
   5153 
   5154     append_reply(request, rep);
   5155 }
   5156 
   5157 mDNSlocal mStatus _handle_queryrecord_request_with_trust(request_state *request,
   5158     const uds_queryrecord_params_t *const params)
   5159 {
   5160     mStatus err;
   5161     if (!request->peer_token)
   5162     {
   5163         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_queryrecord_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   5164         err = _handle_queryrecord_request_start(request, params);
   5165     }
   5166     else
   5167     {
   5168         const char *service_ptr = NULL;
   5169         char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
   5170         domainname query_name;
   5171         if (MakeDomainNameFromDNSNameString(&query_name, params->qname))
   5172         {
   5173             domainlabel name;
   5174             domainname type, domain;
   5175             bool good = DeconstructServiceName(&query_name, &name, &type, &domain);
   5176             if (good)
   5177             {
   5178                 ConvertDomainNameToCString(&type, type_str);
   5179                 service_ptr = type_str;
   5180             }
   5181         }
   5182 
   5183         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   5184         mdns_trust_flags_t flags = mdns_trust_flags_none;
   5185         mdns_trust_status_t status = mdns_trust_check_query(*token, params->qname, service_ptr,
   5186             params->cr.qtype, (params->cr.flags & kDNSServiceFlagsForceMulticast) != 0, &flags);
   5187         switch (status)
   5188         {
   5189             case mdns_trust_status_denied:
   5190             case mdns_trust_status_pending:
   5191             {
   5192                 if (!_prepare_trusts_for_request(request))
   5193                 {
   5194                     err = mStatus_NoMemoryErr;
   5195                     goto exit;
   5196                 }
   5197                 mdns_trust_t trust = mdns_trust_create(*token, service_ptr, flags);
   5198                 if (!trust )
   5199                 {
   5200                     err = mStatus_NoMemoryErr;
   5201                     goto exit;
   5202                 }
   5203 
   5204                 uds_queryrecord_params_t *const context =
   5205                     (uds_queryrecord_params_t *)mallocL("context/_handle_queryrecord_request_with_trust", sizeof(*context));
   5206                 if (!context)
   5207                 {
   5208                     my_perror("ERROR: mallocL context/_handle_queryrecord_request_with_trust");
   5209                     mdns_release(trust);
   5210                     err = mStatus_NoMemoryErr;
   5211                     goto exit;
   5212                 }
   5213                 _uds_queryrecord_params_copy(context, params);
   5214                 mdns_trust_set_context(trust, context);
   5215                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   5216                 {
   5217                     freeL("context/_handle_queryrecord_request_with_trust finalizer", ref);
   5218                 });
   5219                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   5220                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   5221                 {
   5222                     if (event == mdns_trust_event_result)
   5223                     {
   5224                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   5225                         KQueueLock();
   5226                         uds_queryrecord_params_t * _params =  mdns_trust_get_context(trust);
   5227                         if (_params)
   5228                         {
   5229                             if (!error)
   5230                             {
   5231                                 error = _handle_queryrecord_request_start(request, _params);
   5232                                 // No context means the request was canceled before we got here
   5233                             }
   5234                             if (error) // (not else if) Always check for error result
   5235                             {
   5236                                 _return_queryrecord_request_error(request, error);
   5237                             }
   5238                         }
   5239                         KQueueUnlock("_handle_queryrecord_request_with_trust");
   5240                     }
   5241                 });
   5242                 CFArrayAppendValue(request->trusts, trust);
   5243                 mdns_release(trust);
   5244                 mdns_trust_activate(trust);
   5245                 err = mStatus_NoError;
   5246                 break;
   5247             }
   5248 
   5249             case mdns_trust_status_no_entitlement:
   5250                 err = mStatus_NoAuth;
   5251                 break;
   5252 
   5253             case mdns_trust_status_granted:
   5254                 err = _handle_queryrecord_request_start(request, params);
   5255                 break;
   5256 
   5257             MDNS_COVERED_SWITCH_DEFAULT:
   5258                 err = mStatus_UnknownErr;
   5259         }
   5260     }
   5261 exit:
   5262     return err;
   5263 }
   5264 #endif // TRUST_ENFORCEMENT
   5265 
   5266 #if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
   5267 mDNSlocal void get_queryrecord_tlvs(request_state *const request, uds_queryrecord_params_t *const params)
   5268 {
   5269     mdns_require_quiet(request->msgptr, exit);
   5270     mdns_require_quiet(request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS, exit);
   5271 
   5272     const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
   5273     const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
   5274     const mDNSu32 aaaaPolicy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY, mDNSNULL);
   5275     params->cr.useAAAAFallback = (aaaaPolicy == kDNSServiceAAAAPolicyFallback);
   5276 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   5277     const mDNSu8 *const resolverOverride = get_tlv_uuid(start, end, IPC_TLV_TYPE_RESOLVER_OVERRIDE);
   5278     if (resolverOverride)
   5279     {
   5280         mDNSPlatformMemCopy(params->resolverUUID, resolverOverride, MDNS_UUID_SIZE);
   5281         params->cr.resolverUUID = params->resolverUUID;
   5282         params->cr.overrideDNSService = mDNStrue;
   5283     }
   5284     else
   5285     {
   5286         const mDNSu32 failoverPolicy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_FAILOVER_POLICY, mDNSNULL);
   5287         params->cr.useFailover = (failoverPolicy == kDNSServiceFailoverPolicyAllow);
   5288         size_t len;
   5289         const mDNSu8 *const data = get_tlv(start, end, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, &len);
   5290         if (data)
   5291         {
   5292             params->cr.customID = Querier_RegisterCustomDNSServiceWithPListData(data, len);
   5293             request->custom_service_id = params->cr.customID;
   5294         }
   5295         params->cr.needEncryption = (get_tlv_uint32(start, end, IPC_TLV_TYPE_REQUIRE_PRIVACY, mDNSNULL) != 0);
   5296     }
   5297 #endif
   5298 
   5299 exit:
   5300     return;
   5301 }
   5302 #endif
   5303 
   5304 mDNSlocal mStatus handle_queryrecord_request(request_state *request)
   5305 {
   5306     mStatus err;
   5307     if (!request->queryrecord)
   5308     {
   5309         request->queryrecord = (QueryRecordClientRequest *)callocL("QueryRecordClientRequest", sizeof(*request->queryrecord));
   5310         mdns_require_action_quiet(request->queryrecord, exit, err = mStatus_NoMemoryErr; uds_log_error(
   5311             "[R%u] Failed to allocate memory for query record request", request->request_id));
   5312     }
   5313     uds_queryrecord_params_t params;
   5314     _uds_queryrecord_params_init(&params);
   5315     params.cr.flags          = get_flags(&request->msgptr, request->msgend);
   5316     params.cr.interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   5317     if (get_string(&request->msgptr, request->msgend, params.qname, sizeof(params.qname)) < 0)
   5318     {
   5319         err = mStatus_BadParamErr;
   5320         goto exit;
   5321     }
   5322     params.cr.qtype          = get_uint16(&request->msgptr, request->msgend);
   5323     params.cr.qclass         = get_uint16(&request->msgptr, request->msgend);
   5324     params.cr.requestID      = request->request_id;
   5325     params.cr.effectivePID   = request->validUUID ? 0 : request->process_id;
   5326     params.cr.effectiveUUID  = request->validUUID ? request->uuid : mDNSNULL;
   5327     params.cr.peerUID        = request->uid;
   5328 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   5329     params.cr.peerToken      = request->peer_token;
   5330 #endif
   5331     if (!request->msgptr)
   5332     {
   5333         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   5334             "[R%d] DNSServiceQueryRecord(unreadable parameters)", request->request_id);
   5335         err = mStatus_BadParamErr;
   5336         goto exit;
   5337     }
   5338     request->flags           = params.cr.flags;
   5339     request->interfaceIndex  = params.cr.interfaceIndex;
   5340 #if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
   5341     get_queryrecord_tlvs(request, &params);
   5342 #endif
   5343 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   5344     err = get_signed_browse_tlvs(request);
   5345     if (err) { LogMsg("%3d: handle_queryrecord_request err reading Validation TLVS", request->sd); return(err); }
   5346 #endif
   5347 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
   5348     get_tracker_info_tlvs(request);
   5349 #endif
   5350     mDNSBool enablesDNSSEC = mDNSfalse;
   5351 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   5352     enablesDNSSEC = dns_service_flags_enables_dnssec(request->flags);
   5353 #endif
   5354 
   5355     domainname query_name;
   5356     const mDNSu8 *const nextUnusedBytes = MakeDomainNameFromDNSNameString(&query_name, params.qname);
   5357     if (!nextUnusedBytes)
   5358     {
   5359         err = mStatus_BadParamErr;
   5360         goto exit;
   5361     }
   5362 
   5363     const mDNSBool localDomain = IsLocalDomain(&query_name);
   5364 
   5365     UDS_LOG_CLIENT_REQUEST_WITH_DNSSEC_INFO(localDomain ? MDNS_LOG_CATEGORY_MDNS : MDNS_LOG_CATEGORY_DEFAULT,
   5366         MDNS_LOG_DEFAULT, "DNSServiceQueryRecord START", &query_name, request, mDNSfalse, enablesDNSSEC,
   5367         "qname: " PRI_DM_NAME ", qtype: " PUB_DNS_TYPE,
   5368         DM_NAME_PARAM_NONNULL(&query_name), DNS_TYPE_PARAM(params.cr.qtype));
   5369 
   5370     request->terminate = NULL;
   5371 
   5372 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5373     mDNSBool trust_check_done = mDNSfalse;
   5374 #endif
   5375 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   5376     if (request->signed_obj)
   5377     {
   5378         mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(request->signed_obj);
   5379         if (browseResult && mdns_signed_browse_result_contains(browseResult, query_name.c, request->interfaceIndex))
   5380         {
   5381             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
   5382                    "[R%d] DNSServiceQueryRecord: Allowing signed result",
   5383                       request->request_id);
   5384 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5385             trust_check_done = mDNStrue;
   5386 #endif
   5387         }
   5388         else
   5389         {
   5390             request->sign_result = mDNSfalse;
   5391             mdns_forget(&request->signed_obj);
   5392         }
   5393     }
   5394 #endif
   5395 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5396     if (!trust_check_done && os_feature_enabled(mDNSResponder, bonjour_privacy) )
   5397     {
   5398         err = _handle_queryrecord_request_with_trust(request, &params);
   5399     }
   5400     else
   5401 #endif
   5402     {
   5403         err = _handle_queryrecord_request_start(request, &params);
   5404     }
   5405 
   5406 exit:
   5407     return(err);
   5408 }
   5409 
   5410 // ***************************************************************************
   5411 // MARK: - DNSServiceEnumerateDomains
   5412 
   5413 mDNSlocal reply_state *format_enumeration_reply(request_state *request,
   5414                                                 const char *domain, DNSServiceFlags flags, mDNSu32 ifi, DNSServiceErrorType err)
   5415 {
   5416     size_t len;
   5417     reply_state *reply;
   5418     uint8_t *data;
   5419 
   5420     len = sizeof(DNSServiceFlags);
   5421     len += sizeof(mDNSu32);
   5422     len += sizeof(DNSServiceErrorType);
   5423     len += strlen(domain) + 1;
   5424 
   5425     reply = create_reply(enumeration_reply_op, len, request);
   5426     reply->rhdr->flags = dnssd_htonl(flags);
   5427     reply->rhdr->ifi   = dnssd_htonl(ifi);
   5428     reply->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
   5429     data = (uint8_t *)&reply->rhdr[1];
   5430     put_string(domain, &data);
   5431     return reply;
   5432 }
   5433 
   5434 mDNSlocal void enum_termination_callback(request_state *request)
   5435 {
   5436     request_enumeration *const enumeration = request->enumeration;
   5437     // Stop the domain enumeration queries to discover the WAB Browse/Registration domains
   5438     if (enumeration->flags & kDNSServiceFlagsRegistrationDomains)
   5439     {
   5440         LogInfo("%3d: DNSServiceEnumeration Cancel WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
   5441         uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
   5442     }
   5443     else
   5444     {
   5445         LogInfo("%3d: DNSServiceEnumeration Cancel WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
   5446         uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
   5447         mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_autoall);
   5448     }
   5449     mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_all);
   5450     mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_default);
   5451 }
   5452 
   5453 mDNSlocal void enum_result_callback(mDNS *const m,
   5454                                     DNSQuestion *const question, const ResourceRecord *const answer, QC_result AddRecord)
   5455 {
   5456     char domain[MAX_ESCAPED_DOMAIN_NAME];
   5457     request_state *request = question->QuestionContext;
   5458     DNSServiceFlags flags = 0;
   5459     reply_state *reply;
   5460     (void)m; // Unused
   5461 
   5462     if (answer->rrtype != kDNSType_PTR) return;
   5463 
   5464     // We only return add/remove events for the browse and registration lists
   5465     // For the default browse and registration answers, we only give an "ADD" event
   5466     const request_enumeration *const enumeration = request->enumeration;
   5467     if (question == &enumeration->q_default && !AddRecord) return;
   5468 
   5469     if (AddRecord)
   5470     {
   5471         flags |= kDNSServiceFlagsAdd;
   5472         if (question == &enumeration->q_default) flags |= kDNSServiceFlagsDefault;
   5473     }
   5474 
   5475     ConvertDomainNameToCString(&answer->rdata->u.name, domain);
   5476     // Note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
   5477     // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
   5478     // network, so we just pass kDNSServiceInterfaceIndexAny
   5479     reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError);
   5480     if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; }
   5481 
   5482     LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   5483            "[R%d->Q%d] DNSServiceEnumerateDomains(" PRI_DM_LABEL ") RESULT " PUB_ADD_RMV_U ": " PRI_S,
   5484            request->request_id, mDNSVal16(question->TargetQID), DM_LABEL_PARAM(&question->qname),
   5485            ADD_RMV_U_PARAM(AddRecord), domain);
   5486 
   5487     append_reply(request, reply);
   5488 }
   5489 
   5490 mDNSlocal mStatus handle_enum_request(request_state *request)
   5491 {
   5492     mStatus err;
   5493     DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
   5494     DNSServiceFlags reg = flags & kDNSServiceFlagsRegistrationDomains;
   5495     mDNS_DomainType t_all     = reg ? mDNS_DomainTypeRegistration        : mDNS_DomainTypeBrowse;
   5496     mDNS_DomainType t_default = reg ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
   5497     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   5498     mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   5499     mdns_require_action_quiet((interfaceIndex == 0) || InterfaceID, exit, err = mStatus_BadParamErr);
   5500     mdns_require_action_quiet(request->msgptr, exit, err = mStatus_BadParamErr; uds_log_error(
   5501         "[R%u] DNSServiceEnumerateDomains(unreadable parameters)", request->request_id));
   5502 
   5503     if (!request->enumeration)
   5504     {
   5505         request->enumeration = (request_enumeration *)callocL("request_enumeration", sizeof(*request->enumeration));
   5506         mdns_require_action_quiet(request->enumeration, exit, err = mStatus_NoMemoryErr; uds_log_error(
   5507             "[R%u] Failed to allocate memory for enumeration request", request->request_id));
   5508     }
   5509     request->flags = flags;
   5510     request->interfaceIndex = interfaceIndex;
   5511 
   5512     // mark which kind of enumeration we're doing so that we know what domain enumeration queries to stop
   5513     request_enumeration *const enumeration = request->enumeration;
   5514     enumeration->flags = reg;
   5515 
   5516     // enumeration requires multiple questions, so we must link all the context pointers so that
   5517     // necessary context can be reached from the callbacks
   5518     enumeration->q_all.QuestionContext = request;
   5519     enumeration->q_default.QuestionContext = request;
   5520     if (!reg) enumeration->q_autoall.QuestionContext = request;
   5521 
   5522     // if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
   5523     if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
   5524 
   5525     // make the calls
   5526     LogOperation("%3d: DNSServiceEnumerateDomains(%X=%s)", request->sd, flags,
   5527                  (flags & kDNSServiceFlagsBrowseDomains      ) ? "kDNSServiceFlagsBrowseDomains" :
   5528                  (flags & kDNSServiceFlagsRegistrationDomains) ? "kDNSServiceFlagsRegistrationDomains" : "<<Unknown>>");
   5529     err = mDNS_GetDomains(&mDNSStorage, &enumeration->q_all, t_all, NULL, InterfaceID, enum_result_callback, request);
   5530     if (!err)
   5531     {
   5532         err = mDNS_GetDomains(&mDNSStorage, &enumeration->q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
   5533         if (err) mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_all);
   5534         else if (!reg)
   5535         {
   5536             err = mDNS_GetDomains(&mDNSStorage, &enumeration->q_autoall, mDNS_DomainTypeBrowseAutomatic, NULL, InterfaceID, enum_result_callback, request);
   5537             if (err)
   5538             {
   5539                 mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_all);
   5540                 mDNS_StopGetDomains(&mDNSStorage, &enumeration->q_default);
   5541             }
   5542         }
   5543         if (!err) request->terminate = enum_termination_callback;
   5544     }
   5545     if (!err)
   5546     {
   5547         // Start the domain enumeration queries to discover the WAB Browse/Registration domains
   5548         if (reg)
   5549         {
   5550             LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
   5551             uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
   5552         }
   5553         else
   5554         {
   5555             LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
   5556             uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
   5557         }
   5558     }
   5559 
   5560 exit:
   5561     return(err);
   5562 }
   5563 
   5564 // ***************************************************************************
   5565 // MARK: - DNSServiceReconfirmRecord & Misc
   5566 
   5567 mDNSlocal mStatus handle_reconfirm_request(request_state *request)
   5568 {
   5569     mStatus status = mStatus_BadParamErr;
   5570     AuthRecord *rr = read_rr_from_ipc_msg(request, 0, 0);
   5571     if (rr)
   5572     {
   5573         status = mDNS_ReconfirmByValue(&mDNSStorage, &rr->resrec);
   5574 
   5575         if (status == mStatus_NoError)
   5576         {
   5577             UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   5578                 "DNSServiceReconfirmRecord START", rr->resrec.name, request, mDNSfalse,
   5579                 "rr name: " PRI_DM_NAME ", rr type: " PUB_DNS_TYPE, DM_NAME_PARAM(rr->resrec.name),
   5580                 DNS_TYPE_PARAM(rr->resrec.rrtype));
   5581         }
   5582         else
   5583         {
   5584             UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
   5585                 "DNSServiceReconfirmRecord FAILED", rr->resrec.name, request, mDNSfalse,
   5586                 "rr name: " PRI_DM_NAME ", rr type: " PUB_DNS_TYPE ", error: %d", DM_NAME_PARAM(rr->resrec.name),
   5587                 DNS_TYPE_PARAM(rr->resrec.rrtype), status);
   5588         }
   5589 
   5590         freeL("AuthRecord/handle_reconfirm_request", rr);
   5591     }
   5592     return(status);
   5593 }
   5594 
   5595 
   5596 mDNSlocal mStatus handle_release_request(request_state *request)
   5597 {
   5598     (void) request;
   5599     return mStatus_UnsupportedErr;
   5600 }
   5601 
   5602 
   5603 mDNSlocal mStatus handle_setdomain_request(request_state *request)
   5604 {
   5605     char domainstr[MAX_ESCAPED_DOMAIN_NAME];
   5606     domainname domain;
   5607     DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
   5608     (void)flags; // Unused
   5609     if (get_string(&request->msgptr, request->msgend, domainstr, sizeof(domainstr)) < 0 ||
   5610         !MakeDomainNameFromDNSNameString(&domain, domainstr))
   5611     { LogMsg("%3d: DNSServiceSetDefaultDomainForUser(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
   5612 
   5613     LogOperation("%3d: DNSServiceSetDefaultDomainForUser(%##s)", request->sd, domain.c);
   5614     return(mStatus_NoError);
   5615 }
   5616 
   5617 typedef packedstruct
   5618 {
   5619     mStatus err;
   5620     mDNSu32 len;
   5621     mDNSu32 vers;
   5622 } DaemonVersionReply;
   5623 
   5624 mDNSlocal void handle_getproperty_request(request_state *request)
   5625 {
   5626     const mStatus BadParamErr = (mStatus)dnssd_htonl((mDNSu32)mStatus_BadParamErr);
   5627     char prop[256];
   5628     if (get_string(&request->msgptr, request->msgend, prop, sizeof(prop)) >= 0)
   5629     {
   5630         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5631                "[R%d] DNSServiceGetProperty(" PUB_S ")", request->request_id, prop);
   5632         if (!strcmp(prop, kDNSServiceProperty_DaemonVersion))
   5633         {
   5634             DaemonVersionReply x = { 0, dnssd_htonl(4), dnssd_htonl(_DNS_SD_H) };
   5635             send_all(request->sd, (const char *)&x, sizeof(x));
   5636             return;
   5637         }
   5638     }
   5639 
   5640     // If we didn't recogize the requested property name, return BadParamErr
   5641     send_all(request->sd, (const char *)&BadParamErr, sizeof(BadParamErr));
   5642 }
   5643 
   5644 mDNSlocal void handle_connection_delegate_request(request_state *request)
   5645 {
   5646     (void) request;
   5647 }
   5648 
   5649 typedef packedstruct
   5650 {
   5651     mStatus err;
   5652     mDNSs32 pid;
   5653 } PIDInfo;
   5654 
   5655 // ***************************************************************************
   5656 // MARK: - DNSServiceNATPortMappingCreate
   5657 
   5658 #define DNSServiceProtocol(X) ((X) == NATOp_AddrRequest ? 0 : (X) == NATOp_MapUDP ? kDNSServiceProtocol_UDP : kDNSServiceProtocol_TCP)
   5659 
   5660 mDNSlocal void port_mapping_termination_callback(request_state *request)
   5661 {
   5662     request_port_mapping *const pm = request->pm;
   5663     LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT,
   5664         "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP PID[%d](" PUB_S ") -- duration: " PUB_TIME_DUR,
   5665         request->request_id, DNSServiceProtocol(pm->NATinfo.Protocol),
   5666         mDNSVal16(pm->NATinfo.IntPort), mDNSVal16(pm->ReqExt), pm->NATinfo.NATLease,
   5667         request->process_id, request->pid_name, request_state_get_duration(request));
   5668 
   5669     mDNS_StopNATOperation(&mDNSStorage, &pm->NATinfo);
   5670 }
   5671 
   5672 // Called via function pointer when we get a NAT Traversal (address request or port mapping) response
   5673 mDNSlocal void port_mapping_create_request_callback(mDNS *m, NATTraversalInfo *n)
   5674 {
   5675     request_state *request = (request_state *)n->clientContext;
   5676     reply_state *rep;
   5677     size_t replyLen;
   5678     uint8_t *data;
   5679 
   5680     if (!request) { LogMsg("port_mapping_create_request_callback called with unknown request_state object"); return; }
   5681 
   5682     // calculate reply data length
   5683     replyLen = sizeof(DNSServiceFlags);
   5684     replyLen += 3 * sizeof(mDNSu32);  // if index + addr + ttl
   5685     replyLen += sizeof(DNSServiceErrorType);
   5686     replyLen += 2 * sizeof(mDNSu16);  // Internal Port + External Port
   5687     replyLen += sizeof(mDNSu8);       // protocol
   5688 
   5689     rep = create_reply(port_mapping_reply_op, replyLen, request);
   5690 
   5691     rep->rhdr->flags = dnssd_htonl(0);
   5692     rep->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, n->InterfaceID, mDNSfalse));
   5693     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)n->Result);
   5694 
   5695     data = (uint8_t *)&rep->rhdr[1];
   5696 
   5697     const request_port_mapping *const pm = request->pm;
   5698     *data++ = pm->NATinfo.ExternalAddress.b[0];
   5699     *data++ = pm->NATinfo.ExternalAddress.b[1];
   5700     *data++ = pm->NATinfo.ExternalAddress.b[2];
   5701     *data++ = pm->NATinfo.ExternalAddress.b[3];
   5702     *data++ = DNSServiceProtocol(pm->NATinfo.Protocol);
   5703     *data++ = pm->NATinfo.IntPort.b[0];
   5704     *data++ = pm->NATinfo.IntPort.b[1];
   5705     *data++ = pm->NATinfo.ExternalPort.b[0];
   5706     *data++ = pm->NATinfo.ExternalPort.b[1];
   5707     put_uint32(pm->NATinfo.Lifetime, &data);
   5708 
   5709     LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT,
   5710         "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) RESULT " PRI_IPv4_ADDR ":%u TTL %u",
   5711         request->request_id, DNSServiceProtocol(pm->NATinfo.Protocol),
   5712         mDNSVal16(pm->NATinfo.IntPort), mDNSVal16(pm->ReqExt), pm->NATinfo.NATLease,
   5713         &pm->NATinfo.ExternalAddress, mDNSVal16(pm->NATinfo.ExternalPort),
   5714         pm->NATinfo.Lifetime);
   5715 
   5716     append_reply(request, rep);
   5717 }
   5718 
   5719 mDNSlocal mStatus handle_port_mapping_request(request_state *request)
   5720 {
   5721     mDNSu32 ttl = 0;
   5722     mStatus err = mStatus_NoError;
   5723 
   5724     DNSServiceFlags flags          = get_flags(&request->msgptr, request->msgend);
   5725     mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
   5726     mDNSInterfaceID InterfaceID    = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
   5727     mDNSu8 protocol       = (mDNSu8)get_uint32(&request->msgptr, request->msgend);
   5728     (void)flags; // Unused
   5729     if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
   5730     if (!request->pm)
   5731     {
   5732         request->pm = (request_port_mapping *)callocL("request_port_mapping", sizeof(*request->pm));
   5733         mdns_require_action_quiet(request->pm, exit, err = mStatus_NoMemoryErr; uds_log_error(
   5734             "[R%u] Failed to allocate memory for port mapping request", request->request_id));
   5735     }
   5736     request_port_mapping *const pm = request->pm;
   5737     if (request->msgptr + 8 > request->msgend) request->msgptr = NULL;
   5738     else
   5739     {
   5740         pm->NATinfo.IntPort.b[0] = *request->msgptr++;
   5741         pm->NATinfo.IntPort.b[1] = *request->msgptr++;
   5742         pm->ReqExt.b[0]          = *request->msgptr++;
   5743         pm->ReqExt.b[1]          = *request->msgptr++;
   5744         ttl = get_uint32(&request->msgptr, request->msgend);
   5745     }
   5746 
   5747     if (!request->msgptr)
   5748     {
   5749         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5750                "[R%d] DNSServiceNATPortMappingCreate(unreadable parameters)", request->request_id);
   5751         return(mStatus_BadParamErr);
   5752     }
   5753 
   5754     if (protocol == 0)  // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too
   5755     {
   5756         if (!mDNSIPPortIsZero(pm->NATinfo.IntPort) || !mDNSIPPortIsZero(pm->ReqExt) || ttl) return(mStatus_BadParamErr);
   5757     }
   5758     else
   5759     {
   5760         if (mDNSIPPortIsZero(pm->NATinfo.IntPort)) return(mStatus_BadParamErr);
   5761         if (!(protocol & (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP))) return(mStatus_BadParamErr);
   5762     }
   5763 
   5764     request->flags             = flags;
   5765     request->interfaceIndex    = interfaceIndex;
   5766     pm->NATinfo.Protocol       = !protocol ? NATOp_AddrRequest : (protocol == kDNSServiceProtocol_UDP) ? NATOp_MapUDP : NATOp_MapTCP;
   5767     // pm->NATinfo.IntPort already set above.
   5768     pm->NATinfo.RequestedPort  = pm->ReqExt;
   5769     pm->NATinfo.NATLease       = ttl;
   5770     pm->NATinfo.clientCallback = port_mapping_create_request_callback;
   5771     pm->NATinfo.clientContext  = request;
   5772 
   5773     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5774         "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START PID[%d](" PUB_S ")",
   5775         request->request_id, protocol, mDNSVal16(pm->NATinfo.IntPort), mDNSVal16(pm->ReqExt),
   5776         pm->NATinfo.NATLease, request->process_id, request->pid_name);
   5777     err = mDNS_StartNATOperation(&mDNSStorage, &pm->NATinfo);
   5778     if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
   5779     else request->terminate = port_mapping_termination_callback;
   5780 
   5781 exit:
   5782     return(err);
   5783 }
   5784 
   5785 // ***************************************************************************
   5786 // MARK: - DNSServiceGetAddrInfo
   5787 
   5788 mDNSlocal void addrinfo_termination_callback(request_state *request)
   5789 {
   5790     GetAddrInfoClientRequest *const addrinfo = request->addrinfo;
   5791 
   5792     UDS_LOG_CLIENT_REQUEST(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   5793         "DNSServiceGetAddrInfo STOP", GetAddrInfoClientRequestGetQName(addrinfo), request,
   5794         mDNStrue, "hostname: " PRI_DM_NAME, DM_NAME_PARAM(GetAddrInfoClientRequestGetQName(addrinfo)));
   5795 
   5796     GetAddrInfoClientRequestStop(addrinfo);
   5797 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   5798     if (request->powerlog_start_time != 0)
   5799     {
   5800         const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   5801         mdns_powerlog_getaddrinfo_stop(request->pid_name, request->powerlog_start_time, usesAWDL);
   5802         request->powerlog_start_time = 0;
   5803     }
   5804 #endif
   5805 }
   5806 
   5807 typedef struct {
   5808     mDNSu32     protocols;
   5809     char        hostname[MAX_ESCAPED_DOMAIN_NAME];
   5810 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   5811     mDNSBool    require_privacy;
   5812 #endif
   5813 } _addrinfo_start_params_t;
   5814 
   5815 mDNSlocal mStatus _handle_addrinfo_request_start(request_state *request, const _addrinfo_start_params_t * const params)
   5816 {
   5817     mStatus err;
   5818 
   5819     request->terminate = addrinfo_termination_callback;
   5820 
   5821     GetAddrInfoClientRequestParams gaiParams;
   5822     GetAddrInfoClientRequestParamsInit(&gaiParams);
   5823     gaiParams.requestID      = request->request_id;
   5824     gaiParams.hostnameStr    = params->hostname;
   5825     gaiParams.interfaceIndex = request->interfaceIndex;
   5826     gaiParams.flags          = request->flags;
   5827     gaiParams.protocols      = params->protocols;
   5828     gaiParams.effectivePID   = request->validUUID ? 0 : request->process_id;
   5829     gaiParams.effectiveUUID  = request->validUUID ? request->uuid : mDNSNULL;
   5830     gaiParams.peerUID        = request->uid;
   5831 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   5832     gaiParams.needEncryption = params->require_privacy ? mDNStrue : mDNSfalse;
   5833     gaiParams.customID       = request->custom_service_id;
   5834 #endif
   5835 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   5836     gaiParams.peerToken      = request->peer_token;
   5837 #endif
   5838 #if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_DEBUGGING)
   5839     get_tracker_info_tlvs(request);
   5840 #endif
   5841     err = GetAddrInfoClientRequestStart(request->addrinfo, &gaiParams, queryrecord_result_reply, request);
   5842 #if MDNSRESPONDER_SUPPORTS(APPLE, POWERLOG_MDNS_REQUESTS)
   5843     if (!err)
   5844     {
   5845         const domainname *const qname = GetAddrInfoClientRequestGetQName(request->addrinfo);
   5846         if ((request->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) && IsLocalDomain(qname))
   5847         {
   5848             const mDNSBool usesAWDL = ClientRequestUsesAWDL(request->interfaceIndex, request->flags);
   5849             request->powerlog_start_time = mdns_powerlog_getaddrinfo_start(request->pid_name, usesAWDL);
   5850         }
   5851     }
   5852 #endif
   5853     return err;
   5854 }
   5855 
   5856 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   5857 
   5858 mDNSlocal void _return_addrinfo_request_error(request_state * request, mStatus error)
   5859 {
   5860     _return_queryrecord_request_error(request, error);
   5861 }
   5862 
   5863 mDNSlocal mStatus _handle_addrinfo_request_with_trust(request_state *request, const _addrinfo_start_params_t * const params)
   5864 {
   5865     mStatus err;
   5866     if (!request->peer_token)
   5867     {
   5868         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_addrinfo_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
   5869         err = _handle_addrinfo_request_start(request, params);
   5870     }
   5871     else
   5872     {
   5873         const audit_token_t *const token = mdns_audit_token_get_token(request->peer_token);
   5874         mdns_trust_flags_t flags = mdns_trust_flags_none;
   5875         mdns_trust_status_t status = mdns_trust_check_getaddrinfo(*token, params->hostname, &flags);
   5876         switch (status)
   5877         {
   5878             case mdns_trust_status_denied:
   5879             case mdns_trust_status_pending:
   5880             {
   5881                 if (!_prepare_trusts_for_request(request))
   5882                 {
   5883                     err = mStatus_NoMemoryErr;
   5884                     goto exit;
   5885                 }
   5886                 mdns_trust_t trust = mdns_trust_create(*token, NULL, flags);
   5887                 if (!trust )
   5888                 {
   5889                     err = mStatus_NoMemoryErr;
   5890                     goto exit;
   5891                 }
   5892 
   5893                 void * context = mallocL("context/_handle_addrinfo_request_with_trust", sizeof(_addrinfo_start_params_t));
   5894                 if (!context)
   5895                 {
   5896                     my_perror("ERROR: mallocL context/_handle_addrinfo_request_with_trust");
   5897                     mdns_release(trust);
   5898                     err = mStatus_NoMemoryErr;
   5899                     goto exit;
   5900                 }
   5901                 memcpy(context, params, sizeof(_addrinfo_start_params_t));
   5902                 mdns_trust_set_context(trust, context);
   5903                 mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
   5904                 {
   5905                     freeL("context/_handle_addrinfo_request_with_trust finalizer", ref);
   5906                 });
   5907                 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
   5908                 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
   5909                 {
   5910                     if (event == mdns_trust_event_result)
   5911                     {
   5912                         mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
   5913                         KQueueLock();
   5914                         _addrinfo_start_params_t * _params =  mdns_trust_get_context(trust);
   5915                         if (_params)
   5916                         {
   5917                             if (!error)
   5918                             {
   5919                                 error = _handle_addrinfo_request_start(request, _params);
   5920                                 // No context means the request was canceled before we got here
   5921                             }
   5922                             if (error) // (not else if) Always check for error result
   5923                             {
   5924                                 _return_addrinfo_request_error(request, error);
   5925                             }
   5926                         }
   5927                         KQueueUnlock("_handle_addrinfo_request_with_trust");
   5928                     }
   5929                 });
   5930                 CFArrayAppendValue(request->trusts, trust);
   5931                 mdns_release(trust);
   5932                 mdns_trust_activate(trust);
   5933                 err = mStatus_NoError;
   5934                 break;
   5935             }
   5936 
   5937             case mdns_trust_status_no_entitlement:
   5938                 err = mStatus_NoAuth;
   5939                 break;
   5940 
   5941             case mdns_trust_status_granted:
   5942                 err = _handle_addrinfo_request_start(request, params);
   5943                 break;
   5944 
   5945             MDNS_COVERED_SWITCH_DEFAULT:
   5946                 err = mStatus_UnknownErr;
   5947         }
   5948     }
   5949 exit:
   5950     return err;
   5951 }
   5952 #endif // TRUST_ENFORCEMENT
   5953 
   5954 mDNSlocal mStatus handle_addrinfo_request(request_state *request)
   5955 {
   5956     mStatus err;
   5957     if (!request->addrinfo)
   5958     {
   5959         request->addrinfo = (GetAddrInfoClientRequest *)callocL("GetAddrInfoClientRequest", sizeof(*request->addrinfo));
   5960         mdns_require_action_quiet(request->addrinfo, exit, err = mStatus_NoMemoryErr; uds_log_error(
   5961             "[R%u] Failed to allocate memory for addrinfo request", request->request_id));
   5962     }
   5963     DNSServiceFlags     flags;
   5964     mDNSu32             interfaceIndex;
   5965     _addrinfo_start_params_t params;
   5966     flags               = get_flags(&request->msgptr, request->msgend);
   5967     interfaceIndex      = get_uint32(&request->msgptr, request->msgend);
   5968     params.protocols    = get_uint32(&request->msgptr, request->msgend);
   5969     if (get_string(&request->msgptr, request->msgend, params.hostname, sizeof(params.hostname)) < 0)
   5970     {
   5971         err = mStatus_BadParamErr;
   5972         goto exit;
   5973     }
   5974     if (!request->msgptr)
   5975     {
   5976         LogMsg("%3d: DNSServiceGetAddrInfo(unreadable parameters)", request->sd);
   5977         err = mStatus_BadParamErr;
   5978         goto exit;
   5979     }
   5980 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   5981     params.require_privacy = mDNSfalse;
   5982 #endif
   5983 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
   5984     if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
   5985     {
   5986         size_t len;
   5987         const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
   5988         const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
   5989         const mDNSu8 *const data = get_tlv(start, end, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, &len);
   5990         if (data)
   5991         {
   5992             request->custom_service_id = Querier_RegisterCustomDNSServiceWithPListData(data, len);
   5993         }
   5994         const mDNSu32 u32 = get_tlv_uint32(start, end, IPC_TLV_TYPE_REQUIRE_PRIVACY, mDNSNULL);
   5995         params.require_privacy = (u32 != 0) ? mDNStrue : mDNSfalse;
   5996     }
   5997 #endif
   5998 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   5999     err = get_signed_resolve_tlvs(request);
   6000     if (err) { LogMsg("%3d: handle_addrinfo_request err reading Validation TLVS", request->sd); return(err); }
   6001 #endif
   6002     request->flags          = flags;
   6003     request->interfaceIndex = interfaceIndex;
   6004 
   6005     mDNSBool enablesDNSSEC = mDNSfalse;
   6006 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   6007     enablesDNSSEC = dns_service_flags_enables_dnssec(request->flags);
   6008 #endif
   6009 
   6010     domainname qname;
   6011     MakeDomainNameFromDNSNameString(&qname, params.hostname);
   6012     UDS_LOG_CLIENT_REQUEST_WITH_DNSSEC_INFO(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6013         "DNSServiceGetAddrInfo START", &qname, request, mDNSfalse, enablesDNSSEC,
   6014         "hostname: " PRI_DM_NAME ", protocols: %u", DM_NAME_PARAM_NONNULL(&qname), params.protocols);
   6015 
   6016     request->terminate = NULL;
   6017 
   6018 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   6019     mDNSBool trust_check_done = mDNSfalse;
   6020 #endif
   6021 #if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
   6022     if (request->signed_obj)
   6023     {
   6024         mdns_signed_resolve_result_t resolveResult = mdns_signed_resolve_result_downcast(request->signed_obj);
   6025         if (resolveResult &&
   6026             mdns_signed_resolve_result_contains(resolveResult, params.hostname, interfaceIndex))
   6027         {
   6028             if (mdns_system_is_signed_result_uuid_valid(mdns_signed_result_get_uuid(resolveResult)))
   6029             {
   6030                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
   6031                        "[R%d] DNSServiceGetAddrInfo: Allowing signed result",
   6032                           request->request_id);
   6033 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   6034                 trust_check_done = mDNStrue;
   6035 #endif
   6036             }
   6037             else
   6038             {
   6039                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6040                        "[R%d] DNSServiceGetAddrInfo: Signed result UUID revoked.",
   6041                           request->request_id);
   6042                 return mStatus_PolicyDenied;
   6043             }
   6044         }
   6045         else
   6046         {
   6047             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6048                    "[R%d] DNSServiceGetAddrInfo: Signed result does not cover hostname: " PRI_S ", ifindex: %u.",
   6049                       request->request_id, params.hostname, request->interfaceIndex);
   6050             request->sign_result = mDNSfalse;
   6051             mdns_forget(&request->signed_obj);
   6052         }
   6053     }
   6054 #endif
   6055 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
   6056     if (!trust_check_done && os_feature_enabled(mDNSResponder, bonjour_privacy))
   6057     {
   6058         err = _handle_addrinfo_request_with_trust(request, &params);
   6059     }
   6060     else
   6061     {
   6062         err = _handle_addrinfo_request_start(request, &params);
   6063     }
   6064 #else
   6065     err = _handle_addrinfo_request_start(request, &params);
   6066 #endif
   6067 
   6068 exit:
   6069     return(err);
   6070 }
   6071 
   6072 // ***************************************************************************
   6073 // MARK: - Main Request Handler etc.
   6074 
   6075 mDNSlocal request_state *NewRequest(void)
   6076 {
   6077     request_state *request;
   6078     request_state **p = &all_requests;
   6079     request = (request_state *) callocL("request_state", sizeof(*request));
   6080     if (!request) FatalError("ERROR: calloc");
   6081     while (*p) p = &(*p)->next;
   6082     *p = request;
   6083     return(request);
   6084 }
   6085 
   6086 // read_msg may be called any time when the transfer state (req->ts) is t_morecoming.
   6087 // if there is no data on the socket, the socket will be closed and t_terminated will be returned
   6088 mDNSlocal void read_msg(request_state *req)
   6089 {
   6090     if (req->ts == t_terminated || req->ts == t_error)
   6091     {
   6092         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6093                   "[R%u] ERROR: read_msg called with transfer state terminated or error", req->request_id);
   6094         req->ts = t_error;
   6095         return;
   6096     }
   6097 
   6098     if (req->ts == t_complete)  // this must be death or something is wrong
   6099     {
   6100         char buf[4];    // dummy for death notification
   6101         const ssize_t nread = udsSupportReadFD(req->sd, buf, 4, 0, req->platform_data);
   6102         if (!nread) { req->ts = t_terminated; return; }
   6103         if (nread < 0) goto rerror;
   6104         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6105                   "[R%u] ERROR: read data from a completed request", req->request_id);
   6106         req->ts = t_error;
   6107         return;
   6108     }
   6109 
   6110     if (req->ts != t_morecoming)
   6111     {
   6112         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6113                   "[R%u] ERROR: read_msg called with invalid transfer state (%d)", req->request_id, req->ts);
   6114         req->ts = t_error;
   6115         return;
   6116     }
   6117 
   6118     if (req->hdr_bytes < sizeof(ipc_msg_hdr))
   6119     {
   6120         const mDNSu32 nleft = sizeof(ipc_msg_hdr) - req->hdr_bytes;
   6121         const ssize_t nread = udsSupportReadFD(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0, req->platform_data);
   6122         if (nread == 0) { req->ts = t_terminated; return; }
   6123         if (nread < 0) goto rerror;
   6124         req->hdr_bytes += (mDNSu32)nread;
   6125         if (req->hdr_bytes > sizeof(ipc_msg_hdr))
   6126         {
   6127             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6128                       "[R%u] ERROR: read_msg - read too many header bytes", req->request_id);
   6129             req->ts = t_error;
   6130             return;
   6131         }
   6132 
   6133         // only read data if header is complete
   6134         if (req->hdr_bytes == sizeof(ipc_msg_hdr))
   6135         {
   6136             ConvertHeaderBytes(&req->hdr);
   6137             if (req->hdr.version != VERSION)
   6138             {
   6139                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6140                           "[R%u] ERROR: client version 0x%08X daemon version 0x%08X", req->request_id, req->hdr.version, VERSION);
   6141                 req->ts = t_error;
   6142                 return;
   6143             }
   6144 
   6145             // Largest conceivable single request is a DNSServiceRegisterRecord() or DNSServiceAddRecord()
   6146             // with 64kB of rdata. Adding 1009 byte for a maximal domain name, plus a safety margin
   6147             // for other overhead, this means any message above 70kB is definitely bogus.
   6148             if (req->hdr.datalen > 70000)
   6149             {
   6150                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6151                           "[R%u] ERROR: read_msg: hdr.datalen %u (0x%X) > 70000", req->request_id, req->hdr.datalen, req->hdr.datalen);
   6152                 req->ts = t_error;
   6153                 return;
   6154             }
   6155             req->msgbuf = (uint8_t *)callocL("request_state msgbuf", req->hdr.datalen + MSG_PAD_BYTES);
   6156             if (!req->msgbuf) { my_perror("ERROR: calloc"); req->ts = t_error; return; }
   6157             req->msgptr = req->msgbuf;
   6158             req->msgend = req->msgbuf + req->hdr.datalen;
   6159         }
   6160     }
   6161 
   6162     // If our header is complete, but we're still needing more body data, then try to read it now
   6163     // Note: For cancel_request req->hdr.datalen == 0, but there's no error return socket for cancel_request
   6164     // Any time we need to get the error return socket we know we'll have at least one data byte
   6165     // (even if only the one-byte empty C string placeholder for the old ctrl_path parameter)
   6166     if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes < req->hdr.datalen)
   6167     {
   6168         size_t nleft = req->hdr.datalen - req->data_bytes;
   6169         ssize_t nread;
   6170 #if !defined(_WIN32)
   6171         struct iovec vec = { req->msgbuf + req->data_bytes, nleft };    // Tell recvmsg where we want the bytes put
   6172         struct msghdr msg;
   6173         struct cmsghdr *cmsg = NULL;
   6174         char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
   6175         msg.msg_name       = 0;
   6176         msg.msg_namelen    = 0;
   6177         msg.msg_iov        = &vec;
   6178         msg.msg_iovlen     = 1;
   6179         msg.msg_control    = cbuf;
   6180         msg.msg_controllen = sizeof(cbuf);
   6181         msg.msg_flags      = 0;
   6182         nread = recvmsg(req->sd, &msg, 0);
   6183 #else
   6184         nread = udsSupportReadFD(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0, req->platform_data);
   6185 #endif
   6186         if (nread == 0) { req->ts = t_terminated; return; }
   6187         if (nread < 0) goto rerror;
   6188         req->data_bytes += (size_t)nread;
   6189         if (req->data_bytes > req->hdr.datalen)
   6190         {
   6191             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6192                       "[R%u] ERROR: read_msg - read too many data bytes", req->request_id);
   6193             req->ts = t_error;
   6194             return;
   6195         }
   6196 #if !defined(_WIN32)
   6197         // There is no error sd if IPC_FLAGS_NOERRSD is set.
   6198         if (!(req->hdr.ipc_flags & IPC_FLAGS_NOERRSD))
   6199         {
   6200             cmsg = CMSG_FIRSTHDR(&msg);
   6201         }
   6202 #if defined(DEBUG_64BIT_SCM_RIGHTS) && DEBUG_64BIT_SCM_RIGHTS
   6203         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6204                   "[R%u] Expecting %d %d %d %d", req->request_id, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS);
   6205         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6206                   "[R%u] Got       %d %d %d %d", req->request_id, msg.msg_controllen, cmsg ? cmsg->cmsg_len : -1, cmsg ? cmsg->cmsg_level : -1, cmsg ? cmsg->cmsg_type : -1);
   6207 #endif // DEBUG_64BIT_SCM_RIGHTS
   6208         if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
   6209         {
   6210             req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
   6211 #if defined(DEBUG_64BIT_SCM_RIGHTS) && DEBUG_64BIT_SCM_RIGHTS
   6212             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6213                       "[R%u] read req->errsd %d", req->request_id, req->errsd);
   6214 #endif // DEBUG_64BIT_SCM_RIGHTS
   6215             if (req->data_bytes < req->hdr.datalen)
   6216             {
   6217                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
   6218                           "[R%u] Client(PID [%d](" PUB_S ")) sent result code socket %d via SCM_RIGHTS with req->data_bytes %lu < req->hdr.datalen %d",
   6219                           req->request_id, req->process_id, req->pid_name, req->errsd, (unsigned long)req->data_bytes, req->hdr.datalen);
   6220                 req->ts = t_error;
   6221                 return;
   6222             }
   6223         }
   6224 #endif
   6225     }
   6226 
   6227     // If our header and data are both complete, see if we need to make our separate error return socket
   6228     if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes == req->hdr.datalen)
   6229     {
   6230         if (!(req->hdr.ipc_flags & IPC_FLAGS_NOERRSD) && req->terminate && req->hdr.op != cancel_request)
   6231         {
   6232             dnssd_sockaddr_t cliaddr;
   6233 #if defined(USE_TCP_LOOPBACK)
   6234             mDNSOpaque16 port;
   6235             u_long opt = 1;
   6236             port.b[0] = req->msgptr[0];
   6237             port.b[1] = req->msgptr[1];
   6238             req->msgptr += 2;
   6239             cliaddr.sin_family      = AF_INET;
   6240             cliaddr.sin_port        = port.NotAnInteger;
   6241             cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
   6242 #else
   6243             char ctrl_path[MAX_CTLPATH];
   6244             get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH);  // path is first element in message buffer
   6245             mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr));
   6246             cliaddr.sun_family = AF_LOCAL;
   6247             mDNSPlatformStrLCopy(cliaddr.sun_path, ctrl_path, sizeof(cliaddr.sun_path));
   6248             // If the error return path UDS name is empty string, that tells us
   6249             // that this is a new version of the library that's going to pass us
   6250             // the error return path socket via sendmsg/recvmsg
   6251             if (ctrl_path[0] == 0)
   6252             {
   6253                 if (req->errsd == req->sd)
   6254                 {
   6255                     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6256                               "[R%u] read_msg: ERROR failed to get errsd via SCM_RIGHTS", req->request_id);
   6257                     req->ts = t_error;
   6258                     return;
   6259                 }
   6260                 goto got_errfd;
   6261             }
   6262 #endif
   6263 
   6264             req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0);
   6265             if (!dnssd_SocketValid(req->errsd))
   6266             {
   6267                 my_throttled_perror("ERROR: socket");
   6268                 req->ts = t_error;
   6269                 return;
   6270             }
   6271 
   6272             if (connect(req->errsd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
   6273             {
   6274 #if !defined(USE_TCP_LOOPBACK)
   6275                 struct stat sb;
   6276                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6277                           "[R%u] read_msg: Couldn't connect to error return path socket " PUB_S " errno %d (" PUB_S ")",
   6278                           req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
   6279                 if (stat(cliaddr.sun_path, &sb) < 0)
   6280                 {
   6281                     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6282                               "[R%u] read_msg: stat failed " PUB_S " errno %d (" PUB_S ")",
   6283                               req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
   6284                 }
   6285                 else
   6286                 {
   6287                     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6288                               "[R%u] read_msg: file " PUB_S " mode %o (octal) uid %d gid %d",
   6289                               req->request_id, cliaddr.sun_path, sb.st_mode, sb.st_uid, sb.st_gid);
   6290                 }
   6291 #endif
   6292                 req->ts = t_error;
   6293                 return;
   6294             }
   6295 
   6296 #if !defined(USE_TCP_LOOPBACK)
   6297 got_errfd:
   6298 #endif
   6299 
   6300 #if defined(_WIN32)
   6301             if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0)
   6302 #else
   6303             if (fcntl(req->errsd, F_SETFL, fcntl(req->errsd, F_GETFL, 0) | O_NONBLOCK) != 0)
   6304 #endif
   6305             {
   6306                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6307                           "[R%u] ERROR: could not set control socket to non-blocking mode errno %d (" PUB_S ")",
   6308                           req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
   6309                 req->ts = t_error;
   6310                 return;
   6311             }
   6312         }
   6313 
   6314         req->ts = t_complete;
   6315     }
   6316 
   6317     return;
   6318 
   6319 rerror:
   6320     if (dnssd_errno == dnssd_EWOULDBLOCK || dnssd_errno == dnssd_EINTR) return;
   6321     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6322               "[R%u] ERROR: read_msg errno %d (" PUB_S ")", req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
   6323     req->ts = t_error;
   6324 }
   6325 
   6326 mDNSlocal void returnAsyncErrorCode(request_state *const request, const mStatus error)
   6327 {
   6328     size_t len;
   6329     const char *const emptystr = "\0";
   6330     uint8_t *data;
   6331     reply_state *rep;
   6332 
   6333     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6334        "[R%u] returnAsyncErrorCode: error code(%d)", request->request_id, error);
   6335 
   6336     //Do not call callback when there is no error, refer to rdar://88599677
   6337     if (error == mStatus_NoError)
   6338     {
   6339         return;
   6340     }
   6341     // calculate reply length
   6342     len = sizeof(DNSServiceFlags);
   6343     len += sizeof(mDNSu32);  // interface index
   6344     len += sizeof(DNSServiceErrorType);
   6345     len += 2 * (strlen(emptystr) + 1); // empty name, empty target
   6346     len += 2 * sizeof(mDNSu16);  // port, txtLen
   6347     len += 0; //req->u.resolve.txt->rdlength;
   6348 
   6349     rep = create_reply(async_error_op, len, request);
   6350 
   6351     rep->rhdr->flags = 0;
   6352     rep->rhdr->ifi   = 0;
   6353     rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
   6354 
   6355     data = (uint8_t *)&rep->rhdr[1];
   6356 
   6357     // write reply data to message
   6358     put_string(emptystr, &data); // name
   6359     put_string(emptystr, &data); // target
   6360     put_uint16(0,        &data); // port
   6361     put_uint16(0,        &data); // txtLen
   6362 
   6363     append_reply(request, rep);
   6364 }
   6365 
   6366 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   6367 mDNSlocal mStatus request_state_prepare_audit_token(request_state *const req)
   6368 {
   6369     mStatus err;
   6370     mdns_require_action_quiet(!req->peer_token, exit, err = mStatus_NoError);
   6371 
   6372     audit_token_t token;
   6373     memset(&token, 0, sizeof(token));
   6374     const OSStatus token_err = mdns_system_get_peer_audit_token_from_uds_connection(req->sd, &token);
   6375     mdns_require_noerr_action_quiet(token_err, exit, err = mStatus_NoError;
   6376         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
   6377         "[R%u] Failed to get peer audit token -- error: %ld, client pid: %lld (" PUB_S ")",
   6378         req->request_id, (long)token_err, (long long)req->process_id, req->pid_name));
   6379 
   6380     req->peer_token = mdns_audit_token_create(&token);
   6381     mdns_require_action_quiet(req->peer_token, exit, err = mStatus_NoMemoryErr;
   6382         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
   6383         "[R%u] Failed to create peer audit token -- client pid: %lld (" PUB_S ")",
   6384         req->request_id, (long long)req->process_id, req->pid_name));
   6385 
   6386     err = mStatus_NoError;
   6387 
   6388 exit:
   6389     return err;
   6390 }
   6391 #endif
   6392 
   6393 mDNSlocal mStatus handle_client_request(request_state *req)
   6394 {
   6395     mStatus err = mStatus_NoError;
   6396 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   6397     err = request_state_prepare_audit_token(req);
   6398     mdns_require_noerr_quiet(err, exit);
   6399 #endif
   6400     switch(req->hdr.op)
   6401     {
   6402             // These are all operations that have their own first-class request_state object
   6403         case connection_request:
   6404             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6405                    "[R%d] DNSServiceCreateConnection START PID[%d](" PUB_S ")",
   6406                    req->request_id, req->process_id, req->pid_name);
   6407             req->terminate = connection_termination;
   6408             break;
   6409         case connection_delegate_request:
   6410             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   6411                    "[R%d] DNSServiceCreateDelegateConnection START PID[%d](" PUB_S ")",
   6412                    req->request_id, req->process_id, req->pid_name);
   6413             req->terminate = connection_termination;
   6414             handle_connection_delegate_request(req);
   6415             break;
   6416         case resolve_request:              err = handle_resolve_request     (req);  break;
   6417         case query_request:                err = handle_queryrecord_request (req);  break;
   6418         case browse_request:               err = handle_browse_request      (req);  break;
   6419         case reg_service_request:          err = handle_regservice_request  (req);  break;
   6420         case enumeration_request:          err = handle_enum_request        (req);  break;
   6421         case reconfirm_record_request:     err = handle_reconfirm_request   (req);  break;
   6422         case setdomain_request:            err = handle_setdomain_request   (req);  break;
   6423         case getproperty_request:                handle_getproperty_request (req);  break;
   6424         case port_mapping_request:         err = handle_port_mapping_request(req);  break;
   6425         case addrinfo_request:             err = handle_addrinfo_request    (req);  break;
   6426 
   6427             // These are all operations that work with an existing request_state object
   6428         case reg_record_request:           err = handle_regrecord_request   (req);  break;
   6429         case add_record_request:           err = handle_add_request         (req);  break;
   6430         case update_record_request:        err = handle_update_request      (req);  break;
   6431         case remove_record_request:        err = handle_removerecord_request(req);  break;
   6432         case cancel_request:                     handle_cancel_request      (req);  break;
   6433         case release_request:              err = handle_release_request     (req);  break;
   6434         case send_bpf_OBSOLETE:            // No longer supported.
   6435         default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]",
   6436                         req->sd, req->hdr.op, req->process_id, req->pid_name);
   6437             err = mStatus_BadParamErr;
   6438             break;
   6439     }
   6440 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   6441 exit:
   6442 #endif
   6443     return err;
   6444 }
   6445 
   6446 #define RecordOrientedOp(X) \
   6447     ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request)
   6448 
   6449 // The lightweight operations are the ones that don't need a dedicated request_state structure allocated for them
   6450 #define LightweightOp(X) (RecordOrientedOp(X) || (X) == cancel_request)
   6451 
   6452 mDNSlocal void request_callback(int fd, void *info)
   6453 {
   6454     request_state *req = info;
   6455     (void)fd; // Unused
   6456 
   6457     for (;;)
   6458     {
   6459         mStatus err = mStatus_NoError;
   6460         mDNSs32 min_size = sizeof(DNSServiceFlags);
   6461 
   6462         read_msg(req);
   6463         if (req->ts == t_morecoming)
   6464             return;
   6465         if (req->ts == t_terminated || req->ts == t_error)
   6466         {
   6467             AbortUnlinkAndFree(req);
   6468             return;
   6469         }
   6470         if (req->ts != t_complete)
   6471         {
   6472             LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name);
   6473             AbortUnlinkAndFree(req);
   6474             return;
   6475         }
   6476 
   6477         switch(req->hdr.op)            //          Interface       + other data
   6478         {
   6479             case connection_request:       min_size = 0;                                                                           break;
   6480             case connection_delegate_request: min_size = 4; /* pid */                                                              break;
   6481             case reg_service_request:      min_size += sizeof(mDNSu32) + 4 /* name, type, domain, host */ + 4 /* port, textlen */; break;
   6482             case add_record_request:       min_size +=                   4 /* type, rdlen */              + 4 /* ttl */;           break;
   6483             case update_record_request:    min_size +=                   2 /* rdlen */                    + 4 /* ttl */;           break;
   6484             case remove_record_request:                                                                                            break;
   6485             case browse_request:           min_size += sizeof(mDNSu32) + 2 /* type, domain */;                                     break;
   6486             case resolve_request:          min_size += sizeof(mDNSu32) + 3 /* type, type, domain */;                               break;
   6487             case query_request:            min_size += sizeof(mDNSu32) + 1 /* name */                     + 4 /* type, class*/;    break;
   6488             case enumeration_request:      min_size += sizeof(mDNSu32);                                                            break;
   6489             case reg_record_request:       min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */ + 4 /* ttl */;  break;
   6490             case reconfirm_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */;                break;
   6491             case setdomain_request:        min_size +=                   1 /* domain */;                                           break;
   6492             case getproperty_request:      min_size = 2;                                                                           break;
   6493             case port_mapping_request:     min_size += sizeof(mDNSu32) + 4 /* udp/tcp */ + 4 /* int/ext port */    + 4 /* ttl */;  break;
   6494             case addrinfo_request:         min_size += sizeof(mDNSu32) + 4 /* v4/v6 */   + 1 /* hostname */;                       break;
   6495             case cancel_request:           min_size = 0;                                                                           break;
   6496             case release_request:          min_size += sizeof(mDNSu32) + 3 /* type, type, domain */;                               break;
   6497             case send_bpf_OBSOLETE:        // No longer supported.
   6498             default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]",
   6499                             req->hdr.op, req->process_id, req->pid_name);
   6500                      min_size = -1;                                                                                                break;
   6501         }
   6502 
   6503         if ((mDNSs32)req->data_bytes < min_size)
   6504         {
   6505             LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]",
   6506                     req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name);
   6507             AbortUnlinkAndFree(req);
   6508             return;
   6509         }
   6510         if (LightweightOp(req->hdr.op) && !req->terminate)
   6511         {
   6512             LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]",
   6513                     req->hdr.op, req->process_id, req->pid_name);
   6514             AbortUnlinkAndFree(req);
   6515             return;
   6516         }
   6517 
   6518         // If req->terminate is already set, this means this operation is sharing an existing connection
   6519         if (req->terminate && !LightweightOp(req->hdr.op))
   6520         {
   6521             request_state *newreq = NewRequest();
   6522             newreq->primary = req;
   6523             newreq->sd      = req->sd;
   6524             newreq->errsd   = req->errsd;
   6525             newreq->uid     = req->uid;
   6526             newreq->hdr     = req->hdr;
   6527             newreq->msgbuf  = req->msgbuf;
   6528             newreq->msgptr  = req->msgptr;
   6529             newreq->msgend  = req->msgend;
   6530             newreq->request_id = GetNewRequestID();
   6531             newreq->request_start_time_secs = 0;
   6532             newreq->last_full_log_time_secs = 0;
   6533 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
   6534             mdns_replace(&newreq->peer_token, req->peer_token);
   6535 #endif
   6536             // if the parent request is a delegate connection, copy the
   6537             // relevant bits
   6538             if (req->validUUID)
   6539             {
   6540                 newreq->validUUID = mDNStrue;
   6541                 mDNSPlatformMemCopy(newreq->uuid, req->uuid, UUID_SIZE);
   6542             }
   6543             else
   6544             {
   6545                 if (req->process_id)
   6546                 {
   6547                     newreq->process_id = req->process_id;
   6548                     mDNSPlatformStrLCopy(newreq->pid_name, req->pid_name, (mDNSu32)sizeof(newreq->pid_name));
   6549                 }
   6550                 else
   6551                 {
   6552                     set_peer_pid(newreq);
   6553                 }
   6554             }
   6555             req = newreq;
   6556         }
   6557 
   6558         // Check if the request wants no asynchronous replies.
   6559         if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = mDNStrue;
   6560 
   6561         // If we're shutting down, don't allow new client requests
   6562         // We do allow "cancel" and "getproperty" during shutdown
   6563         if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
   6564             err = mStatus_ServiceNotRunning;
   6565         else
   6566             err = handle_client_request(req);
   6567 
   6568         // req->msgbuf may be NULL, e.g. for connection_request or remove_record_request
   6569         if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
   6570 
   6571         // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
   6572         // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
   6573         if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request && req->hdr.op != getpid_request)
   6574         {
   6575             const mStatus err_netorder = (mStatus)dnssd_htonl((mDNSu32)err);
   6576             if ((req->hdr.ipc_flags & IPC_FLAGS_NOERRSD))
   6577             {
   6578                 returnAsyncErrorCode(req, err);
   6579             }
   6580             else
   6581             {
   6582                 send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder));
   6583             }
   6584             if (req->errsd != req->sd)
   6585             {
   6586                 dnssd_close(req->errsd);
   6587                 req->errsd = req->sd;
   6588                 // Also need to reset the parent's errsd, if this is a subordinate operation
   6589                 if (req->primary) req->primary->errsd = req->primary->sd;
   6590             }
   6591         }
   6592 
   6593         // Reset ready to accept the next req on this pipe
   6594         if (req->primary) req = req->primary;
   6595         req->ts         = t_morecoming;
   6596         req->hdr_bytes  = 0;
   6597         req->data_bytes = 0;
   6598         req->msgbuf     = mDNSNULL;
   6599         req->msgptr     = mDNSNULL;
   6600         req->msgend     = 0;
   6601     }
   6602 }
   6603 
   6604 mDNSlocal void connect_callback(int fd, void *info)
   6605 {
   6606     dnssd_sockaddr_t cliaddr;
   6607     dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
   6608     dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
   6609 #if defined(SO_NOSIGPIPE) || defined(_WIN32)
   6610     unsigned int optval = 1;
   6611 #endif
   6612 
   6613     (void)info; // Unused
   6614 
   6615     if (!dnssd_SocketValid(sd))
   6616     {
   6617         if (dnssd_errno != dnssd_EWOULDBLOCK)
   6618             my_throttled_perror("ERROR: accept");
   6619         return;
   6620     }
   6621 
   6622 #ifdef SO_NOSIGPIPE
   6623     // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
   6624     if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
   6625     {
   6626         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "%3d: WARNING: setsockopt - SO_NOSIGPIPE %d (" PUB_S ")", sd, dnssd_errno,
   6627             dnssd_strerror(dnssd_errno));
   6628     }
   6629 
   6630 #endif
   6631 
   6632 #if defined(_WIN32)
   6633     if (ioctlsocket(sd, FIONBIO, &optval) != 0)
   6634 #else
   6635     if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK) != 0)
   6636 #endif
   6637     {
   6638         my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
   6639         dnssd_close(sd);
   6640         return;
   6641     }
   6642     else
   6643     {
   6644         request_state *request = NewRequest();
   6645         request->ts    = t_morecoming;
   6646         request->sd    = sd;
   6647         request->errsd = sd;
   6648         request->request_id = GetNewRequestID();
   6649         request->request_start_time_secs = 0;
   6650         request->last_full_log_time_secs = 0;
   6651         set_peer_pid(request);
   6652         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "%3d: connect_callback: Adding FD for uid %u", request->sd, request->uid);
   6653         udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data);
   6654     }
   6655 }
   6656 
   6657 mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
   6658 {
   6659 #if defined(SO_NP_EXTENSIONS)
   6660     struct      so_np_extensions sonpx;
   6661     socklen_t optlen = sizeof(struct so_np_extensions);
   6662     sonpx.npx_flags = SONPX_SETOPTSHUT;
   6663     sonpx.npx_mask  = SONPX_SETOPTSHUT;
   6664     if (setsockopt(skt, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, optlen) < 0)
   6665         my_perror("WARNING: could not set sockopt - SO_NP_EXTENSIONS");
   6666 #endif
   6667 #if defined(_WIN32)
   6668     // SEH: do we even need to do this on windows?
   6669     // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
   6670     u_long opt = 1;
   6671     if (ioctlsocket(skt, FIONBIO, &opt) != 0)
   6672 #else
   6673     if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) != 0)
   6674 #endif
   6675     {
   6676         my_perror("ERROR: could not set listen socket to non-blocking mode");
   6677         return mDNSfalse;
   6678     }
   6679 
   6680     if (listen(skt, LISTENQ) != 0)
   6681     {
   6682         my_perror("ERROR: could not listen on listen socket");
   6683         return mDNSfalse;
   6684     }
   6685 
   6686     if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL, (void **) NULL))
   6687     {
   6688         my_perror("ERROR: could not add listen socket to event loop");
   6689         return mDNSfalse;
   6690     }
   6691     else
   6692     {
   6693         LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
   6694         mDNSStorage.uds_listener_skt = skt;
   6695     }
   6696     return mDNStrue;
   6697 }
   6698 
   6699 #if MDNS_MALLOC_DEBUGGING
   6700 mDNSlocal void udsserver_validatelists(void *context);
   6701 #endif
   6702 
   6703 mDNSexport int udsserver_init(dnssd_sock_t skts[], const size_t count)
   6704 {
   6705     dnssd_sockaddr_t laddr;
   6706     int ret;
   6707 
   6708 #ifndef NO_PID_FILE
   6709     FILE *fp = fopen(PID_FILE, "w");
   6710     if (fp != NULL)
   6711     {
   6712         fprintf(fp, "%d\n", getpid());
   6713         fclose(fp);
   6714     }
   6715 #endif
   6716 
   6717 #if MDNS_MALLOC_DEBUGGING
   6718 	static mDNSListValidator validator;
   6719 	mDNSPlatformAddListValidator(&validator, udsserver_validatelists, "udsserver_validatelists", NULL);
   6720 #endif
   6721 
   6722     if (skts)
   6723     {
   6724         size_t i;
   6725         for (i = 0; i < count; i++)
   6726             if (dnssd_SocketValid(skts[i]) && !uds_socket_setup(skts[i]))
   6727                 goto error;
   6728     }
   6729     else
   6730     {
   6731         listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
   6732         if (!dnssd_SocketValid(listenfd))
   6733         {
   6734             my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
   6735             goto error;
   6736         }
   6737 
   6738         mDNSPlatformMemZero(&laddr, sizeof(laddr));
   6739 
   6740         #if defined(USE_TCP_LOOPBACK)
   6741         {
   6742             laddr.sin_family = AF_INET;
   6743 #ifdef WIN32_CENTENNIAL
   6744             // sin_port = 0, use the first available port from the dynamic client port range (49152-65535)
   6745             // (Used to be MDNS_TCP_SERVERPORT_CENTENNIAL)
   6746 #else
   6747             laddr.sin_port = htons(MDNS_TCP_SERVERPORT);
   6748 #endif
   6749             laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
   6750             ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
   6751             if (ret < 0)
   6752             {
   6753                 my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
   6754                 goto error;
   6755             }
   6756 
   6757 #ifdef WIN32_CENTENNIAL
   6758             // Retrieve the port number assigned to the socket
   6759             mDNSPlatformMemZero(&laddr, sizeof(laddr));
   6760             int len = sizeof(laddr);
   6761 
   6762             ret = getsockname(listenfd, (struct sockaddr*)&laddr, &len);
   6763             if (ret < 0)
   6764             {
   6765                 my_perror("ERROR: getsockname(listenfd, (struct sockaddr*)&laddr, &len); failed");
   6766                 goto error;
   6767             }
   6768 
   6769             char port[128];
   6770             if (0 != _ultoa_s(ntohs(laddr.sin_port), port, sizeof(port), 10))
   6771             {
   6772                 my_perror("ERROR: _itoa_s(ntohs(laddr.sin_port), &port); failed");
   6773                 goto error;
   6774             }
   6775             if (!SetEnvironmentVariableA("MDNS_TCP_SERVERPORT_CENTENNIAL", port))
   6776             {
   6777                 my_perror("ERROR: SetEnvironmentVariableA(MDNS_TCP_SERVERPORT_CENTENNIAL, port); failed");
   6778                 goto error;
   6779             }
   6780 #endif
   6781         }
   6782         #else
   6783         {
   6784             mode_t mask = umask(0);
   6785             unlink(boundPath);  // OK if this fails
   6786             laddr.sun_family = AF_LOCAL;
   6787             #ifndef NOT_HAVE_SA_LEN
   6788             // According to Stevens (section 3.2), there is no portable way to
   6789             // determine whether sa_len is defined on a particular platform.
   6790             laddr.sun_len = sizeof(struct sockaddr_un);
   6791             #endif
   6792             if (strlen(boundPath) >= sizeof(laddr.sun_path))
   6793             {
   6794                 LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
   6795                 goto error;
   6796             }
   6797             mDNSPlatformStrLCopy(laddr.sun_path, boundPath, sizeof(laddr.sun_path));
   6798             ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
   6799             umask(mask);
   6800             if (ret < 0)
   6801             {
   6802                 LogMsg("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed `%s': %s", boundPath, strerror(errno));
   6803                 goto error;
   6804             }
   6805         }
   6806         #endif
   6807 
   6808         if (!uds_socket_setup(listenfd)) goto error;
   6809     }
   6810 
   6811 #if !defined(PLATFORM_NO_RLIMIT)
   6812     {
   6813         // Set maximum number of open file descriptors
   6814     #define MIN_OPENFILES 10240
   6815         struct rlimit maxfds, newfds;
   6816 
   6817         // Due to bugs in OS X (<rdar://problem/2941095>, <rdar://problem/3342704>, <rdar://problem/3839173>)
   6818         // you have to get and set rlimits once before getrlimit will return sensible values
   6819         if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
   6820         if (setrlimit(RLIMIT_NOFILE, &maxfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
   6821 
   6822         if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
   6823         newfds.rlim_max = (maxfds.rlim_max > MIN_OPENFILES) ? maxfds.rlim_max : MIN_OPENFILES;
   6824         newfds.rlim_cur = (maxfds.rlim_cur > MIN_OPENFILES) ? maxfds.rlim_cur : MIN_OPENFILES;
   6825         if (newfds.rlim_max != maxfds.rlim_max || newfds.rlim_cur != maxfds.rlim_cur)
   6826             if (setrlimit(RLIMIT_NOFILE, &newfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
   6827 
   6828         if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
   6829         debugf("maxfds.rlim_max %d", (long)maxfds.rlim_max);
   6830         debugf("maxfds.rlim_cur %d", (long)maxfds.rlim_cur);
   6831     }
   6832 #endif
   6833 
   6834     // We start a "LocalOnly" query looking for Automatic Browse Domain records.
   6835     // When Domain Enumeration in uDNS.c finds an "lb" record from the network, its "FoundDomain" routine
   6836     // creates a "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
   6837     mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ_Internal, mDNS_DomainTypeBrowseAutomatic,
   6838         mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL);
   6839 
   6840     // Add "local" as recommended registration domain ("dns-sd -E"), recommended browsing domain ("dns-sd -F"), and automatic browsing domain
   6841     RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration);
   6842     RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse);
   6843     AddAutoBrowseDomain(0, &localdomain);
   6844 
   6845     udsserver_handle_configchange(&mDNSStorage);
   6846     return 0;
   6847 
   6848 error:
   6849 
   6850     my_perror("ERROR: udsserver_init");
   6851     return -1;
   6852 }
   6853 
   6854 mDNSexport int udsserver_exit(void)
   6855 {
   6856     // Cancel all outstanding client requests
   6857     while (all_requests) AbortUnlinkAndFree(all_requests);
   6858 
   6859     // Clean up any special mDNSInterface_LocalOnly records we created, both the entries for "local" we
   6860     // created in udsserver_init, and others we created as a result of reading local configuration data
   6861     while (LocalDomainEnumRecords)
   6862     {
   6863         ARListElem *rem = LocalDomainEnumRecords;
   6864         LocalDomainEnumRecords = LocalDomainEnumRecords->next;
   6865         mDNS_Deregister(&mDNSStorage, &rem->ar);
   6866     }
   6867 
   6868     // If the launching environment created no listening socket,
   6869     // that means we created it ourselves, so we should clean it up on exit
   6870     if (dnssd_SocketValid(listenfd))
   6871     {
   6872         dnssd_close(listenfd);
   6873 #if !defined(USE_TCP_LOOPBACK)
   6874         // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
   6875         // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
   6876         // It would be nice if we could find a solution to this problem
   6877         if (unlink(boundPath))
   6878             debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
   6879 #endif
   6880     }
   6881 
   6882 #ifndef NO_PID_FILE
   6883     unlink(PID_FILE);
   6884 #endif
   6885 
   6886     return 0;
   6887 }
   6888 
   6889 mDNSlocal void LogClientInfoToFD(int fd, request_state *req)
   6890 {
   6891     char reqIDStr[14];
   6892     char prefix[18];
   6893 
   6894     mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
   6895 
   6896     mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
   6897 
   6898     if (!req->terminate)
   6899         LogToFD(fd, "%s No operation yet on this socket", prefix);
   6900     else if (req->terminate == connection_termination)
   6901     {
   6902         int num_records = 0, num_ops = 0;
   6903         const registered_record_entry *p;
   6904         request_state *r;
   6905         for (p = req->reg_recs; p; p=p->next)
   6906         {
   6907             num_records++;
   6908         }
   6909         for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
   6910         LogToFD(fd, "%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
   6911                   prefix, num_records, num_records != 1 ? "s" : "", num_ops,     num_ops     != 1 ? "s" : "",
   6912                   req->process_id, req->pid_name);
   6913         for (p = req->reg_recs; p; p=p->next)
   6914         {
   6915             LogToFD(fd, " ->  DNSServiceRegisterRecord   0x%08X %2d %3d %s PID[%d](%s)",
   6916                 req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
   6917         }
   6918         for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfoToFD(fd, r);
   6919     }
   6920     else if (req->terminate == regservice_termination_callback)
   6921     {
   6922         service_instance *ptr;
   6923         const request_servicereg *const servicereg = req->servicereg;
   6924         for (ptr = servicereg->instances; ptr; ptr = ptr->next)
   6925         {
   6926             LogToFD(fd, "%-9s DNSServiceRegister         0x%08X %2d %##s %u/%u PID[%d](%s)",
   6927                 (ptr == servicereg->instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
   6928                 mDNSVal16(servicereg->port),
   6929                 SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
   6930         }
   6931     }
   6932     else if (req->terminate == browse_termination_callback)
   6933     {
   6934         const request_browse *const browse = req->browse;
   6935         for (const browser_t *blist = browse->browsers; blist; blist = blist->next)
   6936         {
   6937             LogToFD(fd, "%-9s DNSServiceBrowse           0x%08X %2d %##s PID[%d](%s)",
   6938                 (blist == browse->browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
   6939                 req->process_id, req->pid_name);
   6940         }
   6941     }
   6942     else if (req->terminate == resolve_termination_callback)
   6943     {
   6944         LogToFD(fd, "%s DNSServiceResolve          0x%08X %2d %##s PID[%d](%s)",
   6945             prefix, req->flags, req->interfaceIndex, req->resolve->qsrv.qname.c, req->process_id, req->pid_name);
   6946     }
   6947     else if (req->terminate == queryrecord_termination_callback)
   6948     {
   6949         const QueryRecordClientRequest *const queryrecord = req->queryrecord;
   6950 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   6951         const bool redacted = (queryrecord->op.q.logPrivacyLevel == dnssd_log_privacy_level_private);
   6952 #endif
   6953 
   6954         LogToFD(fd, "%s DNSServiceQueryRecord      0x%08X %2d %##s (%s) PID[%d](%s)", prefix, req->flags,
   6955             req->interfaceIndex,
   6956 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   6957             redacted ? PRIVATE_DOMAIN_NAME : QueryRecordClientRequestGetQName(queryrecord),
   6958 #else
   6959             QueryRecordClientRequestGetQName(queryrecord),
   6960 #endif
   6961             DNSTypeName(QueryRecordClientRequestGetType(queryrecord)),
   6962             req->process_id, req->pid_name);
   6963     }
   6964     else if (req->terminate == enum_termination_callback)
   6965         LogToFD(fd, "%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
   6966                   prefix, req->flags, req->interfaceIndex, req->enumeration->q_all.qname.c, req->process_id, req->pid_name);
   6967     else if (req->terminate == port_mapping_termination_callback)
   6968     {
   6969         const request_port_mapping *const pm = req->pm;
   6970         LogToFD(fd, "%s DNSServiceNATPortMapping   0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)",
   6971             prefix,
   6972             req->flags,
   6973             req->interfaceIndex,
   6974             pm->NATinfo.Protocol & NATOp_MapTCP ? "TCP" : "   ",
   6975             pm->NATinfo.Protocol & NATOp_MapUDP ? "UDP" : "   ",
   6976             mDNSVal16(pm->NATinfo.IntPort),
   6977             mDNSVal16(pm->ReqExt),
   6978             &pm->NATinfo.ExternalAddress,
   6979             mDNSVal16(pm->NATinfo.ExternalPort),
   6980             pm->NATinfo.NATLease,
   6981             pm->NATinfo.Lifetime,
   6982             req->process_id, req->pid_name);
   6983     }
   6984     else if (req->terminate == addrinfo_termination_callback)
   6985     {
   6986         const GetAddrInfoClientRequest *const addrinfo = req->addrinfo;
   6987 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   6988         bool redacted = false;
   6989         if (addrinfo->op4)
   6990         {
   6991             redacted = (addrinfo->op4->q.logPrivacyLevel == dnssd_log_privacy_level_private);
   6992         }
   6993         else if (addrinfo->op6)
   6994         {
   6995             redacted = (addrinfo->op6->q.logPrivacyLevel == dnssd_log_privacy_level_private);
   6996         }
   6997 #endif
   6998 
   6999         LogToFD(fd, "%s DNSServiceGetAddrInfo      0x%08X %2d %s%s %##s PID[%d](%s)", prefix, req->flags,
   7000             req->interfaceIndex,
   7001             addrinfo->protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
   7002             addrinfo->protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
   7003 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   7004             redacted ? PRIVATE_DOMAIN_NAME : GetAddrInfoClientRequestGetQName(req->addrinfo),
   7005 #else
   7006             GetAddrInfoClientRequestGetQName(req->addrinfo),
   7007 #endif
   7008             req->process_id, req->pid_name);
   7009     }
   7010     else
   7011         LogToFD(fd, "%s Unrecognized operation %p", prefix, req->terminate);
   7012 }
   7013 
   7014 mDNSlocal void LogClientInfo(request_state *req)
   7015 {
   7016     char reqIDStr[14];
   7017     char prefix[18];
   7018 
   7019     mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
   7020 
   7021     mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
   7022 
   7023     if (!req->terminate)
   7024     LogMsgNoIdent("%s No operation yet on this socket", prefix);
   7025     else if (req->terminate == connection_termination)
   7026     {
   7027         int num_records = 0, num_ops = 0;
   7028         const registered_record_entry *p;
   7029         request_state *r;
   7030         for (p = req->reg_recs; p; p=p->next)
   7031         {
   7032             num_records++;
   7033         }
   7034         for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
   7035         LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
   7036                       prefix, num_records, num_records != 1 ? "s" : "", num_ops,     num_ops     != 1 ? "s" : "",
   7037                       req->process_id, req->pid_name);
   7038         for (p = req->reg_recs; p; p=p->next)
   7039         {
   7040             LogMsgNoIdent(" ->  DNSServiceRegisterRecord   0x%08X %2d %3d %s PID[%d](%s)",
   7041                 req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
   7042         }
   7043         for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(r);
   7044     }
   7045     else if (req->terminate == regservice_termination_callback)
   7046     {
   7047         service_instance *ptr;
   7048         const request_servicereg *const servicereg = req->servicereg;
   7049         for (ptr = servicereg->instances; ptr; ptr = ptr->next)
   7050         {
   7051             LogMsgNoIdent("%-9s DNSServiceRegister         0x%08X %2d %##s %u/%u PID[%d](%s)",
   7052                 (ptr == servicereg->instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
   7053                 mDNSVal16(servicereg->port),
   7054                 SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
   7055         }
   7056     }
   7057     else if (req->terminate == browse_termination_callback)
   7058     {
   7059         const request_browse *const browse = req->browse;
   7060         for (const browser_t *blist = browse->browsers; blist; blist = blist->next)
   7061         {
   7062             LogMsgNoIdent("%-9s DNSServiceBrowse           0x%08X %2d %##s PID[%d](%s)",
   7063                 (blist == browse->browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
   7064                 req->process_id, req->pid_name);
   7065         }
   7066     }
   7067     else if (req->terminate == resolve_termination_callback)
   7068     LogMsgNoIdent("%s DNSServiceResolve          0x%08X %2d %##s PID[%d](%s)",
   7069                   prefix, req->flags, req->interfaceIndex, req->resolve->qsrv.qname.c, req->process_id, req->pid_name);
   7070     else if (req->terminate == queryrecord_termination_callback)
   7071     {
   7072         LogMsgNoIdent("%s DNSServiceQueryRecord      0x%08X %2d %##s (%s) PID[%d](%s)",
   7073             prefix, req->flags, req->interfaceIndex, QueryRecordClientRequestGetQName(req->queryrecord),
   7074             DNSTypeName(QueryRecordClientRequestGetType(req->queryrecord)), req->process_id, req->pid_name);
   7075     }
   7076     else if (req->terminate == enum_termination_callback)
   7077     LogMsgNoIdent("%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
   7078                   prefix, req->flags, req->interfaceIndex, req->enumeration->q_all.qname.c, req->process_id, req->pid_name);
   7079     else if (req->terminate == port_mapping_termination_callback)
   7080     {
   7081         const request_port_mapping *const pm = req->pm;
   7082         LogMsgNoIdent("%s DNSServiceNATPortMapping   0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)",
   7083             prefix,
   7084             req->flags,
   7085             req->interfaceIndex,
   7086             pm->NATinfo.Protocol & NATOp_MapTCP ? "TCP" : "   ",
   7087             pm->NATinfo.Protocol & NATOp_MapUDP ? "UDP" : "   ",
   7088             mDNSVal16(pm->NATinfo.IntPort),
   7089             mDNSVal16(pm->ReqExt),
   7090             &pm->NATinfo.ExternalAddress,
   7091             mDNSVal16(pm->NATinfo.ExternalPort),
   7092             pm->NATinfo.NATLease,
   7093             pm->NATinfo.Lifetime,
   7094             req->process_id, req->pid_name);
   7095     }
   7096     else if (req->terminate == addrinfo_termination_callback)
   7097     {
   7098         const GetAddrInfoClientRequest *const addrinfo = req->addrinfo;
   7099         LogMsgNoIdent("%s DNSServiceGetAddrInfo      0x%08X %2d %s%s %##s PID[%d](%s)",
   7100             prefix, req->flags, req->interfaceIndex,
   7101             addrinfo->protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
   7102             addrinfo->protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
   7103             GetAddrInfoClientRequestGetQName(addrinfo), req->process_id, req->pid_name);
   7104     }
   7105     else
   7106     LogMsgNoIdent("%s Unrecognized operation %p", prefix, req->terminate);
   7107 }
   7108 
   7109 mDNSlocal void GetMcastClients(request_state *req)
   7110 {
   7111     if (req->terminate == connection_termination)
   7112     {
   7113         int num_records = 0, num_ops = 0;
   7114         const registered_record_entry *p;
   7115         request_state *r;
   7116         for (p = req->reg_recs; p; p=p->next)
   7117         {
   7118             num_records++;
   7119         }
   7120         for (r = req->next; r; r=r->next)
   7121             if (r->primary == req)
   7122                 num_ops++;
   7123         for (p = req->reg_recs; p; p=p->next)
   7124         {
   7125             if (!AuthRecord_uDNS(p->rr))
   7126                 n_mrecords++;
   7127         }
   7128         for (r = req->next; r; r=r->next)
   7129             if (r->primary == req)
   7130                 GetMcastClients(r);
   7131     }
   7132     else if (req->terminate == regservice_termination_callback)
   7133     {
   7134         service_instance *ptr;
   7135         for (ptr = req->servicereg->instances; ptr; ptr = ptr->next)
   7136         {
   7137             if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
   7138                 n_mrecords++;
   7139         }
   7140     }
   7141     else if (req->terminate == browse_termination_callback)
   7142     {
   7143         for (const browser_t *blist = req->browse->browsers; blist; blist = blist->next)
   7144         {
   7145             if (mDNSOpaque16IsZero(blist->q.TargetQID))
   7146                 n_mquests++;
   7147         }
   7148     }
   7149     else if (req->terminate == resolve_termination_callback)
   7150     {
   7151         const request_resolve *const resolve = req->resolve;
   7152         if ((mDNSOpaque16IsZero(resolve->qsrv.TargetQID)) && (resolve->qsrv.ThisQInterval > 0))
   7153         {
   7154             n_mquests++;
   7155         }
   7156     }
   7157     else if (req->terminate == queryrecord_termination_callback)
   7158     {
   7159         if (QueryRecordClientRequestIsMulticast(req->queryrecord))
   7160         {
   7161             n_mquests++;
   7162         }
   7163     }
   7164     else if (req->terminate == addrinfo_termination_callback)
   7165     {
   7166         if (GetAddrInfoClientRequestIsMulticast(req->addrinfo))
   7167         {
   7168             n_mquests++;
   7169         }
   7170     }
   7171     else
   7172     {
   7173         return;
   7174     }
   7175 }
   7176 
   7177 
   7178 mDNSlocal void LogMcastClientInfo(request_state *req)
   7179 {
   7180     if (!req->terminate)
   7181         LogMcastNoIdent("No operation yet on this socket");
   7182     else if (req->terminate == connection_termination)
   7183     {
   7184         int num_records = 0, num_ops = 0;
   7185         const registered_record_entry *p;
   7186         request_state *r;
   7187         for (p = req->reg_recs; p; p=p->next)
   7188         {
   7189             num_records++;
   7190         }
   7191         for (r = req->next; r; r=r->next)
   7192             if (r->primary == req)
   7193                 num_ops++;
   7194         for (p = req->reg_recs; p; p=p->next)
   7195         {
   7196             if (!AuthRecord_uDNS(p->rr))
   7197                 LogMcastNoIdent("R: ->  DNSServiceRegisterRecord:  %##s %s PID[%d](%s)", p->rr->resrec.name->c,
   7198                                 DNSTypeName(p->rr->resrec.rrtype), req->process_id, req->pid_name, i_mcount++);
   7199         }
   7200         for (r = req->next; r; r=r->next)
   7201             if (r->primary == req)
   7202                 LogMcastClientInfo(r);
   7203     }
   7204     else if (req->terminate == regservice_termination_callback)
   7205     {
   7206         service_instance *ptr;
   7207         const request_servicereg *const servicereg = req->servicereg;
   7208         for (ptr = servicereg->instances; ptr; ptr = ptr->next)
   7209         {
   7210             if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
   7211             {
   7212                 LogMcastNoIdent("R: DNSServiceRegister:  %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(servicereg->port),
   7213                                 SRS_PORT(&ptr->srs), req->process_id, req->pid_name, i_mcount++);
   7214             }
   7215         }
   7216     }
   7217     else if (req->terminate == browse_termination_callback)
   7218     {
   7219         for (const browser_t *blist = req->browse->browsers; blist; blist = blist->next)
   7220         {
   7221             if (mDNSOpaque16IsZero(blist->q.TargetQID))
   7222                 LogMcastNoIdent("Q: DNSServiceBrowse  %##s %s PID[%d](%s)", blist->q.qname.c, DNSTypeName(blist->q.qtype),
   7223                                 req->process_id, req->pid_name, i_mcount++);
   7224         }
   7225     }
   7226     else if (req->terminate == resolve_termination_callback)
   7227     {
   7228         const request_resolve *const resolve = req->resolve;
   7229         if ((mDNSOpaque16IsZero(resolve->qsrv.TargetQID)) && (resolve->qsrv.ThisQInterval > 0))
   7230         {
   7231             LogMcastNoIdent("Q: DNSServiceResolve  %##s %s PID[%d](%s)", resolve->qsrv.qname.c, DNSTypeName(resolve->qsrv.qtype),
   7232                             req->process_id, req->pid_name, i_mcount++);
   7233         }
   7234     }
   7235     else if (req->terminate == queryrecord_termination_callback)
   7236     {
   7237         if (QueryRecordClientRequestIsMulticast(req->queryrecord))
   7238         {
   7239             LogMcastNoIdent("Q: DNSServiceQueryRecord  %##s %s PID[%d](%s)",
   7240                 QueryRecordClientRequestGetQName(req->queryrecord),
   7241                 DNSTypeName(QueryRecordClientRequestGetType(req->queryrecord)),
   7242                 req->process_id, req->pid_name, i_mcount++);
   7243         }
   7244     }
   7245     else if (req->terminate == addrinfo_termination_callback)
   7246     {
   7247         const GetAddrInfoClientRequest *const addrinfo = req->addrinfo;
   7248         if (GetAddrInfoClientRequestIsMulticast(addrinfo))
   7249         {
   7250             LogMcastNoIdent("Q: DNSServiceGetAddrInfo  %s%s %##s PID[%d](%s)",
   7251                 addrinfo->protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
   7252                 addrinfo->protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
   7253                 GetAddrInfoClientRequestGetQName(addrinfo), req->process_id, req->pid_name, i_mcount++);
   7254         }
   7255     }
   7256 }
   7257 
   7258 mDNSlocal char *RecordTypeName(mDNSu8 rtype)
   7259 {
   7260     switch (rtype)
   7261     {
   7262     case kDNSRecordTypeUnregistered:  return ("Unregistered ");
   7263     case kDNSRecordTypeDeregistering: return ("Deregistering");
   7264     case kDNSRecordTypeUnique:        return ("Unique       ");
   7265     case kDNSRecordTypeAdvisory:      return ("Advisory     ");
   7266     case kDNSRecordTypeShared:        return ("Shared       ");
   7267     case kDNSRecordTypeVerified:      return ("Verified     ");
   7268     case kDNSRecordTypeKnownUnique:   return ("KnownUnique  ");
   7269     default: return("Unknown");
   7270     }
   7271 }
   7272 
   7273 mDNSlocal int LogEtcHostsToFD(int fd, mDNS *const m)
   7274 {
   7275     mDNSBool showheader = mDNStrue;
   7276     const AuthRecord *ar;
   7277     mDNSu32 slot;
   7278     AuthGroup *ag;
   7279     int count = 0;
   7280     int authslot = 0;
   7281     mDNSBool truncated = 0;
   7282 
   7283     for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
   7284     {
   7285         if (m->rrauth.rrauth_hash[slot]) authslot++;
   7286         for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
   7287             for (ar = ag->members; ar; ar = ar->next)
   7288             {
   7289                 if (ar->RecordCallback != FreeEtcHosts) continue;
   7290                 if (showheader) { showheader = mDNSfalse; LogToFD(fd, "  State       Interface"); }
   7291 
   7292                 // Print a maximum of 50 records
   7293                 if (count++ >= 50) { truncated = mDNStrue; continue; }
   7294                 if (ar->ARType == AuthRecordLocalOnly)
   7295                 {
   7296                     if (ar->resrec.InterfaceID == mDNSInterface_LocalOnly)
   7297                         LogToFD(fd, " %s   LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
   7298                     else
   7299                     {
   7300                         mDNSu32 scopeid  = (mDNSu32)(uintptr_t)ar->resrec.InterfaceID;
   7301                         LogToFD(fd, " %s   %u  %s", RecordTypeName(ar->resrec.RecordType), scopeid, ARDisplayString(m, ar));
   7302                     }
   7303                 }
   7304             }
   7305     }
   7306 
   7307     if (showheader) LogToFD(fd, "<None>");
   7308     else if (truncated) LogToFD(fd, "<Truncated: to 50 records, Total records %d, Total Auth Groups %d, Auth Slots %d>", count, m->rrauth.rrauth_totalused, authslot);
   7309     return count;
   7310 }
   7311 
   7312 mDNSlocal void LogLocalOnlyAuthRecordsToFD(int fd, mDNS *const m)
   7313 {
   7314     mDNSBool showheader = mDNStrue;
   7315     const AuthRecord *ar;
   7316     mDNSu32 slot;
   7317     AuthGroup *ag;
   7318 
   7319     for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
   7320     {
   7321         for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
   7322             for (ar = ag->members; ar; ar = ar->next)
   7323             {
   7324                 if (ar->RecordCallback == FreeEtcHosts) continue;
   7325                 if (showheader) { showheader = mDNSfalse; LogToFD(fd, "  State       Interface"); }
   7326 
   7327                 // Print a maximum of 400 records
   7328                 if (ar->ARType == AuthRecordLocalOnly)
   7329                     LogToFD(fd, " %s   LO  %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
   7330                 else if (ar->ARType == AuthRecordP2P)
   7331                 {
   7332                     if (ar->resrec.InterfaceID == mDNSInterface_BLE)
   7333                         LogToFD(fd, " %s   BLE %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
   7334                     else
   7335                         LogToFD(fd, " %s   PP  %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
   7336                 }
   7337             }
   7338     }
   7339 
   7340     if (showheader) LogToFD(fd, "<None>");
   7341 }
   7342 
   7343 mDNSlocal void LogOneAuthRecordToFD(const int fd, const AuthRecord *const ar, const mDNSs32 now,
   7344     const char *const ifname)
   7345 {
   7346     char timeRegistered[MIN_TIMESTAMP_STRING_LENGTH];
   7347     getLocalTimestampFromPlatformTime(now, ar->TimeRegistered, timeRegistered, sizeof(timeRegistered));
   7348 
   7349     if (AuthRecord_uDNS(ar))
   7350     {
   7351         LogToFD(fd, "%s %7d %7d %7d %-7s %4d %s %s",
   7352             timeRegistered,
   7353             ar->ThisAPInterval / mDNSPlatformOneSecond,
   7354             (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
   7355             ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
   7356             "-U-",
   7357             ar->state,
   7358             ar->AllowRemoteQuery ? "" : " ",
   7359             ARDisplayString(&mDNSStorage, ar));
   7360     }
   7361     else
   7362     {
   7363         LogToFD(fd, "%s %7d %7d %7d %-7s 0x%02X %s %s",
   7364             timeRegistered,
   7365             ar->ThisAPInterval / mDNSPlatformOneSecond,
   7366             ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
   7367             ar->TimeExpire    ? (ar->TimeExpire                      - now) / mDNSPlatformOneSecond : 0,
   7368             ifname ? ifname : "ALL",
   7369             ar->resrec.RecordType,
   7370             ar->AllowRemoteQuery ? "" : " ",
   7371             ARDisplayString(&mDNSStorage, ar));
   7372     }
   7373 }
   7374 
   7375 mDNSlocal void LogAuthRecordsToFD(int fd,
   7376                                     const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
   7377 {
   7378     mDNSBool showheader = mDNStrue;
   7379     const AuthRecord *ar;
   7380     OwnerOptData owner = zeroOwner;
   7381     for (ar = ResourceRecords; ar; ar=ar->next)
   7382     {
   7383         const char *const ifname = InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID);
   7384         if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
   7385         {
   7386             if (showheader)
   7387             {
   7388                 showheader = mDNSfalse;
   7389                 LogToFD(fd, "Time Registered                  Int    Next  Expire if     State");
   7390             }
   7391             if (proxy) (*proxy)++;
   7392             if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
   7393             {
   7394                 owner = ar->WakeUp;
   7395                 if (owner.password.l[0])
   7396                     LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
   7397                 else if (!mDNSSameEthAddress(&owner.HMAC, &owner.IMAC))
   7398                     LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a seq %d",               &owner.HMAC, &owner.IMAC,                  owner.seq);
   7399                 else
   7400                     LogToFD(fd, "Proxying for %.6a seq %d",                                &owner.HMAC,                               owner.seq);
   7401             }
   7402             if (AuthRecord_uDNS(ar))
   7403             {
   7404                 LogOneAuthRecordToFD(fd, ar, now, ifname);
   7405             }
   7406             else if (ar->ARType == AuthRecordLocalOnly)
   7407             {
   7408                 LogToFD(fd, "                             LO %s", ARDisplayString(&mDNSStorage, ar));
   7409             }
   7410             else if (ar->ARType == AuthRecordP2P)
   7411             {
   7412                 if (ar->resrec.InterfaceID == mDNSInterface_BLE)
   7413                     LogToFD(fd, "                             BLE %s", ARDisplayString(&mDNSStorage, ar));
   7414                 else
   7415                     LogToFD(fd, "                             PP %s", ARDisplayString(&mDNSStorage, ar));
   7416             }
   7417             else
   7418             {
   7419                 LogOneAuthRecordToFD(fd, ar, now, ifname);
   7420             }
   7421         }
   7422     }
   7423     if (showheader) LogToFD(fd, "<None>");
   7424 }
   7425 
   7426 mDNSlocal void PrintOneCacheRecordToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
   7427 {
   7428 
   7429 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7430     char *dnssec_description = dnssec_obj_resource_record_member_copy_state_dump_description(cr->resrec.dnssec, NULL);
   7431 #endif
   7432 
   7433 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   7434     const mDNSBool redacted = (cr->PrivacyLevel == mDNSCRLogPrivacyLevel_Private);
   7435 #endif
   7436 
   7437     LogToFD(fd, "%3d %s%8d %-7s%s %-6s"
   7438 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7439               "   %-40s"
   7440 #endif
   7441               "%s",
   7442               slot,
   7443               cr->CRActiveQuestion ? "*" : " ",
   7444               remain,
   7445               ifname ? ifname : "-U-",
   7446               (cr->resrec.RecordType == kDNSRecordTypePacketNegative)  ? "-" :
   7447               (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+",
   7448               DNSTypeName(cr->resrec.rrtype),
   7449 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7450               dnssec_description,
   7451 #endif
   7452 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   7453               redacted ? "     " PRIVATE_RECORD_DESCRIPTION : CRDisplayString(&mDNSStorage, cr)
   7454 #else
   7455               CRDisplayString(&mDNSStorage, cr)
   7456 #endif
   7457             );
   7458     (*CacheUsed)++;
   7459 
   7460 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7461     mdns_free(dnssec_description);
   7462 #endif
   7463 }
   7464 
   7465 mDNSlocal void PrintCachedRecordsToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
   7466 {
   7467     CacheRecord *soa;
   7468 
   7469     soa = cr->soa;
   7470     if (soa)
   7471     {
   7472         PrintOneCacheRecordToFD(fd, soa, slot, remain, ifname, CacheUsed);
   7473     }
   7474 }
   7475 
   7476 mDNSexport void LogMDNSStatisticsToFD(int fd, mDNS *const m)
   7477 {
   7478     LogToFD(fd, "--- MDNS Statistics ---");
   7479 
   7480     LogToFD(fd, "Name Conflicts                 %u", m->mDNSStats.NameConflicts);
   7481     LogToFD(fd, "KnownUnique Name Conflicts     %u", m->mDNSStats.KnownUniqueNameConflicts);
   7482     LogToFD(fd, "Duplicate Query Suppressions   %u", m->mDNSStats.DupQuerySuppressions);
   7483     LogToFD(fd, "KA Suppressions                %u", m->mDNSStats.KnownAnswerSuppressions);
   7484     LogToFD(fd, "KA Multiple Packets            %u", m->mDNSStats.KnownAnswerMultiplePkts);
   7485     LogToFD(fd, "Poof Cache Deletions           %u", m->mDNSStats.PoofCacheDeletions);
   7486     LogToFD(fd, "--------------------------------");
   7487 
   7488     LogToFD(fd, "Multicast packets Sent         %u", m->MulticastPacketsSent);
   7489     LogToFD(fd, "Multicast packets Received     %u", m->MPktNum);
   7490     LogToFD(fd, "Remote Subnet packets          %u", m->RemoteSubnet);
   7491     LogToFD(fd, "QU questions  received         %u", m->mDNSStats.UnicastBitInQueries);
   7492     LogToFD(fd, "Normal multicast questions     %u", m->mDNSStats.NormalQueries);
   7493     LogToFD(fd, "Answers for questions          %u", m->mDNSStats.MatchingAnswersForQueries);
   7494     LogToFD(fd, "Unicast responses              %u", m->mDNSStats.UnicastResponses);
   7495     LogToFD(fd, "Multicast responses            %u", m->mDNSStats.MulticastResponses);
   7496     LogToFD(fd, "Unicast response Demotions     %u", m->mDNSStats.UnicastDemotedToMulticast);
   7497     LogToFD(fd, "--------------------------------");
   7498 
   7499     LogToFD(fd, "Sleeps                         %u", m->mDNSStats.Sleeps);
   7500     LogToFD(fd, "Wakeups                        %u", m->mDNSStats.Wakes);
   7501     LogToFD(fd, "Interface UP events            %u", m->mDNSStats.InterfaceUp);
   7502     LogToFD(fd, "Interface UP Flap events       %u", m->mDNSStats.InterfaceUpFlap);
   7503     LogToFD(fd, "Interface Down events          %u", m->mDNSStats.InterfaceDown);
   7504     LogToFD(fd, "Interface DownFlap events      %u", m->mDNSStats.InterfaceDownFlap);
   7505     LogToFD(fd, "Cache refresh queries          %u", m->mDNSStats.CacheRefreshQueries);
   7506     LogToFD(fd, "Cache refreshed                %u", m->mDNSStats.CacheRefreshed);
   7507     LogToFD(fd, "Wakeup on Resolves             %u", m->mDNSStats.WakeOnResolves);
   7508 }
   7509 
   7510 mDNSexport void udsserver_info_dump_to_fd(int fd)
   7511 {
   7512     mDNS *const m = &mDNSStorage;
   7513     const mDNSs32 now = mDNS_TimeNow(m);
   7514     mDNSu32 CacheUsed = 0, CacheActive = 0, slot;
   7515     int ProxyA = 0, ProxyD = 0;
   7516     mDNSu32 groupCount = 0;
   7517     mDNSu32 mcastRecordCount = 0;
   7518     mDNSu32 ucastRecordCount = 0;
   7519     const CacheGroup *cg;
   7520     const CacheRecord *cr;
   7521     const DNSQuestion *q;
   7522     const DNameListElem *d;
   7523     const SearchListElem *s;
   7524 
   7525     LogToFD(fd, "------------ Cache -------------");
   7526     LogToFD(fd, "Slt Q     TTL if     U Type     DNSSEC                                   rdlen");
   7527     for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
   7528     {
   7529         for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
   7530         {
   7531             groupCount++;   // Count one cache entity for the CacheGroup object
   7532             for (cr = cg->members; cr; cr=cr->next)
   7533             {
   7534                 const mDNSu32 remain = cr->resrec.rroriginalttl - (mDNSu32)((now - cr->TimeRcvd) / mDNSPlatformOneSecond);
   7535                 const char *ifname;
   7536                 mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
   7537                 mDNSu32 *const countPtr = InterfaceID ? &mcastRecordCount : &ucastRecordCount;
   7538 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   7539                 const mdns_dns_service_t dnsservice = mdns_cache_metadata_get_dns_service(cr->resrec.metadata);
   7540                 if (!InterfaceID && dnsservice && mdns_dns_service_is_interface_scoped(dnsservice))
   7541                 {
   7542                     InterfaceID = (mDNSInterfaceID)(uintptr_t)mdns_dns_service_get_interface_index(dnsservice);
   7543                 }
   7544 #else
   7545                 if (!InterfaceID && cr->resrec.rDNSServer && cr->resrec.rDNSServer->scopeType)
   7546                     InterfaceID = cr->resrec.rDNSServer->interface;
   7547 #endif
   7548                 ifname = InterfaceNameForID(m, InterfaceID);
   7549                 if (cr->CRActiveQuestion) CacheActive++;
   7550                 PrintOneCacheRecordToFD(fd, cr, slot, remain, ifname, countPtr);
   7551                 PrintCachedRecordsToFD(fd, cr, slot, remain, ifname, countPtr);
   7552             }
   7553         }
   7554     }
   7555 
   7556     CacheUsed = groupCount + mcastRecordCount + ucastRecordCount;
   7557     if (m->rrcache_totalused != CacheUsed)
   7558         LogToFD(fd, "Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed);
   7559     if (m->rrcache_active != CacheActive)
   7560         LogToFD(fd, "Cache use mismatch: rrcache_active is %lu, true count %lu", m->rrcache_active, CacheActive);
   7561     LogToFD(fd, "Cache size %u entities; %u in use (%u group, %u multicast, %u unicast); %u referenced by active questions",
   7562               m->rrcache_size, CacheUsed, groupCount, mcastRecordCount, ucastRecordCount, CacheActive);
   7563 
   7564     LogToFD(fd, "--------- Auth Records ---------");
   7565     LogAuthRecordsToFD(fd, now, m->ResourceRecords, mDNSNULL);
   7566 
   7567     LogToFD(fd, "--------- LocalOnly, P2P Auth Records ---------");
   7568     LogLocalOnlyAuthRecordsToFD(fd, m);
   7569 
   7570     LogToFD(fd, "--------- /etc/hosts ---------");
   7571     LogEtcHostsToFD(fd, m);
   7572 
   7573     LogToFD(fd, "------ Duplicate Records -------");
   7574     LogAuthRecordsToFD(fd, now, m->DuplicateRecords, mDNSNULL);
   7575 
   7576     LogToFD(fd, "----- Auth Records Proxied -----");
   7577     LogAuthRecordsToFD(fd, now, m->ResourceRecords, &ProxyA);
   7578 
   7579     LogToFD(fd, "-- Duplicate Records Proxied ---");
   7580     LogAuthRecordsToFD(fd, now, m->DuplicateRecords, &ProxyD);
   7581 
   7582     LogToFD(fd, "---------- Questions -----------");
   7583     if (!m->Questions) LogToFD(fd, "<None>");
   7584     else
   7585     {
   7586         CacheUsed = 0;
   7587         CacheActive = 0;
   7588         LogToFD(fd, "   Int  Next if     T NumAns "
   7589     #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   7590                 "VDNS                               "
   7591     #endif
   7592                 "Qptr               DupOf              SU SQ "
   7593     #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7594                 "DNSSEC "
   7595     #endif
   7596                 "Type    Name");
   7597         for (q = m->Questions; q; q=q->next)
   7598         {
   7599             mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
   7600             mDNSs32 n = (NextQSendTime(q) - now) / mDNSPlatformOneSecond;
   7601             char *ifname = InterfaceNameForID(m, q->InterfaceID);
   7602             CacheUsed++;
   7603             if (q->ThisQInterval) CacheActive++;
   7604 
   7605 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   7606             const mDNSBool redacted = (q->logPrivacyLevel == dnssd_log_privacy_level_private);
   7607 #endif
   7608 
   7609             LogToFD(fd, "%6d%6d %-7s%s %6d "
   7610                 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   7611                     "0x%08x%08x%08x%08x "
   7612                 #endif
   7613                     "0x%p 0x%p %1d %2d  "
   7614                 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7615                     "%-7s"
   7616                 #endif
   7617                     "%-8s%##s%s",
   7618                       i, n,
   7619                       ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
   7620                       mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
   7621                       q->CurrentAnswers,
   7622                 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
   7623                       q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0],
   7624                 #endif
   7625                       q, q->DuplicateOf,
   7626                       q->SuppressUnusable, q->Suppressed,
   7627                 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
   7628                       dns_question_is_dnssec_requestor(q) ? "YES" : "NO",
   7629                 #endif
   7630                       DNSTypeName(q->qtype),
   7631                 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
   7632                       redacted ? PRIVATE_DOMAIN_NAME->c : q->qname.c,
   7633                 #else
   7634                       q->qname.c,
   7635                 #endif
   7636                       q->DuplicateOf ? " (dup)" : "");
   7637         }
   7638         LogToFD(fd, "%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
   7639     }
   7640 
   7641     LogToFD(fd, "----- LocalOnly, P2P Questions -----");
   7642     if (!m->LocalOnlyQuestions) LogToFD(fd, "<None>");
   7643     else for (q = m->LocalOnlyQuestions; q; q=q->next)
   7644         LogToFD(fd, "                 %3s   %5d  %-6s%##s%s",
   7645                   q->InterfaceID == mDNSInterface_LocalOnly ? "LO ": q->InterfaceID == mDNSInterface_BLE ? "BLE": "P2P",
   7646                   q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
   7647 
   7648     LogToFD(fd, "---- Active UDS Client Requests ----");
   7649     if (!all_requests) LogToFD(fd, "<None>");
   7650     else
   7651     {
   7652         request_state *req, *r;
   7653         for (req = all_requests; req; req=req->next)
   7654         {
   7655             if (req->primary)   // If this is a subbordinate operation, check that the parent is in the list
   7656             {
   7657                 for (r = all_requests; r && r != req; r=r->next) if (r == req->primary) goto foundparent;
   7658                 LogToFD(fd, "%3d: Orhpan operation %p; parent %p not found in request list", req->sd);
   7659             }
   7660             // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
   7661             LogClientInfoToFD(fd, req);
   7662         foundparent:;
   7663         }
   7664     }
   7665 
   7666     LogToFD(fd, "-------- NAT Traversals --------");
   7667     LogToFD(fd, "ExtAddress %.4a Retry %d Interval %d",
   7668               &m->ExtAddress,
   7669               m->retryGetAddr ? (m->retryGetAddr - now) / mDNSPlatformOneSecond : 0,
   7670               m->retryIntervalGetAddr / mDNSPlatformOneSecond);
   7671     if (m->NATTraversals)
   7672     {
   7673         const NATTraversalInfo *nat;
   7674         for (nat = m->NATTraversals; nat; nat=nat->next)
   7675         {
   7676             LogToFD(fd, "%p %s Int %5d %s Err %d Retry %5d Interval %5d Expire %5d Req %.4a:%d Ext %.4a:%d",
   7677                       nat,
   7678                       nat->Protocol ? (nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP") : "ADD",
   7679                       mDNSVal16(nat->IntPort),
   7680                       (nat->lastSuccessfulProtocol == NATTProtocolNone    ? "None    " :
   7681                        nat->lastSuccessfulProtocol == NATTProtocolNATPMP  ? "NAT-PMP " :
   7682                        nat->lastSuccessfulProtocol == NATTProtocolUPNPIGD ? "UPnP/IGD" :
   7683                        nat->lastSuccessfulProtocol == NATTProtocolPCP     ? "PCP     " :
   7684                        /* else */                                           "Unknown " ),
   7685                       nat->Result,
   7686                       nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
   7687                       nat->retryInterval / mDNSPlatformOneSecond,
   7688                       nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
   7689                       &nat->NewAddress, mDNSVal16(nat->RequestedPort),
   7690                       &nat->ExternalAddress, mDNSVal16(nat->ExternalPort));
   7691         }
   7692     }
   7693 
   7694     LogToFD(fd, "--------- AuthInfoList ---------");
   7695     if (!m->AuthInfoList) LogToFD(fd, "<None>");
   7696     else
   7697     {
   7698         const DomainAuthInfo *a;
   7699         for (a = m->AuthInfoList; a; a = a->next)
   7700         {
   7701             LogToFD(fd, "%##s %##s %##s %d %d",
   7702                       a->domain.c, a->keyname.c,
   7703                       a->hostname.c, (a->port.b[0] << 8 | a->port.b[1]),
   7704                       (a->deltime ? (a->deltime - now) : 0));
   7705         }
   7706     }
   7707 
   7708     LogToFD(fd, "---------- Misc State ----------");
   7709 
   7710     LogToFD(fd, "PrimaryMAC:   %.6a", &m->PrimaryMAC);
   7711 
   7712     LogToFD(fd, "m->SleepState %d (%s) seq %d",
   7713               m->SleepState,
   7714               m->SleepState == SleepState_Awake        ? "Awake"        :
   7715               m->SleepState == SleepState_Transferring ? "Transferring" :
   7716               m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?",
   7717               m->SleepSeqNum);
   7718 
   7719     if (!m->SPSSocket) LogToFD(fd, "Not offering Sleep Proxy Service");
   7720 #ifndef SPC_DISABLED
   7721     else LogToFD(fd, "Offering Sleep Proxy Service: %#s", m->SPSRecords.RR_SRV.resrec.name->c);
   7722 #endif
   7723     if (m->ProxyRecords == ProxyA + ProxyD) LogToFD(fd, "ProxyRecords: %d + %d = %d", ProxyA, ProxyD, ProxyA + ProxyD);
   7724     else LogToFD(fd, "ProxyRecords: MISMATCH %d + %d = %d  %d", ProxyA, ProxyD, ProxyA + ProxyD, m->ProxyRecords);
   7725 
   7726     LogToFD(fd, "------ Auto Browse Domains -----");
   7727     if (!AutoBrowseDomains) LogToFD(fd, "<None>");
   7728     else for (d=AutoBrowseDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
   7729 
   7730     LogToFD(fd, "--- Auto Registration Domains --");
   7731     if (!AutoRegistrationDomains) LogToFD(fd, "<None>");
   7732     else for (d=AutoRegistrationDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
   7733 
   7734     LogToFD(fd, "--- Search Domains --");
   7735     if (!SearchList) LogToFD(fd, "<None>");
   7736     else
   7737     {
   7738         for (s=SearchList; s; s=s->next)
   7739         {
   7740             char *ifname = InterfaceNameForID(m, s->InterfaceID);
   7741             LogToFD(fd, "%##s %s", s->domain.c, ifname ? ifname : "");
   7742         }
   7743     }
   7744     LogMDNSStatisticsToFD(fd, m);
   7745 
   7746     LogToFD(fd, "---- Task Scheduling Timers ----");
   7747 
   7748 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
   7749     LogToFD(fd, "BonjourEnabled %d", m->BonjourEnabled);
   7750 #endif
   7751 
   7752     if (!m->NewQuestions)
   7753         LogToFD(fd, "NewQuestion <NONE>");
   7754     else
   7755         LogToFD(fd, "NewQuestion DelayAnswering %d %d %##s (%s)",
   7756                   m->NewQuestions->DelayAnswering, m->NewQuestions->DelayAnswering-now,
   7757                   m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
   7758 
   7759     if (!m->NewLocalOnlyQuestions)
   7760         LogToFD(fd, "NewLocalOnlyQuestions <NONE>");
   7761     else
   7762         LogToFD(fd, "NewLocalOnlyQuestions %##s (%s)",
   7763                   m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
   7764 
   7765     if (!m->NewLocalRecords)
   7766         LogToFD(fd, "NewLocalRecords <NONE>");
   7767     else
   7768         LogToFD(fd, "NewLocalRecords %02X %s", m->NewLocalRecords->resrec.RecordType, ARDisplayString(m, m->NewLocalRecords));
   7769 
   7770     LogToFD(fd, "SPSProxyListChanged%s", m->SPSProxyListChanged ? "" : " <NONE>");
   7771     LogToFD(fd, "LocalRemoveEvents%s",   m->LocalRemoveEvents   ? "" : " <NONE>");
   7772     LogToFD(fd, "m->WABBrowseQueriesCount %d", m->WABBrowseQueriesCount);
   7773     LogToFD(fd, "m->WABLBrowseQueriesCount %d", m->WABLBrowseQueriesCount);
   7774     LogToFD(fd, "m->WABRegQueriesCount %d", m->WABRegQueriesCount);
   7775     LogToFD(fd, "m->AutoTargetServices %u", m->AutoTargetServices);
   7776 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
   7777     LogToFD(fd, "m->AutoTargetAWDLIncludedCount %u", m->AutoTargetAWDLIncludedCount);
   7778     LogToFD(fd, "m->AutoTargetAWDLOnlyCount     %u", m->AutoTargetAWDLOnlyCount);
   7779 #endif
   7780 
   7781     LogToFD(fd, "                         ABS (hex)  ABS (dec)  REL (hex)  REL (dec)");
   7782     LogToFD(fd, "m->timenow               %08X %11d", now, now);
   7783     LogToFD(fd, "m->timenow_adjust        %08X %11d", m->timenow_adjust, m->timenow_adjust);
   7784     LogTimerToFD(fd, "m->NextScheduledEvent   ", m->NextScheduledEvent);
   7785 
   7786 #ifndef UNICAST_DISABLED
   7787     LogTimerToFD(fd, "m->NextuDNSEvent        ", m->NextuDNSEvent);
   7788     LogTimerToFD(fd, "m->NextSRVUpdate        ", m->NextSRVUpdate);
   7789     LogTimerToFD(fd, "m->NextScheduledNATOp   ", m->NextScheduledNATOp);
   7790     LogTimerToFD(fd, "m->retryGetAddr         ", m->retryGetAddr);
   7791 #endif
   7792 
   7793     LogTimerToFD(fd, "m->NextCacheCheck       ", m->NextCacheCheck);
   7794     LogTimerToFD(fd, "m->NextScheduledSPS     ", m->NextScheduledSPS);
   7795     LogTimerToFD(fd, "m->NextScheduledKA      ", m->NextScheduledKA);
   7796 
   7797 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
   7798     LogTimerToFD(fd, "m->NextBonjourDisableTime ", m->NextBonjourDisableTime);
   7799 #endif
   7800 
   7801     LogTimerToFD(fd, "m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
   7802     LogTimerToFD(fd, "m->DelaySleep           ", m->DelaySleep);
   7803 
   7804     LogTimerToFD(fd, "m->NextScheduledQuery   ", m->NextScheduledQuery);
   7805     LogTimerToFD(fd, "m->NextScheduledProbe   ", m->NextScheduledProbe);
   7806     LogTimerToFD(fd, "m->NextScheduledResponse", m->NextScheduledResponse);
   7807 
   7808     LogTimerToFD(fd, "m->SuppressQueries      ", m->SuppressQueries);
   7809     LogTimerToFD(fd, "m->SuppressResponses    ", m->SuppressResponses);
   7810     LogTimerToFD(fd, "m->SuppressProbes       ", m->SuppressProbes);
   7811     LogTimerToFD(fd, "m->ProbeFailTime        ", m->ProbeFailTime);
   7812     LogTimerToFD(fd, "m->DelaySleep           ", m->DelaySleep);
   7813     LogTimerToFD(fd, "m->SleepLimit           ", m->SleepLimit);
   7814     LogTimerToFD(fd, "m->NextScheduledStopTime ", m->NextScheduledStopTime);
   7815 }
   7816 
   7817 #if MDNS_MALLOC_DEBUGGING
   7818 mDNSlocal void udsserver_validatelists(void *context)
   7819 {
   7820     const request_state *req, *p;
   7821 	(void)context; // unused
   7822     for (req = all_requests; req; req=req->next)
   7823     {
   7824         if (req->next == (request_state *)~0 || (req->sd < 0 && req->sd != -2))
   7825             LogMemCorruption("UDS request list: %p is garbage (%d)", req, req->sd);
   7826 
   7827         if (req->primary == req)
   7828             LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req, req->sd);
   7829 
   7830         if (req->primary && req->replies)
   7831             LogMemCorruption("UDS request list: Subordinate request %p/%d/%p should not have replies (%p)",
   7832                              req, req->sd, req->primary && req->replies);
   7833 
   7834         p = req->primary;
   7835         if ((long)p & 3)
   7836             LogMemCorruption("UDS request list: req %p primary %p is misaligned (%d)", req, p, req->sd);
   7837         else if (p && (p->next == (request_state *)~0 || (p->sd < 0 && p->sd != -2)))
   7838             LogMemCorruption("UDS request list: req %p primary %p is garbage (%d)", req, p, p->sd);
   7839 
   7840         reply_state *rep;
   7841         for (rep = req->replies; rep; rep=rep->next)
   7842             if (rep->next == (reply_state *)~0)
   7843                 LogMemCorruption("UDS req->replies: %p is garbage", rep);
   7844 
   7845         if (req->terminate == connection_termination)
   7846         {
   7847             registered_record_entry *r;
   7848             for (r = req->reg_recs; r; r=r->next)
   7849             {
   7850                 if (r->next == (registered_record_entry *)~0)
   7851                 {
   7852                     LogMemCorruption("UDS req->reg_recs: %p is garbage", r);
   7853                 }
   7854             }
   7855         }
   7856         else if (req->terminate == regservice_termination_callback)
   7857         {
   7858             service_instance *s;
   7859             for (s = req->servicereg->instances; s; s=s->next)
   7860             {
   7861                 if (s->next == (service_instance *)~0)
   7862                 {
   7863                     LogMemCorruption("UDS req->servicereg->instances: %p is garbage", s);
   7864                 }
   7865             }
   7866         }
   7867         else if (req->terminate == browse_termination_callback)
   7868         {
   7869             browser_t *b;
   7870             for (b = req->u.browser.browsers; b; b=b->next)
   7871                 if (b->next == (browser_t *)~0)
   7872                     LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", b);
   7873         }
   7874     }
   7875 
   7876     DNameListElem *d;
   7877     for (d = SCPrefBrowseDomains; d; d=d->next)
   7878         if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
   7879             LogMemCorruption("SCPrefBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
   7880 
   7881     ARListElem *b;
   7882     for (b = LocalDomainEnumRecords; b; b=b->next)
   7883         if (b->next == (ARListElem *)~0 || b->ar.resrec.name->c[0] > 63)
   7884             LogMemCorruption("LocalDomainEnumRecords: %p is garbage (%d)", b, b->ar.resrec.name->c[0]);
   7885 
   7886     for (d = AutoBrowseDomains; d; d=d->next)
   7887         if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
   7888             LogMemCorruption("AutoBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
   7889 
   7890     for (d = AutoRegistrationDomains; d; d=d->next)
   7891         if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
   7892             LogMemCorruption("AutoRegistrationDomains: %p is garbage (%d)", d, d->name.c[0]);
   7893 }
   7894 #endif // MDNS_MALLOC_DEBUGGING
   7895 
   7896 mDNSlocal transfer_state send_msg(request_state *const req)
   7897 {
   7898     reply_state *const rep = req->replies;      // Send the first waiting reply
   7899     ssize_t nwritten;
   7900     const mDNSu32 len = rep->totallen - rep->nwritten;
   7901 
   7902     ConvertHeaderBytes(rep->mhdr);
   7903     nwritten = send(req->sd, (char *)&rep->mhdr + rep->nwritten, len, 0);
   7904     ConvertHeaderBytes(rep->mhdr);
   7905 
   7906     if (nwritten < 0)
   7907     {
   7908         if (dnssd_errno == dnssd_EINTR || dnssd_errno == dnssd_EWOULDBLOCK) nwritten = 0;
   7909         else
   7910         {
   7911 #if !defined(PLATFORM_NO_EPIPE)
   7912             if (dnssd_errno == EPIPE)
   7913                 return(req->ts = t_terminated);
   7914             else
   7915 #endif
   7916             {
   7917                 LogMsg("send_msg ERROR: failed to write %u of %d bytes to fd %d errno %d (%s)",
   7918                        len, rep->totallen, req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
   7919                 return(t_error);
   7920             }
   7921         }
   7922     }
   7923     rep->nwritten += (mDNSu32)nwritten;
   7924     return (rep->nwritten == rep->totallen) ? t_complete : t_morecoming;
   7925 }
   7926 
   7927 mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
   7928 {
   7929     mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
   7930     request_state **req = &all_requests;
   7931 
   7932     while (*req)
   7933     {
   7934         request_state *r = *req;
   7935 
   7936         if (r->terminate == resolve_termination_callback)
   7937         {
   7938             request_resolve *const resolve = r->resolve;
   7939             if (resolve->ReportTime && ((now - resolve->ReportTime) >= 0))
   7940             {
   7941                 resolve->ReportTime = 0;
   7942                 // if client received results (we have both SRV and TXT record) and resolve still active
   7943                 if (resolve_result_is_complete(resolve))
   7944                 {
   7945                     LogMsgNoIdent("Client application PID[%d](%s) has received results for DNSServiceResolve(%##s) yet remains active over two minutes.", r->process_id, r->pid_name, resolve->qsrv.qname.c);
   7946                 }
   7947             }
   7948         }
   7949         // Note: Only primary req's have reply lists, not subordinate req's.
   7950         while (r->replies)      // Send queued replies
   7951         {
   7952             transfer_state result;
   7953             if (r->replies->next)
   7954                 r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
   7955             result = send_msg(r);   // Returns t_morecoming if buffer full because client is not reading
   7956             if (result == t_complete)
   7957             {
   7958                 reply_state *fptr = r->replies;
   7959                 r->replies = r->replies->next;
   7960                 freeL("reply_state/udsserver_idle", fptr);
   7961                 r->time_blocked = 0; // reset failure counter after successful send
   7962                 r->unresponsiveness_reports = 0;
   7963                 continue;
   7964             }
   7965             else if (result == t_terminated)
   7966             {
   7967                 LogInfo("%3d: Could not write data to client PID[%d](%s) because connection is terminated by the client", r->sd, r->process_id, r->pid_name);
   7968                 abort_request(r);
   7969             }
   7970             else if (result == t_error)
   7971             {
   7972                 LogMsg("%3d: Could not write data to client PID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name);
   7973                 LogClientInfo(r);
   7974                 abort_request(r);
   7975             }
   7976             break;
   7977         }
   7978 
   7979         if (r->replies)     // If we failed to send everything, check our time_blocked timer
   7980         {
   7981             if (nextevent - now > mDNSPlatformOneSecond)
   7982                 nextevent = now + mDNSPlatformOneSecond;
   7983 
   7984             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
   7985                "[R%u] Could not send all replies. Will try again in %d ticks.", r->request_id, nextevent - now);
   7986             if (mDNSStorage.SleepState != SleepState_Awake)
   7987                 r->time_blocked = 0;
   7988             else if (!r->time_blocked)
   7989                 r->time_blocked = NonZeroTime(now);
   7990             else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1))
   7991             {
   7992                 int num = 0;
   7993                 struct reply_state *x = r->replies;
   7994                 while (x)
   7995                 {
   7996                     num++;
   7997                     x=x->next;
   7998                 }
   7999                 LogMsg("%3d: Could not write data to client PID[%d](%s) after %ld seconds, %d repl%s waiting",
   8000                        r->sd, r->process_id, r->pid_name, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies");
   8001                 if (++r->unresponsiveness_reports >= 60)
   8002                 {
   8003                     LogMsg("%3d: Client PID[%d](%s) unresponsive; aborting connection", r->sd, r->process_id, r->pid_name);
   8004                     LogClientInfo(r);
   8005                     abort_request(r);
   8006                 }
   8007             }
   8008         }
   8009 
   8010         if (!dnssd_SocketValid(r->sd)) // If this request is finished, unlink it from the list and free the memory
   8011         {
   8012             // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
   8013             *req = r->next;
   8014             request_state_forget(&r);
   8015         }
   8016         else
   8017             req = &r->next;
   8018     }
   8019     return nextevent;
   8020 }
   8021 
   8022 struct CompileTimeAssertionChecks_uds_daemon
   8023 {
   8024     // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
   8025     // other overly-large structures instead of having a pointer to them, can inadvertently
   8026     // cause structure sizes (and therefore memory usage) to balloon unreasonably.
   8027     char sizecheck_request_state          [(sizeof(request_state)           <= 1072) ? 1 : -1];
   8028     char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <=   64) ? 1 : -1];
   8029     char sizecheck_service_instance       [(sizeof(service_instance)        <= 6552) ? 1 : -1];
   8030     char sizecheck_browser_t              [(sizeof(browser_t)               <=  984) ? 1 : -1];
   8031     char sizecheck_reply_hdr              [(sizeof(reply_hdr)               <=   12) ? 1 : -1];
   8032     char sizecheck_reply_state            [(sizeof(reply_state)             <=   64) ? 1 : -1];
   8033 };
   8034 
   8035 #ifdef UNIT_TEST
   8036 #include "../unittests/uds_daemon_ut.c"
   8037 #endif  //  UNIT_TEST
   8038