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