#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
+extern void LogErrorMessage(const char *format, ...);
+
// ***************************************************************************
// Structures
static ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
struct sockaddr *const from, size_t *const fromlen, struct in_addr *dstaddr, char ifname[128])
{
+ static int numLogMessages = 0;
struct iovec databuffers = { (char *)buffer, max };
struct msghdr msg;
ssize_t n;
// Receive the data
n = recvmsg(s, &msg, 0);
- if (n<0 || msg.msg_controllen < sizeof(struct cmsghdr) || (msg.msg_flags & MSG_CTRUNC))
- { perror("recvmsg"); return(n); }
+ if (n<0)
+ {
+ if (numLogMessages++ < 100) LogErrorMessage("CFSocket.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
+ return(-1);
+ }
+ if (msg.msg_controllen < sizeof(struct cmsghdr))
+ {
+ if (numLogMessages++ < 100) LogErrorMessage("CFSocket.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %d",
+ s, msg.msg_controllen, sizeof(struct cmsghdr));
+ return(-1);
+ }
+ if (msg.msg_flags & MSG_CTRUNC)
+ {
+ if (numLogMessages++ < 100) LogErrorMessage("CFSocket.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
+ return(-1);
+ }
*fromlen = msg.msg_namelen;
size_t fromlen = sizeof(from);
char packetifname[128] = "";
int err;
+ int s1 = -1;
(void)address; // Parameter not used
(void)data; // Parameter not used
- if (type != kCFSocketReadCallBack) debugf("myCFSocketCallBack: Why is type not kCFSocketReadCallBack?");
+ if (type != kCFSocketReadCallBack) LogErrorMessage("CFSocketCallBack: CallBackType %d is not kCFSocketReadCallBack", type);
#if mDNS_AllowPort53
if (s == info->cfsocket53)
- err = myrecvfrom(info->socket53, &packet, sizeof(packet), (struct sockaddr *)&from, &fromlen, &to, packetifname);
+ s1 = info->socket53;
else
#endif
- err = myrecvfrom(info->socket, &packet, sizeof(packet), (struct sockaddr *)&from, &fromlen, &to, packetifname);
+ if (s == info->cfsocket)
+ s1 = info->socket;
+
+ err = myrecvfrom(s1, &packet, sizeof(packet), (struct sockaddr *)&from, &fromlen, &to, packetifname);
- if (err < 0) { debugf("myCFSocketCallBack recvfrom error %d", err); return; }
+ if (err < 0 || s1 < 0 || s1 != CFSocketGetNative(s))
+ {
+ LogErrorMessage("CFSocketCallBack: s1 %d native socket %d", s1, CFSocketGetNative(s));
+ LogErrorMessage("CFSocketCallBack: cfs %X, cfsocket53 %X, cfsocket %X", s, info->cfsocket53, info->cfsocket);
+ LogErrorMessage("CFSocketCallBack: skt53 %X, sktv4 %X", info->socket53, info->socket);
+ LogErrorMessage("CFSocketCallBack recvfrom(%d) error %d errno %d", s1, err, errno);
+ return;
+ }
senderaddr.NotAnInteger = from.sin_addr.s_addr;
senderport.NotAnInteger = from.sin_port;
struct ip_mreq imr;
struct sockaddr_in listening_sockaddr;
CFRunLoopSourceRef rls;
-
+
+ if (*s > 0) { LogErrorMessage("SetupSocket ERROR: socket %d is already set", *s); return(-1); }
+ if (*c) { LogErrorMessage("SetupSocket ERROR: CFSocketRef %X is already set", *c); return(-1); }
+
// Open the socket...
*s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
*c = NULL;
if (*s < 0) { perror("socket"); return(*s); }
-
+
// ... with a shared UDP port
err = setsockopt(*s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
if (err < 0) { perror("setsockopt - SO_REUSEPORT"); return(err); }
if (!err)
err = SetupSocket(ifa_addr, MulticastDNSPort, &info->socket, &info->cfsocket, &myCFSocketContext);
- debugf("SetupInterface: %s Flags %04X %.4a Registered",
- ifa->ifa_name, ifa->ifa_flags, &info->ifinfo.ip);
+ debugf("SetupInterface: %s Flags %04X %.4a Registered socket53 %d socket5353 %d",
+ ifa->ifa_name, ifa->ifa_flags, &info->ifinfo.ip, info->socket53, info->socket);
return(err);
}
#include "DNSServiceDiscoveryReply.h"
#include "mDNSClientAPI.h" // Defines the interface to the client layer above
+#include "mDNSPlatformFunctions.h" // For mDNSPlatformTimeNow() and mDNSPlatformOneSecond
#include "mDNSPlatformEnvironment.h" // Defines the specific types needed to run mDNS on this platform
#include "mDNSsprintf.h"
#include "mDNSvsprintf.h" // Used to implement LogErrorMessage();
DNSQuestion def; // Question asking for default domain
};
+typedef struct DNSServiceBrowserResult_struct DNSServiceBrowserResult;
+struct DNSServiceBrowserResult_struct
+ {
+ DNSServiceBrowserResult *next;
+ int resultType;
+ char name[256], type[256], dom[256];
+ };
+
typedef struct DNSServiceBrowser_struct DNSServiceBrowser;
struct DNSServiceBrowser_struct
{
DNSServiceBrowser *next;
mach_port_t ClientMachPort;
DNSQuestion q;
- int resultType; // Set to -1 if no outstanding reply
- char name[256], type[256], dom[256];
+ DNSServiceBrowserResult *results;
+ mDNSs32 lastsuccess;
};
typedef struct DNSServiceResolver_struct DNSServiceResolver;
*b = (*b)->next;
debugf("Aborting DNSServiceBrowser %d", ClientMachPort);
mDNS_StopBrowse(&mDNSStorage, &x->q);
+ while (x->results)
+ {
+ DNSServiceBrowserResult *r = x->results;
+ x->results = x->results->next;
+ freeL("DNSServiceBrowserResult", r);
+ }
freeL("DNSServiceBrowser", x);
return;
}
//*************************************************************************************************************
// Browse for services
-mDNSlocal void DeliverInstance(DNSServiceBrowser *x, DNSServiceDiscoveryReplyFlags flags)
- {
- kern_return_t status;
- debugf("DNSServiceBrowserReply_rpc sending reply for %s (%s)", x->name,
- (flags & DNSServiceDiscoverReplyFlagsMoreComing) ? "more coming" : "last in batch");
- status = DNSServiceBrowserReply_rpc(x->ClientMachPort, x->resultType, x->name, x->type, x->dom, flags, MDNS_MM_TIMEOUT);
- x->resultType = -1;
- if (status == MACH_SEND_TIMED_OUT)
- AbortBlockedClient(x->ClientMachPort, "browse");
- }
-
mDNSlocal void DeliverInstanceTimerCallBack(CFRunLoopTimerRef timer, void *info)
{
+ mDNSBool tryagain = mDNSfalse;
DNSServiceBrowser *b = DNSServiceBrowserList;
(void)timer; // Parameter not used
// and that will cause the DNSServiceBrowser object's memory to be freed before it returns
DNSServiceBrowser *x = b;
b = b->next;
- if (x->resultType != -1)
- DeliverInstance(x, 0);
+ if (x->results) // Try to deliver the list of results
+ {
+ mDNSs32 now = mDNSPlatformTimeNow();
+ while (x->results)
+ {
+ DNSServiceBrowserResult *const r = x->results;
+ DNSServiceDiscoveryReplyFlags flags = (r->next) ? DNSServiceDiscoverReplyFlagsMoreComing : 0;
+ kern_return_t status = DNSServiceBrowserReply_rpc(x->ClientMachPort, r->resultType, r->name, r->type, r->dom, flags, 1);
+ // If we failed to send the mach message, try again in one second
+ if (status == MACH_SEND_TIMED_OUT)
+ { tryagain = mDNStrue; break; }
+ else
+ {
+ x->lastsuccess = now;
+ x->results = x->results->next;
+ freeL("DNSServiceBrowserResult", r);
+ }
+ }
+ // If this client hasn't read a single message in the last 60 seconds, abort it
+ if (now - x->lastsuccess >= 60 * mDNSPlatformOneSecond)
+ AbortBlockedClient(x->ClientMachPort, "browse");
+ }
}
+ if (tryagain)
+ CFRunLoopTimerSetNextFireDate(DeliverInstanceTimer, CFAbsoluteTimeGetCurrent() + 1.0);
}
mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer)
{
- DNSServiceBrowser *x = (DNSServiceBrowser *)question->Context;
+ DNSServiceBrowser *browser = (DNSServiceBrowser *)question->Context;
+ DNSServiceBrowserResult **p = &browser->results;
+ DNSServiceBrowserResult *x = mallocL("DNSServiceBrowserResult", sizeof(*x));
domainlabel name;
domainname type, domain;
return;
}
- if (x->resultType != -1) DeliverInstance(x, DNSServiceDiscoverReplyFlagsMoreComing);
+ if (!x) return;
debugf("FoundInstance: %##s", answer->rdata->u.name.c);
ConvertDomainLabelToCString_unescaped(&name, x->name);
if (answer->rrremainingttl)
x->resultType = DNSServiceBrowserReplyAddInstance;
else x->resultType = DNSServiceBrowserReplyRemoveInstance;
+ x->next = NULL;
+ while (*p) p = &(*p)->next;
+ *p = x;
// We schedule this timer 1/10 second in the future because CFRunLoop doesn't respect
// the relative priority between CFSocket and CFRunLoopTimer, and continues to call
DNSServiceBrowser *x = mallocL("DNSServiceBrowser", sizeof(*x));
if (!x) { debugf("provide_DNSServiceBrowserCreate_rpc: No memory!"); return(mStatus_NoMemoryErr); }
x->ClientMachPort = client;
- x->resultType = -1;
+ x->results = NULL;
+ x->lastsuccess = 0;
x->next = DNSServiceBrowserList;
DNSServiceBrowserList = x;
}
}
-mDNSlocal void CheckForDuplicateRegistrations(DNSServiceRegistration *x, domainlabel *n, domainname *t, domainname *d)
+mDNSlocal void CheckForDuplicateRegistrations(DNSServiceRegistration *x, domainlabel *n, domainname *t, domainname *d, mDNSIPPort port)
{
char name[256];
int count = 0;
mDNS_sprintf(name, "%##s", &srvname);
for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
- if (rr->rrtype == kDNSType_SRV && SameDomainName(&rr->name, &srvname))
+ if (rr->rrtype == kDNSType_SRV && rr->rdata->u.srv.port.NotAnInteger == port.NotAnInteger && SameDomainName(&rr->name, &srvname))
count++;
if (count)
{
- debugf("Client %5d registering Service Record Set \"%##s\"; WARNING! now have %d instances",
- x->ClientMachPort, &srvname, count+1);
- LogErrorMessage("%5d: WARNING! Bogus client application has now registered %d identical instances of service %##s",
- x->ClientMachPort, count+1, &srvname);
+ debugf("Client %5d registering Service Record Set \"%##s\"; WARNING! now have %d instances port %d",
+ x->ClientMachPort, &srvname, count+1, (int)port.b[0] << 8 | port.b[1]);
+ LogErrorMessage("%5d: WARNING! Bogus client application has now registered %d identical instances of service %##s port %d",
+ x->ClientMachPort, count+1, &srvname, (int)port.b[0] << 8 | port.b[1]);
}
}
debugf("Client %d: provide_DNSServiceRegistrationCreate_rpc", client);
debugf("Client %d: Register Service: %#s.%##s%##s %d %.30s",
client, &x->name, &t, &d, (int)port.b[0] << 8 | port.b[1], txtRecord);
- CheckForDuplicateRegistrations(x, &x->name, &t, &d);
+ if (port.NotAnInteger) CheckForDuplicateRegistrations(x, &x->name, &t, &d, port);
err = mDNS_RegisterService(&mDNSStorage, &x->s, &x->name, &t, &d, mDNSNULL, port, txtinfo, data_len, RegCallback, x);
if (err) AbortClient(client);
#include "mDNSPlatformFunctions.h" // Defines the interface required of the supporting layer below
#include "mDNSsprintf.h"
+extern void LogErrorMessage(const char *format, ...);
+
#if(defined(_MSC_VER))
// Disable warnings about Microsoft Visual Studio/C++ not understanding "pragma unused"
#pragma warning( disable:4068 )
case kDNSType_CNAME:// Same as PTR
case kDNSType_PTR: return(CompressedDomainNameLength(&rr->rdata->u.name, name));
case kDNSType_TXT: return(rr->rdata->RDLength); // TXT is not self-describing, so have to just trust rdlength
+ case kDNSType_AAAA: return(16); break;
case kDNSType_SRV: return(6 + CompressedDomainNameLength(&rr->rdata->u.srv.target, name));
default: debugf("Warning! Don't know how to get length of resource type %d", rr->rrtype);
return(rr->rdata->RDLength);
{
DNSQuestion *q;
for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions
- if (!q->DuplicateOf && ResourceRecordAnswersQuestion(rr, q))
+ if (q->ThisQInterval > 0 && !q->DuplicateOf && ResourceRecordAnswersQuestion(rr, q))
return(q);
return(mDNSNULL);
}
rr->Callback(m, rr, mStatus_MemFree);
else if (drt == mDNS_Dereg_conflict)
{
- m->SuppressProbes = timenow + mDNSPlatformOneSecond;
- if (m->SuppressProbes == 0) m->SuppressProbes = 1;
+ m->ProbeFailTime = timenow;
+ // If we've had ten probe failures, rate-limit to one every five seconds
+ // The result is ORed with 1 to make sure SuppressProbes is not accidentally set to zero
+ if (m->NumFailedProbes < 10) m->NumFailedProbes++;
+ else m->SuppressProbes = (timenow + mDNSPlatformOneSecond * 5) | 1;
if (rr->Callback) rr->Callback(m, rr, mStatus_NameConflict);
}
}
rr->rrtype, pktrdlength, rr->rdata->MaxRDLength);
return(mDNSNULL);
}
- debugf("getResourceRecord: Warning! Reading resource type %d as opaque data", rr->rrtype);
+ if (rr->rrtype != kDNSType_AAAA)
+ debugf("getResourceRecord: Warning! Reading resource type %d as opaque data", rr->rrtype);
// Note: Just because we don't understand the record type, that doesn't
// mean we fail. The DNS protocol specifies rdlength, so we can
// safely skip over unknown records and ignore them.
if (m->CurrentRecord) debugf("BuildResponse ERROR m->CurrentRecord already set");
m->CurrentRecord = m->ResourceRecords;
-
+
// If we're sleeping, only send deregistrations
if (m->SleepState)
{
if (response->h.numAnswers == 0) debugf("BuildResponse announcements failed");
if (newptr || response->h.numAnswers == 0)
{
- if (minExistingAnnounceInterval > rr->NextSendInterval)
+ if (minExistingAnnounceInterval < rr->NextSendInterval)
minExistingAnnounceInterval = rr->NextSendInterval;
rr->SendPriority = 0;
rr->Requester = zeroIPAddr;
}
}
-#define TimeToSendThisQuestion(Q,time) (!(Q)->DuplicateOf && time - (Q)->NextQTime >= 0)
+#define TimeToSendThisQuestion(Q,time) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf && (time) - (Q)->NextQTime >= 0)
mDNSlocal mDNSBool HaveQueries(const mDNS *const m, const mDNSs32 timenow)
{
mDNSs32 needquery = timenow + mDNSPlatformOneSecond;
DNSQuestion *q;
for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions
- if (!q->DuplicateOf && q->NextQTime - needquery > 0 && ResourceRecordAnswersQuestion(rr, q))
+ if (q->ThisQInterval > 0 && !q->DuplicateOf && q->NextQTime - needquery > 0 && ResourceRecordAnswersQuestion(rr, q))
{
q->NextQTime = needquery;
// As long as responses are still coming in, don't do the exponential backoff
m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
for (rr=m->rrcache; rr && m->CurrentQuestion == q; rr=rr->next)
if (ResourceRecordAnswersQuestion(rr, q))
- AnswerQuestionWithResourceRecord(m, q, rr, timenow);
+ {
+ mDNSu32 SecsSinceRcvd = ((mDNSu32)(timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
+ if (rr->rroriginalttl <= SecsSinceRcvd) rr->rrremainingttl = 0;
+ else rr->rrremainingttl = rr->rroriginalttl - SecsSinceRcvd;
+
+ // We only give positive responses to new questions.
+ // Since this question is new, it has not received any answers yet, so there's no point
+ // telling it about records that are going away that it never heard about in the first place.
+ if (rr->rrremainingttl > 0)
+ AnswerQuestionWithResourceRecord(m, q, rr, timenow);
+ // MUST NOT touch q again after calling AnswerQuestionWithResourceRecord()
+ }
m->CurrentQuestion = mDNSNULL;
m->lock_rrcache = 0;
}
{
// If the record's interface matches the one we're flushing,
// then pretend we just received a 'goodbye' packet for this record.
- rr->TimeRcvd = timenow;
- rr->UnansweredQueries = 0;
- rr->rroriginalttl = 1;
+ rr->TimeRcvd = timenow - mDNSPlatformOneSecond * 60;
+ rr->UnansweredQueries = 2;
+ rr->rroriginalttl = 0;
count++;
}
}
if (m->SuppressProbes && timenow - m->SuppressProbes >= 0)
m->SuppressProbes = 0;
+ if (m->NumFailedProbes && timenow - m->ProbeFailTime >= mDNSPlatformOneSecond * 10)
+ m->NumFailedProbes = 0;
+
// 1. See if we can answer any of our new local questions from the cache
while (m->NewQuestions) AnswerNewQuestion(m, timenow);
}
else if (m->SuppressSending == 0 || timenow - m->SuppressSending >= 0)
{
+ int i;
// If the platform code is ready,
// and we're not suppressing packet generation right now
// send our responses, probes, and questions
m->SuppressSending = 0;
- while (HaveResponses(m, timenow)) SendResponses(m, timenow);
- while (HaveQueries (m, timenow)) SendQueries (m, timenow);
+ for (i=0; i<100 && HaveResponses(m, timenow); i++) SendResponses(m, timenow);
+ if (i >= 100) LogErrorMessage("mDNSCoreTask: HaveResponses returned true %d times", i);
+ for (i=0; i<100 && HaveQueries (m, timenow); i++) SendQueries (m, timenow);
+ if (i >= 100) LogErrorMessage("mDNSCoreTask: HaveQueries returned true %d times", i);
}
if (m->rrcache_size) TidyRRCache(m, timenow);
rr->NextSendInterval = DefaultSendIntervalForRecordType(rr->RecordType);
}
for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions
- if (!q->DuplicateOf)
+ if (q->ThisQInterval > 0 && !q->DuplicateOf)
{
q->NextQTime = timenow;
q->ThisQInterval = mDNSPlatformOneSecond; // MUST NOT be zero for an active question
if (!result) result = CompareRData(&pktrr, our);
switch (result)
{
- case 1: debugf("ResolveSimultaneousProbe: %##s (%s): We won", our->name.c, DNSTypeName(our->rrtype));
+ case -1: debugf("ResolveSimultaneousProbe: %##s (%s): We won", our->name.c, DNSTypeName(our->rrtype));
break;
case 0: break;
- case -1: debugf("ResolveSimultaneousProbe: %##s (%s): We lost", our->name.c, DNSTypeName(our->rrtype));
+ case 1: debugf("ResolveSimultaneousProbe: %##s (%s): We lost", our->name.c, DNSTypeName(our->rrtype));
mDNS_Deregister_internal(m, our, timenow, mDNS_Dereg_conflict);
return;
}
rr->ProbeCount = DefaultProbeCountForTypeUnique + 1;
rr->NextSendTime = timenow;
rr->NextSendInterval = DefaultSendIntervalForRecordType(kDNSRecordTypeUnique);
+ m->ProbeFailTime = timenow;
+ // If we've had ten probe failures, rate-limit to one every five seconds
+ // The result is ORed with 1 to make sure SuppressProbes is not accidentally set to zero
+ if (m->NumFailedProbes < 10) m->NumFailedProbes++;
+ else m->SuppressProbes = (timenow + mDNSPlatformOneSecond * 5) | 1;
}
else
{
mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
{
DNSQuestion *q;
- for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions
- if (q->rrtype == question->rrtype &&
- q->rrclass == question->rrclass &&
- SameDomainName(&q->name, &question->name)) return(q);
+ // Note: A question can only be marked as a duplicate of one that occurs *earlier* in the list.
+ // This prevents circular references, where two questions are each marked as a duplicate of the other.
+ // Accordingly, we break out of the loop when we get to 'question', because there's no point searching
+ // further in the list.
+ for (q = m->ActiveQuestions; q && q != question; q=q->next) // Scan our list of questions
+ if (q->InterfaceAddr.NotAnInteger == question->InterfaceAddr.NotAnInteger && // for another question with the same InterfaceID,
+ q->rrtype == question->rrtype && // type,
+ q->rrclass == question->rrclass && // class,
+ SameDomainName(&q->name, &question->name)) // and name
+ return(q);
return(mDNSNULL);
}
return(mStatus_AlreadyRegistered);
}
+ if (question->InterfaceAddr.NotAnInteger)
+ {
+ NetworkInterfaceInfo *p = m->HostInterfaces;
+ while (p && p->ip.NotAnInteger != question->InterfaceAddr.NotAnInteger) p=p->next;
+ if (!p)
+ {
+ LogErrorMessage("mDNS_StartQuery_internal: question->InterfaceAddr %.4a not found in interface list", &question->InterfaceAddr);
+ question->InterfaceAddr.NotAnInteger = 0;
+ }
+ }
+
question->next = mDNSNULL;
question->NextQTime = timenow;
question->ThisQInterval = mDNSPlatformOneSecond; // MUST NOT be zero for an active question
UpdateQuestionDuplicates(m, question);
- question->next = mDNSNULL;
- question->ThisQInterval = 0;
- question->NextQInterval = 0;
+ question->ThisQInterval = -1;
+ question->NextQInterval = -1;
// If we just deleted the question that AnswerLocalQuestions() is about to look at,
// bump its pointer forward one question.
m->NewQuestions = m->NewQuestions->next;
}
+ // Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions
+ question->next = mDNSNULL;
}
mDNSexport mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question)
if (!query->GotSRV)
{
query->GotSRV = mDNStrue;
+ query->qADD.InterfaceAddr = answer->InterfaceAddr;
query->qADD.name = answer->rdata->u.srv.target;
mDNS_StartQuery_internal(m, &query->qADD, mDNSPlatformTimeNow());
}
// If this is not our first answer, only re-issue the address query if the target host name has changed
- else if (!SameDomainName(&query->qADD.name, &answer->rdata->u.srv.target))
+ else if (query->qADD.InterfaceAddr.NotAnInteger != answer->InterfaceAddr.NotAnInteger ||
+ !SameDomainName(&query->qADD.name, &answer->rdata->u.srv.target))
{
mDNS_StopQuery_internal(m, &query->qADD);
+ query->qADD.InterfaceAddr = answer->InterfaceAddr;
query->qADD.name = answer->rdata->u.srv.target;
mDNS_StartQuery_internal(m, &query->qADD, mDNSPlatformTimeNow());
}
mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query)
{
mDNS_Lock(m);
- if (query->qSRV.ThisQInterval) mDNS_StopQuery_internal(m, &query->qSRV);
- if (query->qTXT.ThisQInterval) mDNS_StopQuery_internal(m, &query->qTXT);
- if (query->qADD.ThisQInterval) mDNS_StopQuery_internal(m, &query->qADD);
+ if (query->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qSRV);
+ if (query->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qTXT);
+ if (query->qADD.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qADD);
mDNS_Unlock(m);
}
// ... Add an HINFO record, etc.?
}
+ { // Reactivate Interface Questions
+ DNSQuestion *q;
+ for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions
+ if (!q->InterfaceAddr.NotAnInteger || q->InterfaceAddr.NotAnInteger == set->ip.NotAnInteger)
+ {
+ q->NextQTime = timenow;
+ q->ThisQInterval = mDNSPlatformOneSecond; // MUST be > zero for an active question
+ q->NextQInterval = mDNSPlatformOneSecond;
+ }
+ }
+
set->next = mDNSNULL;
*p = set;
mDNS_Unlock(m);
// Flush any cache entries we received on this interface
FlushCacheRecords(m, set->ip, timenow);
+ { // Deactivate Interface Questions
+ DNSQuestion *q;
+ for (q = m->ActiveQuestions; q; q=q->next)
+ if (q->InterfaceAddr.NotAnInteger == set->ip.NotAnInteger)
+ q->ThisQInterval = 0;
+ }
+
// If we were advertising on this interface, deregister now
// When doing the mDNS_Close processing, we first call mDNS_DeadvertiseInterface for each interface
// so by the time the platform support layer gets to call mDNS_DeregisterInterface,
if (host && host->c[0]) sr->Host = *host;
else sr->Host.c[0] = 0;
- mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, zeroIPAddr, kDNSType_PTR, 24*3600, kDNSRecordTypeShared, ServiceCallback, sr);
- mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, zeroIPAddr, kDNSType_SRV, 60, kDNSRecordTypeUnique, ServiceCallback, sr);
- mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, zeroIPAddr, kDNSType_TXT, 60, kDNSRecordTypeUnique, ServiceCallback, sr);
+ mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, zeroIPAddr, kDNSType_PTR, 2*3600, kDNSRecordTypeShared, ServiceCallback, sr);
+ mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, zeroIPAddr, kDNSType_SRV, 60, kDNSRecordTypeUnique, ServiceCallback, sr);
+ mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, zeroIPAddr, kDNSType_TXT, 60, kDNSRecordTypeUnique, ServiceCallback, sr);
// If the client is registering an oversized TXT record,
// it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it
mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, ResourceRecord *rr,
mDNSu8 DomainType, const mDNSIPAddr InterfaceAddr, char *domname)
{
- mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceAddr, kDNSType_PTR, 24*3600, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
+ mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceAddr, kDNSType_PTR, 2*3600, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
ConvertCStringToDomainName(mDNS_DomainTypeNames[DomainType], &rr->name);
ConvertCStringToDomainName(domname, &rr->rdata->u.name);
return(mDNS_Register(m, rr));
m->CurrentRecord = mDNSNULL;
m->HostInterfaces = mDNSNULL;
m->SuppressSending = 0;
+ m->ProbeFailTime = 0;
+ m->NumFailedProbes = 0;
+ m->SuppressProbes = 0;
m->SleepState = mDNSfalse;
m->NetChanged = mDNSfalse;