1*472cd20dSToomas Soome /*
2*472cd20dSToomas Soome * Copyright (c) 2018-2020 Apple Inc. All rights reserved.
3*472cd20dSToomas Soome *
4*472cd20dSToomas Soome * Licensed under the Apache License, Version 2.0 (the "License");
5*472cd20dSToomas Soome * you may not use this file except in compliance with the License.
6*472cd20dSToomas Soome * You may obtain a copy of the License at
7*472cd20dSToomas Soome *
8*472cd20dSToomas Soome * http://www.apache.org/licenses/LICENSE-2.0
9*472cd20dSToomas Soome *
10*472cd20dSToomas Soome * Unless required by applicable law or agreed to in writing, software
11*472cd20dSToomas Soome * distributed under the License is distributed on an "AS IS" BASIS,
12*472cd20dSToomas Soome * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*472cd20dSToomas Soome * See the License for the specific language governing permissions and
14*472cd20dSToomas Soome * limitations under the License.
15*472cd20dSToomas Soome */
16*472cd20dSToomas Soome
17*472cd20dSToomas Soome #include "ClientRequests.h"
18*472cd20dSToomas Soome
19*472cd20dSToomas Soome #include "DNSCommon.h"
20*472cd20dSToomas Soome #include "uDNS.h"
21*472cd20dSToomas Soome
22*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
23*472cd20dSToomas Soome #include "QuerierSupport.h"
24*472cd20dSToomas Soome #endif
25*472cd20dSToomas Soome
26*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
27*472cd20dSToomas Soome #include "D2D.h"
28*472cd20dSToomas Soome #endif
29*472cd20dSToomas Soome
30*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
31*472cd20dSToomas Soome #include "mDNSMacOSX.h"
32*472cd20dSToomas Soome #endif
33*472cd20dSToomas Soome
34*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
35*472cd20dSToomas Soome #include <dispatch/dispatch.h>
36*472cd20dSToomas Soome #include <net/if.h>
37*472cd20dSToomas Soome #endif
38*472cd20dSToomas Soome
39*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
40*472cd20dSToomas Soome #include <WebFilterDNS/WebFilterDNS.h>
41*472cd20dSToomas Soome
42*472cd20dSToomas Soome int WCFIsServerRunning(WCFConnection *conn) __attribute__((weak_import));
43*472cd20dSToomas Soome int WCFNameResolvesToAddr(WCFConnection *conn, char* domainName, struct sockaddr* address, uid_t userid) __attribute__((weak_import));
44*472cd20dSToomas Soome int WCFNameResolvesToName(WCFConnection *conn, char* fromName, char* toName, uid_t userid) __attribute__((weak_import));
45*472cd20dSToomas Soome #endif
46*472cd20dSToomas Soome
47*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
48*472cd20dSToomas Soome #include "dnssec_v2.h"
49*472cd20dSToomas Soome #endif
50*472cd20dSToomas Soome
51*472cd20dSToomas Soome #define RecordTypeIsAddress(TYPE) (((TYPE) == kDNSType_A) || ((TYPE) == kDNSType_AAAA))
52*472cd20dSToomas Soome
53*472cd20dSToomas Soome extern mDNS mDNSStorage;
54*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
55*472cd20dSToomas Soome extern domainname ActiveDirectoryPrimaryDomain;
56*472cd20dSToomas Soome #endif
57*472cd20dSToomas Soome
58*472cd20dSToomas Soome // Normally we append search domains only for queries with a single label that are not fully qualified. This can be
59*472cd20dSToomas Soome // overridden to apply search domains for queries (that are not fully qualified) with any number of labels e.g., moon,
60*472cd20dSToomas Soome // moon.cs, moon.cs.be, etc. - Mohan
61*472cd20dSToomas Soome mDNSBool AlwaysAppendSearchDomains = mDNSfalse;
62*472cd20dSToomas Soome
63*472cd20dSToomas Soome // Control enabling optimistic DNS - Phil
64*472cd20dSToomas Soome mDNSBool EnableAllowExpired = mDNStrue;
65*472cd20dSToomas Soome
66*472cd20dSToomas Soome
67*472cd20dSToomas Soome typedef struct
68*472cd20dSToomas Soome {
69*472cd20dSToomas Soome mDNSu32 requestID;
70*472cd20dSToomas Soome const domainname * qname;
71*472cd20dSToomas Soome mDNSu16 qtype;
72*472cd20dSToomas Soome mDNSu16 qclass;
73*472cd20dSToomas Soome mDNSInterfaceID interfaceID;
74*472cd20dSToomas Soome mDNSs32 serviceID;
75*472cd20dSToomas Soome mDNSu32 flags;
76*472cd20dSToomas Soome mDNSBool appendSearchDomains;
77*472cd20dSToomas Soome mDNSs32 effectivePID;
78*472cd20dSToomas Soome const mDNSu8 * effectiveUUID;
79*472cd20dSToomas Soome mDNSu32 peerUID;
80*472cd20dSToomas Soome mDNSBool isInAppBrowserRequest;
81*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
82*472cd20dSToomas Soome const mDNSu8 * resolverUUID;
83*472cd20dSToomas Soome mdns_dns_service_id_t customID;
84*472cd20dSToomas Soome mDNSBool needEncryption;
85*472cd20dSToomas Soome #endif
86*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
87*472cd20dSToomas Soome const audit_token_t * peerAuditToken;
88*472cd20dSToomas Soome const audit_token_t * delegatorAuditToken;
89*472cd20dSToomas Soome #endif
90*472cd20dSToomas Soome
91*472cd20dSToomas Soome } QueryRecordOpParams;
92*472cd20dSToomas Soome
QueryRecordOpParamsInit(QueryRecordOpParams * inParams)93*472cd20dSToomas Soome mDNSlocal void QueryRecordOpParamsInit(QueryRecordOpParams *inParams)
94*472cd20dSToomas Soome {
95*472cd20dSToomas Soome mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
96*472cd20dSToomas Soome inParams->serviceID = -1;
97*472cd20dSToomas Soome }
98*472cd20dSToomas Soome
99*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpCreate(QueryRecordOp **outOp);
100*472cd20dSToomas Soome mDNSlocal void QueryRecordOpFree(QueryRecordOp *operation);
101*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStart(QueryRecordOp *inOp, const QueryRecordOpParams *inParams,
102*472cd20dSToomas Soome QueryRecordResultHandler inResultHandler, void *inResultContext);
103*472cd20dSToomas Soome mDNSlocal void QueryRecordOpStop(QueryRecordOp *op);
104*472cd20dSToomas Soome mDNSlocal mDNSBool QueryRecordOpIsMulticast(const QueryRecordOp *op);
105*472cd20dSToomas Soome mDNSlocal void QueryRecordOpCallback(mDNS *m, DNSQuestion *inQuestion, const ResourceRecord *inAnswer,
106*472cd20dSToomas Soome QC_result inAddRecord);
107*472cd20dSToomas Soome mDNSlocal void QueryRecordOpResetHandler(DNSQuestion *inQuestion);
108*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStartQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion);
109*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStopQuestion(DNSQuestion *inQuestion);
110*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpRestartUnicastQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion,
111*472cd20dSToomas Soome const domainname *inSearchDomain);
112*472cd20dSToomas Soome mDNSlocal mStatus InterfaceIndexToInterfaceID(mDNSu32 inInterfaceIndex, mDNSInterfaceID *outInterfaceID);
113*472cd20dSToomas Soome mDNSlocal mDNSBool DomainNameIsSingleLabel(const domainname *inName);
114*472cd20dSToomas Soome mDNSlocal mDNSBool StringEndsWithDot(const char *inString);
115*472cd20dSToomas Soome mDNSlocal const domainname * NextSearchDomain(QueryRecordOp *inOp);
116*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
117*472cd20dSToomas Soome mDNSlocal mDNSBool DomainNameIsInSearchList(const domainname *domain, mDNSBool inExcludeLocal);
118*472cd20dSToomas Soome #endif
119*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
120*472cd20dSToomas Soome mDNSlocal void NotifyWebContentFilter(const ResourceRecord *inAnswer, uid_t inUID);
121*472cd20dSToomas Soome #endif
122*472cd20dSToomas Soome
GetAddrInfoClientRequestParamsInit(GetAddrInfoClientRequestParams * inParams)123*472cd20dSToomas Soome mDNSexport void GetAddrInfoClientRequestParamsInit(GetAddrInfoClientRequestParams *inParams)
124*472cd20dSToomas Soome {
125*472cd20dSToomas Soome mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
126*472cd20dSToomas Soome }
127*472cd20dSToomas Soome
GetAddrInfoClientRequestStart(GetAddrInfoClientRequest * inRequest,const GetAddrInfoClientRequestParams * inParams,QueryRecordResultHandler inResultHandler,void * inResultContext)128*472cd20dSToomas Soome mDNSexport mStatus GetAddrInfoClientRequestStart(GetAddrInfoClientRequest *inRequest,
129*472cd20dSToomas Soome const GetAddrInfoClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext)
130*472cd20dSToomas Soome {
131*472cd20dSToomas Soome mStatus err;
132*472cd20dSToomas Soome domainname hostname;
133*472cd20dSToomas Soome mDNSBool appendSearchDomains;
134*472cd20dSToomas Soome mDNSInterfaceID interfaceID;
135*472cd20dSToomas Soome DNSServiceFlags flags;
136*472cd20dSToomas Soome mDNSs32 serviceID;
137*472cd20dSToomas Soome QueryRecordOpParams opParams;
138*472cd20dSToomas Soome
139*472cd20dSToomas Soome if (!MakeDomainNameFromDNSNameString(&hostname, inParams->hostnameStr))
140*472cd20dSToomas Soome {
141*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
142*472cd20dSToomas Soome "[R%u] ERROR: bad hostname '" PRI_S "'", inParams->requestID, inParams->hostnameStr);
143*472cd20dSToomas Soome err = mStatus_BadParamErr;
144*472cd20dSToomas Soome goto exit;
145*472cd20dSToomas Soome }
146*472cd20dSToomas Soome
147*472cd20dSToomas Soome if (inParams->protocols & ~(kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6))
148*472cd20dSToomas Soome {
149*472cd20dSToomas Soome err = mStatus_BadParamErr;
150*472cd20dSToomas Soome goto exit;
151*472cd20dSToomas Soome }
152*472cd20dSToomas Soome
153*472cd20dSToomas Soome flags = inParams->flags;
154*472cd20dSToomas Soome if (inParams->protocols == 0)
155*472cd20dSToomas Soome {
156*472cd20dSToomas Soome flags |= kDNSServiceFlagsSuppressUnusable;
157*472cd20dSToomas Soome inRequest->protocols = kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6;
158*472cd20dSToomas Soome }
159*472cd20dSToomas Soome else
160*472cd20dSToomas Soome {
161*472cd20dSToomas Soome inRequest->protocols = inParams->protocols;
162*472cd20dSToomas Soome }
163*472cd20dSToomas Soome
164*472cd20dSToomas Soome if (flags & kDNSServiceFlagsServiceIndex)
165*472cd20dSToomas Soome {
166*472cd20dSToomas Soome // NOTE: kDNSServiceFlagsServiceIndex flag can only be set for DNSServiceGetAddrInfo()
167*472cd20dSToomas Soome LogInfo("GetAddrInfoClientRequestStart: kDNSServiceFlagsServiceIndex is SET by the client");
168*472cd20dSToomas Soome
169*472cd20dSToomas Soome // If kDNSServiceFlagsServiceIndex is SET, interpret the interfaceID as the serviceId and set the interfaceID to 0.
170*472cd20dSToomas Soome serviceID = (mDNSs32)inParams->interfaceIndex;
171*472cd20dSToomas Soome interfaceID = mDNSNULL;
172*472cd20dSToomas Soome }
173*472cd20dSToomas Soome else
174*472cd20dSToomas Soome {
175*472cd20dSToomas Soome serviceID = -1;
176*472cd20dSToomas Soome err = InterfaceIndexToInterfaceID(inParams->interfaceIndex, &interfaceID);
177*472cd20dSToomas Soome if (err) goto exit;
178*472cd20dSToomas Soome }
179*472cd20dSToomas Soome inRequest->interfaceID = interfaceID;
180*472cd20dSToomas Soome
181*472cd20dSToomas Soome if (!StringEndsWithDot(inParams->hostnameStr) && (AlwaysAppendSearchDomains || DomainNameIsSingleLabel(&hostname)))
182*472cd20dSToomas Soome {
183*472cd20dSToomas Soome appendSearchDomains = mDNStrue;
184*472cd20dSToomas Soome }
185*472cd20dSToomas Soome else
186*472cd20dSToomas Soome {
187*472cd20dSToomas Soome appendSearchDomains = mDNSfalse;
188*472cd20dSToomas Soome }
189*472cd20dSToomas Soome QueryRecordOpParamsInit(&opParams);
190*472cd20dSToomas Soome opParams.requestID = inParams->requestID;
191*472cd20dSToomas Soome opParams.qname = &hostname;
192*472cd20dSToomas Soome opParams.qclass = kDNSClass_IN;
193*472cd20dSToomas Soome opParams.interfaceID = inRequest->interfaceID;
194*472cd20dSToomas Soome opParams.serviceID = serviceID;
195*472cd20dSToomas Soome opParams.flags = flags;
196*472cd20dSToomas Soome opParams.appendSearchDomains = appendSearchDomains;
197*472cd20dSToomas Soome opParams.effectivePID = inParams->effectivePID;
198*472cd20dSToomas Soome opParams.effectiveUUID = inParams->effectiveUUID;
199*472cd20dSToomas Soome opParams.peerUID = inParams->peerUID;
200*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
201*472cd20dSToomas Soome opParams.resolverUUID = inParams->resolverUUID;
202*472cd20dSToomas Soome opParams.customID = inParams->customID;
203*472cd20dSToomas Soome opParams.needEncryption = inParams->needEncryption;
204*472cd20dSToomas Soome #endif
205*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
206*472cd20dSToomas Soome opParams.peerAuditToken = inParams->peerAuditToken;
207*472cd20dSToomas Soome opParams.delegatorAuditToken = inParams->delegatorAuditToken;
208*472cd20dSToomas Soome opParams.isInAppBrowserRequest = inParams->isInAppBrowserRequest;
209*472cd20dSToomas Soome #endif
210*472cd20dSToomas Soome if (inRequest->protocols & kDNSServiceProtocol_IPv6)
211*472cd20dSToomas Soome {
212*472cd20dSToomas Soome err = QueryRecordOpCreate(&inRequest->op6);
213*472cd20dSToomas Soome if (err) goto exit;
214*472cd20dSToomas Soome
215*472cd20dSToomas Soome opParams.qtype = kDNSType_AAAA;
216*472cd20dSToomas Soome err = QueryRecordOpStart(inRequest->op6, &opParams, inResultHandler, inResultContext);
217*472cd20dSToomas Soome if (err) goto exit;
218*472cd20dSToomas Soome }
219*472cd20dSToomas Soome if (inRequest->protocols & kDNSServiceProtocol_IPv4)
220*472cd20dSToomas Soome {
221*472cd20dSToomas Soome err = QueryRecordOpCreate(&inRequest->op4);
222*472cd20dSToomas Soome if (err) goto exit;
223*472cd20dSToomas Soome
224*472cd20dSToomas Soome opParams.qtype = kDNSType_A;
225*472cd20dSToomas Soome err = QueryRecordOpStart(inRequest->op4, &opParams, inResultHandler, inResultContext);
226*472cd20dSToomas Soome if (err) goto exit;
227*472cd20dSToomas Soome }
228*472cd20dSToomas Soome err = mStatus_NoError;
229*472cd20dSToomas Soome
230*472cd20dSToomas Soome exit:
231*472cd20dSToomas Soome if (err) GetAddrInfoClientRequestStop(inRequest);
232*472cd20dSToomas Soome return err;
233*472cd20dSToomas Soome }
234*472cd20dSToomas Soome
GetAddrInfoClientRequestStop(GetAddrInfoClientRequest * inRequest)235*472cd20dSToomas Soome mDNSexport void GetAddrInfoClientRequestStop(GetAddrInfoClientRequest *inRequest)
236*472cd20dSToomas Soome {
237*472cd20dSToomas Soome if (inRequest->op4) QueryRecordOpStop(inRequest->op4);
238*472cd20dSToomas Soome if (inRequest->op6) QueryRecordOpStop(inRequest->op6);
239*472cd20dSToomas Soome
240*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
241*472cd20dSToomas Soome {
242*472cd20dSToomas Soome const QueryRecordOp * const op4 = inRequest->op4;
243*472cd20dSToomas Soome const QueryRecordOp * const op6 = inRequest->op6;
244*472cd20dSToomas Soome const DNSQuestion * q4 = mDNSNULL;
245*472cd20dSToomas Soome const DNSQuestion * q6 = mDNSNULL;
246*472cd20dSToomas Soome
247*472cd20dSToomas Soome if (op4)
248*472cd20dSToomas Soome {
249*472cd20dSToomas Soome if (op4->answered)
250*472cd20dSToomas Soome {
251*472cd20dSToomas Soome // If we have a v4 answer and if we timed out prematurely before, provide a trigger to the upper layer so
252*472cd20dSToomas Soome // that it can retry questions if needed. - Mohan
253*472cd20dSToomas Soome q4 = &op4->q;
254*472cd20dSToomas Soome }
255*472cd20dSToomas Soome else if (op4->q.TimeoutQuestion)
256*472cd20dSToomas Soome {
257*472cd20dSToomas Soome // If we are not delivering answers, we may be timing out prematurely. Note down the current state so that
258*472cd20dSToomas Soome // we know to retry when we see a valid response again. - Mohan
259*472cd20dSToomas Soome mDNSPlatformUpdateDNSStatus(&op4->q);
260*472cd20dSToomas Soome }
261*472cd20dSToomas Soome }
262*472cd20dSToomas Soome if (op6)
263*472cd20dSToomas Soome {
264*472cd20dSToomas Soome if (op6->answered)
265*472cd20dSToomas Soome {
266*472cd20dSToomas Soome q6 = &op6->q;
267*472cd20dSToomas Soome }
268*472cd20dSToomas Soome else if (op6->q.TimeoutQuestion)
269*472cd20dSToomas Soome {
270*472cd20dSToomas Soome mDNSPlatformUpdateDNSStatus(&op6->q);
271*472cd20dSToomas Soome }
272*472cd20dSToomas Soome }
273*472cd20dSToomas Soome mDNSPlatformTriggerDNSRetry(q4, q6);
274*472cd20dSToomas Soome }
275*472cd20dSToomas Soome #endif
276*472cd20dSToomas Soome
277*472cd20dSToomas Soome if (inRequest->op4)
278*472cd20dSToomas Soome {
279*472cd20dSToomas Soome QueryRecordOpFree(inRequest->op4);
280*472cd20dSToomas Soome inRequest->op4 = mDNSNULL;
281*472cd20dSToomas Soome }
282*472cd20dSToomas Soome if (inRequest->op6)
283*472cd20dSToomas Soome {
284*472cd20dSToomas Soome QueryRecordOpFree(inRequest->op6);
285*472cd20dSToomas Soome inRequest->op6 = mDNSNULL;
286*472cd20dSToomas Soome }
287*472cd20dSToomas Soome }
288*472cd20dSToomas Soome
GetAddrInfoClientRequestGetQName(const GetAddrInfoClientRequest * inRequest)289*472cd20dSToomas Soome mDNSexport const domainname * GetAddrInfoClientRequestGetQName(const GetAddrInfoClientRequest *inRequest)
290*472cd20dSToomas Soome {
291*472cd20dSToomas Soome if (inRequest->op4) return &inRequest->op4->q.qname;
292*472cd20dSToomas Soome if (inRequest->op6) return &inRequest->op6->q.qname;
293*472cd20dSToomas Soome return (const domainname *)"";
294*472cd20dSToomas Soome }
295*472cd20dSToomas Soome
GetAddrInfoClientRequestIsMulticast(const GetAddrInfoClientRequest * inRequest)296*472cd20dSToomas Soome mDNSexport mDNSBool GetAddrInfoClientRequestIsMulticast(const GetAddrInfoClientRequest *inRequest)
297*472cd20dSToomas Soome {
298*472cd20dSToomas Soome if ((inRequest->op4 && QueryRecordOpIsMulticast(inRequest->op4)) ||
299*472cd20dSToomas Soome (inRequest->op6 && QueryRecordOpIsMulticast(inRequest->op6)))
300*472cd20dSToomas Soome {
301*472cd20dSToomas Soome return mDNStrue;
302*472cd20dSToomas Soome }
303*472cd20dSToomas Soome return mDNSfalse;
304*472cd20dSToomas Soome }
305*472cd20dSToomas Soome
QueryRecordClientRequestParamsInit(QueryRecordClientRequestParams * inParams)306*472cd20dSToomas Soome mDNSexport void QueryRecordClientRequestParamsInit(QueryRecordClientRequestParams *inParams)
307*472cd20dSToomas Soome {
308*472cd20dSToomas Soome mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
309*472cd20dSToomas Soome }
310*472cd20dSToomas Soome
QueryRecordClientRequestStart(QueryRecordClientRequest * inRequest,const QueryRecordClientRequestParams * inParams,QueryRecordResultHandler inResultHandler,void * inResultContext)311*472cd20dSToomas Soome mDNSexport mStatus QueryRecordClientRequestStart(QueryRecordClientRequest *inRequest,
312*472cd20dSToomas Soome const QueryRecordClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext)
313*472cd20dSToomas Soome {
314*472cd20dSToomas Soome mStatus err;
315*472cd20dSToomas Soome domainname qname;
316*472cd20dSToomas Soome mDNSInterfaceID interfaceID;
317*472cd20dSToomas Soome mDNSBool appendSearchDomains;
318*472cd20dSToomas Soome QueryRecordOpParams opParams;
319*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
320*472cd20dSToomas Soome dnssec_context_t * dnssecContext = mDNSNULL;
321*472cd20dSToomas Soome #endif
322*472cd20dSToomas Soome
323*472cd20dSToomas Soome err = InterfaceIndexToInterfaceID(inParams->interfaceIndex, &interfaceID);
324*472cd20dSToomas Soome if (err) goto exit;
325*472cd20dSToomas Soome
326*472cd20dSToomas Soome if (!MakeDomainNameFromDNSNameString(&qname, inParams->qnameStr))
327*472cd20dSToomas Soome {
328*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
329*472cd20dSToomas Soome "[R%u] ERROR: bad domain name '" PRI_S "'", inParams->requestID, inParams->qnameStr);
330*472cd20dSToomas Soome err = mStatus_BadParamErr;
331*472cd20dSToomas Soome goto exit;
332*472cd20dSToomas Soome }
333*472cd20dSToomas Soome
334*472cd20dSToomas Soome if (RecordTypeIsAddress(inParams->qtype) && !StringEndsWithDot(inParams->qnameStr) &&
335*472cd20dSToomas Soome (AlwaysAppendSearchDomains || DomainNameIsSingleLabel(&qname)))
336*472cd20dSToomas Soome {
337*472cd20dSToomas Soome appendSearchDomains = mDNStrue;
338*472cd20dSToomas Soome }
339*472cd20dSToomas Soome else
340*472cd20dSToomas Soome {
341*472cd20dSToomas Soome appendSearchDomains = mDNSfalse;
342*472cd20dSToomas Soome }
343*472cd20dSToomas Soome QueryRecordOpParamsInit(&opParams);
344*472cd20dSToomas Soome opParams.requestID = inParams->requestID;
345*472cd20dSToomas Soome opParams.qname = &qname;
346*472cd20dSToomas Soome opParams.qtype = inParams->qtype;
347*472cd20dSToomas Soome opParams.qclass = inParams->qclass;
348*472cd20dSToomas Soome opParams.interfaceID = interfaceID;
349*472cd20dSToomas Soome opParams.appendSearchDomains = appendSearchDomains;
350*472cd20dSToomas Soome opParams.effectivePID = inParams->effectivePID;
351*472cd20dSToomas Soome opParams.effectiveUUID = inParams->effectiveUUID;
352*472cd20dSToomas Soome opParams.peerUID = inParams->peerUID;
353*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
354*472cd20dSToomas Soome opParams.resolverUUID = inParams->resolverUUID;
355*472cd20dSToomas Soome opParams.customID = inParams->customID;
356*472cd20dSToomas Soome opParams.needEncryption = inParams->needEncryption;
357*472cd20dSToomas Soome #endif
358*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
359*472cd20dSToomas Soome opParams.peerAuditToken = inParams->peerAuditToken;
360*472cd20dSToomas Soome opParams.delegatorAuditToken = inParams->delegatorAuditToken;
361*472cd20dSToomas Soome opParams.isInAppBrowserRequest = inParams->isInAppBrowserRequest;
362*472cd20dSToomas Soome #endif
363*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
364*472cd20dSToomas Soome // Query ends with ".local." and query for RRSIG or ANY type cannot be validated by DNSSEC even if the user sets the
365*472cd20dSToomas Soome // kDNSServiceFlagsEnableDNSSEC flag.
366*472cd20dSToomas Soome if (FLAGS_CONTAIN_DNSOK_BIT(inParams->flags) && is_eligible_for_dnssec(&qname, inParams->qtype))
367*472cd20dSToomas Soome {
368*472cd20dSToomas Soome opParams.flags = inParams->flags | kDNSServiceFlagsReturnIntermediates; // to handle CNAME reference
369*472cd20dSToomas Soome err = create_dnssec_context_t(inRequest, inParams->requestID, &qname, inParams->qtype, inParams->qclass,
370*472cd20dSToomas Soome interfaceID, -1, inParams->flags, appendSearchDomains, inParams->effectivePID, inParams->effectiveUUID,
371*472cd20dSToomas Soome inParams->peerUID,
372*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
373*472cd20dSToomas Soome inParams->peerAuditToken, inParams->delegatorAuditToken,
374*472cd20dSToomas Soome #endif
375*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
376*472cd20dSToomas Soome mDNSNULL, inParams->needEncryption, inParams->customID,
377*472cd20dSToomas Soome #endif
378*472cd20dSToomas Soome inResultHandler, inResultContext, mDNSNULL, &dnssecContext);
379*472cd20dSToomas Soome require_action(err == mStatus_NoError, exit, log_debug("create_dnssec_context_t failed; error_description='%s'",
380*472cd20dSToomas Soome mStatusDescription(err)));
381*472cd20dSToomas Soome
382*472cd20dSToomas Soome err = QueryRecordOpStart(&inRequest->op, &opParams, query_record_result_reply_with_dnssec, dnssecContext);
383*472cd20dSToomas Soome } else
384*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
385*472cd20dSToomas Soome {
386*472cd20dSToomas Soome opParams.flags = inParams->flags;
387*472cd20dSToomas Soome err = QueryRecordOpStart(&inRequest->op, &opParams, inResultHandler, inResultContext);
388*472cd20dSToomas Soome }
389*472cd20dSToomas Soome
390*472cd20dSToomas Soome exit:
391*472cd20dSToomas Soome if (err) QueryRecordClientRequestStop(inRequest);
392*472cd20dSToomas Soome return err;
393*472cd20dSToomas Soome }
394*472cd20dSToomas Soome
QueryRecordClientRequestStop(QueryRecordClientRequest * inRequest)395*472cd20dSToomas Soome mDNSexport void QueryRecordClientRequestStop(QueryRecordClientRequest *inRequest)
396*472cd20dSToomas Soome {
397*472cd20dSToomas Soome QueryRecordOpStop(&inRequest->op);
398*472cd20dSToomas Soome
399*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
400*472cd20dSToomas Soome stop_dnssec_if_enable_dnssec(inRequest);
401*472cd20dSToomas Soome #endif
402*472cd20dSToomas Soome
403*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
404*472cd20dSToomas Soome if (inRequest->op.answered)
405*472cd20dSToomas Soome {
406*472cd20dSToomas Soome DNSQuestion *v4q, *v6q;
407*472cd20dSToomas Soome // If we are receiving positive answers, provide the hint to the upper layer. - Mohan
408*472cd20dSToomas Soome v4q = (inRequest->op.q.qtype == kDNSType_A) ? &inRequest->op.q : mDNSNULL;
409*472cd20dSToomas Soome v6q = (inRequest->op.q.qtype == kDNSType_AAAA) ? &inRequest->op.q : mDNSNULL;
410*472cd20dSToomas Soome mDNSPlatformTriggerDNSRetry(v4q, v6q);
411*472cd20dSToomas Soome }
412*472cd20dSToomas Soome #endif
413*472cd20dSToomas Soome }
414*472cd20dSToomas Soome
QueryRecordClientRequestGetQName(const QueryRecordClientRequest * inRequest)415*472cd20dSToomas Soome mDNSexport const domainname * QueryRecordClientRequestGetQName(const QueryRecordClientRequest *inRequest)
416*472cd20dSToomas Soome {
417*472cd20dSToomas Soome return &inRequest->op.q.qname;
418*472cd20dSToomas Soome }
419*472cd20dSToomas Soome
QueryRecordClientRequestGetType(const QueryRecordClientRequest * inRequest)420*472cd20dSToomas Soome mDNSexport mDNSu16 QueryRecordClientRequestGetType(const QueryRecordClientRequest *inRequest)
421*472cd20dSToomas Soome {
422*472cd20dSToomas Soome return inRequest->op.q.qtype;
423*472cd20dSToomas Soome }
424*472cd20dSToomas Soome
QueryRecordClientRequestIsMulticast(QueryRecordClientRequest * inRequest)425*472cd20dSToomas Soome mDNSexport mDNSBool QueryRecordClientRequestIsMulticast(QueryRecordClientRequest *inRequest)
426*472cd20dSToomas Soome {
427*472cd20dSToomas Soome return (QueryRecordOpIsMulticast(&inRequest->op) ? mDNStrue : mDNSfalse);
428*472cd20dSToomas Soome }
429*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
QueryRecordOpStartForClientRequest(QueryRecordOp * inOp,mDNSu32 inReqID,const domainname * inQName,mDNSu16 inQType,mDNSu16 inQClass,mDNSInterfaceID inInterfaceID,mDNSs32 inServiceID,mDNSu32 inFlags,mDNSBool inAppendSearchDomains,mDNSs32 inPID,const mDNSu8 inUUID[UUID_SIZE],mDNSu32 inUID,const audit_token_t * inPeerAuditTokenPtr,const audit_token_t * inDelegateAuditTokenPtr,const mDNSu8 inResolverUUID[UUID_SIZE],mDNSBool inNeedEncryption,const mdns_dns_service_id_t inCustomID,QueryRecordResultHandler inResultHandler,void * inResultContext)430*472cd20dSToomas Soome mDNSexport mStatus QueryRecordOpStartForClientRequest(
431*472cd20dSToomas Soome QueryRecordOp * inOp,
432*472cd20dSToomas Soome mDNSu32 inReqID,
433*472cd20dSToomas Soome const domainname * inQName,
434*472cd20dSToomas Soome mDNSu16 inQType,
435*472cd20dSToomas Soome mDNSu16 inQClass,
436*472cd20dSToomas Soome mDNSInterfaceID inInterfaceID,
437*472cd20dSToomas Soome mDNSs32 inServiceID,
438*472cd20dSToomas Soome mDNSu32 inFlags,
439*472cd20dSToomas Soome mDNSBool inAppendSearchDomains,
440*472cd20dSToomas Soome mDNSs32 inPID,
441*472cd20dSToomas Soome const mDNSu8 inUUID[UUID_SIZE],
442*472cd20dSToomas Soome mDNSu32 inUID,
443*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
444*472cd20dSToomas Soome const audit_token_t * inPeerAuditTokenPtr,
445*472cd20dSToomas Soome const audit_token_t * inDelegateAuditTokenPtr,
446*472cd20dSToomas Soome #endif
447*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
448*472cd20dSToomas Soome const mDNSu8 inResolverUUID[UUID_SIZE],
449*472cd20dSToomas Soome mDNSBool inNeedEncryption,
450*472cd20dSToomas Soome const mdns_dns_service_id_t inCustomID,
451*472cd20dSToomas Soome #endif
452*472cd20dSToomas Soome QueryRecordResultHandler inResultHandler,
453*472cd20dSToomas Soome void * inResultContext) {
454*472cd20dSToomas Soome QueryRecordOpParams opParams;
455*472cd20dSToomas Soome QueryRecordOpParamsInit(&opParams);
456*472cd20dSToomas Soome opParams.requestID = inReqID;
457*472cd20dSToomas Soome opParams.qname = inQName;
458*472cd20dSToomas Soome opParams.qtype = inQType;
459*472cd20dSToomas Soome opParams.qclass = inQClass;
460*472cd20dSToomas Soome opParams.interfaceID = inInterfaceID;
461*472cd20dSToomas Soome opParams.serviceID = inServiceID;
462*472cd20dSToomas Soome opParams.flags = inFlags;
463*472cd20dSToomas Soome opParams.appendSearchDomains = inAppendSearchDomains;
464*472cd20dSToomas Soome opParams.effectivePID = inPID;
465*472cd20dSToomas Soome opParams.effectiveUUID = inUUID;
466*472cd20dSToomas Soome opParams.peerUID = inUID;
467*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
468*472cd20dSToomas Soome opParams.resolverUUID = inResolverUUID;
469*472cd20dSToomas Soome opParams.customID = inCustomID;
470*472cd20dSToomas Soome opParams.needEncryption = inNeedEncryption;
471*472cd20dSToomas Soome #endif
472*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
473*472cd20dSToomas Soome opParams.peerAuditToken = inPeerAuditTokenPtr;
474*472cd20dSToomas Soome opParams.delegatorAuditToken = inDelegateAuditTokenPtr;
475*472cd20dSToomas Soome #endif
476*472cd20dSToomas Soome return QueryRecordOpStart(inOp, &opParams, inResultHandler, inResultContext);
477*472cd20dSToomas Soome }
478*472cd20dSToomas Soome
QueryRecordOpStopForClientRequest(QueryRecordOp * op)479*472cd20dSToomas Soome mDNSexport void QueryRecordOpStopForClientRequest(QueryRecordOp *op) {
480*472cd20dSToomas Soome QueryRecordOpStop(op);
481*472cd20dSToomas Soome }
482*472cd20dSToomas Soome
483*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
484*472cd20dSToomas Soome
QueryRecordOpCreate(QueryRecordOp ** outOp)485*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpCreate(QueryRecordOp **outOp)
486*472cd20dSToomas Soome {
487*472cd20dSToomas Soome mStatus err;
488*472cd20dSToomas Soome QueryRecordOp *op;
489*472cd20dSToomas Soome
490*472cd20dSToomas Soome op = (QueryRecordOp *) mDNSPlatformMemAllocateClear(sizeof(*op));
491*472cd20dSToomas Soome if (!op)
492*472cd20dSToomas Soome {
493*472cd20dSToomas Soome err = mStatus_NoMemoryErr;
494*472cd20dSToomas Soome goto exit;
495*472cd20dSToomas Soome }
496*472cd20dSToomas Soome *outOp = op;
497*472cd20dSToomas Soome err = mStatus_NoError;
498*472cd20dSToomas Soome
499*472cd20dSToomas Soome exit:
500*472cd20dSToomas Soome return err;
501*472cd20dSToomas Soome }
502*472cd20dSToomas Soome
QueryRecordOpFree(QueryRecordOp * operation)503*472cd20dSToomas Soome mDNSlocal void QueryRecordOpFree(QueryRecordOp *operation)
504*472cd20dSToomas Soome {
505*472cd20dSToomas Soome mDNSPlatformMemFree(operation);
506*472cd20dSToomas Soome }
507*472cd20dSToomas Soome
508*472cd20dSToomas Soome #define VALID_MSAD_SRV_TRANSPORT(T) \
509*472cd20dSToomas Soome (SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_tcp") || SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_udp"))
510*472cd20dSToomas Soome #define VALID_MSAD_SRV(Q) ((Q)->qtype == kDNSType_SRV && VALID_MSAD_SRV_TRANSPORT(SecondLabel(&(Q)->qname)))
511*472cd20dSToomas Soome
QueryRecordOpStart(QueryRecordOp * inOp,const QueryRecordOpParams * inParams,QueryRecordResultHandler inResultHandler,void * inResultContext)512*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStart(QueryRecordOp *inOp, const QueryRecordOpParams *inParams,
513*472cd20dSToomas Soome QueryRecordResultHandler inResultHandler, void *inResultContext)
514*472cd20dSToomas Soome {
515*472cd20dSToomas Soome mStatus err;
516*472cd20dSToomas Soome DNSQuestion * const q = &inOp->q;
517*472cd20dSToomas Soome mDNSu32 len;
518*472cd20dSToomas Soome
519*472cd20dSToomas Soome // Save the original qname.
520*472cd20dSToomas Soome
521*472cd20dSToomas Soome len = DomainNameLength(inParams->qname);
522*472cd20dSToomas Soome inOp->qname = (domainname *) mDNSPlatformMemAllocate(len);
523*472cd20dSToomas Soome if (!inOp->qname)
524*472cd20dSToomas Soome {
525*472cd20dSToomas Soome err = mStatus_NoMemoryErr;
526*472cd20dSToomas Soome goto exit;
527*472cd20dSToomas Soome }
528*472cd20dSToomas Soome mDNSPlatformMemCopy(inOp->qname, inParams->qname, len);
529*472cd20dSToomas Soome
530*472cd20dSToomas Soome inOp->interfaceID = inParams->interfaceID;
531*472cd20dSToomas Soome inOp->reqID = inParams->requestID;
532*472cd20dSToomas Soome inOp->resultHandler = inResultHandler;
533*472cd20dSToomas Soome inOp->resultContext = inResultContext;
534*472cd20dSToomas Soome
535*472cd20dSToomas Soome // Set up DNSQuestion.
536*472cd20dSToomas Soome
537*472cd20dSToomas Soome if (EnableAllowExpired && (inParams->flags & kDNSServiceFlagsAllowExpiredAnswers))
538*472cd20dSToomas Soome {
539*472cd20dSToomas Soome q->allowExpired = AllowExpired_AllowExpiredAnswers;
540*472cd20dSToomas Soome }
541*472cd20dSToomas Soome else
542*472cd20dSToomas Soome {
543*472cd20dSToomas Soome q->allowExpired = AllowExpired_None;
544*472cd20dSToomas Soome }
545*472cd20dSToomas Soome q->ServiceID = inParams->serviceID;
546*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
547*472cd20dSToomas Soome q->inAppBrowserRequest = inParams->isInAppBrowserRequest;
548*472cd20dSToomas Soome if (inParams->peerAuditToken)
549*472cd20dSToomas Soome {
550*472cd20dSToomas Soome q->peerAuditToken = *inParams->peerAuditToken;
551*472cd20dSToomas Soome }
552*472cd20dSToomas Soome if (inParams->delegatorAuditToken)
553*472cd20dSToomas Soome {
554*472cd20dSToomas Soome q->delegateAuditToken = *inParams->delegatorAuditToken;
555*472cd20dSToomas Soome }
556*472cd20dSToomas Soome #endif
557*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
558*472cd20dSToomas Soome if (inParams->resolverUUID)
559*472cd20dSToomas Soome {
560*472cd20dSToomas Soome mDNSPlatformMemCopy(q->ResolverUUID, inParams->resolverUUID, UUID_SIZE);
561*472cd20dSToomas Soome }
562*472cd20dSToomas Soome #endif
563*472cd20dSToomas Soome q->InterfaceID = inParams->interfaceID;
564*472cd20dSToomas Soome q->flags = inParams->flags;
565*472cd20dSToomas Soome AssignDomainName(&q->qname, inParams->qname);
566*472cd20dSToomas Soome q->qtype = inParams->qtype;
567*472cd20dSToomas Soome q->qclass = inParams->qclass;
568*472cd20dSToomas Soome q->LongLived = (inParams->flags & kDNSServiceFlagsLongLivedQuery) ? mDNStrue : mDNSfalse;
569*472cd20dSToomas Soome q->ForceMCast = (inParams->flags & kDNSServiceFlagsForceMulticast) ? mDNStrue : mDNSfalse;
570*472cd20dSToomas Soome q->ReturnIntermed = (inParams->flags & kDNSServiceFlagsReturnIntermediates) ? mDNStrue : mDNSfalse;
571*472cd20dSToomas Soome q->SuppressUnusable = (inParams->flags & kDNSServiceFlagsSuppressUnusable) ? mDNStrue : mDNSfalse;
572*472cd20dSToomas Soome q->TimeoutQuestion = (inParams->flags & kDNSServiceFlagsTimeout) ? mDNStrue : mDNSfalse;
573*472cd20dSToomas Soome q->UseBackgroundTraffic = (inParams->flags & kDNSServiceFlagsBackgroundTrafficClass) ? mDNStrue : mDNSfalse;
574*472cd20dSToomas Soome q->AppendSearchDomains = inParams->appendSearchDomains;
575*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
576*472cd20dSToomas Soome q->RequireEncryption = inParams->needEncryption;
577*472cd20dSToomas Soome q->CustomID = inParams->customID;
578*472cd20dSToomas Soome #endif
579*472cd20dSToomas Soome q->InitialCacheMiss = mDNSfalse;
580*472cd20dSToomas Soome
581*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
582*472cd20dSToomas Soome err = initialize_dnssec_status_t(&q->DNSSECStatus, inParams->qname, inParams->qtype, inParams->flags, inResultContext);
583*472cd20dSToomas Soome require_action(err == mStatus_NoError, exit, log_debug("initialize_dnssec_status failed; error_description='%s'", mStatusDescription(err)));
584*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
585*472cd20dSToomas Soome
586*472cd20dSToomas Soome q->pid = inParams->effectivePID;
587*472cd20dSToomas Soome if (inParams->effectiveUUID)
588*472cd20dSToomas Soome {
589*472cd20dSToomas Soome mDNSPlatformMemCopy(q->uuid, inParams->effectiveUUID, UUID_SIZE);
590*472cd20dSToomas Soome }
591*472cd20dSToomas Soome q->euid = inParams->peerUID;
592*472cd20dSToomas Soome q->request_id = inParams->requestID;
593*472cd20dSToomas Soome q->QuestionCallback = QueryRecordOpCallback;
594*472cd20dSToomas Soome q->ResetHandler = QueryRecordOpResetHandler;
595*472cd20dSToomas Soome
596*472cd20dSToomas Soome // For single label queries that are not fully qualified, look at /etc/hosts, cache and try search domains before trying
597*472cd20dSToomas Soome // them on the wire as a single label query. - Mohan
598*472cd20dSToomas Soome
599*472cd20dSToomas Soome if (q->AppendSearchDomains && DomainNameIsSingleLabel(inOp->qname)) q->InterfaceID = mDNSInterface_LocalOnly;
600*472cd20dSToomas Soome err = QueryRecordOpStartQuestion(inOp, q);
601*472cd20dSToomas Soome if (err) goto exit;
602*472cd20dSToomas Soome
603*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
604*472cd20dSToomas Soome if (callExternalHelpers(q->InterfaceID, &q->qname, q->flags))
605*472cd20dSToomas Soome {
606*472cd20dSToomas Soome external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, q->flags, q->pid);
607*472cd20dSToomas Soome }
608*472cd20dSToomas Soome #endif
609*472cd20dSToomas Soome
610*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
611*472cd20dSToomas Soome if ((RecordTypeIsAddress(q->qtype) || VALID_MSAD_SRV(&inOp->q)) && !q->ForceMCast &&
612*472cd20dSToomas Soome SameDomainLabel(LastLabel(&q->qname), (const mDNSu8 *)&localdomain))
613*472cd20dSToomas Soome {
614*472cd20dSToomas Soome DNSQuestion * q2;
615*472cd20dSToomas Soome
616*472cd20dSToomas Soome q2 = (DNSQuestion *) mDNSPlatformMemAllocate((mDNSu32)sizeof(*inOp->q2));
617*472cd20dSToomas Soome if (!q2)
618*472cd20dSToomas Soome {
619*472cd20dSToomas Soome err = mStatus_NoMemoryErr;
620*472cd20dSToomas Soome goto exit;
621*472cd20dSToomas Soome }
622*472cd20dSToomas Soome inOp->q2 = q2;
623*472cd20dSToomas Soome
624*472cd20dSToomas Soome *q2 = *q;
625*472cd20dSToomas Soome q2->IsUnicastDotLocal = mDNStrue;
626*472cd20dSToomas Soome
627*472cd20dSToomas Soome if ((CountLabels(&q2->qname) == 2) && !SameDomainName(&q2->qname, &ActiveDirectoryPrimaryDomain)
628*472cd20dSToomas Soome && !DomainNameIsInSearchList(&q2->qname, mDNSfalse))
629*472cd20dSToomas Soome {
630*472cd20dSToomas Soome inOp->q2Type = q2->qtype;
631*472cd20dSToomas Soome inOp->q2LongLived = q2->LongLived;
632*472cd20dSToomas Soome inOp->q2ReturnIntermed = q2->ReturnIntermed;
633*472cd20dSToomas Soome inOp->q2TimeoutQuestion = q2->TimeoutQuestion;
634*472cd20dSToomas Soome inOp->q2AppendSearchDomains = q2->AppendSearchDomains;
635*472cd20dSToomas Soome
636*472cd20dSToomas Soome AssignDomainName(&q2->qname, &localdomain);
637*472cd20dSToomas Soome q2->qtype = kDNSType_SOA;
638*472cd20dSToomas Soome q2->LongLived = mDNSfalse;
639*472cd20dSToomas Soome q2->ReturnIntermed = mDNStrue;
640*472cd20dSToomas Soome q2->TimeoutQuestion = mDNSfalse;
641*472cd20dSToomas Soome q2->AppendSearchDomains = mDNSfalse;
642*472cd20dSToomas Soome }
643*472cd20dSToomas Soome
644*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
645*472cd20dSToomas Soome "[R%u] QueryRecordOpStart: starting parallel unicast query for " PRI_DM_NAME " " PUB_S,
646*472cd20dSToomas Soome inOp->reqID, DM_NAME_PARAM(&q2->qname), DNSTypeName(q2->qtype));
647*472cd20dSToomas Soome
648*472cd20dSToomas Soome err = QueryRecordOpStartQuestion(inOp, q2);
649*472cd20dSToomas Soome if (err) goto exit;
650*472cd20dSToomas Soome }
651*472cd20dSToomas Soome #endif
652*472cd20dSToomas Soome err = mStatus_NoError;
653*472cd20dSToomas Soome
654*472cd20dSToomas Soome exit:
655*472cd20dSToomas Soome if (err) QueryRecordOpStop(inOp);
656*472cd20dSToomas Soome return err;
657*472cd20dSToomas Soome }
658*472cd20dSToomas Soome
QueryRecordOpStop(QueryRecordOp * op)659*472cd20dSToomas Soome mDNSlocal void QueryRecordOpStop(QueryRecordOp *op)
660*472cd20dSToomas Soome {
661*472cd20dSToomas Soome if (op->q.QuestionContext)
662*472cd20dSToomas Soome {
663*472cd20dSToomas Soome QueryRecordOpStopQuestion(&op->q);
664*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
665*472cd20dSToomas Soome if (callExternalHelpers(op->q.InterfaceID, op->qname, op->q.flags))
666*472cd20dSToomas Soome {
667*472cd20dSToomas Soome external_stop_browsing_for_service(op->q.InterfaceID, &op->q.qname, op->q.qtype, op->q.flags, op->q.pid);
668*472cd20dSToomas Soome }
669*472cd20dSToomas Soome #endif
670*472cd20dSToomas Soome }
671*472cd20dSToomas Soome if (op->qname)
672*472cd20dSToomas Soome {
673*472cd20dSToomas Soome mDNSPlatformMemFree(op->qname);
674*472cd20dSToomas Soome op->qname = mDNSNULL;
675*472cd20dSToomas Soome }
676*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
677*472cd20dSToomas Soome if (op->q2)
678*472cd20dSToomas Soome {
679*472cd20dSToomas Soome if (op->q2->QuestionContext) QueryRecordOpStopQuestion(op->q2);
680*472cd20dSToomas Soome mDNSPlatformMemFree(op->q2);
681*472cd20dSToomas Soome op->q2 = mDNSNULL;
682*472cd20dSToomas Soome }
683*472cd20dSToomas Soome #endif
684*472cd20dSToomas Soome }
685*472cd20dSToomas Soome
QueryRecordOpIsMulticast(const QueryRecordOp * op)686*472cd20dSToomas Soome mDNSlocal mDNSBool QueryRecordOpIsMulticast(const QueryRecordOp *op)
687*472cd20dSToomas Soome {
688*472cd20dSToomas Soome return ((mDNSOpaque16IsZero(op->q.TargetQID) && (op->q.ThisQInterval > 0)) ? mDNStrue : mDNSfalse);
689*472cd20dSToomas Soome }
690*472cd20dSToomas Soome
691*472cd20dSToomas Soome // GetTimeNow is a callback-safe alternative to mDNS_TimeNow(), which expects to be called with m->mDNS_busy == 0.
GetTimeNow(mDNS * m)692*472cd20dSToomas Soome mDNSlocal mDNSs32 GetTimeNow(mDNS *m)
693*472cd20dSToomas Soome {
694*472cd20dSToomas Soome mDNSs32 time;
695*472cd20dSToomas Soome mDNS_Lock(m);
696*472cd20dSToomas Soome time = m->timenow;
697*472cd20dSToomas Soome mDNS_Unlock(m);
698*472cd20dSToomas Soome return time;
699*472cd20dSToomas Soome }
700*472cd20dSToomas Soome
QueryRecordOpCallback(mDNS * m,DNSQuestion * inQuestion,const ResourceRecord * inAnswer,QC_result inAddRecord)701*472cd20dSToomas Soome mDNSlocal void QueryRecordOpCallback(mDNS *m, DNSQuestion *inQuestion, const ResourceRecord *inAnswer, QC_result inAddRecord)
702*472cd20dSToomas Soome {
703*472cd20dSToomas Soome mStatus resultErr;
704*472cd20dSToomas Soome QueryRecordOp *const op = (QueryRecordOp *)inQuestion->QuestionContext;
705*472cd20dSToomas Soome const domainname * domain;
706*472cd20dSToomas Soome
707*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
708*472cd20dSToomas Soome if ((inQuestion == op->q2) && (inQuestion->qtype == kDNSType_SOA))
709*472cd20dSToomas Soome {
710*472cd20dSToomas Soome DNSQuestion * const q2 = op->q2;
711*472cd20dSToomas Soome
712*472cd20dSToomas Soome if (inAnswer->rrtype != kDNSType_SOA) goto exit;
713*472cd20dSToomas Soome QueryRecordOpStopQuestion(q2);
714*472cd20dSToomas Soome
715*472cd20dSToomas Soome // Restore DNSQuestion variables that were modified for the SOA query.
716*472cd20dSToomas Soome
717*472cd20dSToomas Soome q2->qtype = op->q2Type;
718*472cd20dSToomas Soome q2->LongLived = op->q2LongLived;
719*472cd20dSToomas Soome q2->ReturnIntermed = op->q2ReturnIntermed;
720*472cd20dSToomas Soome q2->TimeoutQuestion = op->q2TimeoutQuestion;
721*472cd20dSToomas Soome q2->AppendSearchDomains = op->q2AppendSearchDomains;
722*472cd20dSToomas Soome
723*472cd20dSToomas Soome if (inAnswer->RecordType != kDNSRecordTypePacketNegative)
724*472cd20dSToomas Soome {
725*472cd20dSToomas Soome QueryRecordOpRestartUnicastQuestion(op, q2, mDNSNULL);
726*472cd20dSToomas Soome }
727*472cd20dSToomas Soome else if (q2->AppendSearchDomains)
728*472cd20dSToomas Soome {
729*472cd20dSToomas Soome domain = NextSearchDomain(op);
730*472cd20dSToomas Soome if (domain) QueryRecordOpRestartUnicastQuestion(op, q2, domain);
731*472cd20dSToomas Soome }
732*472cd20dSToomas Soome goto exit;
733*472cd20dSToomas Soome }
734*472cd20dSToomas Soome #endif
735*472cd20dSToomas Soome
736*472cd20dSToomas Soome if (inAddRecord == QC_suppressed)
737*472cd20dSToomas Soome {
738*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
739*472cd20dSToomas Soome "[R%u] QueryRecordOpCallback: Suppressed question " PRI_DM_NAME " (" PUB_S ")",
740*472cd20dSToomas Soome op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype));
741*472cd20dSToomas Soome
742*472cd20dSToomas Soome resultErr = kDNSServiceErr_NoSuchRecord;
743*472cd20dSToomas Soome }
744*472cd20dSToomas Soome else if (inAnswer->RecordType == kDNSRecordTypePacketNegative)
745*472cd20dSToomas Soome {
746*472cd20dSToomas Soome if (inQuestion->TimeoutQuestion && ((GetTimeNow(m) - inQuestion->StopTime) >= 0))
747*472cd20dSToomas Soome {
748*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
749*472cd20dSToomas Soome "[R%u] QueryRecordOpCallback: Question " PRI_DM_NAME " (" PUB_S ") timing out, InterfaceID %p",
750*472cd20dSToomas Soome op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype),
751*472cd20dSToomas Soome inQuestion->InterfaceID);
752*472cd20dSToomas Soome resultErr = kDNSServiceErr_Timeout;
753*472cd20dSToomas Soome }
754*472cd20dSToomas Soome else
755*472cd20dSToomas Soome {
756*472cd20dSToomas Soome if (inQuestion->AppendSearchDomains && (op->searchListIndex >= 0) && inAddRecord)
757*472cd20dSToomas Soome {
758*472cd20dSToomas Soome domain = NextSearchDomain(op);
759*472cd20dSToomas Soome if (domain || DomainNameIsSingleLabel(op->qname))
760*472cd20dSToomas Soome {
761*472cd20dSToomas Soome QueryRecordOpStopQuestion(inQuestion);
762*472cd20dSToomas Soome QueryRecordOpRestartUnicastQuestion(op, inQuestion, domain);
763*472cd20dSToomas Soome goto exit;
764*472cd20dSToomas Soome }
765*472cd20dSToomas Soome }
766*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
767*472cd20dSToomas Soome if (!inAnswer->InterfaceID && IsLocalDomain(inAnswer->name))
768*472cd20dSToomas Soome {
769*472cd20dSToomas Soome if ((RecordTypeIsAddress(inQuestion->qtype) &&
770*472cd20dSToomas Soome (inAnswer->negativeRecordType == kNegativeRecordType_NoData)) ||
771*472cd20dSToomas Soome DomainNameIsInSearchList(&inQuestion->qname, mDNStrue))
772*472cd20dSToomas Soome {
773*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
774*472cd20dSToomas Soome "[R%u] QueryRecordOpCallback: Question " PRI_DM_NAME " (" PUB_S ") answering local with negative unicast response",
775*472cd20dSToomas Soome op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype));
776*472cd20dSToomas Soome }
777*472cd20dSToomas Soome else
778*472cd20dSToomas Soome {
779*472cd20dSToomas Soome goto exit;
780*472cd20dSToomas Soome }
781*472cd20dSToomas Soome }
782*472cd20dSToomas Soome #endif
783*472cd20dSToomas Soome resultErr = kDNSServiceErr_NoSuchRecord;
784*472cd20dSToomas Soome }
785*472cd20dSToomas Soome }
786*472cd20dSToomas Soome else
787*472cd20dSToomas Soome {
788*472cd20dSToomas Soome resultErr = kDNSServiceErr_NoError;
789*472cd20dSToomas Soome }
790*472cd20dSToomas Soome
791*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
792*472cd20dSToomas Soome if ((resultErr != kDNSServiceErr_Timeout) && (inAddRecord == QC_add))
793*472cd20dSToomas Soome {
794*472cd20dSToomas Soome op->answered = mDNStrue;
795*472cd20dSToomas Soome }
796*472cd20dSToomas Soome #endif
797*472cd20dSToomas Soome
798*472cd20dSToomas Soome if (op->resultHandler) op->resultHandler(m, inQuestion, inAnswer, inAddRecord, resultErr, op->resultContext);
799*472cd20dSToomas Soome if (resultErr == kDNSServiceErr_Timeout) QueryRecordOpStopQuestion(inQuestion);
800*472cd20dSToomas Soome
801*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
802*472cd20dSToomas Soome NotifyWebContentFilter(inAnswer, inQuestion->euid);
803*472cd20dSToomas Soome #endif
804*472cd20dSToomas Soome
805*472cd20dSToomas Soome exit:
806*472cd20dSToomas Soome return;
807*472cd20dSToomas Soome }
808*472cd20dSToomas Soome
QueryRecordOpResetHandler(DNSQuestion * inQuestion)809*472cd20dSToomas Soome mDNSlocal void QueryRecordOpResetHandler(DNSQuestion *inQuestion)
810*472cd20dSToomas Soome {
811*472cd20dSToomas Soome QueryRecordOp *const op = (QueryRecordOp *)inQuestion->QuestionContext;
812*472cd20dSToomas Soome
813*472cd20dSToomas Soome AssignDomainName(&inQuestion->qname, op->qname);
814*472cd20dSToomas Soome if (inQuestion->AppendSearchDomains && DomainNameIsSingleLabel(op->qname))
815*472cd20dSToomas Soome {
816*472cd20dSToomas Soome inQuestion->InterfaceID = mDNSInterface_LocalOnly;
817*472cd20dSToomas Soome }
818*472cd20dSToomas Soome else
819*472cd20dSToomas Soome {
820*472cd20dSToomas Soome inQuestion->InterfaceID = op->interfaceID;
821*472cd20dSToomas Soome }
822*472cd20dSToomas Soome op->searchListIndex = 0;
823*472cd20dSToomas Soome }
824*472cd20dSToomas Soome
QueryRecordOpStartQuestion(QueryRecordOp * inOp,DNSQuestion * inQuestion)825*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStartQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion)
826*472cd20dSToomas Soome {
827*472cd20dSToomas Soome mStatus err;
828*472cd20dSToomas Soome
829*472cd20dSToomas Soome inQuestion->QuestionContext = inOp;
830*472cd20dSToomas Soome err = mDNS_StartQuery(&mDNSStorage, inQuestion);
831*472cd20dSToomas Soome if (err)
832*472cd20dSToomas Soome {
833*472cd20dSToomas Soome LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
834*472cd20dSToomas Soome "[R%u] ERROR: QueryRecordOpStartQuestion mDNS_StartQuery for " PRI_DM_NAME " " PUB_S " failed with error %d",
835*472cd20dSToomas Soome inOp->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype), err);
836*472cd20dSToomas Soome inQuestion->QuestionContext = mDNSNULL;
837*472cd20dSToomas Soome }
838*472cd20dSToomas Soome return err;
839*472cd20dSToomas Soome }
840*472cd20dSToomas Soome
QueryRecordOpStopQuestion(DNSQuestion * inQuestion)841*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpStopQuestion(DNSQuestion *inQuestion)
842*472cd20dSToomas Soome {
843*472cd20dSToomas Soome mStatus err;
844*472cd20dSToomas Soome
845*472cd20dSToomas Soome err = mDNS_StopQuery(&mDNSStorage, inQuestion);
846*472cd20dSToomas Soome inQuestion->QuestionContext = mDNSNULL;
847*472cd20dSToomas Soome return err;
848*472cd20dSToomas Soome }
849*472cd20dSToomas Soome
QueryRecordOpRestartUnicastQuestion(QueryRecordOp * inOp,DNSQuestion * inQuestion,const domainname * inSearchDomain)850*472cd20dSToomas Soome mDNSlocal mStatus QueryRecordOpRestartUnicastQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion,
851*472cd20dSToomas Soome const domainname *inSearchDomain)
852*472cd20dSToomas Soome {
853*472cd20dSToomas Soome mStatus err;
854*472cd20dSToomas Soome
855*472cd20dSToomas Soome inQuestion->InterfaceID = inOp->interfaceID;
856*472cd20dSToomas Soome AssignDomainName(&inQuestion->qname, inOp->qname);
857*472cd20dSToomas Soome if (inSearchDomain) AppendDomainName(&inQuestion->qname, inSearchDomain);
858*472cd20dSToomas Soome if (SameDomainLabel(LastLabel(&inQuestion->qname), (const mDNSu8 *)&localdomain))
859*472cd20dSToomas Soome {
860*472cd20dSToomas Soome inQuestion->IsUnicastDotLocal = mDNStrue;
861*472cd20dSToomas Soome }
862*472cd20dSToomas Soome else
863*472cd20dSToomas Soome {
864*472cd20dSToomas Soome inQuestion->IsUnicastDotLocal = mDNSfalse;
865*472cd20dSToomas Soome }
866*472cd20dSToomas Soome err = QueryRecordOpStartQuestion(inOp, inQuestion);
867*472cd20dSToomas Soome return err;
868*472cd20dSToomas Soome }
869*472cd20dSToomas Soome
InterfaceIndexToInterfaceID(mDNSu32 inInterfaceIndex,mDNSInterfaceID * outInterfaceID)870*472cd20dSToomas Soome mDNSlocal mStatus InterfaceIndexToInterfaceID(mDNSu32 inInterfaceIndex, mDNSInterfaceID *outInterfaceID)
871*472cd20dSToomas Soome {
872*472cd20dSToomas Soome mStatus err;
873*472cd20dSToomas Soome mDNSInterfaceID interfaceID;
874*472cd20dSToomas Soome
875*472cd20dSToomas Soome interfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, inInterfaceIndex);
876*472cd20dSToomas Soome
877*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
878*472cd20dSToomas Soome // The request is scoped to a specific interface index, but the interface is not currently in our list.
879*472cd20dSToomas Soome if ((inInterfaceIndex != kDNSServiceInterfaceIndexAny) && (interfaceID == mDNSInterface_Any))
880*472cd20dSToomas Soome {
881*472cd20dSToomas Soome static dispatch_once_t getLoopbackIndexOnce = 0;
882*472cd20dSToomas Soome static mDNSu32 loopbackIndex = 0;
883*472cd20dSToomas Soome
884*472cd20dSToomas Soome dispatch_once(&getLoopbackIndexOnce,
885*472cd20dSToomas Soome ^{
886*472cd20dSToomas Soome loopbackIndex = if_nametoindex("lo0");
887*472cd20dSToomas Soome });
888*472cd20dSToomas Soome
889*472cd20dSToomas Soome // If it's one of the specially defined inteface index values, just return an error. Also, caller should return an
890*472cd20dSToomas Soome // error immediately if lo0 is not configured into the current active interfaces. See <rdar://problem/21967160>.
891*472cd20dSToomas Soome if ((inInterfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
892*472cd20dSToomas Soome (inInterfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
893*472cd20dSToomas Soome (inInterfaceIndex == kDNSServiceInterfaceIndexP2P) ||
894*472cd20dSToomas Soome (inInterfaceIndex == kDNSServiceInterfaceIndexBLE) ||
895*472cd20dSToomas Soome (inInterfaceIndex == loopbackIndex))
896*472cd20dSToomas Soome {
897*472cd20dSToomas Soome LogInfo("ERROR: bad interfaceIndex %d", inInterfaceIndex);
898*472cd20dSToomas Soome err = mStatus_BadParamErr;
899*472cd20dSToomas Soome goto exit;
900*472cd20dSToomas Soome }
901*472cd20dSToomas Soome
902*472cd20dSToomas Soome // Otherwise, use the specified interface index value and the request will be applied to that interface when it
903*472cd20dSToomas Soome // comes up.
904*472cd20dSToomas Soome interfaceID = (mDNSInterfaceID)(uintptr_t)inInterfaceIndex;
905*472cd20dSToomas Soome LogInfo("Query pending for interface index %d", inInterfaceIndex);
906*472cd20dSToomas Soome }
907*472cd20dSToomas Soome #endif
908*472cd20dSToomas Soome
909*472cd20dSToomas Soome *outInterfaceID = interfaceID;
910*472cd20dSToomas Soome err = mStatus_NoError;
911*472cd20dSToomas Soome
912*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
913*472cd20dSToomas Soome exit:
914*472cd20dSToomas Soome #endif
915*472cd20dSToomas Soome return err;
916*472cd20dSToomas Soome }
917*472cd20dSToomas Soome
DomainNameIsSingleLabel(const domainname * inName)918*472cd20dSToomas Soome mDNSlocal mDNSBool DomainNameIsSingleLabel(const domainname *inName)
919*472cd20dSToomas Soome {
920*472cd20dSToomas Soome const mDNSu8 *const label = inName->c;
921*472cd20dSToomas Soome return (((label[0] != 0) && (label[1 + label[0]] == 0)) ? mDNStrue : mDNSfalse);
922*472cd20dSToomas Soome }
923*472cd20dSToomas Soome
StringEndsWithDot(const char * inString)924*472cd20dSToomas Soome mDNSlocal mDNSBool StringEndsWithDot(const char *inString)
925*472cd20dSToomas Soome {
926*472cd20dSToomas Soome const char * ptr;
927*472cd20dSToomas Soome mDNSu32 escapeCount;
928*472cd20dSToomas Soome mDNSBool result;
929*472cd20dSToomas Soome
930*472cd20dSToomas Soome // Loop invariant: escapeCount is the number of consecutive escape characters that immediately precede *ptr.
931*472cd20dSToomas Soome // - If escapeCount is even, then *ptr is immediately preceded by escapeCount / 2 consecutive literal backslash
932*472cd20dSToomas Soome // characters, so *ptr is not escaped.
933*472cd20dSToomas Soome // - If escapeCount is odd, then *ptr is immediately preceded by (escapeCount - 1) / 2 consecutive literal backslash
934*472cd20dSToomas Soome // characters followed by an escape character, so *ptr is escaped.
935*472cd20dSToomas Soome escapeCount = 0;
936*472cd20dSToomas Soome result = mDNSfalse;
937*472cd20dSToomas Soome for (ptr = inString; *ptr != '\0'; ptr++)
938*472cd20dSToomas Soome {
939*472cd20dSToomas Soome if (*ptr == '\\')
940*472cd20dSToomas Soome {
941*472cd20dSToomas Soome escapeCount++;
942*472cd20dSToomas Soome }
943*472cd20dSToomas Soome else
944*472cd20dSToomas Soome {
945*472cd20dSToomas Soome if ((*ptr == '.') && (ptr[1] == '\0'))
946*472cd20dSToomas Soome {
947*472cd20dSToomas Soome if ((escapeCount % 2) == 0) result = mDNStrue;
948*472cd20dSToomas Soome break;
949*472cd20dSToomas Soome }
950*472cd20dSToomas Soome escapeCount = 0;
951*472cd20dSToomas Soome }
952*472cd20dSToomas Soome }
953*472cd20dSToomas Soome return result;
954*472cd20dSToomas Soome }
955*472cd20dSToomas Soome
NextSearchDomain(QueryRecordOp * inOp)956*472cd20dSToomas Soome mDNSlocal const domainname * NextSearchDomain(QueryRecordOp *inOp)
957*472cd20dSToomas Soome {
958*472cd20dSToomas Soome const domainname * domain;
959*472cd20dSToomas Soome
960*472cd20dSToomas Soome while ((domain = uDNS_GetNextSearchDomain(inOp->interfaceID, &inOp->searchListIndex, mDNSfalse)) != mDNSNULL)
961*472cd20dSToomas Soome {
962*472cd20dSToomas Soome if ((DomainNameLength(inOp->qname) - 1 + DomainNameLength(domain)) <= MAX_DOMAIN_NAME) break;
963*472cd20dSToomas Soome }
964*472cd20dSToomas Soome if (!domain) inOp->searchListIndex = -1;
965*472cd20dSToomas Soome return domain;
966*472cd20dSToomas Soome }
967*472cd20dSToomas Soome
968*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
DomainNameIsInSearchList(const domainname * inName,mDNSBool inExcludeLocal)969*472cd20dSToomas Soome mDNSlocal mDNSBool DomainNameIsInSearchList(const domainname *inName, mDNSBool inExcludeLocal)
970*472cd20dSToomas Soome {
971*472cd20dSToomas Soome const SearchListElem * item;
972*472cd20dSToomas Soome int labelCount, domainLabelCount;
973*472cd20dSToomas Soome
974*472cd20dSToomas Soome labelCount = CountLabels(inName);
975*472cd20dSToomas Soome for (item = SearchList; item; item = item->next)
976*472cd20dSToomas Soome {
977*472cd20dSToomas Soome if (inExcludeLocal && SameDomainName(&item->domain, &localdomain)) continue;
978*472cd20dSToomas Soome domainLabelCount = CountLabels(&item->domain);
979*472cd20dSToomas Soome if (labelCount >= domainLabelCount)
980*472cd20dSToomas Soome {
981*472cd20dSToomas Soome if (SameDomainName(&item->domain, SkipLeadingLabels(inName, (labelCount - domainLabelCount))))
982*472cd20dSToomas Soome {
983*472cd20dSToomas Soome return mDNStrue;
984*472cd20dSToomas Soome }
985*472cd20dSToomas Soome }
986*472cd20dSToomas Soome }
987*472cd20dSToomas Soome return mDNSfalse;
988*472cd20dSToomas Soome }
989*472cd20dSToomas Soome #endif
990*472cd20dSToomas Soome
991*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
NotifyWebContentFilter(const ResourceRecord * inAnswer,uid_t inUID)992*472cd20dSToomas Soome mDNSlocal void NotifyWebContentFilter(const ResourceRecord *inAnswer, uid_t inUID)
993*472cd20dSToomas Soome {
994*472cd20dSToomas Soome if (WCFIsServerRunning)
995*472cd20dSToomas Soome {
996*472cd20dSToomas Soome const mDNS *const m = &mDNSStorage;
997*472cd20dSToomas Soome
998*472cd20dSToomas Soome if (WCFIsServerRunning(m->WCF) && inAnswer->rdlength != 0)
999*472cd20dSToomas Soome {
1000*472cd20dSToomas Soome struct sockaddr_storage addr;
1001*472cd20dSToomas Soome addr.ss_len = 0;
1002*472cd20dSToomas Soome if (inAnswer->rrtype == kDNSType_A || inAnswer->rrtype == kDNSType_AAAA)
1003*472cd20dSToomas Soome {
1004*472cd20dSToomas Soome if (inAnswer->rrtype == kDNSType_A)
1005*472cd20dSToomas Soome {
1006*472cd20dSToomas Soome struct sockaddr_in *const sin = (struct sockaddr_in *)&addr;
1007*472cd20dSToomas Soome sin->sin_port = 0;
1008*472cd20dSToomas Soome // Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this:
1009*472cd20dSToomas Soome // sin->sin_addr.s_addr = inAnswer->rdata->u.ipv4.NotAnInteger;
1010*472cd20dSToomas Soome if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(mDNSv4Addr)), inAnswer))
1011*472cd20dSToomas Soome LogMsg("NotifyWebContentFilter: WCF AF_INET putRData failed");
1012*472cd20dSToomas Soome else
1013*472cd20dSToomas Soome {
1014*472cd20dSToomas Soome addr.ss_len = sizeof (struct sockaddr_in);
1015*472cd20dSToomas Soome addr.ss_family = AF_INET;
1016*472cd20dSToomas Soome }
1017*472cd20dSToomas Soome }
1018*472cd20dSToomas Soome else if (inAnswer->rrtype == kDNSType_AAAA)
1019*472cd20dSToomas Soome {
1020*472cd20dSToomas Soome struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)&addr;
1021*472cd20dSToomas Soome sin6->sin6_port = 0;
1022*472cd20dSToomas Soome // Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this:
1023*472cd20dSToomas Soome // sin6->sin6_addr.__u6_addr.__u6_addr32[0] = inAnswer->rdata->u.ipv6.l[0];
1024*472cd20dSToomas Soome // sin6->sin6_addr.__u6_addr.__u6_addr32[1] = inAnswer->rdata->u.ipv6.l[1];
1025*472cd20dSToomas Soome // sin6->sin6_addr.__u6_addr.__u6_addr32[2] = inAnswer->rdata->u.ipv6.l[2];
1026*472cd20dSToomas Soome // sin6->sin6_addr.__u6_addr.__u6_addr32[3] = inAnswer->rdata->u.ipv6.l[3];
1027*472cd20dSToomas Soome if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(mDNSv6Addr)), inAnswer))
1028*472cd20dSToomas Soome LogMsg("NotifyWebContentFilter: WCF AF_INET6 putRData failed");
1029*472cd20dSToomas Soome else
1030*472cd20dSToomas Soome {
1031*472cd20dSToomas Soome addr.ss_len = sizeof (struct sockaddr_in6);
1032*472cd20dSToomas Soome addr.ss_family = AF_INET6;
1033*472cd20dSToomas Soome }
1034*472cd20dSToomas Soome }
1035*472cd20dSToomas Soome if (addr.ss_len)
1036*472cd20dSToomas Soome {
1037*472cd20dSToomas Soome char name[MAX_ESCAPED_DOMAIN_NAME];
1038*472cd20dSToomas Soome ConvertDomainNameToCString(inAnswer->name, name);
1039*472cd20dSToomas Soome
1040*472cd20dSToomas Soome debugf("NotifyWebContentFilter: Name %s, uid %u, addr length %d", name, inUID, addr.ss_len);
1041*472cd20dSToomas Soome if (WCFNameResolvesToAddr)
1042*472cd20dSToomas Soome {
1043*472cd20dSToomas Soome WCFNameResolvesToAddr(m->WCF, name, (struct sockaddr *)&addr, inUID);
1044*472cd20dSToomas Soome }
1045*472cd20dSToomas Soome }
1046*472cd20dSToomas Soome }
1047*472cd20dSToomas Soome else if (inAnswer->rrtype == kDNSType_CNAME)
1048*472cd20dSToomas Soome {
1049*472cd20dSToomas Soome domainname cname;
1050*472cd20dSToomas Soome char name[MAX_ESCAPED_DOMAIN_NAME];
1051*472cd20dSToomas Soome char cname_cstr[MAX_ESCAPED_DOMAIN_NAME];
1052*472cd20dSToomas Soome
1053*472cd20dSToomas Soome if (!putRData(mDNSNULL, cname.c, (mDNSu8 *)(cname.c + MAX_DOMAIN_NAME), inAnswer))
1054*472cd20dSToomas Soome LogMsg("NotifyWebContentFilter: WCF CNAME putRData failed");
1055*472cd20dSToomas Soome else
1056*472cd20dSToomas Soome {
1057*472cd20dSToomas Soome ConvertDomainNameToCString(inAnswer->name, name);
1058*472cd20dSToomas Soome ConvertDomainNameToCString(&cname, cname_cstr);
1059*472cd20dSToomas Soome if (WCFNameResolvesToAddr)
1060*472cd20dSToomas Soome {
1061*472cd20dSToomas Soome WCFNameResolvesToName(m->WCF, name, cname_cstr, inUID);
1062*472cd20dSToomas Soome }
1063*472cd20dSToomas Soome }
1064*472cd20dSToomas Soome }
1065*472cd20dSToomas Soome }
1066*472cd20dSToomas Soome }
1067*472cd20dSToomas Soome }
1068*472cd20dSToomas Soome #endif
1069