mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 05:09:34 +08:00

The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-765.1.2.tar.gz Move mDNS_StartResolveService() and mDNS_StopResolveService() to an RTEMS-specific file (rtemsbsd/mdns/mDNSResolveService.c) using the v576.30.4 implementation. Apple removed these functions without explanation. Update #3522.
315 lines
15 KiB
C
Executable File
315 lines
15 KiB
C
Executable File
/* -*- Mode: C; tab-width: 4 -*-
|
|
*
|
|
* Copyright (c) 2002-2015 Apple Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* This code is completely 100% portable C. It does not depend on any external header files
|
|
* from outside the mDNS project -- all the types it expects to find are defined right here.
|
|
*
|
|
* The previous point is very important: This file does not depend on any external
|
|
* header files. It should compile on *any* platform that has a C compiler, without
|
|
* making *any* assumptions about availability of so-called "standard" C functions,
|
|
* routines, or types (which may or may not be present on any given platform).
|
|
*/
|
|
|
|
/*
|
|
* Apple removed the mDNS_StartResolveService() and mDNS_StopResolveService()
|
|
* functions in v765.1.2. The reason for this is unknown.
|
|
*/
|
|
|
|
#include "DNSCommon.h" // Defines general DNS utility routines
|
|
#include "uDNS.h" // Defines entry points into unicast-specific routines
|
|
|
|
mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m)
|
|
{
|
|
NetworkInterfaceInfo *intf;
|
|
for (intf = m->HostInterfaces; intf; intf = intf->next)
|
|
if (intf->ip.type == mDNSAddrType_IPv6) return(mDNStrue);
|
|
return(mDNSfalse);
|
|
}
|
|
|
|
mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
|
|
{
|
|
ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
|
|
mDNSBool PortChanged = !mDNSSameIPPort(query->info->port, answer->rdata->u.srv.port);
|
|
if (!AddRecord) return;
|
|
if (answer->rrtype != kDNSType_SRV) return;
|
|
|
|
query->info->port = answer->rdata->u.srv.port;
|
|
|
|
// If this is our first answer, then set the GotSRV flag and start the address query
|
|
if (!query->GotSRV)
|
|
{
|
|
query->GotSRV = mDNStrue;
|
|
query->qAv4.InterfaceID = answer->InterfaceID;
|
|
AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
|
|
query->qAv6.InterfaceID = answer->InterfaceID;
|
|
AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
|
|
mDNS_StartQuery(m, &query->qAv4);
|
|
// Only do the AAAA query if this machine actually has IPv6 active
|
|
if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
|
|
}
|
|
// If this is not our first answer, only re-issue the address query if the target host name has changed
|
|
else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) ||
|
|
!SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target))
|
|
{
|
|
mDNS_StopQuery(m, &query->qAv4);
|
|
if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery(m, &query->qAv6);
|
|
if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged)
|
|
{
|
|
// If we get here, it means:
|
|
// 1. This is not our first SRV answer
|
|
// 2. The interface ID is different, but the target host and port are the same
|
|
// This implies that we're seeing the exact same SRV record on more than one interface, so we should
|
|
// make our address queries at least as broad as the original SRV query so that we catch all the answers.
|
|
query->qAv4.InterfaceID = query->qSRV.InterfaceID; // Will be mDNSInterface_Any, or a specific interface
|
|
query->qAv6.InterfaceID = query->qSRV.InterfaceID;
|
|
}
|
|
else
|
|
{
|
|
query->qAv4.InterfaceID = answer->InterfaceID;
|
|
AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
|
|
query->qAv6.InterfaceID = answer->InterfaceID;
|
|
AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
|
|
}
|
|
debugf("FoundServiceInfoSRV: Restarting address queries for %##s (%s)", query->qAv4.qname.c, DNSTypeName(query->qAv4.qtype));
|
|
mDNS_StartQuery(m, &query->qAv4);
|
|
// Only do the AAAA query if this machine actually has IPv6 active
|
|
if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
|
|
}
|
|
else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged)
|
|
{
|
|
if (++query->Answers >= 100)
|
|
debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u",
|
|
query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c,
|
|
mDNSVal16(answer->rdata->u.srv.port));
|
|
query->ServiceInfoQueryCallback(m, query);
|
|
}
|
|
// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
|
|
// callback function is allowed to do anything, including deleting this query and freeing its memory.
|
|
}
|
|
|
|
mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
|
|
{
|
|
ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
|
|
if (!AddRecord) return;
|
|
if (answer->rrtype != kDNSType_TXT) return;
|
|
if (answer->rdlength > sizeof(query->info->TXTinfo)) return;
|
|
|
|
query->GotTXT = mDNStrue;
|
|
query->info->TXTlen = answer->rdlength;
|
|
query->info->TXTinfo[0] = 0; // In case answer->rdlength is zero
|
|
mDNSPlatformMemCopy(query->info->TXTinfo, answer->rdata->u.txt.c, answer->rdlength);
|
|
|
|
verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD);
|
|
|
|
// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
|
|
// callback function is allowed to do anything, including deleting this query and freeing its memory.
|
|
if (query->ServiceInfoQueryCallback && query->GotADD)
|
|
{
|
|
if (++query->Answers >= 100)
|
|
debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...",
|
|
query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c);
|
|
query->ServiceInfoQueryCallback(m, query);
|
|
}
|
|
}
|
|
|
|
mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
|
|
{
|
|
ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
|
|
//LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer));
|
|
if (!AddRecord) return;
|
|
|
|
if (answer->rrtype == kDNSType_A)
|
|
{
|
|
query->info->ip.type = mDNSAddrType_IPv4;
|
|
query->info->ip.ip.v4 = answer->rdata->u.ipv4;
|
|
}
|
|
else if (answer->rrtype == kDNSType_AAAA)
|
|
{
|
|
query->info->ip.type = mDNSAddrType_IPv6;
|
|
query->info->ip.ip.v6 = answer->rdata->u.ipv6;
|
|
}
|
|
else
|
|
{
|
|
debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype));
|
|
return;
|
|
}
|
|
|
|
query->GotADD = mDNStrue;
|
|
query->info->InterfaceID = answer->InterfaceID;
|
|
|
|
verbosedebugf("FoundServiceInfo v%ld: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT);
|
|
|
|
// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
|
|
// callback function is allowed to do anything, including deleting this query and freeing its memory.
|
|
if (query->ServiceInfoQueryCallback && query->GotTXT)
|
|
{
|
|
if (++query->Answers >= 100)
|
|
debugf(answer->rrtype == kDNSType_A ?
|
|
"**** WARNING **** have given %lu answers for %##s (A) %.4a" :
|
|
"**** WARNING **** have given %lu answers for %##s (AAAA) %.16a",
|
|
query->Answers, query->qSRV.qname.c, &answer->rdata->u.data);
|
|
query->ServiceInfoQueryCallback(m, query);
|
|
}
|
|
}
|
|
|
|
// On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure
|
|
// If the query is not interface-specific, then InterfaceID may be zero
|
|
// Each time the Callback is invoked, the remainder of the fields will have been filled in
|
|
// In addition, InterfaceID will be updated to give the interface identifier corresponding to that response
|
|
mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
|
|
ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context)
|
|
{
|
|
mStatus status;
|
|
mDNS_Lock(m);
|
|
|
|
query->qSRV.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
|
|
query->qSRV.InterfaceID = info->InterfaceID;
|
|
query->qSRV.flags = 0;
|
|
query->qSRV.Target = zeroAddr;
|
|
AssignDomainName(&query->qSRV.qname, &info->name);
|
|
query->qSRV.qtype = kDNSType_SRV;
|
|
query->qSRV.qclass = kDNSClass_IN;
|
|
query->qSRV.LongLived = mDNSfalse;
|
|
query->qSRV.ExpectUnique = mDNStrue;
|
|
query->qSRV.ForceMCast = mDNSfalse;
|
|
query->qSRV.ReturnIntermed = mDNSfalse;
|
|
query->qSRV.SuppressUnusable = mDNSfalse;
|
|
query->qSRV.SearchListIndex = 0;
|
|
query->qSRV.AppendSearchDomains = 0;
|
|
query->qSRV.RetryWithSearchDomains = mDNSfalse;
|
|
query->qSRV.TimeoutQuestion = 0;
|
|
query->qSRV.WakeOnResolve = 0;
|
|
query->qSRV.UseBackgroundTrafficClass = mDNSfalse;
|
|
query->qSRV.ValidationRequired = 0;
|
|
query->qSRV.ValidatingResponse = 0;
|
|
query->qSRV.ProxyQuestion = 0;
|
|
query->qSRV.qnameOrig = mDNSNULL;
|
|
query->qSRV.AnonInfo = mDNSNULL;
|
|
query->qSRV.QuestionCallback = FoundServiceInfoSRV;
|
|
query->qSRV.QuestionContext = query;
|
|
|
|
query->qTXT.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
|
|
query->qTXT.InterfaceID = info->InterfaceID;
|
|
query->qTXT.flags = 0;
|
|
query->qTXT.Target = zeroAddr;
|
|
AssignDomainName(&query->qTXT.qname, &info->name);
|
|
query->qTXT.qtype = kDNSType_TXT;
|
|
query->qTXT.qclass = kDNSClass_IN;
|
|
query->qTXT.LongLived = mDNSfalse;
|
|
query->qTXT.ExpectUnique = mDNStrue;
|
|
query->qTXT.ForceMCast = mDNSfalse;
|
|
query->qTXT.ReturnIntermed = mDNSfalse;
|
|
query->qTXT.SuppressUnusable = mDNSfalse;
|
|
query->qTXT.SearchListIndex = 0;
|
|
query->qTXT.AppendSearchDomains = 0;
|
|
query->qTXT.RetryWithSearchDomains = mDNSfalse;
|
|
query->qTXT.TimeoutQuestion = 0;
|
|
query->qTXT.WakeOnResolve = 0;
|
|
query->qTXT.UseBackgroundTrafficClass = mDNSfalse;
|
|
query->qTXT.ValidationRequired = 0;
|
|
query->qTXT.ValidatingResponse = 0;
|
|
query->qTXT.ProxyQuestion = 0;
|
|
query->qTXT.qnameOrig = mDNSNULL;
|
|
query->qTXT.AnonInfo = mDNSNULL;
|
|
query->qTXT.QuestionCallback = FoundServiceInfoTXT;
|
|
query->qTXT.QuestionContext = query;
|
|
|
|
query->qAv4.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
|
|
query->qAv4.InterfaceID = info->InterfaceID;
|
|
query->qAv4.flags = 0;
|
|
query->qAv4.Target = zeroAddr;
|
|
query->qAv4.qname.c[0] = 0;
|
|
query->qAv4.qtype = kDNSType_A;
|
|
query->qAv4.qclass = kDNSClass_IN;
|
|
query->qAv4.LongLived = mDNSfalse;
|
|
query->qAv4.ExpectUnique = mDNStrue;
|
|
query->qAv4.ForceMCast = mDNSfalse;
|
|
query->qAv4.ReturnIntermed = mDNSfalse;
|
|
query->qAv4.SuppressUnusable = mDNSfalse;
|
|
query->qAv4.SearchListIndex = 0;
|
|
query->qAv4.AppendSearchDomains = 0;
|
|
query->qAv4.RetryWithSearchDomains = mDNSfalse;
|
|
query->qAv4.TimeoutQuestion = 0;
|
|
query->qAv4.WakeOnResolve = 0;
|
|
query->qAv4.UseBackgroundTrafficClass = mDNSfalse;
|
|
query->qAv4.ValidationRequired = 0;
|
|
query->qAv4.ValidatingResponse = 0;
|
|
query->qAv4.ProxyQuestion = 0;
|
|
query->qAv4.qnameOrig = mDNSNULL;
|
|
query->qAv4.AnonInfo = mDNSNULL;
|
|
query->qAv4.QuestionCallback = FoundServiceInfo;
|
|
query->qAv4.QuestionContext = query;
|
|
|
|
query->qAv6.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
|
|
query->qAv6.InterfaceID = info->InterfaceID;
|
|
query->qAv6.flags = 0;
|
|
query->qAv6.Target = zeroAddr;
|
|
query->qAv6.qname.c[0] = 0;
|
|
query->qAv6.qtype = kDNSType_AAAA;
|
|
query->qAv6.qclass = kDNSClass_IN;
|
|
query->qAv6.LongLived = mDNSfalse;
|
|
query->qAv6.ExpectUnique = mDNStrue;
|
|
query->qAv6.ForceMCast = mDNSfalse;
|
|
query->qAv6.ReturnIntermed = mDNSfalse;
|
|
query->qAv6.SuppressUnusable = mDNSfalse;
|
|
query->qAv6.SearchListIndex = 0;
|
|
query->qAv6.AppendSearchDomains = 0;
|
|
query->qAv6.RetryWithSearchDomains = mDNSfalse;
|
|
query->qAv6.TimeoutQuestion = 0;
|
|
query->qAv6.UseBackgroundTrafficClass = mDNSfalse;
|
|
query->qAv6.ValidationRequired = 0;
|
|
query->qAv6.ValidatingResponse = 0;
|
|
query->qAv6.ProxyQuestion = 0;
|
|
query->qAv6.qnameOrig = mDNSNULL;
|
|
query->qAv6.AnonInfo = mDNSNULL;
|
|
query->qAv6.QuestionCallback = FoundServiceInfo;
|
|
query->qAv6.QuestionContext = query;
|
|
|
|
query->GotSRV = mDNSfalse;
|
|
query->GotTXT = mDNSfalse;
|
|
query->GotADD = mDNSfalse;
|
|
query->Answers = 0;
|
|
|
|
query->info = info;
|
|
query->ServiceInfoQueryCallback = Callback;
|
|
query->ServiceInfoQueryContext = Context;
|
|
|
|
// info->name = Must already be set up by client
|
|
// info->interface = Must already be set up by client
|
|
info->ip = zeroAddr;
|
|
info->port = zeroIPPort;
|
|
info->TXTlen = 0;
|
|
|
|
// We use mDNS_StartQuery_internal here because we're already holding the lock
|
|
status = mDNS_StartQuery_internal(m, &query->qSRV);
|
|
if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT);
|
|
if (status != mStatus_NoError) mDNS_StopResolveService(m, query);
|
|
|
|
mDNS_Unlock(m);
|
|
return(status);
|
|
}
|
|
|
|
mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q)
|
|
{
|
|
mDNS_Lock(m);
|
|
// We use mDNS_StopQuery_internal here because we're already holding the lock
|
|
if (q->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qSRV);
|
|
if (q->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qTXT);
|
|
if (q->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv4);
|
|
if (q->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv6);
|
|
mDNS_Unlock(m);
|
|
}
|