2 * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #define usleep(X) Sleep(((X)+999)/1000)
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
26 #include <sys/resource.h>
32 #include "mDNSEmbeddedAPI.h"
33 #include "DNSCommon.h"
35 #include "uds_daemon.h"
36 #include "dns_sd_internal.h"
38 // Apple-specific functionality, not required for other platforms
39 #if APPLE_OSX_mDNSResponder
41 #include <sys/ucred.h>
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
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
54 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
58 #if APPLE_OSX_mDNSResponder
62 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
63 #include "mDNSMacOSX.h"
64 #include <os/feature_private.h>
67 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
68 #include <bsm/libbsm.h>
71 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
72 #include "QuerierSupport.h"
75 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
79 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
80 #include "dnssec_v2.h"
83 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
84 #include "dnssd_server.h"
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)
91 // ***************************************************************************
92 #if COMPILER_LIKES_PRAGMA_MARK
94 #pragma mark - Globals
98 mDNSexport mDNS mDNSStorage
;
99 mDNSexport
const char ProgramName
[] = "mDNSResponder";
101 #if defined(USE_TCP_LOOPBACK)
102 static char* boundPath
= NULL
;
104 static char* boundPath
= MDNS_UDS_SERVERPATH
;
107 #define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder"
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
123 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
124 mDNSu32 curr_num_regservices
= 0;
125 mDNSu32 max_num_regservices
= 0;
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.
137 mDNSexport DNameListElem
*AutoRegistrationDomains
; // Domains where we automatically register for empty-string registrations
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
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
147 // If a platform specifies its own PID file name, we use that
149 #define PID_FILE "/var/run/mDNSResponder.pid"
152 // ***************************************************************************
153 #if COMPILER_LIKES_PRAGMA_MARK
155 #pragma mark - General Utility Functions
158 mDNSlocal mDNSu32
GetNewRequestID(void)
160 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
161 return dnssd_server_get_new_request_id();
163 static mDNSu32 s_last_id
= 0;
168 mDNSlocal
void FatalError(char *errmsg
)
170 LogMsg("%s: %s", errmsg
, dnssd_strerror(dnssd_errno
));
174 mDNSlocal mDNSu32
dnssd_htonl(mDNSu32 l
)
177 char *data
= (char*) &ret
;
178 put_uint32(l
, &data
);
182 // hack to search-replace perror's to LogMsg's
183 mDNSlocal
void my_perror(char *errmsg
)
185 LogMsg("%s: %d (%s)", errmsg
, dnssd_errno
, dnssd_strerror(dnssd_errno
));
188 // Throttled version of my_perror: Logs once every 250 msgs
189 mDNSlocal
void my_throttled_perror(char *err_msg
)
191 static int uds_throttle_count
= 0;
192 if ((uds_throttle_count
++ % 250) == 0)
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
)
200 if (mDNSOpaque16IsZero(q
->TargetQID
)) // Check for Mcast Query
202 mDNSBool mflag
= mDNSfalse
;
203 if (status
== q_start
)
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
);
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
)
227 if (!AuthRecord_uDNS(ar
)) // Check for Mcast Service
229 mDNSBool mflag
= mDNSfalse
;
230 if (status
== reg_start
)
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
);
250 // For complete Mcast State Log, pass mDNStrue to mstatelog in LogMcastStateInfo()
251 mDNSexport
void LogMcastStateInfo(mDNSBool mflag
, mDNSBool start
, mDNSBool mstatelog
)
253 mDNS
*const m
= &mDNSStorage
;
258 LogMcastNoIdent("<None>");
262 request_state
*req
, *r
;
263 for (req
= all_requests
; req
; req
=req
->next
)
265 if (req
->primary
) // If this is a subbordinate operation, check that the parent is in the list
267 for (r
= all_requests
; r
&& r
!= req
; r
=r
->next
)
268 if (r
== req
->primary
)
271 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
272 GetMcastClients(req
);
275 LogMcastNoIdent("--- MCAST RECORDS COUNT[%d] MCAST QUESTIONS COUNT[%d] ---", n_mrecords
, n_mquests
);
276 n_mrecords
= n_mquests
= 0; // Reset the values
281 static mDNSu32 i_mpktnum
;
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 ---");
291 LogMcastNoIdent("<None>");
295 request_state
*req
, *r
;
296 for (req
= all_requests
; req
; req
=req
->next
)
298 if (req
->primary
) // If this is a subbordinate operation, check that the parent is in the list
300 for (r
= all_requests
; r
&& r
!= req
; r
=r
->next
)
301 if (r
== req
->primary
)
303 LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req
->sd
);
305 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
306 LogMcastClientInfo(req
);
309 if(!mcount
) // To initially set mcount
314 i_mpktnum
= m
->MPktNum
;
315 LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount
, i_mpktnum
);
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 ---");
323 mDNSlocal
void abort_request(request_state
*req
)
325 if (req
->terminate
== (req_termination_fn
) ~0)
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
);
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)
339 Querier_DeregisterCustomDNSService(req
->custom_service_id
);
340 req
->custom_service_id
= 0;
344 if (!dnssd_SocketValid(req
->sd
))
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
);
351 // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
354 if (req
->errsd
!= req
->sd
)
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
);
361 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEBUG
,
362 "[R%d] Removing FD %d", req
->request_id
, req
->sd
);
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
; }
367 while (req
->replies
) // free pending replies
369 reply_state
*ptr
= req
->replies
;
370 req
->replies
= req
->replies
->next
;
371 freeL("reply_state (abort)", ptr
);
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
380 #error This will not work on Windows, look at IsValidSocket in mDNSShared/CommonServices.h to see why
382 req
->sd
= req
->errsd
= -2;
384 req
->sd
= req
->errsd
= dnssd_InvalidSocket
;
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;
391 mDNSexport
void SetDebugBoundPath(void)
393 #if !defined(USE_TCP_LOOPBACK)
394 boundPath
= MDNS_UDS_SERVERPATH_DEBUG
;
398 mDNSexport
int IsDebugSocketInUse(void)
400 #if !defined(USE_TCP_LOOPBACK)
401 return !strcmp(boundPath
, MDNS_UDS_SERVERPATH_DEBUG
);
408 mDNSlocal
void AbortUnlinkAndFree(request_state
*req
)
410 request_state
**p
= &all_requests
;
412 while (*p
&& *p
!= req
) p
=&(*p
)->next
;
416 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
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
);
425 freeL("request_state/AbortUnlinkAndFree", req
);
427 else LogMsg("AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req
);
430 mDNSlocal reply_state
*create_reply(const reply_op_t op
, const size_t datalen
, request_state
*const request
)
434 if ((unsigned)datalen
< sizeof(reply_hdr
))
436 LogMsg("ERROR: create_reply - data length less than length of required fields");
440 reply
= (reply_state
*) callocL("reply_state", sizeof(reply_state
) + datalen
- sizeof(reply_hdr
));
441 if (!reply
) FatalError("ERROR: calloc");
443 reply
->next
= mDNSNULL
;
444 reply
->totallen
= (mDNSu32
)datalen
+ sizeof(ipc_msg_hdr
);
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;
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
)
467 freeL("reply_state/append_reply", rep
);
471 r
= req
->primary
? req
->primary
: req
;
473 while (*ptr
) ptr
= &(*ptr
)->next
;
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
)
485 domainname type
, dom
;
487 if (servicename
&& !DeconstructServiceName(servicename
, &name
, &type
, &dom
))
488 return kDNSServiceErr_Invalid
;
491 char namestr
[MAX_DOMAIN_LABEL
+1];
492 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
493 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
499 ConvertDomainLabelToCString_unescaped(&name
, namestr
);
500 ConvertDomainNameToCString(&type
, typestr
);
501 ConvertDomainNameToCString(&dom
, domstr
);
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);
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
);
525 data
= (char *)&(*rep
)->rhdr
[1];
526 put_string(namestr
, &data
);
527 put_string(typestr
, &data
);
528 put_string(domstr
, &data
);
530 return mStatus_NoError
;
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
)
537 char namestr
[MAX_DOMAIN_LABEL
+1];
538 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
539 static const char domstr
[] = ".";
547 // 1. Put first label in namestr
548 ConvertDomainLabelToCString_unescaped((const domainlabel
*)servicename
, namestr
);
550 // 2. Put second label and "local" into typestr
551 mDNS_snprintf(typestr
, sizeof(typestr
), "%#s.local.", SecondLabel(servicename
));
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);
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
);
574 data
= (char *)&(*rep
)->rhdr
[1];
575 put_string(namestr
, &data
);
576 put_string(typestr
, &data
);
577 put_string(domstr
, &data
);
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
)
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;
596 mDNSInterfaceID InterfaceID
;
600 request
->flags
= flags
;
601 request
->interfaceIndex
= interfaceIndex
;
603 if (str_err
) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL
; }
605 if (!request
->msgptr
) { LogMsg("Error reading Resource Record from client"); return NULL
; }
607 if (validate_flags
&&
608 !((flags
& kDNSServiceFlagsShared
) == kDNSServiceFlagsShared
) &&
609 !((flags
& kDNSServiceFlagsUnique
) == kDNSServiceFlagsUnique
) &&
610 !((flags
& kDNSServiceFlagsKnownUnique
) == kDNSServiceFlagsKnownUnique
))
612 LogMsg("ERROR: Bad resource record flags (must be one of either kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique)");
615 InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage
, interfaceIndex
);
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
))
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
;
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");
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
;
647 artype
= AuthRecordAny
;
649 if (flags
& kDNSServiceFlagsShared
)
650 recordType
= (mDNSu8
) kDNSRecordTypeShared
;
651 else if (flags
& kDNSServiceFlagsKnownUnique
)
652 recordType
= (mDNSu8
) kDNSRecordTypeKnownUnique
;
654 recordType
= (mDNSu8
) kDNSRecordTypeUnique
;
656 mDNS_SetupResourceRecord(rr
, mDNSNULL
, InterfaceID
, type
, 0, recordType
, artype
, mDNSNULL
, mDNSNULL
);
658 if (!MakeDomainNameFromDNSNameString(&rr
->namestorage
, name
))
660 LogMsg("ERROR: bad name: %s", name
);
661 freeL("AuthRecord/read_rr_from_ipc_msg", rr
);
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
))
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
);
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
683 mDNSlocal
int build_domainname_from_strings(domainname
*srv
, char *name
, char *regtype
, char *domain
)
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;
695 mDNSlocal
void send_all(dnssd_sock_t s
, const char *ptr
, int len
)
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.
703 LogMsg("ERROR: send_all(%d) wrote %ld of %d errno %d (%s)",
704 s
, (long)n
, len
, dnssd_errno
, dnssd_strerror(dnssd_errno
));
709 mDNSlocal mDNSBool
AuthorizedDomain(const request_state
* const request
, const domainname
* const d
, const DNameListElem
* const doms
)
711 const DNameListElem
*delem
= mDNSNULL
;
712 int bestDelta
= -1; // the delta of the best match, lower is better
714 mDNSBool allow
= mDNSfalse
;
716 if (SystemUID(request
->uid
)) return mDNStrue
;
718 dLabels
= CountLabels(d
);
719 for (delem
= doms
; delem
; delem
= delem
->next
)
723 int delemLabels
= CountLabels(&delem
->name
);
724 int delta
= dLabels
- delemLabels
;
725 if ((bestDelta
== -1 || delta
<= bestDelta
) && SameDomainName(&delem
->name
, SkipLeadingLabels(d
, delta
)))
728 allow
= (allow
|| (delem
->uid
== request
->uid
));
733 return bestDelta
== -1 ? mDNStrue
: allow
;
737 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
738 mDNSlocal
void SetupAuditTokenForRequest(request_state
*request
)
741 pid_t audit_pid
= audit_token_to_pid(request
->audit_token
);
744 #if !defined(LOCAL_PEERTOKEN)
745 #define LOCAL_PEERTOKEN 0x006 /* retrieve peer audit token */
747 socklen_t len
= sizeof(audit_token_t
);
748 int ret
= getsockopt(request
->sd
, SOL_LOCAL
, LOCAL_PEERTOKEN
, &request
->audit_token
, &len
);
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
);
759 // ***************************************************************************
760 #if COMPILER_LIKES_PRAGMA_MARK
762 #pragma mark - external helpers
765 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
766 mDNSlocal
void external_start_advertising_helper(service_instance
*const instance
)
768 AuthRecord
*st
= instance
->subtypes
;
769 ExtraResourceRecord
*e
;
771 const pid_t requestPID
= instance
->request
->process_id
;
773 if (mDNSIPPortIsZero(instance
->request
->u
.servicereg
.port
))
775 LogInfo("external_start_advertising_helper: Not registering service with port number zero");
779 if (instance
->external_advertise
) LogMsg("external_start_advertising_helper: external_advertise already set!");
781 for ( i
= 0; i
< instance
->request
->u
.servicereg
.num_subtypes
; i
++)
782 external_start_advertising_service(&st
[i
].resrec
, instance
->request
->flags
, requestPID
);
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
);
788 for (e
= instance
->srs
.Extras
; e
; e
= e
->next
)
789 external_start_advertising_service(&e
->r
.resrec
, instance
->request
->flags
, requestPID
);
791 instance
->external_advertise
= mDNStrue
;
794 mDNSlocal
void external_stop_advertising_helper(service_instance
*const instance
)
796 AuthRecord
*st
= instance
->subtypes
;
797 ExtraResourceRecord
*e
;
800 if (!instance
->external_advertise
) return;
802 LogInfo("external_stop_advertising_helper: calling external_stop_advertising_service");
804 if (instance
->request
)
806 const pid_t requestPID
= instance
->request
->process_id
;
807 for (i
= 0; i
< instance
->request
->u
.servicereg
.num_subtypes
; i
++)
809 external_stop_advertising_service(&st
[i
].resrec
, instance
->request
->flags
, requestPID
);
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
);
816 for (e
= instance
->srs
.Extras
; e
; e
= e
->next
)
818 external_stop_advertising_service(&e
->r
.resrec
, instance
->request
->flags
, requestPID
);
822 instance
->external_advertise
= mDNSfalse
;
824 #endif // MDNSRESPONDER_SUPPORTS(APPLE, D2D)
826 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
827 mDNSlocal dispatch_queue_t
_get_trust_results_dispatch_queue(void)
829 static dispatch_once_t once
= 0;
830 static dispatch_queue_t queue
= NULL
;
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
);
840 // ***************************************************************************
841 #if COMPILER_LIKES_PRAGMA_MARK
843 #pragma mark - DNSServiceRegister
846 mDNSexport
void FreeExtraRR(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
848 ExtraResourceRecord
*extra
= (ExtraResourceRecord
*)rr
->RecordContext
;
851 if (result
!= mStatus_MemFree
) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result
); return; }
853 LogInfo(" FreeExtraRR %s", RRDisplayString(m
, &rr
->resrec
));
855 if (rr
->resrec
.rdata
!= &rr
->rdatastorage
)
856 freeL("Extra RData", rr
->resrec
.rdata
);
857 freeL("ExtraResourceRecord/FreeExtraRR", extra
);
860 mDNSlocal
void unlink_and_free_service_instance(service_instance
*srv
)
862 ExtraResourceRecord
*e
= srv
->srs
.Extras
, *tmp
;
864 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
865 external_stop_advertising_helper(srv
);
868 // clear pointers from parent struct
871 service_instance
**p
= &srv
->request
->u
.servicereg
.instances
;
874 if (*p
== srv
) { *p
= (*p
)->next
; break; }
881 e
->r
.RecordContext
= e
;
884 FreeExtraRR(&mDNSStorage
, &tmp
->r
, mStatus_MemFree
);
887 if (srv
->srs
.RR_TXT
.resrec
.rdata
!= &srv
->srs
.RR_TXT
.rdatastorage
)
888 freeL("TXT RData", srv
->srs
.RR_TXT
.resrec
.rdata
);
892 freeL("ServiceSubTypes", srv
->subtypes
);
893 srv
->subtypes
= NULL
;
895 freeL("service_instance", srv
);
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
)
904 ResourceRecord
*r
= &srs
->RR_SRV
.resrec
;
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
))
911 verbosedebugf("%d peer registrations for %##s", count
, r
->name
->c
);
915 mDNSexport
int CountExistingRegistrations(domainname
*srv
, mDNSIPPort port
)
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
))
927 mDNSlocal
void SendServiceRemovalNotification(ServiceRecordSet
*const srs
)
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
; }
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
)
941 mDNSBool SuppressError
= mDNSfalse
;
942 service_instance
*instance
;
948 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "regservice_callback: srs is NULL %d", result
);
952 instance
= srs
->ServiceContext
;
955 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "regservice_callback: srs->ServiceContext is NULL %d", result
);
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
;
965 if (mDNS_LoggingEnabled
)
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;
971 case mStatus_NoError
:
972 result_description
= "REGISTERED";
974 case mStatus_MemFree
:
975 result_description
= "DEREGISTERED";
977 case mStatus_NameConflict
:
978 result_description
= "NAME CONFLICT";
981 mDNS_snprintf(description
, sizeof(description
), "%s %d", SuppressError
? "suppressed error" : "CALLBACK", result
);
982 result_description
= description
;
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
);
989 if (!instance
->request
&& result
!= mStatus_MemFree
)
991 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "regservice_callback: instance->request is NULL %d", result
);
995 if (result
== mStatus_NoError
)
997 if (instance
->request
->u
.servicereg
.allowremotequery
)
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
;
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
; }
1011 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1012 if (callExternalHelpers(instance
->request
->u
.servicereg
.InterfaceID
, &instance
->domain
, instance
->request
->flags
))
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
);
1018 if (instance
->request
->u
.servicereg
.autoname
&& CountPeerRegistrations(srs
) == 0)
1019 RecordUpdatedNiceLabel(0); // Successfully got new name, tell user immediately
1021 else if (result
== mStatus_MemFree
)
1023 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
1024 curr_num_regservices
--;
1026 if (instance
->request
&& instance
->renameonmemfree
)
1028 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1029 external_stop_advertising_helper(instance
);
1031 instance
->renameonmemfree
= 0;
1032 err
= mDNS_RenameAndReregisterService(m
, srs
, &instance
->request
->u
.servicereg
.name
);
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
1038 unlink_and_free_service_instance(instance
);
1040 else if (result
== mStatus_NameConflict
)
1042 if (instance
->request
->u
.servicereg
.autorename
)
1044 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1045 external_stop_advertising_helper(instance
);
1047 if (instance
->request
->u
.servicereg
.autoname
&& CountPeerRegistrations(srs
) == 0)
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()
1053 else // On conflict for a non-autoname service, rename and reregister just that one service
1055 if (instance
->clientnotified
) SendServiceRemovalNotification(srs
);
1056 mDNS_RenameAndReregisterService(m
, srs
, mDNSNULL
);
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
; }
1067 unlink_and_free_service_instance(instance
);
1070 else // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
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
; }
1081 mDNSlocal
void regrecord_callback(mDNS
*const m
, AuthRecord
*rr
, mStatus result
)
1084 if (!rr
->RecordContext
) // parent struct already freed by termination callback
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
));
1090 if (result
!= mStatus_MemFree
)
1091 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "regrecord_callback: error %d received after parent termination", result
);
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
);
1103 registered_record_entry
*re
= rr
->RecordContext
;
1104 request_state
*request
= re
->request
;
1106 if (mDNS_LoggingEnabled
)
1108 const char *result_description
;
1109 char description
[16]; // 16-byte is enough for holding -2147483648\0
1111 case mStatus_NoError
:
1112 result_description
= "REGISTERED";
1114 case mStatus_MemFree
:
1115 result_description
= "DEREGISTERED";
1117 case mStatus_NameConflict
:
1118 result_description
= "NAME CONFLICT";
1121 mDNS_snprintf(description
, sizeof(description
), "%d", result
);
1122 result_description
= description
;
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
);
1130 if (result
!= mStatus_MemFree
)
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
);
1143 // If this is a callback to a keepalive record, do not free it.
1144 if (result
== mStatus_BadStateErr
)
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
);
1151 // unlink from list, free memory
1152 registered_record_entry
**ptr
= &request
->u
.reg_recs
;
1153 while (*ptr
&& (*ptr
) != re
) ptr
= &(*ptr
)->next
;
1156 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
1157 "[R%u] regrecord_callback - record not in list!", request
->request_id
);
1160 *ptr
= (*ptr
)->next
;
1161 freeL("registered_record_entry AuthRecord regrecord_callback", re
->rr
);
1162 freeL("registered_record_entry regrecord_callback", re
);
1167 if (re
->external_advertise
)
1169 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
1170 "[R%u] regrecord_callback: external_advertise already set!", request
->request_id
);
1173 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1174 if (callExternalHelpers(re
->origInterfaceID
, &rr
->namestorage
, request
->flags
))
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
;
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
)
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)
1197 // to extract the effective pid value
1198 if (getsockopt(request
->sd
, SOL_LOCAL
, LOCAL_PEEREPID
, &p
, &len
) != 0)
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)
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)
1210 #endif // LOCAL_PEEREPID
1213 mDNSlocal
void connection_termination(request_state
*request
)
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
;
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
);
1225 if ((*req
)->primary
== request
)
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
);
1233 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
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
);
1242 freeL("request_state/connection_termination", tmp
);
1245 req
= &(*req
)->next
;
1248 while (request
->u
.reg_recs
)
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
,
1255 request
->u
.reg_recs
= request
->u
.reg_recs
->next
;
1256 ptr
->rr
->RecordContext
= NULL
;
1257 if (ptr
->external_advertise
)
1259 ptr
->external_advertise
= mDNSfalse
;
1260 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1261 external_stop_advertising_service(&ptr
->rr
->resrec
, request
->flags
, request
->process_id
);
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
);
1270 mDNSlocal
void handle_cancel_request(request_state
*request
)
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]);
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])
1281 // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
1282 request_state
*tmp
= *req
;
1285 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
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
);
1294 freeL("request_state/handle_cancel_request", tmp
);
1297 req
= &(*req
)->next
;
1301 mDNSlocal mStatus
_handle_regrecord_request_start(request_state
*request
, AuthRecord
* rr
)
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
))
1311 freeL("AuthRecord/handle_regrecord_request", rr
);
1312 return (mStatus_BadParamErr
);
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
;
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
;
1325 re
->origInterfaceID
= rr
->resrec
.InterfaceID
;
1326 if (rr
->resrec
.InterfaceID
== mDNSInterface_P2P
)
1327 rr
->resrec
.InterfaceID
= mDNSInterface_Any
;
1329 if (!AuthorizedDomain(request
, rr
->resrec
.name
, AutoRegistrationDomains
)) return (mStatus_NoError
);
1331 if (rr
->resrec
.rroriginalttl
== 0)
1332 rr
->resrec
.rroriginalttl
= DefaultTTLforRRType(rr
->resrec
.rrtype
);
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
,
1339 err
= mDNS_Register(&mDNSStorage
, rr
);
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
);
1350 LogMcastS(rr
, request
, reg_start
);
1351 re
->next
= request
->u
.reg_recs
;
1352 request
->u
.reg_recs
= re
;
1357 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1359 mDNSlocal
void _return_regrecord_request_error(request_state
*request
, mStatus error
)
1362 if (GenerateNTDResponse(NULL
, 0, request
, &rep
, reg_record_reply_op
, 0, error
) != mStatus_NoError
)
1364 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "[R%u] DNSServiceRegisterRecord _return_regrecord_request_error: error(%d)", request
->request_id
, error
);
1368 append_reply(request
, rep
);
1372 mDNSlocal mStatus
_handle_regrecord_request_with_trust(request_state
*request
, AuthRecord
* rr
)
1375 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
1382 const char *service_ptr
= NULL
;
1383 char type_str
[MAX_ESCAPED_DOMAIN_NAME
] = "";
1385 domainname type
, domain
;
1386 bool good
= DeconstructServiceName(rr
->resrec
.name
, &name
, &type
, &domain
);
1389 ConvertDomainNameToCString(&type
, type_str
);
1390 service_ptr
= type_str
;
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
);
1397 case mdns_trust_status_denied
:
1398 case mdns_trust_status_pending
:
1400 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, service_ptr
, flags
);
1403 freeL("AuthRecord/_handle_regrecord_request_with_trust", rr
);
1404 err
= mStatus_NoMemoryErr
;
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
)
1411 if (event
== mdns_trust_event_result
)
1413 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
1415 AuthRecord
* _rr
= mdns_trust_get_context(trust
);
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
1424 if (error
) // (not else if) Always check for error result
1426 _return_regrecord_request_error(request
, error
);
1429 KQueueUnlock("_handle_regrecord_request_with_trust");
1432 request
->trust
= trust
;
1433 mdns_trust_activate(trust
);
1434 err
= mStatus_NoError
;
1438 case mdns_trust_status_no_entitlement
:
1439 err
= mStatus_NoAuth
;
1442 case mdns_trust_status_granted
:
1443 err
= _handle_regrecord_request_start(request
, rr
);
1447 err
= mStatus_UnknownErr
;
1454 #endif // TRUST_ENFORCEMENT
1456 mDNSlocal mStatus
handle_regrecord_request(request_state
*request
)
1458 mStatus err
= mStatus_BadParamErr
;
1461 if (request
->terminate
!= connection_termination
)
1462 { LogMsg("%3d: DNSServiceRegisterRecord(not a shared connection ref)", request
->sd
); return(err
); }
1464 rr
= read_rr_from_ipc_msg(request
, 1, 1);
1467 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1468 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
) &&
1469 IsLocalDomain(rr
->resrec
.name
))
1471 err
= _handle_regrecord_request_with_trust(request
, rr
);
1475 err
= _handle_regrecord_request_start(request
, rr
);
1478 err
= _handle_regrecord_request_start(request
, rr
);
1484 mDNSlocal
void UpdateDeviceInfoRecord(mDNS
*const m
);
1486 mDNSlocal
void regservice_termination_callback(request_state
*request
)
1490 LogMsg("regservice_termination_callback context is NULL");
1493 while (request
->u
.servicereg
.instances
)
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
);
1502 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1503 external_stop_advertising_helper(p
);
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
1512 LogMcastS(&p
->srs
.RR_SRV
, request
, reg_stop
);
1513 if (mDNS_DeregisterService(&mDNSStorage
, &p
->srs
))
1515 unlink_and_free_service_instance(p
);
1516 // Don't touch service_instance *p after this -- it's likely to have been freed already
1519 if (request
->u
.servicereg
.txtdata
)
1521 freeL("service_info txtdata", request
->u
.servicereg
.txtdata
);
1522 request
->u
.servicereg
.txtdata
= NULL
;
1524 if (request
->u
.servicereg
.autoname
)
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
);
1532 mDNSlocal request_state
*LocateSubordinateRequest(request_state
*request
)
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
);
1542 mDNSlocal mStatus
add_record_to_service(request_state
*request
, service_instance
*instance
, mDNSu16 rrtype
, mDNSu16 rdlen
,
1543 const mDNSu8
*const rdata
, mDNSu32 ttl
)
1545 ServiceRecordSet
*srs
= &instance
->srs
;
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
; }
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
))
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
;
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
;
1568 result
= mDNS_AddRecordToService(&mDNSStorage
, srs
, extra
, &extra
->r
.rdatastorage
, ttl
, request
->flags
);
1571 freeL("ExtraResourceRecord/add_record_to_service", extra
);
1574 LogMcastS(&srs
->RR_PTR
, request
, reg_start
);
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
))
1581 LogInfo("add_record_to_service: calling external_start_advertising_service");
1582 external_start_advertising_service(&extra
->r
.resrec
, request
->flags
, request
->process_id
);
1588 mDNSlocal mStatus
handle_add_request(request_state
*request
)
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
1600 if (!request
->msgptr
)
1602 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
1603 "[R%d] DNSServiceAddRecord(unreadable parameters)", request
->request_id
);
1604 return(mStatus_BadParamErr
);
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
);
1610 if (request
->terminate
!= regservice_termination_callback
)
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
);
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
))
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
);
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
);
1631 for (i
= request
->u
.servicereg
.instances
; i
; i
= i
->next
)
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
1641 mDNSlocal
void update_callback(mDNS
*const m
, AuthRecord
*const rr
, RData
*oldrd
, mDNSu16 oldrdlen
)
1643 mDNSBool external_advertise
= (rr
->UpdateContext
) ? *((mDNSBool
*)rr
->UpdateContext
) : mDNSfalse
;
1646 // There are three cases.
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
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
)
1657 ResourceRecord ext
= rr
->resrec
;
1658 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1659 DNSServiceFlags flags
= deriveD2DFlagsFromAuthRecType(rr
->ARType
);
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);
1671 if (oldrd
!= &rr
->rdatastorage
) freeL("RData/update_callback", oldrd
);
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
)
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
;
1687 rr
.rdata
->MaxRDLength
= (mDNSu16
)rdcapacity
;
1688 rr
.rdlength
= rdlen
;
1689 if (!SetRData(mDNSNULL
, rdata
, rdata
+ rdlen
, &rr
, rdlen
))
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
;
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; }
1703 if (external_advertise
) ar
->UpdateContext
= (void *)external_advertise
;
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
); }
1710 mDNSlocal mStatus
handle_update_request(request_state
*request
)
1712 const ipc_msg_hdr
*const hdr
= &request
->hdr
;
1713 mStatus result
= mStatus_BadReferenceErr
;
1714 service_instance
*i
;
1715 AuthRecord
*rr
= NULL
;
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
1724 if (!request
->msgptr
)
1726 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
1727 "[R%d] DNSServiceUpdateRecord(unreadable parameters)", request
->request_id
);
1728 return(mStatus_BadParamErr
);
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
);
1734 if (request
->terminate
== connection_termination
)
1736 // update an individually registered record
1737 registered_record_entry
*reptr
;
1738 for (reptr
= request
->u
.reg_recs
; reptr
; reptr
= reptr
->next
)
1740 if (reptr
->key
== hdr
->reg_index
)
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
);
1751 result
= mStatus_BadReferenceErr
;
1755 if (request
->terminate
!= regservice_termination_callback
)
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
);
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
))
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
);
1770 // update the saved off TXT data for the service
1771 if (hdr
->reg_index
== TXT_RECORD_INDEX
)
1773 if (request
->u
.servicereg
.txtdata
)
1774 { freeL("service_info txtdata", request
->u
.servicereg
.txtdata
); request
->u
.servicereg
.txtdata
= NULL
; }
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
);
1781 request
->u
.servicereg
.txtlen
= rdlen
;
1784 // update a record from a service record set
1785 for (i
= request
->u
.servicereg
.instances
; i
; i
= i
->next
)
1787 if (hdr
->reg_index
== TXT_RECORD_INDEX
) rr
= &i
->srs
.RR_TXT
;
1790 ExtraResourceRecord
*e
;
1791 for (e
= i
->srs
.Extras
; e
; e
= e
->next
)
1792 if (e
->ClientID
== hdr
->reg_index
) { rr
= &e
->r
; break; }
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
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
);
1811 // remove a resource record registered via DNSServiceRegisterRecord()
1812 mDNSlocal mStatus
remove_record(request_state
*request
)
1814 mStatus err
= mStatus_UnknownErr
;
1815 registered_record_entry
*e
, **ptr
= &request
->u
.reg_recs
;
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
; }
1820 *ptr
= e
->next
; // unlink
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
)
1827 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1828 external_stop_advertising_service(&e
->rr
->resrec
, request
->flags
, request
->process_id
);
1830 e
->external_advertise
= mDNSfalse
;
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
1836 LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err
);
1837 freeL("registered_record_entry AuthRecord remove_record", e
->rr
);
1839 freeL("registered_record_entry remove_record", e
);
1843 mDNSlocal mStatus
remove_extra(const request_state
*const request
, service_instance
*const serv
, mDNSu16
*const rrtype
)
1845 mStatus err
= mStatus_BadReferenceErr
;
1846 ExtraResourceRecord
*ptr
;
1848 for (ptr
= serv
->srs
.Extras
; ptr
; ptr
= ptr
->next
)
1850 if (ptr
->ClientID
== request
->hdr
.reg_index
) // found match
1852 *rrtype
= ptr
->r
.resrec
.rrtype
;
1853 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
1854 if (serv
->external_advertise
)
1856 external_stop_advertising_service(&ptr
->r
.resrec
, request
->flags
, request
->process_id
);
1859 err
= mDNS_RemoveRecordFromService(&mDNSStorage
, &serv
->srs
, ptr
, FreeExtraRR
, ptr
);
1866 mDNSlocal mStatus
handle_removerecord_request(request_state
*request
)
1868 mStatus err
= mStatus_BadReferenceErr
;
1869 get_flags(&request
->msgptr
, request
->msgend
); // flags unused
1871 if (!request
->msgptr
)
1873 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
1874 "[R%d] DNSServiceRemoveRecord(unreadable parameters)", request
->request_id
);
1875 return(mStatus_BadParamErr
);
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
);
1881 if (request
->terminate
== connection_termination
)
1882 err
= remove_record(request
); // remove individually registered record
1883 else if (request
->terminate
!= regservice_termination_callback
)
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
);
1891 service_instance
*i
;
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
)
1899 err
= remove_extra(request
, i
, &rrtype
);
1900 if (err
&& i
->default_local
) break;
1901 else err
= mStatus_NoError
; // suppress non-local default errors
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
)
1915 if (p
[0] == '\\' && p
[1])
1919 else if (p
[0] == ',' && p
[1])
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
)
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
1947 else if (p
[0] == '.')
1954 // Returns -1 if illegal subtype found
1955 mDNSlocal mDNSs32
ChopSubTypes(char *regtype
)
1957 mDNSs32 NumSubTypes
= 0;
1958 char *stp
= FindFirstSubType(regtype
);
1959 while (stp
&& *stp
) // If we found a comma...
1961 if (*stp
== ',') return(-1);
1963 stp
= FindNextSubType(stp
);
1965 if (!stp
) return(-1);
1966 return(NumSubTypes
);
1969 mDNSlocal AuthRecord
*AllocateSubTypes(mDNSs32 NumSubTypes
, char *p
)
1971 AuthRecord
*st
= mDNSNULL
;
1975 st
= (AuthRecord
*) callocL("ServiceSubTypes", NumSubTypes
* sizeof(AuthRecord
));
1976 if (!st
) return(mDNSNULL
);
1977 for (i
= 0; i
< NumSubTypes
; i
++)
1979 mDNS_SetupResourceRecord(&st
[i
], mDNSNULL
, mDNSInterface_Any
, kDNSQType_ANY
, kStandardTTL
, 0, AuthRecordAny
, mDNSNULL
, mDNSNULL
);
1982 if (!MakeDomainNameFromDNSNameString(&st
[i
].namestorage
, p
))
1984 freeL("ServiceSubTypes", st
);
1992 mDNSlocal mStatus
register_service_instance(request_state
*request
, const domainname
*domain
)
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
);
1998 mDNSInterfaceID interfaceID
= request
->u
.servicereg
.InterfaceID
;
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
;
2007 for (ptr
= &request
->u
.servicereg
.instances
; *ptr
; ptr
= &(*ptr
)->next
)
2009 if (SameDomainName(&(*ptr
)->domain
, domain
))
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
;
2017 instance
= (service_instance
*) callocL("service_instance", sizeof(*instance
) + extra_size
);
2018 if (!instance
) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr
; }
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
);
2028 instance
->subtypes
= AllocateSubTypes(request
->u
.servicereg
.num_subtypes
, request
->u
.servicereg
.type_as_string
);
2030 if (request
->u
.servicereg
.num_subtypes
&& !instance
->subtypes
)
2032 unlink_and_free_service_instance(instance
);
2034 FatalError("ERROR: malloc");
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
);
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
);
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
);
2062 mDNSlocal
void udsserver_default_reg_domain_changed(const DNameListElem
*const d
, const mDNSBool add
)
2064 request_state
*request
;
2066 LogMsg("%s registration domain %##s", add
? "Adding" : "Removing", d
->name
.c
);
2067 for (request
= all_requests
; request
; request
= request
->next
)
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
)
2073 service_instance
**ptr
= &request
->u
.servicereg
.instances
;
2074 while (*ptr
&& !SameDomainName(&(*ptr
)->domain
, &d
->name
)) ptr
= &(*ptr
)->next
;
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
);
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.
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
);
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
);
2099 service_instance
*si
= *ptr
;
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.
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
); }
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
)
2125 switch(interfaceIndex
)
2127 case kDNSServiceInterfaceIndexAny
:
2128 case kDNSServiceInterfaceIndexLocalOnly
:
2129 case kDNSServiceInterfaceIndexUnicast
:
2130 case kDNSServiceInterfaceIndexP2P
:
2131 case kDNSServiceInterfaceIndexBLE
:
2138 mDNSlocal mStatus
_handle_regservice_request_start(request_state
*request
, const domainname
* const d
)
2142 request
->terminate
= regservice_termination_callback
;
2143 err
= register_service_instance(request
, d
);
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
;
2152 err
= AuthorizedDomain(request
, d
, AutoRegistrationDomains
) ? register_service_instance(request
, d
) : mStatus_NoError
;
2156 if (request
->u
.servicereg
.autoname
) UpdateDeviceInfoRecord(&mDNSStorage
);
2158 if (request
->u
.servicereg
.default_domain
)
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
);
2170 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2172 mDNSlocal
void _return_regservice_request_error(request_state
*request
, mStatus error
)
2174 if (request
->u
.servicereg
.txtdata
)
2176 freeL("service_info txtdata", request
->u
.servicereg
.txtdata
);
2177 request
->u
.servicereg
.txtdata
= NULL
;
2181 if (GenerateNTDResponse(NULL
, 0, request
, &rep
, reg_service_reply_op
, 0, error
) != mStatus_NoError
)
2183 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, "[R%u] DNSServiceRegister _return_regservice_request_error: error(%d)", request
->request_id
, error
);
2187 append_reply(request
, rep
);
2191 mDNSlocal mStatus
_handle_regservice_request_with_trust(request_state
*request
, const domainname
* const d
)
2194 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
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
);
2204 case mdns_trust_status_denied
:
2205 case mdns_trust_status_pending
:
2207 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, request
->u
.servicereg
.type_as_string
, flags
);
2210 err
= mStatus_NoMemoryErr
;
2213 void * context
= mallocL("context/_handle_regservice_request_with_trust", sizeof(domainname
));
2216 my_perror("ERROR: mallocL context/_handle_regservice_request_with_trust");
2217 mdns_release(trust
);
2218 err
= mStatus_NoMemoryErr
;
2221 memcpy(context
, d
, sizeof(domainname
));
2222 mdns_trust_set_context(trust
, context
);
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
)
2227 if (event
== mdns_trust_event_result
)
2229 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
2231 const domainname
* _d
= mdns_trust_get_context(trust
);
2236 error
= _handle_regservice_request_start(request
, _d
);
2237 // No context means the request was canceled before we got here
2239 if (error
) // (not else if) Always check for error result
2241 _return_regservice_request_error(request
, error
);
2244 KQueueUnlock("_register_service_instance_with_trust");
2247 request
->trust
= trust
;
2248 mdns_trust_activate(trust
);
2249 err
= mStatus_NoError
;
2253 case mdns_trust_status_no_entitlement
:
2254 err
= mStatus_NoAuth
;
2257 case mdns_trust_status_granted
:
2258 err
= _handle_regservice_request_start(request
, d
);
2262 err
= mStatus_UnknownErr
;
2269 #endif // TRUST_ENFORCEMENT
2271 mDNSlocal mStatus
handle_regservice_request(request_state
*request
)
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
2278 const char *msgTXTData
;
2280 DNSServiceFlags flags
= get_flags(&request
->msgptr
, request
->msgend
);
2281 mDNSu32 interfaceIndex
= get_uint32(&request
->msgptr
, request
->msgend
);
2282 mDNSInterfaceID InterfaceID
;
2284 // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the
2285 // kDNSServiceFlagsIncludeP2P flag set.
2286 if (interfaceIndex
== kDNSServiceInterfaceIndexP2P
)
2288 LogOperation("handle_regservice_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
2289 flags
|= kDNSServiceFlagsIncludeP2P
;
2290 interfaceIndex
= kDNSServiceInterfaceIndexAny
;
2293 InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage
, interfaceIndex
);
2295 // The registration is scoped to a specific interface index, but the
2296 // interface is not currently in our list.
2297 if (interfaceIndex
&& !InterfaceID
)
2299 // If it's one of the specially defined inteface index values, just return an error.
2300 if (PreDefinedInterfaceIndex(interfaceIndex
))
2302 LogInfo("handle_regservice_request: bad interfaceIndex %d", interfaceIndex
);
2303 return(mStatus_BadParamErr
);
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
);
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
); }
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
));
2326 if (request
->msgptr
+ 2 > request
->msgend
) request
->msgptr
= NULL
;
2329 request
->u
.servicereg
.port
.b
[0] = *request
->msgptr
++;
2330 request
->u
.servicereg
.port
.b
[1] = *request
->msgptr
++;
2333 request
->u
.servicereg
.txtlen
= get_uint16(&request
->msgptr
, request
->msgend
);
2334 msgTXTData
= get_rdata(&request
->msgptr
, request
->msgend
, request
->u
.servicereg
.txtlen
);
2336 if (!request
->msgptr
) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request
->sd
); return(mStatus_BadParamErr
); }
2338 if (request
->u
.servicereg
.txtlen
)
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
);
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)
2349 LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", request
->u
.servicereg
.type_as_string
);
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
; }
2359 request
->u
.servicereg
.name
= mDNSStorage
.nicelabel
;
2360 request
->u
.servicereg
.autoname
= mDNStrue
;
2364 // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
2365 if ((flags
& kDNSServiceFlagsNoAutoRename
) == 0)
2367 int newlen
= TruncateUTF8ToLength((mDNSu8
*)name
, mDNSPlatformStrLen(name
), MAX_DOMAIN_LABEL
);
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
;
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
; }
2383 request
->u
.servicereg
.default_domain
= mDNStrue
;
2384 MakeDomainNameFromDNSNameString(&d
, "local.");
2387 if (!ConstructServiceName(&srv
, &request
->u
.servicereg
.name
, &request
->u
.servicereg
.type
, &d
))
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
;
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;
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
))
2403 int count
= CountExistingRegistrations(&srv
, request
->u
.servicereg
.port
);
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
));
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
))
2413 request
->flags
|= (kDNSServiceFlagsAutoTrigger
| kDNSServiceFlagsIncludeAWDL
);
2414 LogInfo("handle_regservice_request: registration promoted to use kDNSServiceFlagsAutoTrigger");
2416 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
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
);
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
;
2431 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2432 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
) &&
2433 (request
->u
.servicereg
.default_domain
|| IsLocalDomain(&d
)))
2435 err
= _handle_regservice_request_with_trust(request
, &d
);
2436 if (err
== mStatus_NoAuth
&& request
->u
.servicereg
.txtdata
)
2438 freeL("service_info txtdata", request
->u
.servicereg
.txtdata
);
2439 request
->u
.servicereg
.txtdata
= NULL
;
2444 err
= _handle_regservice_request_start(request
, &d
);
2447 err
= _handle_regservice_request_start(request
, &d
);
2453 freeL("handle_regservice_request (txtdata)", request
->u
.servicereg
.txtdata
);
2454 request
->u
.servicereg
.txtdata
= NULL
;
2455 return mStatus_BadParamErr
;
2458 // ***************************************************************************
2459 #if COMPILER_LIKES_PRAGMA_MARK
2461 #pragma mark - DNSServiceBrowse
2464 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
2466 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: 0;
2467 request_state
*req
= question
->QuestionContext
;
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; }
2474 if (mDNSOpaque16IsZero(question
->TargetQID
) && (question
->BrowseThreshold
> 0) && (question
->CurrentAnswers
>= question
->BrowseThreshold
))
2476 flags
|= kDNSServiceFlagsThresholdReached
;
2479 // if returning a negative answer, then use question's name in reply
2480 if (answer
->RecordType
== kDNSRecordTypePacketNegative
)
2482 GenerateBrowseReply(&question
->qname
, answer
->InterfaceID
, req
, &rep
, browse_reply_op
, flags
, kDNSServiceErr_NoSuchRecord
);
2486 if (GenerateNTDResponse(&answer
->rdata
->u
.name
, answer
->InterfaceID
, req
, &rep
, browse_reply_op
, flags
, mStatus_NoError
) != mStatus_NoError
)
2488 if (SameDomainName(&req
->u
.browser
.regtype
, (const domainname
*)"\x09_services\x07_dns-sd\x04_udp"))
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
);
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
);
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
));
2509 append_reply(req
, rep
);
2512 mDNSlocal
void SetQuestionPolicy(DNSQuestion
*q
, request_state
*req
)
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.
2527 mDNSPlatformMemCopy(q
->uuid
, req
->uuid
, UUID_SIZE
);
2532 q
->pid
= req
->process_id
;
2535 //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
2538 mDNSlocal mStatus
add_domain_to_browser(request_state
*info
, const domainname
*d
)
2543 for (p
= info
->u
.browser
.browsers
; p
; p
= p
->next
)
2545 if (SameDomainName(&p
->domain
, d
))
2546 { debugf("add_domain_to_browser %##s already in list", d
->c
); return mStatus_AlreadyRegistered
; }
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
);
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
);
2562 b
->next
= info
->u
.browser
.browsers
;
2563 info
->u
.browser
.browsers
= b
;
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
))
2569 info
->flags
|= (kDNSServiceFlagsAutoTrigger
| kDNSServiceFlagsIncludeAWDL
);
2570 b
->q
.flags
|= (kDNSServiceFlagsAutoTrigger
| kDNSServiceFlagsIncludeAWDL
);
2571 LogInfo("add_domain_to_browser: request promoted to use kDNSServiceFlagsAutoTrigger");
2573 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
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
))
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
);
2589 mDNSlocal
void browse_termination_callback(request_state
*info
)
2591 if (info
->u
.browser
.default_domain
)
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
);
2597 while (info
->u
.browser
.browsers
)
2599 browser_t
*ptr
= info
->u
.browser
.browsers
;
2601 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
2602 if (callExternalHelpers(ptr
->q
.InterfaceID
, &ptr
->domain
, ptr
->q
.flags
))
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
);
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
);
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
);
2622 mDNSlocal
void udsserver_automatic_browse_domain_changed(const DNameListElem
*const d
, const mDNSBool add
)
2624 request_state
*request
;
2625 debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add
? "Adding" : "Removing", d
->name
.c
);
2627 for (request
= all_requests
; request
; request
= request
->next
)
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
)
2633 browser_t
**ptr
= &request
->u
.browser
.browsers
;
2634 while (*ptr
&& !SameDomainName(&(*ptr
)->domain
, &d
->name
)) ptr
= &(*ptr
)->next
;
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
);
2643 if (!*ptr
) LogMsg("udsserver_automatic_browse_domain_changed ERROR %##s not found", &d
->name
);
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
);
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
);
2664 mDNSlocal
void FreeARElemCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2667 if (result
== mStatus_MemFree
)
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
);
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.
2686 mDNSlocal
void RegisterLocalOnlyDomainEnumPTR(mDNS
*m
, const domainname
*d
, int type
)
2688 // allocate/register legacy and non-legacy _browse PTR record
2690 ARListElem
*ptr
= (ARListElem
*) mDNSPlatformMemAllocateClear(sizeof(*ptr
));
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
);
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
);
2704 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err
);
2705 mDNSPlatformMemFree(ptr
);
2709 ptr
->next
= LocalDomainEnumRecords
;
2710 LocalDomainEnumRecords
= ptr
;
2714 mDNSlocal
void DeregisterLocalOnlyDomainEnumPTR(mDNS
*m
, const domainname
*d
, int type
)
2716 ARListElem
**ptr
= &LocalDomainEnumRecords
;
2717 domainname lhs
; // left-hand side of PTR, for comparison
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
);
2724 MakeDomainNameFromDNSNameString(&lhs
, mDNS_DomainTypeNames
[type
]);
2725 AppendDNSNameString (&lhs
, "local");
2729 if (SameDomainName(&(*ptr
)->ar
.resrec
.rdata
->u
.name
, d
) && SameDomainName((*ptr
)->ar
.resrec
.name
, &lhs
))
2731 ARListElem
*rem
= *ptr
;
2732 *ptr
= (*ptr
)->next
;
2733 mDNS_Deregister(m
, &rem
->ar
);
2736 else ptr
= &(*ptr
)->next
;
2740 mDNSlocal
void AddAutoBrowseDomain(const mDNSu32 uid
, const domainname
*const name
)
2742 DNameListElem
*new = (DNameListElem
*) mDNSPlatformMemAllocateClear(sizeof(*new));
2743 if (!new) { LogMsg("ERROR: malloc"); return; }
2744 AssignDomainName(&new->name
, name
);
2746 new->next
= AutoBrowseDomains
;
2747 AutoBrowseDomains
= new;
2748 udsserver_automatic_browse_domain_changed(new, mDNStrue
);
2751 mDNSlocal
void RmvAutoBrowseDomain(const mDNSu32 uid
, const domainname
*const name
)
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
);
2758 DNameListElem
*ptr
= *p
;
2760 udsserver_automatic_browse_domain_changed(ptr
, mDNSfalse
);
2761 mDNSPlatformMemFree(ptr
);
2765 mDNSlocal
void SetPrefsBrowseDomains(mDNS
*m
, DNameListElem
*browseDomains
, mDNSBool add
)
2768 for (d
= browseDomains
; d
; d
= d
->next
)
2772 RegisterLocalOnlyDomainEnumPTR(m
, &d
->name
, mDNS_DomainTypeBrowse
);
2773 AddAutoBrowseDomain(d
->uid
, &d
->name
);
2777 DeregisterLocalOnlyDomainEnumPTR(m
, &d
->name
, mDNS_DomainTypeBrowse
);
2778 RmvAutoBrowseDomain(d
->uid
, &d
->name
);
2783 #if APPLE_OSX_mDNSResponder
2785 mDNSlocal
void UpdateDeviceInfoRecord(mDNS
*const m
)
2787 int num_autoname
= 0;
2790 // Don't need to register the device info record for kDNSServiceInterfaceIndexLocalOnly registrations.
2791 for (req
= all_requests
; req
; req
= req
->next
)
2793 if (req
->terminate
== regservice_termination_callback
&& req
->u
.servicereg
.autoname
&& req
->interfaceIndex
!= kDNSServiceInterfaceIndexLocalOnly
)
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
))
2801 LogOperation("UpdateDeviceInfoRecord Deregister %##s", m
->DeviceInfo
.resrec
.name
);
2802 mDNS_Deregister(m
, &m
->DeviceInfo
);
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)
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
);
2816 #else // APPLE_OSX_mDNSResponder
2817 mDNSlocal
void UpdateDeviceInfoRecord(mDNS
*const m
)
2821 #endif // APPLE_OSX_mDNSResponder
2823 mDNSexport
void udsserver_handle_configchange(mDNS
*const m
)
2826 service_instance
*ptr
;
2827 DNameListElem
*RegDomains
= NULL
;
2828 DNameListElem
*BrowseDomains
= NULL
;
2831 UpdateDeviceInfoRecord(m
);
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
))
2838 req
->u
.servicereg
.name
= m
->nicelabel
;
2839 for (ptr
= req
->u
.servicereg
.instances
; ptr
; ptr
= ptr
->next
)
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
2849 // Let the platform layer get the current DNS information
2851 mDNSPlatformSetDNSConfig(mDNSfalse
, mDNSfalse
, mDNSNULL
, &RegDomains
, &BrowseDomains
, mDNSfalse
);
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
2858 // Add any new domains not already in our AutoRegistrationDomains list
2859 for (p
=RegDomains
; p
; p
=p
->next
)
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
2865 RegisterLocalOnlyDomainEnumPTR(m
, &p
->name
, mDNS_DomainTypeRegistration
);
2866 udsserver_default_reg_domain_changed(p
, mDNStrue
);
2868 else // else found same domainname in both old and new lists, so no change, just delete old copy
2870 DNameListElem
*del
= *pp
;
2872 mDNSPlatformMemFree(del
);
2876 // Delete any domains in our old AutoRegistrationDomains list that are now gone
2877 while (AutoRegistrationDomains
)
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
);
2886 // Now we have our new updated automatic registration domain list
2887 AutoRegistrationDomains
= RegDomains
;
2889 // Add new browse domains to internal list
2890 if (BrowseDomains
) SetPrefsBrowseDomains(m
, BrowseDomains
, mDNStrue
);
2892 // Remove old browse domains from internal list
2893 if (SCPrefBrowseDomains
)
2895 SetPrefsBrowseDomains(m
, SCPrefBrowseDomains
, mDNSfalse
);
2896 while (SCPrefBrowseDomains
)
2898 DNameListElem
*fptr
= SCPrefBrowseDomains
;
2899 SCPrefBrowseDomains
= SCPrefBrowseDomains
->next
;
2900 mDNSPlatformMemFree(fptr
);
2904 // Replace the old browse domains array with the new array
2905 SCPrefBrowseDomains
= BrowseDomains
;
2908 mDNSlocal
void AutomaticBrowseDomainChange(mDNS
*const m
, DNSQuestion
*q
, const ResourceRecord
*const answer
, QC_result AddRecord
)
2913 LogOperation("AutomaticBrowseDomainChange: %s automatic browse domain %##s",
2914 AddRecord
? "Adding" : "Removing", answer
->rdata
->u
.name
.c
);
2916 if (AddRecord
) AddAutoBrowseDomain(0, &answer
->rdata
->u
.name
);
2917 else RmvAutoBrowseDomain(0, &answer
->rdata
->u
.name
);
2920 mDNSlocal mStatus
_handle_browse_request_start(request_state
*request
, const char * domain
)
2923 mStatus err
= mStatus_NoError
;
2925 request
->terminate
= browse_termination_callback
;
2929 if (!MakeDomainNameFromDNSNameString(&d
, domain
)) return(mStatus_BadParamErr
);
2930 err
= add_domain_to_browser(request
, &d
);
2934 DNameListElem
*sdom
;
2935 for (sdom
= AutoBrowseDomains
; sdom
; sdom
= sdom
->next
)
2936 if (!sdom
->uid
|| SystemUID(request
->uid
) || request
->uid
== sdom
->uid
)
2938 err
= add_domain_to_browser(request
, &sdom
->name
);
2941 if (SameDomainName(&sdom
->name
, &localdomain
)) break;
2942 else err
= mStatus_NoError
; // suppress errors for non-local "default" domains
2950 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
2952 mDNSlocal
void _return_browse_request_error(request_state
*request
, mStatus error
)
2956 GenerateBrowseReply(NULL
, 0, request
, &rep
, browse_reply_op
, 0, error
);
2958 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
2959 "[R%d] DNSServiceBrowse _return_browse_request_error: error (%d)", request
->request_id
, error
);
2961 append_reply(request
, rep
);
2964 mDNSlocal mStatus
_handle_browse_request_with_trust(request_state
*request
, const char * domain
)
2967 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
2974 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
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
);
2981 case mdns_trust_status_denied
:
2982 case mdns_trust_status_pending
:
2984 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, typestr
, flags
);
2987 err
= mStatus_NoMemoryErr
;
2991 size_t len
= strlen(domain
) + 1;
2992 void * context
= mallocL("context/_handle_browse_request_with_trust", len
);
2995 my_perror("ERROR: mallocL context/_handle_browse_request_with_trust");
2996 mdns_release(trust
);
2997 err
= mStatus_NoMemoryErr
;
3000 memcpy(context
, domain
, len
);
3001 mdns_trust_set_context(trust
, context
);
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
)
3006 if (event
== mdns_trust_event_result
)
3008 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
3010 const char * _domain
= mdns_trust_get_context(trust
);
3015 error
= _handle_browse_request_start(request
, _domain
);
3016 // No context means the request was canceled before we got here
3018 if (error
) // (not else if) Always check for error result
3020 _return_browse_request_error(request
, error
);
3023 KQueueUnlock("_handle_browse_request_with_trust");
3026 request
->trust
= trust
;
3027 mdns_trust_activate(trust
);
3028 err
= mStatus_NoError
;
3032 case mdns_trust_status_no_entitlement
:
3033 err
= mStatus_NoAuth
;
3036 case mdns_trust_status_granted
:
3037 err
= _handle_browse_request_start(request
, domain
);
3041 err
= mStatus_UnknownErr
;
3048 #endif // TRUST_ENFORCEMENT
3050 mDNSlocal mStatus
handle_browse_request(request_state
*request
)
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
;
3058 DNSServiceFlags flags
= get_flags(&request
->msgptr
, request
->msgend
);
3059 mDNSu32 interfaceIndex
= get_uint32(&request
->msgptr
, request
->msgend
);
3060 mDNSInterfaceID InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage
, interfaceIndex
);
3062 // The browse is scoped to a specific interface index, but the
3063 // interface is not currently in our list.
3064 if (interfaceIndex
&& !InterfaceID
)
3066 // If it's one of the specially defined inteface index values, just return an error.
3067 if (PreDefinedInterfaceIndex(interfaceIndex
))
3069 LogInfo("handle_browse_request: bad interfaceIndex %d", interfaceIndex
);
3070 return(mStatus_BadParamErr
);
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
);
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
);
3082 if (!request
->msgptr
) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request
->sd
); return(mStatus_BadParamErr
); }
3084 request
->flags
= flags
;
3085 request
->interfaceIndex
= interfaceIndex
;
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)
3092 if (!AppendDNSNameString(&typedn
, regtype
+ strlen(regtype
) + 1))
3093 return(mStatus_BadParamErr
);
3096 if (!regtype
[0] || !AppendDNSNameString(&typedn
, regtype
)) return(mStatus_BadParamErr
);
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
));
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
;
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
);
3113 if (request
->u
.browser
.default_domain
)
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
);
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
;
3126 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3128 if (!MakeDomainNameFromDNSNameString(&d
, domain
)) return(mStatus_BadParamErr
);
3130 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
) &&
3131 (request
->u
.browser
.default_domain
|| IsLocalDomain(&d
) || request
->u
.browser
.ForceMCast
))
3133 err
= _handle_browse_request_with_trust(request
, domain
);
3137 err
= _handle_browse_request_start(request
, domain
);
3140 err
= _handle_browse_request_start(request
, domain
);
3146 // ***************************************************************************
3147 #if COMPILER_LIKES_PRAGMA_MARK
3149 #pragma mark - DNSServiceResolve
3152 mDNSlocal
void resolve_termination_callback(request_state
*request
)
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
)
3164 external_stop_resolving_service(request
->u
.resolve
.qsrv
.InterfaceID
, &request
->u
.resolve
.qsrv
.qname
, request
->flags
, request
->process_id
);
3170 char regtype
[MAX_ESCAPED_DOMAIN_NAME
];
3172 mDNSInterfaceID InterfaceID
;
3173 } _resolve_start_params_t
;
3175 mDNSlocal mStatus
_handle_resolve_request_start(request_state
*request
, const _resolve_start_params_t
* const params
)
3179 err
= mDNS_StartQuery(&mDNSStorage
, &request
->u
.resolve
.qsrv
);
3183 err
= mDNS_StartQuery(&mDNSStorage
, &request
->u
.resolve
.qtxt
);
3186 mDNS_StopQuery(&mDNSStorage
, &request
->u
.resolve
.qsrv
);
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
, ¶ms
->fqdn
, request
->flags
))
3195 request
->u
.resolve
.external_advertise
= mDNStrue
;
3196 LogInfo("handle_resolve_request: calling external_start_resolving_service()");
3197 external_start_resolving_service(params
->InterfaceID
, ¶ms
->fqdn
, request
->flags
, request
->process_id
);
3207 mDNSlocal
void resolve_result_callback(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
3210 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], target
[MAX_ESCAPED_DOMAIN_NAME
] = "0";
3213 request_state
*req
= question
->QuestionContext
;
3214 const DNSServiceErrorType error
=
3215 (answer
->RecordType
== kDNSRecordTypePacketNegative
) ? kDNSServiceErr_NoSuchRecord
: kDNSServiceErr_NoError
;
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
));
3224 if (req
->u
.resolve
.srv
== answer
) req
->u
.resolve
.srv
= mDNSNULL
;
3225 if (req
->u
.resolve
.txt
== answer
) req
->u
.resolve
.txt
= mDNSNULL
;
3229 if (answer
->rrtype
== kDNSType_SRV
) req
->u
.resolve
.srv
= answer
;
3230 if (answer
->rrtype
== kDNSType_TXT
) req
->u
.resolve
.txt
= answer
;
3232 if (!req
->u
.resolve
.txt
|| !req
->u
.resolve
.srv
) return; // only deliver result to client if we have both answers
3234 ConvertDomainNameToCString(answer
->name
, fullname
);
3236 if (answer
->RecordType
!= kDNSRecordTypePacketNegative
)
3237 ConvertDomainNameToCString(&req
->u
.resolve
.srv
->rdata
->u
.srv
.target
, target
);
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
;
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
);
3254 data
= (char *)&rep
->rhdr
[1];
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
);
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
);
3270 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3272 mDNSlocal
void _return_resolve_request_error(request_state
* request
, mStatus error
)
3275 char * emptystr
= "\0";
3279 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
3280 "[R%u] DNSServiceResolve _return_resolve_request_error: error(%d)", request
->request_id
, error
);
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;
3290 rep
= create_reply(resolve_reply_op
, len
, request
);
3292 rep
->rhdr
->flags
= 0;
3294 rep
->rhdr
->error
= dnssd_htonl(error
);
3296 data
= (char *)&rep
->rhdr
[1];
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
3304 append_reply(request
, rep
);
3307 mDNSlocal mStatus
_handle_resolve_request_with_trust(request_state
*request
, const _resolve_start_params_t
* const params
)
3310 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
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
);
3321 case mdns_trust_status_denied
:
3322 case mdns_trust_status_pending
:
3324 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, params
->regtype
, flags
);
3327 err
= mStatus_NoMemoryErr
;
3331 void * context
= mallocL("context/_handle_resolve_request_with_trust", sizeof(_resolve_start_params_t
));
3334 my_perror("ERROR: mallocL context/_handle_resolve_request_with_trust");
3335 mdns_release(trust
);
3336 err
= mStatus_NoMemoryErr
;
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
)
3344 if (event
== mdns_trust_event_result
)
3346 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
3348 _resolve_start_params_t
* _params
= mdns_trust_get_context(trust
);
3353 error
= _handle_resolve_request_start(request
, _params
);
3354 // No context means the request was canceled before we got here
3356 if (error
) // (not else if) Always check for error result
3358 _return_resolve_request_error(request
, error
);
3361 KQueueUnlock("_handle_resolve_request_with_trust");
3364 request
->trust
= trust
;
3365 mdns_trust_activate(trust
);
3366 err
= mStatus_NoError
;
3370 case mdns_trust_status_no_entitlement
:
3371 err
= mStatus_NoAuth
;
3374 case mdns_trust_status_granted
:
3375 err
= _handle_resolve_request_start(request
, params
);
3379 err
= mStatus_UnknownErr
;
3386 #endif // TRUST_ENFORCEMENT
3388 mDNSlocal mStatus
handle_resolve_request(request_state
*request
)
3390 char name
[256], domain
[MAX_ESCAPED_DOMAIN_NAME
];
3391 _resolve_start_params_t params
;
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
);
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
)
3402 LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
3403 flags
|= kDNSServiceFlagsIncludeP2P
;
3404 interfaceIndex
= kDNSServiceInterfaceIndexAny
;
3407 params
.InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage
, interfaceIndex
);
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
)
3413 // If it's one of the specially defined inteface index values, just return an error.
3414 if (PreDefinedInterfaceIndex(interfaceIndex
))
3416 LogInfo("handle_resolve_request: bad interfaceIndex %d", interfaceIndex
);
3417 return(mStatus_BadParamErr
);
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
);
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
); }
3431 if (!request
->msgptr
) { LogMsg("%3d: DNSServiceResolve(unreadable parameters)", request
->sd
); return(mStatus_BadParamErr
); }
3433 if (build_domainname_from_strings(¶ms
.fqdn
, name
, params
.regtype
, domain
) < 0)
3434 { LogMsg("ERROR: handle_resolve_request bad “%s” “%s” “%s”", name
, params
.regtype
, domain
); return(mStatus_BadParamErr
); }
3436 mDNSPlatformMemZero(&request
->u
.resolve
, sizeof(request
->u
.resolve
));
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
))
3442 flags
|= (kDNSServiceFlagsAutoTrigger
| kDNSServiceFlagsIncludeAWDL
);
3443 LogInfo("handle_resolve_request: request promoted to use kDNSServiceFlagsAutoTrigger");
3445 #endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
3447 request
->flags
= flags
;
3448 request
->interfaceIndex
= interfaceIndex
;
3451 request
->u
.resolve
.qsrv
.InterfaceID
= params
.InterfaceID
;
3452 request
->u
.resolve
.qsrv
.flags
= flags
;
3453 AssignDomainName(&request
->u
.resolve
.qsrv
.qname
, ¶ms
.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
;
3471 request
->u
.resolve
.qtxt
.InterfaceID
= params
.InterfaceID
;
3472 request
->u
.resolve
.qtxt
.flags
= flags
;
3473 AssignDomainName(&request
->u
.resolve
.qtxt
.qname
, ¶ms
.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
;
3491 request
->u
.resolve
.ReportTime
= NonZeroTime(mDNS_TimeNow(&mDNSStorage
) + 130 * mDNSPlatformOneSecond
);
3493 request
->u
.resolve
.external_advertise
= mDNSfalse
;
3496 if (!AuthorizedDomain(request
, &fqdn
, AutoBrowseDomains
)) return(mStatus_NoError
);
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
);
3505 request
->terminate
= NULL
;
3506 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3508 if (!MakeDomainNameFromDNSNameString(&d
, domain
)) return(mStatus_BadParamErr
);
3510 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
) &&
3511 (IsLocalDomain(&d
) || request
->u
.resolve
.qsrv
.ForceMCast
))
3513 err
= _handle_resolve_request_with_trust(request
, ¶ms
);
3517 err
= _handle_resolve_request_start(request
, ¶ms
);
3520 err
= _handle_resolve_request_start(request
, ¶ms
);
3526 // ***************************************************************************
3527 #if COMPILER_LIKES_PRAGMA_MARK
3529 #pragma mark - DNSServiceQueryRecord
3532 mDNSlocal
void queryrecord_result_reply(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
, DNSServiceErrorType error
, void *context
)
3534 char name
[MAX_ESCAPED_DOMAIN_NAME
];
3536 DNSServiceFlags flags
= 0;
3539 request_state
*req
= (request_state
*)context
;
3540 const char *dnssec_result_description
= "";
3542 ConvertDomainNameToCString(answer
->name
, name
);
3544 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
3545 if (question
->DNSSECStatus
.enable_dnssec
) {
3546 if (answer
->dnssec_result
== dnssec_secure
)
3548 flags
|= kDNSServiceFlagsSecure
;
3549 dnssec_result_description
= ", DNSSEC_Secure";
3551 else if (answer
->dnssec_result
== dnssec_insecure
)
3553 flags
|= kDNSServiceFlagsInsecure
;
3554 dnssec_result_description
= ", DNSSEC_Insecure";
3556 else if (answer
->dnssec_result
== dnssec_bogus
)
3558 flags
|= kDNSServiceFlagsBogus
;
3559 dnssec_result_description
= ", DNSSEC_Bogus";
3561 else if (answer
->dnssec_result
== dnssec_indeterminate
)
3563 flags
|= kDNSServiceFlagsIndeterminate
;
3564 dnssec_result_description
= ", DNSSEC_Indeterminated";
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";
3573 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
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
));
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
3590 rep
= create_reply(req
->hdr
.op
== query_request
? query_reply_op
: addrinfo_reply_op
, len
, req
);
3593 flags
|= kDNSServiceFlagsAdd
;
3594 if (answer
->mortality
== Mortality_Ghost
)
3595 flags
|= kDNSServiceFlagsExpiredAnswer
;
3596 if (!question
->InitialCacheMiss
)
3597 flags
|= kDNSServiceFlagAnsweredFromCache
;
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
);
3610 data
= (char *)&rep
->rhdr
[1];
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
);
3624 append_reply(req
, rep
);
3627 mDNSlocal
void queryrecord_termination_callback(request_state
*request
)
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
);
3635 QueryRecordClientRequestStop(&request
->u
.queryrecord
);
3639 char qname
[MAX_ESCAPED_DOMAIN_NAME
];
3640 mDNSu32 interfaceIndex
;
3641 DNSServiceFlags flags
;
3644 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3645 mDNSBool require_privacy
;
3647 } _queryrecord_start_params_t
;
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
,
3654 const mDNSu8
*value
= NULL
;
3655 mdns_tlv16_get_value(start
, end
, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA
, &len
, &value
, NULL
);
3663 mDNSlocal mDNSBool
ipc_tlv_get_require_privacy(const mDNSu8
*const start
, const mDNSu8
*const end
)
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
;
3672 mDNSlocal mStatus
_handle_queryrecord_request_start(request_state
*request
, const _queryrecord_start_params_t
* const params
)
3676 request
->terminate
= queryrecord_termination_callback
;
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
;
3693 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
3694 queryParams
.peerAuditToken
= &request
->audit_token
;
3696 err
= QueryRecordClientRequestStart(&request
->u
.queryrecord
, &queryParams
, queryrecord_result_reply
, request
);
3700 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3702 mDNSlocal
void _return_queryrecord_request_error(request_state
* request
, mStatus error
)
3705 char * emptystr
= "\0";
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
);
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
3721 rep
= create_reply(request
->hdr
.op
== query_request
? query_reply_op
: addrinfo_reply_op
, len
, request
);
3723 rep
->rhdr
->flags
= 0;
3725 rep
->rhdr
->error
= dnssd_htonl(error
);
3727 data
= (char *)&rep
->rhdr
[1];
3729 put_string(emptystr
, &data
);
3730 put_uint16(0, &data
);
3731 put_uint16(0, &data
);
3732 put_uint16(0, &data
);
3734 put_uint32(0, &data
);
3736 append_reply(request
, rep
);
3739 mDNSlocal mStatus
_handle_queryrecord_request_with_trust(request_state
*request
, const _queryrecord_start_params_t
* const params
)
3742 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
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
))
3755 domainname type
, domain
;
3756 bool good
= DeconstructServiceName(&query_name
, &name
, &type
, &domain
);
3759 ConvertDomainNameToCString(&type
, type_str
);
3760 service_ptr
= type_str
;
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
);
3768 case mdns_trust_status_denied
:
3769 case mdns_trust_status_pending
:
3771 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, service_ptr
, flags
);
3774 err
= mStatus_NoMemoryErr
;
3778 void * context
= mallocL("context/_handle_queryrecord_request_with_trust", sizeof(_queryrecord_start_params_t
));
3781 my_perror("ERROR: mallocL context/_handle_queryrecord_request_with_trust");
3782 mdns_release(trust
);
3783 err
= mStatus_NoMemoryErr
;
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
)
3791 if (event
== mdns_trust_event_result
)
3793 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
3795 _queryrecord_start_params_t
* _params
= mdns_trust_get_context(trust
);
3800 error
= _handle_queryrecord_request_start(request
, _params
);
3801 // No context means the request was canceled before we got here
3803 if (error
) // (not else if) Always check for error result
3805 _return_queryrecord_request_error(request
, error
);
3808 KQueueUnlock("_handle_queryrecord_request_with_trust");
3811 request
->trust
= trust
;
3812 mdns_trust_activate(trust
);
3813 err
= mStatus_NoError
;
3817 case mdns_trust_status_no_entitlement
:
3818 err
= mStatus_NoAuth
;
3821 case mdns_trust_status_granted
:
3822 err
= _handle_queryrecord_request_start(request
, params
);
3826 err
= mStatus_UnknownErr
;
3833 #endif // TRUST_ENFORCEMENT
3835 mDNSlocal mStatus
handle_queryrecord_request(request_state
*request
)
3838 _queryrecord_start_params_t params
;
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)
3844 err
= mStatus_BadParamErr
;
3847 params
.qtype
= get_uint16(&request
->msgptr
, request
->msgend
);
3848 params
.qclass
= get_uint16(&request
->msgptr
, request
->msgend
);
3850 if (!request
->msgptr
)
3852 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
3853 "[R%d] DNSServiceQueryRecord(unreadable parameters)", request
->request_id
);
3854 err
= mStatus_BadParamErr
;
3857 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3858 params
.require_privacy
= mDNSfalse
;
3860 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
3861 if (request
->msgptr
&& (request
->hdr
.ipc_flags
& IPC_FLAGS_TRAILING_TLVS
))
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
);
3869 request
->custom_service_id
= Querier_RegisterCustomDNSServiceWithPListData(data
, len
);
3871 params
.require_privacy
= ipc_tlv_get_require_privacy(start
, end
);
3874 request
->flags
= params
.flags
;
3875 request
->interfaceIndex
= params
.interfaceIndex
;
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
,
3882 mDNSPlatformMemZero(&request
->u
.queryrecord
, (mDNSu32
)sizeof(request
->u
.queryrecord
));
3883 request
->terminate
= NULL
;
3885 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
3886 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
))
3888 err
= _handle_queryrecord_request_with_trust(request
, ¶ms
);
3892 err
= _handle_queryrecord_request_start(request
, ¶ms
);
3895 err
= _handle_queryrecord_request_start(request
, ¶ms
);
3902 // ***************************************************************************
3903 #if COMPILER_LIKES_PRAGMA_MARK
3905 #pragma mark - DNSServiceEnumerateDomains
3908 mDNSlocal reply_state
*format_enumeration_reply(request_state
*request
,
3909 const char *domain
, DNSServiceFlags flags
, mDNSu32 ifi
, DNSServiceErrorType err
)
3915 len
= sizeof(DNSServiceFlags
);
3916 len
+= sizeof(mDNSu32
);
3917 len
+= sizeof(DNSServiceErrorType
);
3918 len
+= strlen(domain
) + 1;
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
);
3929 mDNSlocal
void enum_termination_callback(request_state
*request
)
3931 // Stop the domain enumeration queries to discover the WAB Browse/Registration domains
3932 if (request
->u
.enumeration
.flags
& kDNSServiceFlagsRegistrationDomains
)
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
);
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
);
3943 mDNS_StopGetDomains(&mDNSStorage
, &request
->u
.enumeration
.q_all
);
3944 mDNS_StopGetDomains(&mDNSStorage
, &request
->u
.enumeration
.q_default
);
3947 mDNSlocal
void enum_result_callback(mDNS
*const m
,
3948 DNSQuestion
*const question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
3950 char domain
[MAX_ESCAPED_DOMAIN_NAME
];
3951 request_state
*request
= question
->QuestionContext
;
3952 DNSServiceFlags flags
= 0;
3956 if (answer
->rrtype
!= kDNSType_PTR
) return;
3959 if (!AuthorizedDomain(request
, &answer
->rdata
->u
.name
, request
->u
.enumeration
.flags
? AutoRegistrationDomains
: AutoBrowseDomains
)) return;
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;
3968 flags
|= kDNSServiceFlagsAdd
;
3969 if (question
== &request
->u
.enumeration
.q_default
) flags
|= kDNSServiceFlagsDefault
;
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; }
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
);
3984 append_reply(request
, reply
);
3987 mDNSlocal mStatus
handle_enum_request(request_state
*request
)
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
);
3998 if (!request
->msgptr
)
3999 { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request
->sd
); return(mStatus_BadParamErr
); }
4001 request
->flags
= flags
;
4002 request
->interfaceIndex
= interfaceIndex
;
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
;
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
;
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
;
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
);
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
);
4027 err
= mDNS_GetDomains(&mDNSStorage
, &request
->u
.enumeration
.q_autoall
, mDNS_DomainTypeBrowseAutomatic
, NULL
, InterfaceID
, enum_result_callback
, request
);
4030 mDNS_StopGetDomains(&mDNSStorage
, &request
->u
.enumeration
.q_all
);
4031 mDNS_StopGetDomains(&mDNSStorage
, &request
->u
.enumeration
.q_default
);
4034 if (!err
) request
->terminate
= enum_termination_callback
;
4038 // Start the domain enumeration queries to discover the WAB Browse/Registration domains
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
);
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
);
4054 // ***************************************************************************
4055 #if COMPILER_LIKES_PRAGMA_MARK
4057 #pragma mark - DNSServiceReconfirmRecord & Misc
4060 mDNSlocal mStatus
handle_reconfirm_request(request_state
*request
)
4062 mStatus status
= mStatus_BadParamErr
;
4063 AuthRecord
*rr
= read_rr_from_ipc_msg(request
, 0, 0);
4066 status
= mDNS_ReconfirmByValue(&mDNSStorage
, &rr
->resrec
);
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
);
4079 #if APPLE_OSX_mDNSResponder
4081 mDNSlocal mStatus
handle_release_request(request_state
*request
)
4084 char name
[256], regtype
[MAX_ESCAPED_DOMAIN_NAME
], domain
[MAX_ESCAPED_DOMAIN_NAME
];
4085 domainname instance
;
4087 // extract the data from the message
4088 DNSServiceFlags flags
= get_flags(&request
->msgptr
, request
->msgend
);
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)
4094 LogMsg("ERROR: handle_release_request - Couldn't read name/regtype/domain");
4095 return(mStatus_BadParamErr
);
4098 if (!request
->msgptr
)
4100 LogMsg("%3d: PeerConnectionRelease(unreadable parameters)", request
->sd
);
4101 return(mStatus_BadParamErr
);
4104 if (build_domainname_from_strings(&instance
, name
, regtype
, domain
) < 0)
4106 LogMsg("ERROR: handle_release_request bad “%s” “%s” “%s”", name
, regtype
, domain
);
4107 return(mStatus_BadParamErr
);
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
);
4114 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
4115 external_connection_release(&instance
);
4120 #else // APPLE_OSX_mDNSResponder
4122 mDNSlocal mStatus
handle_release_request(request_state
*request
)
4125 return mStatus_UnsupportedErr
;
4128 #endif // APPLE_OSX_mDNSResponder
4130 mDNSlocal mStatus
handle_setdomain_request(request_state
*request
)
4132 char domainstr
[MAX_ESCAPED_DOMAIN_NAME
];
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
); }
4140 LogOperation("%3d: DNSServiceSetDefaultDomainForUser(%##s)", request
->sd
, domain
.c
);
4141 return(mStatus_NoError
);
4144 typedef packedstruct
4149 } DaemonVersionReply
;
4151 mDNSlocal
void handle_getproperty_request(request_state
*request
)
4153 const mStatus BadParamErr
= dnssd_htonl((mDNSu32
)mStatus_BadParamErr
);
4155 if (get_string(&request
->msgptr
, request
->msgend
, prop
, sizeof(prop
)) >= 0)
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
))
4161 DaemonVersionReply x
= { 0, dnssd_htonl(4), dnssd_htonl(_DNS_SD_H
) };
4162 send_all(request
->sd
, (const char *)&x
, sizeof(x
));
4167 // If we didn't recogize the requested property name, return BadParamErr
4168 send_all(request
->sd
, (const char *)&BadParamErr
, sizeof(BadParamErr
));
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
)
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
;
4186 pid
= get_uint32(&request
->msgptr
, request
->msgend
);
4187 #ifdef LOCAL_PEEREPID
4191 if (getsockopt(request
->sd
, SOL_LOCAL
, LOCAL_PEEREPID
, &request
->process_id
, &len
) != 0)
4193 LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREPID failed errno:%d / %s", errno
, strerror(errno
));
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)
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
);
4203 #ifdef LOCAL_PEEREUUID
4207 if (getsockopt(request
->sd
, SOL_LOCAL
, LOCAL_PEEREUUID
, request
->uuid
, &len
) != 0)
4209 LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREUUID failed errno:%d / %s", errno
, strerror(errno
));
4212 request
->validUUID
= mDNStrue
;
4217 mDNSlocal
void handle_connection_delegate_request(request_state
*request
)
4223 typedef packedstruct
4229 // ***************************************************************************
4230 #if COMPILER_LIKES_PRAGMA_MARK
4232 #pragma mark - DNSServiceNATPortMappingCreate
4235 #define DNSServiceProtocol(X) ((X) == NATOp_AddrRequest ? 0 : (X) == NATOp_MapUDP ? kDNSServiceProtocol_UDP : kDNSServiceProtocol_TCP)
4237 mDNSlocal
void port_mapping_termination_callback(request_state
*request
)
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
);
4244 mDNS_StopNATOperation(&mDNSStorage
, &request
->u
.pm
.NATinfo
);
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
)
4250 request_state
*request
= (request_state
*)n
->clientContext
;
4255 if (!request
) { LogMsg("port_mapping_create_request_callback called with unknown request_state object"); return; }
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
4264 rep
= create_reply(port_mapping_reply_op
, replyLen
, request
);
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
);
4270 data
= (char *)&rep
->rhdr
[1];
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
);
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
);
4290 append_reply(request
, rep
);
4293 mDNSlocal mStatus
handle_port_mapping_request(request_state
*request
)
4296 mStatus err
= mStatus_NoError
;
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
;
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
);
4314 if (!request
->msgptr
)
4316 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
,
4317 "[R%d] DNSServiceNATPortMappingCreate(unreadable parameters)", request
->request_id
);
4318 return(mStatus_BadParamErr
);
4321 if (protocol
== 0) // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too
4323 if (!mDNSIPPortIsZero(request
->u
.pm
.NATinfo
.IntPort
) || !mDNSIPPortIsZero(request
->u
.pm
.ReqExt
) || ttl
) return(mStatus_BadParamErr
);
4327 if (mDNSIPPortIsZero(request
->u
.pm
.NATinfo
.IntPort
)) return(mStatus_BadParamErr
);
4328 if (!(protocol
& (kDNSServiceProtocol_UDP
| kDNSServiceProtocol_TCP
))) return(mStatus_BadParamErr
);
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
;
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
;
4351 // ***************************************************************************
4352 #if COMPILER_LIKES_PRAGMA_MARK
4354 #pragma mark - DNSServiceGetAddrInfo
4357 mDNSlocal
void addrinfo_termination_callback(request_state
*request
)
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
);
4364 GetAddrInfoClientRequestStop(&request
->u
.addrinfo
);
4369 char hostname
[MAX_ESCAPED_DOMAIN_NAME
];
4370 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
4371 mDNSBool require_privacy
;
4373 } _addrinfo_start_params_t
;
4375 mDNSlocal mStatus
_handle_addrinfo_request_start(request_state
*request
, const _addrinfo_start_params_t
* const params
)
4379 request
->terminate
= addrinfo_termination_callback
;
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
;
4395 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
4396 gaiParams
.peerAuditToken
= &request
->audit_token
;
4398 err
= GetAddrInfoClientRequestStart(&request
->u
.addrinfo
, &gaiParams
, queryrecord_result_reply
, request
);
4403 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
4405 mDNSlocal
void _return_addrinfo_request_error(request_state
* request
, mStatus error
)
4407 _return_queryrecord_request_error(request
, error
);
4410 mDNSlocal mStatus
_handle_addrinfo_request_with_trust(request_state
*request
, const _addrinfo_start_params_t
* const params
)
4413 if (audit_token_to_pid(request
->audit_token
) == 0)
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
);
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
);
4424 case mdns_trust_status_denied
:
4425 case mdns_trust_status_pending
:
4427 mdns_trust_t trust
= mdns_trust_create(request
->audit_token
, NULL
, flags
);
4430 err
= mStatus_NoMemoryErr
;
4434 void * context
= mallocL("context/_handle_addrinfo_request_with_trust", sizeof(_addrinfo_start_params_t
));
4437 my_perror("ERROR: mallocL context/_handle_addrinfo_request_with_trust");
4438 mdns_release(trust
);
4439 err
= mStatus_NoMemoryErr
;
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
)
4447 if (event
== mdns_trust_event_result
)
4449 mStatus error
= (update
!= mdns_trust_status_granted
) ? mStatus_PolicyDenied
: mStatus_NoError
;
4451 _addrinfo_start_params_t
* _params
= mdns_trust_get_context(trust
);
4456 error
= _handle_addrinfo_request_start(request
, _params
);
4457 // No context means the request was canceled before we got here
4459 if (error
) // (not else if) Always check for error result
4461 _return_addrinfo_request_error(request
, error
);
4464 KQueueUnlock("_handle_addrinfo_request_with_trust");
4467 request
->trust
= trust
;
4468 mdns_trust_activate(trust
);
4469 err
= mStatus_NoError
;
4473 case mdns_trust_status_no_entitlement
:
4474 err
= mStatus_NoAuth
;
4477 case mdns_trust_status_granted
:
4478 err
= _handle_addrinfo_request_start(request
, params
);
4482 err
= mStatus_UnknownErr
;
4489 #endif // TRUST_ENFORCEMENT
4491 mDNSlocal mStatus
handle_addrinfo_request(request_state
*request
)
4494 DNSServiceFlags flags
;
4495 mDNSu32 interfaceIndex
;
4496 _addrinfo_start_params_t params
;
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)
4503 err
= mStatus_BadParamErr
;
4506 if (!request
->msgptr
)
4508 LogMsg("%3d: DNSServiceGetAddrInfo(unreadable parameters)", request
->sd
);
4509 err
= mStatus_BadParamErr
;
4512 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
4513 params
.require_privacy
= mDNSfalse
;
4515 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
4516 if (request
->msgptr
&& (request
->hdr
.ipc_flags
& IPC_FLAGS_TRAILING_TLVS
))
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
);
4524 request
->custom_service_id
= Querier_RegisterCustomDNSServiceWithPListData(data
, len
);
4526 params
.require_privacy
= ipc_tlv_get_require_privacy(start
, end
);
4529 request
->flags
= flags
;
4530 request
->interfaceIndex
= interfaceIndex
;
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
,
4537 mDNSPlatformMemZero(&request
->u
.addrinfo
, (mDNSu32
)sizeof(request
->u
.addrinfo
));
4538 request
->terminate
= NULL
;
4540 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
4541 if (os_feature_enabled(mDNSResponder
, bonjour_privacy
))
4543 err
= _handle_addrinfo_request_with_trust(request
, ¶ms
);
4547 err
= _handle_addrinfo_request_start(request
, ¶ms
);
4550 err
= _handle_addrinfo_request_start(request
, ¶ms
);
4557 // ***************************************************************************
4558 #if COMPILER_LIKES_PRAGMA_MARK
4560 #pragma mark - Main Request Handler etc.
4563 mDNSlocal request_state
*NewRequest(void)
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
;
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
)
4578 if (req
->ts
== t_terminated
|| req
->ts
== t_error
)
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
);
4586 if (req
->ts
== t_complete
) // this must be death or something is wrong
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
);
4598 if (req
->ts
!= t_morecoming
)
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
);
4606 if (req
->hdr_bytes
< sizeof(ipc_msg_hdr
))
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
))
4615 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
4616 "[R%u] ERROR: read_msg - read too many header bytes", req
->request_id
);
4621 // only read data if header is complete
4622 if (req
->hdr_bytes
== sizeof(ipc_msg_hdr
))
4624 ConvertHeaderBytes(&req
->hdr
);
4625 if (req
->hdr
.version
!= VERSION
)
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
);
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)
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
);
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
;
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
)
4656 mDNSu32 nleft
= req
->hdr
.datalen
- req
->data_bytes
;
4658 #if !defined(_WIN32)
4659 struct iovec vec
= { req
->msgbuf
+ req
->data_bytes
, nleft
}; // Tell recvmsg where we want the bytes put
4661 struct cmsghdr
*cmsg
;
4662 char cbuf
[CMSG_SPACE(4 * sizeof(dnssd_sock_t
))];
4664 msg
.msg_namelen
= 0;
4667 msg
.msg_control
= cbuf
;
4668 msg
.msg_controllen
= sizeof(cbuf
);
4670 nread
= recvmsg(req
->sd
, &msg
, 0);
4672 nread
= udsSupportReadFD(req
->sd
, (char *)req
->msgbuf
+ req
->data_bytes
, nleft
, 0, req
->platform_data
);
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
)
4679 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
4680 "[R%u] ERROR: read_msg - read too many data bytes", req
->request_id
);
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
)
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
)
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
);
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
)
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
);
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
)
4727 if (req
->terminate
&& req
->hdr
.op
!= cancel_request
)
4729 dnssd_sockaddr_t cliaddr
;
4730 #if defined(USE_TCP_LOOPBACK)
4733 port
.b
[0] = req
->msgptr
[0];
4734 port
.b
[1] = req
->msgptr
[1];
4736 cliaddr
.sin_family
= AF_INET
;
4737 cliaddr
.sin_port
= port
.NotAnInteger
;
4738 cliaddr
.sin_addr
.s_addr
= inet_addr(MDNS_TCP_SERVERADDR
);
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)
4750 if (req
->errsd
== req
->sd
)
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
);
4761 req
->errsd
= socket(AF_DNSSD
, SOCK_STREAM
, 0);
4762 if (!dnssd_SocketValid(req
->errsd
))
4764 my_throttled_perror("ERROR: socket");
4769 if (connect(req
->errsd
, (struct sockaddr
*)&cliaddr
, sizeof(cliaddr
)) < 0)
4771 #if !defined(USE_TCP_LOOPBACK)
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)
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
));
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
);
4793 #if !defined(USE_TCP_LOOPBACK)
4798 if (ioctlsocket(req
->errsd
, FIONBIO
, &opt
) != 0)
4800 if (fcntl(req
->errsd
, F_SETFL
, fcntl(req
->errsd
, F_GETFL
, 0) | O_NONBLOCK
) != 0)
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
));
4811 req
->ts
= t_complete
;
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
));
4823 mDNSlocal mStatus
handle_client_request(request_state
*req
)
4825 mStatus err
= mStatus_NoError
;
4826 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
4827 SetupAuditTokenForRequest(req
);
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
;
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
);
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;
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
;
4873 #define RecordOrientedOp(X) \
4874 ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request)
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)
4879 mDNSlocal
void request_callback(int fd
, void *info
)
4882 request_state
*req
= info
;
4883 mDNSs32 min_size
= sizeof(DNSServiceFlags
);
4889 if (req
->ts
== t_morecoming
)
4891 if (req
->ts
== t_terminated
|| req
->ts
== t_error
)
4893 AbortUnlinkAndFree(req
);
4896 if (req
->ts
!= t_complete
)
4898 LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req
->ts
, req
->process_id
, req
->pid_name
);
4899 AbortUnlinkAndFree(req
);
4903 switch(req
->hdr
.op
) // Interface + other data
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;
4929 if ((mDNSs32
)req
->data_bytes
< min_size
)
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
);
4936 if (LightweightOp(req
->hdr
.op
) && !req
->terminate
)
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
);
4944 // If req->terminate is already set, this means this operation is sharing an existing connection
4945 if (req
->terminate
&& !LightweightOp(req
->hdr
.op
))
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
;
4960 // if the parent request is a delegate connection, copy the
4964 newreq
->validUUID
= mDNStrue
;
4965 mDNSPlatformMemCopy(newreq
->uuid
, req
->uuid
, UUID_SIZE
);
4969 if (req
->process_id
)
4971 newreq
->process_id
= req
->process_id
;
4972 mDNSPlatformStrLCopy(newreq
->pid_name
, req
->pid_name
, (mDNSu32
)sizeof(newreq
->pid_name
));
4976 set_peer_pid(newreq
);
4982 // Check if the request wants no asynchronous replies.
4983 if (req
->hdr
.ipc_flags
& IPC_FLAGS_NOREPLY
) req
->no_reply
= 1;
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
;
4990 err
= handle_client_request(req
);
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
);
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
)
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
)
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
;
5010 // Reset ready to accept the next req on this pipe
5011 if (req
->primary
) req
= req
->primary
;
5012 req
->ts
= t_morecoming
;
5014 req
->data_bytes
= 0;
5015 req
->msgbuf
= mDNSNULL
;
5016 req
->msgptr
= mDNSNULL
;
5021 mDNSlocal
void connect_callback(int fd
, void *info
)
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;
5030 (void)info
; // Unused
5032 if (!dnssd_SocketValid(sd
))
5034 if (dnssd_errno
!= dnssd_EWOULDBLOCK
)
5035 my_throttled_perror("ERROR: accept");
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
));
5046 if (ioctlsocket(sd
, FIONBIO
, &optval
) != 0)
5048 if (fcntl(sd
, F_SETFL
, fcntl(sd
, F_GETFL
, 0) | O_NONBLOCK
) != 0)
5051 my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
5057 request_state
*request
= NewRequest();
5058 request
->ts
= t_morecoming
;
5060 request
->errsd
= sd
;
5061 request
->request_id
= GetNewRequestID();
5062 set_peer_pid(request
);
5063 #if APPLE_OSX_mDNSResponder
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
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
);
5077 mDNSlocal mDNSBool
uds_socket_setup(dnssd_sock_t skt
)
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");
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
5091 if (ioctlsocket(skt
, FIONBIO
, &opt
) != 0)
5093 if (fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
) != 0)
5096 my_perror("ERROR: could not set listen socket to non-blocking mode");
5100 if (listen(skt
, LISTENQ
) != 0)
5102 my_perror("ERROR: could not listen on listen socket");
5106 if (mStatus_NoError
!= udsSupportAddFDToEventLoop(skt
, connect_callback
, (void *) NULL
, (void **) NULL
))
5108 my_perror("ERROR: could not add listen socket to event loop");
5113 LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt
);
5114 mDNSStorage
.uds_listener_skt
= skt
;
5119 #if MDNS_MALLOC_DEBUGGING
5120 mDNSlocal
void udsserver_validatelists(void *context
);
5123 mDNSexport
int udsserver_init(dnssd_sock_t skts
[], const size_t count
)
5125 dnssd_sockaddr_t laddr
;
5129 FILE *fp
= fopen(PID_FILE
, "w");
5132 fprintf(fp
, "%d\n", getpid());
5137 #if MDNS_MALLOC_DEBUGGING
5138 static mDNSListValidator validator
;
5139 mDNSPlatformAddListValidator(&validator
, udsserver_validatelists
, "udsserver_validatelists", NULL
);
5145 for (i
= 0; i
< count
; i
++)
5146 if (dnssd_SocketValid(skts
[i
]) && !uds_socket_setup(skts
[i
]))
5151 listenfd
= socket(AF_DNSSD
, SOCK_STREAM
, 0);
5152 if (!dnssd_SocketValid(listenfd
))
5154 my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
5158 mDNSPlatformMemZero(&laddr
, sizeof(laddr
));
5160 #if defined(USE_TCP_LOOPBACK)
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
));
5168 my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
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
);
5182 if (strlen(boundPath
) >= sizeof(laddr
.sun_path
))
5184 LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr
.sun_path
));
5187 mDNSPlatformStrLCopy(laddr
.sun_path
, boundPath
, sizeof(laddr
.sun_path
));
5188 ret
= bind(listenfd
, (struct sockaddr
*) &laddr
, sizeof(laddr
));
5192 my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
5198 if (!uds_socket_setup(listenfd
)) goto error
;
5201 #if !defined(PLATFORM_NO_RLIMIT)
5203 // Set maximum number of open file descriptors
5204 #define MIN_OPENFILES 10240
5205 struct rlimit maxfds
, newfds
;
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");
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");
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
);
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
);
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
);
5235 udsserver_handle_configchange(&mDNSStorage
);
5240 my_perror("ERROR: udsserver_init");
5244 mDNSexport
int udsserver_exit(void)
5246 // Cancel all outstanding client requests
5247 while (all_requests
) AbortUnlinkAndFree(all_requests
);
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
)
5253 ARListElem
*rem
= LocalDomainEnumRecords
;
5254 LocalDomainEnumRecords
= LocalDomainEnumRecords
->next
;
5255 mDNS_Deregister(&mDNSStorage
, &rem
->ar
);
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
))
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
);
5279 mDNSlocal
void LogClientInfoToFD(int fd
, request_state
*req
)
5284 mDNS_snprintf(reqIDStr
, sizeof(reqIDStr
), "[R%u]", req
->request_id
);
5286 mDNS_snprintf(prefix
, sizeof(prefix
), "%-6s %2s", reqIDStr
, req
->primary
? "->" : "");
5288 if (!req
->terminate
)
5289 LogToFD(fd
, "%s No operation yet on this socket", prefix
);
5290 else if (req
->terminate
== connection_termination
)
5292 int num_records
= 0, num_ops
= 0;
5293 const registered_record_entry
*p
;
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
);
5305 else if (req
->terminate
== regservice_termination_callback
)
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
);
5314 else if (req
->terminate
== browse_termination_callback
)
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
);
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)",
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
);
5352 LogToFD(fd
, "%s Unrecognized operation %p", prefix
, req
->terminate
);
5355 mDNSlocal
void LogClientInfo(request_state
*req
)
5360 mDNS_snprintf(reqIDStr
, sizeof(reqIDStr
), "[R%u]", req
->request_id
);
5362 mDNS_snprintf(prefix
, sizeof(prefix
), "%-6s %2s", reqIDStr
, req
->primary
? "->" : "");
5364 if (!req
->terminate
)
5365 LogMsgNoIdent("%s No operation yet on this socket", prefix
);
5366 else if (req
->terminate
== connection_termination
)
5368 int num_records
= 0, num_ops
= 0;
5369 const registered_record_entry
*p
;
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
);
5381 else if (req
->terminate
== regservice_termination_callback
)
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
);
5390 else if (req
->terminate
== browse_termination_callback
)
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
);
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)",
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
);
5428 LogMsgNoIdent("%s Unrecognized operation %p", prefix
, req
->terminate
);
5431 mDNSlocal
void GetMcastClients(request_state
*req
)
5433 if (req
->terminate
== connection_termination
)
5435 int num_records
= 0, num_ops
= 0;
5436 const registered_record_entry
*p
;
5438 for (p
= req
->u
.reg_recs
; p
; p
=p
->next
)
5440 for (r
= req
->next
; r
; r
=r
->next
)
5441 if (r
->primary
== req
)
5443 for (p
= req
->u
.reg_recs
; p
; p
=p
->next
)
5445 if (!AuthRecord_uDNS(p
->rr
))
5448 for (r
= req
->next
; r
; r
=r
->next
)
5449 if (r
->primary
== req
)
5452 else if (req
->terminate
== regservice_termination_callback
)
5454 service_instance
*ptr
;
5455 for (ptr
= req
->u
.servicereg
.instances
; ptr
; ptr
= ptr
->next
)
5457 if (!AuthRecord_uDNS(&ptr
->srs
.RR_SRV
))
5461 else if (req
->terminate
== browse_termination_callback
)
5464 for (blist
= req
->u
.browser
.browsers
; blist
; blist
= blist
->next
)
5466 if (mDNSOpaque16IsZero(blist
->q
.TargetQID
))
5470 else if (req
->terminate
== resolve_termination_callback
)
5472 if ((mDNSOpaque16IsZero(req
->u
.resolve
.qsrv
.TargetQID
)) && (req
->u
.resolve
.qsrv
.ThisQInterval
> 0))
5475 else if (req
->terminate
== queryrecord_termination_callback
)
5477 if (QueryRecordClientRequestIsMulticast(&req
->u
.queryrecord
))
5480 else if (req
->terminate
== addrinfo_termination_callback
)
5482 if (GetAddrInfoClientRequestIsMulticast(&req
->u
.addrinfo
))
5492 mDNSlocal
void LogMcastClientInfo(request_state
*req
)
5494 if (!req
->terminate
)
5495 LogMcastNoIdent("No operation yet on this socket");
5496 else if (req
->terminate
== connection_termination
)
5498 int num_records
= 0, num_ops
= 0;
5499 const registered_record_entry
*p
;
5501 for (p
= req
->u
.reg_recs
; p
; p
=p
->next
)
5503 for (r
= req
->next
; r
; r
=r
->next
)
5504 if (r
->primary
== req
)
5506 for (p
= req
->u
.reg_recs
; p
; p
=p
->next
)
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
++);
5512 for (r
= req
->next
; r
; r
=r
->next
)
5513 if (r
->primary
== req
)
5514 LogMcastClientInfo(r
);
5516 else if (req
->terminate
== regservice_termination_callback
)
5518 service_instance
*ptr
;
5519 for (ptr
= req
->u
.servicereg
.instances
; ptr
; ptr
= ptr
->next
)
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
++);
5526 else if (req
->terminate
== browse_termination_callback
)
5529 for (blist
= req
->u
.browser
.browsers
; blist
; blist
= blist
->next
)
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
++);
5536 else if (req
->terminate
== resolve_termination_callback
)
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
++);
5542 else if (req
->terminate
== queryrecord_termination_callback
)
5544 if (QueryRecordClientRequestIsMulticast(&req
->u
.queryrecord
))
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
++);
5552 else if (req
->terminate
== addrinfo_termination_callback
)
5554 if (GetAddrInfoClientRequestIsMulticast(&req
->u
.addrinfo
))
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
++);
5564 mDNSlocal
char *RecordTypeName(mDNSu8 rtype
)
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");
5579 mDNSlocal
int LogEtcHostsToFD(int fd
, mDNS
*const m
)
5581 mDNSBool showheader
= mDNStrue
;
5582 const AuthRecord
*ar
;
5587 mDNSBool truncated
= 0;
5589 for (slot
= 0; slot
< AUTH_HASH_SLOTS
; slot
++)
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
)
5595 if (ar
->RecordCallback
!= FreeEtcHosts
) continue;
5596 if (showheader
) { showheader
= mDNSfalse
; LogToFD(fd
, " State Interface"); }
5598 // Print a maximum of 50 records
5599 if (count
++ >= 50) { truncated
= mDNStrue
; continue; }
5600 if (ar
->ARType
== AuthRecordLocalOnly
)
5602 if (ar
->resrec
.InterfaceID
== mDNSInterface_LocalOnly
)
5603 LogToFD(fd
, " %s LO %s", RecordTypeName(ar
->resrec
.RecordType
), ARDisplayString(m
, ar
));
5606 mDNSu32 scopeid
= (mDNSu32
)(uintptr_t)ar
->resrec
.InterfaceID
;
5607 LogToFD(fd
, " %s %u %s", RecordTypeName(ar
->resrec
.RecordType
), scopeid
, ARDisplayString(m
, ar
));
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
);
5618 mDNSlocal
void LogLocalOnlyAuthRecordsToFD(int fd
, mDNS
*const m
)
5620 mDNSBool showheader
= mDNStrue
;
5621 const AuthRecord
*ar
;
5625 for (slot
= 0; slot
< AUTH_HASH_SLOTS
; slot
++)
5627 for (ag
= m
->rrauth
.rrauth_hash
[slot
]; ag
; ag
= ag
->next
)
5628 for (ar
= ag
->members
; ar
; ar
= ar
->next
)
5630 if (ar
->RecordCallback
== FreeEtcHosts
) continue;
5631 if (showheader
) { showheader
= mDNSfalse
; LogToFD(fd
, " State Interface"); }
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
)
5638 if (ar
->resrec
.InterfaceID
== mDNSInterface_BLE
)
5639 LogToFD(fd
, " %s BLE %s", RecordTypeName(ar
->resrec
.RecordType
), ARDisplayString(m
, ar
));
5641 LogToFD(fd
, " %s PP %s", RecordTypeName(ar
->resrec
.RecordType
), ARDisplayString(m
, ar
));
5646 if (showheader
) LogToFD(fd
, "<None>");
5649 mDNSlocal
void LogOneAuthRecordToFD(int fd
, const AuthRecord
*ar
, mDNSs32 now
, const char *ifname
)
5651 if (AuthRecord_uDNS(ar
))
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,
5659 ar
->AllowRemoteQuery
? "☠" : " ",
5660 ARDisplayString(&mDNSStorage
, ar
));
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
));
5675 mDNSlocal
void LogAuthRecordsToFD(int fd
,
5676 const mDNSs32 now
, AuthRecord
*ResourceRecords
, int *proxy
)
5678 mDNSBool showheader
= mDNStrue
;
5679 const AuthRecord
*ar
;
5680 OwnerOptData owner
= zeroOwner
;
5681 for (ar
= ResourceRecords
; ar
; ar
=ar
->next
)
5683 const char *const ifname
= InterfaceNameForID(&mDNSStorage
, ar
->resrec
.InterfaceID
);
5684 if ((ar
->WakeUp
.HMAC
.l
[0] != 0) == (proxy
!= mDNSNULL
))
5686 if (showheader
) { showheader
= mDNSfalse
; LogToFD(fd
, " Int Next Expire if State"); }
5687 if (proxy
) (*proxy
)++;
5688 if (!mDNSPlatformMemSame(&owner
, &ar
->WakeUp
, sizeof(owner
)))
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
);
5696 LogToFD(fd
, "Proxying for %.6a seq %d", &owner
.HMAC
, owner
.seq
);
5698 if (AuthRecord_uDNS(ar
))
5700 LogOneAuthRecordToFD(fd
, ar
, now
, ifname
);
5702 else if (ar
->ARType
== AuthRecordLocalOnly
)
5704 LogToFD(fd
, " LO %s", ARDisplayString(&mDNSStorage
, ar
));
5706 else if (ar
->ARType
== AuthRecordP2P
)
5708 if (ar
->resrec
.InterfaceID
== mDNSInterface_BLE
)
5709 LogToFD(fd
, " BLE %s", ARDisplayString(&mDNSStorage
, ar
));
5711 LogToFD(fd
, " PP %s", ARDisplayString(&mDNSStorage
, ar
));
5715 LogOneAuthRecordToFD(fd
, ar
, now
, ifname
);
5719 if (showheader
) LogToFD(fd
, "<None>");
5722 mDNSlocal
void PrintOneCacheRecordToFD(int fd
, const CacheRecord
*cr
, mDNSu32 slot
, const mDNSu32 remain
, const char *ifname
, mDNSu32
*CacheUsed
)
5724 LogToFD(fd
, "%3d %s%8d %-7s%s %-6s%s",
5726 cr
->CRActiveQuestion
? "*" : " ",
5728 ifname
? ifname
: "-U-",
5729 (cr
->resrec
.RecordType
== kDNSRecordTypePacketNegative
) ? "-" :
5730 (cr
->resrec
.RecordType
& kDNSRecordTypePacketUniqueMask
) ? " " : "+",
5731 DNSTypeName(cr
->resrec
.rrtype
),
5732 CRDisplayString(&mDNSStorage
, cr
));
5736 mDNSlocal
void PrintCachedRecordsToFD(int fd
, const CacheRecord
*cr
, mDNSu32 slot
, const mDNSu32 remain
, const char *ifname
, mDNSu32
*CacheUsed
)
5743 PrintOneCacheRecordToFD(fd
, soa
, slot
, remain
, ifname
, CacheUsed
);
5747 mDNSexport
void LogMDNSStatisticsToFD(int fd
, mDNS
*const m
)
5749 LogToFD(fd
, "--- MDNS Statistics ---");
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
, "--------------------------------");
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
, "--------------------------------");
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
);
5781 mDNSexport
void udsserver_info_dump_to_fd(int fd
)
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
;
5796 LogToFD(fd
, "------------ Cache -------------");
5797 LogToFD(fd
, "Slt Q TTL if U Type rdlen");
5798 for (slot
= 0; slot
< CACHE_HASH_SLOTS
; slot
++)
5800 for (cg
= m
->rrcache_hash
[slot
]; cg
; cg
=cg
->next
)
5802 groupCount
++; // Count one cache entity for the CacheGroup object
5803 for (cr
= cg
->members
; cr
; cr
=cr
->next
)
5805 const mDNSs32 remain
= cr
->resrec
.rroriginalttl
- (now
- cr
->TimeRcvd
) / mDNSPlatformOneSecond
;
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
))
5813 InterfaceID
= (mDNSInterfaceID
)(uintptr_t)mdns_dns_service_get_interface_index(cr
->resrec
.dnsservice
);
5816 if (!InterfaceID
&& cr
->resrec
.rDNSServer
&& cr
->resrec
.rDNSServer
->scopeType
)
5817 InterfaceID
= cr
->resrec
.rDNSServer
->interface
;
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
);
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
);
5835 LogToFD(fd
, "--------- Auth Records ---------");
5836 LogAuthRecordsToFD(fd
, now
, m
->ResourceRecords
, mDNSNULL
);
5838 LogToFD(fd
, "--------- LocalOnly, P2P Auth Records ---------");
5839 LogLocalOnlyAuthRecordsToFD(fd
, m
);
5841 LogToFD(fd
, "--------- /etc/hosts ---------");
5842 LogEtcHostsToFD(fd
, m
);
5844 LogToFD(fd
, "------ Duplicate Records -------");
5845 LogAuthRecordsToFD(fd
, now
, m
->DuplicateRecords
, mDNSNULL
);
5847 LogToFD(fd
, "----- Auth Records Proxied -----");
5848 LogAuthRecordsToFD(fd
, now
, m
->ResourceRecords
, &ProxyA
);
5850 LogToFD(fd
, "-- Duplicate Records Proxied ---");
5851 LogAuthRecordsToFD(fd
, now
, m
->DuplicateRecords
, &ProxyD
);
5853 LogToFD(fd
, "---------- Questions -----------");
5854 if (!m
->Questions
) LogToFD(fd
, "<None>");
5859 LogToFD(fd
, " Int Next if T NumAns VDNS Qptr DupOf SU SQ Type Name");
5860 for (q
= m
->Questions
; q
; q
=q
->next
)
5862 mDNSs32 i
= q
->ThisQInterval
/ mDNSPlatformOneSecond
;
5863 mDNSs32 n
= (NextQSendTime(q
) - now
) / mDNSPlatformOneSecond
;
5864 char *ifname
= InterfaceNameForID(m
, q
->InterfaceID
);
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",
5870 LogToFD(fd
, "%6d%6d %-7s%s %5d 0x%08x%08x%08x%08x 0x%p 0x%p %1d %2d %-5s%##s%s",
5873 ifname
? ifname
: mDNSOpaque16IsZero(q
->TargetQID
) ? "" : "-U-",
5874 mDNSOpaque16IsZero(q
->TargetQID
) ? (q
->LongLived
? "l" : " ") : (q
->LongLived
? "L" : "O"),
5876 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
5877 q
->validDNSServers
.l
[3], q
->validDNSServers
.l
[2], q
->validDNSServers
.l
[1], q
->validDNSServers
.l
[0],
5880 q
->SuppressUnusable
, q
->Suppressed
, DNSTypeName(q
->qtype
), q
->qname
.c
,
5881 q
->DuplicateOf
? " (dup)" : "");
5883 LogToFD(fd
, "%lu question%s; %lu active", CacheUsed
, CacheUsed
> 1 ? "s" : "", CacheActive
);
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)" : "");
5893 LogToFD(fd
, "---- Active UDS Client Requests ----");
5894 if (!all_requests
) LogToFD(fd
, "<None>");
5897 request_state
*req
, *r
;
5898 for (req
= all_requests
; req
; req
=req
->next
)
5900 if (req
->primary
) // If this is a subbordinate operation, check that the parent is in the list
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
);
5905 // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
5906 LogClientInfoToFD(fd
, req
);
5911 LogToFD(fd
, "-------- NAT Traversals --------");
5912 LogToFD(fd
, "ExtAddress %.4a Retry %d Interval %d",
5914 m
->retryGetAddr
? (m
->retryGetAddr
- now
) / mDNSPlatformOneSecond
: 0,
5915 m
->retryIntervalGetAddr
/ mDNSPlatformOneSecond
);
5916 if (m
->NATTraversals
)
5918 const NATTraversalInfo
*nat
;
5919 for (nat
= m
->NATTraversals
; nat
; nat
=nat
->next
)
5921 LogToFD(fd
, "%p %s Int %5d %s Err %d Retry %5d Interval %5d Expire %5d Req %.4a:%d Ext %.4a:%d",
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 " ),
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
));
5939 LogToFD(fd
, "--------- AuthInfoList ---------");
5940 if (!m
->AuthInfoList
) LogToFD(fd
, "<None>");
5943 const DomainAuthInfo
*a
;
5944 for (a
= m
->AuthInfoList
; a
; a
= a
->next
)
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));
5953 LogToFD(fd
, "---------- Misc State ----------");
5955 LogToFD(fd
, "PrimaryMAC: %.6a", &m
->PrimaryMAC
);
5957 LogToFD(fd
, "m->SleepState %d (%s) seq %d",
5959 m
->SleepState
== SleepState_Awake
? "Awake" :
5960 m
->SleepState
== SleepState_Transferring
? "Transferring" :
5961 m
->SleepState
== SleepState_Sleeping
? "Sleeping" : "?",
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
);
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
);
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
);
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
);
5979 LogToFD(fd
, "--- Search Domains --");
5980 if (!SearchList
) LogToFD(fd
, "<None>");
5983 for (s
=SearchList
; s
; s
=s
->next
)
5985 char *ifname
= InterfaceNameForID(m
, s
->InterfaceID
);
5986 LogToFD(fd
, "%##s %s", s
->domain
.c
, ifname
? ifname
: "");
5989 LogMDNSStatisticsToFD(fd
, m
);
5991 LogToFD(fd
, "---- Task Scheduling Timers ----");
5993 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
5994 LogToFD(fd
, "BonjourEnabled %d", m
->BonjourEnabled
);
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
6002 if (!m
->NewQuestions
)
6003 LogToFD(fd
, "NewQuestion <NONE>");
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
));
6009 if (!m
->NewLocalOnlyQuestions
)
6010 LogToFD(fd
, "NewLocalOnlyQuestions <NONE>");
6012 LogToFD(fd
, "NewLocalOnlyQuestions %##s (%s)",
6013 m
->NewLocalOnlyQuestions
->qname
.c
, DNSTypeName(m
->NewLocalOnlyQuestions
->qtype
));
6015 if (!m
->NewLocalRecords
)
6016 LogToFD(fd
, "NewLocalRecords <NONE>");
6018 LogToFD(fd
, "NewLocalRecords %02X %s", m
->NewLocalRecords
->resrec
.RecordType
, ARDisplayString(m
, m
->NewLocalRecords
));
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
);
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
);
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
);
6043 LogTimerToFD(fd
, "m->NextCacheCheck ", m
->NextCacheCheck
);
6044 LogTimerToFD(fd
, "m->NextScheduledSPS ", m
->NextScheduledSPS
);
6045 LogTimerToFD(fd
, "m->NextScheduledKA ", m
->NextScheduledKA
);
6047 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
6048 LogTimerToFD(fd
, "m->NextBonjourDisableTime ", m
->NextBonjourDisableTime
);
6051 LogTimerToFD(fd
, "m->NextScheduledSPRetry ", m
->NextScheduledSPRetry
);
6052 LogTimerToFD(fd
, "m->DelaySleep ", m
->DelaySleep
);
6054 LogTimerToFD(fd
, "m->NextScheduledQuery ", m
->NextScheduledQuery
);
6055 LogTimerToFD(fd
, "m->NextScheduledProbe ", m
->NextScheduledProbe
);
6056 LogTimerToFD(fd
, "m->NextScheduledResponse", m
->NextScheduledResponse
);
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
);
6066 #if MDNS_MALLOC_DEBUGGING
6067 mDNSlocal
void udsserver_validatelists(void *context
)
6069 const request_state
*req
, *p
;
6070 (void)context
; // unused
6071 for (req
= all_requests
; req
; req
=req
->next
)
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
);
6076 if (req
->primary
== req
)
6077 LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req
, req
->sd
);
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
);
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
);
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
);
6094 if (req
->terminate
== connection_termination
)
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
);
6101 else if (req
->terminate
== regservice_termination_callback
)
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
);
6108 else if (req
->terminate
== browse_termination_callback
)
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
);
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]);
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]);
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]);
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]);
6135 #endif // MDNS_MALLOC_DEBUGGING
6137 mDNSlocal
int send_msg(request_state
*const req
)
6139 reply_state
*const rep
= req
->replies
; // Send the first waiting reply
6142 ConvertHeaderBytes(rep
->mhdr
);
6143 nwriten
= send(req
->sd
, (char *)&rep
->mhdr
+ rep
->nwriten
, rep
->totallen
- rep
->nwriten
, 0);
6144 ConvertHeaderBytes(rep
->mhdr
);
6148 if (dnssd_errno
== dnssd_EINTR
|| dnssd_errno
== dnssd_EWOULDBLOCK
) nwriten
= 0;
6151 #if !defined(PLATFORM_NO_EPIPE)
6152 if (dnssd_errno
== EPIPE
)
6153 return(req
->ts
= t_terminated
);
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
));
6163 rep
->nwriten
+= nwriten
;
6164 return (rep
->nwriten
== rep
->totallen
) ? t_complete
: t_morecoming
;
6167 mDNSexport mDNSs32
udsserver_idle(mDNSs32 nextevent
)
6169 mDNSs32 now
= mDNS_TimeNow(&mDNSStorage
);
6170 request_state
**req
= &all_requests
;
6174 request_state
*const r
= *req
;
6176 if (r
->terminate
== resolve_termination_callback
)
6177 if (r
->u
.resolve
.ReportTime
&& now
- r
->u
.resolve
.ReportTime
>= 0)
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
);
6185 // Note: Only primary req's have reply lists, not subordinate req's.
6186 while (r
->replies
) // Send queued replies
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
)
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;
6201 else if (result
== t_terminated
)
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
);
6206 else if (result
== t_error
)
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
);
6215 if (r
->replies
) // If we failed to send everything, check our time_blocked timer
6217 if (nextevent
- now
> mDNSPlatformOneSecond
)
6218 nextevent
= now
+ mDNSPlatformOneSecond
;
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))
6229 struct reply_state
*x
= r
->replies
;
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)
6239 LogMsg("%3d: Client PID[%d](%s) unresponsive; aborting connection", r
->sd
, r
->process_id
, r
->pid_name
);
6246 if (!dnssd_SocketValid(r
->sd
)) // If this request is finished, unlink it from the list and free the memory
6248 // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
6250 freeL("request_state/udsserver_idle", r
);
6258 struct CompileTimeAssertionChecks_uds_daemon
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];
6272 #include "../unittests/uds_daemon_ut.c"