* routines, or types (which may or may not be present on any given platform).
*/
-#include "DNSCommon.h" // Defines general DNS untility routines
+#include "DNSCommon.h" // Defines general DNS utility routines
#include "uDNS.h" // Defines entry points into unicast-specific routines
#include "nsec.h"
#include "dnssec.h"
{
const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name);
if (q->CNAMEReferrals >= 10 || selfref)
+ {
LogMsg("AnswerQuestionByFollowingCNAME: %p %##s (%s) NOT following CNAME referral %d%s for %s",
q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr));
+ }
else
{
const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value
}
}
- // If this resource record is referencing a specific interface, make sure it exists.
- // Skip checks for LocalOnly and P2P as they are not valid InterfaceIDs. Also, for scoped
- // entries in /etc/hosts skip that check as that interface may not be valid at this time.
- if (rr->resrec.InterfaceID && rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
- {
- NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
- if (!intf)
- {
- debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
- return(mStatus_BadReferenceErr);
- }
- }
-
rr->next = mDNSNULL;
// Field Group 1: The actual information pertaining to this resource record
if (rr->SendRNow)
{
if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
- LogMsg("SendResponses: No active interface %p to send: %p %02X %s", rr->SendRNow, rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
+ LogInfo("SendResponses: No active interface %d to send: %d %02X %s",
+ (uint32_t)rr->SendRNow, (uint32_t)rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
rr->SendRNow = mDNSNULL;
}
{
if (ar->AddressProxy.type == mDNSAddrType_IPv4)
{
+ // There's a problem here. If a host is waking up, and we probe to see if it responds, then
+ // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
+ // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
+ // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
+ // A similar concern may apply to the NDP Probe too. -- SC
LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
}
if (ar->SendRNow)
{
if (ar->ARType != AuthRecordLocalOnly && ar->ARType != AuthRecordP2P)
- LogMsg("SendQueries: No active interface %p to send probe: %p %s", ar->SendRNow, ar->resrec.InterfaceID, ARDisplayString(m, ar));
+ LogInfo("SendQueries: No active interface %d to send probe: %d %s",
+ (uint32_t)ar->SendRNow, (uint32_t)ar->resrec.InterfaceID, ARDisplayString(m, ar));
ar->SendRNow = mDNSNULL;
}
{
DNSQuestion *x;
for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion
- LogMsg("SendQueries: No active interface %p to send %s question: %p %##s (%s)", q->SendQNow, x ? "new" : "old", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
+ LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
+ (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
q->SendQNow = mDNSNULL;
}
q->CachedAnswerNeedsUpdate = mDNSfalse;
}
// Disallow sleep if there is no sleep proxy server
- if (FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL) == mDNSNULL)
+ const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL);
+ if ( cr == mDNSNULL)
{
allowSleep = mDNSfalse;
mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname);
LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname);
break;
}
+ else if (m->SPSType != 0)
+ {
+ mDNSu32 mymetric = LocalSPSMetric(m);
+ mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
+ if (metric >= mymetric)
+ {
+ allowSleep = mDNSfalse;
+ mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname);
+ LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname);
+ break;
+ }
+ }
}
}
}
// Call the platform code to enable/disable sleep
mDNSPlatformSetAllowSleep(m, allowSleep, reason);
#else
- (void) m;
+ (void) m;
#endif /* !defined(IDLESLEEPCONTROL_DISABLED) */
-
}
mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSu32 scopeid)
else // If we have at least one advertised service
{
NetworkInterfaceInfo *intf;
+
+ // Clear out the SCDynamic entry that stores the external SPS information
+ mDNSPlatformClearSPSMACAddr();
+
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
{
// Intialize it to false. These values make sense only when SleepState is set to Sleeping.
// (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling)
// for multicast questions, we don't want to treat LongLived as anything special
#define IsLLQ(Q) ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID))
+#define IsAWDLIncluded(Q) (((Q)->flags & kDNSServiceFlagsIncludeAWDL) != 0)
mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
{
(q->DisallowPID == question->DisallowPID) && // Disallowing a PID should not affect a PID that is allowed
(q->BrowseThreshold == question->BrowseThreshold) && // browse thresholds must match
q->qnamehash == question->qnamehash &&
+ (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match
SameDomainName(&q->qname, &question->qname)) // and name
return(q);
return(mDNSNULL);
mDNSlocal void SuppressStatusChanged(mDNS *const m, DNSQuestion *q, DNSQuestion **restart)
{
// NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero
- // LOddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
+ // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
// LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers)
if (q->SuppressQuery)
{
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
if (!intf)
- LogMsg("ValidateParameters: Note: InterfaceID %p for question %##s (%s) not currently found in active interface list",
- question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
+ LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list",
+ (uint32_t)question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
}
return(mStatus_NoError);
question->LOAddressAnswers = 0;
question->FlappingInterface1 = mDNSNULL;
question->FlappingInterface2 = mDNSNULL;
-
- question->ServiceID = mDNSPlatformGetServiceID(m, question);
-
+
+ // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetServiceID()
+ // since we would already have the question->ServiceID in that case.
+ if (!(question->flags & kDNSServiceFlagsServiceIndex))
+ question->ServiceID = mDNSPlatformGetServiceID(m, question);
+ else
+ LogInfo("InitCommonState: Query for %##s (%s), PID[%d], ServiceID %d is already set by client", question->qname.c,
+ DNSTypeName(question->qtype), question->pid, question->ServiceID);
+
InitDNSConfig(m, question);
question->AuthInfo = GetAuthInfoForQuestion(m, question);
// set DisallowPID
question->DisallowPID = (question->ServiceID == 0 || (mDNSPlatformAllowPID(m, question) == 0));
if (question->DisallowPID)
- {
LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c,
- DNSTypeName(question->qtype), question->pid, question->ServiceID);
- }
+ DNSTypeName(question->qtype), question->pid, question->ServiceID);
question->NextInDQList = mDNSNULL;
question->SendQNow = mDNSNULL;
question->ForceMCast = ForceMCast;
question->ReturnIntermed = mDNSfalse;
question->SuppressUnusable = mDNSfalse;
+ question->DenyOnCellInterface = mDNSfalse;
+ question->DenyOnExpInterface = mDNSfalse;
question->SearchListIndex = 0;
question->AppendSearchDomains = 0;
question->RetryWithSearchDomains = mDNSfalse;
query->qSRV.ForceMCast = mDNSfalse;
query->qSRV.ReturnIntermed = mDNSfalse;
query->qSRV.SuppressUnusable = mDNSfalse;
+ query->qSRV.DenyOnCellInterface = mDNSfalse;
+ query->qSRV.DenyOnExpInterface = mDNSfalse;
query->qSRV.SearchListIndex = 0;
query->qSRV.AppendSearchDomains = 0;
query->qSRV.RetryWithSearchDomains = mDNSfalse;
query->qTXT.ForceMCast = mDNSfalse;
query->qTXT.ReturnIntermed = mDNSfalse;
query->qTXT.SuppressUnusable = mDNSfalse;
+ query->qTXT.DenyOnCellInterface = mDNSfalse;
+ query->qTXT.DenyOnExpInterface = mDNSfalse;
query->qTXT.SearchListIndex = 0;
query->qTXT.AppendSearchDomains = 0;
query->qTXT.RetryWithSearchDomains = mDNSfalse;
query->qAv4.ForceMCast = mDNSfalse;
query->qAv4.ReturnIntermed = mDNSfalse;
query->qAv4.SuppressUnusable = mDNSfalse;
+ query->qAv4.DenyOnCellInterface = mDNSfalse;
+ query->qAv4.DenyOnExpInterface = mDNSfalse;
query->qAv4.SearchListIndex = 0;
query->qAv4.AppendSearchDomains = 0;
query->qAv4.RetryWithSearchDomains = mDNSfalse;
query->qAv6.ForceMCast = mDNSfalse;
query->qAv6.ReturnIntermed = mDNSfalse;
query->qAv6.SuppressUnusable = mDNSfalse;
+ query->qAv6.DenyOnCellInterface = mDNSfalse;
+ query->qAv6.DenyOnExpInterface = mDNSfalse;
query->qAv6.SearchListIndex = 0;
query->qAv6.AppendSearchDomains = 0;
query->qAv6.RetryWithSearchDomains = mDNSfalse;
question->ForceMCast = mDNSfalse;
question->ReturnIntermed = mDNSfalse;
question->SuppressUnusable = mDNSfalse;
+ question->DenyOnCellInterface = mDNSfalse;
+ question->DenyOnExpInterface = mDNSfalse;
question->SearchListIndex = 0;
question->AppendSearchDomains = 0;
question->RetryWithSearchDomains = mDNSfalse;
primary = FindFirstAdvertisedInterface(m);
if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary
+ // If interface is marked as a direct link, we can assume the address record is unique
+ // and does not need to go through the probe phase of the probe/announce packet sequence.
+ mDNSu8 recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique);
+
+ if (set->DirectLink)
+ LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname);
+
// Send dynamic update for non-linklocal IPv4 Addresses
- mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNS_HostNameCallback, set);
+ mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set);
mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
set->RR_A.RRSet = &primary->RR_A; // May refer to self
+ mDNS_Register_internal(m, &set->RR_A);
+ mDNS_Register_internal(m, &set->RR_PTR);
+
#if APPLE_OSX_mDNSResponder
+ // must be after the mDNS_Register_internal() calls so that records have complete rdata fields, etc
D2D_start_advertising_interface(set);
#endif // APPLE_OSX_mDNSResponder
- mDNS_Register_internal(m, &set->RR_A);
- mDNS_Register_internal(m, &set->RR_PTR);
-
if (!NO_HINFO && m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254)
{
mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data;
if (set->Advertise)
AdvertiseInterface(m, set);
- LogInfo("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip,
+ LogInfo("mDNS_RegisterInterface: InterfaceID %d %s (%#a) %s",
+ (uint32_t)set->InterfaceID, set->ifname, &set->ip,
set->InterfaceActive ?
"not represented in list; marking active and retriggering queries" :
"already represented in list; marking inactive for now");
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID);
if (intf)
{
- LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;"
- " making it active", set->InterfaceID, set->ifname, &set->ip);
+ LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %d %s (%#a) exists;"
+ " making it active", (uint32_t)set->InterfaceID, set->ifname, &set->ip);
if (intf->InterfaceActive)
LogMsg("mDNS_DeregisterInterface: ERROR intf->InterfaceActive already set for %s (%#a)", set->ifname, &set->ip);
intf->InterfaceActive = mDNStrue;
CacheRecord *rr;
DNSQuestion *q;
- LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
- " marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip);
+ LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %d %s (%#a) deregistered;"
+ " marking questions etc. dormant", (uint32_t)set->InterfaceID, set->ifname, &set->ip);
m->mDNSStats.InterfaceDown++;