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