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