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