xref: /netbsd-src/external/apache2/mDNSResponder/dist/mDNSShared/uds_daemon.c (revision 450dee115da5565aafca4d92dc3ba1c9d6b0cd2a)
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