2 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
28 #include "DNSCommon.h"
33 typedef struct SearchListElem
35 struct SearchListElem
*next
;
39 DNSQuestion DefBrowseQ
;
40 DNSQuestion LegacyBrowseQ
;
41 DNSQuestion RegisterQ
;
42 DNSQuestion DefRegisterQ
;
45 // for domain enumeration and default browsing/registration
46 static SearchListElem
*SearchList
= mDNSNULL
; // where we search for _browse domains
47 static DNSQuestion LegacyBrowseDomainQ
; // our local enumeration query for _legacy._browse domains
48 static DNameListElem
*DefBrowseList
= mDNSNULL
; // cache of answers to above query (where we search for empty string browses)
49 static DNameListElem
*DefRegList
= mDNSNULL
; // manually generated list of domains where we register for empty string registrations
50 static ARListElem
*SCPrefBrowseDomains
= mDNSNULL
; // manually generated local-only PTR records for browse domains we get from SCPreferences
52 static domainname dDNSRegDomain
; // Default wide-area zone for service registration
53 static domainname dDNSBrowseDomain
; // Default wide-area zone for legacy ("empty string") browses
54 static domainname dDNSHostname
;
57 mStatus
dDNS_SetupAddr(mDNSAddr
*ip
, const struct sockaddr
*const sa
)
59 if (!sa
) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid
); }
61 if (sa
->sa_family
== AF_INET
)
63 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)sa
;
64 ip
->type
= mDNSAddrType_IPv4
;
65 ip
->ip
.v4
.NotAnInteger
= ifa_addr
->sin_addr
.s_addr
;
66 return(mStatus_NoError
);
69 if (sa
->sa_family
== AF_INET6
)
71 struct sockaddr_in6
*ifa_addr
= (struct sockaddr_in6
*)sa
;
72 ip
->type
= mDNSAddrType_IPv6
;
74 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0;
76 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.u
.Word
[1] = 0;
78 ip
->ip
.v6
= *(mDNSv6Addr
*)&ifa_addr
->sin6_addr
;
79 return(mStatus_NoError
);
82 LogMsg("SetupAddr invalid sa_family %d", sa
->sa_family
);
83 return(mStatus_Invalid
);
86 mDNSlocal
void MarkSearchListElem(domainname
*domain
)
88 SearchListElem
*new, *ptr
;
90 // if domain is in list, mark as pre-existent (0)
91 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
)
92 if (SameDomainName(&ptr
->domain
, domain
))
94 if (ptr
->flag
!= 1) ptr
->flag
= 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
98 // if domain not in list, add to list, mark as add (1)
101 new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem
));
102 if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
103 bzero(new, sizeof(SearchListElem
));
104 AssignDomainName(&new->domain
, domain
);
105 new->flag
= 1; // add
106 new->next
= SearchList
;
111 //!!!KRS here is where we will give success/failure notification to the UI
112 mDNSlocal
void SCPrefsdDNSCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
115 debugf("SCPrefsdDNSCallback: result %d for registration of name %##s", result
, rr
->resrec
.name
->c
);
116 dDNSPlatformSetNameStatus(rr
->resrec
.name
, result
);
119 mDNSlocal
void FreeARElemCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
121 ARListElem
*elem
= rr
->RecordContext
;
125 if (result
== mStatus_MemFree
) freeL("FreeARElemCallback", elem
);
128 mDNSlocal
void FoundDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
130 SearchListElem
*slElem
= question
->QuestionContext
;
131 ARListElem
*arElem
, *ptr
, *prev
;
138 arElem
= mallocL("FoundDomain - arElem", sizeof(ARListElem
));
139 if (!arElem
) { LogMsg("ERROR: malloc"); return; }
140 mDNS_SetupResourceRecord(&arElem
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, arElem
);
141 if (question
== &slElem
->BrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowse
];
142 else if (question
== &slElem
->DefBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseDefault
];
143 else if (question
== &slElem
->LegacyBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseLegacy
];
144 else if (question
== &slElem
->RegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
];
145 else if (question
== &slElem
->DefRegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistrationDefault
];
146 else { LogMsg("FoundDomain - unknown question"); return; }
148 MakeDomainNameFromDNSNameString(arElem
->ar
.resrec
.name
, name
);
149 AppendDNSNameString (arElem
->ar
.resrec
.name
, "local");
150 AssignDomainName(&arElem
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
);
151 err
= mDNS_Register(m
, &arElem
->ar
);
154 LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err
);
155 freeL("FoundDomain - arElem", arElem
);
158 arElem
->next
= slElem
->AuthRecs
;
159 slElem
->AuthRecs
= arElem
;
163 ptr
= slElem
->AuthRecs
;
167 if (SameDomainName(&ptr
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
))
169 debugf("Deregistering PTR %s -> %s", ptr
->ar
.resrec
.name
->c
, ptr
->ar
.resrec
.rdata
->u
.name
.c
);
171 if (prev
) prev
->next
= ptr
->next
;
172 else slElem
->AuthRecs
= ptr
->next
;
174 err
= mDNS_Deregister(m
, dereg
);
175 if (err
) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err
);
186 mDNSexport DNameListElem
*mDNSPlatformGetSearchDomainList(void)
188 return mDNS_CopyDNameList(DefBrowseList
);
191 mDNSexport DNameListElem
*mDNSPlatformGetRegDomainList(void)
193 return mDNS_CopyDNameList(DefRegList
);
196 mDNSlocal
void AddDefRegDomain(domainname
*d
)
198 DNameListElem
*newelem
= NULL
, *ptr
;
200 // make sure name not already in list
201 for (ptr
= DefRegList
; ptr
; ptr
= ptr
->next
)
203 if (SameDomainName(&ptr
->name
, d
))
204 { debugf("duplicate addition of default reg domain %##s", d
->c
); return; }
207 newelem
= mallocL("DNameListElem", sizeof(*newelem
));
208 if (!newelem
) { LogMsg("Error - malloc"); return; }
209 AssignDomainName(&newelem
->name
, d
);
210 newelem
->next
= DefRegList
;
211 DefRegList
= newelem
;
213 dDNSPlatformDefaultRegDomainChanged(d
, mDNStrue
);
214 udsserver_default_reg_domain_changed(d
, mDNStrue
);
217 mDNSlocal
void RemoveDefRegDomain(domainname
*d
)
219 DNameListElem
*ptr
= DefRegList
, *prev
= NULL
;
223 if (SameDomainName(&ptr
->name
, d
))
225 if (prev
) prev
->next
= ptr
->next
;
226 else DefRegList
= ptr
->next
;
227 freeL("DNameListElem", ptr
);
228 dDNSPlatformDefaultRegDomainChanged(d
, mDNSfalse
);
229 udsserver_default_reg_domain_changed(d
, mDNSfalse
);
235 debugf("Requested removal of default registration domain %##s not in contained in list", d
->c
);
239 mDNSlocal
void FoundDefBrowseDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
241 DNameListElem
*ptr
, *prev
, *new;
243 (void)question
; // unused
247 new = mallocL("FoundDefBrowseDomain", sizeof(DNameListElem
));
248 if (!new) { LogMsg("ERROR: malloc"); return; }
249 AssignDomainName(&new->name
, &answer
->rdata
->u
.name
);
250 new->next
= DefBrowseList
;
252 dDNSPlatformDefaultBrowseDomainChanged(&new->name
, mDNStrue
);
253 udsserver_default_browse_domain_changed(&new->name
, mDNStrue
);
262 if (SameDomainName(&ptr
->name
, &answer
->rdata
->u
.name
))
264 dDNSPlatformDefaultBrowseDomainChanged(&ptr
->name
, mDNSfalse
);
265 udsserver_default_browse_domain_changed(&ptr
->name
, mDNSfalse
);
266 if (prev
) prev
->next
= ptr
->next
;
267 else DefBrowseList
= ptr
->next
;
268 freeL("FoundDefBrowseDomain", ptr
);
274 LogMsg("FoundDefBrowseDomain: Got remove event for domain %s not in list", answer
->rdata
->u
.name
.c
);
279 mDNSlocal mStatus
RegisterNameServers( mDNS
*const m
)
281 IPAddrListElem
* list
;
282 IPAddrListElem
* elem
;
284 mDNS_DeleteDNSServers(m
); // deregister orig list
286 list
= dDNSPlatformGetDNSServers();
288 for ( elem
= list
; elem
; elem
= elem
->next
)
290 LogOperation("RegisterNameServers: Adding %#a", &elem
->addr
);
291 mDNS_AddDNSServer(m
, &elem
->addr
, NULL
);
294 dDNS_FreeIPAddrList( list
);
296 return mStatus_NoError
;
300 mDNSlocal mStatus
RegisterSearchDomains( mDNS
*const m
)
302 SearchListElem
*ptr
, *prev
, *freeSLPtr
;
303 DNameListElem
* elem
;
304 DNameListElem
* list
;
309 // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
310 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
) ptr
->flag
= dict
? -1 : 0;
312 // get all the domains from "Search Domains" field of sharing prefs
314 list
= dDNSPlatformGetSearchDomainList();
316 for ( elem
= list
; elem
; elem
= elem
->next
)
318 MarkSearchListElem(&elem
->name
);
321 mDNS_FreeDNameList( list
);
323 list
= dDNSPlatformGetDomainName();
327 MarkSearchListElem( &list
->name
);
328 mDNS_FreeDNameList( list
);
331 list
= dDNSPlatformGetReverseMapSearchDomainList( );
333 for ( elem
= list
; elem
; elem
= elem
->next
)
335 MarkSearchListElem(&elem
->name
);
338 mDNS_FreeDNameList( list
);
340 if (dDNSRegDomain
.c
[0]) MarkSearchListElem(&dDNSRegDomain
); // implicitly browse reg domain too (no-op if same as BrowseDomain)
342 // delete elems marked for removal, do queries for elems marked add
347 if (ptr
->flag
== -1) // remove
349 mDNS_StopQuery(m
, &ptr
->BrowseQ
);
350 mDNS_StopQuery(m
, &ptr
->RegisterQ
);
351 mDNS_StopQuery(m
, &ptr
->DefBrowseQ
);
352 mDNS_StopQuery(m
, &ptr
->DefRegisterQ
);
353 mDNS_StopQuery(m
, &ptr
->LegacyBrowseQ
);
355 // deregister records generated from answers to the query
356 arList
= ptr
->AuthRecs
;
357 ptr
->AuthRecs
= mDNSNULL
;
360 AuthRecord
*dereg
= &arList
->ar
;
361 arList
= arList
->next
;
362 debugf("Deregistering PTR %s -> %s", dereg
->resrec
.name
->c
, dereg
->resrec
.rdata
->u
.name
.c
);
363 err
= mDNS_Deregister(m
, dereg
);
364 if (err
) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err
);
367 // remove elem from list, delete
368 if (prev
) prev
->next
= ptr
->next
;
369 else SearchList
= ptr
->next
;
372 freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr
);
376 if (ptr
->flag
== 1) // add
378 mStatus err1
, err2
, err3
, err4
, err5
;
379 err1
= mDNS_GetDomains(m
, &ptr
->BrowseQ
, mDNS_DomainTypeBrowse
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
380 err2
= mDNS_GetDomains(m
, &ptr
->DefBrowseQ
, mDNS_DomainTypeBrowseDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
381 err3
= mDNS_GetDomains(m
, &ptr
->RegisterQ
, mDNS_DomainTypeRegistration
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
382 err4
= mDNS_GetDomains(m
, &ptr
->DefRegisterQ
, mDNS_DomainTypeRegistrationDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
383 err5
= mDNS_GetDomains(m
, &ptr
->LegacyBrowseQ
, mDNS_DomainTypeBrowseLegacy
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
384 if (err1
|| err2
|| err3
|| err4
|| err5
)
385 LogMsg("GetDomains for domain %##s returned error(s):\n"
386 "%d (mDNS_DomainTypeBrowse)\n"
387 "%d (mDNS_DomainTypeBrowseDefault)\n"
388 "%d (mDNS_DomainTypeRegistration)\n"
389 "%d (mDNS_DomainTypeRegistrationDefault)"
390 "%d (mDNS_DomainTypeBrowseLegacy)\n",
391 ptr
->domain
.c
, err1
, err2
, err3
, err4
, err5
);
395 if (ptr
->flag
) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr
->flag
); }
401 return mStatus_NoError
;
404 // Add or remove a user-specified domain to the list of empty-string browse domains
405 // Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
406 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
)
410 LogMsg("%s default browse domain %##s", add
? "Adding" : "Removing", d
->c
);
412 // Create dummy record pointing to the domain to be added/removed
413 mDNS_SetupResourceRecord(&rec
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, mDNSNULL
, mDNSNULL
);
414 AssignDomainName(&rec
.resrec
.rdata
->u
.name
, d
);
416 // add/remove the "_legacy" entry
417 MakeDomainNameFromDNSNameString(rec
.resrec
.name
, mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseLegacy
]);
418 AppendDNSNameString (rec
.resrec
.name
, "local");
419 FoundDefBrowseDomain(m
, &LegacyBrowseDomainQ
, &rec
.resrec
, add
);
425 // allocate/register a non-legacy _browse PTR record
426 ARListElem
*ptr
= mallocL("ARListElem", sizeof(*ptr
));
427 mDNS_SetupResourceRecord(&ptr
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, ptr
);
428 MakeDomainNameFromDNSNameString(ptr
->ar
.resrec
.name
, mDNS_DomainTypeNames
[mDNS_DomainTypeBrowse
]);
429 AppendDNSNameString (ptr
->ar
.resrec
.name
, "local");
430 AssignDomainName(&ptr
->ar
.resrec
.rdata
->u
.name
, d
);
431 err
= mDNS_Register(m
, &ptr
->ar
);
434 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err
);
435 freeL("ARListElem", ptr
);
439 ptr
->next
= SCPrefBrowseDomains
;
440 SCPrefBrowseDomains
= ptr
;
445 ARListElem
**remove
= &SCPrefBrowseDomains
;
446 while (*remove
&& !SameDomainName(&(*remove
)->ar
.resrec
.rdata
->u
.name
, d
)) remove
= &(*remove
)->next
;
447 if (!*remove
) { LogMsg("SetSCPrefsBrowseDomain (remove) - domain %##s not found!", d
->c
); return; }
448 mDNS_Deregister(m
, &(*remove
)->ar
);
449 *remove
= (*remove
)->next
;
454 mStatus
dDNS_Setup( mDNS
*const m
)
456 static mDNSBool LegacyNATInitialized
= mDNSfalse
;
457 mDNSBool dict
= mDNStrue
;
460 // YO CFDictionaryRef dict;
461 // YO CFStringRef key;
462 domainname BrowseDomain
, RegDomain
, fqdn
;
464 // get fqdn, zone from SCPrefs
465 dDNSPlatformGetConfig(&fqdn
, &RegDomain
, &BrowseDomain
);
467 // YO if (!fqdn.c[0] && !RegDomain.c[0]) ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &fqdn, &RegDomain);
469 if (!SameDomainName(&RegDomain
, &dDNSRegDomain
))
471 if (dDNSRegDomain
.c
[0])
473 RemoveDefRegDomain(&dDNSRegDomain
);
474 SetSCPrefsBrowseDomain(m
, &dDNSRegDomain
, mDNSfalse
); // if we were automatically browsing in our registration domain, stop
477 AssignDomainName(&dDNSRegDomain
, &RegDomain
);
479 if (dDNSRegDomain
.c
[0])
481 dDNSPlatformSetSecretForDomain(m
, &dDNSRegDomain
);
482 AddDefRegDomain(&dDNSRegDomain
);
483 SetSCPrefsBrowseDomain(m
, &dDNSRegDomain
, mDNStrue
);
487 if (!SameDomainName(&BrowseDomain
, &dDNSBrowseDomain
))
489 if (dDNSBrowseDomain
.c
[0]) SetSCPrefsBrowseDomain(m
, &dDNSBrowseDomain
, mDNSfalse
);
490 AssignDomainName(&dDNSBrowseDomain
, &BrowseDomain
);
491 if (dDNSBrowseDomain
.c
[0]) SetSCPrefsBrowseDomain(m
, &dDNSBrowseDomain
, mDNStrue
);
494 if (!SameDomainName(&fqdn
, &dDNSHostname
))
496 if (dDNSHostname
.c
[0]) mDNS_RemoveDynDNSHostName(m
, &dDNSHostname
);
497 AssignDomainName(&dDNSHostname
, &fqdn
);
498 if (dDNSHostname
.c
[0])
500 dDNSPlatformSetSecretForDomain(m
, &fqdn
); // no-op if "zone" secret, above, is to be used for hostname
501 mDNS_AddDynDNSHostName(m
, &dDNSHostname
, SCPrefsdDNSCallback
, mDNSNULL
);
502 dDNSPlatformSetNameStatus(&dDNSHostname
, 1);
507 // YO SCDynamicStoreRef store = SCDynamicStoreCreate(mDNSNULL, CFSTR("mDNSResponder:dDNSConfigChanged"), mDNSNULL, mDNSNULL);
508 // YO if (!store) return;
510 // YO key = SCDynamicStoreKeyCreateNetworkGlobalEntity(mDNSNULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
511 // YO if (!key) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
512 // YO dict = SCDynamicStoreCopyValue(store, key);
513 // YO CFRelease(key);
515 // handle any changes to search domains and DNS server addresses
516 if ( dDNSPlatformRegisterSplitDNS(m
) != mStatus_NoError
)
517 if (dict
) RegisterNameServers( m
); // fall back to non-split DNS aware configuration on failure
518 RegisterSearchDomains( m
); // note that we register name servers *before* search domains
519 // if (dict) CFRelease(dict);
522 // YO key = SCDynamicStoreKeyCreateNetworkGlobalEntity(mDNSNULL,kSCDynamicStoreDomainState, kSCEntNetIPv4);
523 // YO if (!key) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
524 // YO dict = SCDynamicStoreCopyValue(store, key);
525 // YO CFRelease(key);
526 // YO CFRelease(store);
528 // YO { mDNS_SetPrimaryInterfaceInfo(m, mDNSNULL, mDNSNULL); return; } // lost v4
530 // handle router changes
533 // YO r.type = mDNSAddrType_IPv4;
534 // YO r.ip.v4.NotAnInteger = 0;
535 // YO CFStringRef router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
538 // YO if (!CFStringGetCString(router, buf, 256, kCFStringEncodingUTF8))
539 // YO LogMsg("Could not convert router to CString");
540 // YO else inet_aton(buf, (struct in_addr *)&r.ip.v4);
543 // handle router and primary interface changes
545 ip
.type
= r
.type
= mDNSAddrType_IPv4
;
546 ip
.ip
.v4
.NotAnInteger
= r
.ip
.v4
.NotAnInteger
= 0;
548 if ( dDNSPlatformGetPrimaryInterface( m
, &ip
, &r
) == mStatus_NoError
)
550 mDNS_SetPrimaryInterfaceInfo(m
, &ip
, r
.ip
.v4
.NotAnInteger
? &r
: mDNSNULL
);
553 return mStatus_NoError
;
557 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
558 // 1) query for b._dns-sd._udp.local on LocalOnly interface
559 // (.local manually generated via explicit callback)
560 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
561 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
562 // 4) result above should generate a callback from question in (1). result added to global list
563 // 5) global list delivered to client via GetSearchDomainList()
564 // 6) client calls to enumerate domains now go over LocalOnly interface
565 // (!!!KRS may add outgoing interface in addition)
567 mStatus
dDNS_InitDNSConfig(mDNS
*const m
)
571 // start query for domains to be used in default (empty string domain) browses
572 err
= mDNS_GetDomains(m
, &LegacyBrowseDomainQ
, mDNS_DomainTypeBrowseLegacy
, NULL
, mDNSInterface_LocalOnly
, FoundDefBrowseDomain
, NULL
);
574 // provide .local automatically
575 SetSCPrefsBrowseDomain(m
, &localdomain
, mDNStrue
);
576 return mStatus_NoError
;
580 dDNS_FreeIPAddrList(IPAddrListElem
* list
)
582 IPAddrListElem
* fptr
;
588 mDNSPlatformMemFree(fptr
);