for (p = &SearchList; *p; p = &(*p)->next)
if (SameDomainName(&(*p)->domain, domain))
{
- // If domain is already in list, and marked for deletion, change it to "leave alone"
- if ((*p)->flag == -1) (*p)->flag = 0;
+ // If domain is already in list, and marked for deletion, unmark the delete
+ // Be careful not to touch the other flags that may be present
+ if ((*p)->flag & SLE_DELETE) (*p)->flag &= ~SLE_DELETE;
LogInfo("mDNS_AddSearchDomain already in list %##s", domain->c);
return;
}
if (!*p) { LogMsg("ERROR: mDNS_AddSearchDomain - malloc"); return; }
mDNSPlatformMemZero(*p, sizeof(SearchListElem));
AssignDomainName(&(*p)->domain, domain);
- (*p)->flag = 1; // add
(*p)->next = mDNSNULL;
LogInfo("mDNS_AddSearchDomain created new %##s", domain->c);
}
}
#endif
-mDNSlocal void FoundDirDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+mDNSlocal void FoundCFDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
SearchListElem *slElem = question->QuestionContext;
mDNSBool RegisterAutoTunnel6 = mDNStrue;
char *res = "DisableInboundRelay";
- LogInfo("FoundDirDomain: InterfaceID %p %s Question %##s Answer %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", question->qname.c, RRDisplayString(m, answer));
+ LogInfo("FoundCFDomain: InterfaceID %p %s Question %##s Answer %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", question->qname.c, RRDisplayString(m, answer));
if (answer->rrtype != kDNSType_TXT)
{
- LogMsg("FoundDirDomain: answer type is not TXT %s for question %##s", DNSTypeName(answer->rrtype), question->qname.c);
+ LogMsg("FoundCFDomain: answer type is not TXT %s for question %##s", DNSTypeName(answer->rrtype), question->qname.c);
return;
}
if (answer->RecordType == kDNSRecordTypePacketNegative)
{
- LogInfo("FoundDirDomain: Negative answer for %##s", question->qname.c);
+ LogInfo("FoundCFDomain: Negative answer for %##s", question->qname.c);
return;
}
if (answer->InterfaceID == mDNSInterface_LocalOnly)
{
- LogInfo("FoundDirDomain: LocalOnly interfaceID for %##s", question->qname.c);
+ LogInfo("FoundCFDomain: LocalOnly interfaceID for %##s", question->qname.c);
return;
}
// TXT record is encoded as <len><data>
if (answer->rdlength != mDNSPlatformStrLen(res) + 1)
{
- LogInfo("FoundDirDomain: Invalid TXT record to disable %##s, length %d", question->qname.c, answer->rdlength);
+ LogInfo("FoundCFDomain: Invalid TXT record to disable %##s, length %d", question->qname.c, answer->rdlength);
return;
}
// Compare the data (excluding the len byte)
if (!mDNSPlatformMemSame(&answer->rdata->u.txt.c[1], res, answer->rdlength - 1))
{
- LogInfo("FoundDirDomain: Invalid TXT record to disable %##s", question->qname.c);
+ LogInfo("FoundCFDomain: Invalid TXT record to disable %##s", question->qname.c);
return;
}
// have zero answers across all domains to register autotunnel6.
if (AddRecord)
{
- slElem->numDirAnswers++;
+ slElem->numCfAnswers++;
RegisterAutoTunnel6 = mDNSfalse;
}
else
{
const SearchListElem *s;
- slElem->numDirAnswers--;
- if (slElem->numDirAnswers < 0) LogMsg("FoundDirDomain: numDirAnswers less than zero %d", slElem->numDirAnswers);
+ slElem->numCfAnswers--;
+ if (slElem->numCfAnswers < 0) LogMsg("FoundCFDomain: numCfAnswers less than zero %d", slElem->numCfAnswers);
// See if any domain (including the slElem) has any answers
for (s=SearchList; s; s=s->next)
- if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
+ if (s->numCfAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
}
#if APPLE_OSX_mDNSResponder
CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
}
#endif
-mDNSlocal void mDNS_StartDirQuestion(mDNS *const m, DNSQuestion *question, domainname *domain, void *context)
+mDNSlocal void mDNS_StartCFQuestion(mDNS *const m, DNSQuestion *question, domainname *domain, void *context)
{
AssignDomainName (&question->qname, (const domainname*)"\002cf" "\007_dns-sd" "\x04_udp");
AppendDomainName (&question->qname, domain);
question->ForceMCast = mDNSfalse;
question->ReturnIntermed = mDNSfalse;
question->SuppressUnusable = mDNSfalse;
- question->QuestionCallback = FoundDirDomain;
+ question->QuestionCallback = FoundCFDomain;
question->QuestionContext = context;
- LogInfo("mDNS_StartDirQuestion: Start DIR domain question %##s", question->qname.c);
+ LogInfo("mDNS_StartCFQuestion: Start CF domain question %##s", question->qname.c);
if (mDNS_StartQuery(m, question))
- LogMsg("mDNS_StartDirQuestion: ERROR!! cannot start _dir._dns-sd query");
+ LogMsg("mDNS_StartCFQuestion: ERROR!! cannot start cf._dns-sd query");
}
// This should probably move to the UDS daemon -- the concept of legacy clients and automatic registration / automatic browsing
// is really a UDS API issue, not something intrinsic to uDNS
-mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
+mDNSexport mStatus uDNS_SetupSearchDomains(mDNS *const m, int action)
{
SearchListElem **p = &SearchList, *ptr;
const SearchListElem *s;
mDNSBool RegisterAutoTunnel6 = mDNStrue;
mStatus err;
- // step 1: mark each element for removal (-1)
- for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = -1;
+ // step 1: mark each element for removal
+ for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag |= SLE_DELETE;
// Client has requested domain enumeration or automatic browse -- time to make sure we have the search domains from the platform layer
mDNS_Lock(m);
- m->RegisterSearchDomains = mDNStrue;
- mDNSPlatformSetDNSConfig(m, mDNSfalse, m->RegisterSearchDomains, mDNSNULL, mDNSNULL, mDNSNULL);
+ mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL);
mDNS_Unlock(m);
+ if (action & UDNS_START_WAB_QUERY)
+ m->StartWABQueries = mDNStrue;
+
// delete elems marked for removal, do queries for elems marked add
while (*p)
{
ptr = *p;
- LogInfo("RegisterSearchDomains %d %p %##s", ptr->flag, ptr->AuthRecs, ptr->domain.c);
- if (ptr->flag == -1) // remove
+ LogInfo("uDNS_SetupSearchDomains:action %d: Flags %d, AuthRecs %p, %##s", action, ptr->flag, ptr->AuthRecs, ptr->domain.c);
+ if (ptr->flag & SLE_DELETE)
{
ARListElem *arList = ptr->AuthRecs;
ptr->AuthRecs = mDNSNULL;
*p = ptr->next;
// If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
- // Note: Stopping a question will not generate the RMV events for the question (handled in FoundDirDomain)
+ // Note: Stopping a question will not generate the RMV events for the question (handled in FoundCFDomain)
// and hence we need to recheck all the domains to see if we need to register/deregister _autotunnel6.
// This is done at the end.
- if (!SameDomainName(&ptr->domain, &localdomain))
+ if ((ptr->flag & SLE_WAB_QUERY_STARTED) && !SameDomainName(&ptr->domain, &localdomain))
{
mDNS_StopGetDomains(m, &ptr->BrowseQ);
mDNS_StopGetDomains(m, &ptr->RegisterQ);
mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
- mDNS_StopGetDomains(m, &ptr->DirQ);
}
+#if !TARGET_OS_EMBEDDED
+ if ((ptr->flag & SLE_CF_QUERY_STARTED) && !SameDomainName(&ptr->domain, &localdomain))
+ {
+ mDNS_StopGetDomains(m, &ptr->CfQ);
+ }
+#endif
mDNSPlatformMemFree(ptr);
// deregister records generated from answers to the query
arList = arList->next;
debugf("Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
err = mDNS_Deregister(m, &dereg->ar);
- if (err) LogMsg("uDNS_RegisterSearchDomains ERROR!! mDNS_Deregister returned %d", err);
+ if (err) LogMsg("uDNS_SetupSearchDomains:: ERROR!! mDNS_Deregister returned %d", err);
// Memory will be freed in the FreeARElemCallback
}
continue;
}
- if (ptr->flag == 1) // add
+ if ((action & UDNS_START_WAB_QUERY) && !(ptr->flag & SLE_WAB_QUERY_STARTED))
{
- // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
+ // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries.
if (!SameDomainName(&ptr->domain, &localdomain))
{
mStatus err1, err2, err3, err4, err5;
err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
if (err1 || err2 || err3 || err4 || err5)
- LogMsg("uDNS_RegisterSearchDomains: GetDomains for domain %##s returned error(s):\n"
+ LogMsg("uDNS_SetupSearchDomains: GetDomains for domain %##s returned error(s):\n"
"%d (mDNS_DomainTypeBrowse)\n"
"%d (mDNS_DomainTypeBrowseDefault)\n"
"%d (mDNS_DomainTypeRegistration)\n"
"%d (mDNS_DomainTypeRegistrationDefault)"
"%d (mDNS_DomainTypeBrowseAutomatic)\n",
ptr->domain.c, err1, err2, err3, err4, err5);
- mDNS_StartDirQuestion(m, &ptr->DirQ, &ptr->domain, ptr);
+ ptr->flag |= SLE_WAB_QUERY_STARTED;
}
- ptr->flag = 0;
}
-
- if (ptr->flag) { LogMsg("uDNS_RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
+#if !TARGET_OS_EMBEDDED
+ if ((action & UDNS_START_CF_QUERY) && !(ptr->flag & SLE_CF_QUERY_STARTED))
+ {
+ if (!SameDomainName(&ptr->domain, &localdomain))
+ {
+ mDNS_StartCFQuestion(m, &ptr->CfQ, &ptr->domain, ptr);
+ ptr->flag |= SLE_CF_QUERY_STARTED;
+ }
+ }
+#endif
p = &ptr->next;
}
+#if !TARGET_OS_EMBEDDED
// if there is any domain has answers, need to deregister autotunnel6
for (s=SearchList; s; s=s->next)
- if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
+ if (s->numCfAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
#if APPLE_OSX_mDNSResponder
CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
+#endif
#endif
return mStatus_NoError;
}
#include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
#include "PlatformCommon.h"
#include "uds_daemon.h"
-#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <stdarg.h> // For va_list support
static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
-// We arbitrarily limit the message size to 128 bytes (which seems sufficient now) so that
-// freeing ELogContext is simpler which is treated as opaque quantity in many places
-typedef struct
- {
- char subdomain[32];
- char message[128];
- uuid_t uuid;
- int result;
- } ELogContext;
-
-typedef enum { HTTPGet = 1, HTTPPost } HTTPOperation;
-typedef enum { ConfigInvalid = 0, ConfigFetching, ConfigValid } ConfigState;
-typedef void (*HTTPClientCallback)(CFMutableDataRef responseData, ELogContext *context);
-#define kReadStreamBufferSize 4096
-#define kMaximumResponseSize 32768
-#define kHTTPResponseCodeOK 200
-#define kHTTPResponseCodeAuthFailure 401
-#define kHTTPResponseCodeForbidden 403
-#define kHTTPResponseCodeNotFound 404
-
-// eReporter configuration needs to be fetched whenever it becomes stale. We fetch it lazily
-// when we send the report.
-struct eReporterConfiguration {
- CFDictionaryRef eRDict;
- ConfigState eRState;
-} eReporterConfig;
-
-typedef struct
- {
- mDNSBool authChecked;
- CFHTTPAuthenticationRef authentication;
- CFMutableDataRef responseData;
- HTTPClientCallback callback;
- ELogContext cbcontext;
- HTTPOperation op;
- CFStringRef headerFieldName;
- CFStringRef headerFieldValue;
- CFDataRef bodyData;
- CFStringRef url;
- } HTTPDataStreamContext;
-
-
-// Forward declarations
-mDNSlocal void HTTPDataStream(CFStringRef url, HTTPOperation op, CFDataRef bodyData, CFStringRef headerFieldName,
- CFStringRef headerFieldValue, CFHTTPAuthenticationRef auth, CFMutableDictionaryRef credentials,
- HTTPClientCallback callback, ELogContext *context);
-mDNSlocal void mDNSReporterLogValidConfig(ELogContext *elog);
-
-mDNSlocal void CancelReadStream(CFReadStreamRef readStream)
- {
- if (readStream)
- {
- CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
- CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetMain(), kCFRunLoopCommonModes);
- CFReadStreamClose(readStream);
- CFRelease(readStream);
- }
- }
-
-mDNSlocal void CancelHTTPDataStream(CFReadStreamRef stream, HTTPDataStreamContext *context)
- {
- LogInfo("CancelHTTPDataStream: called");
- if (context)
- {
- if (context->authentication) CFRelease(context->authentication);
- if (context->responseData) CFRelease(context->responseData);
- if (context->headerFieldName) CFRelease(context->headerFieldName);
- if (context->headerFieldValue) CFRelease(context->headerFieldValue);
- if (context->bodyData) CFRelease(context->bodyData);
- if (context->url) CFRelease(context->url);
- freeL("HTTPDataStreamContext", context);
- }
- CancelReadStream(stream);
- }
-
-mDNSlocal CFIndex HTTPResponseCode(CFReadStreamRef stream)
- {
- CFIndex errorCode = 0;
- CFHTTPMessageRef responseHeaders = (CFHTTPMessageRef)CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
- if (responseHeaders)
- {
- errorCode = CFHTTPMessageGetResponseStatusCode(responseHeaders);
- CFRelease(responseHeaders);
- }
- return errorCode;
- }
-
-mDNSlocal void RetryWithHTTPAuth(HTTPDataStreamContext *context, CFReadStreamRef stream)
- {
- CFStreamError err;
- DomainAuthInfo *FoundInList;
- CFMutableDictionaryRef credentials = NULL;
-
- // Need to use the same authentication object till it goes invalid
- if (!context->authentication)
- {
- CFHTTPMessageRef responseHeader = (CFHTTPMessageRef)CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
- // Get the authentication information from the response.
- context->authentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);
- CFRelease(responseHeader);
- }
-
- // Check to see if the authentication is valid for use. Anything could have gone wrong
- // from bad credentials to wrong type of authentication etc.
- if (!context->authentication || !CFHTTPAuthenticationIsValid(context->authentication, &err))
- {
- LogMsg("RetryWithHTTPAuth: ERROR!! Authentication failed");
- if (context->authentication)
- {
- // Check for bad credentials and treat these separately
- if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName ||
- err.error == kCFStreamErrorHTTPAuthenticationBadPassword))
- {
- LogMsg("RetryWithHTTPAuth: ERROR!! Bad credentials %d", err.error);
- }
- }
- CancelHTTPDataStream(stream, context);
- return;
- }
-
- // Do we need username & password? Not all authentication types require them.
- if (CFHTTPAuthenticationRequiresUserNameAndPassword(context->authentication))
- {
- char username[MAX_DOMAIN_LABEL + 1];
-
-
- // Use the first BTMM username and password
- for (FoundInList = (&mDNSStorage)->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
- if (!FoundInList->deltime && FoundInList->AutoTunnel) break;
-
- if (!FoundInList)
- {
- LogInfo("RetryHTTPWithAuth: No BTMM credentials");
- CancelHTTPDataStream(stream, context);
- return;
- }
-
- ConvertDomainLabelToCString_unescaped((domainlabel *)FoundInList->domain.c, username);
- CFStringRef user = CFStringCreateWithBytes(NULL, (const mDNSu8 *)username, strlen(username), kCFStringEncodingASCII, false);
- if (!user)
- {
- LogMsg("RetryHTTPWithAuth: ERROR!! CFStringCreateWithBytes error");
- CancelHTTPDataStream(stream, context);
- return;
- }
- CFStringRef pass = CFStringCreateWithBytes(NULL, (const mDNSu8 *)FoundInList->b64keydata, strlen(FoundInList->b64keydata),
- kCFStringEncodingASCII, false);
- if (!pass)
- {
- LogMsg("RetryHTTPWithAuth: ERROR!! CFStringCreateWithBytes error");
- CFRelease(user);
- CancelHTTPDataStream(stream, context);
- return;
- }
- // Build the credentials dictionary
- credentials = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (!credentials)
- {
- LogMsg("RetryHTTPWithAuth: ERROR!! cannot allocate credentials");
- CFRelease(user);
- CFRelease(pass);
- CancelHTTPDataStream(stream, context);
- return;
- }
- CFDictionarySetValue(credentials, kCFHTTPAuthenticationUsername, user);
- CFDictionarySetValue(credentials, kCFHTTPAuthenticationPassword, pass);
- CFRelease(user);
- CFRelease(pass);
- }
- else
- {
- LogMsg("RetryHTTPWithAuth: ERROR!! Unknown authentication method");
- CancelHTTPDataStream(stream, context);
- return;
- }
-
- HTTPDataStream(context->url, context->op, context->bodyData, context->headerFieldName, context->headerFieldValue,
- context->authentication, credentials, context->callback, &context->cbcontext);
-
- if (credentials) CFRelease(credentials);
-
- // Cancel the old one
- CancelHTTPDataStream(stream, context);
- }
-
-mDNSlocal void HTTPDataStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *info)
- {
- HTTPDataStreamContext *context = (HTTPDataStreamContext *)info;
- CFIndex status;
-
- status = HTTPResponseCode(stream);
-
- // if we are forbidden to access, we need to refetch the configuration file.
- // For keeping it simple, we don't retry immediately. When the next message
- // is logged, we will try getting the config file. If we want to modify this
- // in the future to retry now, then we need to know to stop retrying after a
- // few times.
- if ((status == kHTTPResponseCodeNotFound) || (status == kHTTPResponseCodeForbidden))
- {
- if (status == kHTTPResponseCodeNotFound)
- LogMsg("HTTPDataStreamCallback: ERROR!! Config plist cannot be found");
- else if (status == kHTTPResponseCodeForbidden)
- LogInfo("HTTPDataStreamCallback: Config plist Forbidden by server");
- if (context->callback) context->callback(context->responseData, &context->cbcontext);
- CancelHTTPDataStream(stream, context);
- return;
- }
-
- switch (type)
- {
- case kCFStreamEventHasBytesAvailable:
- {
- mDNSu8 buffer[kReadStreamBufferSize];
- CFIndex bytesRead;
-
- if (!context->authChecked)
- {
- context->authChecked = mDNStrue;
- if (status == kHTTPResponseCodeAuthFailure)
- {
- RetryWithHTTPAuth(context, stream);
- return;
- }
- }
-
- bytesRead = CFReadStreamRead(stream, buffer, sizeof(buffer));
- if (bytesRead > 0)
- {
- CFDataAppendBytes(context->responseData, buffer, bytesRead);
- if (CFDataGetLength(context->responseData) > kMaximumResponseSize)
- {
- LogMsg("HTTPDataStreamCallback: ERROR!! Appended max data %d", kMaximumResponseSize);
- }
- else { LogInfo("HTTPDataStreamCallback: successfully appended data of size %ld", bytesRead); return; }
- }
- else if (bytesRead < 0)
- {
- LogMsg("HTTPDataStreamCallback: ERROR!! CFReadStreamRead returned %ld", bytesRead);
- }
- }
- break;
- case kCFStreamEventEndEncountered:
- {
- if (!context->authChecked)
- {
- context->authChecked = mDNStrue;
- if (status == kHTTPResponseCodeAuthFailure)
- {
- RetryWithHTTPAuth(context, stream);
- return;
- }
- }
- if (status != kHTTPResponseCodeOK)
- LogMsg("HTTPDataStreamCallback: ERROR!! EndEncountered, statusCode %d, Operation %d", status, context->op);
- else
- LogInfo("HTTPDataStreamCallback: HTTP Ok for Operation %d", context->op);
- if (context->callback) context->callback(context->responseData, &context->cbcontext);
- }
- break;
- case kCFStreamEventErrorOccurred:
- LogInfo("HTTPDataStreamCallback: ERROR!! kCFStreamEventErrorOccurred for Operation %d", context->op);
- if (context->callback) context->callback(context->responseData, &context->cbcontext);
- break;
- default:
- LogMsg("HTTPDataStreamCallback: ERROR!! default case");
- if (context->callback) context->callback(context->responseData, &context->cbcontext);
- break;
- }
- CancelHTTPDataStream(stream, context);
-}
-
-// Everything needs to be copied or retained locally if need to be accessed beyond function scope
-mDNSlocal void HTTPDataStream(CFStringRef url, HTTPOperation op, CFDataRef bodyData, CFStringRef headerFieldName,
- CFStringRef headerFieldValue, CFHTTPAuthenticationRef authentication, CFMutableDictionaryRef credentials,
- HTTPClientCallback callback, ELogContext *cbcontext)
- {
- CFURLRef myURL = NULL;
- CFHTTPMessageRef myRequest = NULL;
- CFReadStreamRef readStream = NULL;
- HTTPDataStreamContext *contextInfo = NULL;
- CFDictionaryRef proxyDict = NULL;
-
- contextInfo = mallocL("HTTPDataStreamContext", sizeof(HTTPDataStreamContext));
- if (!contextInfo) { LogMsg("HTTPDataStream: mallocL failure"); return; }
-
- mDNSPlatformMemZero(contextInfo, sizeof(*contextInfo));
- // Need to remember the state, so that if we need to retry with authentication, we can
- // reissue the request
- contextInfo->url = CFRetain(url);
- contextInfo->callback = callback;
- if(cbcontext) memcpy(&contextInfo->cbcontext, cbcontext, sizeof(ELogContext));
- contextInfo->authChecked = mDNSfalse;
- contextInfo->op = op;
- if (authentication) contextInfo->authentication = (CFHTTPAuthenticationRef) CFRetain(authentication);
- if (headerFieldName) contextInfo->headerFieldName = CFRetain(headerFieldName);
- if (headerFieldValue) contextInfo->headerFieldValue = CFRetain(headerFieldValue);
- if (bodyData) contextInfo->bodyData = CFRetain(bodyData);
-
- myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
- if (!myURL) { LogMsg("HTTPDataStream: CFURLCreateWithString error"); goto cleanup; }
-
- CFStringRef requestMethod = op == HTTPGet ? CFSTR("GET") : CFSTR("POST");
- myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
- if (!myRequest) { LogMsg("HTTPDataStream: CFHTTPMessageCreateRequest error"); goto cleanup; }
-
- if (bodyData) CFHTTPMessageSetBody(myRequest, bodyData);
- if (headerFieldName) CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);
-
- if (credentials)
- {
- if (!CFHTTPMessageApplyCredentialDictionary(myRequest, contextInfo->authentication, credentials, NULL))
- {
- LogMsg("HTTPDataStream: ERROR!! CFHTTPMessageApplyCredentialDictionary error");
- goto cleanup;
- }
- }
-
- readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
- if (!readStream) { LogMsg("HTTPDataStream: CFStringCreateWithBytes error"); goto cleanup; }
-
- proxyDict = SCDynamicStoreCopyProxies(NULL);
- if (proxyDict)
- {
- mDNSBool ret = CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPProxy, proxyDict);
- CFRelease(proxyDict);
- if (!ret)
- {
- LogMsg("HTTPDataStream: CFReadStreamSetProperty HTTP proxy failed");
- goto cleanup;
- }
- }
-
- CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
-
- CFStreamClientContext readContext = {0, contextInfo, NULL, NULL, NULL};
- CFReadStreamSetClient(readStream, events, HTTPDataStreamCallback, &readContext);
- CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetMain(), kCFRunLoopCommonModes);
- if (CFReadStreamOpen(readStream))
- {
- contextInfo->responseData = CFDataCreateMutable(NULL, 0);
- if (contextInfo->responseData)
- {
- // Release the things that we don't need
- CFRelease(myURL);
- CFRelease(myRequest);
- return;
- }
- LogMsg("HTTPDataStream: ERROR!! responseData allocation failed");
- }
- else LogMsg("HTTPDataStream: ERROR!! CFReadStreamOpen failed");
-cleanup:
- if (readStream) CancelReadStream(readStream);
- if (myRequest) CFRelease(myRequest);
- if (myURL) CFRelease(myURL);
- if (contextInfo)
- {
- if (contextInfo->authentication) CFRelease(contextInfo->authentication);
- if (contextInfo->headerFieldName) CFRelease(contextInfo->headerFieldName);
- if (contextInfo->headerFieldValue) CFRelease(contextInfo->headerFieldValue);
- if (contextInfo->bodyData) CFRelease(contextInfo->bodyData);
- if (contextInfo->url) CFRelease(contextInfo->url);
- freeL("HTTPDataStreamContext", contextInfo);
- }
- }
-
-mDNSlocal CFStringRef eReporterGetValueForKey(CFDictionaryRef dict, char *keyCString)
- {
- CFStringRef value;
- CFStringRef key;
-
- key = CFStringCreateWithCString(NULL, keyCString, kCFStringEncodingUTF8);
- if (!CFDictionaryContainsKey(dict, key))
- {
- LogMsg("eReporterGetValueForKey: ERROR!! key %s not found", keyCString);
- return NULL;
- }
- value = (CFStringRef)CFDictionaryGetValue(dict, key);
- CFRelease(key);
- if (!value)
- {
- LogMsg("eReporterGetValueForKey: ERROR!! value not found for %s", keyCString);
- return NULL;
- }
- return value;
- }
-
-mDNSlocal void eReporterConfigCallback(CFMutableDataRef responseData, ELogContext *context)
- {
- CFDictionaryRef dict = NULL;
- char *plistKeys[] = {"URL", "Publish", "LoadText", "URI", NULL};
- int i;
- CFErrorRef error;
-
- if (!CFDataGetLength(responseData))
- {
- LogInfo("eReporterConfigCallback: Zero length data");
- eReporterConfig.eRState = ConfigInvalid;
- return;
- }
- CFPropertyListFormat format = kCFPropertyListXMLFormat_v1_0;
- dict = CFPropertyListCreateWithData(0, responseData, kCFPropertyListImmutable, &format, &error);
- if ( dict == NULL )
- {
- LogMsg("eReporterConfigCallback: Parsing property list failed");
- eReporterConfig.eRState = ConfigInvalid;
- CFRelease(error);
- return;
- }
- i = 0;
- while (plistKeys[i] != NULL)
- {
- if (eReporterGetValueForKey(dict, plistKeys[i]) == NULL)
- {
- LogMsg("eReporterConfigCallback: ERROR!! problem accessing key %s", plistKeys[i]);
- CFRelease(dict);
- eReporterConfig.eRState = ConfigInvalid;
- return;
- }
- i++;
- }
- if (eReporterConfig.eRDict) CFRelease(eReporterConfig.eRDict);
- eReporterConfig.eRDict = dict;
- eReporterConfig.eRState = ConfigValid;
- mDNSReporterLogValidConfig(context);
- }
-
-mDNSlocal mDNSBool FetchEReporterConfiguration(ELogContext *context)
- {
- const char *urlString = "https://configuration.apple.com./configurations/internetservices/e3/mDNSResponder/Configurations1.0.plist";
- //const char *urlString = "http://isdev02:9702/configuration/configurations/internetservices/e3/btmm/Configurations1.0.plist"; //dev server
-
- CFStringRef url = CFStringCreateWithBytes(NULL, (const mDNSu8 *)urlString, strlen(urlString), kCFStringEncodingASCII, false);
- if (!url) { LogMsg("FetchEReporterConfiguration: CFStringCreateWithBytes error"); return mDNSfalse; }
-
- if (eReporterConfig.eRState == ConfigValid || eReporterConfig.eRState == ConfigFetching)
- {
- CFRelease(url);
- return mDNSfalse;
- }
-
- eReporterConfig.eRState = ConfigFetching;
- HTTPDataStream(url, HTTPGet, NULL, NULL, NULL, NULL, NULL, eReporterConfigCallback, context);
- CFRelease(url);
- return mDNStrue;
- }
-
-// Builds an element of type : <key name="nameAttr"> value </key> and attaches it to
-// xmlTree
-mDNSlocal mDNSBool AddElementToTree(CFXMLTreeRef xmlTree, char *nameAttr, char *value)
- {
- /* <key name="BTMM domain"> domain </key> */
-
- CFStringRef textval = CFStringCreateWithCString(NULL, value, kCFStringEncodingUTF8);
- if (!textval) { LogMsg("AddElementToTree: cannot create CString for value %s", value); return mDNSfalse; }
-
- CFStringRef keys[1] = { CFSTR("name") };
- CFStringRef values[1] = { CFStringCreateWithCString(NULL, nameAttr, kCFStringEncodingUTF8) };
-
- CFDictionaryRef dict = CFDictionaryCreate(NULL, (void*)keys, (void*)values, 1, &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- if (!dict)
- {
- LogMsg("AddElementToTree: ERROR!! CFDictionaryCreate failed for %s", nameAttr);
- CFRelease(textval);
- CFRelease(values[0]);
- return mDNSfalse;
- }
-
- CFMutableArrayRef attr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- if (!attr)
- {
- LogMsg("AddElementToTree: ERROR!! CFArrayCreateMutable failed for %s", nameAttr);
- CFRelease(textval);
- CFRelease(dict);
- CFRelease(values[0]);
- return mDNSfalse;
- }
-
- CFArrayAppendValue(attr, keys[0]);
-
- /* Build <key name="nameAttr"> */
-
- CFXMLElementInfo nameInfo;
- nameInfo.attributes = (CFDictionaryRef)dict;
- nameInfo.attributeOrder = (CFArrayRef) attr;
- nameInfo.isEmpty = mDNSfalse;
- CFXMLNodeRef nameNode = CFXMLNodeCreate(kCFAllocatorDefault, kCFXMLNodeTypeElement, CFSTR("key"), &nameInfo,
- kCFXMLNodeCurrentVersion);
- CFXMLTreeRef nameTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, nameNode);
- CFTreeAppendChild(xmlTree, nameTree);
- CFRelease(nameNode);
- CFRelease(attr);
- CFRelease(dict);
- CFRelease(values[0]);
-
- /* Build the rest: value </key> */
-
- CFXMLNodeRef nameTextNode = CFXMLNodeCreate(kCFAllocatorDefault, kCFXMLNodeTypeText, textval, NULL,
- kCFXMLNodeCurrentVersion);
- CFXMLTreeRef nameTextTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, nameTextNode);
- CFTreeAppendChild(nameTree, nameTextTree);
- CFRelease(nameTextTree);
- CFRelease(nameTextNode);
- CFRelease(textval);
-
- // Now that we are done with nameTree, we can release it
- CFRelease(nameTree);
-
- return mDNStrue;
- }
-
-mDNSlocal void LogPOSTArgs(CFStringRef finalURL, CFStringRef LoadTextName, CFStringRef LoadTextValue, CFDataRef bodyData)
- {
- char buf1[128], buf2[64], buf3[64], buf4[1024];
-
- if (!CFStringGetCString(finalURL, buf1, sizeof(buf1), kCFStringEncodingUTF8) ||
- !CFStringGetCString(LoadTextName, buf2, sizeof(buf2), kCFStringEncodingUTF8) ||
- !CFStringGetCString(LoadTextValue, buf3, sizeof(buf3), kCFStringEncodingUTF8))
- {
- LogMsg("mDNSEReportPOSTArgs: Error in parsing arguments");
- return;
- }
- CFStringRef bstr = CFStringCreateFromExternalRepresentation(NULL, bodyData, kCFStringEncodingUTF8);
- buf4[0] = 0;
- if (!CFStringGetCString(bstr, buf4, sizeof(buf4), kCFStringEncodingUTF8))
- {
- LogMsg("mDNSEReportPOSTArgs: buf4 cstring conversion problem");
- }
- if (bstr) CFRelease(bstr);
- LogInfo("LogPOSTArgs: URL : %s, LoadTextName: %s, LoadTextValue: %s, bodyData %s", buf1, buf2, buf3, buf4);
- }
-
-// This function is called when there is a valid configuration for eReporter service
-// We add the following:
-//
-// <key name="uuid"> uuid </key>
-// <key name="Subdomain"> subdomain </key>
-// <key name="Message"> message </key>
-// <key name="Time"> YYYY-MM-DD HH24:MI:SS </key>
-// <key name="SPS"> True/False </key>
-// <key name="Result"> Success/Fail </key>
-//
-// if result is -1, result won't be added. 1 means "Failed" and 0 means "Success"
-//
-mDNSlocal void mDNSReporterLogValidConfig(ELogContext *elog)
- {
- CFMutableStringRef finalURL = NULL;
- CFStringRef LoadTextName = NULL;
- CFDataRef bodyData = NULL;
- CFBooleanRef pub;
- CFXMLTreeRef appTree = NULL;
-
- pub = (CFBooleanRef)eReporterGetValueForKey(eReporterConfig.eRDict, "Publish");
- if (pub == NULL)
- {
- LogMsg("mDNSReporterLogValidConfig: Publish key does not exist");
- return;
- }
-
- Boolean pubVal = CFBooleanGetValue(pub);
- if (!pubVal)
- {
- // Set the config state to invalid so that we will refetch the configuration next time
- // in case Publish value changes between now and then
- eReporterConfig.eRState = ConfigInvalid;
- LogInfo("mDNSReporterLogValidConfig: Value for Publish is %d", pubVal);
- return;
- }
-
- CFXMLDocumentInfo documentInfo;
- documentInfo.sourceURL = NULL;
- documentInfo.encoding = kCFStringEncodingUTF8;
- CFXMLNodeRef docNode = CFXMLNodeCreate( kCFAllocatorDefault, kCFXMLNodeTypeDocument, CFSTR(""), &documentInfo,
- kCFXMLNodeCurrentVersion);
- CFXMLTreeRef xmlDocument = CFXMLTreeCreateWithNode(kCFAllocatorDefault, docNode);
- CFRelease(docNode);
-
- /* <?xml version="1.0" encoding="utf-8"?> */
- CFXMLProcessingInstructionInfo instructionInfo;
- instructionInfo.dataString = CFSTR("version=\"1.0\" encoding=\"utf-8\"");
- CFXMLNodeRef instructionNode = CFXMLNodeCreate(NULL, kCFXMLNodeTypeProcessingInstruction, CFSTR("xml"),
- &instructionInfo, kCFXMLNodeCurrentVersion);
- CFXMLTreeRef instructionTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, instructionNode);
- CFTreeAppendChild(xmlDocument, instructionTree);
- CFRelease(instructionTree);
- CFRelease(instructionNode);
-
- /* Root Element: <app name="mDNSResponder" version="XXX"> */
-
- CFStringRef appKeys[2] = { CFSTR("name"), CFSTR("version") };
- CFStringRef appValues[2] = { CFStringCreateWithCString(NULL, "mDNSResponder", kCFStringEncodingUTF8),
- CFStringCreateWithCString(NULL, STRINGIFY(mDNSResponderVersion), kCFStringEncodingUTF8) };
-
- CFDictionaryRef appDict = CFDictionaryCreate(NULL, (void*)appKeys, (void*)appValues, 2, &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- if (!appDict) { LogMsg("mDNSEReporterLogValidConfig: CFDictionaryCreate App failed"); goto cleanup; }
-
- CFMutableArrayRef appAttr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- if (!appAttr) { LogMsg("mDNSEReporterLogValidConfig: CFArrayCreateMutable App failed"); goto cleanup; }
-
- CFArrayAppendValue(appAttr, appKeys[0]);
- CFArrayAppendValue(appAttr, appKeys[1]);
-
- CFXMLElementInfo appInfo;
- appInfo.attributes = (CFDictionaryRef) appDict;
- appInfo.attributeOrder = (CFArrayRef) appAttr;
- appInfo.isEmpty = mDNSfalse;
- CFXMLNodeRef appNode = CFXMLNodeCreate ( kCFAllocatorDefault, kCFXMLNodeTypeElement, CFSTR("app"), &appInfo,
- kCFXMLNodeCurrentVersion);
- appTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, appNode);
- CFTreeAppendChild(xmlDocument, appTree);
- CFRelease(appNode);
- CFRelease(appAttr);
- CFRelease(appDict);
- CFRelease(appValues[0]);
- CFRelease(appValues[1]);
- // appTree will be released at the end as we will be appeneding other nodes to appTree below
-
- char uuidStr[37];
- uuid_unparse(elog->uuid, uuidStr);
- AddElementToTree(appTree, "UUID", uuidStr);
-
- AddElementToTree(appTree, "Subdomain", elog->subdomain);
- AddElementToTree(appTree, "Message", elog->message);
-
- char tm_buffer[128];
- time_t t = time(NULL);
- struct tm *tm_t = gmtime(&t);
- mDNS_snprintf(tm_buffer, sizeof(tm_buffer), "%4d-%02d-%02d %02d:%02d:%02d", tm_t->tm_year + 1900, tm_t->tm_mon + 1,
- tm_t->tm_mday, tm_t->tm_hour, tm_t->tm_min, tm_t->tm_sec);
- AddElementToTree(appTree, "Time", tm_buffer);
-
- const CacheRecord *sps[3] = { mDNSNULL };
- NetworkInterfaceInfo *intf;
- mDNSBool SleepProxy = mDNSfalse;
- for (intf = GetFirstActiveInterface(mDNSStorage.HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
- {
- if (intf->NetWake)
- {
- FindSPSInCache(&mDNSStorage, &intf->NetWakeBrowse, sps);
- if (sps[0])
- {
- SleepProxy = mDNStrue;
- break;
- }
- }
- else { LogInfo("mDNSEReporterValidConfig: NetWake is not set %p", intf->InterfaceID); }
- }
- AddElementToTree(appTree, "SPS", (SleepProxy ? "True" : "False"));
-
- if (elog->result != -1)
- AddElementToTree(appTree, "Result", elog->result ? "fail" : "success");
-
- bodyData = CFXMLTreeCreateXMLData(NULL, xmlDocument);
- if (!bodyData) { LogMsg("mDNSEReporterLogValidConfig: CFXMLTreeCreateData failed for bodyData"); goto cleanup; }
-
- CFStringRef url = eReporterGetValueForKey(eReporterConfig.eRDict, "URL");
- if (!url) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for URL"); goto cleanup; }
-
- CFStringRef uri = eReporterGetValueForKey(eReporterConfig.eRDict, "URI");
- if (!uri) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for URI"); goto cleanup; }
-
- finalURL = CFStringCreateMutable(NULL, 0);
- if (!finalURL) { LogMsg("mDNSEReporterLogValidConfig: CFStringCreateMutable failed for finalURL"); goto cleanup; }
-
- CFStringAppend(finalURL, url);
- CFStringAppend(finalURL, uri);
-
- LoadTextName = CFStringCreateWithCString(NULL, "x-LoadText", kCFStringEncodingUTF8);
- if (!LoadTextName) { LogMsg("mDNSEReporterLogValidConfig: CFStringCreateWithCString failed for LoadText"); goto cleanup; }
-
- CFStringRef LoadTextValue = eReporterGetValueForKey(eReporterConfig.eRDict, "LoadText");
- if (!LoadTextValue) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for LoadTextValue"); goto cleanup; }
-
- LogPOSTArgs(finalURL, LoadTextName, LoadTextValue, bodyData);
-
- // we don't have a callback for the POST. If there is an error in POST, it will be logged
- // by the callback of HTTPDataStream
- HTTPDataStream(finalURL, HTTPPost, bodyData, LoadTextName, LoadTextValue, NULL, NULL, NULL, NULL);
-
-cleanup:
- // Free whatever was allocated in this function
- if (bodyData) CFRelease(bodyData);
- if (finalURL) CFRelease(finalURL);
- if (LoadTextName) CFRelease(LoadTextName);
- if (appTree) CFRelease(appTree);
- CFRelease(xmlDocument);
- }
-
-mDNSlocal void mDNSEReporterLog(uuid_t *uuid, const char *subdomain, int result, char *message)
- {
- // We allocate ELogContext and free it at the end of the function. It is the
- // responsibility of the called function to copy it if it needs to hold
- // on to it
- ELogContext *info = mallocL("ELogContext", sizeof (ELogContext));
- if (!info) { LogMsg("mDNSEReporterLog: malloc failed"); return; }
-
- // Take a local copy of all the log information
- strlcpy(info->subdomain, subdomain, sizeof(info->subdomain));
- strlcpy(info->message, message, sizeof(info->message));
- info->result = result;
- uuid_copy(info->uuid, *uuid);
- if (eReporterConfig.eRState != ConfigValid)
- {
- // Currently we can't have two outstanding configuration fetches. If we have two quick
- // back to back logs while the configuration is being fetched, we log only the first
- // message to EReporter. If the configuration is valid (common case), then we don't
- // drop any messages
- if (!FetchEReporterConfiguration(info))
- {
- LogInfo("mDNSEReporterLog: Configuration being fetched.., Not logging");
- }
- freeL("ELogContext", info);
- return;
- }
- mDNSReporterLogValidConfig(info);
- freeL("ELogContext", info);
- }
-
#ifndef NO_SECURITYFRAMEWORK
static CFMutableDictionaryRef domainStatusDict = NULL;
}
}
- // If we have a relay address, check the LLQ status as they don't go over the relay connection.
- // If LLQs fail, then report failure. In future, when LLQs go over the relay connection, we don't
- // need this logic
- if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ // If we have a relay address which lets other hosts to reach us through the relay, then we should
+ // report success except for the LLQs they don't go over the relay connection. If LLQs fail, then
+ // report failure. In future, when LLQs go over the relay connection, we don't need this logic
+ if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddrIn))
{
// If we have a bad signature error updating RR, it overrides any error as
// the user needs to be notified immediately
static char statusBuf[16];
mDNS_snprintf(statusBuf, sizeof(statusBuf), "%d", (int)status);
mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status ? "failure" : "success", statusBuf, "");
- mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status, statusBuf);
mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
}
}
CFRelease(domain);
CFRelease(dict);
-
debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
#endif // def NO_SECURITYFRAMEWORK
}
DomainAuthInfo *info;
for (info = m->AuthInfoList; info; info = info->next)
- if (info->AutoTunnel && !info->deltime && (!mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) || !mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr)))
+ if (info->AutoTunnel && !info->deltime && (!mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) || !mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddrIn)))
break;
if (info != AnonymousRacoonConfig)
NATProblem = mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) || info->AutoTunnelNAT.Result;
- if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddrIn))
{
// If we don't have a relay address, check to see if we are behind a Double NAT or NAT with no NAT-PMP
// support.
// change, so check to see if the value has changed. This can also be zero when we are deregistering and
// getting called from the AutoTunnelRecordCallback
- if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddrIn))
{
LogInfo("RegisterAutoTunnel6Record: Relay address is zero, not registering");
return;
}
if ((info->AutoTunnel6Record.resrec.RecordType > kDNSRecordTypeDeregistering) &&
- (mDNSSameIPv6Address(info->AutoTunnel6Record.resrec.rdata->u.ipv6, m->AutoTunnelRelayAddr)))
+ (mDNSSameIPv6Address(info->AutoTunnel6Record.resrec.rdata->u.ipv6, m->AutoTunnelRelayAddrIn)))
{
- LogInfo("RegisterAutoTunnel6Record: Relay address %.16a same, not registering", &m->AutoTunnelRelayAddr);
+ LogInfo("RegisterAutoTunnel6Record: Relay address %.16a same, not registering", &m->AutoTunnelRelayAddrIn);
return;
}
AssignDomainName (&info->AutoTunnel6Record.namestorage, (const domainname*) "\x0C" "_autotunnel6");
AppendDomainLabel(&info->AutoTunnel6Record.namestorage, &m->hostlabel);
AppendDomainName (&info->AutoTunnel6Record.namestorage, &info->domain);
- info->AutoTunnel6Record.resrec.rdata->u.ipv6 = m->AutoTunnelRelayAddr;
+ info->AutoTunnel6Record.resrec.rdata->u.ipv6 = m->AutoTunnelRelayAddrIn;
info->AutoTunnel6Record.resrec.RecordType = kDNSRecordTypeKnownUnique;
err = mDNS_Register_internal(m, &info->AutoTunnel6Record);
else LogInfo("RegisterAutoTunnel6Record registering AutoTunnel6 Record %##s", info->AutoTunnel6Record.namestorage.c);
LogInfo("AutoTunnel6 server listening for connections on %##s[%.16a] :%##s[%.16a]",
- info->AutoTunnel6Record.namestorage.c, &m->AutoTunnelRelayAddr,
+ info->AutoTunnel6Record.namestorage.c, &m->AutoTunnelRelayAddrIn,
info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
- } else {LogInfo("RegisterAutoTunnel6Record: client context %p, RequestedPort %d, Address %.16a, record type %d", info->AutoTunnelNAT.clientContext, info->AutoTunnelNAT.RequestedPort, &m->AutoTunnelRelayAddr, info->AutoTunnel6Record.resrec.RecordType);}
+ } else {LogInfo("RegisterAutoTunnel6Record: client context %p, RequestedPort %d, Address %.16a, record type %d", info->AutoTunnelNAT.clientContext, info->AutoTunnelNAT.RequestedPort, &m->AutoTunnelRelayAddrIn, info->AutoTunnel6Record.resrec.RecordType);}
RegisterAutoTunnelHostRecord(m, info);
// When the AutoTunnel6 record comes up, we need to kick racoon and update the status.
{
LogInfo("TunnelClientFinish: Relay address %.16a", &answer->rdata->u.ipv6);
tun->rmt_outer6 = answer->rdata->u.ipv6;
- tun->loc_outer6 = m->AutoTunnelRelayAddr;
+ tun->loc_outer6 = m->AutoTunnelRelayAddrOut;
}
else
{
mStatus result = needSetKeys ? AutoTunnelSetKeys(tun, mDNStrue) : mStatus_NoError;
static char msgbuf[32];
- mDNS_snprintf(msgbuf, sizeof(msgbuf), "Client AutoTunnel setup - %d", result);
+ mDNS_snprintf(msgbuf, sizeof(msgbuf), "Tunnel setup - %d", result);
mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result ? "failure" : "success", msgbuf, "");
- mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result, msgbuf);
// Kick off any questions that were held pending this tunnel setup
ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
}
static char msgbuf[16];
mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s lookup", DNSTypeName(question->qtype));
mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", "failure", msgbuf, "");
- mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.config", 1, msgbuf);
UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
return;
}
}
tun->rmt_inner = answer->rdata->u.ipv6;
LogInfo("AutoTunnelCallback:TC_STATE_AAAA_PEER: dst host %.16a", &tun->rmt_inner);
- if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddrOut))
{
LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA");
tun->tc_state = TC_STATE_AAAA_PEER_RELAY;
// Set the address to zero before calling DeregisterAutoTunnel6Record. If we call
// Deregister too quickly before the previous Register completed (just scheduled
// to be sent out) and when DeregisterAutoTunnel6Record calls mDNS_Register_internal,
- // it invokes the AutoTunnelRecordCallback immediately and AutoTunnelRelayAddr should
+ // it invokes the AutoTunnelRecordCallback immediately and AutoTunnelRelayAddrIn should
// be zero so that we don't register again.
- m->AutoTunnelRelayAddr = zerov6Addr;
+ m->AutoTunnelRelayAddrIn = zerov6Addr;
if (!m->AuthInfoList) LogInfo("RemoveAutoTunnel6Record: No Domain AuthInfo");
for (info = m->AuthInfoList; info; info = info->next)
{
return;
}
- m->AutoTunnelRelayAddr = v6addr;
+ m->AutoTunnelRelayAddrOut = v6addr;
+
+ // if disabled administratively, don't bother to register. RegisterAutoTunnel6Record makes these same
+ // checks, but we do it here not just as an optimization but mainly to keep AutoTunnelRelayAddrIn zero
+ // as a non-zero AutoTunnelRelayAddrIn indicates that we have registered _autotunnel6 record and hence
+ // other hosts can connect to this host through the relay
+ if (!m->RegisterAutoTunnel6 || DisableInboundRelayConnection)
+ {
+ LogInfo("RegisterAutoTunnel6Record: registration Disabled RegisterAutoTunnel6 %d, DisableInbound %d",
+ m->RegisterAutoTunnel6, DisableInboundRelayConnection);
+ return;
+ }
+ m->AutoTunnelRelayAddrIn = v6addr;
if (!m->AuthInfoList) LogInfo("AddAutoTunnel6Record: No Domain AuthInfo");
for (info = m->AuthInfoList; info; info = info->next)
{
LogInfo("ParseBackToMyMac: CFDictionaryGetValue No value for BackToMyMac, Removing autotunnel6");
RemoveAutoTunnel6Record(m);
+ // Note: AutoTunnelRelayAddrIn is zeroed out in RemoveAutoTunnel6Record as it is called
+ // from other places.
+ m->AutoTunnelRelayAddrOut = zerov6Addr;
return;
}
{
LogInfo("ParseBackToMyMac: NULL value for Interface, Removing autotunnel6");
RemoveAutoTunnel6Record(m);
+ m->AutoTunnelRelayAddrOut = zerov6Addr;
// We don't have a utun interface, start the relay connection if possible
UpdateBTMMRelayConnection(m);
}
else
{
if (!mDNSSameIPv6Address(p->loc_inner, m->AutoTunnelHostAddr) ||
- !mDNSSameIPv6Address(p->loc_outer6, m->AutoTunnelRelayAddr))
+ !mDNSSameIPv6Address(p->loc_outer6, m->AutoTunnelRelayAddrOut))
{
AutoTunnelSetKeys(p, mDNSfalse);
p->loc_inner = m->AutoTunnelHostAddr;
- p->loc_outer6 = m->AutoTunnelRelayAddr;
+ p->loc_outer6 = m->AutoTunnelRelayAddrOut;
AutoTunnelSetKeys(p, mDNStrue);
}
}
msg.k.event_code == KEV_DL_LINK_ADDRESS_CHANGED ? "KEV_DL_LINK_ADDRESS_CHANGED" :
msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED ? "KEV_DL_WAKEFLAGS_CHANGED" : "?");
- if (msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED) SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+ // We receive network change notifications both through configd and through SYSPROTO_EVENT socket.
+ // Configd may not generate network change events for manually configured interfaces (i.e., non-DHCP)
+ // always during sleep/wakeup due to some race conditions (See radar:8666757). At the same time, if
+ // "Wake on Network Access" is not turned on, the notification will not have KEV_DL_WAKEFLAGS_CHANGED.
+ // Hence, during wake up, if we see a KEV_DL_LINK_ON (i.e., link is UP), we trigger a network change.
+
+ if (msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED || msg.k.event_code == KEV_DL_LINK_ON)
+ SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
}
mDNS_Unlock(m);
#endif
m->AutoTunnelHostAddr.b[0] = 0; // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
- m->AutoTunnelRelayAddr = zerov6Addr;
+ m->AutoTunnelRelayAddrIn = zerov6Addr;
+ m->AutoTunnelRelayAddrOut = zerov6Addr;
NetworkChangedKey_IPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
NetworkChangedKey_IPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);