1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #if __APPLE__ 19 // In Mac OS X 10.5 and later trying to use the daemon function gives a daemon is deprecated 20 // error, which prevents compilation because we build with "-Werror". 21 // Since this is supposed to be portable cross-platform code, we don't care that daemon is 22 // deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message. 23 #define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou 24 #endif 25 26 #include <signal.h> 27 #include <pthread.h> 28 #include <stdlib.h> 29 #include <unistd.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <netinet/in.h> 33 #include <arpa/inet.h> 34 #include <stdio.h> 35 #include <syslog.h> 36 #include <string.h> 37 #include <sys/time.h> 38 #include <sys/resource.h> 39 #include <time.h> 40 #include <errno.h> 41 42 #if __APPLE__ 43 #undef daemon 44 extern int daemon(int, int); 45 #endif 46 47 // Solaris doesn't have daemon(), so we define it here 48 #ifdef NOT_HAVE_DAEMON 49 #include "../mDNSPosix/mDNSUNP.h" // For daemon() 50 #endif // NOT_HAVE_DAEMON 51 52 #include "dnsextd.h" 53 #include "../mDNSShared/uds_daemon.h" 54 #include "../mDNSShared/dnssd_ipc.h" 55 #include "../mDNSCore/uDNS.h" 56 #include "../mDNSShared/DebugServices.h" 57 58 // Compatibility workaround 59 #ifndef AF_LOCAL 60 #define AF_LOCAL AF_UNIX 61 #endif 62 63 // 64 // Constants 65 // 66 mDNSexport const char ProgramName[] = "dnsextd"; 67 68 #define LOOPBACK "127.0.0.1" 69 #if !defined(LISTENQ) 70 # define LISTENQ 128 // tcp connection backlog 71 #endif 72 #define RECV_BUFLEN 9000 73 #define LEASETABLE_INIT_NBUCKETS 256 // initial hashtable size (doubles as table fills) 74 #define EXPIRATION_INTERVAL 300 // check for expired records every 5 minutes 75 #define SRV_TTL 7200 // TTL For _dns-update SRV records 76 #define CONFIG_FILE "/etc/dnsextd.conf" 77 #define TCP_SOCKET_FLAGS kTCPSocketFlags_UseTLS 78 79 // LLQ Lease bounds (seconds) 80 #define LLQ_MIN_LEASE (15 * 60) 81 #define LLQ_MAX_LEASE (120 * 60) 82 #define LLQ_LEASE_FUDGE 60 83 84 // LLQ SOA poll interval (microseconds) 85 #define LLQ_MONITOR_ERR_INTERVAL (60 * 1000000) 86 #define LLQ_MONITOR_INTERVAL 250000 87 #ifdef SIGINFO 88 #define INFO_SIGNAL SIGINFO 89 #else 90 #define INFO_SIGNAL SIGUSR1 91 #endif 92 93 #define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y)) 94 95 // 96 // Data Structures 97 // Structs/fields that must be locked for thread safety are explicitly commented 98 // 99 100 // args passed to UDP request handler thread as void* 101 102 typedef struct 103 { 104 PktMsg pkt; 105 struct sockaddr_in cliaddr; 106 DaemonInfo *d; 107 int sd; 108 } UDPContext; 109 110 // args passed to TCP request handler thread as void* 111 typedef struct 112 { 113 PktMsg pkt; 114 struct sockaddr_in cliaddr; 115 TCPSocket *sock; // socket connected to client 116 DaemonInfo *d; 117 } TCPContext; 118 119 // args passed to UpdateAnswerList thread as void* 120 typedef struct 121 { 122 DaemonInfo *d; 123 AnswerListElem *a; 124 } UpdateAnswerListArgs; 125 126 // 127 // Global Variables 128 // 129 130 // booleans to determine runtime output 131 // read-only after initialization (no mutex protection) 132 static mDNSBool foreground = 0; 133 static mDNSBool verbose = 0; 134 135 // globals set via signal handler (accessed exclusively by main select loop and signal handler) 136 static mDNSBool terminate = 0; 137 static mDNSBool dumptable = 0; 138 static mDNSBool hangup = 0; 139 140 // global for config file location 141 static char * cfgfile = NULL; 142 143 // 144 // Logging Routines 145 // Log messages are delivered to syslog unless -f option specified 146 // 147 148 // common message logging subroutine 149 mDNSlocal void PrintLog(const char *buffer) 150 { 151 if (foreground) 152 { 153 fprintf(stderr,"%s\n", buffer); 154 fflush(stderr); 155 } 156 else 157 { 158 openlog("dnsextd", LOG_CONS, LOG_DAEMON); 159 syslog(LOG_ERR, "%s", buffer); 160 closelog(); 161 } 162 } 163 164 // Verbose Logging (conditional on -v option) 165 mDNSlocal void VLog(const char *format, ...) 166 { 167 char buffer[512]; 168 va_list ptr; 169 170 if (!verbose) return; 171 va_start(ptr,format); 172 buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; 173 va_end(ptr); 174 PrintLog(buffer); 175 } 176 177 // Unconditional Logging 178 mDNSlocal void Log(const char *format, ...) 179 { 180 char buffer[512]; 181 va_list ptr; 182 183 va_start(ptr,format); 184 buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; 185 va_end(ptr); 186 PrintLog(buffer); 187 } 188 189 // Error Logging 190 // prints message "dnsextd <function>: <operation> - <error message>" 191 // must be compiled w/ -D_REENTRANT for thread-safe errno usage 192 mDNSlocal void LogErr(const char *fn, const char *operation) 193 { 194 char buf[512], errbuf[256]; 195 strerror_r(errno, errbuf, sizeof(errbuf)); 196 snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf); 197 PrintLog(buf); 198 } 199 200 // 201 // Networking Utility Routines 202 // 203 204 // Convert DNS Message Header from Network to Host byte order 205 mDNSlocal void HdrNToH(PktMsg *pkt) 206 { 207 // Read the integer parts which are in IETF byte-order (MSB first, LSB second) 208 mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; 209 pkt->msg.h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); 210 pkt->msg.h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]); 211 pkt->msg.h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]); 212 pkt->msg.h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]); 213 } 214 215 // Convert DNS Message Header from Host to Network byte order 216 mDNSlocal void HdrHToN(PktMsg *pkt) 217 { 218 mDNSu16 numQuestions = pkt->msg.h.numQuestions; 219 mDNSu16 numAnswers = pkt->msg.h.numAnswers; 220 mDNSu16 numAuthorities = pkt->msg.h.numAuthorities; 221 mDNSu16 numAdditionals = pkt->msg.h.numAdditionals; 222 mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; 223 224 // Put all the integer values in IETF byte-order (MSB first, LSB second) 225 *ptr++ = (mDNSu8)(numQuestions >> 8); 226 *ptr++ = (mDNSu8)(numQuestions & 0xFF); 227 *ptr++ = (mDNSu8)(numAnswers >> 8); 228 *ptr++ = (mDNSu8)(numAnswers & 0xFF); 229 *ptr++ = (mDNSu8)(numAuthorities >> 8); 230 *ptr++ = (mDNSu8)(numAuthorities & 0xFF); 231 *ptr++ = (mDNSu8)(numAdditionals >> 8); 232 *ptr++ = (mDNSu8)(numAdditionals & 0xFF); 233 } 234 235 236 // Add socket to event loop 237 238 mDNSlocal mStatus AddSourceToEventLoop( DaemonInfo * self, TCPSocket *sock, EventCallback callback, void *context ) 239 { 240 EventSource * newSource; 241 mStatus err = mStatus_NoError; 242 243 if ( self->eventSources.LinkOffset == 0 ) 244 { 245 InitLinkedList( &self->eventSources, offsetof( EventSource, next)); 246 } 247 248 newSource = ( EventSource*) malloc( sizeof *newSource ); 249 if ( newSource == NULL ) 250 { 251 err = mStatus_NoMemoryErr; 252 goto exit; 253 } 254 255 newSource->callback = callback; 256 newSource->context = context; 257 newSource->sock = sock; 258 newSource->fd = mDNSPlatformTCPGetFD( sock ); 259 260 AddToTail( &self->eventSources, newSource ); 261 262 exit: 263 264 return err; 265 } 266 267 268 // Remove socket from event loop 269 270 mDNSlocal mStatus RemoveSourceFromEventLoop( DaemonInfo * self, TCPSocket *sock ) 271 { 272 EventSource * source; 273 mStatus err; 274 275 for ( source = ( EventSource* ) self->eventSources.Head; source; source = source->next ) 276 { 277 if ( source->sock == sock ) 278 { 279 RemoveFromList( &self->eventSources, source ); 280 281 free( source ); 282 err = mStatus_NoError; 283 goto exit; 284 } 285 } 286 287 err = mStatus_NoSuchNameErr; 288 289 exit: 290 291 return err; 292 } 293 294 // create a socket connected to nameserver 295 // caller terminates connection via close() 296 mDNSlocal TCPSocket *ConnectToServer(DaemonInfo *d) 297 { 298 int ntries = 0, retry = 0; 299 300 while (1) 301 { 302 mDNSIPPort port = zeroIPPort; 303 int fd; 304 305 TCPSocket *sock = mDNSPlatformTCPSocket( NULL, 0, &port ); 306 if ( !sock ) { LogErr("ConnectToServer", "socket"); return NULL; } 307 fd = mDNSPlatformTCPGetFD( sock ); 308 if (!connect( fd, (struct sockaddr *)&d->ns_addr, sizeof(d->ns_addr))) return sock; 309 mDNSPlatformTCPCloseConnection( sock ); 310 if (++ntries < 10) 311 { 312 LogErr("ConnectToServer", "connect"); 313 Log("ConnectToServer - retrying connection"); 314 if (!retry) retry = 500000 + random() % 500000; 315 usleep(retry); 316 retry *= 2; 317 } 318 else { Log("ConnectToServer - %d failed attempts. Aborting.", ntries); return NULL; } 319 } 320 } 321 322 // send an entire block of data over a connected socket 323 mDNSlocal int MySend(TCPSocket *sock, const void *msg, int len) 324 { 325 int selectval, n, nsent = 0; 326 fd_set wset; 327 struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 328 329 while (nsent < len) 330 { 331 int fd; 332 333 FD_ZERO(&wset); 334 335 fd = mDNSPlatformTCPGetFD( sock ); 336 337 FD_SET( fd, &wset ); 338 selectval = select( fd+1, NULL, &wset, NULL, &timeout); 339 if (selectval < 0) { LogErr("MySend", "select"); return -1; } 340 if (!selectval || !FD_ISSET(fd, &wset)) { Log("MySend - timeout"); return -1; } 341 342 n = mDNSPlatformWriteTCP( sock, ( char* ) msg + nsent, len - nsent); 343 344 if (n < 0) { LogErr("MySend", "send"); return -1; } 345 nsent += n; 346 } 347 return 0; 348 } 349 350 // Transmit a DNS message, prefixed by its length, over TCP, blocking if necessary 351 mDNSlocal int SendPacket(TCPSocket *sock, PktMsg *pkt) 352 { 353 // send the lenth, in network byte order 354 mDNSu16 len = htons((mDNSu16)pkt->len); 355 if (MySend(sock, &len, sizeof(len)) < 0) return -1; 356 357 // send the message 358 VLog("SendPacket Q:%d A:%d A:%d A:%d ", 359 ntohs(pkt->msg.h.numQuestions), 360 ntohs(pkt->msg.h.numAnswers), 361 ntohs(pkt->msg.h.numAuthorities), 362 ntohs(pkt->msg.h.numAdditionals)); 363 return MySend(sock, &pkt->msg, pkt->len); 364 } 365 366 // Receive len bytes, waiting until we have all of them. 367 // Returns number of bytes read (which should always be the number asked for). 368 static int my_recv(TCPSocket *sock, void *const buf, const int len, mDNSBool * closed) 369 { 370 // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; 371 // use an explicit while() loop instead. 372 // Also, don't try to do '+=' arithmetic on the original "void *" pointer -- 373 // arithmetic on "void *" pointers is compiler-dependent. 374 375 fd_set rset; 376 struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 377 int selectval, remaining = len; 378 char *ptr = (char *)buf; 379 ssize_t num_read; 380 381 while (remaining) 382 { 383 int fd; 384 385 fd = mDNSPlatformTCPGetFD( sock ); 386 387 FD_ZERO(&rset); 388 FD_SET(fd, &rset); 389 selectval = select(fd+1, &rset, NULL, NULL, &timeout); 390 if (selectval < 0) { LogErr("my_recv", "select"); return -1; } 391 if (!selectval || !FD_ISSET(fd, &rset)) 392 { 393 Log("my_recv - timeout"); 394 return -1; 395 } 396 397 num_read = mDNSPlatformReadTCP( sock, ptr, remaining, closed ); 398 399 if (((num_read == 0) && *closed) || (num_read < 0) || (num_read > remaining)) return -1; 400 if (num_read == 0) return 0; 401 ptr += num_read; 402 remaining -= num_read; 403 } 404 return(len); 405 } 406 407 // Return a DNS Message read off of a TCP socket, or NULL on failure 408 // If storage is non-null, result is placed in that buffer. Otherwise, 409 // returned value is allocated with Malloc, and contains sufficient extra 410 // storage for a Lease OPT RR 411 412 mDNSlocal PktMsg* 413 RecvPacket 414 ( 415 TCPSocket * sock, 416 PktMsg * storage, 417 mDNSBool * closed 418 ) 419 { 420 int nread; 421 int allocsize; 422 mDNSu16 msglen = 0; 423 PktMsg * pkt = NULL; 424 unsigned int srclen; 425 int fd; 426 mStatus err = 0; 427 428 fd = mDNSPlatformTCPGetFD( sock ); 429 430 nread = my_recv( sock, &msglen, sizeof( msglen ), closed ); 431 432 require_action_quiet( nread != -1, exit, err = mStatus_UnknownErr ); 433 require_action_quiet( nread > 0, exit, err = mStatus_NoError ); 434 435 msglen = ntohs( msglen ); 436 require_action_quiet( nread == sizeof( msglen ), exit, err = mStatus_UnknownErr; Log( "Could not read length field of message") ); 437 438 if ( storage ) 439 { 440 require_action_quiet( msglen <= sizeof( storage->msg ), exit, err = mStatus_UnknownErr; Log( "RecvPacket: provided buffer too small." ) ); 441 pkt = storage; 442 } 443 else 444 { 445 // buffer extra space to add an OPT RR 446 447 if ( msglen > sizeof(DNSMessage)) 448 { 449 allocsize = sizeof(PktMsg) - sizeof(DNSMessage) + msglen; 450 } 451 else 452 { 453 allocsize = sizeof(PktMsg); 454 } 455 456 pkt = malloc(allocsize); 457 require_action_quiet( pkt, exit, err = mStatus_NoMemoryErr; LogErr( "RecvPacket", "malloc" ) ); 458 mDNSPlatformMemZero( pkt, sizeof( *pkt ) ); 459 } 460 461 pkt->len = msglen; 462 srclen = sizeof(pkt->src); 463 464 if ( getpeername( fd, ( struct sockaddr* ) &pkt->src, &srclen ) || ( srclen != sizeof( pkt->src ) ) ) 465 { 466 LogErr("RecvPacket", "getpeername"); 467 mDNSPlatformMemZero(&pkt->src, sizeof(pkt->src)); 468 } 469 470 nread = my_recv(sock, &pkt->msg, msglen, closed ); 471 require_action_quiet( nread >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvPacket", "recv" ) ); 472 require_action_quiet( nread == msglen, exit, err = mStatus_UnknownErr ; Log( "Could not read entire message" ) ); 473 require_action_quiet( pkt->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr ; Log( "RecvPacket: Message too short (%d bytes)", pkt->len ) ); 474 475 exit: 476 477 if ( err && pkt ) 478 { 479 if ( pkt != storage ) 480 { 481 free(pkt); 482 } 483 484 pkt = NULL; 485 } 486 487 return pkt; 488 } 489 490 491 mDNSlocal DNSZone* 492 FindZone 493 ( 494 DaemonInfo * self, 495 domainname * name 496 ) 497 { 498 DNSZone * zone; 499 500 for ( zone = self->zones; zone; zone = zone->next ) 501 { 502 if ( SameDomainName( &zone->name, name ) ) 503 { 504 break; 505 } 506 } 507 508 return zone; 509 } 510 511 512 mDNSlocal mDNSBool 513 ZoneHandlesName 514 ( 515 const domainname * zname, 516 const domainname * dname 517 ) 518 { 519 mDNSu16 i = DomainNameLength( zname ); 520 mDNSu16 j = DomainNameLength( dname ); 521 522 if ( ( i == ( MAX_DOMAIN_NAME + 1 ) ) || ( j == ( MAX_DOMAIN_NAME + 1 ) ) || ( i > j ) || ( memcmp( zname->c, dname->c + ( j - i ), i ) != 0 ) ) 523 { 524 return mDNSfalse; 525 } 526 527 return mDNStrue; 528 } 529 530 531 mDNSlocal mDNSBool IsQuery( PktMsg * pkt ) 532 { 533 return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery ); 534 } 535 536 537 mDNSlocal mDNSBool IsUpdate( PktMsg * pkt ) 538 { 539 return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_OP_Update ); 540 } 541 542 543 mDNSlocal mDNSBool IsNotify(PktMsg *pkt) 544 { 545 return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( mDNSu8) ( kDNSFlag0_OP_Notify ); 546 } 547 548 549 mDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt) 550 { 551 const mDNSu8 *ptr = NULL, *end = (mDNSu8 *)&pkt->msg + pkt->len; 552 LargeCacheRecord lcr; 553 int i; 554 mDNSBool result = mDNSfalse; 555 556 HdrNToH(pkt); 557 if ((mDNSu8)(pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (mDNSu8)(kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery)) goto end; 558 559 if (!pkt->msg.h.numAdditionals) goto end; 560 ptr = LocateAdditionals(&pkt->msg, end); 561 if (!ptr) goto end; 562 563 // find last Additional info. 564 for (i = 0; i < pkt->msg.h.numAdditionals; i++) 565 { 566 ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); 567 if (!ptr) { Log("Unable to read additional record"); goto end; } 568 } 569 570 if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= DNSOpt_LLQData_Space && lcr.r.resrec.rdata->u.opt[0].opt == kDNSOpt_LLQ ) 571 { 572 result = mDNStrue; 573 } 574 575 end: 576 HdrHToN(pkt); 577 return result; 578 } 579 580 // !!!KRS implement properly 581 mDNSlocal mDNSBool IsLLQAck(PktMsg *pkt) 582 { 583 if ((pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery ) && 584 pkt->msg.h.numQuestions && !pkt->msg.h.numAnswers && !pkt->msg.h.numAuthorities) return mDNStrue; 585 return mDNSfalse; 586 } 587 588 589 mDNSlocal mDNSBool 590 IsPublicSRV 591 ( 592 DaemonInfo * self, 593 DNSQuestion * q 594 ) 595 { 596 DNameListElem * elem; 597 mDNSBool ret = mDNSfalse; 598 int i = ( int ) DomainNameLength( &q->qname ) - 1; 599 600 for ( elem = self->public_names; elem; elem = elem->next ) 601 { 602 int j = ( int ) DomainNameLength( &elem->name ) - 1; 603 604 if ( i > j ) 605 { 606 for ( ; i >= 0; i--, j-- ) 607 { 608 if ( q->qname.c[ i ] != elem->name.c[ j ] ) 609 { 610 ret = mDNStrue; 611 goto exit; 612 } 613 } 614 } 615 } 616 617 exit: 618 619 return ret; 620 } 621 622 623 mDNSlocal void 624 SetZone 625 ( 626 DaemonInfo * self, 627 PktMsg * pkt 628 ) 629 { 630 domainname zname; 631 mDNSu8 QR_OP; 632 const mDNSu8 * ptr = pkt->msg.data; 633 mDNSBool exception = mDNSfalse; 634 635 // Initialize 636 637 pkt->zone = NULL; 638 pkt->isZonePublic = mDNStrue; 639 zname.c[0] = '\0'; 640 641 // Figure out what type of packet this is 642 643 QR_OP = ( mDNSu8 ) ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ); 644 645 if ( IsQuery( pkt ) ) 646 { 647 DNSQuestion question; 648 649 // It's a query 650 651 ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question ); 652 653 AppendDomainName( &zname, &question.qname ); 654 655 exception = ( ( question.qtype == kDNSType_SOA ) || ( question.qtype == kDNSType_NS ) || ( ( question.qtype == kDNSType_SRV ) && IsPublicSRV( self, &question ) ) ); 656 } 657 else if ( IsUpdate( pkt ) ) 658 { 659 DNSQuestion question; 660 661 // It's an update. The format of the zone section is the same as the format for the question section 662 // according to RFC 2136, so we'll just treat this as a question so we can get at the zone. 663 664 ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question ); 665 666 AppendDomainName( &zname, &question.qname ); 667 668 exception = mDNSfalse; 669 } 670 671 if ( zname.c[0] != '\0' ) 672 { 673 // Find the right zone 674 675 for ( pkt->zone = self->zones; pkt->zone; pkt->zone = pkt->zone->next ) 676 { 677 if ( ZoneHandlesName( &pkt->zone->name, &zname ) ) 678 { 679 VLog( "found correct zone %##s for query", pkt->zone->name.c ); 680 681 pkt->isZonePublic = ( ( pkt->zone->type == kDNSZonePublic ) || exception ); 682 683 VLog( "zone %##s is %s", pkt->zone->name.c, ( pkt->isZonePublic ) ? "public" : "private" ); 684 685 break; 686 } 687 } 688 } 689 } 690 691 692 mDNSlocal int 693 UDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc) 694 { 695 fd_set rset; 696 struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 697 int sd; 698 int res; 699 mStatus err = mStatus_NoError; 700 701 // Initialize 702 703 *trunc = mDNSfalse; 704 705 // Create a socket 706 707 sd = socket( AF_INET, SOCK_DGRAM, 0 ); 708 require_action( sd >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "socket" ) ); 709 710 // Send the packet to the nameserver 711 712 VLog("UDPServerTransaction Q:%d A:%d A:%d A:%d ", 713 ntohs(request->msg.h.numQuestions), 714 ntohs(request->msg.h.numAnswers), 715 ntohs(request->msg.h.numAuthorities), 716 ntohs(request->msg.h.numAdditionals)); 717 res = sendto( sd, (char *)&request->msg, request->len, 0, ( struct sockaddr* ) &d->ns_addr, sizeof( d->ns_addr ) ); 718 require_action( res == (int) request->len, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "sendto" ) ); 719 720 // Wait for reply 721 722 FD_ZERO( &rset ); 723 FD_SET( sd, &rset ); 724 res = select( sd + 1, &rset, NULL, NULL, &timeout ); 725 require_action( res >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "select" ) ); 726 require_action( ( res > 0 ) && FD_ISSET( sd, &rset ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - timeout" ) ); 727 728 // Receive reply 729 730 reply->len = recvfrom( sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL ); 731 require_action( ( ( int ) reply->len ) >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "recvfrom" ) ); 732 require_action( reply->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - Message too short (%d bytes)", reply->len ) ); 733 734 // Check for truncation bit 735 736 if ( reply->msg.h.flags.b[0] & kDNSFlag0_TC ) 737 { 738 *trunc = mDNStrue; 739 } 740 741 exit: 742 743 if ( sd >= 0 ) 744 { 745 close( sd ); 746 } 747 748 return err; 749 } 750 751 // 752 // Dynamic Update Utility Routines 753 // 754 755 // check if a request and server response complete a successful dynamic update 756 mDNSlocal mDNSBool SuccessfulUpdateTransaction(PktMsg *request, PktMsg *reply) 757 { 758 char buf[32]; 759 char *vlogmsg = NULL; 760 761 // check messages 762 if (!request || !reply) { vlogmsg = "NULL message"; goto failure; } 763 if (request->len < sizeof(DNSMessageHeader) || reply->len < sizeof(DNSMessageHeader)) { vlogmsg = "Malformatted message"; goto failure; } 764 765 // check request operation 766 if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask)) 767 { vlogmsg = "Request opcode not an update"; goto failure; } 768 769 // check result 770 if ((reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask)) { vlogmsg = "Reply contains non-zero rcode"; goto failure; } 771 if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_OP_Update | kDNSFlag0_QR_Response)) 772 { vlogmsg = "Reply opcode not an update response"; goto failure; } 773 774 VLog("Successful update from %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32)); 775 return mDNStrue; 776 777 failure: 778 VLog("Request %s: %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32), vlogmsg); 779 return mDNSfalse; 780 } 781 782 // Allocate an appropriately sized CacheRecord and copy data from original. 783 // Name pointer in CacheRecord object is set to point to the name specified 784 // 785 mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name) 786 { 787 CacheRecord *cr; 788 size_t size = sizeof(*cr); 789 if (orig->resrec.rdlength > InlineCacheRDSize) size += orig->resrec.rdlength - InlineCacheRDSize; 790 cr = malloc(size); 791 if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; } 792 memcpy(cr, orig, size); 793 cr->resrec.rdata = (RData*)&cr->smallrdatastorage; 794 cr->resrec.name = name; 795 796 return cr; 797 } 798 799 800 // 801 // Lease Hashtable Utility Routines 802 // 803 804 // double hash table size 805 // caller must lock table prior to invocation 806 mDNSlocal void RehashTable(DaemonInfo *d) 807 { 808 RRTableElem *ptr, *tmp, **new; 809 int i, bucket, newnbuckets = d->nbuckets * 2; 810 811 VLog("Rehashing lease table (new size %d buckets)", newnbuckets); 812 new = malloc(sizeof(RRTableElem *) * newnbuckets); 813 if (!new) { LogErr("RehashTable", "malloc"); return; } 814 mDNSPlatformMemZero(new, newnbuckets * sizeof(RRTableElem *)); 815 816 for (i = 0; i < d->nbuckets; i++) 817 { 818 ptr = d->table[i]; 819 while (ptr) 820 { 821 bucket = ptr->rr.resrec.namehash % newnbuckets; 822 tmp = ptr; 823 ptr = ptr->next; 824 tmp->next = new[bucket]; 825 new[bucket] = tmp; 826 } 827 } 828 d->nbuckets = newnbuckets; 829 free(d->table); 830 d->table = new; 831 } 832 833 // print entire contents of hashtable, invoked via SIGINFO 834 mDNSlocal void PrintLeaseTable(DaemonInfo *d) 835 { 836 int i; 837 RRTableElem *ptr; 838 char rrbuf[MaxMsg], addrbuf[16]; 839 struct timeval now; 840 int hr, min, sec; 841 842 if (gettimeofday(&now, NULL)) { LogErr("PrintTable", "gettimeofday"); return; } 843 if (pthread_mutex_lock(&d->tablelock)) { LogErr("PrintTable", "pthread_mutex_lock"); return; } 844 845 Log("Dumping Lease Table Contents (table contains %d resource records)", d->nelems); 846 for (i = 0; i < d->nbuckets; i++) 847 { 848 for (ptr = d->table[i]; ptr; ptr = ptr->next) 849 { 850 hr = ((ptr->expire - now.tv_sec) / 60) / 60; 851 min = ((ptr->expire - now.tv_sec) / 60) % 60; 852 sec = (ptr->expire - now.tv_sec) % 60; 853 Log("Update from %s, Expires in %d:%d:%d\n\t%s", inet_ntop(AF_INET, &ptr->cli.sin_addr, addrbuf, 16), hr, min, sec, 854 GetRRDisplayString_rdb(&ptr->rr.resrec, &ptr->rr.resrec.rdata->u, rrbuf)); 855 } 856 } 857 pthread_mutex_unlock(&d->tablelock); 858 } 859 860 // 861 // Startup SRV Registration Routines 862 // Register _dns-update._udp/_tcp.<zone> SRV records indicating the port on which 863 // the daemon accepts requests 864 // 865 866 // delete all RRS of a given name/type 867 mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit, ResourceRecord *rr) 868 { 869 ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name); 870 if (!ptr || ptr + 10 >= limit) return NULL; // out of space 871 ptr[0] = (mDNSu8)(rr->rrtype >> 8); 872 ptr[1] = (mDNSu8)(rr->rrtype & 0xFF); 873 ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8); 874 ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY & 0xFF); 875 mDNSPlatformMemZero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata 876 msg->h.mDNS_numUpdates++; 877 return ptr + 10; 878 } 879 880 mDNSlocal mDNSu8 *PutUpdateSRV(DaemonInfo *d, DNSZone * zone, PktMsg *pkt, mDNSu8 *ptr, char *regtype, mDNSIPPort port, mDNSBool registration) 881 { 882 AuthRecord rr; 883 char hostname[1024], buf[MaxMsg]; 884 mDNSu8 *end = (mDNSu8 *)&pkt->msg + sizeof(DNSMessage); 885 886 ( void ) d; 887 888 mDNS_SetupResourceRecord(&rr, NULL, 0, kDNSType_SRV, SRV_TTL, kDNSRecordTypeUnique, AuthRecordAny, NULL, NULL); 889 rr.resrec.rrclass = kDNSClass_IN; 890 rr.resrec.rdata->u.srv.priority = 0; 891 rr.resrec.rdata->u.srv.weight = 0; 892 rr.resrec.rdata->u.srv.port = port; 893 if (gethostname(hostname, 1024) < 0 || !MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname)) 894 rr.resrec.rdata->u.srv.target.c[0] = '\0'; 895 896 MakeDomainNameFromDNSNameString(&rr.namestorage, regtype); 897 AppendDomainName(&rr.namestorage, &zone->name); 898 VLog("%s %s", registration ? "Registering SRV record" : "Deleting existing RRSet", 899 GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf)); 900 if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec); 901 else ptr = putRRSetDeletion(&pkt->msg, ptr, end, &rr.resrec); 902 return ptr; 903 } 904 905 906 // perform dynamic update. 907 // specify deletion by passing false for the register parameter, otherwise register the records. 908 mDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration) 909 { 910 TCPSocket *sock = NULL; 911 DNSZone * zone; 912 int err = mStatus_NoError; 913 914 sock = ConnectToServer( d ); 915 require_action( sock, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: ConnectToServer failed" ) ); 916 917 for ( zone = d->zones; zone; zone = zone->next ) 918 { 919 PktMsg pkt; 920 mDNSu8 *ptr = pkt.msg.data; 921 mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); 922 PktMsg *reply = NULL; 923 mDNSBool closed; 924 mDNSBool ok; 925 926 // Initialize message 927 InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags); 928 pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines 929 pkt.src.sin_family = AF_INET; 930 931 // format message body 932 ptr = putZone(&pkt.msg, ptr, end, &zone->name, mDNSOpaque16fromIntVal(kDNSClass_IN)); 933 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 934 935 if ( zone->type == kDNSZonePrivate ) 936 { 937 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls._tcp.", d->private_port, registration); 938 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 939 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls._tcp.", d->private_port, registration); 940 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 941 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls._tcp.", d->private_port, registration); 942 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 943 944 if ( !registration ) 945 { 946 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration); 947 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 948 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration); 949 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 950 } 951 } 952 else 953 { 954 if ( !registration ) 955 { 956 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls.", d->private_port, registration); 957 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 958 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls.", d->private_port, registration); 959 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 960 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls.", d->private_port, registration); 961 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 962 } 963 964 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration); 965 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 966 ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration); 967 require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 968 } 969 970 HdrHToN(&pkt); 971 972 if ( zone->updateKeys ) 973 { 974 DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 ); 975 require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) ); 976 } 977 978 pkt.len = ptr - (mDNSu8 *)&pkt.msg; 979 980 // send message, receive reply 981 982 err = SendPacket( sock, &pkt ); 983 require_action( !err, exit, Log( "UpdateSRV: SendPacket failed" ) ); 984 985 reply = RecvPacket( sock, NULL, &closed ); 986 require_action( reply, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: RecvPacket returned NULL" ) ); 987 988 ok = SuccessfulUpdateTransaction( &pkt, reply ); 989 990 if ( !ok ) 991 { 992 Log("SRV record registration failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask); 993 } 994 995 free( reply ); 996 } 997 998 exit: 999 1000 if ( sock ) 1001 { 1002 mDNSPlatformTCPCloseConnection( sock ); 1003 } 1004 1005 return err; 1006 } 1007 1008 // wrapper routines/macros 1009 #define ClearUpdateSRV(d) UpdateSRV(d, 0) 1010 1011 // clear any existing records prior to registration 1012 mDNSlocal int SetUpdateSRV(DaemonInfo *d) 1013 { 1014 int err; 1015 1016 err = ClearUpdateSRV(d); // clear any existing record 1017 if (!err) err = UpdateSRV(d, 1); 1018 return err; 1019 } 1020 1021 // 1022 // Argument Parsing and Configuration 1023 // 1024 1025 mDNSlocal void PrintUsage(void) 1026 { 1027 fprintf(stderr, "Usage: dnsextd [-f <config file>] [-vhd] ...\n" 1028 "Use \"dnsextd -h\" for help\n"); 1029 } 1030 1031 mDNSlocal void PrintHelp(void) 1032 { 1033 fprintf(stderr, "\n\n"); 1034 PrintUsage(); 1035 1036 fprintf(stderr, 1037 "dnsextd is a daemon that implements DNS extensions supporting Dynamic DNS Update Leases\n" 1038 "and Long Lived Queries, used in Wide-Area DNS Service Discovery, on behalf of name servers\n" 1039 "that do not natively support these extensions. (See dns-sd.org for more info on DNS Service\n" 1040 "Discovery, Update Leases, and Long Lived Queries.)\n\n" 1041 1042 "dnsextd requires one argument,the zone, which is the domain for which Update Leases\n" 1043 "and Long Lived Queries are to be administered. dnsextd communicates directly with the\n" 1044 "primary master server for this zone.\n\n" 1045 1046 "The options are as follows:\n\n" 1047 1048 "-f Specify configuration file. The default is /etc/dnsextd.conf.\n\n" 1049 1050 "-d Run daemon in foreground.\n\n" 1051 1052 "-h Print help.\n\n" 1053 1054 "-v Verbose output.\n\n" 1055 ); 1056 } 1057 1058 1059 // Note: ProcessArgs called before process is daemonized, and therefore must open no descriptors 1060 // returns 0 (success) if program is to continue execution 1061 // output control arguments (-f, -v) do not affect this routine 1062 mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) 1063 { 1064 DNSZone * zone; 1065 int opt; 1066 int err = 0; 1067 1068 cfgfile = strdup( CONFIG_FILE ); 1069 require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); 1070 1071 // defaults, may be overriden by command option 1072 1073 // setup our sockaddr 1074 1075 mDNSPlatformMemZero( &d->addr, sizeof( d->addr ) ); 1076 d->addr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 1077 d->addr.sin_port = UnicastDNSPort.NotAnInteger; 1078 d->addr.sin_family = AF_INET; 1079 #ifndef NOT_HAVE_SA_LEN 1080 d->addr.sin_len = sizeof( d->addr ); 1081 #endif 1082 1083 // setup nameserver's sockaddr 1084 1085 mDNSPlatformMemZero(&d->ns_addr, sizeof(d->ns_addr)); 1086 d->ns_addr.sin_family = AF_INET; 1087 inet_pton( AF_INET, LOOPBACK, &d->ns_addr.sin_addr ); 1088 d->ns_addr.sin_port = NSIPCPort.NotAnInteger; 1089 #ifndef NOT_HAVE_SA_LEN 1090 d->ns_addr.sin_len = sizeof( d->ns_addr ); 1091 #endif 1092 1093 // setup our ports 1094 1095 d->private_port = PrivateDNSPort; 1096 d->llq_port = DNSEXTPort; 1097 1098 while ((opt = getopt(argc, argv, "f:hdv")) != -1) 1099 { 1100 switch(opt) 1101 { 1102 case 'f': free( cfgfile ); cfgfile = strdup( optarg ); require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); break; 1103 case 'h': PrintHelp(); return -1; 1104 case 'd': foreground = 1; break; // Also used when launched via OS X's launchd mechanism 1105 case 'v': verbose = 1; break; 1106 default: goto arg_error; 1107 } 1108 } 1109 1110 err = ParseConfig( d, cfgfile ); 1111 require_noerr( err, arg_error ); 1112 1113 // Make sure we've specified some zones 1114 1115 require_action( d->zones, arg_error, err = mStatus_UnknownErr ); 1116 1117 // if we have a shared secret, use it for the entire zone 1118 1119 for ( zone = d->zones; zone; zone = zone->next ) 1120 { 1121 if ( zone->updateKeys ) 1122 { 1123 AssignDomainName( &zone->updateKeys->domain, &zone->name ); 1124 } 1125 } 1126 1127 return 0; 1128 1129 arg_error: 1130 1131 PrintUsage(); 1132 return -1; 1133 } 1134 1135 1136 // 1137 // Initialization Routines 1138 // 1139 1140 // Allocate memory, initialize locks and bookkeeping variables 1141 mDNSlocal int InitLeaseTable(DaemonInfo *d) 1142 { 1143 if (pthread_mutex_init(&d->tablelock, NULL)) { LogErr("InitLeaseTable", "pthread_mutex_init"); return -1; } 1144 d->nbuckets = LEASETABLE_INIT_NBUCKETS; 1145 d->nelems = 0; 1146 d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); 1147 if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; } 1148 mDNSPlatformMemZero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); 1149 return 0; 1150 } 1151 1152 1153 mDNSlocal int 1154 SetupSockets 1155 ( 1156 DaemonInfo * self 1157 ) 1158 { 1159 static const int kOn = 1; 1160 int sockpair[2]; 1161 mDNSBool private = mDNSfalse; 1162 struct sockaddr_in daddr; 1163 DNSZone * zone; 1164 mStatus err = 0; 1165 1166 // set up sockets on which we all ns requests 1167 1168 self->tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 1169 require_action( dnssd_SocketValid(self->tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1170 1171 #if defined(SO_REUSEADDR) 1172 err = setsockopt(self->tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 1173 require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tcpsd" ) ); 1174 #endif 1175 1176 err = bind( self->tcpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) ); 1177 require_action( !err, exit, LogErr( "SetupSockets", "bind self->tcpsd" ) ); 1178 1179 err = listen( self->tcpsd, LISTENQ ); 1180 require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 1181 1182 self->udpsd = socket( AF_INET, SOCK_DGRAM, 0 ); 1183 require_action( dnssd_SocketValid(self->udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1184 1185 #if defined(SO_REUSEADDR) 1186 err = setsockopt(self->udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 1187 require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->udpsd" ) ); 1188 #endif 1189 1190 err = bind( self->udpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) ); 1191 require_action( !err, exit, LogErr( "SetupSockets", "bind self->udpsd" ) ); 1192 1193 // set up sockets on which we receive llq requests 1194 1195 mDNSPlatformMemZero(&self->llq_addr, sizeof(self->llq_addr)); 1196 self->llq_addr.sin_family = AF_INET; 1197 self->llq_addr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 1198 self->llq_addr.sin_port = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger; 1199 1200 if (self->llq_addr.sin_port == self->addr.sin_port) 1201 { 1202 self->llq_tcpsd = self->tcpsd; 1203 self->llq_udpsd = self->udpsd; 1204 } 1205 else 1206 { 1207 self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 1208 require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1209 1210 #if defined(SO_REUSEADDR) 1211 err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 1212 require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) ); 1213 #endif 1214 1215 err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) ); 1216 require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) ); 1217 1218 err = listen( self->llq_tcpsd, LISTENQ ); 1219 require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 1220 1221 self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 ); 1222 require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1223 1224 #if defined(SO_REUSEADDR) 1225 err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 1226 require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) ); 1227 #endif 1228 1229 err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) ); 1230 require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) ); 1231 } 1232 1233 // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred 1234 1235 err = socketpair( AF_LOCAL, SOCK_STREAM, 0, sockpair ); 1236 require_action( !err, exit, LogErr( "SetupSockets", "socketpair" ) ); 1237 1238 self->LLQEventListenSock = sockpair[0]; 1239 self->LLQEventNotifySock = sockpair[1]; 1240 1241 // set up socket on which we receive private requests 1242 1243 self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 1244 require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1245 mDNSPlatformMemZero(&daddr, sizeof(daddr)); 1246 daddr.sin_family = AF_INET; 1247 daddr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 1248 daddr.sin_port = ( self->private_port.NotAnInteger ) ? self->private_port.NotAnInteger : PrivateDNSPort.NotAnInteger; 1249 1250 self->tlssd = socket( AF_INET, SOCK_STREAM, 0 ); 1251 require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 1252 1253 #if defined(SO_REUSEADDR) 1254 err = setsockopt(self->tlssd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 1255 require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tlssd" ) ); 1256 #endif 1257 1258 err = bind( self->tlssd, ( struct sockaddr* ) &daddr, sizeof( daddr ) ); 1259 require_action( !err, exit, LogErr( "SetupSockets", "bind self->tlssd" ) ); 1260 1261 err = listen( self->tlssd, LISTENQ ); 1262 require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 1263 1264 // Do we have any private zones? 1265 1266 for ( zone = self->zones; zone; zone = zone->next ) 1267 { 1268 if ( zone->type == kDNSZonePrivate ) 1269 { 1270 private = mDNStrue; 1271 break; 1272 } 1273 } 1274 1275 if ( private ) 1276 { 1277 err = mDNSPlatformTLSSetupCerts(); 1278 require_action( !err, exit, LogErr( "SetupSockets", "mDNSPlatformTLSSetupCerts" ) ); 1279 } 1280 1281 exit: 1282 1283 return err; 1284 } 1285 1286 // 1287 // periodic table updates 1288 // 1289 1290 // Delete a resource record from the nameserver via a dynamic update 1291 // sd is a socket already connected to the server 1292 mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zname, TCPSocket *sock) 1293 { 1294 DNSZone * zone; 1295 PktMsg pkt; 1296 mDNSu8 *ptr = pkt.msg.data; 1297 mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); 1298 char buf[MaxMsg]; 1299 mDNSBool closed; 1300 PktMsg *reply = NULL; 1301 1302 VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf)); 1303 1304 InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags); 1305 1306 ptr = putZone(&pkt.msg, ptr, end, zname, mDNSOpaque16fromIntVal(rr->resrec.rrclass)); 1307 if (!ptr) goto end; 1308 ptr = putDeletionRecord(&pkt.msg, ptr, &rr->resrec); 1309 if (!ptr) goto end; 1310 1311 HdrHToN(&pkt); 1312 1313 zone = FindZone( d, zname ); 1314 1315 if ( zone && zone->updateKeys) 1316 { 1317 DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 ); 1318 if (!ptr) goto end; 1319 } 1320 1321 pkt.len = ptr - (mDNSu8 *)&pkt.msg; 1322 pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines 1323 pkt.src.sin_family = AF_INET; 1324 if (SendPacket( sock, &pkt)) { Log("DeleteOneRecord: SendPacket failed"); } 1325 reply = RecvPacket( sock, NULL, &closed ); 1326 if (reply) HdrNToH(reply); 1327 require_action( reply, end, Log( "DeleteOneRecord: RecvPacket returned NULL" ) ); 1328 1329 if (!SuccessfulUpdateTransaction(&pkt, reply)) 1330 Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask : -1); 1331 1332 end: 1333 if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); } 1334 if (reply) free(reply); 1335 } 1336 1337 // iterate over table, deleting expired records (or all records if DeleteAll is true) 1338 mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll) 1339 { 1340 struct timeval now; 1341 int i; 1342 TCPSocket *sock = ConnectToServer(d); 1343 if (!sock) { Log("DeleteRecords: ConnectToServer failed"); return; } 1344 if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; } 1345 if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; } 1346 1347 for (i = 0; i < d->nbuckets; i++) 1348 { 1349 RRTableElem **ptr = &d->table[i]; 1350 while (*ptr) 1351 { 1352 if (DeleteAll || (*ptr)->expire - now.tv_sec < 0) 1353 { 1354 RRTableElem *fptr; 1355 // delete record from server 1356 DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sock); 1357 fptr = *ptr; 1358 *ptr = (*ptr)->next; 1359 free(fptr); 1360 d->nelems--; 1361 } 1362 else ptr = &(*ptr)->next; 1363 } 1364 } 1365 pthread_mutex_unlock(&d->tablelock); 1366 mDNSPlatformTCPCloseConnection( sock ); 1367 } 1368 1369 // 1370 // main update request handling 1371 // 1372 1373 // Add, delete, or refresh records in table based on contents of a successfully completed dynamic update 1374 mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease) 1375 { 1376 RRTableElem **rptr, *tmp; 1377 int i, allocsize, bucket; 1378 LargeCacheRecord lcr; 1379 ResourceRecord *rr = &lcr.r.resrec; 1380 const mDNSu8 *ptr, *end; 1381 struct timeval tv; 1382 DNSQuestion zone; 1383 char buf[MaxMsg]; 1384 1385 if (pthread_mutex_lock(&d->tablelock)) { LogErr("UpdateLeaseTable", "pthread_mutex_lock"); return; } 1386 HdrNToH(pkt); 1387 ptr = pkt->msg.data; 1388 end = (mDNSu8 *)&pkt->msg + pkt->len; 1389 ptr = getQuestion(&pkt->msg, ptr, end, 0, &zone); 1390 if (!ptr) { Log("UpdateLeaseTable: cannot read zone"); goto cleanup; } 1391 ptr = LocateAuthorities(&pkt->msg, end); 1392 if (!ptr) { Log("UpdateLeaseTable: Format error"); goto cleanup; } 1393 1394 for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++) 1395 { 1396 mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse; 1397 1398 ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); 1399 if (!ptr || lcr.r.resrec.RecordType == kDNSRecordTypePacketNegative) { Log("UpdateLeaseTable: GetLargeResourceRecord failed"); goto cleanup; } 1400 bucket = rr->namehash % d->nbuckets; 1401 rptr = &d->table[bucket]; 1402 1403 // handle deletions 1404 if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) 1405 DeleteAllRRSets = mDNStrue; // delete all rrsets for a name 1406 else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) 1407 DeleteOneRRSet = mDNStrue; 1408 else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE) 1409 DeleteOneRR = mDNStrue; 1410 1411 if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR) 1412 { 1413 while (*rptr) 1414 { 1415 if (SameDomainName((*rptr)->rr.resrec.name, rr->name) && 1416 (DeleteAllRRSets || 1417 (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) || 1418 (DeleteOneRR && IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)))) 1419 { 1420 tmp = *rptr; 1421 VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf)); 1422 *rptr = (*rptr)->next; 1423 free(tmp); 1424 d->nelems--; 1425 } 1426 else rptr = &(*rptr)->next; 1427 } 1428 } 1429 else if (lease > 0) 1430 { 1431 // see if add or refresh 1432 while (*rptr && !IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next; 1433 if (*rptr) 1434 { 1435 // refresh 1436 if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } 1437 (*rptr)->expire = tv.tv_sec + (unsigned)lease; 1438 VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); 1439 } 1440 else 1441 { 1442 // New record - add to table 1443 if (d->nelems > d->nbuckets) 1444 { 1445 RehashTable(d); 1446 bucket = rr->namehash % d->nbuckets; 1447 rptr = &d->table[bucket]; 1448 } 1449 if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } 1450 allocsize = sizeof(RRTableElem); 1451 if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize); 1452 tmp = malloc(allocsize); 1453 if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; } 1454 memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize); 1455 tmp->rr.resrec.rdata = (RData *)&tmp->rr.smallrdatastorage; 1456 AssignDomainName(&tmp->name, rr->name); 1457 tmp->rr.resrec.name = &tmp->name; 1458 tmp->expire = tv.tv_sec + (unsigned)lease; 1459 tmp->cli.sin_addr = pkt->src.sin_addr; 1460 AssignDomainName(&tmp->zone, &zone.qname); 1461 tmp->next = d->table[bucket]; 1462 d->table[bucket] = tmp; 1463 d->nelems++; 1464 VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); 1465 } 1466 } 1467 } 1468 1469 cleanup: 1470 pthread_mutex_unlock(&d->tablelock); 1471 HdrHToN(pkt); 1472 } 1473 1474 // Given a successful reply from a server, create a new reply that contains lease information 1475 // Replies are currently not signed !!!KRS change this 1476 mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease) 1477 { 1478 PktMsg *reply; 1479 mDNSu8 *ptr, *end; 1480 mDNSOpaque16 flags; 1481 1482 (void)d; //unused 1483 reply = malloc(sizeof(*reply)); 1484 if (!reply) { LogErr("FormatLeaseReply", "malloc"); return NULL; } 1485 flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; 1486 flags.b[1] = 0; 1487 1488 InitializeDNSMessage(&reply->msg.h, orig->msg.h.id, flags); 1489 reply->src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // unused except for log messages 1490 reply->src.sin_family = AF_INET; 1491 ptr = reply->msg.data; 1492 end = (mDNSu8 *)&reply->msg + sizeof(DNSMessage); 1493 ptr = putUpdateLease(&reply->msg, ptr, lease); 1494 if (!ptr) { Log("FormatLeaseReply: putUpdateLease failed"); free(reply); return NULL; } 1495 reply->len = ptr - (mDNSu8 *)&reply->msg; 1496 HdrHToN(reply); 1497 return reply; 1498 } 1499 1500 1501 // pkt is thread-local, not requiring locking 1502 1503 mDNSlocal PktMsg* 1504 HandleRequest 1505 ( 1506 DaemonInfo * self, 1507 PktMsg * request 1508 ) 1509 { 1510 PktMsg * reply = NULL; 1511 PktMsg * leaseReply; 1512 PktMsg buf; 1513 char addrbuf[32]; 1514 TCPSocket * sock = NULL; 1515 mStatus err; 1516 mDNSs32 lease = 0; 1517 if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) == kDNSFlag0_OP_Update) 1518 { 1519 int i, adds = 0, dels = 0; 1520 const mDNSu8 *ptr, *end = (mDNSu8 *)&request->msg + request->len; 1521 HdrNToH(request); 1522 lease = GetPktLease(&mDNSStorage, &request->msg, end); 1523 ptr = LocateAuthorities(&request->msg, end); 1524 for (i = 0; i < request->msg.h.mDNS_numUpdates; i++) 1525 { 1526 LargeCacheRecord lcr; 1527 ptr = GetLargeResourceRecord(NULL, &request->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); 1528 if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rroriginalttl) adds++; else dels++; 1529 } 1530 HdrHToN(request); 1531 if (adds && !lease) 1532 { 1533 static const mDNSOpaque16 UpdateRefused = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, kDNSFlag1_RC_Refused } }; 1534 Log("Rejecting Update Request with %d additions but no lease", adds); 1535 reply = malloc(sizeof(*reply)); 1536 mDNSPlatformMemZero(&reply->src, sizeof(reply->src)); 1537 reply->len = sizeof(DNSMessageHeader); 1538 reply->zone = NULL; 1539 reply->isZonePublic = 0; 1540 InitializeDNSMessage(&reply->msg.h, request->msg.h.id, UpdateRefused); 1541 return(reply); 1542 } 1543 if (lease > 7200) // Don't allow lease greater than two hours; typically 90-minute renewal period 1544 lease = 7200; 1545 } 1546 // Send msg to server, read reply 1547 1548 if ( request->len <= 512 ) 1549 { 1550 mDNSBool trunc; 1551 1552 if ( UDPServerTransaction( self, request, &buf, &trunc) < 0 ) 1553 { 1554 Log("HandleRequest - UDPServerTransaction failed. Trying TCP"); 1555 } 1556 else if ( trunc ) 1557 { 1558 VLog("HandleRequest - answer truncated. Using TCP"); 1559 } 1560 else 1561 { 1562 reply = &buf; // success 1563 } 1564 } 1565 1566 if ( !reply ) 1567 { 1568 mDNSBool closed; 1569 int res; 1570 1571 sock = ConnectToServer( self ); 1572 require_action_quiet( sock, exit, err = mStatus_UnknownErr ; Log( "Discarding request from %s due to connection errors", inet_ntop( AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 1573 1574 res = SendPacket( sock, request ); 1575 require_action_quiet( res >= 0, exit, err = mStatus_UnknownErr ; Log( "Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 1576 1577 reply = RecvPacket( sock, &buf, &closed ); 1578 } 1579 1580 // IMPORTANT: reply is in network byte order at this point in the code 1581 // We keep it this way because we send it back to the client in the same form 1582 1583 // Is it an update? 1584 1585 if ( reply && ( ( reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( kDNSFlag0_OP_Update | kDNSFlag0_QR_Response ) ) ) 1586 { 1587 char pingmsg[4]; 1588 mDNSBool ok = SuccessfulUpdateTransaction( request, reply ); 1589 require_action( ok, exit, err = mStatus_UnknownErr; VLog( "Message from %s not a successful update.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 1590 1591 UpdateLeaseTable( request, self, lease ); 1592 1593 if ( lease > 0 ) 1594 { 1595 leaseReply = FormatLeaseReply( self, reply, lease ); 1596 1597 if ( !leaseReply ) 1598 { 1599 Log("HandleRequest - unable to format lease reply"); 1600 } 1601 1602 // %%% Looks like a potential memory leak -- who frees the original reply? 1603 reply = leaseReply; 1604 } 1605 1606 // tell the main thread there was an update so it can send LLQs 1607 1608 if ( send( self->LLQEventNotifySock, pingmsg, sizeof( pingmsg ), 0 ) != sizeof( pingmsg ) ) 1609 { 1610 LogErr("HandleRequest", "send"); 1611 } 1612 } 1613 1614 exit: 1615 1616 if ( sock ) 1617 { 1618 mDNSPlatformTCPCloseConnection( sock ); 1619 } 1620 1621 if ( reply == &buf ) 1622 { 1623 reply = malloc( sizeof( *reply ) ); 1624 1625 if ( reply ) 1626 { 1627 reply->len = buf.len; 1628 memcpy(&reply->msg, &buf.msg, buf.len); 1629 } 1630 else 1631 { 1632 LogErr("HandleRequest", "malloc"); 1633 } 1634 } 1635 1636 return reply; 1637 } 1638 1639 1640 // 1641 // LLQ Support Routines 1642 // 1643 1644 // Set fields of an LLQ OPT Resource Record 1645 mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, const mDNSOpaque64 *const id, mDNSs32 lease) 1646 { 1647 mDNSPlatformMemZero(opt, sizeof(*opt)); 1648 mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 1649 opt->resrec.rrclass = NormalMaxDNSMessageData; 1650 opt->resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record 1651 opt->resrec.rdestimate = sizeof(rdataOPT); 1652 opt->resrec.rdata->u.opt[0].opt = kDNSOpt_LLQ; 1653 opt->resrec.rdata->u.opt[0].u.llq.vers = kLLQ_Vers; 1654 opt->resrec.rdata->u.opt[0].u.llq.llqOp = opcode; 1655 opt->resrec.rdata->u.opt[0].u.llq.err = LLQErr_NoError; 1656 opt->resrec.rdata->u.opt[0].u.llq.id = *id; 1657 opt->resrec.rdata->u.opt[0].u.llq.llqlease = lease; 1658 } 1659 1660 // Calculate effective remaining lease of an LLQ 1661 mDNSlocal mDNSu32 LLQLease(LLQEntry *e) 1662 { 1663 struct timeval t; 1664 1665 gettimeofday(&t, NULL); 1666 if (e->expire < t.tv_sec) return 0; 1667 else return e->expire - t.tv_sec; 1668 } 1669 1670 mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) 1671 { 1672 int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; 1673 LLQEntry **ptr = &d->LLQTable[bucket]; 1674 AnswerListElem *a = e->AnswerList; 1675 char addr[32]; 1676 1677 inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 1678 VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr); 1679 1680 if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE) 1681 { 1682 // currently, generating initial answers blocks the main thread, so we keep the answer list 1683 // even if the ref count drops to zero. To prevent unbounded table growth, we free shared answers 1684 // if the ref count drops to zero AND there are more table elements than buckets 1685 // !!!KRS update this when we make the table dynamically growable 1686 1687 CacheRecord *cr = a->KnownAnswers, *tmp; 1688 AnswerListElem **tbl = &d->AnswerTable[bucket]; 1689 1690 while (cr) 1691 { 1692 tmp = cr; 1693 cr = cr->next; 1694 free(tmp); 1695 } 1696 1697 while (*tbl && *tbl != a) tbl = &(*tbl)->next; 1698 if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; } 1699 else Log("Error: DeleteLLQ - AnswerList not found in table"); 1700 } 1701 1702 // remove LLQ from table, free memory 1703 while(*ptr && *ptr != e) ptr = &(*ptr)->next; 1704 if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; } 1705 *ptr = (*ptr)->next; 1706 free(e); 1707 } 1708 1709 mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst, TCPSocket *sock) 1710 { 1711 char addr[32]; 1712 int err = -1; 1713 1714 HdrHToN(pkt); 1715 1716 if ( sock ) 1717 { 1718 if ( SendPacket( sock, pkt ) != 0 ) 1719 { 1720 LogErr("DaemonInfo", "MySend"); 1721 Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32)); 1722 } 1723 } 1724 else 1725 { 1726 if (sendto(d->llq_udpsd, &pkt->msg, pkt->len, 0, (struct sockaddr *)&dst, sizeof(dst)) != (int)pkt->len) 1727 { 1728 LogErr("DaemonInfo", "sendto"); 1729 Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32)); 1730 } 1731 } 1732 1733 err = 0; 1734 HdrNToH(pkt); 1735 return err; 1736 } 1737 1738 mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e) 1739 { 1740 PktMsg q; 1741 int i; 1742 TCPSocket *sock = NULL; 1743 const mDNSu8 *ansptr; 1744 mDNSu8 *end = q.msg.data; 1745 PktMsg buf, *reply = NULL; 1746 LargeCacheRecord lcr; 1747 CacheRecord *AnswerList = NULL; 1748 mDNSu8 rcode; 1749 1750 VLog("Querying server for %##s type %d", e->name.c, e->type); 1751 1752 InitializeDNSMessage(&q.msg.h, zeroID, uQueryFlags); 1753 1754 end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN); 1755 if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; } 1756 q.len = (int)(end - (mDNSu8 *)&q.msg); 1757 1758 HdrHToN(&q); 1759 1760 if (!e->UseTCP) 1761 { 1762 mDNSBool trunc; 1763 1764 if (UDPServerTransaction(d, &q, &buf, &trunc) < 0) 1765 Log("AnswerQuestion %##s - UDPServerTransaction failed. Trying TCP", e->name.c); 1766 else if (trunc) 1767 { VLog("AnswerQuestion %##s - answer truncated. Using TCP", e->name.c); e->UseTCP = mDNStrue; } 1768 else reply = &buf; // success 1769 } 1770 1771 if (!reply) 1772 { 1773 mDNSBool closed; 1774 1775 sock = ConnectToServer(d); 1776 if (!sock) { Log("AnswerQuestion: ConnectToServer failed"); goto end; } 1777 if (SendPacket( sock, &q)) { Log("AnswerQuestion: SendPacket failed"); mDNSPlatformTCPCloseConnection( sock ); goto end; } 1778 reply = RecvPacket( sock, NULL, &closed ); 1779 mDNSPlatformTCPCloseConnection( sock ); 1780 require_action( reply, end, Log( "AnswerQuestion: RecvPacket returned NULL" ) ); 1781 } 1782 1783 HdrNToH(&q); 1784 if (reply) HdrNToH(reply); 1785 1786 if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery)) 1787 { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; } 1788 rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask); 1789 if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; } 1790 1791 end = (mDNSu8 *)&reply->msg + reply->len; 1792 ansptr = LocateAnswers(&reply->msg, end); 1793 if (!ansptr) { Log("Error: AnswerQuestion - LocateAnswers returned NULL"); goto end; } 1794 1795 for (i = 0; i < reply->msg.h.numAnswers; i++) 1796 { 1797 ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr); 1798 if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; } 1799 if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative) 1800 { 1801 if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name)) 1802 { 1803 Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding", 1804 lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type); 1805 } 1806 else 1807 { 1808 CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name); 1809 if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; } 1810 cr->next = AnswerList; 1811 AnswerList = cr; 1812 } 1813 } 1814 } 1815 1816 end: 1817 if (reply && reply != &buf) free(reply); 1818 return AnswerList; 1819 } 1820 1821 // Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list 1822 mDNSlocal void *UpdateAnswerList(void *args) 1823 { 1824 CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer" 1825 DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d; 1826 AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a; 1827 1828 free(args); 1829 args = NULL; 1830 1831 // get up to date answers 1832 NewAnswers = AnswerQuestion(d, a); 1833 1834 // first pass - mark all answers for deletion 1835 for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 1836 (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete 1837 1838 // second pass - mark answers pre-existent 1839 for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 1840 { 1841 for (na = &NewAnswers; *na; na = &(*na)->next) 1842 { 1843 if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) 1844 { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change 1845 } 1846 } 1847 1848 // third pass - add new records to Event list 1849 na = &NewAnswers; 1850 while (*na) 1851 { 1852 for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 1853 if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break; 1854 if (!*ka) 1855 { 1856 // answer is not in list - splice from NewAnswers list, add to Event list 1857 cr = *na; 1858 *na = (*na)->next; // splice from list 1859 cr->next = a->EventList; // add spliced record to event list 1860 a->EventList = cr; 1861 cr->resrec.rroriginalttl = 1; // 1 means add 1862 } 1863 else na = &(*na)->next; 1864 } 1865 1866 // move all the removes from the answer list to the event list 1867 ka = &a->KnownAnswers; 1868 while (*ka) 1869 { 1870 if ((*ka)->resrec.rroriginalttl == (unsigned)-1) 1871 { 1872 cr = *ka; 1873 *ka = (*ka)->next; 1874 cr->next = a->EventList; 1875 a->EventList = cr; 1876 } 1877 else ka = &(*ka)->next; 1878 } 1879 1880 // lastly, free the remaining records (known answers) in NewAnswers list 1881 while (NewAnswers) 1882 { 1883 cr = NewAnswers; 1884 NewAnswers = NewAnswers->next; 1885 free(cr); 1886 } 1887 1888 return NULL; 1889 } 1890 1891 mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) 1892 { 1893 PktMsg response; 1894 CacheRecord *cr; 1895 mDNSu8 *end = (mDNSu8 *)&response.msg.data; 1896 mDNSOpaque16 msgID; 1897 char rrbuf[MaxMsg], addrbuf[32]; 1898 AuthRecord opt; 1899 1900 // Should this really be random? Do we use the msgID on the receiving end? 1901 msgID.NotAnInteger = random(); 1902 if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); 1903 InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags); 1904 end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 1905 if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; } 1906 1907 // put adds/removes in packet 1908 for (cr = e->AnswerList->EventList; cr; cr = cr->next) 1909 { 1910 if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf); 1911 VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); 1912 end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl); 1913 if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; } 1914 } 1915 1916 FormatLLQOpt(&opt, kLLQOp_Event, &e->id, LLQLease(e)); 1917 end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0); 1918 if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; } 1919 1920 response.len = (int)(end - (mDNSu8 *)&response.msg); 1921 if (SendLLQ(d, &response, e->cli, NULL ) < 0) LogMsg("Error: SendEvents - SendLLQ"); 1922 } 1923 1924 mDNSlocal void PrintLLQAnswers(DaemonInfo *d) 1925 { 1926 int i; 1927 char rrbuf[MaxMsg]; 1928 1929 Log("Printing LLQ Answer Table contents"); 1930 1931 for (i = 0; i < LLQ_TABLESIZE; i++) 1932 { 1933 AnswerListElem *a = d->AnswerTable[i]; 1934 while(a) 1935 { 1936 int ancount = 0; 1937 const CacheRecord *rr = a->KnownAnswers; 1938 while (rr) { ancount++; rr = rr->next; } 1939 Log("%p : Question %##s; type %d; referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount); 1940 for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf)); 1941 a = a->next; 1942 } 1943 } 1944 } 1945 1946 mDNSlocal void PrintLLQTable(DaemonInfo *d) 1947 { 1948 LLQEntry *e; 1949 char addr[32]; 1950 int i; 1951 1952 Log("Printing LLQ table contents"); 1953 1954 for (i = 0; i < LLQ_TABLESIZE; i++) 1955 { 1956 e = d->LLQTable[i]; 1957 while(e) 1958 { 1959 char *state; 1960 1961 switch (e->state) 1962 { 1963 case RequestReceived: state = "RequestReceived"; break; 1964 case ChallengeSent: state = "ChallengeSent"; break; 1965 case Established: state = "Established"; break; 1966 default: state = "unknown"; 1967 } 1968 inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 1969 1970 Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)", 1971 addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList); 1972 e = e->next; 1973 } 1974 } 1975 } 1976 1977 // Send events to clients as a result of a change in the zone 1978 mDNSlocal void GenLLQEvents(DaemonInfo *d) 1979 { 1980 LLQEntry **e; 1981 int i; 1982 struct timeval t; 1983 UpdateAnswerListArgs *args; 1984 1985 VLog("Generating LLQ Events"); 1986 1987 gettimeofday(&t, NULL); 1988 1989 // get all answers up to date 1990 for (i = 0; i < LLQ_TABLESIZE; i++) 1991 { 1992 AnswerListElem *a = d->AnswerTable[i]; 1993 while(a) 1994 { 1995 args = malloc(sizeof(*args)); 1996 if (!args) { LogErr("GenLLQEvents", "malloc"); return; } 1997 args->d = d; 1998 args->a = a; 1999 if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; } 2000 usleep(1); 2001 a = a->next; 2002 } 2003 } 2004 2005 for (i = 0; i < LLQ_TABLESIZE; i++) 2006 { 2007 AnswerListElem *a = d->AnswerTable[i]; 2008 while(a) 2009 { 2010 if (pthread_join(a->tid, NULL)) LogErr("GenLLQEvents", "pthread_join"); 2011 a = a->next; 2012 } 2013 } 2014 2015 // for each established LLQ, send events 2016 for (i = 0; i < LLQ_TABLESIZE; i++) 2017 { 2018 e = &d->LLQTable[i]; 2019 while(*e) 2020 { 2021 if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e); 2022 else 2023 { 2024 if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e); 2025 e = &(*e)->next; 2026 } 2027 } 2028 } 2029 2030 // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes 2031 for (i = 0; i < LLQ_TABLESIZE; i++) 2032 { 2033 AnswerListElem *a = d->AnswerTable[i]; 2034 while(a) 2035 { 2036 if (a->EventList) 2037 { 2038 CacheRecord *cr = a->EventList, *tmp; 2039 while (cr) 2040 { 2041 tmp = cr; 2042 cr = cr->next; 2043 if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp); 2044 else 2045 { 2046 tmp->next = a->KnownAnswers; 2047 a->KnownAnswers = tmp; 2048 tmp->resrec.rroriginalttl = 0; 2049 } 2050 } 2051 a->EventList = NULL; 2052 } 2053 a = a->next; 2054 } 2055 } 2056 } 2057 2058 mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) 2059 { 2060 int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; 2061 AnswerListElem *a = d->AnswerTable[bucket]; 2062 while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next; 2063 if (!a) 2064 { 2065 a = malloc(sizeof(*a)); 2066 if (!a) { LogErr("SetAnswerList", "malloc"); return; } 2067 AssignDomainName(&a->name, &e->qname); 2068 a->type = e->qtype; 2069 a->refcount = 0; 2070 a->EventList = NULL; 2071 a->UseTCP = mDNSfalse; 2072 a->next = d->AnswerTable[bucket]; 2073 d->AnswerTable[bucket] = a; 2074 d->AnswerTableCount++; 2075 a->KnownAnswers = AnswerQuestion(d, a); 2076 } 2077 2078 e->AnswerList = a; 2079 a->refcount ++; 2080 } 2081 2082 // Allocate LLQ entry, insert into table 2083 mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease ) 2084 { 2085 char addr[32]; 2086 struct timeval t; 2087 int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; 2088 LLQEntry *e; 2089 2090 e = malloc(sizeof(*e)); 2091 if (!e) { LogErr("NewLLQ", "malloc"); return NULL; } 2092 2093 inet_ntop(AF_INET, &cli.sin_addr, addr, 32); 2094 VLog("Allocating LLQ entry for client %s question %##s type %d", addr, qname->c, qtype); 2095 2096 // initialize structure 2097 e->cli = cli; 2098 AssignDomainName(&e->qname, qname); 2099 e->qtype = qtype; 2100 e->id = zeroOpaque64; 2101 e->state = RequestReceived; 2102 e->AnswerList = NULL; 2103 2104 if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE; 2105 else if (lease > LLQ_MAX_LEASE) lease = LLQ_MAX_LEASE; 2106 2107 gettimeofday(&t, NULL); 2108 e->expire = t.tv_sec + (int)lease; 2109 e->lease = lease; 2110 2111 // add to table 2112 e->next = d->LLQTable[bucket]; 2113 d->LLQTable[bucket] = e; 2114 2115 return e; 2116 } 2117 2118 // Handle a refresh request from client 2119 mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock ) 2120 { 2121 AuthRecord opt; 2122 PktMsg ack; 2123 mDNSu8 *end = (mDNSu8 *)&ack.msg.data; 2124 char addr[32]; 2125 2126 inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 2127 VLog("%s LLQ for %##s from %s", llq->llqlease ? "Refreshing" : "Deleting", e->qname.c, addr); 2128 2129 if (llq->llqlease) 2130 { 2131 struct timeval t; 2132 if (llq->llqlease < LLQ_MIN_LEASE) llq->llqlease = LLQ_MIN_LEASE; 2133 else if (llq->llqlease > LLQ_MAX_LEASE) llq->llqlease = LLQ_MIN_LEASE; 2134 gettimeofday(&t, NULL); 2135 e->expire = t.tv_sec + llq->llqlease; 2136 } 2137 2138 ack.src.sin_addr.s_addr = 0; // unused 2139 InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); 2140 end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 2141 if (!end) { Log("Error: putQuestion"); return; } 2142 2143 FormatLLQOpt(&opt, kLLQOp_Refresh, &e->id, llq->llqlease ? LLQLease(e) : 0); 2144 end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); 2145 if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 2146 2147 ack.len = (int)(end - (mDNSu8 *)&ack.msg); 2148 if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQRefresh"); 2149 2150 if (llq->llqlease) e->state = Established; 2151 else DeleteLLQ(d, e); 2152 } 2153 2154 // Complete handshake with Ack an initial answers 2155 mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock) 2156 { 2157 char addr[32]; 2158 CacheRecord *ptr; 2159 AuthRecord opt; 2160 PktMsg ack; 2161 mDNSu8 *end = (mDNSu8 *)&ack.msg.data; 2162 char rrbuf[MaxMsg], addrbuf[32]; 2163 2164 inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 2165 2166 if (!mDNSSameOpaque64(&llq->id, &e->id) || 2167 llq->vers != kLLQ_Vers || 2168 llq->llqOp != kLLQOp_Setup || 2169 llq->err != LLQErr_NoError || 2170 llq->llqlease > e->lease + LLQ_LEASE_FUDGE || 2171 llq->llqlease < e->lease - LLQ_LEASE_FUDGE) 2172 { 2173 Log("Incorrect challenge response from %s", addr); 2174 return; 2175 } 2176 2177 if (e->state == Established) VLog("Retransmitting LLQ ack + answers for %##s", e->qname.c); 2178 else VLog("Delivering LLQ ack + answers for %##s", e->qname.c); 2179 2180 // format ack + answers 2181 ack.src.sin_addr.s_addr = 0; // unused 2182 InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); 2183 end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 2184 if (!end) { Log("Error: putQuestion"); return; } 2185 2186 if (e->state != Established) { SetAnswerList(d, e); e->state = Established; } 2187 2188 if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); 2189 for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next) 2190 { 2191 if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf); 2192 VLog("%s Intitial Answer - %s", addr, rrbuf); 2193 end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAnswers, &ptr->resrec, 1); 2194 if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 2195 } 2196 2197 FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e)); 2198 end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); 2199 if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 2200 2201 ack.len = (int)(end - (mDNSu8 *)&ack.msg); 2202 if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQCompleteHandshake"); 2203 } 2204 2205 mDNSlocal void LLQSetupChallenge(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID) 2206 { 2207 struct timeval t; 2208 PktMsg challenge; 2209 mDNSu8 *end = challenge.msg.data; 2210 AuthRecord opt; 2211 2212 if (e->state == ChallengeSent) VLog("Retransmitting LLQ setup challenge for %##s", e->qname.c); 2213 else VLog("Sending LLQ setup challenge for %##s", e->qname.c); 2214 2215 if (!mDNSOpaque64IsZero(&llq->id)) { Log("Error: LLQSetupChallenge - nonzero ID"); return; } // server bug 2216 if (llq->llqOp != kLLQOp_Setup) { Log("LLQSetupChallenge - incorrrect operation from client"); return; } // client error 2217 2218 if (mDNSOpaque64IsZero(&e->id)) // don't regenerate random ID for retransmissions 2219 { 2220 // construct ID <time><random> 2221 gettimeofday(&t, NULL); 2222 e->id.l[0] = t.tv_sec; 2223 e->id.l[1] = random(); 2224 } 2225 2226 // format response (query + LLQ opt rr) 2227 challenge.src.sin_addr.s_addr = 0; // unused 2228 InitializeDNSMessage(&challenge.msg.h, msgID, ResponseFlags); 2229 end = putQuestion(&challenge.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 2230 if (!end) { Log("Error: putQuestion"); return; } 2231 FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e)); 2232 end = PutResourceRecordTTLJumbo(&challenge.msg, end, &challenge.msg.h.numAdditionals, &opt.resrec, 0); 2233 if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 2234 challenge.len = (int)(end - (mDNSu8 *)&challenge.msg); 2235 if (SendLLQ(d, &challenge, e->cli, NULL)) { Log("Error: LLQSetupChallenge"); return; } 2236 e->state = ChallengeSent; 2237 } 2238 2239 // Take action on an LLQ message from client. Entry must be initialized and in table 2240 mDNSlocal void UpdateLLQ(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock ) 2241 { 2242 switch(e->state) 2243 { 2244 case RequestReceived: 2245 if ( sock ) 2246 { 2247 struct timeval t; 2248 gettimeofday(&t, NULL); 2249 e->id.l[0] = t.tv_sec; // construct ID <time><random> 2250 e->id.l[1] = random(); 2251 llq->id = e->id; 2252 LLQCompleteHandshake( d, e, llq, msgID, sock ); 2253 2254 // Set the state to established because we've just set the LLQ up using TCP 2255 e->state = Established; 2256 } 2257 else 2258 { 2259 LLQSetupChallenge(d, e, llq, msgID); 2260 } 2261 return; 2262 case ChallengeSent: 2263 if (mDNSOpaque64IsZero(&llq->id)) LLQSetupChallenge(d, e, llq, msgID); // challenge sent and lost 2264 else LLQCompleteHandshake(d, e, llq, msgID, sock ); 2265 return; 2266 case Established: 2267 if (mDNSOpaque64IsZero(&llq->id)) 2268 { 2269 // client started over. reset state. 2270 LLQEntry *newe = NewLLQ(d, e->cli, &e->qname, e->qtype, llq->llqlease ); 2271 if (!newe) return; 2272 DeleteLLQ(d, e); 2273 LLQSetupChallenge(d, newe, llq, msgID); 2274 return; 2275 } 2276 else if (llq->llqOp == kLLQOp_Setup) 2277 { LLQCompleteHandshake(d, e, llq, msgID, sock); return; } // Ack lost 2278 else if (llq->llqOp == kLLQOp_Refresh) 2279 { LLQRefresh(d, e, llq, msgID, sock); return; } 2280 else { Log("Unhandled message for established LLQ"); return; } 2281 } 2282 } 2283 2284 mDNSlocal LLQEntry *LookupLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, const mDNSOpaque64 *const id) 2285 { 2286 int bucket = bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; 2287 LLQEntry *ptr = d->LLQTable[bucket]; 2288 2289 while(ptr) 2290 { 2291 if (((ptr->state == ChallengeSent && mDNSOpaque64IsZero(id) && (cli.sin_port == ptr->cli.sin_port)) || // zero-id due to packet loss OK in state ChallengeSent 2292 mDNSSameOpaque64(id, &ptr->id)) && // id match 2293 (cli.sin_addr.s_addr == ptr->cli.sin_addr.s_addr) && (qtype == ptr->qtype) && SameDomainName(&ptr->qname, qname)) // same source, type, qname 2294 return ptr; 2295 ptr = ptr->next; 2296 } 2297 return NULL; 2298 } 2299 2300 mDNSlocal int 2301 RecvNotify 2302 ( 2303 DaemonInfo * d, 2304 PktMsg * pkt 2305 ) 2306 { 2307 int res; 2308 int err = 0; 2309 2310 pkt->msg.h.flags.b[0] |= kDNSFlag0_QR_Response; 2311 2312 res = sendto( d->udpsd, &pkt->msg, pkt->len, 0, ( struct sockaddr* ) &pkt->src, sizeof( pkt->src ) ); 2313 require_action( res == ( int ) pkt->len, exit, err = mStatus_UnknownErr; LogErr( "RecvNotify", "sendto" ) ); 2314 2315 exit: 2316 2317 return err; 2318 } 2319 2320 2321 mDNSlocal int RecvLLQ( DaemonInfo *d, PktMsg *pkt, TCPSocket *sock ) 2322 { 2323 DNSQuestion q; 2324 LargeCacheRecord opt; 2325 int i, err = -1; 2326 char addr[32]; 2327 const mDNSu8 *qptr = pkt->msg.data; 2328 const mDNSu8 *end = (mDNSu8 *)&pkt->msg + pkt->len; 2329 const mDNSu8 *aptr; 2330 LLQOptData *llq = NULL; 2331 LLQEntry *e = NULL; 2332 2333 HdrNToH(pkt); 2334 aptr = LocateAdditionals(&pkt->msg, end); // Can't do this until after HdrNToH(pkt); 2335 inet_ntop(AF_INET, &pkt->src.sin_addr, addr, 32); 2336 2337 VLog("Received LLQ msg from %s", addr); 2338 // sanity-check packet 2339 if (!pkt->msg.h.numQuestions || !pkt->msg.h.numAdditionals) 2340 { 2341 Log("Malformatted LLQ from %s with %d questions, %d additionals", addr, pkt->msg.h.numQuestions, pkt->msg.h.numAdditionals); 2342 goto end; 2343 } 2344 2345 // Locate the OPT record. 2346 // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response." 2347 // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section, 2348 // but not necessarily the *last* entry in the Additional Section. 2349 for (i = 0; i < pkt->msg.h.numAdditionals; i++) 2350 { 2351 aptr = GetLargeResourceRecord(NULL, &pkt->msg, aptr, end, 0, kDNSRecordTypePacketAdd, &opt); 2352 if (!aptr) { Log("Malformatted LLQ from %s: could not get Additional record %d", addr, i); goto end; } 2353 if (opt.r.resrec.RecordType != kDNSRecordTypePacketNegative && opt.r.resrec.rrtype == kDNSType_OPT) break; 2354 } 2355 2356 // validate OPT 2357 if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an OPT RR", addr); goto end; } 2358 if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * DNSOpt_LLQData_Space) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); } 2359 2360 // dispatch each question 2361 for (i = 0; i < pkt->msg.h.numQuestions; i++) 2362 { 2363 qptr = getQuestion(&pkt->msg, qptr, end, 0, &q); 2364 if (!qptr) { Log("Malformatted LLQ from %s: cannot read question %d", addr, i); goto end; } 2365 llq = (LLQOptData *)&opt.r.resrec.rdata->u.opt[0].u.llq + i; // point into OptData at index i 2366 if (llq->vers != kLLQ_Vers) { Log("LLQ from %s contains bad version %d (expected %d)", addr, llq->vers, kLLQ_Vers); goto end; } 2367 2368 e = LookupLLQ(d, pkt->src, &q.qname, q.qtype, &llq->id); 2369 if (!e) 2370 { 2371 // no entry - if zero ID, create new 2372 e = NewLLQ(d, pkt->src, &q.qname, q.qtype, llq->llqlease ); 2373 if (!e) goto end; 2374 } 2375 UpdateLLQ(d, e, llq, pkt->msg.h.id, sock); 2376 } 2377 err = 0; 2378 2379 end: 2380 HdrHToN(pkt); 2381 return err; 2382 } 2383 2384 2385 mDNSlocal mDNSBool IsAuthorized( DaemonInfo * d, PktMsg * pkt, DomainAuthInfo ** key, mDNSu16 * rcode, mDNSu16 * tcode ) 2386 { 2387 const mDNSu8 * lastPtr = NULL; 2388 const mDNSu8 * ptr = NULL; 2389 DomainAuthInfo * keys; 2390 mDNSu8 * end = ( mDNSu8* ) &pkt->msg + pkt->len; 2391 LargeCacheRecord lcr; 2392 mDNSBool hasTSIG = mDNSfalse; 2393 mDNSBool strip = mDNSfalse; 2394 mDNSBool ok = mDNSfalse; 2395 int i; 2396 2397 // Unused parameters 2398 2399 ( void ) d; 2400 2401 HdrNToH(pkt); 2402 2403 *key = NULL; 2404 2405 if ( pkt->msg.h.numAdditionals ) 2406 { 2407 ptr = LocateAdditionals(&pkt->msg, end); 2408 if (ptr) 2409 { 2410 for (i = 0; i < pkt->msg.h.numAdditionals; i++) 2411 { 2412 lastPtr = ptr; 2413 ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); 2414 if (!ptr) 2415 { 2416 Log("Unable to read additional record"); 2417 lastPtr = NULL; 2418 break; 2419 } 2420 } 2421 2422 hasTSIG = ( ptr && lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG ); 2423 } 2424 else 2425 { 2426 LogMsg( "IsAuthorized: unable to find Additional section" ); 2427 } 2428 } 2429 2430 // If we don't know what zone this is, then it's authorized. 2431 2432 if ( !pkt->zone ) 2433 { 2434 ok = mDNStrue; 2435 strip = mDNSfalse; 2436 goto exit; 2437 } 2438 2439 if ( IsQuery( pkt ) ) 2440 { 2441 keys = pkt->zone->queryKeys; 2442 strip = mDNStrue; 2443 } 2444 else if ( IsUpdate( pkt ) ) 2445 { 2446 keys = pkt->zone->updateKeys; 2447 strip = mDNSfalse; 2448 } 2449 else 2450 { 2451 ok = mDNStrue; 2452 strip = mDNSfalse; 2453 goto exit; 2454 } 2455 2456 if ( pkt->isZonePublic ) 2457 { 2458 ok = mDNStrue; 2459 goto exit; 2460 } 2461 2462 // If there are no keys, then we're authorized 2463 2464 if ( ( hasTSIG && !keys ) || ( !hasTSIG && keys ) ) 2465 { 2466 Log( "Invalid TSIG spec %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c ); 2467 *rcode = kDNSFlag1_RC_NotAuth; 2468 *tcode = TSIG_ErrBadKey; 2469 strip = mDNStrue; 2470 ok = mDNSfalse; 2471 goto exit; 2472 } 2473 2474 // Find the right key 2475 2476 for ( *key = keys; *key; *key = (*key)->next ) 2477 { 2478 if ( SameDomainName( lcr.r.resrec.name, &(*key)->keyname ) ) 2479 { 2480 break; 2481 } 2482 } 2483 2484 if ( !(*key) ) 2485 { 2486 Log( "Invalid TSIG name %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c ); 2487 *rcode = kDNSFlag1_RC_NotAuth; 2488 *tcode = TSIG_ErrBadKey; 2489 strip = mDNStrue; 2490 ok = mDNSfalse; 2491 goto exit; 2492 } 2493 2494 // Okay, we have the correct key and a TSIG record. DNSDigest_VerifyMessage does the heavy 2495 // lifting of message verification 2496 2497 pkt->msg.h.numAdditionals--; 2498 2499 HdrHToN( pkt ); 2500 2501 ok = DNSDigest_VerifyMessage( &pkt->msg, ( mDNSu8* ) lastPtr, &lcr, (*key), rcode, tcode ); 2502 2503 HdrNToH( pkt ); 2504 2505 pkt->msg.h.numAdditionals++; 2506 2507 exit: 2508 2509 if ( hasTSIG && strip ) 2510 { 2511 // Strip the TSIG from the message 2512 2513 pkt->msg.h.numAdditionals--; 2514 pkt->len = lastPtr - ( mDNSu8* ) ( &pkt->msg ); 2515 } 2516 2517 HdrHToN(pkt); 2518 2519 return ok; 2520 } 2521 2522 // request handler wrappers for TCP and UDP requests 2523 // (read message off socket, fork thread that invokes main processing routine and handles cleanup) 2524 2525 mDNSlocal void* 2526 UDPMessageHandler 2527 ( 2528 void * vptr 2529 ) 2530 { 2531 UDPContext * context = ( UDPContext* ) vptr; 2532 PktMsg * reply = NULL; 2533 int res; 2534 mStatus err; 2535 2536 // !!!KRS strictly speaking, we shouldn't use TCP for a UDP request because the server 2537 // may give us a long answer that would require truncation for UDP delivery to client 2538 2539 reply = HandleRequest( context->d, &context->pkt ); 2540 require_action( reply, exit, err = mStatus_UnknownErr ); 2541 2542 res = sendto( context->sd, &reply->msg, reply->len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) ); 2543 require_action_quiet( res == ( int ) reply->len, exit, LogErr( "UDPMessageHandler", "sendto" ) ); 2544 2545 exit: 2546 2547 if ( reply ) 2548 { 2549 free( reply ); 2550 } 2551 2552 free( context ); 2553 2554 pthread_exit( NULL ); 2555 2556 return NULL; 2557 } 2558 2559 2560 mDNSlocal int 2561 RecvUDPMessage 2562 ( 2563 DaemonInfo * self, 2564 int sd 2565 ) 2566 { 2567 UDPContext * context = NULL; 2568 pthread_t tid; 2569 mDNSu16 rcode; 2570 mDNSu16 tcode; 2571 DomainAuthInfo * key; 2572 unsigned int clisize = sizeof( context->cliaddr ); 2573 int res; 2574 mStatus err = mStatus_NoError; 2575 2576 context = malloc( sizeof( UDPContext ) ); 2577 require_action( context, exit, err = mStatus_NoMemoryErr ; LogErr( "RecvUDPMessage", "malloc" ) ); 2578 2579 mDNSPlatformMemZero( context, sizeof( *context ) ); 2580 context->d = self; 2581 context->sd = sd; 2582 2583 res = recvfrom(sd, &context->pkt.msg, sizeof(context->pkt.msg), 0, (struct sockaddr *)&context->cliaddr, &clisize); 2584 2585 require_action( res >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvUDPMessage", "recvfrom" ) ); 2586 context->pkt.len = res; 2587 require_action( clisize == sizeof( context->cliaddr ), exit, err = mStatus_UnknownErr ; Log( "Client address of unknown size %d", clisize ) ); 2588 context->pkt.src = context->cliaddr; 2589 2590 // Set the zone in the packet 2591 2592 SetZone( context->d, &context->pkt ); 2593 2594 // Notify messages handled by main thread 2595 2596 if ( IsNotify( &context->pkt ) ) 2597 { 2598 int e = RecvNotify( self, &context->pkt ); 2599 free(context); 2600 return e; 2601 } 2602 else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) ) 2603 { 2604 if ( IsLLQRequest( &context->pkt ) ) 2605 { 2606 // LLQ messages handled by main thread 2607 int e = RecvLLQ( self, &context->pkt, NULL ); 2608 free(context); 2609 return e; 2610 } 2611 2612 if ( IsLLQAck(&context->pkt ) ) 2613 { 2614 // !!!KRS need to do acks + retrans 2615 2616 free(context); 2617 return 0; 2618 } 2619 2620 err = pthread_create( &tid, NULL, UDPMessageHandler, context ); 2621 require_action( !err, exit, LogErr( "RecvUDPMessage", "pthread_create" ) ); 2622 2623 pthread_detach(tid); 2624 } 2625 else 2626 { 2627 PktMsg reply; 2628 int e; 2629 2630 memcpy( &reply, &context->pkt, sizeof( PktMsg ) ); 2631 2632 reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD; 2633 reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_NXDomain; 2634 2635 e = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) ); 2636 require_action_quiet( e == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) ); 2637 2638 err = mStatus_NoAuth; 2639 } 2640 2641 exit: 2642 2643 if ( err && context ) 2644 { 2645 free( context ); 2646 } 2647 2648 return err; 2649 } 2650 2651 2652 mDNSlocal void 2653 FreeTCPContext 2654 ( 2655 TCPContext * context 2656 ) 2657 { 2658 if ( context ) 2659 { 2660 if ( context->sock ) 2661 { 2662 mDNSPlatformTCPCloseConnection( context->sock ); 2663 } 2664 2665 free( context ); 2666 } 2667 } 2668 2669 2670 mDNSlocal void* 2671 TCPMessageHandler 2672 ( 2673 void * vptr 2674 ) 2675 { 2676 TCPContext * context = ( TCPContext* ) vptr; 2677 PktMsg * reply = NULL; 2678 int res; 2679 char buf[32]; 2680 2681 //!!!KRS if this read blocks indefinitely, we can run out of threads 2682 // read the request 2683 2684 reply = HandleRequest( context->d, &context->pkt ); 2685 require_action_quiet( reply, exit, LogMsg( "TCPMessageHandler: No reply for client %s", inet_ntop( AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) ); 2686 2687 // deliver reply to client 2688 2689 res = SendPacket( context->sock, reply ); 2690 require_action( res >= 0, exit, LogMsg("TCPMessageHandler: Unable to send reply to client %s", inet_ntop(AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) ); 2691 2692 exit: 2693 2694 FreeTCPContext( context ); 2695 2696 if ( reply ) 2697 { 2698 free( reply ); 2699 } 2700 2701 pthread_exit(NULL); 2702 } 2703 2704 2705 mDNSlocal void 2706 RecvTCPMessage 2707 ( 2708 void * param 2709 ) 2710 { 2711 TCPContext * context = ( TCPContext* ) param; 2712 mDNSu16 rcode; 2713 mDNSu16 tcode; 2714 pthread_t tid; 2715 DomainAuthInfo * key; 2716 PktMsg * pkt; 2717 mDNSBool closed; 2718 mDNSBool freeContext = mDNStrue; 2719 mStatus err = mStatus_NoError; 2720 2721 // Receive a packet. It's okay if we don't actually read a packet, as long as the closed flag is 2722 // set to false. This is because SSL/TLS layer might gobble up the first packet that we read off the 2723 // wire. We'll let it do that, and wait for the next packet which will be ours. 2724 2725 pkt = RecvPacket( context->sock, &context->pkt, &closed ); 2726 if (pkt) HdrNToH(pkt); 2727 require_action( pkt || !closed, exit, err = mStatus_UnknownErr; LogMsg( "client disconnected" ) ); 2728 2729 if ( pkt ) 2730 { 2731 // Always do this, regardless of what kind of packet it is. If we wanted LLQ events to be sent over TCP, 2732 // we would change this line of code. As it is now, we will reply to an LLQ via TCP, but then events 2733 // are sent over UDP 2734 2735 RemoveSourceFromEventLoop( context->d, context->sock ); 2736 2737 // Set's the DNS Zone that is associated with this message 2738 2739 SetZone( context->d, &context->pkt ); 2740 2741 // IsAuthorized will make sure the message is authorized for the designated zone. 2742 // After verifying the signature, it will strip the TSIG from the message 2743 2744 if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) ) 2745 { 2746 if ( IsLLQRequest( &context->pkt ) ) 2747 { 2748 // LLQ messages handled by main thread 2749 RecvLLQ( context->d, &context->pkt, context->sock); 2750 } 2751 else 2752 { 2753 err = pthread_create( &tid, NULL, TCPMessageHandler, context ); 2754 2755 if ( err ) 2756 { 2757 LogErr( "RecvTCPMessage", "pthread_create" ); 2758 err = mStatus_NoError; 2759 goto exit; 2760 } 2761 2762 // Let the thread free the context 2763 2764 freeContext = mDNSfalse; 2765 2766 pthread_detach(tid); 2767 } 2768 } 2769 else 2770 { 2771 PktMsg reply; 2772 2773 LogMsg( "Client %s Not authorized for zone %##s", inet_ntoa( context->pkt.src.sin_addr ), pkt->zone->name.c ); 2774 2775 memcpy( &reply, &context->pkt, sizeof( PktMsg ) ); 2776 2777 reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD; 2778 reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_Refused; 2779 2780 SendPacket( context->sock, &reply ); 2781 } 2782 } 2783 else 2784 { 2785 freeContext = mDNSfalse; 2786 } 2787 2788 exit: 2789 2790 if ( err ) 2791 { 2792 RemoveSourceFromEventLoop( context->d, context->sock ); 2793 } 2794 2795 if ( freeContext ) 2796 { 2797 FreeTCPContext( context ); 2798 } 2799 } 2800 2801 2802 mDNSlocal int 2803 AcceptTCPConnection 2804 ( 2805 DaemonInfo * self, 2806 int sd, 2807 TCPSocketFlags flags 2808 ) 2809 { 2810 TCPContext * context = NULL; 2811 unsigned int clilen = sizeof( context->cliaddr); 2812 int newSock; 2813 mStatus err = mStatus_NoError; 2814 2815 context = ( TCPContext* ) malloc( sizeof( TCPContext ) ); 2816 require_action( context, exit, err = mStatus_NoMemoryErr; LogErr( "AcceptTCPConnection", "malloc" ) ); 2817 mDNSPlatformMemZero( context, sizeof( sizeof( TCPContext ) ) ); 2818 context->d = self; 2819 newSock = accept( sd, ( struct sockaddr* ) &context->cliaddr, &clilen ); 2820 require_action( newSock != -1, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "accept" ) ); 2821 2822 context->sock = mDNSPlatformTCPAccept( flags, newSock ); 2823 require_action( context->sock, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "mDNSPlatformTCPAccept" ) ); 2824 2825 err = AddSourceToEventLoop( self, context->sock, RecvTCPMessage, context ); 2826 require_action( !err, exit, LogErr( "AcceptTCPConnection", "AddSourceToEventLoop" ) ); 2827 2828 exit: 2829 2830 if ( err && context ) 2831 { 2832 free( context ); 2833 context = NULL; 2834 } 2835 2836 return err; 2837 } 2838 2839 2840 // main event loop 2841 // listen for incoming requests, periodically check table for expired records, respond to signals 2842 mDNSlocal int Run(DaemonInfo *d) 2843 { 2844 int staticMaxFD, nfds; 2845 fd_set rset; 2846 struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 }; 2847 mDNSBool EventsPending = mDNSfalse; 2848 2849 VLog("Listening for requests..."); 2850 2851 staticMaxFD = 0; 2852 2853 if ( d->tcpsd + 1 > staticMaxFD ) staticMaxFD = d->tcpsd + 1; 2854 if ( d->udpsd + 1 > staticMaxFD ) staticMaxFD = d->udpsd + 1; 2855 if ( d->tlssd + 1 > staticMaxFD ) staticMaxFD = d->tlssd + 1; 2856 if ( d->llq_tcpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_tcpsd + 1; 2857 if ( d->llq_udpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_udpsd + 1; 2858 if ( d->LLQEventListenSock + 1 > staticMaxFD ) staticMaxFD = d->LLQEventListenSock + 1; 2859 2860 while(1) 2861 { 2862 EventSource * source; 2863 int maxFD; 2864 2865 // set timeout 2866 timeout.tv_sec = timeout.tv_usec = 0; 2867 if (gettimeofday(&timenow, NULL)) { LogErr("Run", "gettimeofday"); return -1; } 2868 2869 if (EventsPending) 2870 { 2871 if (timenow.tv_sec - EventTS.tv_sec >= 5) // if we've been waiting 5 seconds for a "quiet" period to send 2872 { GenLLQEvents(d); EventsPending = mDNSfalse; } // events, we go ahead and do it now 2873 else timeout.tv_usec = 500000; // else do events after 1/2 second with no new events or LLQs 2874 } 2875 if (!EventsPending) 2876 { 2877 // if no pending events, timeout when we need to check for expired records 2878 if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0) 2879 { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } // table check overdue 2880 if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL; 2881 timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec; 2882 } 2883 2884 FD_ZERO(&rset); 2885 FD_SET( d->tcpsd, &rset ); 2886 FD_SET( d->udpsd, &rset ); 2887 FD_SET( d->tlssd, &rset ); 2888 FD_SET( d->llq_tcpsd, &rset ); 2889 FD_SET( d->llq_udpsd, &rset ); 2890 FD_SET( d->LLQEventListenSock, &rset ); 2891 2892 maxFD = staticMaxFD; 2893 2894 for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next ) 2895 { 2896 FD_SET( source->fd, &rset ); 2897 2898 if ( source->fd > maxFD ) 2899 { 2900 maxFD = source->fd; 2901 } 2902 } 2903 2904 nfds = select( maxFD + 1, &rset, NULL, NULL, &timeout); 2905 if (nfds < 0) 2906 { 2907 if (errno == EINTR) 2908 { 2909 if (terminate) 2910 { 2911 // close sockets to prevent clients from making new requests during shutdown 2912 close( d->tcpsd ); 2913 close( d->udpsd ); 2914 close( d->tlssd ); 2915 close( d->llq_tcpsd ); 2916 close( d->llq_udpsd ); 2917 d->tcpsd = d->udpsd = d->tlssd = d->llq_tcpsd = d->llq_udpsd = -1; 2918 DeleteRecords(d, mDNStrue); 2919 return 0; 2920 } 2921 else if (dumptable) 2922 { 2923 Log( "Received SIGINFO" ); 2924 2925 PrintLeaseTable(d); 2926 PrintLLQTable(d); 2927 PrintLLQAnswers(d); 2928 dumptable = 0; 2929 } 2930 else if (hangup) 2931 { 2932 int err; 2933 2934 Log( "Received SIGHUP" ); 2935 2936 err = ParseConfig( d, cfgfile ); 2937 2938 if ( err ) 2939 { 2940 LogErr( "Run", "ParseConfig" ); 2941 return -1; 2942 } 2943 2944 hangup = 0; 2945 } 2946 else 2947 { 2948 Log("Received unhandled signal - continuing"); 2949 } 2950 } 2951 else 2952 { 2953 LogErr("Run", "select"); return -1; 2954 } 2955 } 2956 else if (nfds) 2957 { 2958 if (FD_ISSET(d->udpsd, &rset)) RecvUDPMessage( d, d->udpsd ); 2959 if (FD_ISSET(d->llq_udpsd, &rset)) RecvUDPMessage( d, d->llq_udpsd ); 2960 if (FD_ISSET(d->tcpsd, &rset)) AcceptTCPConnection( d, d->tcpsd, 0 ); 2961 if (FD_ISSET(d->llq_tcpsd, &rset)) AcceptTCPConnection( d, d->llq_tcpsd, 0 ); 2962 if (FD_ISSET(d->tlssd, &rset)) AcceptTCPConnection( d, d->tlssd, TCP_SOCKET_FLAGS ); 2963 if (FD_ISSET(d->LLQEventListenSock, &rset)) 2964 { 2965 // clear signalling data off socket 2966 char buf[256]; 2967 recv(d->LLQEventListenSock, buf, 256, 0); 2968 if (!EventsPending) 2969 { 2970 EventsPending = mDNStrue; 2971 if (gettimeofday(&EventTS, NULL)) { LogErr("Run", "gettimeofday"); return -1; } 2972 } 2973 } 2974 2975 for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next ) 2976 { 2977 if ( FD_ISSET( source->fd, &rset ) ) 2978 { 2979 source->callback( source->context ); 2980 break; // in case we removed this guy from the event loop 2981 } 2982 } 2983 } 2984 else 2985 { 2986 // timeout 2987 if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; } 2988 else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } 2989 } 2990 } 2991 return 0; 2992 } 2993 2994 // signal handler sets global variables, which are inspected by main event loop 2995 // (select automatically returns due to the handled signal) 2996 mDNSlocal void HndlSignal(int sig) 2997 { 2998 if (sig == SIGTERM || sig == SIGINT ) { terminate = 1; return; } 2999 if (sig == INFO_SIGNAL) { dumptable = 1; return; } 3000 if (sig == SIGHUP) { hangup = 1; return; } 3001 } 3002 3003 mDNSlocal mStatus 3004 SetPublicSRV 3005 ( 3006 DaemonInfo * d, 3007 const char * name 3008 ) 3009 { 3010 DNameListElem * elem; 3011 mStatus err = mStatus_NoError; 3012 3013 elem = ( DNameListElem* ) malloc( sizeof( DNameListElem ) ); 3014 require_action( elem, exit, err = mStatus_NoMemoryErr ); 3015 MakeDomainNameFromDNSNameString( &elem->name, name ); 3016 elem->next = d->public_names; 3017 d->public_names = elem; 3018 3019 exit: 3020 3021 return err; 3022 } 3023 3024 3025 int main(int argc, char *argv[]) 3026 { 3027 int started_via_launchd = 0; 3028 DaemonInfo *d; 3029 struct rlimit rlim; 3030 3031 Log("dnsextd starting"); 3032 3033 d = malloc(sizeof(*d)); 3034 if (!d) { LogErr("main", "malloc"); exit(1); } 3035 mDNSPlatformMemZero(d, sizeof(DaemonInfo)); 3036 3037 // Setup the public SRV record names 3038 3039 SetPublicSRV(d, "_dns-update._udp."); 3040 SetPublicSRV(d, "_dns-llq._udp."); 3041 SetPublicSRV(d, "_dns-update-tls._tcp."); 3042 SetPublicSRV(d, "_dns-query-tls._tcp."); 3043 SetPublicSRV(d, "_dns-llq-tls._tcp."); 3044 3045 // Setup signal handling 3046 3047 if (signal(SIGHUP, HndlSignal) == SIG_ERR) perror("Can't catch SIGHUP"); 3048 if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM"); 3049 if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO"); 3050 if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT"); 3051 if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE"); 3052 3053 // remove open file limit 3054 rlim.rlim_max = RLIM_INFINITY; 3055 rlim.rlim_cur = RLIM_INFINITY; 3056 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) 3057 { 3058 LogErr("main", "setrlimit"); 3059 Log("Using default file descriptor resource limit"); 3060 } 3061 3062 if (argc > 1 && !strcasecmp(argv[1], "-launchd")) 3063 { 3064 Log("started_via_launchd"); 3065 started_via_launchd = 1; 3066 argv++; 3067 argc--; 3068 } 3069 if (ProcessArgs(argc, argv, d) < 0) { LogErr("main", "ProcessArgs"); exit(1); } 3070 3071 if (!foreground && !started_via_launchd) 3072 { 3073 if (daemon(0,0)) 3074 { 3075 LogErr("main", "daemon"); 3076 foreground = 1; 3077 } 3078 } 3079 3080 if (InitLeaseTable(d) < 0) { LogErr("main", "InitLeaseTable"); exit(1); } 3081 if (SetupSockets(d) < 0) { LogErr("main", "SetupSockets"); exit(1); } 3082 if (SetUpdateSRV(d) < 0) { LogErr("main", "SetUpdateSRV"); exit(1); } 3083 3084 Run(d); 3085 3086 Log("dnsextd stopping"); 3087 3088 if (ClearUpdateSRV(d) < 0) { LogErr("main", "ClearUpdateSRV"); exit(1); } // clear update srv's even if Run or pthread_create returns an error 3089 free(d); 3090 exit(0); 3091 } 3092 3093 3094 // These are stubbed out implementations of up-call routines that the various platform support layers 3095 // call. These routines are fully implemented in both mDNS.c and uDNS.c, but dnsextd doesn't 3096 // link this code in. 3097 // 3098 // It's an error for these routines to actually be called, so perhaps we should log any call 3099 // to them. 3100 void mDNSCoreInitComplete( mDNS * const m, mStatus result) { ( void ) m; ( void ) result; } 3101 void mDNS_ConfigChanged(mDNS *const m) { ( void ) m; } 3102 void mDNSCoreMachineSleep(mDNS * const m, mDNSBool wake) { ( void ) m; ( void ) wake; } 3103 void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end, 3104 const mDNSAddr *const srcaddr, const mDNSIPPort srcport, 3105 const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID iid) 3106 { ( void ) m; ( void ) msg; ( void ) end; ( void ) srcaddr; ( void ) srcport; ( void ) dstaddr; ( void ) dstport; ( void ) iid; } 3107 DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout) 3108 { ( void ) m; ( void ) d; ( void ) interface; ( void ) addr; ( void ) port; ( void ) scoped; ( void ) timeout; return(NULL); } 3109 void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID) { (void)domain; (void) InterfaceID;} 3110 void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext) 3111 { ( void ) m; ( void ) fqdn; ( void ) StatusCallback; ( void ) StatusContext; } 3112 mDNSs32 mDNS_Execute (mDNS *const m) { ( void ) m; return 0; } 3113 mDNSs32 mDNS_TimeNow(const mDNS *const m) { ( void ) m; return 0; } 3114 mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; } 3115 void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 3116 { ( void ) m; ( void ) set; ( void ) flapping; } 3117 const char * const mDNS_DomainTypeNames[1] = {}; 3118 mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom, 3119 const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context) 3120 { ( void ) m; ( void ) question; ( void ) DomainType; ( void ) dom; ( void ) InterfaceID; ( void ) Callback; ( void ) Context; return 0; } 3121 mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; } 3122 mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 3123 { ( void ) m; ( void ) set; ( void ) flapping; return 0; } 3124 void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) { ( void ) m; ( void ) fqdn; } 3125 void mDNS_SetFQDN(mDNS * const m) { ( void ) m; } 3126 void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router) 3127 { ( void ) m; ( void ) v4addr; ( void ) v6addr; ( void ) router; } 3128 mStatus uDNS_SetupDNSConfig( mDNS *const m ) { ( void ) m; return 0; } 3129 mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, 3130 const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix) 3131 { ( void ) m; ( void ) info; ( void ) domain; ( void ) keyname; ( void ) b64keydata; ( void ) hostname; (void) port; ( void ) autoTunnelPrefix; return 0; } 3132 mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; ( void ) question; return 0; } 3133 void TriggerEventCompletion(void); 3134 void TriggerEventCompletion() {} 3135 mDNS mDNSStorage; 3136 3137 3138 // For convenience when using the "strings" command, this is the last thing in the file 3139 // The "@(#) " pattern is a special prefix the "what" command looks for 3140 const char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; 3141 3142 #if _BUILDING_XCODE_PROJECT_ 3143 // If the process crashes, then this string will be magically included in the automatically-generated crash log 3144 const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5; 3145 asm(".desc ___crashreporter_info__, 0x10"); 3146 #endif 3147