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
GetNewRequestID(void)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
FatalError(char * errmsg)313 mDNSlocal void FatalError(char *errmsg)
314 {
315 LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
316 abort();
317 }
318
dnssd_htonl(mDNSu32 l)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
my_perror(char * errmsg)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
my_throttled_perror(char * err_msg)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.
LogMcastQuestion(const DNSQuestion * const q,request_state * req,q_state status)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()
LogMcastService(const AuthRecord * const ar,request_state * req,reg_state status)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()
LogMcastStateInfo(mDNSBool mflag,mDNSBool start,mDNSBool mstatelog)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
abort_request(request_state * req)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
SetDebugBoundPath(void)536 mDNSexport void SetDebugBoundPath(void)
537 {
538 #if !defined(USE_TCP_LOOPBACK)
539 boundPath = MDNS_UDS_SERVERPATH_DEBUG;
540 #endif
541 }
542
IsDebugSocketInUse(void)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)
_get_trust_results_dispatch_queue(void)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
_prepare_trusts_for_request(request_state * const request)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
request_state_forget(request_state ** const ptr)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
AbortUnlinkAndFree(request_state * req)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
create_reply(const reply_op_t op,const size_t datalen,request_state * const request)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.
append_reply(request_state * req,reply_state * rep)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)
_get_signed_data_tlvs(request_state * const request,size_t * const out_length)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
get_signed_result_flags_tlvs(request_state * const request)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
get_signed_browse_tlvs(request_state * const request)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
get_signed_resolve_tlvs(request_state * const request)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
put_signed_result_tlvs(const uint8_t * data,uint16_t length,ipc_msg_hdr * const hdr,uint8_t ** const ptr,const uint8_t * const limit)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)
get_tracker_info_tlvs(request_state * const request)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
put_tracker_hostname_tlvs(const char * hostname,ipc_msg_hdr * const hdr,uint8_t ** const ptr,const uint8_t * const limit)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
GenerateNTDResponse(const domainname * const servicename,const mDNSInterfaceID id,request_state * const request,reply_state ** const rep,reply_op_t op,DNSServiceFlags flags,mStatus err)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
GenerateBrowseReply(const domainname * const servicename,const mDNSInterfaceID id,request_state * const request,reply_state ** const rep,reply_op_t op,DNSServiceFlags flags,mStatus err)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.
get_service_attr_tsr_params(const request_state * const request,mDNSu32 * const outTimestamp,mDNSu32 * const outHostkeyHash)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
read_rr_from_ipc_msg(request_state * request,int GetTTL,int validate_flags)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
build_domainname_from_strings(domainname * srv,char * name,char * regtype,char * domain)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
send_all(dnssd_sock_t s,const char * ptr,const size_t len)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)
external_start_advertising_helper(service_instance * const instance)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
external_stop_advertising_helper(service_instance * const instance)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
FreeExtraRR(mDNS * const m,AuthRecord * const rr,mStatus result)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
unlink_and_free_service_instance(service_instance * srv)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.
CountPeerRegistrations(ServiceRecordSet * const srs)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
CountExistingRegistrations(domainname * srv,mDNSIPPort port)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
SendServiceRemovalNotification(ServiceRecordSet * const srs)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
regservice_callback(mDNS * const m,ServiceRecordSet * const srs,mStatus result)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
regrecord_callback(mDNS * const m,AuthRecord * rr,mStatus result)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)
set_peer_pid(request_state * request)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
request_state_get_duration(const request_state * const request)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
requestShouldLogName(request_state * const request)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
requestShouldLogFullRequestInfo(request_state * const request)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
connection_termination(request_state * request)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
handle_cancel_request(request_state * request)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
_handle_regrecord_request_start(request_state * request,AuthRecord * rr)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
_return_regrecord_request_error(request_state * request,mStatus error)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
_handle_regrecord_request_with_trust(request_state * request,AuthRecord * rr)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
regRecordAddTSRRecord(request_state * const request,AuthRecord * const rr,const mDNSs32 tsrTimestamp,const mDNSu32 tsrHostkeyHash)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
updateTSRRecord(const request_state * const request,AuthRecord * const tsr,const mDNSs32 tsrTimestamp,const mDNSu32 tsrHostkeyHash)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
conflictWithAuthRecords(mDNS * const m,const AuthRecord * const rr)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
conflictWithCacheRecordsOrFlush(mDNS * const m,const mDNSu32 namehash,const domainname * const name,const mDNSs32 validatedTSRTimestamp,const mDNSu32 tsrHostkeyHash)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
handle_regrecord_request(request_state * request)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(×tampContinuous, 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
regservice_termination_callback(request_state * const request)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
LocateSubordinateRequest(request_state * request)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
add_record_to_service(request_state * const request,service_instance * const instance,const mDNSu16 rrtype,const mDNSu16 rdlen,const mDNSu8 * const rdata,const mDNSu32 ttl)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
handle_add_request(request_state * request)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
update_callback(mDNS * const m,AuthRecord * const rr,RData * oldrd,mDNSu16 oldrdlen)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
update_record(AuthRecord * ar,mDNSu16 rdlen,const mDNSu8 * const rdata,mDNSu32 ttl,const mDNSBool * const external_advertise,const mDNSu32 request_id)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
handle_tsr_update_request(const request_state * const request,const AuthRecord * const rr,const mDNSu32 tsrTimestamp,const mDNSu32 tsrHostkeyHash)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(×tampContinuous, 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
handle_update_request(request_state * request)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()
remove_record(request_state * request)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
remove_extra(const request_state * const request,service_instance * const serv,mDNSu16 * const rrtype)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
handle_removerecord_request(request_state * request)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
FindFirstSubType(char * p)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
FindNextSubType(char * p)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
ChopSubTypes(char * regtype)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
AllocateSubTypes(mDNSu32 NumSubTypes,char * p,AuthRecord ** subtypes)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
register_service_instance(request_state * const request,const domainname * const domain)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(×tampContinuous, 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
udsserver_default_reg_domain_changed(const DNameListElem * const d,const mDNSBool add)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.
PreDefinedInterfaceIndex(mDNSu32 interfaceIndex)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
_handle_regservice_request_start(request_state * const request,const domainname * const d)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
_return_regservice_request_error(request_state * const request,const mStatus error)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
_handle_regservice_request_with_trust(request_state * const request,const domainname * const d)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
handle_regservice_request(request_state * const request)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
FoundInstance(mDNS * const m,DNSQuestion * question,const ResourceRecord * const answer,QC_result AddRecord)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
SetQuestionPolicy(DNSQuestion * q,request_state * req)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)
_get_unicast_discovery_dns_services(request_state * info)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
add_domain_to_browser(request_state * info,const domainname * d)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
browse_termination_callback(request_state * info)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
udsserver_automatic_browse_domain_changed(const DNameListElem * const d,const mDNSBool add)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
FreeARElemCallback(mDNS * const m,AuthRecord * const rr,mStatus result)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
RegisterLocalOnlyDomainEnumPTR(mDNS * m,const domainname * d,int type)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
DeregisterLocalOnlyDomainEnumPTR(mDNS * m,const domainname * d,int type)3617 mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
3618 {
3619 DeregisterLocalOnlyDomainEnumPTR_Internal(m, d, type, mDNSfalse);
3620 }
3621
DeregisterLocalOnlyDomainEnumPTR_Internal(mDNS * const m,const domainname * const d,const int type,const mDNSBool LockHeld)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
FindDNameListElem(const mDNSu32 uid,const domainname * const name,DNameListElem * domains)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
AddAutoBrowseDomain(const mDNSu32 uid,const domainname * const name)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
RmvAutoBrowseDomain(const mDNSu32 uid,const domainname * const name)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
SetPrefsBrowseDomains(mDNS * m,DNameListElem * browseDomains,mDNSBool add)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
UpdateDeviceInfoRecord(mDNS * const m)3761 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
3762 {
3763 (void)m; // unused
3764 }
3765
udsserver_handle_configchange(mDNS * const m)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
FoundNonLocalOnlyAutomaticBrowseDomain(mDNS * const m,DNSQuestion * const q,const ResourceRecord * const answer,const QC_result add_record)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
AutomaticBrowseDomainChange(mDNS * const m,DNSQuestion * q,const ResourceRecord * const answer,QC_result AddRecord)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
_handle_browse_request_start(request_state * request,const char * domain)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
_return_browse_request_error(request_state * request,mStatus error)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
_handle_browse_request_with_trust(request_state * request,const char * domain)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
handle_browse_request(request_state * request)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
resolve_termination_callback(request_state * request)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
_handle_resolve_request_start(request_state * const request,const _resolve_start_params_t * const params)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(¶ms->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, ¶ms->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, ¶ms->fqdn, request->flags, request->process_id);
4276 }
4277 #else
4278 (void)params;
4279 #endif
4280 }
4281 }
4282 return err;
4283 }
4284
resolve_result_forget_srv(request_resolve * const resolve)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
resolve_result_forget_txt(request_resolve * const resolve)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
resolve_result_finalize(request_resolve * resolve)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
resolve_result_is_complete(const request_resolve * const resolve)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
resolve_result_save_answer(request_resolve * const resolve,const ResourceRecord * const answer,const QC_result add_record)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
resolve_result_callback(mDNS * const m,DNSQuestion * question,const ResourceRecord * const answer,QC_result AddRecord)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
_return_resolve_request_error(request_state * request,mStatus error)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
_handle_resolve_request_with_trust(request_state * request,const _resolve_start_params_t * const params)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
handle_resolve_request(request_state * request)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(¶ms.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, ¶ms.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, ¶ms.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, ¶ms);
4840 }
4841 else
4842 {
4843 err = _handle_resolve_request_start(request, ¶ms);
4844 }
4845 #else
4846 err = _handle_resolve_request_start(request, ¶ms);
4847 #endif
4848
4849 exit:
4850 return(err);
4851 }
4852
4853 // ***************************************************************************
4854 // MARK: - DNSServiceQueryRecord
4855
queryrecord_result_reply(mDNS * const m,DNSQuestion * const question,const ResourceRecord * const answer,const mDNSBool expired,const QC_result AddRecord,const DNSServiceErrorType error,void * const context)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
queryrecord_termination_callback(request_state * request)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
_uds_queryrecord_params_init(uds_queryrecord_params_t * const params)5077 static void _uds_queryrecord_params_init(uds_queryrecord_params_t *const params)
5078 {
5079 mDNSPlatformMemZero(params, (mDNSu32)sizeof(*params));
5080 QueryRecordClientRequestParamsInit(¶ms->cr);
5081 params->cr.qnameStr = params->qname;
5082 }
5083
5084 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
_uds_queryrecord_params_copy(uds_queryrecord_params_t * const dst,const uds_queryrecord_params_t * const src)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
_handle_queryrecord_request_start(request_state * request,const uds_queryrecord_params_t * const params)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, ¶ms->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
_return_queryrecord_request_error(request_state * request,mStatus error)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
_handle_queryrecord_request_with_trust(request_state * request,const uds_queryrecord_params_t * const params)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)
get_queryrecord_tlvs(request_state * const request,uds_queryrecord_params_t * const params)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
handle_queryrecord_request(request_state * request)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(¶ms);
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, ¶ms);
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, ¶ms);
5399 }
5400 else
5401 #endif
5402 {
5403 err = _handle_queryrecord_request_start(request, ¶ms);
5404 }
5405
5406 exit:
5407 return(err);
5408 }
5409
5410 // ***************************************************************************
5411 // MARK: - DNSServiceEnumerateDomains
5412
format_enumeration_reply(request_state * request,const char * domain,DNSServiceFlags flags,mDNSu32 ifi,DNSServiceErrorType err)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
enum_termination_callback(request_state * request)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
enum_result_callback(mDNS * const m,DNSQuestion * const question,const ResourceRecord * const answer,QC_result AddRecord)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
handle_enum_request(request_state * request)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
handle_reconfirm_request(request_state * request)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
handle_release_request(request_state * request)5596 mDNSlocal mStatus handle_release_request(request_state *request)
5597 {
5598 (void) request;
5599 return mStatus_UnsupportedErr;
5600 }
5601
5602
handle_setdomain_request(request_state * request)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
handle_getproperty_request(request_state * request)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
handle_connection_delegate_request(request_state * request)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
port_mapping_termination_callback(request_state * request)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
port_mapping_create_request_callback(mDNS * m,NATTraversalInfo * n)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
handle_port_mapping_request(request_state * request)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
addrinfo_termination_callback(request_state * request)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
_handle_addrinfo_request_start(request_state * request,const _addrinfo_start_params_t * const params)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
_return_addrinfo_request_error(request_state * request,mStatus error)5858 mDNSlocal void _return_addrinfo_request_error(request_state * request, mStatus error)
5859 {
5860 _return_queryrecord_request_error(request, error);
5861 }
5862
_handle_addrinfo_request_with_trust(request_state * request,const _addrinfo_start_params_t * const params)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
handle_addrinfo_request(request_state * request)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, ¶ms);
6059 }
6060 else
6061 {
6062 err = _handle_addrinfo_request_start(request, ¶ms);
6063 }
6064 #else
6065 err = _handle_addrinfo_request_start(request, ¶ms);
6066 #endif
6067
6068 exit:
6069 return(err);
6070 }
6071
6072 // ***************************************************************************
6073 // MARK: - Main Request Handler etc.
6074
NewRequest(void)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
read_msg(request_state * req)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
returnAsyncErrorCode(request_state * const request,const mStatus error)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)
request_state_prepare_audit_token(request_state * const req)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
handle_client_request(request_state * req)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
request_callback(int fd,void * info)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
connect_callback(int fd,void * info)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
uds_socket_setup(dnssd_sock_t skt)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
udsserver_init(dnssd_sock_t skts[],const size_t count)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
udsserver_exit(void)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
LogClientInfoToFD(int fd,request_state * req)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
LogClientInfo(request_state * req)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
GetMcastClients(request_state * req)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
LogMcastClientInfo(request_state * req)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
RecordTypeName(mDNSu8 rtype)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
LogEtcHostsToFD(int fd,mDNS * const m)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
LogLocalOnlyAuthRecordsToFD(int fd,mDNS * const m)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
LogOneAuthRecordToFD(const int fd,const AuthRecord * const ar,const mDNSs32 now,const char * const ifname)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
LogAuthRecordsToFD(int fd,const mDNSs32 now,AuthRecord * ResourceRecords,int * proxy)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
PrintOneCacheRecordToFD(int fd,const CacheRecord * cr,mDNSu32 slot,const mDNSu32 remain,const char * ifname,mDNSu32 * CacheUsed)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
PrintCachedRecordsToFD(int fd,const CacheRecord * cr,mDNSu32 slot,const mDNSu32 remain,const char * ifname,mDNSu32 * CacheUsed)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
LogMDNSStatisticsToFD(int fd,mDNS * const m)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
udsserver_info_dump_to_fd(int fd)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
udsserver_validatelists(void * context)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
send_msg(request_state * const req)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
udsserver_idle(mDNSs32 nextevent)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