]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/uds_daemon.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / mDNSShared / uds_daemon.c
1 /*
2 * Copyright (c) 2003-2020 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 * http://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/types.h>
25 #include <sys/time.h>
26 #include <sys/resource.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "mDNSEmbeddedAPI.h"
33 #include "DNSCommon.h"
34 #include "uDNS.h"
35 #include "uds_daemon.h"
36 #include "dns_sd_internal.h"
37
38 // Apple-specific functionality, not required for other platforms
39 #if APPLE_OSX_mDNSResponder
40 #include <os/log.h>
41 #include <sys/ucred.h>
42 #ifndef PID_FILE
43 #define NO_PID_FILE // We need to signal that this platform has no PID file, and not just that we are taking the default
44 #endif
45 #endif
46
47 #ifdef LOCAL_PEEREPID
48 #include <sys/un.h> // for LOCAL_PEEREPID
49 #include <sys/socket.h> // for getsockopt
50 #include <sys/proc_info.h> // for struct proc_bsdshortinfo
51 #include <libproc.h> // for proc_pidinfo()
52 #endif //LOCAL_PEEREPID
53
54 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
55 #include "D2D.h"
56 #endif
57
58 #if APPLE_OSX_mDNSResponder
59 #include "BLE.h"
60 #endif
61
62 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
63 #include "mDNSMacOSX.h"
64 #include <os/feature_private.h>
65 #endif
66
67 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
68 #include <bsm/libbsm.h>
69 #endif
70
71 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
72 #include "QuerierSupport.h"
73 #endif
74
75 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
76 #include "mdns_tlv.h"
77 #endif
78
79 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
80 #include "dnssec_v2.h"
81 #endif
82
83 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
84 #include "dnssd_server.h"
85 #endif
86
87 // User IDs 0-500 are system-wide processes, not actual users in the usual sense
88 // User IDs for real user accounts start at 501 and count up from there
89 #define SystemUID(X) ((X) <= 500)
90
91 // ***************************************************************************
92 #if COMPILER_LIKES_PRAGMA_MARK
93 #pragma mark -
94 #pragma mark - Globals
95 #endif
96
97 // globals
98 mDNSexport mDNS mDNSStorage;
99 mDNSexport const char ProgramName[] = "mDNSResponder";
100
101 #if defined(USE_TCP_LOOPBACK)
102 static char* boundPath = NULL;
103 #else
104 static char* boundPath = MDNS_UDS_SERVERPATH;
105 #endif
106 #if DEBUG
107 #define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder"
108 #endif
109 static dnssd_sock_t listenfd = dnssd_InvalidSocket;
110 static request_state *all_requests = NULL;
111 #ifdef LOCAL_PEEREPID
112 struct proc_bsdshortinfo proc;
113 #endif //LOCAL_PEEREPID
114 mDNSlocal void set_peer_pid(request_state *request);
115 mDNSlocal void LogMcastClientInfo(request_state *req);
116 mDNSlocal void GetMcastClients(request_state *req);
117 static mDNSu32 mcount; // tracks the current active mcast operations for McastLogging
118 static mDNSu32 i_mcount; // sets mcount when McastLogging is enabled(PROF signal is sent)
119 static mDNSu32 n_mrecords; // tracks the current active mcast records for McastLogging
120 static mDNSu32 n_mquests; // tracks the current active mcast questions for McastLogging
121
122
123 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
124 mDNSu32 curr_num_regservices = 0;
125 mDNSu32 max_num_regservices = 0;
126 #endif
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 PID_FILE
149 #define PID_FILE "/var/run/mDNSResponder.pid"
150 #endif
151
152 // ***************************************************************************
153 #if COMPILER_LIKES_PRAGMA_MARK
154 #pragma mark -
155 #pragma mark - General Utility Functions
156 #endif
157
158 mDNSlocal mDNSu32 GetNewRequestID(void)
159 {
160 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
161 return dnssd_server_get_new_request_id();
162 #else
163 static mDNSu32 s_last_id = 0;
164 return ++s_last_id;
165 #endif
166 }
167
168 mDNSlocal void FatalError(char *errmsg)
169 {
170 LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
171 abort();
172 }
173
174 mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l)
175 {
176 mDNSu32 ret;
177 char *data = (char*) &ret;
178 put_uint32(l, &data);
179 return ret;
180 }
181
182 // hack to search-replace perror's to LogMsg's
183 mDNSlocal void my_perror(char *errmsg)
184 {
185 LogMsg("%s: %d (%s)", errmsg, dnssd_errno, dnssd_strerror(dnssd_errno));
186 }
187
188 // Throttled version of my_perror: Logs once every 250 msgs
189 mDNSlocal void my_throttled_perror(char *err_msg)
190 {
191 static int uds_throttle_count = 0;
192 if ((uds_throttle_count++ % 250) == 0)
193 my_perror(err_msg);
194 }
195
196 // LogMcastQuestion/LogMcastQ should be called after the DNSQuestion struct is initialized(especially for q->TargetQID)
197 // Hence all calls are made after mDNS_StartQuery()/mDNS_StopQuery()/mDNS_StopBrowse() is called.
198 mDNSlocal void LogMcastQuestion(const DNSQuestion *const q, request_state *req, q_state status)
199 {
200 if (mDNSOpaque16IsZero(q->TargetQID)) // Check for Mcast Query
201 {
202 mDNSBool mflag = mDNSfalse;
203 if (status == q_start)
204 {
205 if (++mcount == 1)
206 mflag = mDNStrue;
207 }
208 else
209 {
210 mcount--;
211 }
212 LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype),
213 q->InterfaceID == mDNSInterface_LocalOnly ? "lo" :
214 q->InterfaceID == mDNSInterface_P2P ? "p2p" :
215 q->InterfaceID == mDNSInterface_BLE ? "BLE" :
216 q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(&mDNSStorage, q->InterfaceID),
217 req->process_id, req->pid_name);
218 LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
219 }
220 return;
221 }
222
223 // LogMcastService/LogMcastS should be called after the AuthRecord struct is initialized
224 // Hence all calls are made after mDNS_Register()/ just before mDNS_Deregister()
225 mDNSlocal void LogMcastService(const AuthRecord *const ar, request_state *req, reg_state status)
226 {
227 if (!AuthRecord_uDNS(ar)) // Check for Mcast Service
228 {
229 mDNSBool mflag = mDNSfalse;
230 if (status == reg_start)
231 {
232 if (++mcount == 1)
233 mflag = mDNStrue;
234 }
235 else
236 {
237 mcount--;
238 }
239 LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Service" : "-Service", ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype),
240 ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" :
241 ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" :
242 ar->resrec.InterfaceID == mDNSInterface_BLE ? "BLE" :
243 ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID),
244 req->process_id, req->pid_name);
245 LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
246 }
247 return;
248 }
249
250 // For complete Mcast State Log, pass mDNStrue to mstatelog in LogMcastStateInfo()
251 mDNSexport void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog)
252 {
253 mDNS *const m = &mDNSStorage;
254 if (!mstatelog)
255 {
256 if (!all_requests)
257 {
258 LogMcastNoIdent("<None>");
259 }
260 else
261 {
262 request_state *req, *r;
263 for (req = all_requests; req; req=req->next)
264 {
265 if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
266 {
267 for (r = all_requests; r && r != req; r=r->next)
268 if (r == req->primary)
269 goto foundpar;
270 }
271 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
272 GetMcastClients(req);
273 foundpar:;
274 }
275 LogMcastNoIdent("--- MCAST RECORDS COUNT[%d] MCAST QUESTIONS COUNT[%d] ---", n_mrecords, n_mquests);
276 n_mrecords = n_mquests = 0; // Reset the values
277 }
278 }
279 else
280 {
281 static mDNSu32 i_mpktnum;
282 i_mcount = 0;
283 if (start)
284 mcount = 0;
285 // mcount is initialized to 0 when the PROF signal is sent since mcount could have
286 // wrong value if MulticastLogging is disabled and then re-enabled
287 LogMcastNoIdent("--- START MCAST STATE LOG ---");
288 if (!all_requests)
289 {
290 mcount = 0;
291 LogMcastNoIdent("<None>");
292 }
293 else
294 {
295 request_state *req, *r;
296 for (req = all_requests; req; req=req->next)
297 {
298 if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
299 {
300 for (r = all_requests; r && r != req; r=r->next)
301 if (r == req->primary)
302 goto foundparent;
303 LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req->sd);
304 }
305 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
306 LogMcastClientInfo(req);
307 foundparent:;
308 }
309 if(!mcount) // To initially set mcount
310 mcount = i_mcount;
311 }
312 if (mcount == 0)
313 {
314 i_mpktnum = m->MPktNum;
315 LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount, i_mpktnum);
316 }
317 if (mflag)
318 LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum));
319 LogMcastNoIdent("--- END MCAST STATE LOG ---");
320 }
321 }
322
323 mDNSlocal void abort_request(request_state *req)
324 {
325 if (req->terminate == (req_termination_fn) ~0)
326 {
327 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
328 "[R%d] abort_request: ERROR: Attempt to abort operation %p with req->terminate %p", req->request_id, req, req->terminate);
329 return;
330 }
331
332 // First stop whatever mDNSCore operation we were doing
333 // If this is actually a shared connection operation, then its req->terminate function will scan
334 // the all_requests list and terminate any subbordinate operations sharing this file descriptor
335 if (req->terminate) req->terminate(req);
336 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
337 if (req->custom_service_id != 0)
338 {
339 Querier_DeregisterCustomDNSService(req->custom_service_id);
340 req->custom_service_id = 0;
341 }
342 #endif
343
344 if (!dnssd_SocketValid(req->sd))
345 {
346 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
347 "[R%d] abort_request: ERROR: Attempt to abort operation %p with invalid fd %d", req->request_id, req, req->sd);
348 return;
349 }
350
351 // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
352 if (!req->primary)
353 {
354 if (req->errsd != req->sd)
355 {
356 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
357 "[R%d] Removing FD %d and closing errsd %d", req->request_id, req->sd, req->errsd);
358 }
359 else
360 {
361 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
362 "[R%d] Removing FD %d", req->request_id, req->sd);
363 }
364 udsSupportRemoveFDFromEventLoop(req->sd, req->platform_data); // Note: This also closes file descriptor req->sd for us
365 if (req->errsd != req->sd) { dnssd_close(req->errsd); req->errsd = req->sd; }
366
367 while (req->replies) // free pending replies
368 {
369 reply_state *ptr = req->replies;
370 req->replies = req->replies->next;
371 freeL("reply_state (abort)", ptr);
372 }
373 }
374
375 // Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
376 #if MDNS_MALLOC_DEBUGGING
377 // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MDNS_MALLOC_DEBUGGING uses
378 // for detecting when the memory for an object is inadvertently freed while the object is still on some list
379 #ifdef WIN32
380 #error This will not work on Windows, look at IsValidSocket in mDNSShared/CommonServices.h to see why
381 #endif
382 req->sd = req->errsd = -2;
383 #else
384 req->sd = req->errsd = dnssd_InvalidSocket;
385 #endif
386 // We also set req->terminate to a bogus value so we know if abort_request() gets called again for this request
387 req->terminate = (req_termination_fn) ~0;
388 }
389
390 #if DEBUG
391 mDNSexport void SetDebugBoundPath(void)
392 {
393 #if !defined(USE_TCP_LOOPBACK)
394 boundPath = MDNS_UDS_SERVERPATH_DEBUG;
395 #endif
396 }
397
398 mDNSexport int IsDebugSocketInUse(void)
399 {
400 #if !defined(USE_TCP_LOOPBACK)
401 return !strcmp(boundPath, MDNS_UDS_SERVERPATH_DEBUG);
402 #else
403 return mDNSfalse;
404 #endif
405 }
406 #endif
407
408 mDNSlocal void AbortUnlinkAndFree(request_state *req)
409 {
410 request_state **p = &all_requests;
411 abort_request(req);
412 while (*p && *p != req) p=&(*p)->next;
413 if (*p)
414 {
415 *p = req->next;
416 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
417 if (req->trust)
418 {
419 void * context = mdns_trust_get_context(req->trust);
420 mdns_trust_set_context(req->trust, NULL);
421 if (context) freeL("context/AbortUnlinkAndFree", context);
422 mdns_trust_forget(&req->trust);
423 }
424 #endif
425 freeL("request_state/AbortUnlinkAndFree", req);
426 }
427 else LogMsg("AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req);
428 }
429
430 mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, request_state *const request)
431 {
432 reply_state *reply;
433
434 if ((unsigned)datalen < sizeof(reply_hdr))
435 {
436 LogMsg("ERROR: create_reply - data length less than length of required fields");
437 return NULL;
438 }
439
440 reply = (reply_state *) callocL("reply_state", sizeof(reply_state) + datalen - sizeof(reply_hdr));
441 if (!reply) FatalError("ERROR: calloc");
442
443 reply->next = mDNSNULL;
444 reply->totallen = (mDNSu32)datalen + sizeof(ipc_msg_hdr);
445 reply->nwriten = 0;
446
447 reply->mhdr->version = VERSION;
448 reply->mhdr->datalen = (mDNSu32)datalen;
449 reply->mhdr->ipc_flags = 0;
450 reply->mhdr->op = op;
451 reply->mhdr->client_context = request->hdr.client_context;
452 reply->mhdr->reg_index = 0;
453
454 return reply;
455 }
456
457 // Append a reply to the list in a request object
458 // If our request is sharing a connection, then we append our reply_state onto the primary's list
459 // If the request does not want asynchronous replies, then the reply is freed instead of being appended to any list.
460 mDNSlocal void append_reply(request_state *req, reply_state *rep)
461 {
462 request_state *r;
463 reply_state **ptr;
464
465 if (req->no_reply)
466 {
467 freeL("reply_state/append_reply", rep);
468 return;
469 }
470
471 r = req->primary ? req->primary : req;
472 ptr = &r->replies;
473 while (*ptr) ptr = &(*ptr)->next;
474 *ptr = rep;
475 rep->next = NULL;
476 }
477
478 // Generates a response message giving name, type, domain, plus interface index,
479 // suitable for a browse result or service registration result.
480 // On successful completion rep is set to point to a malloc'd reply_state struct
481 mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const mDNSInterfaceID id,
482 request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
483 {
484 domainlabel name;
485 domainname type, dom;
486 *rep = NULL;
487 if (servicename && !DeconstructServiceName(servicename, &name, &type, &dom))
488 return kDNSServiceErr_Invalid;
489 else
490 {
491 char namestr[MAX_DOMAIN_LABEL+1];
492 char typestr[MAX_ESCAPED_DOMAIN_NAME];
493 char domstr [MAX_ESCAPED_DOMAIN_NAME];
494 int len;
495 char *data;
496
497 if (servicename)
498 {
499 ConvertDomainLabelToCString_unescaped(&name, namestr);
500 ConvertDomainNameToCString(&type, typestr);
501 ConvertDomainNameToCString(&dom, domstr);
502 }
503 else
504 {
505 namestr[0] = 0;
506 typestr[0] = 0;
507 domstr[0] = 0;
508 }
509
510 // Calculate reply data length
511 len = sizeof(DNSServiceFlags);
512 len += sizeof(mDNSu32); // if index
513 len += sizeof(DNSServiceErrorType);
514 len += (int) (strlen(namestr) + 1);
515 len += (int) (strlen(typestr) + 1);
516 len += (int) (strlen(domstr) + 1);
517
518 // Build reply header
519 *rep = create_reply(op, len, request);
520 (*rep)->rhdr->flags = dnssd_htonl(flags);
521 (*rep)->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
522 (*rep)->rhdr->error = dnssd_htonl(err);
523
524 // Build reply body
525 data = (char *)&(*rep)->rhdr[1];
526 put_string(namestr, &data);
527 put_string(typestr, &data);
528 put_string(domstr, &data);
529
530 return mStatus_NoError;
531 }
532 }
533
534 mDNSlocal void GenerateBrowseReply(const domainname *const servicename, const mDNSInterfaceID id,
535 request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
536 {
537 char namestr[MAX_DOMAIN_LABEL+1];
538 char typestr[MAX_ESCAPED_DOMAIN_NAME];
539 static const char domstr[] = ".";
540 int len;
541 char *data;
542
543 *rep = NULL;
544
545 if (servicename)
546 {
547 // 1. Put first label in namestr
548 ConvertDomainLabelToCString_unescaped((const domainlabel *)servicename, namestr);
549
550 // 2. Put second label and "local" into typestr
551 mDNS_snprintf(typestr, sizeof(typestr), "%#s.local.", SecondLabel(servicename));
552 }
553 else
554 {
555 namestr[0] = 0;
556 typestr[0] = 0;
557 }
558
559 // Calculate reply data length
560 len = sizeof(DNSServiceFlags);
561 len += sizeof(mDNSu32); // if index
562 len += sizeof(DNSServiceErrorType);
563 len += (int) (strlen(namestr) + 1);
564 len += (int) (strlen(typestr) + 1);
565 len += (int) (strlen(domstr) + 1);
566
567 // Build reply header
568 *rep = create_reply(op, len, request);
569 (*rep)->rhdr->flags = dnssd_htonl(flags);
570 (*rep)->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
571 (*rep)->rhdr->error = dnssd_htonl(err);
572
573 // Build reply body
574 data = (char *)&(*rep)->rhdr[1];
575 put_string(namestr, &data);
576 put_string(typestr, &data);
577 put_string(domstr, &data);
578 }
579
580 // Returns a resource record (allocated w/ malloc) containing the data found in an IPC message
581 // Data must be in the following format: flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional) ttl
582 // (ttl only extracted/set if ttl argument is non-zero). Returns NULL for a bad-parameter error
583 mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, int validate_flags)
584 {
585 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
586 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
587 char name[MAX_ESCAPED_DOMAIN_NAME];
588 int str_err = get_string(&request->msgptr, request->msgend, name, sizeof(name));
589 mDNSu16 type = get_uint16(&request->msgptr, request->msgend);
590 mDNSu16 class = get_uint16(&request->msgptr, request->msgend);
591 mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
592 const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata (&request->msgptr, request->msgend, rdlen);
593 mDNSu32 ttl = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
594 size_t rdcapacity;
595 AuthRecord *rr;
596 mDNSInterfaceID InterfaceID;
597 AuthRecType artype;
598 mDNSu8 recordType;
599
600 request->flags = flags;
601 request->interfaceIndex = interfaceIndex;
602
603 if (str_err) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL; }
604
605 if (!request->msgptr) { LogMsg("Error reading Resource Record from client"); return NULL; }
606
607 if (validate_flags &&
608 !((flags & kDNSServiceFlagsShared) == kDNSServiceFlagsShared) &&
609 !((flags & kDNSServiceFlagsUnique) == kDNSServiceFlagsUnique) &&
610 !((flags & kDNSServiceFlagsKnownUnique) == kDNSServiceFlagsKnownUnique))
611 {
612 LogMsg("ERROR: Bad resource record flags (must be one of either kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique)");
613 return NULL;
614 }
615 InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
616
617 // The registration is scoped to a specific interface index, but the interface is not currently on our list.
618 if ((InterfaceID == mDNSInterface_Any) && (interfaceIndex != kDNSServiceInterfaceIndexAny))
619 {
620 // On Apple platforms, an interface's mDNSInterfaceID is equal to its index. Using an interface index that isn't
621 // currently valid will cause the registration to take place as soon as it becomes valid. On other platforms,
622 // mDNSInterfaceID is actually a pointer to a platform-specific interface object, but we don't know what the pointer
623 // for the interface index will be ahead of time. For now, just return NULL to indicate an error condition since the
624 // interface index is invalid. Otherwise, the registration would be performed on all interfaces.
625 #if APPLE_OSX_mDNSResponder
626 InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
627 #else
628 return NULL;
629 #endif
630 }
631 rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
632 rr = (AuthRecord *) callocL("AuthRecord/read_rr_from_ipc_msg", sizeof(*rr) - sizeof(RDataBody) + rdcapacity);
633 if (!rr) FatalError("ERROR: calloc");
634
635 if (InterfaceID == mDNSInterface_LocalOnly)
636 artype = AuthRecordLocalOnly;
637 else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
638 artype = AuthRecordP2P;
639 else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
640 && (flags & kDNSServiceFlagsIncludeAWDL))
641 artype = AuthRecordAnyIncludeAWDLandP2P;
642 else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
643 artype = AuthRecordAnyIncludeP2P;
644 else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL))
645 artype = AuthRecordAnyIncludeAWDL;
646 else
647 artype = AuthRecordAny;
648
649 if (flags & kDNSServiceFlagsShared)
650 recordType = (mDNSu8) kDNSRecordTypeShared;
651 else if (flags & kDNSServiceFlagsKnownUnique)
652 recordType = (mDNSu8) kDNSRecordTypeKnownUnique;
653 else
654 recordType = (mDNSu8) kDNSRecordTypeUnique;
655
656 mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, type, 0, recordType, artype, mDNSNULL, mDNSNULL);
657
658 if (!MakeDomainNameFromDNSNameString(&rr->namestorage, name))
659 {
660 LogMsg("ERROR: bad name: %s", name);
661 freeL("AuthRecord/read_rr_from_ipc_msg", rr);
662 return NULL;
663 }
664
665 if (flags & kDNSServiceFlagsAllowRemoteQuery) rr->AllowRemoteQuery = mDNStrue;
666 rr->resrec.rrclass = class;
667 rr->resrec.rdlength = rdlen;
668 rr->resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
669 if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr->resrec, rdlen))
670 {
671 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
672 "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
673 request->request_id, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(type));
674 freeL("AuthRecord/read_rr_from_ipc_msg", rr);
675 return NULL;
676 }
677 if (GetTTL) rr->resrec.rroriginalttl = ttl;
678 rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
679 SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
680 return rr;
681 }
682
683 mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
684 {
685 domainlabel n;
686 domainname d, t;
687
688 if (!MakeDomainLabelFromLiteralString(&n, name)) return -1;
689 if (!MakeDomainNameFromDNSNameString(&t, regtype)) return -1;
690 if (!MakeDomainNameFromDNSNameString(&d, domain)) return -1;
691 if (!ConstructServiceName(srv, &n, &t, &d)) return -1;
692 return 0;
693 }
694
695 mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, int len)
696 {
697 const ssize_t n = send(s, ptr, len, 0);
698 // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a small write for us
699 // (four bytes for a typical error code return, 12 bytes for DNSServiceGetProperty(DaemonVersion)).
700 // If it does fail, we don't attempt to handle this failure, but we do log it so we know something is wrong.
701 if (n < len)
702 {
703 LogMsg("ERROR: send_all(%d) wrote %ld of %d errno %d (%s)",
704 s, (long)n, len, dnssd_errno, dnssd_strerror(dnssd_errno));
705 }
706 }
707
708 #if 0
709 mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const domainname * const d, const DNameListElem * const doms)
710 {
711 const DNameListElem *delem = mDNSNULL;
712 int bestDelta = -1; // the delta of the best match, lower is better
713 int dLabels = 0;
714 mDNSBool allow = mDNSfalse;
715
716 if (SystemUID(request->uid)) return mDNStrue;
717
718 dLabels = CountLabels(d);
719 for (delem = doms; delem; delem = delem->next)
720 {
721 if (delem->uid)
722 {
723 int delemLabels = CountLabels(&delem->name);
724 int delta = dLabels - delemLabels;
725 if ((bestDelta == -1 || delta <= bestDelta) && SameDomainName(&delem->name, SkipLeadingLabels(d, delta)))
726 {
727 bestDelta = delta;
728 allow = (allow || (delem->uid == request->uid));
729 }
730 }
731 }
732
733 return bestDelta == -1 ? mDNStrue : allow;
734 }
735 #endif
736
737 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
738 mDNSlocal void SetupAuditTokenForRequest(request_state *request)
739 {
740
741 pid_t audit_pid = audit_token_to_pid(request->audit_token);
742 if (audit_pid == 0)
743 {
744 #if !defined(LOCAL_PEERTOKEN)
745 #define LOCAL_PEERTOKEN 0x006 /* retrieve peer audit token */
746 #endif
747 socklen_t len = sizeof(audit_token_t);
748 int ret = getsockopt(request->sd, SOL_LOCAL, LOCAL_PEERTOKEN, &request->audit_token, &len);
749 if (ret != 0)
750 {
751 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
752 "SetupAuditTokenForRequest: No audit_token using LOCAL_PEERTOKEN (%s PID %d) for op %d ret(%d)",
753 request->pid_name, request->process_id, request->hdr.op, ret);
754 }
755 }
756 }
757 #endif
758
759 // ***************************************************************************
760 #if COMPILER_LIKES_PRAGMA_MARK
761 #pragma mark -
762 #pragma mark - external helpers
763 #endif
764
765 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
766 mDNSlocal void external_start_advertising_helper(service_instance *const instance)
767 {
768 AuthRecord *st = instance->subtypes;
769 ExtraResourceRecord *e;
770 int i;
771 const pid_t requestPID = instance->request->process_id;
772
773 if (mDNSIPPortIsZero(instance->request->u.servicereg.port))
774 {
775 LogInfo("external_start_advertising_helper: Not registering service with port number zero");
776 return;
777 }
778
779 if (instance->external_advertise) LogMsg("external_start_advertising_helper: external_advertise already set!");
780
781 for ( i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
782 external_start_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
783
784 external_start_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
785 external_start_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
786 external_start_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
787
788 for (e = instance->srs.Extras; e; e = e->next)
789 external_start_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
790
791 instance->external_advertise = mDNStrue;
792 }
793
794 mDNSlocal void external_stop_advertising_helper(service_instance *const instance)
795 {
796 AuthRecord *st = instance->subtypes;
797 ExtraResourceRecord *e;
798 int i;
799
800 if (!instance->external_advertise) return;
801
802 LogInfo("external_stop_advertising_helper: calling external_stop_advertising_service");
803
804 if (instance->request)
805 {
806 const pid_t requestPID = instance->request->process_id;
807 for (i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
808 {
809 external_stop_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
810 }
811
812 external_stop_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
813 external_stop_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
814 external_stop_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
815
816 for (e = instance->srs.Extras; e; e = e->next)
817 {
818 external_stop_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
819 }
820 }
821
822 instance->external_advertise = mDNSfalse;
823 }
824 #endif // MDNSRESPONDER_SUPPORTS(APPLE, D2D)
825
826 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
827 mDNSlocal dispatch_queue_t _get_trust_results_dispatch_queue(void)
828 {
829 static dispatch_once_t once = 0;
830 static dispatch_queue_t queue = NULL;
831
832 dispatch_once(&once, ^{
833 dispatch_queue_attr_t const attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
834 queue = dispatch_queue_create("com.apple.mDNSResponder.trust_results-queue", attr);
835 });
836 return queue;
837 }
838 #endif
839
840 // ***************************************************************************
841 #if COMPILER_LIKES_PRAGMA_MARK
842 #pragma mark -
843 #pragma mark - DNSServiceRegister
844 #endif
845
846 mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
847 {
848 ExtraResourceRecord *extra = (ExtraResourceRecord *)rr->RecordContext;
849 (void)m; // Unused
850
851 if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
852
853 LogInfo(" FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
854
855 if (rr->resrec.rdata != &rr->rdatastorage)
856 freeL("Extra RData", rr->resrec.rdata);
857 freeL("ExtraResourceRecord/FreeExtraRR", extra);
858 }
859
860 mDNSlocal void unlink_and_free_service_instance(service_instance *srv)
861 {
862 ExtraResourceRecord *e = srv->srs.Extras, *tmp;
863
864 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
865 external_stop_advertising_helper(srv);
866 #endif
867
868 // clear pointers from parent struct
869 if (srv->request)
870 {
871 service_instance **p = &srv->request->u.servicereg.instances;
872 while (*p)
873 {
874 if (*p == srv) { *p = (*p)->next; break; }
875 p = &(*p)->next;
876 }
877 }
878
879 while (e)
880 {
881 e->r.RecordContext = e;
882 tmp = e;
883 e = e->next;
884 FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree);
885 }
886
887 if (srv->srs.RR_TXT.resrec.rdata != &srv->srs.RR_TXT.rdatastorage)
888 freeL("TXT RData", srv->srs.RR_TXT.resrec.rdata);
889
890 if (srv->subtypes)
891 {
892 freeL("ServiceSubTypes", srv->subtypes);
893 srv->subtypes = NULL;
894 }
895 freeL("service_instance", srv);
896 }
897
898 // Count how many other service records we have locally with the same name, but different rdata.
899 // For auto-named services, we can have at most one per machine -- if we allowed two auto-named services of
900 // the same type on the same machine, we'd get into an infinite autoimmune-response loop of continuous renaming.
901 mDNSexport int CountPeerRegistrations(ServiceRecordSet *const srs)
902 {
903 int count = 0;
904 ResourceRecord *r = &srs->RR_SRV.resrec;
905 AuthRecord *rr;
906
907 for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
908 if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r))
909 count++;
910
911 verbosedebugf("%d peer registrations for %##s", count, r->name->c);
912 return(count);
913 }
914
915 mDNSexport int CountExistingRegistrations(domainname *srv, mDNSIPPort port)
916 {
917 int count = 0;
918 AuthRecord *rr;
919 for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
920 if (rr->resrec.rrtype == kDNSType_SRV &&
921 mDNSSameIPPort(rr->resrec.rdata->u.srv.port, port) &&
922 SameDomainName(rr->resrec.name, srv))
923 count++;
924 return(count);
925 }
926
927 mDNSlocal void SendServiceRemovalNotification(ServiceRecordSet *const srs)
928 {
929 reply_state *rep;
930 service_instance *instance = srs->ServiceContext;
931 if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, 0, mStatus_NoError) != mStatus_NoError)
932 LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
933 else { append_reply(instance->request, rep); instance->clientnotified = mDNSfalse; }
934 }
935
936 // service registration callback performs three duties - frees memory for deregistered services,
937 // handles name conflicts, and delivers completed registration information to the client
938 mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
939 {
940 mStatus err;
941 mDNSBool SuppressError = mDNSfalse;
942 service_instance *instance;
943 reply_state *rep;
944 (void)m; // Unused
945
946 if (!srs)
947 {
948 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: srs is NULL %d", result);
949 return;
950 }
951
952 instance = srs->ServiceContext;
953 if (!instance)
954 {
955 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: srs->ServiceContext is NULL %d", result);
956 return;
957 }
958
959 // don't send errors up to client for wide-area, empty-string registrations
960 if (instance->request &&
961 instance->request->u.servicereg.default_domain &&
962 !instance->default_local)
963 SuppressError = mDNStrue;
964
965 if (mDNS_LoggingEnabled)
966 {
967 const char *result_description;
968 char description[32]; // 32-byte is enough for holding "suppressed error -2147483648\0"
969 mDNSu32 request_id = instance->request ? instance->request->request_id : 0;
970 switch (result) {
971 case mStatus_NoError:
972 result_description = "REGISTERED";
973 break;
974 case mStatus_MemFree:
975 result_description = "DEREGISTERED";
976 break;
977 case mStatus_NameConflict:
978 result_description = "NAME CONFLICT";
979 break;
980 default:
981 mDNS_snprintf(description, sizeof(description), "%s %d", SuppressError ? "suppressed error" : "CALLBACK", result);
982 result_description = description;
983 break;
984 }
985 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%u] DNSServiceRegister(" PRI_DM_NAME ", %u) %s",
986 request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name), mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), result_description);
987 }
988
989 if (!instance->request && result != mStatus_MemFree)
990 {
991 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: instance->request is NULL %d", result);
992 return;
993 }
994
995 if (result == mStatus_NoError)
996 {
997 if (instance->request->u.servicereg.allowremotequery)
998 {
999 ExtraResourceRecord *e;
1000 srs->RR_ADV.AllowRemoteQuery = mDNStrue;
1001 srs->RR_PTR.AllowRemoteQuery = mDNStrue;
1002 srs->RR_SRV.AllowRemoteQuery = mDNStrue;
1003 srs->RR_TXT.AllowRemoteQuery = mDNStrue;
1004 for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
1005 }
1006
1007 if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
1008 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));
1009 else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
1010
1011 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1012 if (callExternalHelpers(instance->request->u.servicereg.InterfaceID, &instance->domain, instance->request->flags))
1013 {
1014 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%u] regservice_callback: calling external_start_advertising_helper()", instance->request->request_id);
1015 external_start_advertising_helper(instance);
1016 }
1017 #endif
1018 if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0)
1019 RecordUpdatedNiceLabel(0); // Successfully got new name, tell user immediately
1020 }
1021 else if (result == mStatus_MemFree)
1022 {
1023 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
1024 curr_num_regservices--;
1025 #endif
1026 if (instance->request && instance->renameonmemfree)
1027 {
1028 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1029 external_stop_advertising_helper(instance);
1030 #endif
1031 instance->renameonmemfree = 0;
1032 err = mDNS_RenameAndReregisterService(m, srs, &instance->request->u.servicereg.name);
1033 if (err)
1034 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] ERROR: regservice_callback - RenameAndReregisterService returned %d", instance->request->request_id, err);
1035 // error should never happen - safest to log and continue
1036 }
1037 else
1038 unlink_and_free_service_instance(instance);
1039 }
1040 else if (result == mStatus_NameConflict)
1041 {
1042 if (instance->request->u.servicereg.autorename)
1043 {
1044 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1045 external_stop_advertising_helper(instance);
1046 #endif
1047 if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0)
1048 {
1049 // On conflict for an autoname service, rename and reregister *all* autoname services
1050 IncrementLabelSuffix(&m->nicelabel, mDNStrue);
1051 mDNS_ConfigChanged(m); // Will call back into udsserver_handle_configchange()
1052 }
1053 else // On conflict for a non-autoname service, rename and reregister just that one service
1054 {
1055 if (instance->clientnotified) SendServiceRemovalNotification(srs);
1056 mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
1057 }
1058 }
1059 else
1060 {
1061 if (!SuppressError)
1062 {
1063 if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
1064 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));
1065 else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
1066 }
1067 unlink_and_free_service_instance(instance);
1068 }
1069 }
1070 else // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
1071 {
1072 if (!SuppressError)
1073 {
1074 if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
1075 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));
1076 else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
1077 }
1078 }
1079 }
1080
1081 mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result)
1082 {
1083 (void)m; // Unused
1084 if (!rr->RecordContext) // parent struct already freed by termination callback
1085 {
1086 if (result == mStatus_NoError)
1087 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Error: regrecord_callback: successful registration of orphaned record " PRI_S, ARDisplayString(m, rr));
1088 else
1089 {
1090 if (result != mStatus_MemFree)
1091 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regrecord_callback: error %d received after parent termination", result);
1092
1093 // We come here when the record is being deregistered either from DNSServiceRemoveRecord or connection_termination.
1094 // If the record has been updated, we need to free the rdata. Every time we call mDNS_Update, it calls update_callback
1095 // with the old rdata (so that we can free it) and stores the new rdata in "rr->resrec.rdata". This means, we need
1096 // to free the latest rdata for which the update_callback was never called with.
1097 if (rr->resrec.rdata != &rr->rdatastorage) freeL("RData/regrecord_callback", rr->resrec.rdata);
1098 freeL("AuthRecord/regrecord_callback", rr);
1099 }
1100 }
1101 else
1102 {
1103 registered_record_entry *re = rr->RecordContext;
1104 request_state *request = re->request;
1105
1106 if (mDNS_LoggingEnabled)
1107 {
1108 const char *result_description;
1109 char description[16]; // 16-byte is enough for holding -2147483648\0
1110 switch (result) {
1111 case mStatus_NoError:
1112 result_description = "REGISTERED";
1113 break;
1114 case mStatus_MemFree:
1115 result_description = "DEREGISTERED";
1116 break;
1117 case mStatus_NameConflict:
1118 result_description = "NAME CONFLICT";
1119 break;
1120 default:
1121 mDNS_snprintf(description, sizeof(description), "%d", result);
1122 result_description = description;
1123 break;
1124 }
1125
1126 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%u] DNSServiceRegisterRecord(%u " PRI_S ")" PUB_S,
1127 request->request_id, re->key, RRDisplayString(m, &rr->resrec), result_description);
1128 }
1129
1130 if (result != mStatus_MemFree)
1131 {
1132 int len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
1133 reply_state *reply = create_reply(reg_record_reply_op, len, request);
1134 reply->mhdr->client_context = re->regrec_client_context;
1135 reply->rhdr->flags = dnssd_htonl(0);
1136 reply->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, rr->resrec.InterfaceID, mDNSfalse));
1137 reply->rhdr->error = dnssd_htonl(result);
1138 append_reply(request, reply);
1139 }
1140
1141 if (result)
1142 {
1143 // If this is a callback to a keepalive record, do not free it.
1144 if (result == mStatus_BadStateErr)
1145 {
1146 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1147 "[R%u] regrecord_callback: Callback with error code mStatus_BadStateErr - not freeing the record.", request->request_id);
1148 }
1149 else
1150 {
1151 // unlink from list, free memory
1152 registered_record_entry **ptr = &request->u.reg_recs;
1153 while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
1154 if (!*ptr)
1155 {
1156 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1157 "[R%u] regrecord_callback - record not in list!", request->request_id);
1158 return;
1159 }
1160 *ptr = (*ptr)->next;
1161 freeL("registered_record_entry AuthRecord regrecord_callback", re->rr);
1162 freeL("registered_record_entry regrecord_callback", re);
1163 }
1164 }
1165 else
1166 {
1167 if (re->external_advertise)
1168 {
1169 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1170 "[R%u] regrecord_callback: external_advertise already set!", request->request_id);
1171 }
1172
1173 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1174 if (callExternalHelpers(re->origInterfaceID, &rr->namestorage, request->flags))
1175 {
1176 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1177 "[R%u] regrecord_callback: calling external_start_advertising_service", request->request_id);
1178 external_start_advertising_service(&rr->resrec, request->flags, request->process_id);
1179 re->external_advertise = mDNStrue;
1180 }
1181 #endif
1182 }
1183 }
1184 }
1185
1186 // set_peer_pid() is called after mem is allocated for each new request in NewRequest()
1187 // This accounts for 2 places (connect_callback, request_callback)
1188 mDNSlocal void set_peer_pid(request_state *request)
1189 {
1190 request->pid_name[0] = '\0';
1191 request->process_id = -1;
1192 #ifdef LOCAL_PEEREPID
1193 pid_t p = (pid_t) -1;
1194 socklen_t len = sizeof(p);
1195 if (request->sd < 0)
1196 return;
1197 // to extract the effective pid value
1198 if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &p, &len) != 0)
1199 return;
1200 // to extract the process name from the pid value
1201 if (proc_pidinfo(p, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0)
1202 return;
1203 mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name));
1204 request->process_id = p;
1205 debugf("set_peer_pid: Client PEEREPID is %d %s", p, request->pid_name);
1206 #else // !LOCAL_PEEREPID
1207 LogInfo("set_peer_pid: Not Supported on this version of OS");
1208 if (request->sd < 0)
1209 return;
1210 #endif // LOCAL_PEEREPID
1211 }
1212
1213 mDNSlocal void connection_termination(request_state *request)
1214 {
1215 // When terminating a shared connection, we need to scan the all_requests list
1216 // and terminate any subbordinate operations sharing this file descriptor
1217 request_state **req = &all_requests;
1218
1219 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1220 "[R%d] DNSServiceCreateConnection STOP PID[%d](" PUB_S ")",
1221 request->request_id, request->process_id, request->pid_name);
1222
1223 while (*req)
1224 {
1225 if ((*req)->primary == request)
1226 {
1227 // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
1228 request_state *tmp = *req;
1229 if (tmp->primary == tmp) LogMsg("connection_termination ERROR (*req)->primary == *req for %p %d", tmp, tmp->sd);
1230 if (tmp->replies) LogMsg("connection_termination ERROR How can subordinate req %p %d have replies queued?", tmp, tmp->sd);
1231 abort_request(tmp);
1232 *req = tmp->next;
1233 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1234 if (tmp->trust)
1235 {
1236 void * context = mdns_trust_get_context(tmp->trust);
1237 mdns_trust_set_context(tmp->trust, NULL);
1238 if (context) freeL("context/connection_termination", context);
1239 mdns_trust_forget(&tmp->trust);
1240 }
1241 #endif
1242 freeL("request_state/connection_termination", tmp);
1243 }
1244 else
1245 req = &(*req)->next;
1246 }
1247
1248 while (request->u.reg_recs)
1249 {
1250 registered_record_entry *ptr = request->u.reg_recs;
1251 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1252 "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") STOP PID[%d](" PUB_S ")",
1253 request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ptr->rr->resrec), request->process_id,
1254 request->pid_name);
1255 request->u.reg_recs = request->u.reg_recs->next;
1256 ptr->rr->RecordContext = NULL;
1257 if (ptr->external_advertise)
1258 {
1259 ptr->external_advertise = mDNSfalse;
1260 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1261 external_stop_advertising_service(&ptr->rr->resrec, request->flags, request->process_id);
1262 #endif
1263 }
1264 LogMcastS(ptr->rr, request, reg_stop);
1265 mDNS_Deregister(&mDNSStorage, ptr->rr); // Will free ptr->rr for us
1266 freeL("registered_record_entry/connection_termination", ptr);
1267 }
1268 }
1269
1270 mDNSlocal void handle_cancel_request(request_state *request)
1271 {
1272 request_state **req = &all_requests;
1273 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%d] Cancel %08X %08X",
1274 request->request_id, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
1275 while (*req)
1276 {
1277 if ((*req)->primary == request &&
1278 (*req)->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
1279 (*req)->hdr.client_context.u32[1] == request->hdr.client_context.u32[1])
1280 {
1281 // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
1282 request_state *tmp = *req;
1283 abort_request(tmp);
1284 *req = tmp->next;
1285 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1286 if (tmp->trust)
1287 {
1288 void * context = mdns_trust_get_context(tmp->trust);
1289 mdns_trust_set_context(tmp->trust, NULL);
1290 if (context) freeL("context/handle_cancel_request", context);
1291 mdns_trust_forget(&tmp->trust);
1292 }
1293 #endif
1294 freeL("request_state/handle_cancel_request", tmp);
1295 }
1296 else
1297 req = &(*req)->next;
1298 }
1299 }
1300
1301 mDNSlocal mStatus _handle_regrecord_request_start(request_state *request, AuthRecord * rr)
1302 {
1303 mStatus err;
1304 registered_record_entry *re;
1305 // Don't allow non-local domains to be regsitered as LocalOnly. Allowing this would permit
1306 // clients to register records such as www.bigbank.com A w.x.y.z to redirect Safari.
1307 if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly && !IsLocalDomain(rr->resrec.name) &&
1308 rr->resrec.rrclass == kDNSClass_IN && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA ||
1309 rr->resrec.rrtype == kDNSType_CNAME))
1310 {
1311 freeL("AuthRecord/handle_regrecord_request", rr);
1312 return (mStatus_BadParamErr);
1313 }
1314 // allocate registration entry, link into list
1315 re = (registered_record_entry *) callocL("registered_record_entry", sizeof(*re));
1316 if (!re) FatalError("ERROR: calloc");
1317 re->key = request->hdr.reg_index;
1318 re->rr = rr;
1319 re->regrec_client_context = request->hdr.client_context;
1320 re->request = request;
1321 re->external_advertise = mDNSfalse;
1322 rr->RecordContext = re;
1323 rr->RecordCallback = regrecord_callback;
1324
1325 re->origInterfaceID = rr->resrec.InterfaceID;
1326 if (rr->resrec.InterfaceID == mDNSInterface_P2P)
1327 rr->resrec.InterfaceID = mDNSInterface_Any;
1328 #if 0
1329 if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError);
1330 #endif
1331 if (rr->resrec.rroriginalttl == 0)
1332 rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
1333
1334 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1335 "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") START PID[%d](" PUB_S ")",
1336 request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &rr->resrec), request->process_id,
1337 request->pid_name);
1338
1339 err = mDNS_Register(&mDNSStorage, rr);
1340 if (err)
1341 {
1342 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1343 "[R%d] DNSServiceRegisterRecord(0x%X, %d," PRI_S ") ERROR (%d)",
1344 request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &rr->resrec), err);
1345 freeL("registered_record_entry", re);
1346 freeL("registered_record_entry/AuthRecord", rr);
1347 }
1348 else
1349 {
1350 LogMcastS(rr, request, reg_start);
1351 re->next = request->u.reg_recs;
1352 request->u.reg_recs = re;
1353 }
1354 return err;
1355 }
1356
1357 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1358
1359 mDNSlocal void _return_regrecord_request_error(request_state *request, mStatus error)
1360 {
1361 reply_state *rep;
1362 if (GenerateNTDResponse(NULL, 0, request, &rep, reg_record_reply_op, 0, error) != mStatus_NoError)
1363 {
1364 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegisterRecord _return_regrecord_request_error: error(%d)", request->request_id, error);
1365 }
1366 else
1367 {
1368 append_reply(request, rep);
1369 }
1370 }
1371
1372 mDNSlocal mStatus _handle_regrecord_request_with_trust(request_state *request, AuthRecord * rr)
1373 {
1374 mStatus err;
1375 if (audit_token_to_pid(request->audit_token) == 0)
1376 {
1377 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, 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);
1378 err = _handle_regrecord_request_start(request, rr);
1379 }
1380 else
1381 {
1382 const char *service_ptr = NULL;
1383 char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
1384 domainlabel name;
1385 domainname type, domain;
1386 bool good = DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
1387 if (good)
1388 {
1389 ConvertDomainNameToCString(&type, type_str);
1390 service_ptr = type_str;
1391 }
1392
1393 mdns_trust_flags_t flags = mdns_trust_flags_none;
1394 mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, service_ptr, &flags);
1395 switch (status)
1396 {
1397 case mdns_trust_status_denied:
1398 case mdns_trust_status_pending:
1399 {
1400 mdns_trust_t trust = mdns_trust_create(request->audit_token, service_ptr, flags);
1401 if (!trust)
1402 {
1403 freeL("AuthRecord/_handle_regrecord_request_with_trust", rr);
1404 err = mStatus_NoMemoryErr;
1405 goto exit;
1406 }
1407 mdns_trust_set_context(trust, rr);
1408 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
1409 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
1410 {
1411 if (event == mdns_trust_event_result)
1412 {
1413 mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
1414 KQueueLock();
1415 AuthRecord * _rr = mdns_trust_get_context(trust);
1416 if (_rr)
1417 {
1418 if (!error)
1419 {
1420 mdns_trust_set_context(trust, NULL); // _handle_regrecord_request_start handles free
1421 error = _handle_regrecord_request_start(request, _rr);
1422 // No context means the request was canceled before we got here
1423 }
1424 if (error) // (not else if) Always check for error result
1425 {
1426 _return_regrecord_request_error(request, error);
1427 }
1428 }
1429 KQueueUnlock("_handle_regrecord_request_with_trust");
1430 }
1431 });
1432 request->trust = trust;
1433 mdns_trust_activate(trust);
1434 err = mStatus_NoError;
1435 break;
1436 }
1437
1438 case mdns_trust_status_no_entitlement:
1439 err = mStatus_NoAuth;
1440 break;
1441
1442 case mdns_trust_status_granted:
1443 err = _handle_regrecord_request_start(request, rr);
1444 break;
1445
1446 default:
1447 err = mStatus_UnknownErr;
1448 break;
1449 }
1450 }
1451 exit:
1452 return err;
1453 }
1454 #endif // TRUST_ENFORCEMENT
1455
1456 mDNSlocal mStatus handle_regrecord_request(request_state *request)
1457 {
1458 mStatus err = mStatus_BadParamErr;
1459 AuthRecord *rr;
1460
1461 if (request->terminate != connection_termination)
1462 { LogMsg("%3d: DNSServiceRegisterRecord(not a shared connection ref)", request->sd); return(err); }
1463
1464 rr = read_rr_from_ipc_msg(request, 1, 1);
1465 if (rr)
1466 {
1467 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1468 if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
1469 IsLocalDomain(rr->resrec.name))
1470 {
1471 err = _handle_regrecord_request_with_trust(request, rr);
1472 }
1473 else
1474 {
1475 err = _handle_regrecord_request_start(request, rr);
1476 }
1477 #else
1478 err = _handle_regrecord_request_start(request, rr);
1479 #endif
1480 }
1481 return(err);
1482 }
1483
1484 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
1485
1486 mDNSlocal void regservice_termination_callback(request_state *request)
1487 {
1488 if (!request)
1489 {
1490 LogMsg("regservice_termination_callback context is NULL");
1491 return;
1492 }
1493 while (request->u.servicereg.instances)
1494 {
1495 service_instance *p = request->u.servicereg.instances;
1496 request->u.servicereg.instances = request->u.servicereg.instances->next;
1497 // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
1498 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%d] DNSServiceRegister(" PRI_DM_NAME ", %u) STOP PID[%d](" PUB_S ")",
1499 request->request_id, DM_NAME_PARAM(p->srs.RR_SRV.resrec.name),
1500 mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port), request->process_id, request->pid_name);
1501
1502 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1503 external_stop_advertising_helper(p);
1504 #endif
1505
1506 // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
1507 // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
1508 // request->u.servicereg.instances as we work our way through the list, implicitly cutting one element at a time
1509 // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
1510 // because by then we might have already freed p
1511 p->request = NULL;
1512 LogMcastS(&p->srs.RR_SRV, request, reg_stop);
1513 if (mDNS_DeregisterService(&mDNSStorage, &p->srs))
1514 {
1515 unlink_and_free_service_instance(p);
1516 // Don't touch service_instance *p after this -- it's likely to have been freed already
1517 }
1518 }
1519 if (request->u.servicereg.txtdata)
1520 {
1521 freeL("service_info txtdata", request->u.servicereg.txtdata);
1522 request->u.servicereg.txtdata = NULL;
1523 }
1524 if (request->u.servicereg.autoname)
1525 {
1526 // Clear autoname before calling UpdateDeviceInfoRecord() so it doesn't mistakenly include this in its count of active autoname registrations
1527 request->u.servicereg.autoname = mDNSfalse;
1528 UpdateDeviceInfoRecord(&mDNSStorage);
1529 }
1530 }
1531
1532 mDNSlocal request_state *LocateSubordinateRequest(request_state *request)
1533 {
1534 request_state *req;
1535 for (req = all_requests; req; req = req->next)
1536 if (req->primary == request &&
1537 req->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
1538 req->hdr.client_context.u32[1] == request->hdr.client_context.u32[1]) return(req);
1539 return(request);
1540 }
1541
1542 mDNSlocal mStatus add_record_to_service(request_state *request, service_instance *instance, mDNSu16 rrtype, mDNSu16 rdlen,
1543 const mDNSu8 *const rdata, mDNSu32 ttl)
1544 {
1545 ServiceRecordSet *srs = &instance->srs;
1546 mStatus result;
1547 const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
1548 ExtraResourceRecord *extra = (ExtraResourceRecord *)callocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + rdcapacity);
1549 if (!extra) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
1550
1551 extra->r.resrec.rrtype = rrtype;
1552 extra->r.resrec.rdata = &extra->r.rdatastorage;
1553 extra->r.resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
1554 extra->r.resrec.rdlength = rdlen;
1555 if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &extra->r.resrec, rdlen))
1556 {
1557 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
1558 "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
1559 request->request_id, DM_NAME_PARAM(request->u.servicereg.instances ?
1560 request->u.servicereg.instances->srs.RR_SRV.resrec.name : mDNSNULL), DNSTypeName(rrtype));
1561 freeL("ExtraResourceRecord/add_record_to_service", extra);
1562 return mStatus_BadParamErr;
1563 }
1564 SetNewRData(&extra->r.resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
1565 // use InterfaceID value from DNSServiceRegister() call that created the original service
1566 extra->r.resrec.InterfaceID = request->u.servicereg.InterfaceID;
1567
1568 result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, request->flags);
1569 if (result)
1570 {
1571 freeL("ExtraResourceRecord/add_record_to_service", extra);
1572 return result;
1573 }
1574 LogMcastS(&srs->RR_PTR, request, reg_start);
1575
1576 extra->ClientID = request->hdr.reg_index;
1577 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1578 if ( instance->external_advertise
1579 && callExternalHelpers(request->u.servicereg.InterfaceID, &instance->domain, request->flags))
1580 {
1581 LogInfo("add_record_to_service: calling external_start_advertising_service");
1582 external_start_advertising_service(&extra->r.resrec, request->flags, request->process_id);
1583 }
1584 #endif
1585 return result;
1586 }
1587
1588 mDNSlocal mStatus handle_add_request(request_state *request)
1589 {
1590 service_instance *i;
1591 mStatus result = mStatus_UnknownErr;
1592 DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend);
1593 mDNSu16 rrtype = get_uint16(&request->msgptr, request->msgend);
1594 mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
1595 const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
1596 mDNSu32 ttl = get_uint32(&request->msgptr, request->msgend);
1597 if (!ttl) ttl = DefaultTTLforRRType(rrtype);
1598 (void)flags; // Unused
1599
1600 if (!request->msgptr)
1601 {
1602 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1603 "[R%d] DNSServiceAddRecord(unreadable parameters)", request->request_id);
1604 return(mStatus_BadParamErr);
1605 }
1606
1607 // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1608 if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1609
1610 if (request->terminate != regservice_termination_callback)
1611 {
1612 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1613 "[R%d] DNSServiceAddRecord(not a registered service ref)", request->request_id);
1614 return(mStatus_BadParamErr);
1615 }
1616
1617 // For a service registered with zero port, don't allow adding records. This mostly happens due to a bug
1618 // in the application. See radar://9165807.
1619 if (mDNSIPPortIsZero(request->u.servicereg.port))
1620 {
1621 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1622 "[R%d] DNSServiceAddRecord: adding record to a service registered with zero port", request->request_id);
1623 return(mStatus_BadParamErr);
1624 }
1625 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1626 "[R%d] DNSServiceAddRecord(%X, " PRI_DM_NAME ", " PUB_S ", %d) PID[%d](" PUB_S ")",
1627 request->request_id, flags,
1628 DM_NAME_PARAM((request->u.servicereg.instances) ? (request->u.servicereg.instances->srs.RR_SRV.resrec.name) : mDNSNULL),
1629 DNSTypeName(rrtype), rdlen, request->process_id, request->pid_name);
1630
1631 for (i = request->u.servicereg.instances; i; i = i->next)
1632 {
1633 result = add_record_to_service(request, i, rrtype, rdlen, rdata, ttl);
1634 if (result && i->default_local) break;
1635 else result = mStatus_NoError; // suppress non-local default errors
1636 }
1637
1638 return(result);
1639 }
1640
1641 mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd, mDNSu16 oldrdlen)
1642 {
1643 mDNSBool external_advertise = (rr->UpdateContext) ? *((mDNSBool *)rr->UpdateContext) : mDNSfalse;
1644 (void)m; // Unused
1645
1646 // There are three cases.
1647 //
1648 // 1. We have updated the primary TXT record of the service
1649 // 2. We have updated the TXT record that was added to the service using DNSServiceAddRecord
1650 // 3. We have updated the TXT record that was registered using DNSServiceRegisterRecord
1651 //
1652 // external_advertise is set if we have advertised at least once during the initial addition
1653 // of the record in all of the three cases above. We should have checked for InterfaceID/LocalDomain
1654 // checks during the first time and hence we don't do any checks here
1655 if (external_advertise)
1656 {
1657 ResourceRecord ext = rr->resrec;
1658 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1659 DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(rr->ARType);
1660 #endif
1661
1662 if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
1663 SetNewRData(&ext, oldrd, oldrdlen);
1664 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1665 external_stop_advertising_service(&ext, flags, 0);
1666 LogInfo("update_callback: calling external_start_advertising_service");
1667 external_start_advertising_service(&rr->resrec, flags, 0);
1668 #endif
1669 }
1670 exit:
1671 if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
1672 }
1673
1674 mDNSlocal mStatus update_record(AuthRecord *ar, mDNSu16 rdlen, const mDNSu8 *const rdata, mDNSu32 ttl,
1675 const mDNSBool *const external_advertise, const mDNSu32 request_id)
1676 {
1677 ResourceRecord rr;
1678 mStatus result;
1679 const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
1680 RData *newrd = (RData *) callocL("RData/update_record", sizeof(*newrd) - sizeof(RDataBody) + rdcapacity);
1681 if (!newrd) FatalError("ERROR: calloc");
1682 mDNSPlatformMemZero(&rr, (mDNSu32)sizeof(rr));
1683 rr.name = ar->resrec.name;
1684 rr.rrtype = ar->resrec.rrtype;
1685 rr.rrclass = ar->resrec.rrclass;
1686 rr.rdata = newrd;
1687 rr.rdata->MaxRDLength = (mDNSu16)rdcapacity;
1688 rr.rdlength = rdlen;
1689 if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr, rdlen))
1690 {
1691 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
1692 "[R%u] update_record: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
1693 request_id, DM_NAME_PARAM(rr.name), DNSTypeName(rr.rrtype));
1694 freeL("RData/update_record", newrd);
1695 return mStatus_BadParamErr;
1696 }
1697 rdlen = GetRDLength(&rr, mDNSfalse);
1698 // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
1699 // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
1700 // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
1701 if (ar->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
1702
1703 if (external_advertise) ar->UpdateContext = (void *)external_advertise;
1704
1705 result = mDNS_Update(&mDNSStorage, ar, ttl, rdlen, newrd, update_callback);
1706 if (result) { LogMsg("update_record: Error %d for %s", (int)result, ARDisplayString(&mDNSStorage, ar)); freeL("RData/update_record", newrd); }
1707 return result;
1708 }
1709
1710 mDNSlocal mStatus handle_update_request(request_state *request)
1711 {
1712 const ipc_msg_hdr *const hdr = &request->hdr;
1713 mStatus result = mStatus_BadReferenceErr;
1714 service_instance *i;
1715 AuthRecord *rr = NULL;
1716
1717 // get the message data
1718 DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend); // flags unused
1719 mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
1720 const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
1721 mDNSu32 ttl = get_uint32(&request->msgptr, request->msgend);
1722 (void)flags; // Unused
1723
1724 if (!request->msgptr)
1725 {
1726 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1727 "[R%d] DNSServiceUpdateRecord(unreadable parameters)", request->request_id);
1728 return(mStatus_BadParamErr);
1729 }
1730
1731 // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1732 if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1733
1734 if (request->terminate == connection_termination)
1735 {
1736 // update an individually registered record
1737 registered_record_entry *reptr;
1738 for (reptr = request->u.reg_recs; reptr; reptr = reptr->next)
1739 {
1740 if (reptr->key == hdr->reg_index)
1741 {
1742 result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise, request->request_id);
1743 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1744 "[R%d] DNSServiceUpdateRecord(" PRI_DM_NAME ", " PUB_S ") PID[%d](" PUB_S ")",
1745 request->request_id, DM_NAME_PARAM(reptr->rr->resrec.name),
1746 reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>",
1747 request->process_id, request->pid_name);
1748 goto end;
1749 }
1750 }
1751 result = mStatus_BadReferenceErr;
1752 goto end;
1753 }
1754
1755 if (request->terminate != regservice_termination_callback)
1756 {
1757 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1758 "[R%d] DNSServiceUpdateRecord(not a registered service ref)", request->request_id);
1759 return(mStatus_BadParamErr);
1760 }
1761
1762 // For a service registered with zero port, only SRV record is initialized. Don't allow any updates.
1763 if (mDNSIPPortIsZero(request->u.servicereg.port))
1764 {
1765 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1766 "[R%d] DNSServiceUpdateRecord: updating the record of a service registered with zero port", request->request_id);
1767 return(mStatus_BadParamErr);
1768 }
1769
1770 // update the saved off TXT data for the service
1771 if (hdr->reg_index == TXT_RECORD_INDEX)
1772 {
1773 if (request->u.servicereg.txtdata)
1774 { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
1775 if (rdlen > 0)
1776 {
1777 request->u.servicereg.txtdata = mallocL("service_info txtdata", rdlen);
1778 if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_update_request - malloc");
1779 mDNSPlatformMemCopy(request->u.servicereg.txtdata, rdata, rdlen);
1780 }
1781 request->u.servicereg.txtlen = rdlen;
1782 }
1783
1784 // update a record from a service record set
1785 for (i = request->u.servicereg.instances; i; i = i->next)
1786 {
1787 if (hdr->reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
1788 else
1789 {
1790 ExtraResourceRecord *e;
1791 for (e = i->srs.Extras; e; e = e->next)
1792 if (e->ClientID == hdr->reg_index) { rr = &e->r; break; }
1793 }
1794
1795 if (!rr) { result = mStatus_BadReferenceErr; goto end; }
1796 result = update_record(rr, rdlen, rdata, ttl, &i->external_advertise, request->request_id);
1797 if (result && i->default_local) goto end;
1798 else result = mStatus_NoError; // suppress non-local default errors
1799 }
1800
1801 end:
1802 if (request->terminate == regservice_termination_callback)
1803 LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s) PID[%d](%s)", request->sd,
1804 (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
1805 rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>",
1806 request->process_id, request->pid_name);
1807
1808 return(result);
1809 }
1810
1811 // remove a resource record registered via DNSServiceRegisterRecord()
1812 mDNSlocal mStatus remove_record(request_state *request)
1813 {
1814 mStatus err = mStatus_UnknownErr;
1815 registered_record_entry *e, **ptr = &request->u.reg_recs;
1816
1817 while (*ptr && (*ptr)->key != request->hdr.reg_index) ptr = &(*ptr)->next;
1818 if (!*ptr) { LogMsg("%3d: DNSServiceRemoveRecord(%u) not found", request->sd, request->hdr.reg_index); return mStatus_BadReferenceErr; }
1819 e = *ptr;
1820 *ptr = e->next; // unlink
1821
1822 LogOperation("%3d: DNSServiceRemoveRecord(%u %s) PID[%d](%s)",
1823 request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec), request->process_id, request->pid_name);
1824 e->rr->RecordContext = NULL;
1825 if (e->external_advertise)
1826 {
1827 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1828 external_stop_advertising_service(&e->rr->resrec, request->flags, request->process_id);
1829 #endif
1830 e->external_advertise = mDNSfalse;
1831 }
1832 LogMcastS(e->rr, request, reg_stop);
1833 err = mDNS_Deregister(&mDNSStorage, e->rr); // Will free e->rr for us; we're responsible for freeing e
1834 if (err)
1835 {
1836 LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err);
1837 freeL("registered_record_entry AuthRecord remove_record", e->rr);
1838 }
1839 freeL("registered_record_entry remove_record", e);
1840 return err;
1841 }
1842
1843 mDNSlocal mStatus remove_extra(const request_state *const request, service_instance *const serv, mDNSu16 *const rrtype)
1844 {
1845 mStatus err = mStatus_BadReferenceErr;
1846 ExtraResourceRecord *ptr;
1847
1848 for (ptr = serv->srs.Extras; ptr; ptr = ptr->next)
1849 {
1850 if (ptr->ClientID == request->hdr.reg_index) // found match
1851 {
1852 *rrtype = ptr->r.resrec.rrtype;
1853 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1854 if (serv->external_advertise)
1855 {
1856 external_stop_advertising_service(&ptr->r.resrec, request->flags, request->process_id);
1857 }
1858 #endif
1859 err = mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
1860 break;
1861 }
1862 }
1863 return err;
1864 }
1865
1866 mDNSlocal mStatus handle_removerecord_request(request_state *request)
1867 {
1868 mStatus err = mStatus_BadReferenceErr;
1869 get_flags(&request->msgptr, request->msgend); // flags unused
1870
1871 if (!request->msgptr)
1872 {
1873 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1874 "[R%d] DNSServiceRemoveRecord(unreadable parameters)", request->request_id);
1875 return(mStatus_BadParamErr);
1876 }
1877
1878 // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1879 if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1880
1881 if (request->terminate == connection_termination)
1882 err = remove_record(request); // remove individually registered record
1883 else if (request->terminate != regservice_termination_callback)
1884 {
1885 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
1886 "[R%d] DNSServiceRemoveRecord(not a registered service ref)", request->request_id);
1887 return(mStatus_BadParamErr);
1888 }
1889 else
1890 {
1891 service_instance *i;
1892 mDNSu16 rrtype = 0;
1893 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%d] DNSServiceRemoveRecord(" PRI_DM_NAME ", " PUB_S ") PID[%d](" PUB_S ")",
1894 request->request_id,
1895 DM_NAME_PARAM((request->u.servicereg.instances) ? (request->u.servicereg.instances->srs.RR_SRV.resrec.name) : mDNSNULL),
1896 rrtype ? DNSTypeName(rrtype) : "<NONE>", request->process_id, request->pid_name);
1897 for (i = request->u.servicereg.instances; i; i = i->next)
1898 {
1899 err = remove_extra(request, i, &rrtype);
1900 if (err && i->default_local) break;
1901 else err = mStatus_NoError; // suppress non-local default errors
1902 }
1903 }
1904
1905 return(err);
1906 }
1907
1908 // If there's a comma followed by another character,
1909 // FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character.
1910 // Otherwise, it returns a pointer to the final nul at the end of the string
1911 mDNSlocal char *FindFirstSubType(char *p)
1912 {
1913 while (*p)
1914 {
1915 if (p[0] == '\\' && p[1])
1916 {
1917 p += 2;
1918 }
1919 else if (p[0] == ',' && p[1])
1920 {
1921 *p++ = 0;
1922 return(p);
1923 }
1924 else
1925 {
1926 p++;
1927 }
1928 }
1929 return(p);
1930 }
1931
1932 // If there's a comma followed by another character,
1933 // FindNextSubType overwrites the comma with a nul and returns the pointer to the next character.
1934 // If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL
1935 // Otherwise, it returns a pointer to the final nul at the end of the string
1936 mDNSlocal char *FindNextSubType(char *p)
1937 {
1938 while (*p)
1939 {
1940 if (p[0] == '\\' && p[1]) // If escape character
1941 p += 2; // ignore following character
1942 else if (p[0] == ',') // If we found a comma
1943 {
1944 if (p[1]) *p++ = 0;
1945 return(p);
1946 }
1947 else if (p[0] == '.')
1948 return(mDNSNULL);
1949 else p++;
1950 }
1951 return(p);
1952 }
1953
1954 // Returns -1 if illegal subtype found
1955 mDNSlocal mDNSs32 ChopSubTypes(char *regtype)
1956 {
1957 mDNSs32 NumSubTypes = 0;
1958 char *stp = FindFirstSubType(regtype);
1959 while (stp && *stp) // If we found a comma...
1960 {
1961 if (*stp == ',') return(-1);
1962 NumSubTypes++;
1963 stp = FindNextSubType(stp);
1964 }
1965 if (!stp) return(-1);
1966 return(NumSubTypes);
1967 }
1968
1969 mDNSlocal AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p)
1970 {
1971 AuthRecord *st = mDNSNULL;
1972 if (NumSubTypes)
1973 {
1974 mDNSs32 i;
1975 st = (AuthRecord *) callocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord));
1976 if (!st) return(mDNSNULL);
1977 for (i = 0; i < NumSubTypes; i++)
1978 {
1979 mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
1980 while (*p) p++;
1981 p++;
1982 if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p))
1983 {
1984 freeL("ServiceSubTypes", st);
1985 return(mDNSNULL);
1986 }
1987 }
1988 }
1989 return(st);
1990 }
1991
1992 mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
1993 {
1994 service_instance **ptr, *instance;
1995 size_t extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
1996 const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
1997 mStatus result;
1998 mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID;
1999
2000 // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS)
2001 // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast
2002 // registrations scoped to a specific interface, so for the automatic domains we add we must *not* specify an interface.
2003 // (Specifying an interface with an apparently wide-area domain (i.e. something other than "local")
2004 // currently forces the registration to use mDNS multicast despite the apparently wide-area domain.)
2005 if (request->u.servicereg.default_domain && !DomainIsLocal) interfaceID = mDNSInterface_Any;
2006
2007 for (ptr = &request->u.servicereg.instances; *ptr; ptr = &(*ptr)->next)
2008 {
2009 if (SameDomainName(&(*ptr)->domain, domain))
2010 {
2011 LogMsg("register_service_instance: domain %##s already registered for %#s.%##s",
2012 domain->c, &request->u.servicereg.name, &request->u.servicereg.type);
2013 return mStatus_AlreadyRegistered;
2014 }
2015 }
2016
2017 instance = (service_instance *) callocL("service_instance", sizeof(*instance) + extra_size);
2018 if (!instance) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
2019
2020 instance->next = mDNSNULL;
2021 instance->request = request;
2022 instance->renameonmemfree = 0;
2023 instance->clientnotified = mDNSfalse;
2024 instance->default_local = (request->u.servicereg.default_domain && DomainIsLocal);
2025 instance->external_advertise = mDNSfalse;
2026 AssignDomainName(&instance->domain, domain);
2027
2028 instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
2029
2030 if (request->u.servicereg.num_subtypes && !instance->subtypes)
2031 {
2032 unlink_and_free_service_instance(instance);
2033 instance = NULL;
2034 FatalError("ERROR: malloc");
2035 }
2036
2037 result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
2038 &request->u.servicereg.name, &request->u.servicereg.type, domain,
2039 request->u.servicereg.host.c[0] ? &request->u.servicereg.host : NULL,
2040 request->u.servicereg.port,
2041 mDNSNULL, request->u.servicereg.txtdata, request->u.servicereg.txtlen,
2042 instance->subtypes, request->u.servicereg.num_subtypes,
2043 interfaceID, regservice_callback, instance, request->flags);
2044
2045 if (!result)
2046 {
2047 *ptr = instance; // Append this to the end of our request->u.servicereg.instances list
2048 LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd,
2049 instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port));
2050 LogMcastS(&instance->srs.RR_SRV, request, reg_start);
2051 }
2052 else
2053 {
2054 LogMsg("register_service_instance %#s.%##s%##s error %d",
2055 &request->u.servicereg.name, &request->u.servicereg.type, domain->c, result);
2056 unlink_and_free_service_instance(instance);
2057 }
2058
2059 return result;
2060 }
2061
2062 mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d, const mDNSBool add)
2063 {
2064 request_state *request;
2065
2066 LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c);
2067 for (request = all_requests; request; request = request->next)
2068 {
2069 if (request->terminate != regservice_termination_callback) continue;
2070 if (!request->u.servicereg.default_domain) continue;
2071 if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
2072 {
2073 service_instance **ptr = &request->u.servicereg.instances;
2074 while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
2075 if (add)
2076 {
2077 // If we don't already have this domain in our list for this registration, add it now
2078 if (!*ptr) register_service_instance(request, &d->name);
2079 else debugf("udsserver_default_reg_domain_changed %##s already in list, not re-adding", &d->name);
2080 }
2081 else
2082 {
2083 // Normally we should not fail to find the specified instance
2084 // One case where this can happen is if a uDNS update fails for some reason,
2085 // and regservice_callback then calls unlink_and_free_service_instance and disposes of that instance.
2086 if (!*ptr)
2087 LogMsg("udsserver_default_reg_domain_changed domain %##s not found for service %#s type %s",
2088 &d->name, request->u.servicereg.name.c, request->u.servicereg.type_as_string);
2089 else
2090 {
2091 DNameListElem *p;
2092 for (p = AutoRegistrationDomains; p; p=p->next)
2093 if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
2094 if (SameDomainName(&d->name, &p->name)) break;
2095 if (p) debugf("udsserver_default_reg_domain_changed %##s still in list, not removing", &d->name);
2096 else
2097 {
2098 mStatus err;
2099 service_instance *si = *ptr;
2100 *ptr = si->next;
2101 if (si->clientnotified) SendServiceRemovalNotification(&si->srs); // Do this *before* clearing si->request backpointer
2102 // Now that we've cut this service_instance from the list, we MUST clear the si->request backpointer.
2103 // Otherwise what can happen is this: While our mDNS_DeregisterService is in the
2104 // process of completing asynchronously, the client cancels the entire operation, so
2105 // regservice_termination_callback then runs through the whole list deregistering each
2106 // instance, clearing the backpointers, and then disposing the parent request_state object.
2107 // However, because this service_instance isn't in the list any more, regservice_termination_callback
2108 // has no way to find it and clear its backpointer, and then when our mDNS_DeregisterService finally
2109 // completes later with a mStatus_MemFree message, it calls unlink_and_free_service_instance() with
2110 // a service_instance with a stale si->request backpointer pointing to memory that's already been freed.
2111 si->request = NULL;
2112 err = mDNS_DeregisterService(&mDNSStorage, &si->srs);
2113 if (err) { LogMsg("udsserver_default_reg_domain_changed err %d", err); unlink_and_free_service_instance(si); }
2114 }
2115 }
2116 }
2117 }
2118 }
2119 }
2120
2121 // Returns true if the interfaceIndex value matches one of the pre-defined
2122 // special values listed in the switch statement below.
2123 mDNSlocal mDNSBool PreDefinedInterfaceIndex(mDNSu32 interfaceIndex)
2124 {
2125 switch(interfaceIndex)
2126 {
2127 case kDNSServiceInterfaceIndexAny:
2128 case kDNSServiceInterfaceIndexLocalOnly:
2129 case kDNSServiceInterfaceIndexUnicast:
2130 case kDNSServiceInterfaceIndexP2P:
2131 case kDNSServiceInterfaceIndexBLE:
2132 return mDNStrue;
2133 default:
2134 return mDNSfalse;
2135 }
2136 }
2137
2138 mDNSlocal mStatus _handle_regservice_request_start(request_state *request, const domainname * const d)
2139 {
2140 mStatus err;
2141
2142 request->terminate = regservice_termination_callback;
2143 err = register_service_instance(request, d);
2144
2145 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
2146 ++curr_num_regservices;
2147 if (curr_num_regservices > max_num_regservices)
2148 max_num_regservices = curr_num_regservices;
2149 #endif
2150
2151 #if 0
2152 err = AuthorizedDomain(request, d, AutoRegistrationDomains) ? register_service_instance(request, d) : mStatus_NoError;
2153 #endif
2154 if (!err)
2155 {
2156 if (request->u.servicereg.autoname) UpdateDeviceInfoRecord(&mDNSStorage);
2157
2158 if (request->u.servicereg.default_domain)
2159 {
2160 DNameListElem *ptr;
2161 // Note that we don't report errors for non-local, non-explicit domains
2162 for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
2163 if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
2164 register_service_instance(request, &ptr->name);
2165 }
2166 }
2167 return err;
2168 }
2169
2170 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2171
2172 mDNSlocal void _return_regservice_request_error(request_state *request, mStatus error)
2173 {
2174 if (request->u.servicereg.txtdata)
2175 {
2176 freeL("service_info txtdata", request->u.servicereg.txtdata);
2177 request->u.servicereg.txtdata = NULL;
2178 }
2179
2180 reply_state *rep;
2181 if (GenerateNTDResponse(NULL, 0, request, &rep, reg_service_reply_op, 0, error) != mStatus_NoError)
2182 {
2183 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegister _return_regservice_request_error: error(%d)", request->request_id, error);
2184 }
2185 else
2186 {
2187 append_reply(request, rep);
2188 }
2189 }
2190
2191 mDNSlocal mStatus _handle_regservice_request_with_trust(request_state *request, const domainname * const d)
2192 {
2193 mStatus err;
2194 if (audit_token_to_pid(request->audit_token) == 0)
2195 {
2196 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);
2197 err = _handle_regservice_request_start(request, d);
2198 }
2199 else
2200 {
2201 mdns_trust_flags_t flags = mdns_trust_flags_none;
2202 mdns_trust_status_t status = mdns_trust_check_register_service(request->audit_token, request->u.servicereg.type_as_string, &flags);
2203 switch (status) {
2204 case mdns_trust_status_denied:
2205 case mdns_trust_status_pending:
2206 {
2207 mdns_trust_t trust = mdns_trust_create(request->audit_token, request->u.servicereg.type_as_string, flags);
2208 if (!trust)
2209 {
2210 err = mStatus_NoMemoryErr;
2211 goto exit;
2212 }
2213 void * context = mallocL("context/_handle_regservice_request_with_trust", sizeof(domainname));
2214 if (!context)
2215 {
2216 my_perror("ERROR: mallocL context/_handle_regservice_request_with_trust");
2217 mdns_release(trust);
2218 err = mStatus_NoMemoryErr;
2219 goto exit;
2220 }
2221 memcpy(context, d, sizeof(domainname));
2222 mdns_trust_set_context(trust, context);
2223
2224 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
2225 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
2226 {
2227 if (event == mdns_trust_event_result)
2228 {
2229 mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
2230 KQueueLock();
2231 const domainname * _d = mdns_trust_get_context(trust);
2232 if (_d)
2233 {
2234 if (!error)
2235 {
2236 error = _handle_regservice_request_start(request, _d);
2237 // No context means the request was canceled before we got here
2238 }
2239 if (error) // (not else if) Always check for error result
2240 {
2241 _return_regservice_request_error(request, error);
2242 }
2243 }
2244 KQueueUnlock("_register_service_instance_with_trust");
2245 }
2246 });
2247 request->trust = trust;
2248 mdns_trust_activate(trust);
2249 err = mStatus_NoError;
2250 break;
2251 }
2252
2253 case mdns_trust_status_no_entitlement:
2254 err = mStatus_NoAuth;
2255 break;
2256
2257 case mdns_trust_status_granted:
2258 err = _handle_regservice_request_start(request, d);
2259 break;
2260
2261 default:
2262 err = mStatus_UnknownErr;
2263 break;
2264 }
2265 }
2266 exit:
2267 return err;
2268 }
2269 #endif // TRUST_ENFORCEMENT
2270
2271 mDNSlocal mStatus handle_regservice_request(request_state *request)
2272 {
2273 char name[256]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes
2274 char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
2275 char type_as_string[MAX_ESCAPED_DOMAIN_NAME]; // Note that this service type may include a trailing list of subtypes
2276 domainname d, srv;
2277 mStatus err;
2278 const char *msgTXTData;
2279
2280 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
2281 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
2282 mDNSInterfaceID InterfaceID;
2283
2284 // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the
2285 // kDNSServiceFlagsIncludeP2P flag set.
2286 if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
2287 {
2288 LogOperation("handle_regservice_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
2289 flags |= kDNSServiceFlagsIncludeP2P;
2290 interfaceIndex = kDNSServiceInterfaceIndexAny;
2291 }
2292
2293 InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
2294
2295 // The registration is scoped to a specific interface index, but the
2296 // interface is not currently in our list.
2297 if (interfaceIndex && !InterfaceID)
2298 {
2299 // If it's one of the specially defined inteface index values, just return an error.
2300 if (PreDefinedInterfaceIndex(interfaceIndex))
2301 {
2302 LogInfo("handle_regservice_request: bad interfaceIndex %d", interfaceIndex);
2303 return(mStatus_BadParamErr);
2304 }
2305
2306 // Otherwise, use the specified interface index value and the registration will
2307 // be applied to that interface when it comes up.
2308 InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
2309 LogInfo("handle_regservice_request: registration pending for interface index %d", interfaceIndex);
2310 }
2311
2312 if (get_string(&request->msgptr, request->msgend, name, sizeof(name )) < 0 ||
2313 get_string(&request->msgptr, request->msgend, type_as_string, sizeof(type_as_string)) < 0 ||
2314 get_string(&request->msgptr, request->msgend, domain, sizeof(domain )) < 0 ||
2315 get_string(&request->msgptr, request->msgend, host, sizeof(host )) < 0)
2316 { LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
2317
2318 request->flags = flags;
2319 request->interfaceIndex = interfaceIndex;
2320 request->u.servicereg.InterfaceID = InterfaceID;
2321 request->u.servicereg.instances = NULL;
2322 request->u.servicereg.txtlen = 0;
2323 request->u.servicereg.txtdata = NULL;
2324 mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string));
2325
2326 if (request->msgptr + 2 > request->msgend) request->msgptr = NULL;
2327 else
2328 {
2329 request->u.servicereg.port.b[0] = *request->msgptr++;
2330 request->u.servicereg.port.b[1] = *request->msgptr++;
2331 }
2332
2333 request->u.servicereg.txtlen = get_uint16(&request->msgptr, request->msgend);
2334 msgTXTData = get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen);
2335
2336 if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
2337
2338 if (request->u.servicereg.txtlen)
2339 {
2340 request->u.servicereg.txtdata = mallocL("service_info txtdata", request->u.servicereg.txtlen);
2341 if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_regservice_request - malloc");
2342 mDNSPlatformMemCopy(request->u.servicereg.txtdata, msgTXTData, request->u.servicereg.txtlen);
2343 }
2344
2345 // Check for sub-types after the service type
2346 request->u.servicereg.num_subtypes = ChopSubTypes(request->u.servicereg.type_as_string); // Note: Modifies regtype string to remove trailing subtypes
2347 if (request->u.servicereg.num_subtypes < 0)
2348 {
2349 LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", request->u.servicereg.type_as_string);
2350 goto bad_param;
2351 }
2352
2353 // Don't try to construct "domainname t" until *after* ChopSubTypes has worked its magic
2354 if (!*request->u.servicereg.type_as_string || !MakeDomainNameFromDNSNameString(&request->u.servicereg.type, request->u.servicereg.type_as_string))
2355 { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", request->u.servicereg.type_as_string); goto bad_param; }
2356
2357 if (!name[0])
2358 {
2359 request->u.servicereg.name = mDNSStorage.nicelabel;
2360 request->u.servicereg.autoname = mDNStrue;
2361 }
2362 else
2363 {
2364 // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
2365 if ((flags & kDNSServiceFlagsNoAutoRename) == 0)
2366 {
2367 int newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL);
2368 name[newlen] = 0;
2369 }
2370 if (!MakeDomainLabelFromLiteralString(&request->u.servicereg.name, name))
2371 { LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; }
2372 request->u.servicereg.autoname = mDNSfalse;
2373 }
2374
2375 if (*domain)
2376 {
2377 request->u.servicereg.default_domain = mDNSfalse;
2378 if (!MakeDomainNameFromDNSNameString(&d, domain))
2379 { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); goto bad_param; }
2380 }
2381 else
2382 {
2383 request->u.servicereg.default_domain = mDNStrue;
2384 MakeDomainNameFromDNSNameString(&d, "local.");
2385 }
2386
2387 if (!ConstructServiceName(&srv, &request->u.servicereg.name, &request->u.servicereg.type, &d))
2388 {
2389 LogMsg("ERROR: handle_regservice_request - Couldn't ConstructServiceName from, “%#s” “%##s” “%##s”",
2390 request->u.servicereg.name.c, request->u.servicereg.type.c, d.c); goto bad_param;
2391 }
2392
2393 if (!MakeDomainNameFromDNSNameString(&request->u.servicereg.host, host))
2394 { LogMsg("ERROR: handle_regservice_request - host bad %s", host); goto bad_param; }
2395 request->u.servicereg.autorename = (flags & kDNSServiceFlagsNoAutoRename ) == 0;
2396 request->u.servicereg.allowremotequery = (flags & kDNSServiceFlagsAllowRemoteQuery) != 0;
2397
2398 // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with
2399 // a port number of zero. When two instances of the protected client are allowed to run on one
2400 // machine, we don't want to see misleading "Bogus client" messages in syslog and the console.
2401 if (!mDNSIPPortIsZero(request->u.servicereg.port))
2402 {
2403 int count = CountExistingRegistrations(&srv, request->u.servicereg.port);
2404 if (count)
2405 LogMsg("Client application[%d](%s) registered %d identical instances of service %##s port %u.", request->process_id,
2406 request->pid_name, count+1, srv.c, mDNSVal16(request->u.servicereg.port));
2407 }
2408
2409 #if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
2410 // Determine if this request should be promoted to use BLE triggered feature.
2411 if (shouldUseBLE(InterfaceID, 0, &request->u.servicereg.type, &d))
2412 {
2413 request->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL);
2414 LogInfo("handle_regservice_request: registration promoted to use kDNSServiceFlagsAutoTrigger");
2415 }
2416 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
2417
2418 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
2419 "[R%d] DNSServiceRegister(%X, %d, \"" PRI_S "\", \"" PRI_S "\", \"" PRI_S "\", \"" PRI_S "\", %u) START PID[%d](" PUB_S ")",
2420 request->request_id, request->flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host,
2421 mDNSVal16(request->u.servicereg.port), request->process_id, request->pid_name);
2422
2423 // We need to unconditionally set request->terminate, because even if we didn't successfully
2424 // start any registrations right now, subsequent configuration changes may cause successful
2425 // registrations to be added, and we'll need to cancel them before freeing this memory.
2426 // We also need to set request->terminate first, before adding additional service instances,
2427 // because the udsserver_validatelists uses the request->terminate function pointer to determine
2428 // what kind of request this is, and therefore what kind of list validation is required.
2429 request->terminate = NULL;
2430
2431 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2432 if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
2433 (request->u.servicereg.default_domain || IsLocalDomain(&d)))
2434 {
2435 err = _handle_regservice_request_with_trust(request, &d);
2436 if (err == mStatus_NoAuth && request->u.servicereg.txtdata)
2437 {
2438 freeL("service_info txtdata", request->u.servicereg.txtdata);
2439 request->u.servicereg.txtdata = NULL;
2440 }
2441 }
2442 else
2443 {
2444 err = _handle_regservice_request_start(request, &d);
2445 }
2446 #else
2447 err = _handle_regservice_request_start(request, &d);
2448 #endif
2449
2450 return(err);
2451
2452 bad_param:
2453 freeL("handle_regservice_request (txtdata)", request->u.servicereg.txtdata);
2454 request->u.servicereg.txtdata = NULL;
2455 return mStatus_BadParamErr;
2456 }
2457
2458 // ***************************************************************************
2459 #if COMPILER_LIKES_PRAGMA_MARK
2460 #pragma mark -
2461 #pragma mark - DNSServiceBrowse
2462 #endif
2463
2464 mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2465 {
2466 DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : 0;
2467 request_state *req = question->QuestionContext;
2468 reply_state *rep;
2469 (void)m; // Unused
2470
2471 if (answer->rrtype != kDNSType_PTR)
2472 { LogMsg("%3d: FoundInstance: Should not be called with rrtype %d (not a PTR record)", req->sd, answer->rrtype); return; }
2473
2474 if (mDNSOpaque16IsZero(question->TargetQID) && (question->BrowseThreshold > 0) && (question->CurrentAnswers >= question->BrowseThreshold))
2475 {
2476 flags |= kDNSServiceFlagsThresholdReached;
2477 }
2478
2479 // if returning a negative answer, then use question's name in reply
2480 if (answer->RecordType == kDNSRecordTypePacketNegative)
2481 {
2482 GenerateBrowseReply(&question->qname, answer->InterfaceID, req, &rep, browse_reply_op, flags, kDNSServiceErr_NoSuchRecord);
2483 goto validReply;
2484 }
2485
2486 if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
2487 {
2488 if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
2489 {
2490 // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
2491 // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
2492 GenerateBrowseReply(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
2493 goto validReply;
2494 }
2495
2496 LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
2497 req->sd, answer->name->c, answer->rdata->u.name.c);
2498 return;
2499 }
2500
2501 validReply:
2502
2503 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
2504 "[R%d->Q%d] DNSServiceBrowse(" PRI_DM_NAME ", " PUB_S ") RESULT " PUB_S " interface %d: " PRI_S,
2505 req->request_id, mDNSVal16(question->TargetQID), DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype),
2506 AddRecord ? "ADD" : "RMV", mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse),
2507 RRDisplayString(m, answer));
2508
2509 append_reply(req, rep);
2510 }
2511
2512 mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req)
2513 {
2514 q->euid = req->uid;
2515 // The policy is either based on pid or UUID. Pass a zero pid
2516 // to the "core" if the UUID is valid. If we always pass the pid,
2517 // then the "core" needs to determine whether the uuid is valid
2518 // by examining all the 16 bytes at the time of the policy
2519 // check and also when setting the delegate socket option. Also, it
2520 // requires that we zero out the uuid wherever the question is
2521 // initialized to make sure that it is not interpreted as valid.
2522 // To prevent these intrusive changes, just pass a zero pid to indicate
2523 // that pid is not valid when uuid is valid. In future if we need the
2524 // pid in the question, we will reevaluate this strategy.
2525 if (req->validUUID)
2526 {
2527 mDNSPlatformMemCopy(q->uuid, req->uuid, UUID_SIZE);
2528 q->pid = 0;
2529 }
2530 else
2531 {
2532 q->pid = req->process_id;
2533 }
2534
2535 //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
2536 }
2537
2538 mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d)
2539 {
2540 browser_t *b, *p;
2541 mStatus err;
2542
2543 for (p = info->u.browser.browsers; p; p = p->next)
2544 {
2545 if (SameDomainName(&p->domain, d))
2546 { debugf("add_domain_to_browser %##s already in list", d->c); return mStatus_AlreadyRegistered; }
2547 }
2548
2549 b = (browser_t *) callocL("browser_t", sizeof(*b));
2550 if (!b) return mStatus_NoMemoryErr;
2551 AssignDomainName(&b->domain, d);
2552 SetQuestionPolicy(&b->q, info);
2553 err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.interface_id, info->flags,
2554 info->u.browser.ForceMCast, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, info);
2555 if (err)
2556 {
2557 LogMsg("mDNS_StartBrowse returned %d for type %##s domain %##s", err, info->u.browser.regtype.c, d->c);
2558 freeL("browser_t/add_domain_to_browser", b);
2559 }
2560 else
2561 {
2562 b->next = info->u.browser.browsers;
2563 info->u.browser.browsers = b;
2564
2565 #if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
2566 // Determine if this request should be promoted to use BLE triggered discovery.
2567 if (shouldUseBLE(info->u.browser.interface_id, 0, &info->u.browser.regtype, (domainname *) d))
2568 {
2569 info->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL);
2570 b->q.flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL);
2571 LogInfo("add_domain_to_browser: request promoted to use kDNSServiceFlagsAutoTrigger");
2572 }
2573 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
2574
2575 LogMcastQ(&b->q, info, q_start);
2576 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
2577 if (callExternalHelpers(info->u.browser.interface_id, &b->domain, info->flags))
2578 {
2579 domainname tmp;
2580 ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &b->domain);
2581 LogDebug("add_domain_to_browser: calling external_start_browsing_for_service()");
2582 external_start_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags, info->process_id);
2583 }
2584 #endif
2585 }
2586 return err;
2587 }
2588
2589 mDNSlocal void browse_termination_callback(request_state *info)
2590 {
2591 if (info->u.browser.default_domain)
2592 {
2593 // Stop the domain enumeration queries to discover the WAB legacy browse domains
2594 LogInfo("%3d: DNSServiceBrowse Cancel WAB PID[%d](%s)", info->sd, info->process_id, info->pid_name);
2595 uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
2596 }
2597 while (info->u.browser.browsers)
2598 {
2599 browser_t *ptr = info->u.browser.browsers;
2600
2601 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
2602 if (callExternalHelpers(ptr->q.InterfaceID, &ptr->domain, ptr->q.flags))
2603 {
2604 domainname tmp;
2605 ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain);
2606 LogInfo("browse_termination_callback: calling external_stop_browsing_for_service()");
2607 external_stop_browsing_for_service(ptr->q.InterfaceID, &tmp, kDNSType_PTR, ptr->q.flags, info->process_id);
2608 }
2609 #endif
2610 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
2611 "[R%d] DNSServiceBrowse(%X, %d, \"" PRI_DM_NAME "\") STOP PID[%d](" PUB_S ")",
2612 info->request_id, info->flags, info->interfaceIndex, DM_NAME_PARAM(&ptr->q.qname),
2613 info->process_id, info->pid_name);
2614
2615 info->u.browser.browsers = ptr->next;
2616 mDNS_StopBrowse(&mDNSStorage, &ptr->q); // no need to error-check result
2617 LogMcastQ(&ptr->q, info, q_stop);
2618 freeL("browser_t/browse_termination_callback", ptr);
2619 }
2620 }
2621
2622 mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *const d, const mDNSBool add)
2623 {
2624 request_state *request;
2625 debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c);
2626
2627 for (request = all_requests; request; request = request->next)
2628 {
2629 if (request->terminate != browse_termination_callback) continue; // Not a browse operation
2630 if (!request->u.browser.default_domain) continue; // Not an auto-browse operation
2631 if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
2632 {
2633 browser_t **ptr = &request->u.browser.browsers;
2634 while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
2635 if (add)
2636 {
2637 // If we don't already have this domain in our list for this browse operation, add it now
2638 if (!*ptr) add_domain_to_browser(request, &d->name);
2639 else debugf("udsserver_automatic_browse_domain_changed %##s already in list, not re-adding", &d->name);
2640 }
2641 else
2642 {
2643 if (!*ptr) LogMsg("udsserver_automatic_browse_domain_changed ERROR %##s not found", &d->name);
2644 else
2645 {
2646 DNameListElem *p;
2647 for (p = AutoBrowseDomains; p; p=p->next)
2648 if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
2649 if (SameDomainName(&d->name, &p->name)) break;
2650 if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
2651 else
2652 {
2653 browser_t *rem = *ptr;
2654 *ptr = (*ptr)->next;
2655 mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
2656 freeL("browser_t/udsserver_automatic_browse_domain_changed", rem);
2657 }
2658 }
2659 }
2660 }
2661 }
2662 }
2663
2664 mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
2665 {
2666 (void)m; // unused
2667 if (result == mStatus_MemFree)
2668 {
2669 // On shutdown, mDNS_Close automatically deregisters all records
2670 // Since in this case no one has called DeregisterLocalOnlyDomainEnumPTR to cut the record
2671 // from the LocalDomainEnumRecords list, we do this here before we free the memory.
2672 // (This should actually no longer be necessary, now that we do the proper cleanup in
2673 // udsserver_exit. To confirm this, we'll log an error message if we do find a record that
2674 // hasn't been cut from the list yet. If these messages don't appear, we can delete this code.)
2675 ARListElem **ptr = &LocalDomainEnumRecords;
2676 while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
2677 if (*ptr) { *ptr = (*ptr)->next; LogMsg("FreeARElemCallback: Have to cut %s", ARDisplayString(m, rr)); }
2678 mDNSPlatformMemFree(rr->RecordContext);
2679 }
2680 }
2681
2682 // RegisterLocalOnlyDomainEnumPTR and DeregisterLocalOnlyDomainEnumPTR largely duplicate code in
2683 // "FoundDomain" in uDNS.c for creating and destroying these special mDNSInterface_LocalOnly records.
2684 // We may want to turn the common code into a subroutine.
2685
2686 mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
2687 {
2688 // allocate/register legacy and non-legacy _browse PTR record
2689 mStatus err;
2690 ARListElem *ptr = (ARListElem *) mDNSPlatformMemAllocateClear(sizeof(*ptr));
2691
2692 debugf("Incrementing %s refcount for %##s",
2693 (type == mDNS_DomainTypeBrowse ) ? "browse domain " :
2694 (type == mDNS_DomainTypeRegistration ) ? "registration dom" :
2695 (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
2696
2697 mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, ptr);
2698 MakeDomainNameFromDNSNameString(&ptr->ar.namestorage, mDNS_DomainTypeNames[type]);
2699 AppendDNSNameString (&ptr->ar.namestorage, "local");
2700 AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
2701 err = mDNS_Register(m, &ptr->ar);
2702 if (err)
2703 {
2704 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
2705 mDNSPlatformMemFree(ptr);
2706 }
2707 else
2708 {
2709 ptr->next = LocalDomainEnumRecords;
2710 LocalDomainEnumRecords = ptr;
2711 }
2712 }
2713
2714 mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
2715 {
2716 ARListElem **ptr = &LocalDomainEnumRecords;
2717 domainname lhs; // left-hand side of PTR, for comparison
2718
2719 debugf("Decrementing %s refcount for %##s",
2720 (type == mDNS_DomainTypeBrowse ) ? "browse domain " :
2721 (type == mDNS_DomainTypeRegistration ) ? "registration dom" :
2722 (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
2723
2724 MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
2725 AppendDNSNameString (&lhs, "local");
2726
2727 while (*ptr)
2728 {
2729 if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
2730 {
2731 ARListElem *rem = *ptr;
2732 *ptr = (*ptr)->next;
2733 mDNS_Deregister(m, &rem->ar);
2734 return;
2735 }
2736 else ptr = &(*ptr)->next;
2737 }
2738 }
2739
2740 mDNSlocal void AddAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
2741 {
2742 DNameListElem *new = (DNameListElem *) mDNSPlatformMemAllocateClear(sizeof(*new));
2743 if (!new) { LogMsg("ERROR: malloc"); return; }
2744 AssignDomainName(&new->name, name);
2745 new->uid = uid;
2746 new->next = AutoBrowseDomains;
2747 AutoBrowseDomains = new;
2748 udsserver_automatic_browse_domain_changed(new, mDNStrue);
2749 }
2750
2751 mDNSlocal void RmvAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
2752 {
2753 DNameListElem **p = &AutoBrowseDomains;
2754 while (*p && (!SameDomainName(&(*p)->name, name) || (*p)->uid != uid)) p = &(*p)->next;
2755 if (!*p) LogMsg("RmvAutoBrowseDomain: Got remove event for domain %##s not in list", name->c);
2756 else
2757 {
2758 DNameListElem *ptr = *p;
2759 *p = ptr->next;
2760 udsserver_automatic_browse_domain_changed(ptr, mDNSfalse);
2761 mDNSPlatformMemFree(ptr);
2762 }
2763 }
2764
2765 mDNSlocal void SetPrefsBrowseDomains(mDNS *m, DNameListElem *browseDomains, mDNSBool add)
2766 {
2767 DNameListElem *d;
2768 for (d = browseDomains; d; d = d->next)
2769 {
2770 if (add)
2771 {
2772 RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
2773 AddAutoBrowseDomain(d->uid, &d->name);
2774 }
2775 else
2776 {
2777 DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
2778 RmvAutoBrowseDomain(d->uid, &d->name);
2779 }
2780 }
2781 }
2782
2783 #if APPLE_OSX_mDNSResponder
2784
2785 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
2786 {
2787 int num_autoname = 0;
2788 request_state *req;
2789
2790 // Don't need to register the device info record for kDNSServiceInterfaceIndexLocalOnly registrations.
2791 for (req = all_requests; req; req = req->next)
2792 {
2793 if (req->terminate == regservice_termination_callback && req->u.servicereg.autoname && req->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly)
2794 num_autoname++;
2795 }
2796
2797 // If DeviceInfo record is currently registered, see if we need to deregister it
2798 if (m->DeviceInfo.resrec.RecordType != kDNSRecordTypeUnregistered)
2799 if (num_autoname == 0 || !SameDomainLabelCS(m->DeviceInfo.resrec.name->c, m->nicelabel.c))
2800 {
2801 LogOperation("UpdateDeviceInfoRecord Deregister %##s", m->DeviceInfo.resrec.name);
2802 mDNS_Deregister(m, &m->DeviceInfo);
2803 }
2804
2805 // If DeviceInfo record is not currently registered, see if we need to register it
2806 if (m->DeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
2807 if (num_autoname > 0)
2808 {
2809 mDNS_SetupResourceRecord(&m->DeviceInfo, mDNSNULL, mDNSNULL, kDNSType_TXT, kStandardTTL, kDNSRecordTypeAdvisory, AuthRecordAny, mDNSNULL, mDNSNULL);
2810 ConstructServiceName(&m->DeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &localdomain);
2811 m->DeviceInfo.resrec.rdlength = initializeDeviceInfoTXT(m, m->DeviceInfo.resrec.rdata->u.data);
2812 LogOperation("UpdateDeviceInfoRecord Register %##s", m->DeviceInfo.resrec.name);
2813 mDNS_Register(m, &m->DeviceInfo);
2814 }
2815 }
2816 #else // APPLE_OSX_mDNSResponder
2817 mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
2818 {
2819 (void)m; // unused
2820 }
2821 #endif // APPLE_OSX_mDNSResponder
2822
2823 mDNSexport void udsserver_handle_configchange(mDNS *const m)
2824 {
2825 request_state *req;
2826 service_instance *ptr;
2827 DNameListElem *RegDomains = NULL;
2828 DNameListElem *BrowseDomains = NULL;
2829 DNameListElem *p;
2830
2831 UpdateDeviceInfoRecord(m);
2832
2833 // For autoname services, see if the default service name has changed, necessitating an automatic update
2834 for (req = all_requests; req; req = req->next)
2835 if (req->terminate == regservice_termination_callback)
2836 if (req->u.servicereg.autoname && !SameDomainLabelCS(req->u.servicereg.name.c, m->nicelabel.c))
2837 {
2838 req->u.servicereg.name = m->nicelabel;
2839 for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
2840 {
2841 ptr->renameonmemfree = 1;
2842 if (ptr->clientnotified) SendServiceRemovalNotification(&ptr->srs);
2843 LogInfo("udsserver_handle_configchange: Calling deregister for Service %##s", ptr->srs.RR_PTR.resrec.name->c);
2844 if (mDNS_DeregisterService_drt(m, &ptr->srs, mDNS_Dereg_rapid))
2845 regservice_callback(m, &ptr->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
2846 }
2847 }
2848
2849 // Let the platform layer get the current DNS information
2850 mDNS_Lock(m);
2851 mDNSPlatformSetDNSConfig(mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains, mDNSfalse);
2852 mDNS_Unlock(m);
2853
2854 // Any automatic registration domains are also implicitly automatic browsing domains
2855 if (RegDomains) SetPrefsBrowseDomains(m, RegDomains, mDNStrue); // Add the new list first
2856 if (AutoRegistrationDomains) SetPrefsBrowseDomains(m, AutoRegistrationDomains, mDNSfalse); // Then clear the old list
2857
2858 // Add any new domains not already in our AutoRegistrationDomains list
2859 for (p=RegDomains; p; p=p->next)
2860 {
2861 DNameListElem **pp = &AutoRegistrationDomains;
2862 while (*pp && ((*pp)->uid != p->uid || !SameDomainName(&(*pp)->name, &p->name))) pp = &(*pp)->next;
2863 if (!*pp) // If not found in our existing list, this is a new default registration domain
2864 {
2865 RegisterLocalOnlyDomainEnumPTR(m, &p->name, mDNS_DomainTypeRegistration);
2866 udsserver_default_reg_domain_changed(p, mDNStrue);
2867 }
2868 else // else found same domainname in both old and new lists, so no change, just delete old copy
2869 {
2870 DNameListElem *del = *pp;
2871 *pp = (*pp)->next;
2872 mDNSPlatformMemFree(del);
2873 }
2874 }
2875
2876 // Delete any domains in our old AutoRegistrationDomains list that are now gone
2877 while (AutoRegistrationDomains)
2878 {
2879 DNameListElem *del = AutoRegistrationDomains;
2880 AutoRegistrationDomains = AutoRegistrationDomains->next; // Cut record from list FIRST,
2881 DeregisterLocalOnlyDomainEnumPTR(m, &del->name, mDNS_DomainTypeRegistration);
2882 udsserver_default_reg_domain_changed(del, mDNSfalse); // before calling udsserver_default_reg_domain_changed()
2883 mDNSPlatformMemFree(del);
2884 }
2885
2886 // Now we have our new updated automatic registration domain list
2887 AutoRegistrationDomains = RegDomains;
2888
2889 // Add new browse domains to internal list
2890 if (BrowseDomains) SetPrefsBrowseDomains(m, BrowseDomains, mDNStrue);
2891
2892 // Remove old browse domains from internal list
2893 if (SCPrefBrowseDomains)
2894 {
2895 SetPrefsBrowseDomains(m, SCPrefBrowseDomains, mDNSfalse);
2896 while (SCPrefBrowseDomains)
2897 {
2898 DNameListElem *fptr = SCPrefBrowseDomains;
2899 SCPrefBrowseDomains = SCPrefBrowseDomains->next;
2900 mDNSPlatformMemFree(fptr);
2901 }
2902 }
2903
2904 // Replace the old browse domains array with the new array
2905 SCPrefBrowseDomains = BrowseDomains;
2906 }
2907
2908 mDNSlocal void AutomaticBrowseDomainChange(mDNS *const m, DNSQuestion *q, const ResourceRecord *const answer, QC_result AddRecord)
2909 {
2910 (void)m; // unused;
2911 (void)q; // unused
2912
2913 LogOperation("AutomaticBrowseDomainChange: %s automatic browse domain %##s",
2914 AddRecord ? "Adding" : "Removing", answer->rdata->u.name.c);
2915
2916 if (AddRecord) AddAutoBrowseDomain(0, &answer->rdata->u.name);
2917 else RmvAutoBrowseDomain(0, &answer->rdata->u.name);
2918 }
2919
2920 mDNSlocal mStatus _handle_browse_request_start(request_state *request, const char * domain)
2921 {
2922 domainname d;
2923 mStatus err = mStatus_NoError;
2924
2925 request->terminate = browse_termination_callback;
2926
2927 if (domain[0])
2928 {
2929 if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
2930 err = add_domain_to_browser(request, &d);
2931 }
2932 else
2933 {
2934 DNameListElem *sdom;
2935 for (sdom = AutoBrowseDomains; sdom; sdom = sdom->next)
2936 if (!sdom->uid || SystemUID(request->uid) || request->uid == sdom->uid)
2937 {
2938 err = add_domain_to_browser(request, &sdom->name);
2939 if (err)
2940 {
2941 if (SameDomainName(&sdom->name, &localdomain)) break;
2942 else err = mStatus_NoError; // suppress errors for non-local "default" domains
2943 }
2944 }
2945 }
2946
2947 return(err);
2948 }
2949
2950 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2951
2952 mDNSlocal void _return_browse_request_error(request_state *request, mStatus error)
2953 {
2954 reply_state *rep;
2955
2956 GenerateBrowseReply(NULL, 0, request, &rep, browse_reply_op, 0, error);
2957
2958 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
2959 "[R%d] DNSServiceBrowse _return_browse_request_error: error (%d)", request->request_id, error);
2960
2961 append_reply(request, rep);
2962 }
2963
2964 mDNSlocal mStatus _handle_browse_request_with_trust(request_state *request, const char * domain)
2965 {
2966 mStatus err;
2967 if (audit_token_to_pid(request->audit_token) == 0)
2968 {
2969 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, 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);
2970 err = _handle_browse_request_start(request, domain);
2971 }
2972 else
2973 {
2974 char typestr[MAX_ESCAPED_DOMAIN_NAME];
2975 typestr[0] = 0;
2976 (void)ConvertDomainNameToCString(&request->u.browser.regtype, typestr);
2977 mdns_trust_flags_t flags = mdns_trust_flags_none;
2978 mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, typestr, &flags);
2979 switch (status)
2980 {
2981 case mdns_trust_status_denied:
2982 case mdns_trust_status_pending:
2983 {
2984 mdns_trust_t trust = mdns_trust_create(request->audit_token, typestr, flags);
2985 if (!trust )
2986 {
2987 err = mStatus_NoMemoryErr;
2988 goto exit;
2989 }
2990
2991 size_t len = strlen(domain) + 1;
2992 void * context = mallocL("context/_handle_browse_request_with_trust", len);
2993 if (!context)
2994 {
2995 my_perror("ERROR: mallocL context/_handle_browse_request_with_trust");
2996 mdns_release(trust);
2997 err = mStatus_NoMemoryErr;
2998 goto exit;
2999 }
3000 memcpy(context, domain, len);
3001 mdns_trust_set_context(trust, context);
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 char * _domain = mdns_trust_get_context(trust);
3011 if (_domain)
3012 {
3013 if (!error)
3014 {
3015 error = _handle_browse_request_start(request, _domain);
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_browse_request_error(request, error);
3021 }
3022 }
3023 KQueueUnlock("_handle_browse_request_with_trust");
3024 }
3025 });
3026 request->trust = trust;
3027 mdns_trust_activate(trust);
3028 err = mStatus_NoError;
3029 break;
3030 }
3031
3032 case mdns_trust_status_no_entitlement:
3033 err = mStatus_NoAuth;
3034 break;
3035
3036 case mdns_trust_status_granted:
3037 err = _handle_browse_request_start(request, domain);
3038 break;
3039
3040 default:
3041 err = mStatus_UnknownErr;
3042 break;
3043 }
3044 }
3045 exit:
3046 return err;
3047 }
3048 #endif // TRUST_ENFORCEMENT
3049
3050 mDNSlocal mStatus handle_browse_request(request_state *request)
3051 {
3052 // Note that regtype may include a trailing subtype
3053 char regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
3054 domainname typedn, temp;
3055 mDNSs32 NumSubTypes;
3056 mStatus err = mStatus_NoError;
3057
3058 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3059 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3060 mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3061
3062 // The browse is scoped to a specific interface index, but the
3063 // interface is not currently in our list.
3064 if (interfaceIndex && !InterfaceID)
3065 {
3066 // If it's one of the specially defined inteface index values, just return an error.
3067 if (PreDefinedInterfaceIndex(interfaceIndex))
3068 {
3069 LogInfo("handle_browse_request: bad interfaceIndex %d", interfaceIndex);
3070 return(mStatus_BadParamErr);
3071 }
3072
3073 // Otherwise, use the specified interface index value and the browse will
3074 // be applied to that interface when it comes up.
3075 InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
3076 LogInfo("handle_browse_request: browse pending for interface index %d", interfaceIndex);
3077 }
3078
3079 if (get_string(&request->msgptr, request->msgend, regtype, sizeof(regtype)) < 0 ||
3080 get_string(&request->msgptr, request->msgend, domain, sizeof(domain )) < 0) return(mStatus_BadParamErr);
3081
3082 if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3083
3084 request->flags = flags;
3085 request->interfaceIndex = interfaceIndex;
3086 typedn.c[0] = 0;
3087 NumSubTypes = ChopSubTypes(regtype); // Note: Modifies regtype string to remove trailing subtypes
3088 if (NumSubTypes < 0 || NumSubTypes > 1)
3089 return(mStatus_BadParamErr);
3090 if (NumSubTypes == 1)
3091 {
3092 if (!AppendDNSNameString(&typedn, regtype + strlen(regtype) + 1))
3093 return(mStatus_BadParamErr);
3094 }
3095
3096 if (!regtype[0] || !AppendDNSNameString(&typedn, regtype)) return(mStatus_BadParamErr);
3097
3098 if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr);
3099 // For over-long service types, we only allow domain "local"
3100 if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain));
3101
3102 // Set up browser info
3103 request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
3104 request->u.browser.interface_id = InterfaceID;
3105 AssignDomainName(&request->u.browser.regtype, &typedn);
3106 request->u.browser.default_domain = !domain[0];
3107 request->u.browser.browsers = NULL;
3108
3109 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%d] DNSServiceBrowse(%X, %d, \"" PRI_DM_NAME "\", \"" PRI_S "\") START PID[%d](" PUB_S ")",
3110 request->request_id, request->flags, interfaceIndex, DM_NAME_PARAM(&request->u.browser.regtype), domain,
3111 request->process_id, request->pid_name);
3112
3113 if (request->u.browser.default_domain)
3114 {
3115 // Start the domain enumeration queries to discover the WAB browse domains
3116 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3117 "[R%d] DNSServiceBrowse Start WAB PID[%d](" PUB_S ")",
3118 request->request_id, request->process_id, request->pid_name);
3119 uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
3120 }
3121 // We need to unconditionally set request->terminate, because even if we didn't successfully
3122 // start any browses right now, subsequent configuration changes may cause successful
3123 // browses to be added, and we'll need to cancel them before freeing this memory.
3124 request->terminate = NULL;
3125
3126 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3127 domainname d;
3128 if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
3129
3130 if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
3131 (request->u.browser.default_domain || IsLocalDomain(&d) || request->u.browser.ForceMCast))
3132 {
3133 err = _handle_browse_request_with_trust(request, domain);
3134 }
3135 else
3136 {
3137 err = _handle_browse_request_start(request, domain);
3138 }
3139 #else
3140 err = _handle_browse_request_start(request, domain);
3141 #endif
3142
3143 return(err);
3144 }
3145
3146 // ***************************************************************************
3147 #if COMPILER_LIKES_PRAGMA_MARK
3148 #pragma mark -
3149 #pragma mark - DNSServiceResolve
3150 #endif
3151
3152 mDNSlocal void resolve_termination_callback(request_state *request)
3153 {
3154 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3155 "[R%d] DNSServiceResolve(%X, %d, \"" PRI_DM_NAME "\") STOP PID[%d](" PUB_S ")",
3156 request->request_id, request->flags, request->interfaceIndex, DM_NAME_PARAM(&request->u.resolve.qtxt.qname),
3157 request->process_id, request->pid_name);
3158 mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt);
3159 mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
3160 LogMcastQ(&request->u.resolve.qsrv, request, q_stop);
3161 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
3162 if (request->u.resolve.external_advertise)
3163 {
3164 external_stop_resolving_service(request->u.resolve.qsrv.InterfaceID, &request->u.resolve.qsrv.qname, request->flags, request->process_id);
3165 }
3166 #endif
3167 }
3168
3169 typedef struct {
3170 char regtype[MAX_ESCAPED_DOMAIN_NAME];
3171 domainname fqdn;
3172 mDNSInterfaceID InterfaceID;
3173 } _resolve_start_params_t;
3174
3175 mDNSlocal mStatus _handle_resolve_request_start(request_state *request, const _resolve_start_params_t * const params)
3176 {
3177 mStatus err;
3178
3179 err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv);
3180
3181 if (!err)
3182 {
3183 err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
3184 if (err)
3185 {
3186 mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
3187 }
3188 else
3189 {
3190 request->terminate = resolve_termination_callback;
3191 LogMcastQ(&request->u.resolve.qsrv, request, q_start);
3192 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
3193 if (callExternalHelpers(params->InterfaceID, &params->fqdn, request->flags))
3194 {
3195 request->u.resolve.external_advertise = mDNStrue;
3196 LogInfo("handle_resolve_request: calling external_start_resolving_service()");
3197 external_start_resolving_service(params->InterfaceID, &params->fqdn, request->flags, request->process_id);
3198 }
3199 #else
3200 (void)params;
3201 #endif
3202 }
3203 }
3204 return err;
3205 }
3206
3207 mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
3208 {
3209 size_t len = 0;
3210 char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME] = "0";
3211 char *data;
3212 reply_state *rep;
3213 request_state *req = question->QuestionContext;
3214 const DNSServiceErrorType error =
3215 (answer->RecordType == kDNSRecordTypePacketNegative) ? kDNSServiceErr_NoSuchRecord : kDNSServiceErr_NoError;
3216 (void)m; // Unused
3217
3218 LogOperation("%3d: DNSServiceResolve(%##s) %s interface %d: %s",
3219 req->sd, question->qname.c, AddRecord ? "ADD" : "RMV",
3220 mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer));
3221
3222 if (!AddRecord)
3223 {
3224 if (req->u.resolve.srv == answer) req->u.resolve.srv = mDNSNULL;
3225 if (req->u.resolve.txt == answer) req->u.resolve.txt = mDNSNULL;
3226 return;
3227 }
3228
3229 if (answer->rrtype == kDNSType_SRV) req->u.resolve.srv = answer;
3230 if (answer->rrtype == kDNSType_TXT) req->u.resolve.txt = answer;
3231
3232 if (!req->u.resolve.txt || !req->u.resolve.srv) return; // only deliver result to client if we have both answers
3233
3234 ConvertDomainNameToCString(answer->name, fullname);
3235
3236 if (answer->RecordType != kDNSRecordTypePacketNegative)
3237 ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target);
3238
3239 // calculate reply length
3240 len += sizeof(DNSServiceFlags);
3241 len += sizeof(mDNSu32); // interface index
3242 len += sizeof(DNSServiceErrorType);
3243 len += strlen(fullname) + 1;
3244 len += strlen(target) + 1;
3245 len += 2 * sizeof(mDNSu16); // port, txtLen
3246 len += req->u.resolve.txt->rdlength;
3247
3248 // allocate/init reply header
3249 rep = create_reply(resolve_reply_op, len, req);
3250 rep->rhdr->flags = dnssd_htonl(0);
3251 rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse));
3252 rep->rhdr->error = dnssd_htonl(error);
3253
3254 data = (char *)&rep->rhdr[1];
3255
3256 // write reply data to message
3257 put_string(fullname, &data);
3258 put_string(target, &data);
3259 *data++ = req->u.resolve.srv->rdata->u.srv.port.b[0];
3260 *data++ = req->u.resolve.srv->rdata->u.srv.port.b[1];
3261 put_uint16(req->u.resolve.txt->rdlength, &data);
3262 put_rdata (req->u.resolve.txt->rdlength, req->u.resolve.txt->rdata->u.data, &data);
3263
3264 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%d->Q%d] DNSServiceResolve(" PRI_S ") RESULT " PRI_S ":%d",
3265 req->request_id, mDNSVal16(question->TargetQID), fullname, target,
3266 mDNSVal16(req->u.resolve.srv->rdata->u.srv.port));
3267 append_reply(req, rep);
3268 }
3269
3270 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3271
3272 mDNSlocal void _return_resolve_request_error(request_state * request, mStatus error)
3273 {
3274 size_t len;
3275 char * emptystr = "\0";
3276 char * data;
3277 reply_state *rep;
3278
3279 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3280 "[R%u] DNSServiceResolve _return_resolve_request_error: error(%d)", request->request_id, error);
3281
3282 // calculate reply length
3283 len = sizeof(DNSServiceFlags);
3284 len += sizeof(mDNSu32); // interface index
3285 len += sizeof(DNSServiceErrorType);
3286 len += 2; // name, target
3287 len += 2 * sizeof(mDNSu16); // port, txtLen
3288 len += 0; //req->u.resolve.txt->rdlength;
3289
3290 rep = create_reply(resolve_reply_op, len, request);
3291
3292 rep->rhdr->flags = 0;
3293 rep->rhdr->ifi = 0;
3294 rep->rhdr->error = dnssd_htonl(error);
3295
3296 data = (char *)&rep->rhdr[1];
3297
3298 // write reply data to message
3299 put_string(emptystr, &data); // name
3300 put_string(emptystr, &data); // target
3301 put_uint16(0, &data); // port
3302 put_uint16(0, &data); // txtLen
3303
3304 append_reply(request, rep);
3305 }
3306
3307 mDNSlocal mStatus _handle_resolve_request_with_trust(request_state *request, const _resolve_start_params_t * const params)
3308 {
3309 mStatus err;
3310 if (audit_token_to_pid(request->audit_token) == 0)
3311 {
3312 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, 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);
3313 err = _handle_resolve_request_start(request, params);
3314 }
3315 else
3316 {
3317 mdns_trust_flags_t flags = mdns_trust_flags_none;
3318 mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, params->regtype, &flags);
3319 switch (status)
3320 {
3321 case mdns_trust_status_denied:
3322 case mdns_trust_status_pending:
3323 {
3324 mdns_trust_t trust = mdns_trust_create(request->audit_token, params->regtype, flags);
3325 if (!trust )
3326 {
3327 err = mStatus_NoMemoryErr;
3328 goto exit;
3329 }
3330
3331 void * context = mallocL("context/_handle_resolve_request_with_trust", sizeof(_resolve_start_params_t));
3332 if (!context)
3333 {
3334 my_perror("ERROR: mallocL context/_handle_resolve_request_with_trust");
3335 mdns_release(trust);
3336 err = mStatus_NoMemoryErr;
3337 goto exit;
3338 }
3339 memcpy(context, params, sizeof(_resolve_start_params_t));
3340 mdns_trust_set_context(trust, context);
3341 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
3342 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
3343 {
3344 if (event == mdns_trust_event_result)
3345 {
3346 mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
3347 KQueueLock();
3348 _resolve_start_params_t * _params = mdns_trust_get_context(trust);
3349 if (_params)
3350 {
3351 if (!error)
3352 {
3353 error = _handle_resolve_request_start(request, _params);
3354 // No context means the request was canceled before we got here
3355 }
3356 if (error) // (not else if) Always check for error result
3357 {
3358 _return_resolve_request_error(request, error);
3359 }
3360 }
3361 KQueueUnlock("_handle_resolve_request_with_trust");
3362 }
3363 });
3364 request->trust = trust;
3365 mdns_trust_activate(trust);
3366 err = mStatus_NoError;
3367 break;
3368 }
3369
3370 case mdns_trust_status_no_entitlement:
3371 err = mStatus_NoAuth;
3372 break;
3373
3374 case mdns_trust_status_granted:
3375 err = _handle_resolve_request_start(request, params);
3376 break;
3377
3378 default:
3379 err = mStatus_UnknownErr;
3380 break;
3381 }
3382 }
3383 exit:
3384 return err;
3385 }
3386 #endif // TRUST_ENFORCEMENT
3387
3388 mDNSlocal mStatus handle_resolve_request(request_state *request)
3389 {
3390 char name[256], domain[MAX_ESCAPED_DOMAIN_NAME];
3391 _resolve_start_params_t params;
3392 mStatus err;
3393
3394 // extract the data from the message
3395 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3396 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3397
3398 // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
3399 // flag set so that the resolve will run over P2P interfaces that are not yet created.
3400 if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
3401 {
3402 LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
3403 flags |= kDNSServiceFlagsIncludeP2P;
3404 interfaceIndex = kDNSServiceInterfaceIndexAny;
3405 }
3406
3407 params.InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3408
3409 // The operation is scoped to a specific interface index, but the
3410 // interface is not currently in our list.
3411 if (interfaceIndex && !params.InterfaceID)
3412 {
3413 // If it's one of the specially defined inteface index values, just return an error.
3414 if (PreDefinedInterfaceIndex(interfaceIndex))
3415 {
3416 LogInfo("handle_resolve_request: bad interfaceIndex %d", interfaceIndex);
3417 return(mStatus_BadParamErr);
3418 }
3419
3420 // Otherwise, use the specified interface index value and the operation will
3421 // be applied to that interface when it comes up.
3422 params.InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
3423 LogInfo("handle_resolve_request: resolve pending for interface index %d", interfaceIndex);
3424 }
3425
3426 if (get_string(&request->msgptr, request->msgend, name, sizeof(name )) < 0 ||
3427 get_string(&request->msgptr, request->msgend, params.regtype, sizeof(params.regtype)) < 0 ||
3428 get_string(&request->msgptr, request->msgend, domain, sizeof(domain )) < 0)
3429 { LogMsg("ERROR: handle_resolve_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
3430
3431 if (!request->msgptr) { LogMsg("%3d: DNSServiceResolve(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3432
3433 if (build_domainname_from_strings(&params.fqdn, name, params.regtype, domain) < 0)
3434 { LogMsg("ERROR: handle_resolve_request bad “%s” “%s” “%s”", name, params.regtype, domain); return(mStatus_BadParamErr); }
3435
3436 mDNSPlatformMemZero(&request->u.resolve, sizeof(request->u.resolve));
3437
3438 #if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
3439 // Determine if this request should be promoted to use BLE triggered discovery.
3440 if (shouldUseBLE(InterfaceID, 0, (domainname *)SkipLeadingLabels(&fqdn, 1), &fqdn))
3441 {
3442 flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL);
3443 LogInfo("handle_resolve_request: request promoted to use kDNSServiceFlagsAutoTrigger");
3444 }
3445 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
3446
3447 request->flags = flags;
3448 request->interfaceIndex = interfaceIndex;
3449
3450 // format questions
3451 request->u.resolve.qsrv.InterfaceID = params.InterfaceID;
3452 request->u.resolve.qsrv.flags = flags;
3453 AssignDomainName(&request->u.resolve.qsrv.qname, &params.fqdn);
3454 request->u.resolve.qsrv.qtype = kDNSType_SRV;
3455 request->u.resolve.qsrv.qclass = kDNSClass_IN;
3456 request->u.resolve.qsrv.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
3457 request->u.resolve.qsrv.ExpectUnique = mDNStrue;
3458 request->u.resolve.qsrv.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
3459 request->u.resolve.qsrv.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
3460 request->u.resolve.qsrv.SuppressUnusable = mDNSfalse;
3461 request->u.resolve.qsrv.AppendSearchDomains = 0;
3462 request->u.resolve.qsrv.TimeoutQuestion = 0;
3463 request->u.resolve.qsrv.WakeOnResolve = (flags & kDNSServiceFlagsWakeOnResolve) != 0;
3464 request->u.resolve.qsrv.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
3465 request->u.resolve.qsrv.ProxyQuestion = 0;
3466 request->u.resolve.qsrv.pid = request->process_id;
3467 request->u.resolve.qsrv.euid = request->uid;
3468 request->u.resolve.qsrv.QuestionCallback = resolve_result_callback;
3469 request->u.resolve.qsrv.QuestionContext = request;
3470
3471 request->u.resolve.qtxt.InterfaceID = params.InterfaceID;
3472 request->u.resolve.qtxt.flags = flags;
3473 AssignDomainName(&request->u.resolve.qtxt.qname, &params.fqdn);
3474 request->u.resolve.qtxt.qtype = kDNSType_TXT;
3475 request->u.resolve.qtxt.qclass = kDNSClass_IN;
3476 request->u.resolve.qtxt.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
3477 request->u.resolve.qtxt.ExpectUnique = mDNStrue;
3478 request->u.resolve.qtxt.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
3479 request->u.resolve.qtxt.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
3480 request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
3481 request->u.resolve.qtxt.AppendSearchDomains = 0;
3482 request->u.resolve.qtxt.TimeoutQuestion = 0;
3483 request->u.resolve.qtxt.WakeOnResolve = 0;
3484 request->u.resolve.qtxt.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
3485 request->u.resolve.qtxt.ProxyQuestion = 0;
3486 request->u.resolve.qtxt.pid = request->process_id;
3487 request->u.resolve.qtxt.euid = request->uid;
3488 request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
3489 request->u.resolve.qtxt.QuestionContext = request;
3490
3491 request->u.resolve.ReportTime = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
3492
3493 request->u.resolve.external_advertise = mDNSfalse;
3494
3495 #if 0
3496 if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains)) return(mStatus_NoError);
3497 #endif
3498
3499 // ask the questions
3500 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3501 "[R%d] DNSServiceResolve(%X, %d, \"" PRI_DM_NAME "\") START PID[%d](" PUB_S ")",
3502 request->request_id, flags, interfaceIndex, DM_NAME_PARAM(&request->u.resolve.qsrv.qname),
3503 request->process_id, request->pid_name);
3504
3505 request->terminate = NULL;
3506 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3507 domainname d;
3508 if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
3509
3510 if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
3511 (IsLocalDomain(&d) || request->u.resolve.qsrv.ForceMCast))
3512 {
3513 err = _handle_resolve_request_with_trust(request, &params);
3514 }
3515 else
3516 {
3517 err = _handle_resolve_request_start(request, &params);
3518 }
3519 #else
3520 err = _handle_resolve_request_start(request, &params);
3521 #endif
3522
3523 return(err);
3524 }
3525
3526 // ***************************************************************************
3527 #if COMPILER_LIKES_PRAGMA_MARK
3528 #pragma mark -
3529 #pragma mark - DNSServiceQueryRecord
3530 #endif
3531
3532 mDNSlocal void queryrecord_result_reply(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord, DNSServiceErrorType error, void *context)
3533 {
3534 char name[MAX_ESCAPED_DOMAIN_NAME];
3535 size_t len;
3536 DNSServiceFlags flags = 0;
3537 reply_state *rep;
3538 char *data;
3539 request_state *req = (request_state *)context;
3540 const char *dnssec_result_description = "";
3541
3542 ConvertDomainNameToCString(answer->name, name);
3543
3544 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
3545 if (question->DNSSECStatus.enable_dnssec) {
3546 if (answer->dnssec_result == dnssec_secure)
3547 {
3548 flags |= kDNSServiceFlagsSecure;
3549 dnssec_result_description = ", DNSSEC_Secure";
3550 }
3551 else if (answer->dnssec_result == dnssec_insecure)
3552 {
3553 flags |= kDNSServiceFlagsInsecure;
3554 dnssec_result_description = ", DNSSEC_Insecure";
3555 }
3556 else if (answer->dnssec_result == dnssec_bogus)
3557 {
3558 flags |= kDNSServiceFlagsBogus;
3559 dnssec_result_description = ", DNSSEC_Bogus";
3560 }
3561 else if (answer->dnssec_result == dnssec_indeterminate)
3562 {
3563 flags |= kDNSServiceFlagsIndeterminate;
3564 dnssec_result_description = ", DNSSEC_Indeterminated";
3565 }
3566 } else if (question->DNSSECStatus.tried_dnssec_but_unsigned) {
3567 // handle the case where we restart the question without the DNSSEC while the user requires DNSSEC result, for
3568 // some reason we failed to get DNSSEC records. In which case, even if we go back to normal query, we should pass
3569 // the DNSSEC result
3570 flags |= kDNSServiceFlagsInsecure;
3571 dnssec_result_description = ", DNSSEC_Insecure";
3572 }
3573 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
3574
3575 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3576 "[R%u->Q%u] DNSService" PUB_S "(" PRI_DM_NAME ", " PUB_S ") RESULT " PUB_S " interface %d: (" PUB_S PUB_S ")" PRI_S,
3577 req->request_id, mDNSVal16(question->TargetQID), req->hdr.op == query_request ? "QueryRecord" : "GetAddrInfo",
3578 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV",
3579 mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse),
3580 MortalityDisplayString(answer->mortality), dnssec_result_description, RRDisplayString(m, answer));
3581
3582 len = sizeof(DNSServiceFlags); // calculate reply data length
3583 len += sizeof(mDNSu32); // interface index
3584 len += sizeof(DNSServiceErrorType);
3585 len += strlen(name) + 1;
3586 len += 3 * sizeof(mDNSu16); // type, class, rdlen
3587 len += answer->rdlength;
3588 len += sizeof(mDNSu32); // TTL
3589
3590 rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req);
3591
3592 if (AddRecord)
3593 flags |= kDNSServiceFlagsAdd;
3594 if (answer->mortality == Mortality_Ghost)
3595 flags |= kDNSServiceFlagsExpiredAnswer;
3596 if (!question->InitialCacheMiss)
3597 flags |= kDNSServiceFlagAnsweredFromCache;
3598
3599 rep->rhdr->flags = dnssd_htonl(flags);
3600 // Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the
3601 // InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions
3602 // to be stopped and started including *this* one. Normally the InterfaceID is valid. But when we
3603 // are using the /etc/hosts entries to answer a question, the InterfaceID may not be known to the
3604 // mDNS core . Eventually, we should remove the calls to "NetworkChanged" in
3605 // mDNSPlatformInterfaceIndexfromInterfaceID when it can't find InterfaceID as ResourceRecords
3606 // should not have existed to answer this question if the corresponding interface is not valid.
3607 rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue));
3608 rep->rhdr->error = dnssd_htonl(error);
3609
3610 data = (char *)&rep->rhdr[1];
3611
3612 put_string(name, &data);
3613 put_uint16(answer->rrtype, &data);
3614 put_uint16(answer->rrclass, &data);
3615 put_uint16(answer->rdlength, &data);
3616 // We need to use putRData here instead of the crude put_rdata function, because the crude put_rdata
3617 // function just does a blind memory copy without regard to structures that may have holes in them.
3618 if (answer->rdlength)
3619 if (!putRData(mDNSNULL, (mDNSu8 *)data, (mDNSu8 *)rep->rhdr + len, answer))
3620 LogMsg("queryrecord_result_reply putRData failed %d", (mDNSu8 *)rep->rhdr + len - (mDNSu8 *)data);
3621 data += answer->rdlength;
3622 put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
3623
3624 append_reply(req, rep);
3625 }
3626
3627 mDNSlocal void queryrecord_termination_callback(request_state *request)
3628 {
3629 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3630 "[R%u] DNSServiceQueryRecord(%X, %d, " PRI_DM_NAME ", " PUB_S ") STOP PID[%d](" PUB_S ")",
3631 request->request_id, request->flags, request->interfaceIndex,
3632 DM_NAME_PARAM(QueryRecordClientRequestGetQName(&request->u.queryrecord)),
3633 DNSTypeName(QueryRecordClientRequestGetType(&request->u.queryrecord)), request->process_id, request->pid_name);
3634
3635 QueryRecordClientRequestStop(&request->u.queryrecord);
3636 }
3637
3638 typedef struct {
3639 char qname[MAX_ESCAPED_DOMAIN_NAME];
3640 mDNSu32 interfaceIndex;
3641 DNSServiceFlags flags;
3642 mDNSu16 qtype;
3643 mDNSu16 qclass;
3644 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3645 mDNSBool require_privacy;
3646 #endif
3647 } _queryrecord_start_params_t;
3648
3649 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
3650 mDNSlocal const mDNSu8 * ipc_tlv_get_resolver_config_plist_data(const mDNSu8 *const start, const mDNSu8 *const end,
3651 size_t *outLen)
3652 {
3653 size_t len = 0;
3654 const mDNSu8 *value = NULL;
3655 mdns_tlv16_get_value(start, end, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, &len, &value, NULL);
3656 if (outLen)
3657 {
3658 *outLen = len;
3659 }
3660 return value;
3661 }
3662
3663 mDNSlocal mDNSBool ipc_tlv_get_require_privacy(const mDNSu8 *const start, const mDNSu8 *const end)
3664 {
3665 size_t len = 0;
3666 const mDNSu8 *value = NULL;
3667 mdns_tlv16_get_value(start, end, IPC_TLV_TYPE_REQUIRE_PRIVACY, &len, &value, NULL);
3668 return ((len == 1) && (*value != 0)) ? mDNStrue : mDNSfalse;
3669 }
3670 #endif
3671
3672 mDNSlocal mStatus _handle_queryrecord_request_start(request_state *request, const _queryrecord_start_params_t * const params)
3673 {
3674 mStatus err;
3675
3676 request->terminate = queryrecord_termination_callback;
3677
3678 QueryRecordClientRequestParams queryParams;
3679 QueryRecordClientRequestParamsInit(&queryParams);
3680 queryParams.requestID = request->request_id;
3681 queryParams.qnameStr = params->qname;
3682 queryParams.interfaceIndex = params->interfaceIndex;
3683 queryParams.flags = params->flags;
3684 queryParams.qtype = params->qtype;
3685 queryParams.qclass = params->qclass;
3686 queryParams.effectivePID = request->validUUID ? 0 : request->process_id;
3687 queryParams.effectiveUUID = request->validUUID ? request->uuid : mDNSNULL;
3688 queryParams.peerUID = request->uid;
3689 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3690 queryParams.needEncryption = params->require_privacy ? mDNStrue : mDNSfalse;
3691 queryParams.customID = request->custom_service_id;
3692 #endif
3693 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
3694 queryParams.peerAuditToken = &request->audit_token;
3695 #endif
3696 err = QueryRecordClientRequestStart(&request->u.queryrecord, &queryParams, queryrecord_result_reply, request);
3697 return err;
3698 }
3699
3700 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3701
3702 mDNSlocal void _return_queryrecord_request_error(request_state * request, mStatus error)
3703 {
3704 size_t len;
3705 char * emptystr = "\0";
3706 char * data;
3707 reply_state *rep;
3708
3709 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3710 "[R%u] DNSService" PUB_S " _return_queryrecord_request_error: error(%d)",
3711 request->request_id, request->hdr.op == query_request ? "QueryRecord" : "GetAddrInfo", error);
3712
3713 len = sizeof(DNSServiceFlags); // calculate reply data length
3714 len += sizeof(mDNSu32); // interface index
3715 len += sizeof(DNSServiceErrorType);
3716 len += strlen(emptystr) + 1;
3717 len += 3 * sizeof(mDNSu16); // type, class, rdlen
3718 len += 0;//answer->rdlength;
3719 len += sizeof(mDNSu32); // TTL
3720
3721 rep = create_reply(request->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, request);
3722
3723 rep->rhdr->flags = 0;
3724 rep->rhdr->ifi = 0;
3725 rep->rhdr->error = dnssd_htonl(error);
3726
3727 data = (char *)&rep->rhdr[1];
3728
3729 put_string(emptystr, &data);
3730 put_uint16(0, &data);
3731 put_uint16(0, &data);
3732 put_uint16(0, &data);
3733 data += 0;
3734 put_uint32(0, &data);
3735
3736 append_reply(request, rep);
3737 }
3738
3739 mDNSlocal mStatus _handle_queryrecord_request_with_trust(request_state *request, const _queryrecord_start_params_t * const params)
3740 {
3741 mStatus err;
3742 if (audit_token_to_pid(request->audit_token) == 0)
3743 {
3744 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);
3745 err = _handle_queryrecord_request_start(request, params);
3746 }
3747 else
3748 {
3749 const char *service_ptr = NULL;
3750 char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
3751 domainname query_name;
3752 if (MakeDomainNameFromDNSNameString(&query_name, params->qname))
3753 {
3754 domainlabel name;
3755 domainname type, domain;
3756 bool good = DeconstructServiceName(&query_name, &name, &type, &domain);
3757 if (good)
3758 {
3759 ConvertDomainNameToCString(&type, type_str);
3760 service_ptr = type_str;
3761 }
3762 }
3763
3764 mdns_trust_flags_t flags = mdns_trust_flags_none;
3765 mdns_trust_status_t status = mdns_trust_check_query(request->audit_token, params->qname, service_ptr, params->qtype, (params->flags & kDNSServiceFlagsForceMulticast) != 0, &flags);
3766 switch (status)
3767 {
3768 case mdns_trust_status_denied:
3769 case mdns_trust_status_pending:
3770 {
3771 mdns_trust_t trust = mdns_trust_create(request->audit_token, service_ptr, flags);
3772 if (!trust )
3773 {
3774 err = mStatus_NoMemoryErr;
3775 goto exit;
3776 }
3777
3778 void * context = mallocL("context/_handle_queryrecord_request_with_trust", sizeof(_queryrecord_start_params_t));
3779 if (!context)
3780 {
3781 my_perror("ERROR: mallocL context/_handle_queryrecord_request_with_trust");
3782 mdns_release(trust);
3783 err = mStatus_NoMemoryErr;
3784 goto exit;
3785 }
3786 memcpy(context, params, sizeof(_queryrecord_start_params_t));
3787 mdns_trust_set_context(trust, context);
3788 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
3789 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
3790 {
3791 if (event == mdns_trust_event_result)
3792 {
3793 mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
3794 KQueueLock();
3795 _queryrecord_start_params_t * _params = mdns_trust_get_context(trust);
3796 if (_params)
3797 {
3798 if (!error)
3799 {
3800 error = _handle_queryrecord_request_start(request, _params);
3801 // No context means the request was canceled before we got here
3802 }
3803 if (error) // (not else if) Always check for error result
3804 {
3805 _return_queryrecord_request_error(request, error);
3806 }
3807 }
3808 KQueueUnlock("_handle_queryrecord_request_with_trust");
3809 }
3810 });
3811 request->trust = trust;
3812 mdns_trust_activate(trust);
3813 err = mStatus_NoError;
3814 break;
3815 }
3816
3817 case mdns_trust_status_no_entitlement:
3818 err = mStatus_NoAuth;
3819 break;
3820
3821 case mdns_trust_status_granted:
3822 err = _handle_queryrecord_request_start(request, params);
3823 break;
3824
3825 default:
3826 err = mStatus_UnknownErr;
3827 break;
3828 }
3829 }
3830 exit:
3831 return err;
3832 }
3833 #endif // TRUST_ENFORCEMENT
3834
3835 mDNSlocal mStatus handle_queryrecord_request(request_state *request)
3836 {
3837 mStatus err;
3838 _queryrecord_start_params_t params;
3839
3840 params.flags = get_flags(&request->msgptr, request->msgend);
3841 params.interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3842 if (get_string(&request->msgptr, request->msgend, params.qname, sizeof(params.qname)) < 0)
3843 {
3844 err = mStatus_BadParamErr;
3845 goto exit;
3846 }
3847 params.qtype = get_uint16(&request->msgptr, request->msgend);
3848 params.qclass = get_uint16(&request->msgptr, request->msgend);
3849
3850 if (!request->msgptr)
3851 {
3852 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
3853 "[R%d] DNSServiceQueryRecord(unreadable parameters)", request->request_id);
3854 err = mStatus_BadParamErr;
3855 goto exit;
3856 }
3857 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3858 params.require_privacy = mDNSfalse;
3859 #endif
3860 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
3861 if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
3862 {
3863 size_t len;
3864 const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
3865 const mDNSu8 *const end = (const mDNSu8 *)request->msgend;
3866 const mDNSu8 *const data = ipc_tlv_get_resolver_config_plist_data(start, end, &len);
3867 if (data)
3868 {
3869 request->custom_service_id = Querier_RegisterCustomDNSServiceWithPListData(data, len);
3870 }
3871 params.require_privacy = ipc_tlv_get_require_privacy(start, end);
3872 }
3873 #endif
3874 request->flags = params.flags;
3875 request->interfaceIndex = params.interfaceIndex;
3876
3877 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3878 "[R%d] DNSServiceQueryRecord(%X, %d, " PRI_S ", " PUB_S ") START PID[%d](" PUB_S ")",
3879 request->request_id, request->flags, request->interfaceIndex, params.qname, DNSTypeName(params.qtype), request->process_id,
3880 request->pid_name);
3881
3882 mDNSPlatformMemZero(&request->u.queryrecord, (mDNSu32)sizeof(request->u.queryrecord));
3883 request->terminate = NULL;
3884
3885 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3886 if (os_feature_enabled(mDNSResponder, bonjour_privacy))
3887 {
3888 err = _handle_queryrecord_request_with_trust(request, &params);
3889 }
3890 else
3891 {
3892 err = _handle_queryrecord_request_start(request, &params);
3893 }
3894 #else
3895 err = _handle_queryrecord_request_start(request, &params);
3896 #endif
3897
3898 exit:
3899 return(err);
3900 }
3901
3902 // ***************************************************************************
3903 #if COMPILER_LIKES_PRAGMA_MARK
3904 #pragma mark -
3905 #pragma mark - DNSServiceEnumerateDomains
3906 #endif
3907
3908 mDNSlocal reply_state *format_enumeration_reply(request_state *request,
3909 const char *domain, DNSServiceFlags flags, mDNSu32 ifi, DNSServiceErrorType err)
3910 {
3911 size_t len;
3912 reply_state *reply;
3913 char *data;
3914
3915 len = sizeof(DNSServiceFlags);
3916 len += sizeof(mDNSu32);
3917 len += sizeof(DNSServiceErrorType);
3918 len += strlen(domain) + 1;
3919
3920 reply = create_reply(enumeration_reply_op, len, request);
3921 reply->rhdr->flags = dnssd_htonl(flags);
3922 reply->rhdr->ifi = dnssd_htonl(ifi);
3923 reply->rhdr->error = dnssd_htonl(err);
3924 data = (char *)&reply->rhdr[1];
3925 put_string(domain, &data);
3926 return reply;
3927 }
3928
3929 mDNSlocal void enum_termination_callback(request_state *request)
3930 {
3931 // Stop the domain enumeration queries to discover the WAB Browse/Registration domains
3932 if (request->u.enumeration.flags & kDNSServiceFlagsRegistrationDomains)
3933 {
3934 LogInfo("%3d: DNSServiceEnumeration Cancel WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
3935 uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
3936 }
3937 else
3938 {
3939 LogInfo("%3d: DNSServiceEnumeration Cancel WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
3940 uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
3941 mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_autoall);
3942 }
3943 mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
3944 mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
3945 }
3946
3947 mDNSlocal void enum_result_callback(mDNS *const m,
3948 DNSQuestion *const question, const ResourceRecord *const answer, QC_result AddRecord)
3949 {
3950 char domain[MAX_ESCAPED_DOMAIN_NAME];
3951 request_state *request = question->QuestionContext;
3952 DNSServiceFlags flags = 0;
3953 reply_state *reply;
3954 (void)m; // Unused
3955
3956 if (answer->rrtype != kDNSType_PTR) return;
3957
3958 #if 0
3959 if (!AuthorizedDomain(request, &answer->rdata->u.name, request->u.enumeration.flags ? AutoRegistrationDomains : AutoBrowseDomains)) return;
3960 #endif
3961
3962 // We only return add/remove events for the browse and registration lists
3963 // For the default browse and registration answers, we only give an "ADD" event
3964 if (question == &request->u.enumeration.q_default && !AddRecord) return;
3965
3966 if (AddRecord)
3967 {
3968 flags |= kDNSServiceFlagsAdd;
3969 if (question == &request->u.enumeration.q_default) flags |= kDNSServiceFlagsDefault;
3970 }
3971
3972 ConvertDomainNameToCString(&answer->rdata->u.name, domain);
3973 // Note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
3974 // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
3975 // network, so we just pass kDNSServiceInterfaceIndexAny
3976 reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError);
3977 if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; }
3978
3979 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
3980 "[R%d->Q%d] DNSServiceEnumerateDomains(%2.*s) RESULT " PUB_S ": " PRI_S,
3981 request->request_id, mDNSVal16(question->TargetQID), question->qname.c[0], &question->qname.c[1],
3982 AddRecord ? "ADD" : "RMV", domain);
3983
3984 append_reply(request, reply);
3985 }
3986
3987 mDNSlocal mStatus handle_enum_request(request_state *request)
3988 {
3989 mStatus err;
3990 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3991 DNSServiceFlags reg = flags & kDNSServiceFlagsRegistrationDomains;
3992 mDNS_DomainType t_all = reg ? mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse;
3993 mDNS_DomainType t_default = reg ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
3994 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3995 mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3996 if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
3997
3998 if (!request->msgptr)
3999 { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
4000
4001 request->flags = flags;
4002 request->interfaceIndex = interfaceIndex;
4003
4004 // mark which kind of enumeration we're doing so that we know what domain enumeration queries to stop
4005 request->u.enumeration.flags = reg;
4006
4007 // enumeration requires multiple questions, so we must link all the context pointers so that
4008 // necessary context can be reached from the callbacks
4009 request->u.enumeration.q_all.QuestionContext = request;
4010 request->u.enumeration.q_default.QuestionContext = request;
4011 if (!reg) request->u.enumeration.q_autoall.QuestionContext = request;
4012
4013 // if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
4014 if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
4015
4016 // make the calls
4017 LogOperation("%3d: DNSServiceEnumerateDomains(%X=%s)", request->sd, flags,
4018 (flags & kDNSServiceFlagsBrowseDomains ) ? "kDNSServiceFlagsBrowseDomains" :
4019 (flags & kDNSServiceFlagsRegistrationDomains) ? "kDNSServiceFlagsRegistrationDomains" : "<<Unknown>>");
4020 err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_all, t_all, NULL, InterfaceID, enum_result_callback, request);
4021 if (!err)
4022 {
4023 err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
4024 if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
4025 else if (!reg)
4026 {
4027 err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_autoall, mDNS_DomainTypeBrowseAutomatic, NULL, InterfaceID, enum_result_callback, request);
4028 if (err)
4029 {
4030 mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
4031 mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
4032 }
4033 }
4034 if (!err) request->terminate = enum_termination_callback;
4035 }
4036 if (!err)
4037 {
4038 // Start the domain enumeration queries to discover the WAB Browse/Registration domains
4039 if (reg)
4040 {
4041 LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
4042 uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
4043 }
4044 else
4045 {
4046 LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
4047 uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
4048 }
4049 }
4050
4051 return(err);
4052 }
4053
4054 // ***************************************************************************
4055 #if COMPILER_LIKES_PRAGMA_MARK
4056 #pragma mark -
4057 #pragma mark - DNSServiceReconfirmRecord & Misc
4058 #endif
4059
4060 mDNSlocal mStatus handle_reconfirm_request(request_state *request)
4061 {
4062 mStatus status = mStatus_BadParamErr;
4063 AuthRecord *rr = read_rr_from_ipc_msg(request, 0, 0);
4064 if (rr)
4065 {
4066 status = mDNS_ReconfirmByValue(&mDNSStorage, &rr->resrec);
4067 LogOperation(
4068 (status == mStatus_NoError) ?
4069 "%3d: DNSServiceReconfirmRecord(%s) interface %d initiated PID[%d](%s)" :
4070 "%3d: DNSServiceReconfirmRecord(%s) interface %d failed PID[%d](%s) status %d",
4071 request->sd, RRDisplayString(&mDNSStorage, &rr->resrec),
4072 mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, rr->resrec.InterfaceID, mDNSfalse),
4073 request->process_id, request->pid_name, status);
4074 freeL("AuthRecord/handle_reconfirm_request", rr);
4075 }
4076 return(status);
4077 }
4078
4079 #if APPLE_OSX_mDNSResponder
4080
4081 mDNSlocal mStatus handle_release_request(request_state *request)
4082 {
4083 mStatus err = 0;
4084 char name[256], regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
4085 domainname instance;
4086
4087 // extract the data from the message
4088 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
4089
4090 if (get_string(&request->msgptr, request->msgend, name, sizeof(name )) < 0 ||
4091 get_string(&request->msgptr, request->msgend, regtype, sizeof(regtype)) < 0 ||
4092 get_string(&request->msgptr, request->msgend, domain, sizeof(domain )) < 0)
4093 {
4094 LogMsg("ERROR: handle_release_request - Couldn't read name/regtype/domain");
4095 return(mStatus_BadParamErr);
4096 }
4097
4098 if (!request->msgptr)
4099 {
4100 LogMsg("%3d: PeerConnectionRelease(unreadable parameters)", request->sd);
4101 return(mStatus_BadParamErr);
4102 }
4103
4104 if (build_domainname_from_strings(&instance, name, regtype, domain) < 0)
4105 {
4106 LogMsg("ERROR: handle_release_request bad “%s” “%s” “%s”", name, regtype, domain);
4107 return(mStatus_BadParamErr);
4108 }
4109
4110 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4111 "[R%d] PeerConnectionRelease(%X " PRI_DM_NAME ") START PID[%d](" PUB_S ")",
4112 request->request_id, flags, DM_NAME_PARAM(&instance), request->process_id, request->pid_name);
4113
4114 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
4115 external_connection_release(&instance);
4116 #endif
4117 return(err);
4118 }
4119
4120 #else // APPLE_OSX_mDNSResponder
4121
4122 mDNSlocal mStatus handle_release_request(request_state *request)
4123 {
4124 (void) request;
4125 return mStatus_UnsupportedErr;
4126 }
4127
4128 #endif // APPLE_OSX_mDNSResponder
4129
4130 mDNSlocal mStatus handle_setdomain_request(request_state *request)
4131 {
4132 char domainstr[MAX_ESCAPED_DOMAIN_NAME];
4133 domainname domain;
4134 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
4135 (void)flags; // Unused
4136 if (get_string(&request->msgptr, request->msgend, domainstr, sizeof(domainstr)) < 0 ||
4137 !MakeDomainNameFromDNSNameString(&domain, domainstr))
4138 { LogMsg("%3d: DNSServiceSetDefaultDomainForUser(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
4139
4140 LogOperation("%3d: DNSServiceSetDefaultDomainForUser(%##s)", request->sd, domain.c);
4141 return(mStatus_NoError);
4142 }
4143
4144 typedef packedstruct
4145 {
4146 mStatus err;
4147 mDNSu32 len;
4148 mDNSu32 vers;
4149 } DaemonVersionReply;
4150
4151 mDNSlocal void handle_getproperty_request(request_state *request)
4152 {
4153 const mStatus BadParamErr = dnssd_htonl((mDNSu32)mStatus_BadParamErr);
4154 char prop[256];
4155 if (get_string(&request->msgptr, request->msgend, prop, sizeof(prop)) >= 0)
4156 {
4157 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4158 "[R%d] DNSServiceGetProperty(" PUB_S ")", request->request_id, prop);
4159 if (!strcmp(prop, kDNSServiceProperty_DaemonVersion))
4160 {
4161 DaemonVersionReply x = { 0, dnssd_htonl(4), dnssd_htonl(_DNS_SD_H) };
4162 send_all(request->sd, (const char *)&x, sizeof(x));
4163 return;
4164 }
4165 }
4166
4167 // If we didn't recogize the requested property name, return BadParamErr
4168 send_all(request->sd, (const char *)&BadParamErr, sizeof(BadParamErr));
4169 }
4170
4171 #ifdef APPLE_OSX_mDNSResponder
4172 // The caller can specify either the pid or the uuid. If the pid is not specified,
4173 // update the effective uuid. Don't overwrite the pid which is used for debugging
4174 // purposes and initialized when the socket is opened.
4175 mDNSlocal void handle_connection_delegate_request(request_state *request)
4176 {
4177 mDNSs32 pid;
4178 socklen_t len;
4179
4180 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4181 "[R%d] DNSServiceCreateDelegateConnection START PID[%d](" PUB_S ")",
4182 request->request_id, request->process_id, request->pid_name);
4183 request->terminate = connection_termination;
4184
4185 len = 0;
4186 pid = get_uint32(&request->msgptr, request->msgend);
4187 #ifdef LOCAL_PEEREPID
4188 if (pid)
4189 {
4190 len = sizeof(pid);
4191 if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &request->process_id, &len) != 0)
4192 {
4193 LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREPID failed errno:%d / %s", errno, strerror(errno));
4194 return;
4195 }
4196 // to extract the process name from the pid value
4197 if (proc_pidinfo(request->process_id, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0)
4198 return;
4199 mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name));
4200 debugf("handle_connection_delegate_request: process id %d, name %s", request->process_id, request->pid_name);
4201 }
4202 #endif
4203 #ifdef LOCAL_PEEREUUID
4204 if (!pid)
4205 {
4206 len = UUID_SIZE;
4207 if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREUUID, request->uuid, &len) != 0)
4208 {
4209 LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREUUID failed errno:%d / %s", errno, strerror(errno));
4210 return;
4211 }
4212 request->validUUID = mDNStrue;
4213 }
4214 #endif
4215 }
4216 #else
4217 mDNSlocal void handle_connection_delegate_request(request_state *request)
4218 {
4219 (void) request;
4220 }
4221 #endif
4222
4223 typedef packedstruct
4224 {
4225 mStatus err;
4226 mDNSs32 pid;
4227 } PIDInfo;
4228
4229 // ***************************************************************************
4230 #if COMPILER_LIKES_PRAGMA_MARK
4231 #pragma mark -
4232 #pragma mark - DNSServiceNATPortMappingCreate
4233 #endif
4234
4235 #define DNSServiceProtocol(X) ((X) == NATOp_AddrRequest ? 0 : (X) == NATOp_MapUDP ? kDNSServiceProtocol_UDP : kDNSServiceProtocol_TCP)
4236
4237 mDNSlocal void port_mapping_termination_callback(request_state *request)
4238 {
4239 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP PID[%d](" PUB_S ")",
4240 request->request_id, DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
4241 mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
4242 request->process_id, request->pid_name);
4243
4244 mDNS_StopNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
4245 }
4246
4247 // Called via function pointer when we get a NAT Traversal (address request or port mapping) response
4248 mDNSlocal void port_mapping_create_request_callback(mDNS *m, NATTraversalInfo *n)
4249 {
4250 request_state *request = (request_state *)n->clientContext;
4251 reply_state *rep;
4252 int replyLen;
4253 char *data;
4254
4255 if (!request) { LogMsg("port_mapping_create_request_callback called with unknown request_state object"); return; }
4256
4257 // calculate reply data length
4258 replyLen = sizeof(DNSServiceFlags);
4259 replyLen += 3 * sizeof(mDNSu32); // if index + addr + ttl
4260 replyLen += sizeof(DNSServiceErrorType);
4261 replyLen += 2 * sizeof(mDNSu16); // Internal Port + External Port
4262 replyLen += sizeof(mDNSu8); // protocol
4263
4264 rep = create_reply(port_mapping_reply_op, replyLen, request);
4265
4266 rep->rhdr->flags = dnssd_htonl(0);
4267 rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, n->InterfaceID, mDNSfalse));
4268 rep->rhdr->error = dnssd_htonl(n->Result);
4269
4270 data = (char *)&rep->rhdr[1];
4271
4272 *data++ = request->u.pm.NATinfo.ExternalAddress.b[0];
4273 *data++ = request->u.pm.NATinfo.ExternalAddress.b[1];
4274 *data++ = request->u.pm.NATinfo.ExternalAddress.b[2];
4275 *data++ = request->u.pm.NATinfo.ExternalAddress.b[3];
4276 *data++ = DNSServiceProtocol(request->u.pm.NATinfo.Protocol);
4277 *data++ = request->u.pm.NATinfo.IntPort.b[0];
4278 *data++ = request->u.pm.NATinfo.IntPort.b[1];
4279 *data++ = request->u.pm.NATinfo.ExternalPort.b[0];
4280 *data++ = request->u.pm.NATinfo.ExternalPort.b[1];
4281 put_uint32(request->u.pm.NATinfo.Lifetime, &data);
4282
4283 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4284 "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) RESULT " PRI_IPv4_ADDR ":%u TTL %u",
4285 request->request_id, DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
4286 mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
4287 &request->u.pm.NATinfo.ExternalAddress, mDNSVal16(request->u.pm.NATinfo.ExternalPort),
4288 request->u.pm.NATinfo.Lifetime);
4289
4290 append_reply(request, rep);
4291 }
4292
4293 mDNSlocal mStatus handle_port_mapping_request(request_state *request)
4294 {
4295 mDNSu32 ttl = 0;
4296 mStatus err = mStatus_NoError;
4297
4298 DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
4299 mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
4300 mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
4301 mDNSu8 protocol = (mDNSu8)get_uint32(&request->msgptr, request->msgend);
4302 (void)flags; // Unused
4303 if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
4304 if (request->msgptr + 8 > request->msgend) request->msgptr = NULL;
4305 else
4306 {
4307 request->u.pm.NATinfo.IntPort.b[0] = *request->msgptr++;
4308 request->u.pm.NATinfo.IntPort.b[1] = *request->msgptr++;
4309 request->u.pm.ReqExt.b[0] = *request->msgptr++;
4310 request->u.pm.ReqExt.b[1] = *request->msgptr++;
4311 ttl = get_uint32(&request->msgptr, request->msgend);
4312 }
4313
4314 if (!request->msgptr)
4315 {
4316 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
4317 "[R%d] DNSServiceNATPortMappingCreate(unreadable parameters)", request->request_id);
4318 return(mStatus_BadParamErr);
4319 }
4320
4321 if (protocol == 0) // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too
4322 {
4323 if (!mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort) || !mDNSIPPortIsZero(request->u.pm.ReqExt) || ttl) return(mStatus_BadParamErr);
4324 }
4325 else
4326 {
4327 if (mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort)) return(mStatus_BadParamErr);
4328 if (!(protocol & (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP))) return(mStatus_BadParamErr);
4329 }
4330
4331 request->flags = flags;
4332 request->interfaceIndex = interfaceIndex;
4333 request->u.pm.NATinfo.Protocol = !protocol ? NATOp_AddrRequest : (protocol == kDNSServiceProtocol_UDP) ? NATOp_MapUDP : NATOp_MapTCP;
4334 // u.pm.NATinfo.IntPort = already set above
4335 request->u.pm.NATinfo.RequestedPort = request->u.pm.ReqExt;
4336 request->u.pm.NATinfo.NATLease = ttl;
4337 request->u.pm.NATinfo.clientCallback = port_mapping_create_request_callback;
4338 request->u.pm.NATinfo.clientContext = request;
4339
4340 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4341 "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START PID[%d](" PUB_S ")",
4342 request->request_id, protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt),
4343 request->u.pm.NATinfo.NATLease, request->process_id, request->pid_name);
4344 err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
4345 if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
4346 else request->terminate = port_mapping_termination_callback;
4347
4348 return(err);
4349 }
4350
4351 // ***************************************************************************
4352 #if COMPILER_LIKES_PRAGMA_MARK
4353 #pragma mark -
4354 #pragma mark - DNSServiceGetAddrInfo
4355 #endif
4356
4357 mDNSlocal void addrinfo_termination_callback(request_state *request)
4358 {
4359 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4360 "[R%u] DNSServiceGetAddrInfo(" PRI_DM_NAME ") STOP PID[%d](" PUB_S ")",
4361 request->request_id, DM_NAME_PARAM(GetAddrInfoClientRequestGetQName(&request->u.addrinfo)),
4362 request->process_id, request->pid_name);
4363
4364 GetAddrInfoClientRequestStop(&request->u.addrinfo);
4365 }
4366
4367 typedef struct {
4368 mDNSu32 protocols;
4369 char hostname[MAX_ESCAPED_DOMAIN_NAME];
4370 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
4371 mDNSBool require_privacy;
4372 #endif
4373 } _addrinfo_start_params_t;
4374
4375 mDNSlocal mStatus _handle_addrinfo_request_start(request_state *request, const _addrinfo_start_params_t * const params)
4376 {
4377 mStatus err;
4378
4379 request->terminate = addrinfo_termination_callback;
4380
4381 GetAddrInfoClientRequestParams gaiParams;
4382 GetAddrInfoClientRequestParamsInit(&gaiParams);
4383 gaiParams.requestID = request->request_id;
4384 gaiParams.hostnameStr = params->hostname;
4385 gaiParams.interfaceIndex = request->interfaceIndex;
4386 gaiParams.flags = request->flags;
4387 gaiParams.protocols = params->protocols;
4388 gaiParams.effectivePID = request->validUUID ? 0 : request->process_id;
4389 gaiParams.effectiveUUID = request->validUUID ? request->uuid : mDNSNULL;
4390 gaiParams.peerUID = request->uid;
4391 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
4392 gaiParams.needEncryption = params->require_privacy ? mDNStrue : mDNSfalse;
4393 gaiParams.customID = request->custom_service_id;
4394 #endif
4395 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
4396 gaiParams.peerAuditToken = &request->audit_token;
4397 #endif
4398 err = GetAddrInfoClientRequestStart(&request->u.addrinfo, &gaiParams, queryrecord_result_reply, request);
4399
4400 return err;
4401 }
4402
4403 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
4404
4405 mDNSlocal void _return_addrinfo_request_error(request_state * request, mStatus error)
4406 {
4407 _return_queryrecord_request_error(request, error);
4408 }
4409
4410 mDNSlocal mStatus _handle_addrinfo_request_with_trust(request_state *request, const _addrinfo_start_params_t * const params)
4411 {
4412 mStatus err;
4413 if (audit_token_to_pid(request->audit_token) == 0)
4414 {
4415 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);
4416 err = _handle_addrinfo_request_start(request, params);
4417 }
4418 else
4419 {
4420 mdns_trust_flags_t flags = mdns_trust_flags_none;
4421 mdns_trust_status_t status = mdns_trust_check_getaddrinfo(request->audit_token, params->hostname, &flags);
4422 switch (status)
4423 {
4424 case mdns_trust_status_denied:
4425 case mdns_trust_status_pending:
4426 {
4427 mdns_trust_t trust = mdns_trust_create(request->audit_token, NULL, flags);
4428 if (!trust )
4429 {
4430 err = mStatus_NoMemoryErr;
4431 goto exit;
4432 }
4433
4434 void * context = mallocL("context/_handle_addrinfo_request_with_trust", sizeof(_addrinfo_start_params_t));
4435 if (!context)
4436 {
4437 my_perror("ERROR: mallocL context/_handle_addrinfo_request_with_trust");
4438 mdns_release(trust);
4439 err = mStatus_NoMemoryErr;
4440 goto exit;
4441 }
4442 memcpy(context, params, sizeof(_addrinfo_start_params_t));
4443 mdns_trust_set_context(trust, context);
4444 mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
4445 mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
4446 {
4447 if (event == mdns_trust_event_result)
4448 {
4449 mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
4450 KQueueLock();
4451 _addrinfo_start_params_t * _params = mdns_trust_get_context(trust);
4452 if (_params)
4453 {
4454 if (!error)
4455 {
4456 error = _handle_addrinfo_request_start(request, _params);
4457 // No context means the request was canceled before we got here
4458 }
4459 if (error) // (not else if) Always check for error result
4460 {
4461 _return_addrinfo_request_error(request, error);
4462 }
4463 }
4464 KQueueUnlock("_handle_addrinfo_request_with_trust");
4465 }
4466 });
4467 request->trust = trust;
4468 mdns_trust_activate(trust);
4469 err = mStatus_NoError;
4470 break;
4471 }
4472
4473 case mdns_trust_status_no_entitlement:
4474 err = mStatus_NoAuth;
4475 break;
4476
4477 case mdns_trust_status_granted:
4478 err = _handle_addrinfo_request_start(request, params);
4479 break;
4480
4481 default:
4482 err = mStatus_UnknownErr;
4483 break;
4484 }
4485 }
4486 exit:
4487 return err;
4488 }
4489 #endif // TRUST_ENFORCEMENT
4490
4491 mDNSlocal mStatus handle_addrinfo_request(request_state *request)
4492 {
4493 mStatus err;
4494 DNSServiceFlags flags;
4495 mDNSu32 interfaceIndex;
4496 _addrinfo_start_params_t params;
4497
4498 flags = get_flags(&request->msgptr, request->msgend);
4499 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
4500 params.protocols = get_uint32(&request->msgptr, request->msgend);
4501 if (get_string(&request->msgptr, request->msgend, params.hostname, sizeof(params.hostname)) < 0)
4502 {
4503 err = mStatus_BadParamErr;
4504 goto exit;
4505 }
4506 if (!request->msgptr)
4507 {
4508 LogMsg("%3d: DNSServiceGetAddrInfo(unreadable parameters)", request->sd);
4509 err = mStatus_BadParamErr;
4510 goto exit;
4511 }
4512 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
4513 params.require_privacy = mDNSfalse;
4514 #endif
4515 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
4516 if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
4517 {
4518 size_t len;
4519 const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
4520 const mDNSu8 *const end = (const mDNSu8 *)request->msgend;
4521 const mDNSu8 *const data = ipc_tlv_get_resolver_config_plist_data(start, end, &len);
4522 if (data)
4523 {
4524 request->custom_service_id = Querier_RegisterCustomDNSServiceWithPListData(data, len);
4525 }
4526 params.require_privacy = ipc_tlv_get_require_privacy(start, end);
4527 }
4528 #endif
4529 request->flags = flags;
4530 request->interfaceIndex = interfaceIndex;
4531
4532 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4533 "[R%u] DNSServiceGetAddrInfo(%X, %d, %u, " PRI_S ") START PID[%d](" PUB_S ")",
4534 request->request_id, request->flags, request->interfaceIndex, params.protocols, params.hostname, request->process_id,
4535 request->pid_name);
4536
4537 mDNSPlatformMemZero(&request->u.addrinfo, (mDNSu32)sizeof(request->u.addrinfo));
4538 request->terminate = NULL;
4539
4540 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
4541 if (os_feature_enabled(mDNSResponder, bonjour_privacy))
4542 {
4543 err = _handle_addrinfo_request_with_trust(request, &params);
4544 }
4545 else
4546 {
4547 err = _handle_addrinfo_request_start(request, &params);
4548 }
4549 #else
4550 err = _handle_addrinfo_request_start(request, &params);
4551 #endif
4552
4553 exit:
4554 return(err);
4555 }
4556
4557 // ***************************************************************************
4558 #if COMPILER_LIKES_PRAGMA_MARK
4559 #pragma mark -
4560 #pragma mark - Main Request Handler etc.
4561 #endif
4562
4563 mDNSlocal request_state *NewRequest(void)
4564 {
4565 request_state *request;
4566 request_state **p = &all_requests;
4567 request = (request_state *) callocL("request_state", sizeof(*request));
4568 if (!request) FatalError("ERROR: calloc");
4569 while (*p) p = &(*p)->next;
4570 *p = request;
4571 return(request);
4572 }
4573
4574 // read_msg may be called any time when the transfer state (req->ts) is t_morecoming.
4575 // if there is no data on the socket, the socket will be closed and t_terminated will be returned
4576 mDNSlocal void read_msg(request_state *req)
4577 {
4578 if (req->ts == t_terminated || req->ts == t_error)
4579 {
4580 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4581 "[R%u] ERROR: read_msg called with transfer state terminated or error", req->request_id);
4582 req->ts = t_error;
4583 return;
4584 }
4585
4586 if (req->ts == t_complete) // this must be death or something is wrong
4587 {
4588 char buf[4]; // dummy for death notification
4589 int nread = udsSupportReadFD(req->sd, buf, 4, 0, req->platform_data);
4590 if (!nread) { req->ts = t_terminated; return; }
4591 if (nread < 0) goto rerror;
4592 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4593 "[R%u] ERROR: read data from a completed request", req->request_id);
4594 req->ts = t_error;
4595 return;
4596 }
4597
4598 if (req->ts != t_morecoming)
4599 {
4600 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4601 "[R%u] ERROR: read_msg called with invalid transfer state (%d)", req->request_id, req->ts);
4602 req->ts = t_error;
4603 return;
4604 }
4605
4606 if (req->hdr_bytes < sizeof(ipc_msg_hdr))
4607 {
4608 mDNSu32 nleft = sizeof(ipc_msg_hdr) - req->hdr_bytes;
4609 int nread = udsSupportReadFD(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0, req->platform_data);
4610 if (nread == 0) { req->ts = t_terminated; return; }
4611 if (nread < 0) goto rerror;
4612 req->hdr_bytes += nread;
4613 if (req->hdr_bytes > sizeof(ipc_msg_hdr))
4614 {
4615 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4616 "[R%u] ERROR: read_msg - read too many header bytes", req->request_id);
4617 req->ts = t_error;
4618 return;
4619 }
4620
4621 // only read data if header is complete
4622 if (req->hdr_bytes == sizeof(ipc_msg_hdr))
4623 {
4624 ConvertHeaderBytes(&req->hdr);
4625 if (req->hdr.version != VERSION)
4626 {
4627 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4628 "[R%u] ERROR: client version 0x%08X daemon version 0x%08X", req->request_id, req->hdr.version, VERSION);
4629 req->ts = t_error;
4630 return;
4631 }
4632
4633 // Largest conceivable single request is a DNSServiceRegisterRecord() or DNSServiceAddRecord()
4634 // with 64kB of rdata. Adding 1009 byte for a maximal domain name, plus a safety margin
4635 // for other overhead, this means any message above 70kB is definitely bogus.
4636 if (req->hdr.datalen > 70000)
4637 {
4638 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4639 "[R%u] ERROR: read_msg: hdr.datalen %u (0x%X) > 70000", req->request_id, req->hdr.datalen, req->hdr.datalen);
4640 req->ts = t_error;
4641 return;
4642 }
4643 req->msgbuf = (char *) callocL("request_state msgbuf", req->hdr.datalen + MSG_PAD_BYTES);
4644 if (!req->msgbuf) { my_perror("ERROR: calloc"); req->ts = t_error; return; }
4645 req->msgptr = req->msgbuf;
4646 req->msgend = req->msgbuf + req->hdr.datalen;
4647 }
4648 }
4649
4650 // If our header is complete, but we're still needing more body data, then try to read it now
4651 // Note: For cancel_request req->hdr.datalen == 0, but there's no error return socket for cancel_request
4652 // Any time we need to get the error return socket we know we'll have at least one data byte
4653 // (even if only the one-byte empty C string placeholder for the old ctrl_path parameter)
4654 if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes < req->hdr.datalen)
4655 {
4656 mDNSu32 nleft = req->hdr.datalen - req->data_bytes;
4657 ssize_t nread;
4658 #if !defined(_WIN32)
4659 struct iovec vec = { req->msgbuf + req->data_bytes, nleft }; // Tell recvmsg where we want the bytes put
4660 struct msghdr msg;
4661 struct cmsghdr *cmsg;
4662 char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
4663 msg.msg_name = 0;
4664 msg.msg_namelen = 0;
4665 msg.msg_iov = &vec;
4666 msg.msg_iovlen = 1;
4667 msg.msg_control = cbuf;
4668 msg.msg_controllen = sizeof(cbuf);
4669 msg.msg_flags = 0;
4670 nread = recvmsg(req->sd, &msg, 0);
4671 #else
4672 nread = udsSupportReadFD(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0, req->platform_data);
4673 #endif
4674 if (nread == 0) { req->ts = t_terminated; return; }
4675 if (nread < 0) goto rerror;
4676 req->data_bytes += nread;
4677 if (req->data_bytes > req->hdr.datalen)
4678 {
4679 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4680 "[R%u] ERROR: read_msg - read too many data bytes", req->request_id);
4681 req->ts = t_error;
4682 return;
4683 }
4684 #if !defined(_WIN32)
4685 cmsg = CMSG_FIRSTHDR(&msg);
4686 #if DEBUG_64BIT_SCM_RIGHTS
4687 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
4688 "[R%u] Expecting %d %d %d %d", req->request_id, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS);
4689 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
4690 "[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);
4691 #endif // DEBUG_64BIT_SCM_RIGHTS
4692 if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
4693 {
4694 #if APPLE_OSX_mDNSResponder
4695 // Strictly speaking BPF_fd belongs solely in the platform support layer, but because
4696 // of privilege separation on Mac OS X we need to get BPF_fd from mDNSResponderHelper,
4697 // and it's convenient to repurpose the existing fd-passing code here for that task
4698 if (req->hdr.op == send_bpf)
4699 {
4700 dnssd_sock_t x = *(dnssd_sock_t *)CMSG_DATA(cmsg);
4701 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
4702 "[R%u] Got len %d, BPF %d", req->request_id, cmsg->cmsg_len, x);
4703 mDNSPlatformReceiveBPF_fd(x);
4704 }
4705 else
4706 #endif // APPLE_OSX_mDNSResponder
4707 req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
4708 #if DEBUG_64BIT_SCM_RIGHTS
4709 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
4710 "[R%u] read req->errsd %d", req->request_id, req->errsd);
4711 #endif // DEBUG_64BIT_SCM_RIGHTS
4712 if (req->data_bytes < req->hdr.datalen)
4713 {
4714 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
4715 "[R%u] Client(PID [%d](" PUB_S ")) sent result code socket %d via SCM_RIGHTS with req->data_bytes %d < req->hdr.datalen %d",
4716 req->request_id, req->process_id, req->pid_name, req->errsd, req->data_bytes, req->hdr.datalen);
4717 req->ts = t_error;
4718 return;
4719 }
4720 }
4721 #endif
4722 }
4723
4724 // If our header and data are both complete, see if we need to make our separate error return socket
4725 if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes == req->hdr.datalen)
4726 {
4727 if (req->terminate && req->hdr.op != cancel_request)
4728 {
4729 dnssd_sockaddr_t cliaddr;
4730 #if defined(USE_TCP_LOOPBACK)
4731 mDNSOpaque16 port;
4732 u_long opt = 1;
4733 port.b[0] = req->msgptr[0];
4734 port.b[1] = req->msgptr[1];
4735 req->msgptr += 2;
4736 cliaddr.sin_family = AF_INET;
4737 cliaddr.sin_port = port.NotAnInteger;
4738 cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
4739 #else
4740 char ctrl_path[MAX_CTLPATH];
4741 get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH); // path is first element in message buffer
4742 mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr));
4743 cliaddr.sun_family = AF_LOCAL;
4744 mDNSPlatformStrLCopy(cliaddr.sun_path, ctrl_path, sizeof(cliaddr.sun_path));
4745 // If the error return path UDS name is empty string, that tells us
4746 // that this is a new version of the library that's going to pass us
4747 // the error return path socket via sendmsg/recvmsg
4748 if (ctrl_path[0] == 0)
4749 {
4750 if (req->errsd == req->sd)
4751 {
4752 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4753 "[R%u] read_msg: ERROR failed to get errsd via SCM_RIGHTS", req->request_id);
4754 req->ts = t_error;
4755 return;
4756 }
4757 goto got_errfd;
4758 }
4759 #endif
4760
4761 req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0);
4762 if (!dnssd_SocketValid(req->errsd))
4763 {
4764 my_throttled_perror("ERROR: socket");
4765 req->ts = t_error;
4766 return;
4767 }
4768
4769 if (connect(req->errsd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
4770 {
4771 #if !defined(USE_TCP_LOOPBACK)
4772 struct stat sb;
4773 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4774 "[R%u] read_msg: Couldn't connect to error return path socket " PUB_S " errno %d (" PUB_S ")",
4775 req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
4776 if (stat(cliaddr.sun_path, &sb) < 0)
4777 {
4778 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4779 "[R%u] read_msg: stat failed " PUB_S " errno %d (" PUB_S ")",
4780 req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
4781 }
4782 else
4783 {
4784 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4785 "[R%u] read_msg: file " PUB_S " mode %o (octal) uid %d gid %d",
4786 req->request_id, cliaddr.sun_path, sb.st_mode, sb.st_uid, sb.st_gid);
4787 }
4788 #endif
4789 req->ts = t_error;
4790 return;
4791 }
4792
4793 #if !defined(USE_TCP_LOOPBACK)
4794 got_errfd:
4795 #endif
4796
4797 #if defined(_WIN32)
4798 if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0)
4799 #else
4800 if (fcntl(req->errsd, F_SETFL, fcntl(req->errsd, F_GETFL, 0) | O_NONBLOCK) != 0)
4801 #endif
4802 {
4803 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4804 "[R%u] ERROR: could not set control socket to non-blocking mode errno %d (" PUB_S ")",
4805 req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
4806 req->ts = t_error;
4807 return;
4808 }
4809 }
4810
4811 req->ts = t_complete;
4812 }
4813
4814 return;
4815
4816 rerror:
4817 if (dnssd_errno == dnssd_EWOULDBLOCK || dnssd_errno == dnssd_EINTR) return;
4818 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
4819 "[R%u] ERROR: read_msg errno %d (" PUB_S ")", req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
4820 req->ts = t_error;
4821 }
4822
4823 mDNSlocal mStatus handle_client_request(request_state *req)
4824 {
4825 mStatus err = mStatus_NoError;
4826 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
4827 SetupAuditTokenForRequest(req);
4828 #endif
4829 switch(req->hdr.op)
4830 {
4831 // These are all operations that have their own first-class request_state object
4832 case connection_request:
4833 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4834 "[R%d] DNSServiceCreateConnection START PID[%d](" PUB_S ")",
4835 req->request_id, req->process_id, req->pid_name);
4836 req->terminate = connection_termination;
4837 break;
4838 case connection_delegate_request:
4839 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
4840 "[R%d] DNSServiceCreateDelegateConnection START PID[%d](" PRI_S ")",
4841 req->request_id, req->process_id, req->pid_name);
4842 req->terminate = connection_termination;
4843 handle_connection_delegate_request(req);
4844 break;
4845 case resolve_request: err = handle_resolve_request (req); break;
4846 case query_request: err = handle_queryrecord_request (req); break;
4847 case browse_request: err = handle_browse_request (req); break;
4848 case reg_service_request: err = handle_regservice_request (req); break;
4849 case enumeration_request: err = handle_enum_request (req); break;
4850 case reconfirm_record_request: err = handle_reconfirm_request (req); break;
4851 case setdomain_request: err = handle_setdomain_request (req); break;
4852 case getproperty_request: handle_getproperty_request (req); break;
4853 case port_mapping_request: err = handle_port_mapping_request(req); break;
4854 case addrinfo_request: err = handle_addrinfo_request (req); break;
4855 case send_bpf: /* Do nothing for send_bpf */ break;
4856
4857 // These are all operations that work with an existing request_state object
4858 case reg_record_request: err = handle_regrecord_request (req); break;
4859 case add_record_request: err = handle_add_request (req); break;
4860 case update_record_request: err = handle_update_request (req); break;
4861 case remove_record_request: err = handle_removerecord_request(req); break;
4862 case cancel_request: handle_cancel_request (req); break;
4863 case release_request: err = handle_release_request (req); break;
4864 default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]",
4865 req->sd, req->hdr.op, req->process_id, req->pid_name);
4866 err = mStatus_BadParamErr;
4867 break;
4868 }
4869
4870 return err;
4871 }
4872
4873 #define RecordOrientedOp(X) \
4874 ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request)
4875
4876 // The lightweight operations are the ones that don't need a dedicated request_state structure allocated for them
4877 #define LightweightOp(X) (RecordOrientedOp(X) || (X) == cancel_request)
4878
4879 mDNSlocal void request_callback(int fd, void *info)
4880 {
4881 mStatus err = 0;
4882 request_state *req = info;
4883 mDNSs32 min_size = sizeof(DNSServiceFlags);
4884 (void)fd; // Unused
4885
4886 for (;;)
4887 {
4888 read_msg(req);
4889 if (req->ts == t_morecoming)
4890 return;
4891 if (req->ts == t_terminated || req->ts == t_error)
4892 {
4893 AbortUnlinkAndFree(req);
4894 return;
4895 }
4896 if (req->ts != t_complete)
4897 {
4898 LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name);
4899 AbortUnlinkAndFree(req);
4900 return;
4901 }
4902
4903 switch(req->hdr.op) // Interface + other data
4904 {
4905 case connection_request: min_size = 0; break;
4906 case connection_delegate_request: min_size = 4; /* pid */ break;
4907 case reg_service_request: min_size += sizeof(mDNSu32) + 4 /* name, type, domain, host */ + 4 /* port, textlen */; break;
4908 case add_record_request: min_size += 4 /* type, rdlen */ + 4 /* ttl */; break;
4909 case update_record_request: min_size += 2 /* rdlen */ + 4 /* ttl */; break;
4910 case remove_record_request: break;
4911 case browse_request: min_size += sizeof(mDNSu32) + 2 /* type, domain */; break;
4912 case resolve_request: min_size += sizeof(mDNSu32) + 3 /* type, type, domain */; break;
4913 case query_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 4 /* type, class*/; break;
4914 case enumeration_request: min_size += sizeof(mDNSu32); break;
4915 case reg_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */ + 4 /* ttl */; break;
4916 case reconfirm_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */; break;
4917 case setdomain_request: min_size += 1 /* domain */; break;
4918 case getproperty_request: min_size = 2; break;
4919 case port_mapping_request: min_size += sizeof(mDNSu32) + 4 /* udp/tcp */ + 4 /* int/ext port */ + 4 /* ttl */; break;
4920 case addrinfo_request: min_size += sizeof(mDNSu32) + 4 /* v4/v6 */ + 1 /* hostname */; break;
4921 case send_bpf: // Same as cancel_request below
4922 case cancel_request: min_size = 0; break;
4923 case release_request: min_size += sizeof(mDNSu32) + 3 /* type, type, domain */; break;
4924 default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]",
4925 req->hdr.op, req->process_id, req->pid_name);
4926 min_size = -1; break;
4927 }
4928
4929 if ((mDNSs32)req->data_bytes < min_size)
4930 {
4931 LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]",
4932 req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name);
4933 AbortUnlinkAndFree(req);
4934 return;
4935 }
4936 if (LightweightOp(req->hdr.op) && !req->terminate)
4937 {
4938 LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]",
4939 req->hdr.op, req->process_id, req->pid_name);
4940 AbortUnlinkAndFree(req);
4941 return;
4942 }
4943
4944 // If req->terminate is already set, this means this operation is sharing an existing connection
4945 if (req->terminate && !LightweightOp(req->hdr.op))
4946 {
4947 request_state *newreq = NewRequest();
4948 newreq->primary = req;
4949 newreq->sd = req->sd;
4950 newreq->errsd = req->errsd;
4951 newreq->uid = req->uid;
4952 newreq->hdr = req->hdr;
4953 newreq->msgbuf = req->msgbuf;
4954 newreq->msgptr = req->msgptr;
4955 newreq->msgend = req->msgend;
4956 newreq->request_id = GetNewRequestID();
4957 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
4958 newreq->audit_token = req->audit_token;
4959 #endif
4960 // if the parent request is a delegate connection, copy the
4961 // relevant bits
4962 if (req->validUUID)
4963 {
4964 newreq->validUUID = mDNStrue;
4965 mDNSPlatformMemCopy(newreq->uuid, req->uuid, UUID_SIZE);
4966 }
4967 else
4968 {
4969 if (req->process_id)
4970 {
4971 newreq->process_id = req->process_id;
4972 mDNSPlatformStrLCopy(newreq->pid_name, req->pid_name, (mDNSu32)sizeof(newreq->pid_name));
4973 }
4974 else
4975 {
4976 set_peer_pid(newreq);
4977 }
4978 }
4979 req = newreq;
4980 }
4981
4982 // Check if the request wants no asynchronous replies.
4983 if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = 1;
4984
4985 // If we're shutting down, don't allow new client requests
4986 // We do allow "cancel" and "getproperty" during shutdown
4987 if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
4988 err = mStatus_ServiceNotRunning;
4989 else
4990 err = handle_client_request(req);
4991
4992 // req->msgbuf may be NULL, e.g. for connection_request or remove_record_request
4993 if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
4994
4995 // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
4996 // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
4997 if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request && req->hdr.op != send_bpf && req->hdr.op != getpid_request)
4998 {
4999 const mStatus err_netorder = dnssd_htonl(err);
5000 send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder));
5001 if (req->errsd != req->sd)
5002 {
5003 dnssd_close(req->errsd);
5004 req->errsd = req->sd;
5005 // Also need to reset the parent's errsd, if this is a subordinate operation
5006 if (req->primary) req->primary->errsd = req->primary->sd;
5007 }
5008 }
5009
5010 // Reset ready to accept the next req on this pipe
5011 if (req->primary) req = req->primary;
5012 req->ts = t_morecoming;
5013 req->hdr_bytes = 0;
5014 req->data_bytes = 0;
5015 req->msgbuf = mDNSNULL;
5016 req->msgptr = mDNSNULL;
5017 req->msgend = 0;
5018 }
5019 }
5020
5021 mDNSlocal void connect_callback(int fd, void *info)
5022 {
5023 dnssd_sockaddr_t cliaddr;
5024 dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
5025 dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
5026 #if defined(SO_NOSIGPIPE) || defined(_WIN32)
5027 unsigned long optval = 1;
5028 #endif
5029
5030 (void)info; // Unused
5031
5032 if (!dnssd_SocketValid(sd))
5033 {
5034 if (dnssd_errno != dnssd_EWOULDBLOCK)
5035 my_throttled_perror("ERROR: accept");
5036 return;
5037 }
5038
5039 #ifdef SO_NOSIGPIPE
5040 // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
5041 if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
5042 LogMsg("%3d: WARNING: setsockopt - SO_NOSIGPIPE %d (%s)", sd, dnssd_errno, dnssd_strerror(dnssd_errno));
5043 #endif
5044
5045 #if defined(_WIN32)
5046 if (ioctlsocket(sd, FIONBIO, &optval) != 0)
5047 #else
5048 if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK) != 0)
5049 #endif
5050 {
5051 my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
5052 dnssd_close(sd);
5053 return;
5054 }
5055 else
5056 {
5057 request_state *request = NewRequest();
5058 request->ts = t_morecoming;
5059 request->sd = sd;
5060 request->errsd = sd;
5061 request->request_id = GetNewRequestID();
5062 set_peer_pid(request);
5063 #if APPLE_OSX_mDNSResponder
5064 struct xucred x;
5065 socklen_t xucredlen = sizeof(x);
5066 if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION)
5067 request->uid = x.cr_uid; // save the effective userid of the client
5068 else
5069 my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
5070 debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
5071 #endif // APPLE_OSX_mDNSResponder
5072 LogDebug("%3d: connect_callback: Adding FD for uid %u", request->sd, request->uid);
5073 udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data);
5074 }
5075 }
5076
5077 mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
5078 {
5079 #if defined(SO_NP_EXTENSIONS)
5080 struct so_np_extensions sonpx;
5081 socklen_t optlen = sizeof(struct so_np_extensions);
5082 sonpx.npx_flags = SONPX_SETOPTSHUT;
5083 sonpx.npx_mask = SONPX_SETOPTSHUT;
5084 if (setsockopt(skt, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, optlen) < 0)
5085 my_perror("WARNING: could not set sockopt - SO_NP_EXTENSIONS");
5086 #endif
5087 #if defined(_WIN32)
5088 // SEH: do we even need to do this on windows?
5089 // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
5090 u_long opt = 1;
5091 if (ioctlsocket(skt, FIONBIO, &opt) != 0)
5092 #else
5093 if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) != 0)
5094 #endif
5095 {
5096 my_perror("ERROR: could not set listen socket to non-blocking mode");
5097 return mDNSfalse;
5098 }
5099
5100 if (listen(skt, LISTENQ) != 0)
5101 {
5102 my_perror("ERROR: could not listen on listen socket");
5103 return mDNSfalse;
5104 }
5105
5106 if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL, (void **) NULL))
5107 {
5108 my_perror("ERROR: could not add listen socket to event loop");
5109 return mDNSfalse;
5110 }
5111 else
5112 {
5113 LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
5114 mDNSStorage.uds_listener_skt = skt;
5115 }
5116 return mDNStrue;
5117 }
5118
5119 #if MDNS_MALLOC_DEBUGGING
5120 mDNSlocal void udsserver_validatelists(void *context);
5121 #endif
5122
5123 mDNSexport int udsserver_init(dnssd_sock_t skts[], const size_t count)
5124 {
5125 dnssd_sockaddr_t laddr;
5126 int ret;
5127
5128 #ifndef NO_PID_FILE
5129 FILE *fp = fopen(PID_FILE, "w");
5130 if (fp != NULL)
5131 {
5132 fprintf(fp, "%d\n", getpid());
5133 fclose(fp);
5134 }
5135 #endif
5136
5137 #if MDNS_MALLOC_DEBUGGING
5138 static mDNSListValidator validator;
5139 mDNSPlatformAddListValidator(&validator, udsserver_validatelists, "udsserver_validatelists", NULL);
5140 #endif
5141
5142 if (skts)
5143 {
5144 size_t i;
5145 for (i = 0; i < count; i++)
5146 if (dnssd_SocketValid(skts[i]) && !uds_socket_setup(skts[i]))
5147 goto error;
5148 }
5149 else
5150 {
5151 listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
5152 if (!dnssd_SocketValid(listenfd))
5153 {
5154 my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
5155 goto error;
5156 }
5157
5158 mDNSPlatformMemZero(&laddr, sizeof(laddr));
5159
5160 #if defined(USE_TCP_LOOPBACK)
5161 {
5162 laddr.sin_family = AF_INET;
5163 laddr.sin_port = htons(MDNS_TCP_SERVERPORT);
5164 laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
5165 ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
5166 if (ret < 0)
5167 {
5168 my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
5169 goto error;
5170 }
5171 }
5172 #else
5173 {
5174 mode_t mask = umask(0);
5175 unlink(boundPath); // OK if this fails
5176 laddr.sun_family = AF_LOCAL;
5177 #ifndef NOT_HAVE_SA_LEN
5178 // According to Stevens (section 3.2), there is no portable way to
5179 // determine whether sa_len is defined on a particular platform.
5180 laddr.sun_len = sizeof(struct sockaddr_un);
5181 #endif
5182 if (strlen(boundPath) >= sizeof(laddr.sun_path))
5183 {
5184 LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
5185 goto error;
5186 }
5187 mDNSPlatformStrLCopy(laddr.sun_path, boundPath, sizeof(laddr.sun_path));
5188 ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
5189 umask(mask);
5190 if (ret < 0)
5191 {
5192 my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
5193 goto error;
5194 }
5195 }
5196 #endif
5197
5198 if (!uds_socket_setup(listenfd)) goto error;
5199 }
5200
5201 #if !defined(PLATFORM_NO_RLIMIT)
5202 {
5203 // Set maximum number of open file descriptors
5204 #define MIN_OPENFILES 10240
5205 struct rlimit maxfds, newfds;
5206
5207 // Due to bugs in OS X (<rdar://problem/2941095>, <rdar://problem/3342704>, <rdar://problem/3839173>)
5208 // you have to get and set rlimits once before getrlimit will return sensible values
5209 if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
5210 if (setrlimit(RLIMIT_NOFILE, &maxfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
5211
5212 if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
5213 newfds.rlim_max = (maxfds.rlim_max > MIN_OPENFILES) ? maxfds.rlim_max : MIN_OPENFILES;
5214 newfds.rlim_cur = (maxfds.rlim_cur > MIN_OPENFILES) ? maxfds.rlim_cur : MIN_OPENFILES;
5215 if (newfds.rlim_max != maxfds.rlim_max || newfds.rlim_cur != maxfds.rlim_cur)
5216 if (setrlimit(RLIMIT_NOFILE, &newfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
5217
5218 if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
5219 debugf("maxfds.rlim_max %d", (long)maxfds.rlim_max);
5220 debugf("maxfds.rlim_cur %d", (long)maxfds.rlim_cur);
5221 }
5222 #endif
5223
5224 // We start a "LocalOnly" query looking for Automatic Browse Domain records.
5225 // When Domain Enumeration in uDNS.c finds an "lb" record from the network, its "FoundDomain" routine
5226 // creates a "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
5227 mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ, mDNS_DomainTypeBrowseAutomatic,
5228 mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL);
5229
5230 // Add "local" as recommended registration domain ("dns-sd -E"), recommended browsing domain ("dns-sd -F"), and automatic browsing domain
5231 RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration);
5232 RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse);
5233 AddAutoBrowseDomain(0, &localdomain);
5234
5235 udsserver_handle_configchange(&mDNSStorage);
5236 return 0;
5237
5238 error:
5239
5240 my_perror("ERROR: udsserver_init");
5241 return -1;
5242 }
5243
5244 mDNSexport int udsserver_exit(void)
5245 {
5246 // Cancel all outstanding client requests
5247 while (all_requests) AbortUnlinkAndFree(all_requests);
5248
5249 // Clean up any special mDNSInterface_LocalOnly records we created, both the entries for "local" we
5250 // created in udsserver_init, and others we created as a result of reading local configuration data
5251 while (LocalDomainEnumRecords)
5252 {
5253 ARListElem *rem = LocalDomainEnumRecords;
5254 LocalDomainEnumRecords = LocalDomainEnumRecords->next;
5255 mDNS_Deregister(&mDNSStorage, &rem->ar);
5256 }
5257
5258 // If the launching environment created no listening socket,
5259 // that means we created it ourselves, so we should clean it up on exit
5260 if (dnssd_SocketValid(listenfd))
5261 {
5262 dnssd_close(listenfd);
5263 #if !defined(USE_TCP_LOOPBACK)
5264 // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
5265 // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
5266 // It would be nice if we could find a solution to this problem
5267 if (unlink(boundPath))
5268 debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
5269 #endif
5270 }
5271
5272 #ifndef NO_PID_FILE
5273 unlink(PID_FILE);
5274 #endif
5275
5276 return 0;
5277 }
5278
5279 mDNSlocal void LogClientInfoToFD(int fd, request_state *req)
5280 {
5281 char reqIDStr[14];
5282 char prefix[18];
5283
5284 mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
5285
5286 mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
5287
5288 if (!req->terminate)
5289 LogToFD(fd, "%s No operation yet on this socket", prefix);
5290 else if (req->terminate == connection_termination)
5291 {
5292 int num_records = 0, num_ops = 0;
5293 const registered_record_entry *p;
5294 request_state *r;
5295 for (p = req->u.reg_recs; p; p=p->next) num_records++;
5296 for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
5297 LogToFD(fd, "%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
5298 prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "",
5299 req->process_id, req->pid_name);
5300 for (p = req->u.reg_recs; p; p=p->next)
5301 LogToFD(fd, " -> DNSServiceRegisterRecord 0x%08X %2d %3d %s PID[%d](%s)",
5302 req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
5303 for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfoToFD(fd, r);
5304 }
5305 else if (req->terminate == regservice_termination_callback)
5306 {
5307 service_instance *ptr;
5308 for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
5309 LogToFD(fd, "%-9s DNSServiceRegister 0x%08X %2d %##s %u/%u PID[%d](%s)",
5310 (ptr == req->u.servicereg.instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
5311 mDNSVal16(req->u.servicereg.port),
5312 SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
5313 }
5314 else if (req->terminate == browse_termination_callback)
5315 {
5316 browser_t *blist;
5317 for (blist = req->u.browser.browsers; blist; blist = blist->next)
5318 LogToFD(fd, "%-9s DNSServiceBrowse 0x%08X %2d %##s PID[%d](%s)",
5319 (blist == req->u.browser.browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
5320 req->process_id, req->pid_name);
5321 }
5322 else if (req->terminate == resolve_termination_callback)
5323 LogToFD(fd, "%s DNSServiceResolve 0x%08X %2d %##s PID[%d](%s)",
5324 prefix, req->flags, req->interfaceIndex, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name);
5325 else if (req->terminate == queryrecord_termination_callback)
5326 LogToFD(fd, "%s DNSServiceQueryRecord 0x%08X %2d %##s (%s) PID[%d](%s)",
5327 prefix, req->flags, req->interfaceIndex, QueryRecordClientRequestGetQName(&req->u.queryrecord), DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)), req->process_id, req->pid_name);
5328 else if (req->terminate == enum_termination_callback)
5329 LogToFD(fd, "%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
5330 prefix, req->flags, req->interfaceIndex, req->u.enumeration.q_all.qname.c, req->process_id, req->pid_name);
5331 else if (req->terminate == port_mapping_termination_callback)
5332 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)",
5333 prefix,
5334 req->flags,
5335 req->interfaceIndex,
5336 req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : " ",
5337 req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : " ",
5338 mDNSVal16(req->u.pm.NATinfo.IntPort),
5339 mDNSVal16(req->u.pm.ReqExt),
5340 &req->u.pm.NATinfo.ExternalAddress,
5341 mDNSVal16(req->u.pm.NATinfo.ExternalPort),
5342 req->u.pm.NATinfo.NATLease,
5343 req->u.pm.NATinfo.Lifetime,
5344 req->process_id, req->pid_name);
5345 else if (req->terminate == addrinfo_termination_callback)
5346 LogToFD(fd, "%s DNSServiceGetAddrInfo 0x%08X %2d %s%s %##s PID[%d](%s)",
5347 prefix, req->flags, req->interfaceIndex,
5348 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : " ",
5349 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : " ",
5350 GetAddrInfoClientRequestGetQName(&req->u.addrinfo), req->process_id, req->pid_name);
5351 else
5352 LogToFD(fd, "%s Unrecognized operation %p", prefix, req->terminate);
5353 }
5354
5355 mDNSlocal void LogClientInfo(request_state *req)
5356 {
5357 char reqIDStr[14];
5358 char prefix[18];
5359
5360 mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
5361
5362 mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
5363
5364 if (!req->terminate)
5365 LogMsgNoIdent("%s No operation yet on this socket", prefix);
5366 else if (req->terminate == connection_termination)
5367 {
5368 int num_records = 0, num_ops = 0;
5369 const registered_record_entry *p;
5370 request_state *r;
5371 for (p = req->u.reg_recs; p; p=p->next) num_records++;
5372 for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
5373 LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
5374 prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "",
5375 req->process_id, req->pid_name);
5376 for (p = req->u.reg_recs; p; p=p->next)
5377 LogMsgNoIdent(" -> DNSServiceRegisterRecord 0x%08X %2d %3d %s PID[%d](%s)",
5378 req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
5379 for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(r);
5380 }
5381 else if (req->terminate == regservice_termination_callback)
5382 {
5383 service_instance *ptr;
5384 for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
5385 LogMsgNoIdent("%-9s DNSServiceRegister 0x%08X %2d %##s %u/%u PID[%d](%s)",
5386 (ptr == req->u.servicereg.instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
5387 mDNSVal16(req->u.servicereg.port),
5388 SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
5389 }
5390 else if (req->terminate == browse_termination_callback)
5391 {
5392 browser_t *blist;
5393 for (blist = req->u.browser.browsers; blist; blist = blist->next)
5394 LogMsgNoIdent("%-9s DNSServiceBrowse 0x%08X %2d %##s PID[%d](%s)",
5395 (blist == req->u.browser.browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
5396 req->process_id, req->pid_name);
5397 }
5398 else if (req->terminate == resolve_termination_callback)
5399 LogMsgNoIdent("%s DNSServiceResolve 0x%08X %2d %##s PID[%d](%s)",
5400 prefix, req->flags, req->interfaceIndex, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name);
5401 else if (req->terminate == queryrecord_termination_callback)
5402 LogMsgNoIdent("%s DNSServiceQueryRecord 0x%08X %2d %##s (%s) PID[%d](%s)",
5403 prefix, req->flags, req->interfaceIndex, QueryRecordClientRequestGetQName(&req->u.queryrecord), DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)), req->process_id, req->pid_name);
5404 else if (req->terminate == enum_termination_callback)
5405 LogMsgNoIdent("%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
5406 prefix, req->flags, req->interfaceIndex, req->u.enumeration.q_all.qname.c, req->process_id, req->pid_name);
5407 else if (req->terminate == port_mapping_termination_callback)
5408 LogMsgNoIdent("%s DNSServiceNATPortMapping 0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)",
5409 prefix,
5410 req->flags,
5411 req->interfaceIndex,
5412 req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : " ",
5413 req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : " ",
5414 mDNSVal16(req->u.pm.NATinfo.IntPort),
5415 mDNSVal16(req->u.pm.ReqExt),
5416 &req->u.pm.NATinfo.ExternalAddress,
5417 mDNSVal16(req->u.pm.NATinfo.ExternalPort),
5418 req->u.pm.NATinfo.NATLease,
5419 req->u.pm.NATinfo.Lifetime,
5420 req->process_id, req->pid_name);
5421 else if (req->terminate == addrinfo_termination_callback)
5422 LogMsgNoIdent("%s DNSServiceGetAddrInfo 0x%08X %2d %s%s %##s PID[%d](%s)",
5423 prefix, req->flags, req->interfaceIndex,
5424 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : " ",
5425 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : " ",
5426 GetAddrInfoClientRequestGetQName(&req->u.addrinfo), req->process_id, req->pid_name);
5427 else
5428 LogMsgNoIdent("%s Unrecognized operation %p", prefix, req->terminate);
5429 }
5430
5431 mDNSlocal void GetMcastClients(request_state *req)
5432 {
5433 if (req->terminate == connection_termination)
5434 {
5435 int num_records = 0, num_ops = 0;
5436 const registered_record_entry *p;
5437 request_state *r;
5438 for (p = req->u.reg_recs; p; p=p->next)
5439 num_records++;
5440 for (r = req->next; r; r=r->next)
5441 if (r->primary == req)
5442 num_ops++;
5443 for (p = req->u.reg_recs; p; p=p->next)
5444 {
5445 if (!AuthRecord_uDNS(p->rr))
5446 n_mrecords++;
5447 }
5448 for (r = req->next; r; r=r->next)
5449 if (r->primary == req)
5450 GetMcastClients(r);
5451 }
5452 else if (req->terminate == regservice_termination_callback)
5453 {
5454 service_instance *ptr;
5455 for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
5456 {
5457 if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
5458 n_mrecords++;
5459 }
5460 }
5461 else if (req->terminate == browse_termination_callback)
5462 {
5463 browser_t *blist;
5464 for (blist = req->u.browser.browsers; blist; blist = blist->next)
5465 {
5466 if (mDNSOpaque16IsZero(blist->q.TargetQID))
5467 n_mquests++;
5468 }
5469 }
5470 else if (req->terminate == resolve_termination_callback)
5471 {
5472 if ((mDNSOpaque16IsZero(req->u.resolve.qsrv.TargetQID)) && (req->u.resolve.qsrv.ThisQInterval > 0))
5473 n_mquests++;
5474 }
5475 else if (req->terminate == queryrecord_termination_callback)
5476 {
5477 if (QueryRecordClientRequestIsMulticast(&req->u.queryrecord))
5478 n_mquests++;
5479 }
5480 else if (req->terminate == addrinfo_termination_callback)
5481 {
5482 if (GetAddrInfoClientRequestIsMulticast(&req->u.addrinfo))
5483 n_mquests++;
5484 }
5485 else
5486 {
5487 return;
5488 }
5489 }
5490
5491
5492 mDNSlocal void LogMcastClientInfo(request_state *req)
5493 {
5494 if (!req->terminate)
5495 LogMcastNoIdent("No operation yet on this socket");
5496 else if (req->terminate == connection_termination)
5497 {
5498 int num_records = 0, num_ops = 0;
5499 const registered_record_entry *p;
5500 request_state *r;
5501 for (p = req->u.reg_recs; p; p=p->next)
5502 num_records++;
5503 for (r = req->next; r; r=r->next)
5504 if (r->primary == req)
5505 num_ops++;
5506 for (p = req->u.reg_recs; p; p=p->next)
5507 {
5508 if (!AuthRecord_uDNS(p->rr))
5509 LogMcastNoIdent("R: -> DNSServiceRegisterRecord: %##s %s PID[%d](%s)", p->rr->resrec.name->c,
5510 DNSTypeName(p->rr->resrec.rrtype), req->process_id, req->pid_name, i_mcount++);
5511 }
5512 for (r = req->next; r; r=r->next)
5513 if (r->primary == req)
5514 LogMcastClientInfo(r);
5515 }
5516 else if (req->terminate == regservice_termination_callback)
5517 {
5518 service_instance *ptr;
5519 for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
5520 {
5521 if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
5522 LogMcastNoIdent("R: DNSServiceRegister: %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port),
5523 SRS_PORT(&ptr->srs), req->process_id, req->pid_name, i_mcount++);
5524 }
5525 }
5526 else if (req->terminate == browse_termination_callback)
5527 {
5528 browser_t *blist;
5529 for (blist = req->u.browser.browsers; blist; blist = blist->next)
5530 {
5531 if (mDNSOpaque16IsZero(blist->q.TargetQID))
5532 LogMcastNoIdent("Q: DNSServiceBrowse %##s %s PID[%d](%s)", blist->q.qname.c, DNSTypeName(blist->q.qtype),
5533 req->process_id, req->pid_name, i_mcount++);
5534 }
5535 }
5536 else if (req->terminate == resolve_termination_callback)
5537 {
5538 if ((mDNSOpaque16IsZero(req->u.resolve.qsrv.TargetQID)) && (req->u.resolve.qsrv.ThisQInterval > 0))
5539 LogMcastNoIdent("Q: DNSServiceResolve %##s %s PID[%d](%s)", req->u.resolve.qsrv.qname.c, DNSTypeName(req->u.resolve.qsrv.qtype),
5540 req->process_id, req->pid_name, i_mcount++);
5541 }
5542 else if (req->terminate == queryrecord_termination_callback)
5543 {
5544 if (QueryRecordClientRequestIsMulticast(&req->u.queryrecord))
5545 {
5546 LogMcastNoIdent("Q: DNSServiceQueryRecord %##s %s PID[%d](%s)",
5547 QueryRecordClientRequestGetQName(&req->u.queryrecord),
5548 DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)),
5549 req->process_id, req->pid_name, i_mcount++);
5550 }
5551 }
5552 else if (req->terminate == addrinfo_termination_callback)
5553 {
5554 if (GetAddrInfoClientRequestIsMulticast(&req->u.addrinfo))
5555 {
5556 LogMcastNoIdent("Q: DNSServiceGetAddrInfo %s%s %##s PID[%d](%s)",
5557 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : " ",
5558 req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : " ",
5559 GetAddrInfoClientRequestGetQName(&req->u.addrinfo), req->process_id, req->pid_name, i_mcount++);
5560 }
5561 }
5562 }
5563
5564 mDNSlocal char *RecordTypeName(mDNSu8 rtype)
5565 {
5566 switch (rtype)
5567 {
5568 case kDNSRecordTypeUnregistered: return ("Unregistered ");
5569 case kDNSRecordTypeDeregistering: return ("Deregistering");
5570 case kDNSRecordTypeUnique: return ("Unique ");
5571 case kDNSRecordTypeAdvisory: return ("Advisory ");
5572 case kDNSRecordTypeShared: return ("Shared ");
5573 case kDNSRecordTypeVerified: return ("Verified ");
5574 case kDNSRecordTypeKnownUnique: return ("KnownUnique ");
5575 default: return("Unknown");
5576 }
5577 }
5578
5579 mDNSlocal int LogEtcHostsToFD(int fd, mDNS *const m)
5580 {
5581 mDNSBool showheader = mDNStrue;
5582 const AuthRecord *ar;
5583 mDNSu32 slot;
5584 AuthGroup *ag;
5585 int count = 0;
5586 int authslot = 0;
5587 mDNSBool truncated = 0;
5588
5589 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
5590 {
5591 if (m->rrauth.rrauth_hash[slot]) authslot++;
5592 for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
5593 for (ar = ag->members; ar; ar = ar->next)
5594 {
5595 if (ar->RecordCallback != FreeEtcHosts) continue;
5596 if (showheader) { showheader = mDNSfalse; LogToFD(fd, " State Interface"); }
5597
5598 // Print a maximum of 50 records
5599 if (count++ >= 50) { truncated = mDNStrue; continue; }
5600 if (ar->ARType == AuthRecordLocalOnly)
5601 {
5602 if (ar->resrec.InterfaceID == mDNSInterface_LocalOnly)
5603 LogToFD(fd, " %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
5604 else
5605 {
5606 mDNSu32 scopeid = (mDNSu32)(uintptr_t)ar->resrec.InterfaceID;
5607 LogToFD(fd, " %s %u %s", RecordTypeName(ar->resrec.RecordType), scopeid, ARDisplayString(m, ar));
5608 }
5609 }
5610 }
5611 }
5612
5613 if (showheader) LogToFD(fd, "<None>");
5614 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);
5615 return count;
5616 }
5617
5618 mDNSlocal void LogLocalOnlyAuthRecordsToFD(int fd, mDNS *const m)
5619 {
5620 mDNSBool showheader = mDNStrue;
5621 const AuthRecord *ar;
5622 mDNSu32 slot;
5623 AuthGroup *ag;
5624
5625 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
5626 {
5627 for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
5628 for (ar = ag->members; ar; ar = ar->next)
5629 {
5630 if (ar->RecordCallback == FreeEtcHosts) continue;
5631 if (showheader) { showheader = mDNSfalse; LogToFD(fd, " State Interface"); }
5632
5633 // Print a maximum of 400 records
5634 if (ar->ARType == AuthRecordLocalOnly)
5635 LogToFD(fd, " %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
5636 else if (ar->ARType == AuthRecordP2P)
5637 {
5638 if (ar->resrec.InterfaceID == mDNSInterface_BLE)
5639 LogToFD(fd, " %s BLE %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
5640 else
5641 LogToFD(fd, " %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
5642 }
5643 }
5644 }
5645
5646 if (showheader) LogToFD(fd, "<None>");
5647 }
5648
5649 mDNSlocal void LogOneAuthRecordToFD(int fd, const AuthRecord *ar, mDNSs32 now, const char *ifname)
5650 {
5651 if (AuthRecord_uDNS(ar))
5652 {
5653 LogToFD(fd, "%7d %7d %7d %-7s %4d %s %s",
5654 ar->ThisAPInterval / mDNSPlatformOneSecond,
5655 (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
5656 ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
5657 "-U-",
5658 ar->state,
5659 ar->AllowRemoteQuery ? "☠" : " ",
5660 ARDisplayString(&mDNSStorage, ar));
5661 }
5662 else
5663 {
5664 LogToFD(fd, "%7d %7d %7d %-7s 0x%02X %s %s",
5665 ar->ThisAPInterval / mDNSPlatformOneSecond,
5666 ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
5667 ar->TimeExpire ? (ar->TimeExpire - now) / mDNSPlatformOneSecond : 0,
5668 ifname ? ifname : "ALL",
5669 ar->resrec.RecordType,
5670 ar->AllowRemoteQuery ? "☠" : " ",
5671 ARDisplayString(&mDNSStorage, ar));
5672 }
5673 }
5674
5675 mDNSlocal void LogAuthRecordsToFD(int fd,
5676 const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
5677 {
5678 mDNSBool showheader = mDNStrue;
5679 const AuthRecord *ar;
5680 OwnerOptData owner = zeroOwner;
5681 for (ar = ResourceRecords; ar; ar=ar->next)
5682 {
5683 const char *const ifname = InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID);
5684 if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
5685 {
5686 if (showheader) { showheader = mDNSfalse; LogToFD(fd, " Int Next Expire if State"); }
5687 if (proxy) (*proxy)++;
5688 if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
5689 {
5690 owner = ar->WakeUp;
5691 if (owner.password.l[0])
5692 LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
5693 else if (!mDNSSameEthAddress(&owner.HMAC, &owner.IMAC))
5694 LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a seq %d", &owner.HMAC, &owner.IMAC, owner.seq);
5695 else
5696 LogToFD(fd, "Proxying for %.6a seq %d", &owner.HMAC, owner.seq);
5697 }
5698 if (AuthRecord_uDNS(ar))
5699 {
5700 LogOneAuthRecordToFD(fd, ar, now, ifname);
5701 }
5702 else if (ar->ARType == AuthRecordLocalOnly)
5703 {
5704 LogToFD(fd, " LO %s", ARDisplayString(&mDNSStorage, ar));
5705 }
5706 else if (ar->ARType == AuthRecordP2P)
5707 {
5708 if (ar->resrec.InterfaceID == mDNSInterface_BLE)
5709 LogToFD(fd, " BLE %s", ARDisplayString(&mDNSStorage, ar));
5710 else
5711 LogToFD(fd, " PP %s", ARDisplayString(&mDNSStorage, ar));
5712 }
5713 else
5714 {
5715 LogOneAuthRecordToFD(fd, ar, now, ifname);
5716 }
5717 }
5718 }
5719 if (showheader) LogToFD(fd, "<None>");
5720 }
5721
5722 mDNSlocal void PrintOneCacheRecordToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
5723 {
5724 LogToFD(fd, "%3d %s%8d %-7s%s %-6s%s",
5725 slot,
5726 cr->CRActiveQuestion ? "*" : " ",
5727 remain,
5728 ifname ? ifname : "-U-",
5729 (cr->resrec.RecordType == kDNSRecordTypePacketNegative) ? "-" :
5730 (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+",
5731 DNSTypeName(cr->resrec.rrtype),
5732 CRDisplayString(&mDNSStorage, cr));
5733 (*CacheUsed)++;
5734 }
5735
5736 mDNSlocal void PrintCachedRecordsToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
5737 {
5738 CacheRecord *soa;
5739
5740 soa = cr->soa;
5741 if (soa)
5742 {
5743 PrintOneCacheRecordToFD(fd, soa, slot, remain, ifname, CacheUsed);
5744 }
5745 }
5746
5747 mDNSexport void LogMDNSStatisticsToFD(int fd, mDNS *const m)
5748 {
5749 LogToFD(fd, "--- MDNS Statistics ---");
5750
5751 LogToFD(fd, "Name Conflicts %u", m->mDNSStats.NameConflicts);
5752 LogToFD(fd, "KnownUnique Name Conflicts %u", m->mDNSStats.KnownUniqueNameConflicts);
5753 LogToFD(fd, "Duplicate Query Suppressions %u", m->mDNSStats.DupQuerySuppressions);
5754 LogToFD(fd, "KA Suppressions %u", m->mDNSStats.KnownAnswerSuppressions);
5755 LogToFD(fd, "KA Multiple Packets %u", m->mDNSStats.KnownAnswerMultiplePkts);
5756 LogToFD(fd, "Poof Cache Deletions %u", m->mDNSStats.PoofCacheDeletions);
5757 LogToFD(fd, "--------------------------------");
5758
5759 LogToFD(fd, "Multicast packets Sent %u", m->MulticastPacketsSent);
5760 LogToFD(fd, "Multicast packets Received %u", m->MPktNum);
5761 LogToFD(fd, "Remote Subnet packets %u", m->RemoteSubnet);
5762 LogToFD(fd, "QU questions received %u", m->mDNSStats.UnicastBitInQueries);
5763 LogToFD(fd, "Normal multicast questions %u", m->mDNSStats.NormalQueries);
5764 LogToFD(fd, "Answers for questions %u", m->mDNSStats.MatchingAnswersForQueries);
5765 LogToFD(fd, "Unicast responses %u", m->mDNSStats.UnicastResponses);
5766 LogToFD(fd, "Multicast responses %u", m->mDNSStats.MulticastResponses);
5767 LogToFD(fd, "Unicast response Demotions %u", m->mDNSStats.UnicastDemotedToMulticast);
5768 LogToFD(fd, "--------------------------------");
5769
5770 LogToFD(fd, "Sleeps %u", m->mDNSStats.Sleeps);
5771 LogToFD(fd, "Wakeups %u", m->mDNSStats.Wakes);
5772 LogToFD(fd, "Interface UP events %u", m->mDNSStats.InterfaceUp);
5773 LogToFD(fd, "Interface UP Flap events %u", m->mDNSStats.InterfaceUpFlap);
5774 LogToFD(fd, "Interface Down events %u", m->mDNSStats.InterfaceDown);
5775 LogToFD(fd, "Interface DownFlap events %u", m->mDNSStats.InterfaceDownFlap);
5776 LogToFD(fd, "Cache refresh queries %u", m->mDNSStats.CacheRefreshQueries);
5777 LogToFD(fd, "Cache refreshed %u", m->mDNSStats.CacheRefreshed);
5778 LogToFD(fd, "Wakeup on Resolves %u", m->mDNSStats.WakeOnResolves);
5779 }
5780
5781 mDNSexport void udsserver_info_dump_to_fd(int fd)
5782 {
5783 mDNS *const m = &mDNSStorage;
5784 const mDNSs32 now = mDNS_TimeNow(m);
5785 mDNSu32 CacheUsed = 0, CacheActive = 0, slot;
5786 int ProxyA = 0, ProxyD = 0;
5787 mDNSu32 groupCount = 0;
5788 mDNSu32 mcastRecordCount = 0;
5789 mDNSu32 ucastRecordCount = 0;
5790 const CacheGroup *cg;
5791 const CacheRecord *cr;
5792 const DNSQuestion *q;
5793 const DNameListElem *d;
5794 const SearchListElem *s;
5795
5796 LogToFD(fd, "------------ Cache -------------");
5797 LogToFD(fd, "Slt Q TTL if U Type rdlen");
5798 for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
5799 {
5800 for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
5801 {
5802 groupCount++; // Count one cache entity for the CacheGroup object
5803 for (cr = cg->members; cr; cr=cr->next)
5804 {
5805 const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
5806 const char *ifname;
5807 mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
5808 mDNSu32 *const countPtr = InterfaceID ? &mcastRecordCount : &ucastRecordCount;
5809 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
5810 if (!InterfaceID && cr->resrec.dnsservice &&
5811 (mdns_dns_service_get_scope(cr->resrec.dnsservice) == mdns_dns_service_scope_interface))
5812 {
5813 InterfaceID = (mDNSInterfaceID)(uintptr_t)mdns_dns_service_get_interface_index(cr->resrec.dnsservice);
5814 }
5815 #else
5816 if (!InterfaceID && cr->resrec.rDNSServer && cr->resrec.rDNSServer->scopeType)
5817 InterfaceID = cr->resrec.rDNSServer->interface;
5818 #endif
5819 ifname = InterfaceNameForID(m, InterfaceID);
5820 if (cr->CRActiveQuestion) CacheActive++;
5821 PrintOneCacheRecordToFD(fd, cr, slot, remain, ifname, countPtr);
5822 PrintCachedRecordsToFD(fd, cr, slot, remain, ifname, countPtr);
5823 }
5824 }
5825 }
5826
5827 CacheUsed = groupCount + mcastRecordCount + ucastRecordCount;
5828 if (m->rrcache_totalused != CacheUsed)
5829 LogToFD(fd, "Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed);
5830 if (m->rrcache_active != CacheActive)
5831 LogToFD(fd, "Cache use mismatch: rrcache_active is %lu, true count %lu", m->rrcache_active, CacheActive);
5832 LogToFD(fd, "Cache size %u entities; %u in use (%u group, %u multicast, %u unicast); %u referenced by active questions",
5833 m->rrcache_size, CacheUsed, groupCount, mcastRecordCount, ucastRecordCount, CacheActive);
5834
5835 LogToFD(fd, "--------- Auth Records ---------");
5836 LogAuthRecordsToFD(fd, now, m->ResourceRecords, mDNSNULL);
5837
5838 LogToFD(fd, "--------- LocalOnly, P2P Auth Records ---------");
5839 LogLocalOnlyAuthRecordsToFD(fd, m);
5840
5841 LogToFD(fd, "--------- /etc/hosts ---------");
5842 LogEtcHostsToFD(fd, m);
5843
5844 LogToFD(fd, "------ Duplicate Records -------");
5845 LogAuthRecordsToFD(fd, now, m->DuplicateRecords, mDNSNULL);
5846
5847 LogToFD(fd, "----- Auth Records Proxied -----");
5848 LogAuthRecordsToFD(fd, now, m->ResourceRecords, &ProxyA);
5849
5850 LogToFD(fd, "-- Duplicate Records Proxied ---");
5851 LogAuthRecordsToFD(fd, now, m->DuplicateRecords, &ProxyD);
5852
5853 LogToFD(fd, "---------- Questions -----------");
5854 if (!m->Questions) LogToFD(fd, "<None>");
5855 else
5856 {
5857 CacheUsed = 0;
5858 CacheActive = 0;
5859 LogToFD(fd, " Int Next if T NumAns VDNS Qptr DupOf SU SQ Type Name");
5860 for (q = m->Questions; q; q=q->next)
5861 {
5862 mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
5863 mDNSs32 n = (NextQSendTime(q) - now) / mDNSPlatformOneSecond;
5864 char *ifname = InterfaceNameForID(m, q->InterfaceID);
5865 CacheUsed++;
5866 if (q->ThisQInterval) CacheActive++;
5867 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
5868 LogToFD(fd, "%6d%6d %-7s%s %5d 0x%p 0x%p %1d %2d %-5s%##s%s",
5869 #else
5870 LogToFD(fd, "%6d%6d %-7s%s %5d 0x%08x%08x%08x%08x 0x%p 0x%p %1d %2d %-5s%##s%s",
5871 #endif
5872 i, n,
5873 ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
5874 mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
5875 q->CurrentAnswers,
5876 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
5877 q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0],
5878 #endif
5879 q, q->DuplicateOf,
5880 q->SuppressUnusable, q->Suppressed, DNSTypeName(q->qtype), q->qname.c,
5881 q->DuplicateOf ? " (dup)" : "");
5882 }
5883 LogToFD(fd, "%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
5884 }
5885
5886 LogToFD(fd, "----- LocalOnly, P2P Questions -----");
5887 if (!m->LocalOnlyQuestions) LogToFD(fd, "<None>");
5888 else for (q = m->LocalOnlyQuestions; q; q=q->next)
5889 LogToFD(fd, " %3s %5d %-6s%##s%s",
5890 q->InterfaceID == mDNSInterface_LocalOnly ? "LO ": q->InterfaceID == mDNSInterface_BLE ? "BLE": "P2P",
5891 q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
5892
5893 LogToFD(fd, "---- Active UDS Client Requests ----");
5894 if (!all_requests) LogToFD(fd, "<None>");
5895 else
5896 {
5897 request_state *req, *r;
5898 for (req = all_requests; req; req=req->next)
5899 {
5900 if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
5901 {
5902 for (r = all_requests; r && r != req; r=r->next) if (r == req->primary) goto foundparent;
5903 LogToFD(fd, "%3d: Orhpan operation %p; parent %p not found in request list", req->sd);
5904 }
5905 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
5906 LogClientInfoToFD(fd, req);
5907 foundparent:;
5908 }
5909 }
5910
5911 LogToFD(fd, "-------- NAT Traversals --------");
5912 LogToFD(fd, "ExtAddress %.4a Retry %d Interval %d",
5913 &m->ExtAddress,
5914 m->retryGetAddr ? (m->retryGetAddr - now) / mDNSPlatformOneSecond : 0,
5915 m->retryIntervalGetAddr / mDNSPlatformOneSecond);
5916 if (m->NATTraversals)
5917 {
5918 const NATTraversalInfo *nat;
5919 for (nat = m->NATTraversals; nat; nat=nat->next)
5920 {
5921 LogToFD(fd, "%p %s Int %5d %s Err %d Retry %5d Interval %5d Expire %5d Req %.4a:%d Ext %.4a:%d",
5922 nat,
5923 nat->Protocol ? (nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP") : "ADD",
5924 mDNSVal16(nat->IntPort),
5925 (nat->lastSuccessfulProtocol == NATTProtocolNone ? "None " :
5926 nat->lastSuccessfulProtocol == NATTProtocolNATPMP ? "NAT-PMP " :
5927 nat->lastSuccessfulProtocol == NATTProtocolUPNPIGD ? "UPnP/IGD" :
5928 nat->lastSuccessfulProtocol == NATTProtocolPCP ? "PCP " :
5929 /* else */ "Unknown " ),
5930 nat->Result,
5931 nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
5932 nat->retryInterval / mDNSPlatformOneSecond,
5933 nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
5934 &nat->NewAddress, mDNSVal16(nat->RequestedPort),
5935 &nat->ExternalAddress, mDNSVal16(nat->ExternalPort));
5936 }
5937 }
5938
5939 LogToFD(fd, "--------- AuthInfoList ---------");
5940 if (!m->AuthInfoList) LogToFD(fd, "<None>");
5941 else
5942 {
5943 const DomainAuthInfo *a;
5944 for (a = m->AuthInfoList; a; a = a->next)
5945 {
5946 LogToFD(fd, "%##s %##s %##s %d %d",
5947 a->domain.c, a->keyname.c,
5948 a->hostname.c, (a->port.b[0] << 8 | a->port.b[1]),
5949 (a->deltime ? (a->deltime - now) : 0));
5950 }
5951 }
5952
5953 LogToFD(fd, "---------- Misc State ----------");
5954
5955 LogToFD(fd, "PrimaryMAC: %.6a", &m->PrimaryMAC);
5956
5957 LogToFD(fd, "m->SleepState %d (%s) seq %d",
5958 m->SleepState,
5959 m->SleepState == SleepState_Awake ? "Awake" :
5960 m->SleepState == SleepState_Transferring ? "Transferring" :
5961 m->SleepState == SleepState_Sleeping ? "Sleeping" : "?",
5962 m->SleepSeqNum);
5963
5964 if (!m->SPSSocket) LogToFD(fd, "Not offering Sleep Proxy Service");
5965 #ifndef SPC_DISABLED
5966 else LogToFD(fd, "Offering Sleep Proxy Service: %#s", m->SPSRecords.RR_SRV.resrec.name->c);
5967 #endif
5968 if (m->ProxyRecords == ProxyA + ProxyD) LogToFD(fd, "ProxyRecords: %d + %d = %d", ProxyA, ProxyD, ProxyA + ProxyD);
5969 else LogToFD(fd, "ProxyRecords: MISMATCH %d + %d = %d %d", ProxyA, ProxyD, ProxyA + ProxyD, m->ProxyRecords);
5970
5971 LogToFD(fd, "------ Auto Browse Domains -----");
5972 if (!AutoBrowseDomains) LogToFD(fd, "<None>");
5973 else for (d=AutoBrowseDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
5974
5975 LogToFD(fd, "--- Auto Registration Domains --");
5976 if (!AutoRegistrationDomains) LogToFD(fd, "<None>");
5977 else for (d=AutoRegistrationDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
5978
5979 LogToFD(fd, "--- Search Domains --");
5980 if (!SearchList) LogToFD(fd, "<None>");
5981 else
5982 {
5983 for (s=SearchList; s; s=s->next)
5984 {
5985 char *ifname = InterfaceNameForID(m, s->InterfaceID);
5986 LogToFD(fd, "%##s %s", s->domain.c, ifname ? ifname : "");
5987 }
5988 }
5989 LogMDNSStatisticsToFD(fd, m);
5990
5991 LogToFD(fd, "---- Task Scheduling Timers ----");
5992
5993 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
5994 LogToFD(fd, "BonjourEnabled %d", m->BonjourEnabled);
5995 #endif
5996
5997 #if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
5998 LogToFD(fd, "EnableBLEBasedDiscovery %d", EnableBLEBasedDiscovery);
5999 LogToFD(fd, "DefaultToBLETriggered %d", DefaultToBLETriggered);
6000 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
6001
6002 if (!m->NewQuestions)
6003 LogToFD(fd, "NewQuestion <NONE>");
6004 else
6005 LogToFD(fd, "NewQuestion DelayAnswering %d %d %##s (%s)",
6006 m->NewQuestions->DelayAnswering, m->NewQuestions->DelayAnswering-now,
6007 m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
6008
6009 if (!m->NewLocalOnlyQuestions)
6010 LogToFD(fd, "NewLocalOnlyQuestions <NONE>");
6011 else
6012 LogToFD(fd, "NewLocalOnlyQuestions %##s (%s)",
6013 m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
6014
6015 if (!m->NewLocalRecords)
6016 LogToFD(fd, "NewLocalRecords <NONE>");
6017 else
6018 LogToFD(fd, "NewLocalRecords %02X %s", m->NewLocalRecords->resrec.RecordType, ARDisplayString(m, m->NewLocalRecords));
6019
6020 LogToFD(fd, "SPSProxyListChanged%s", m->SPSProxyListChanged ? "" : " <NONE>");
6021 LogToFD(fd, "LocalRemoveEvents%s", m->LocalRemoveEvents ? "" : " <NONE>");
6022 LogToFD(fd, "m->WABBrowseQueriesCount %d", m->WABBrowseQueriesCount);
6023 LogToFD(fd, "m->WABLBrowseQueriesCount %d", m->WABLBrowseQueriesCount);
6024 LogToFD(fd, "m->WABRegQueriesCount %d", m->WABRegQueriesCount);
6025 LogToFD(fd, "m->AutoTargetServices %u", m->AutoTargetServices);
6026 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
6027 LogToFD(fd, "m->AutoTargetAWDLIncludedCount %u", m->AutoTargetAWDLIncludedCount);
6028 LogToFD(fd, "m->AutoTargetAWDLOnlyCount %u", m->AutoTargetAWDLOnlyCount);
6029 #endif
6030
6031 LogToFD(fd, " ABS (hex) ABS (dec) REL (hex) REL (dec)");
6032 LogToFD(fd, "m->timenow %08X %11d", now, now);
6033 LogToFD(fd, "m->timenow_adjust %08X %11d", m->timenow_adjust, m->timenow_adjust);
6034 LogTimerToFD(fd, "m->NextScheduledEvent ", m->NextScheduledEvent);
6035
6036 #ifndef UNICAST_DISABLED
6037 LogTimerToFD(fd, "m->NextuDNSEvent ", m->NextuDNSEvent);
6038 LogTimerToFD(fd, "m->NextSRVUpdate ", m->NextSRVUpdate);
6039 LogTimerToFD(fd, "m->NextScheduledNATOp ", m->NextScheduledNATOp);
6040 LogTimerToFD(fd, "m->retryGetAddr ", m->retryGetAddr);
6041 #endif
6042
6043 LogTimerToFD(fd, "m->NextCacheCheck ", m->NextCacheCheck);
6044 LogTimerToFD(fd, "m->NextScheduledSPS ", m->NextScheduledSPS);
6045 LogTimerToFD(fd, "m->NextScheduledKA ", m->NextScheduledKA);
6046
6047 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
6048 LogTimerToFD(fd, "m->NextBonjourDisableTime ", m->NextBonjourDisableTime);
6049 #endif
6050
6051 LogTimerToFD(fd, "m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
6052 LogTimerToFD(fd, "m->DelaySleep ", m->DelaySleep);
6053
6054 LogTimerToFD(fd, "m->NextScheduledQuery ", m->NextScheduledQuery);
6055 LogTimerToFD(fd, "m->NextScheduledProbe ", m->NextScheduledProbe);
6056 LogTimerToFD(fd, "m->NextScheduledResponse", m->NextScheduledResponse);
6057
6058 LogTimerToFD(fd, "m->SuppressSending ", m->SuppressSending);
6059 LogTimerToFD(fd, "m->SuppressProbes ", m->SuppressProbes);
6060 LogTimerToFD(fd, "m->ProbeFailTime ", m->ProbeFailTime);
6061 LogTimerToFD(fd, "m->DelaySleep ", m->DelaySleep);
6062 LogTimerToFD(fd, "m->SleepLimit ", m->SleepLimit);
6063 LogTimerToFD(fd, "m->NextScheduledStopTime ", m->NextScheduledStopTime);
6064 }
6065
6066 #if MDNS_MALLOC_DEBUGGING
6067 mDNSlocal void udsserver_validatelists(void *context)
6068 {
6069 const request_state *req, *p;
6070 (void)context; // unused
6071 for (req = all_requests; req; req=req->next)
6072 {
6073 if (req->next == (request_state *)~0 || (req->sd < 0 && req->sd != -2))
6074 LogMemCorruption("UDS request list: %p is garbage (%d)", req, req->sd);
6075
6076 if (req->primary == req)
6077 LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req, req->sd);
6078
6079 if (req->primary && req->replies)
6080 LogMemCorruption("UDS request list: Subordinate request %p/%d/%p should not have replies (%p)",
6081 req, req->sd, req->primary && req->replies);
6082
6083 p = req->primary;
6084 if ((long)p & 3)
6085 LogMemCorruption("UDS request list: req %p primary %p is misaligned (%d)", req, p, req->sd);
6086 else if (p && (p->next == (request_state *)~0 || (p->sd < 0 && p->sd != -2)))
6087 LogMemCorruption("UDS request list: req %p primary %p is garbage (%d)", req, p, p->sd);
6088
6089 reply_state *rep;
6090 for (rep = req->replies; rep; rep=rep->next)
6091 if (rep->next == (reply_state *)~0)
6092 LogMemCorruption("UDS req->replies: %p is garbage", rep);
6093
6094 if (req->terminate == connection_termination)
6095 {
6096 registered_record_entry *r;
6097 for (r = req->u.reg_recs; r; r=r->next)
6098 if (r->next == (registered_record_entry *)~0)
6099 LogMemCorruption("UDS req->u.reg_recs: %p is garbage", r);
6100 }
6101 else if (req->terminate == regservice_termination_callback)
6102 {
6103 service_instance *s;
6104 for (s = req->u.servicereg.instances; s; s=s->next)
6105 if (s->next == (service_instance *)~0)
6106 LogMemCorruption("UDS req->u.servicereg.instances: %p is garbage", s);
6107 }
6108 else if (req->terminate == browse_termination_callback)
6109 {
6110 browser_t *b;
6111 for (b = req->u.browser.browsers; b; b=b->next)
6112 if (b->next == (browser_t *)~0)
6113 LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", b);
6114 }
6115 }
6116
6117 DNameListElem *d;
6118 for (d = SCPrefBrowseDomains; d; d=d->next)
6119 if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
6120 LogMemCorruption("SCPrefBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
6121
6122 ARListElem *b;
6123 for (b = LocalDomainEnumRecords; b; b=b->next)
6124 if (b->next == (ARListElem *)~0 || b->ar.resrec.name->c[0] > 63)
6125 LogMemCorruption("LocalDomainEnumRecords: %p is garbage (%d)", b, b->ar.resrec.name->c[0]);
6126
6127 for (d = AutoBrowseDomains; d; d=d->next)
6128 if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
6129 LogMemCorruption("AutoBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
6130
6131 for (d = AutoRegistrationDomains; d; d=d->next)
6132 if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
6133 LogMemCorruption("AutoRegistrationDomains: %p is garbage (%d)", d, d->name.c[0]);
6134 }
6135 #endif // MDNS_MALLOC_DEBUGGING
6136
6137 mDNSlocal int send_msg(request_state *const req)
6138 {
6139 reply_state *const rep = req->replies; // Send the first waiting reply
6140 ssize_t nwriten;
6141
6142 ConvertHeaderBytes(rep->mhdr);
6143 nwriten = send(req->sd, (char *)&rep->mhdr + rep->nwriten, rep->totallen - rep->nwriten, 0);
6144 ConvertHeaderBytes(rep->mhdr);
6145
6146 if (nwriten < 0)
6147 {
6148 if (dnssd_errno == dnssd_EINTR || dnssd_errno == dnssd_EWOULDBLOCK) nwriten = 0;
6149 else
6150 {
6151 #if !defined(PLATFORM_NO_EPIPE)
6152 if (dnssd_errno == EPIPE)
6153 return(req->ts = t_terminated);
6154 else
6155 #endif
6156 {
6157 LogMsg("send_msg ERROR: failed to write %d of %d bytes to fd %d errno %d (%s)",
6158 rep->totallen - rep->nwriten, rep->totallen, req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
6159 return(t_error);
6160 }
6161 }
6162 }
6163 rep->nwriten += nwriten;
6164 return (rep->nwriten == rep->totallen) ? t_complete : t_morecoming;
6165 }
6166
6167 mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
6168 {
6169 mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
6170 request_state **req = &all_requests;
6171
6172 while (*req)
6173 {
6174 request_state *const r = *req;
6175
6176 if (r->terminate == resolve_termination_callback)
6177 if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0)
6178 {
6179 r->u.resolve.ReportTime = 0;
6180 // if client received results and resolve still active
6181 if (r->u.resolve.txt && r->u.resolve.srv)
6182 LogMsgNoIdent("Client application PID[%d](%s) has received results for DNSServiceResolve(%##s) yet remains active over two minutes.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c);
6183 }
6184
6185 // Note: Only primary req's have reply lists, not subordinate req's.
6186 while (r->replies) // Send queued replies
6187 {
6188 transfer_state result;
6189 if (r->replies->next)
6190 r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
6191 result = send_msg(r); // Returns t_morecoming if buffer full because client is not reading
6192 if (result == t_complete)
6193 {
6194 reply_state *fptr = r->replies;
6195 r->replies = r->replies->next;
6196 freeL("reply_state/udsserver_idle", fptr);
6197 r->time_blocked = 0; // reset failure counter after successful send
6198 r->unresponsiveness_reports = 0;
6199 continue;
6200 }
6201 else if (result == t_terminated)
6202 {
6203 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);
6204 abort_request(r);
6205 }
6206 else if (result == t_error)
6207 {
6208 LogMsg("%3d: Could not write data to client PID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name);
6209 LogClientInfo(r);
6210 abort_request(r);
6211 }
6212 break;
6213 }
6214
6215 if (r->replies) // If we failed to send everything, check our time_blocked timer
6216 {
6217 if (nextevent - now > mDNSPlatformOneSecond)
6218 nextevent = now + mDNSPlatformOneSecond;
6219
6220 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
6221 "[R%u] Could not send all replies. Will try again in %d ticks.", r->request_id, nextevent - now);
6222 if (mDNSStorage.SleepState != SleepState_Awake)
6223 r->time_blocked = 0;
6224 else if (!r->time_blocked)
6225 r->time_blocked = NonZeroTime(now);
6226 else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1))
6227 {
6228 int num = 0;
6229 struct reply_state *x = r->replies;
6230 while (x)
6231 {
6232 num++;
6233 x=x->next;
6234 }
6235 LogMsg("%3d: Could not write data to client PID[%d](%s) after %ld seconds, %d repl%s waiting",
6236 r->sd, r->process_id, r->pid_name, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies");
6237 if (++r->unresponsiveness_reports >= 60)
6238 {
6239 LogMsg("%3d: Client PID[%d](%s) unresponsive; aborting connection", r->sd, r->process_id, r->pid_name);
6240 LogClientInfo(r);
6241 abort_request(r);
6242 }
6243 }
6244 }
6245
6246 if (!dnssd_SocketValid(r->sd)) // If this request is finished, unlink it from the list and free the memory
6247 {
6248 // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
6249 *req = r->next;
6250 freeL("request_state/udsserver_idle", r);
6251 }
6252 else
6253 req = &r->next;
6254 }
6255 return nextevent;
6256 }
6257
6258 struct CompileTimeAssertionChecks_uds_daemon
6259 {
6260 // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
6261 // other overly-large structures instead of having a pointer to them, can inadvertently
6262 // cause structure sizes (and therefore memory usage) to balloon unreasonably.
6263 char sizecheck_request_state [(sizeof(request_state) <= 3880) ? 1 : -1];
6264 char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 60) ? 1 : -1];
6265 char sizecheck_service_instance [(sizeof(service_instance) <= 6552) ? 1 : -1];
6266 char sizecheck_browser_t [(sizeof(browser_t) <= 1480) ? 1 : -1];
6267 char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1];
6268 char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1];
6269 };
6270
6271 #ifdef UNIT_TEST
6272 #include "../unittests/uds_daemon_ut.c"
6273 #endif // UNIT_TEST