1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
18 * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
19 * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
20 * function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
21 * The shim is responsible for two main things:
22 * - converting string parameters between C string format and native DNS format,
23 * - and for allocating and freeing memory.
26 #include "dns_sd.h" // Defines the interface to the client layer above
27 #include "mDNSEmbeddedAPI.h" // The interface we're building on top of
28 extern mDNS mDNSStorage
; // We need to pass the address of this storage to the lower-layer functions
30 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
34 //*************************************************************************************************************
35 // General Utility Functions
37 // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
38 // Optional type-specific data follows these three fields
39 // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
40 // as the DNSServiceRef for the operation
41 // We stash the value in core context fields so we can get it back to recover our state in our callbacks,
42 // and pass it though to the client for it to recover its state
44 typedef struct mDNS_DirectOP_struct mDNS_DirectOP
;
45 typedef void mDNS_DirectOP_Dispose (mDNS_DirectOP
*op
);
46 struct mDNS_DirectOP_struct
48 mDNS_DirectOP_Dispose
*disposefn
;
53 mDNS_DirectOP_Dispose
*disposefn
;
54 DNSServiceRegisterReply callback
;
56 mDNSBool autoname
; // Set if this name is tied to the Computer Name
57 mDNSBool autorename
; // Set if we just got a name conflict and now need to automatically pick a new name
61 } mDNS_DirectOP_Register
;
65 mDNS_DirectOP_Dispose
*disposefn
;
66 DNSServiceBrowseReply callback
;
69 } mDNS_DirectOP_Browse
;
73 mDNS_DirectOP_Dispose
*disposefn
;
74 DNSServiceResolveReply callback
;
76 const ResourceRecord
*SRV
;
77 const ResourceRecord
*TXT
;
80 } mDNS_DirectOP_Resolve
;
84 mDNS_DirectOP_Dispose
*disposefn
;
85 DNSServiceQueryRecordReply callback
;
88 } mDNS_DirectOP_QueryRecord
;
90 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
92 (void)sdRef
; // Unused
96 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
98 (void)sdRef
; // Unused
99 return(kDNSServiceErr_NoError
);
102 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
104 mDNS_DirectOP
*op
= (mDNS_DirectOP
*)sdRef
;
105 //LogMsg("DNSServiceRefDeallocate");
109 //*************************************************************************************************************
110 // Domain Enumeration
112 // Not yet implemented, so don't include in stub library
113 // We DO include it in the actual Extension, so that if a later client compiled to use this
114 // is run against this Extension, it will get a reasonable error code instead of just
115 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
116 #if !MDNS_BUILDINGSTUBLIBRARY
117 DNSServiceErrorType DNSServiceEnumerateDomains
119 DNSServiceRef
*sdRef
,
120 DNSServiceFlags flags
,
121 uint32_t interfaceIndex
,
122 DNSServiceDomainEnumReply callback
,
123 void *context
/* may be NULL */
126 (void)sdRef
; // Unused
127 (void)flags
; // Unused
128 (void)interfaceIndex
; // Unused
129 (void)callback
; // Unused
130 (void)context
; // Unused
131 return(kDNSServiceErr_Unsupported
);
135 //*************************************************************************************************************
138 mDNSlocal
void FreeDNSServiceRegistration(mDNS_DirectOP_Register
*x
)
142 ExtraResourceRecord
*extras
= x
->s
.Extras
;
143 x
->s
.Extras
= x
->s
.Extras
->next
;
144 if (extras
->r
.resrec
.rdata
!= &extras
->r
.rdatastorage
)
145 mDNSPlatformMemFree(extras
->r
.resrec
.rdata
);
146 mDNSPlatformMemFree(extras
);
149 if (x
->s
.RR_TXT
.resrec
.rdata
!= &x
->s
.RR_TXT
.rdatastorage
)
150 mDNSPlatformMemFree(x
->s
.RR_TXT
.resrec
.rdata
);
152 if (x
->s
.SubTypes
) mDNSPlatformMemFree(x
->s
.SubTypes
);
154 mDNSPlatformMemFree(x
);
157 static void DNSServiceRegisterDispose(mDNS_DirectOP
*op
)
159 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)op
;
160 x
->autorename
= mDNSfalse
;
161 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
162 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
163 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
164 // the list, so we should go ahead and free the memory right now
165 if (mDNS_DeregisterService(&mDNSStorage
, &x
->s
) != mStatus_NoError
)
166 FreeDNSServiceRegistration(x
);
169 mDNSlocal
void RegCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
)
171 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)sr
->ServiceContext
;
174 domainname type
, dom
;
175 char namestr
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
176 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
177 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
178 if (!DeconstructServiceName(sr
->RR_SRV
.resrec
.name
, &name
, &type
, &dom
)) return;
179 if (!ConvertDomainLabelToCString_unescaped(&name
, namestr
)) return;
180 if (!ConvertDomainNameToCString(&type
, typestr
)) return;
181 if (!ConvertDomainNameToCString(&dom
, domstr
)) return;
183 if (result
== mStatus_NoError
)
186 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
188 else if (result
== mStatus_NameConflict
)
190 if (x
->autoname
) mDNS_RenameAndReregisterService(m
, sr
, mDNSNULL
);
191 else if (x
->callback
)
192 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
194 else if (result
== mStatus_MemFree
)
198 x
->autorename
= mDNSfalse
;
199 x
->name
= mDNSStorage
.nicelabel
;
200 mDNS_RenameAndReregisterService(m
, &x
->s
, &x
->name
);
203 FreeDNSServiceRegistration(x
);
207 DNSServiceErrorType DNSServiceRegister
209 DNSServiceRef
*sdRef
,
210 DNSServiceFlags flags
,
211 uint32_t interfaceIndex
,
212 const char *name
, /* may be NULL */
214 const char *domain
, /* may be NULL */
215 const char *host
, /* may be NULL */
216 uint16_t notAnIntPort
,
218 const void *txtRecord
, /* may be NULL */
219 DNSServiceRegisterReply callback
, /* may be NULL */
220 void *context
/* may be NULL */
223 mStatus err
= mStatus_NoError
;
224 const char *errormsg
= "Unknown";
226 domainname t
, d
, h
, srv
;
228 unsigned int size
= sizeof(RDataBody
);
229 AuthRecord
*SubTypes
= mDNSNULL
;
230 mDNSu32 NumSubTypes
= 0;
231 mDNS_DirectOP_Register
*x
;
232 (void)flags
; // Unused
233 (void)interfaceIndex
; // Unused
236 if (!name
) name
= "";
237 if (!name
[0]) n
= mDNSStorage
.nicelabel
;
238 else if (!MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
239 if (!regtype
|| !*regtype
|| !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
240 if (!MakeDomainNameFromDNSNameString(&d
, (domain
&& *domain
) ? domain
: "local.")) { errormsg
= "Bad Domain"; goto badparam
; }
241 if (!MakeDomainNameFromDNSNameString(&h
, (host
&& *host
) ? host
: "")) { errormsg
= "Bad Target Host"; goto badparam
; }
242 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
243 port
.NotAnInteger
= notAnIntPort
;
245 // Allocate memory, and handle failure
248 x
= (mDNS_DirectOP_Register
*)mDNSPlatformMemAllocate(sizeof(*x
) - sizeof(RDataBody
) + size
);
249 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
252 x
->disposefn
= DNSServiceRegisterDispose
;
253 x
->callback
= callback
;
254 x
->context
= context
;
255 x
->autoname
= (!name
[0]);
256 x
->autorename
= mDNSfalse
;
261 err
= mDNS_RegisterService(&mDNSStorage
, &x
->s
,
262 &x
->name
, &t
, &d
, // Name, type, domain
263 &x
->host
, port
, // Host and port
264 txtRecord
, txtLen
, // TXT data, length
265 SubTypes
, NumSubTypes
, // Subtypes
266 mDNSInterface_Any
, // Interface ID
267 RegCallback
, x
, 0); // Callback, context, flags
268 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_RegisterService"; goto fail
; }
270 // Succeeded: Wrap up and return
271 *sdRef
= (DNSServiceRef
)x
;
272 return(mStatus_NoError
);
275 err
= mStatus_BadParamErr
;
277 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
281 //*************************************************************************************************************
282 // Add / Update / Remove records from existing Registration
284 // Not yet implemented, so don't include in stub library
285 // We DO include it in the actual Extension, so that if a later client compiled to use this
286 // is run against this Extension, it will get a reasonable error code instead of just
287 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
288 #if !MDNS_BUILDINGSTUBLIBRARY
289 DNSServiceErrorType DNSServiceAddRecord
292 DNSRecordRef
*RecordRef
,
293 DNSServiceFlags flags
,
300 (void)sdRef
; // Unused
301 (void)RecordRef
; // Unused
302 (void)flags
; // Unused
303 (void)rrtype
; // Unused
304 (void)rdlen
; // Unused
305 (void)rdata
; // Unused
307 return(kDNSServiceErr_Unsupported
);
310 DNSServiceErrorType DNSServiceUpdateRecord
313 DNSRecordRef RecordRef
, /* may be NULL */
314 DNSServiceFlags flags
,
320 (void)sdRef
; // Unused
321 (void)RecordRef
; // Unused
322 (void)flags
; // Unused
323 (void)rdlen
; // Unused
324 (void)rdata
; // Unused
326 return(kDNSServiceErr_Unsupported
);
329 DNSServiceErrorType DNSServiceRemoveRecord
332 DNSRecordRef RecordRef
,
333 DNSServiceFlags flags
336 (void)sdRef
; // Unused
337 (void)RecordRef
; // Unused
338 (void)flags
; // Unused
339 return(kDNSServiceErr_Unsupported
);
343 //*************************************************************************************************************
344 // Browse for services
346 static void DNSServiceBrowseDispose(mDNS_DirectOP
*op
)
348 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)op
;
349 //LogMsg("DNSServiceBrowseDispose");
350 mDNS_StopBrowse(&mDNSStorage
, &x
->q
);
351 mDNSPlatformMemFree(x
);
354 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
356 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0;
358 domainname type
, domain
;
359 char cname
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
360 char ctype
[MAX_ESCAPED_DOMAIN_NAME
];
361 char cdom
[MAX_ESCAPED_DOMAIN_NAME
];
362 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)question
->QuestionContext
;
365 if (answer
->rrtype
!= kDNSType_PTR
)
366 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer
->rrtype
); return; }
368 if (!DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
))
370 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
371 answer
->name
->c
, answer
->rdata
->u
.name
.c
);
375 ConvertDomainLabelToCString_unescaped(&name
, cname
);
376 ConvertDomainNameToCString(&type
, ctype
);
377 ConvertDomainNameToCString(&domain
, cdom
);
379 x
->callback((DNSServiceRef
)x
, flags
, 0, 0, cname
, ctype
, cdom
, x
->context
);
382 DNSServiceErrorType DNSServiceBrowse
384 DNSServiceRef
*sdRef
,
385 DNSServiceFlags flags
,
386 uint32_t interfaceIndex
,
388 const char *domain
, /* may be NULL */
389 DNSServiceBrowseReply callback
,
390 void *context
/* may be NULL */
393 mStatus err
= mStatus_NoError
;
394 const char *errormsg
= "Unknown";
396 mDNS_DirectOP_Browse
*x
;
397 (void)flags
; // Unused
398 (void)interfaceIndex
; // Unused
401 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Illegal regtype"; goto badparam
; }
402 if (!MakeDomainNameFromDNSNameString(&d
, *domain
? domain
: "local.")) { errormsg
= "Illegal domain"; goto badparam
; }
404 // Allocate memory, and handle failure
405 x
= (mDNS_DirectOP_Browse
*)mDNSPlatformMemAllocate(sizeof(*x
));
406 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
409 x
->disposefn
= DNSServiceBrowseDispose
;
410 x
->callback
= callback
;
411 x
->context
= context
;
412 x
->q
.QuestionContext
= x
;
415 err
= mDNS_StartBrowse(&mDNSStorage
, &x
->q
, &t
, &d
, mDNSInterface_Any
, flags
, (flags
& kDNSServiceFlagsForceMulticast
) != 0, (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0, FoundInstance
, x
);
416 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_StartBrowse"; goto fail
; }
418 // Succeeded: Wrap up and return
419 *sdRef
= (DNSServiceRef
)x
;
420 return(mStatus_NoError
);
423 err
= mStatus_BadParamErr
;
425 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
429 //*************************************************************************************************************
430 // Resolve Service Info
432 static void DNSServiceResolveDispose(mDNS_DirectOP
*op
)
434 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)op
;
435 if (x
->qSRV
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qSRV
);
436 if (x
->qTXT
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qTXT
);
437 mDNSPlatformMemFree(x
);
440 mDNSlocal
void FoundServiceInfo(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
442 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)question
->QuestionContext
;
446 if (answer
->rrtype
== kDNSType_SRV
&& x
->SRV
== answer
) x
->SRV
= mDNSNULL
;
447 if (answer
->rrtype
== kDNSType_TXT
&& x
->TXT
== answer
) x
->TXT
= mDNSNULL
;
451 if (answer
->rrtype
== kDNSType_SRV
) x
->SRV
= answer
;
452 if (answer
->rrtype
== kDNSType_TXT
) x
->TXT
= answer
;
453 if (x
->SRV
&& x
->TXT
&& x
->callback
)
455 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], targethost
[MAX_ESCAPED_DOMAIN_NAME
];
456 ConvertDomainNameToCString(answer
->name
, fullname
);
457 ConvertDomainNameToCString(&x
->SRV
->rdata
->u
.srv
.target
, targethost
);
458 x
->callback((DNSServiceRef
)x
, 0, 0, kDNSServiceErr_NoError
, fullname
, targethost
,
459 x
->SRV
->rdata
->u
.srv
.port
.NotAnInteger
, x
->TXT
->rdlength
, (unsigned char*)x
->TXT
->rdata
->u
.txt
.c
, x
->context
);
464 DNSServiceErrorType DNSServiceResolve
466 DNSServiceRef
*sdRef
,
467 DNSServiceFlags flags
,
468 uint32_t interfaceIndex
,
472 DNSServiceResolveReply callback
,
473 void *context
/* may be NULL */
476 mStatus err
= mStatus_NoError
;
477 const char *errormsg
= "Unknown";
479 domainname t
, d
, srv
;
480 mDNS_DirectOP_Resolve
*x
;
482 (void)flags
; // Unused
483 (void)interfaceIndex
; // Unused
486 if (!name
[0] || !MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
487 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
488 if (!domain
[0] || !MakeDomainNameFromDNSNameString(&d
, domain
)) { errormsg
= "Bad Domain"; goto badparam
; }
489 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
491 // Allocate memory, and handle failure
492 x
= (mDNS_DirectOP_Resolve
*)mDNSPlatformMemAllocate(sizeof(*x
));
493 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
496 x
->disposefn
= DNSServiceResolveDispose
;
497 x
->callback
= callback
;
498 x
->context
= context
;
502 x
->qSRV
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
503 x
->qSRV
.InterfaceID
= mDNSInterface_Any
;
505 x
->qSRV
.Target
= zeroAddr
;
506 AssignDomainName(&x
->qSRV
.qname
, &srv
);
507 x
->qSRV
.qtype
= kDNSType_SRV
;
508 x
->qSRV
.qclass
= kDNSClass_IN
;
509 x
->qSRV
.LongLived
= mDNSfalse
;
510 x
->qSRV
.ExpectUnique
= mDNStrue
;
511 x
->qSRV
.ForceMCast
= mDNSfalse
;
512 x
->qSRV
.ReturnIntermed
= mDNSfalse
;
513 x
->qSRV
.SuppressUnusable
= mDNSfalse
;
514 x
->qSRV
.SearchListIndex
= 0;
515 x
->qSRV
.AppendSearchDomains
= 0;
516 x
->qSRV
.RetryWithSearchDomains
= mDNSfalse
;
517 x
->qSRV
.TimeoutQuestion
= 0;
518 x
->qSRV
.WakeOnResolve
= 0;
519 x
->qSRV
.UseBrackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
520 x
->qSRV
.ValidationRequired
= 0;
521 x
->qSRV
.ValidatingResponse
= 0;
522 x
->qSRV
.qnameOrig
= mDNSNULL
;
523 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
524 x
->qSRV
.QuestionContext
= x
;
526 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
527 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
529 x
->qTXT
.Target
= zeroAddr
;
530 AssignDomainName(&x
->qTXT
.qname
, &srv
);
531 x
->qTXT
.qtype
= kDNSType_TXT
;
532 x
->qTXT
.qclass
= kDNSClass_IN
;
533 x
->qTXT
.LongLived
= mDNSfalse
;
534 x
->qTXT
.ExpectUnique
= mDNStrue
;
535 x
->qTXT
.ForceMCast
= mDNSfalse
;
536 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
537 x
->qTXT
.SuppressUnusable
= mDNSfalse
;
538 x
->qTXT
.SearchListIndex
= 0;
539 x
->qTXT
.AppendSearchDomains
= 0;
540 x
->qTXT
.RetryWithSearchDomains
= mDNSfalse
;
541 x
->qTXT
.TimeoutQuestion
= 0;
542 x
->qTXT
.WakeOnResolve
= 0;
543 x
->qTXT
.UseBrackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
544 x
->qTXT
.ValidationRequired
= 0;
545 x
->qTXT
.ValidatingResponse
= 0;
546 x
->qTXT
.qnameOrig
= mDNSNULL
;
547 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
548 x
->qTXT
.QuestionContext
= x
;
550 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
551 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
552 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
553 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
555 // Succeeded: Wrap up and return
556 *sdRef
= (DNSServiceRef
)x
;
557 return(mStatus_NoError
);
560 err
= mStatus_BadParamErr
;
562 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
566 //*************************************************************************************************************
567 // Connection-oriented calls
569 // Not yet implemented, so don't include in stub library
570 // We DO include it in the actual Extension, so that if a later client compiled to use this
571 // is run against this Extension, it will get a reasonable error code instead of just
572 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
573 #if !MDNS_BUILDINGSTUBLIBRARY
574 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
576 (void)sdRef
; // Unused
577 return(kDNSServiceErr_Unsupported
);
580 DNSServiceErrorType DNSServiceRegisterRecord
583 DNSRecordRef
*RecordRef
,
584 DNSServiceFlags flags
,
585 uint32_t interfaceIndex
,
586 const char *fullname
,
592 DNSServiceRegisterRecordReply callback
,
593 void *context
/* may be NULL */
596 (void)sdRef
; // Unused
597 (void)RecordRef
; // Unused
598 (void)flags
; // Unused
599 (void)interfaceIndex
; // Unused
600 (void)fullname
; // Unused
601 (void)rrtype
; // Unused
602 (void)rrclass
; // Unused
603 (void)rdlen
; // Unused
604 (void)rdata
; // Unused
606 (void)callback
; // Unused
607 (void)context
; // Unused
608 return(kDNSServiceErr_Unsupported
);
612 //*************************************************************************************************************
613 // DNSServiceQueryRecord
615 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
617 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
618 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
619 mDNSPlatformMemFree(x
);
622 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
624 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
625 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
627 ConvertDomainNameToCString(answer
->name
, fullname
);
628 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
629 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
632 DNSServiceErrorType DNSServiceQueryRecord
634 DNSServiceRef
*sdRef
,
635 DNSServiceFlags flags
,
636 uint32_t interfaceIndex
,
637 const char *fullname
,
640 DNSServiceQueryRecordReply callback
,
641 void *context
/* may be NULL */
644 mStatus err
= mStatus_NoError
;
645 const char *errormsg
= "Unknown";
646 mDNS_DirectOP_QueryRecord
*x
;
648 (void)flags
; // Unused
649 (void)interfaceIndex
; // Unused
651 // Allocate memory, and handle failure
652 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
653 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
656 x
->disposefn
= DNSServiceQueryRecordDispose
;
657 x
->callback
= callback
;
658 x
->context
= context
;
660 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
661 x
->q
.InterfaceID
= mDNSInterface_Any
;
663 x
->q
.Target
= zeroAddr
;
664 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
666 x
->q
.qclass
= rrclass
;
667 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
668 x
->q
.ExpectUnique
= mDNSfalse
;
669 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
670 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
671 x
->q
.SuppressUnsable
= (flags
& kDNSServiceFlagsSuppressUnusable
) != 0;
672 x
->q
.SearchListIndex
= 0;
673 x
->q
.AppendSearchDomains
= 0;
674 x
->q
.RetryWithSearchDomains
= mDNSfalse
;
675 x
->q
.WakeOnResolve
= 0;
676 x
->q
.UseBrackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
677 x
->q
.qnameOrig
= mDNSNULL
;
678 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
679 x
->q
.QuestionContext
= x
;
681 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
682 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
684 // Succeeded: Wrap up and return
685 *sdRef
= (DNSServiceRef
)x
;
686 return(mStatus_NoError
);
689 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
693 //*************************************************************************************************************
694 // DNSServiceGetAddrInfo
696 static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP
*op
)
698 mDNS_DirectOP_GetAddrInfo
*x
= (mDNS_DirectOP_GetAddrInfo
*)op
;
699 if (x
->aQuery
) DNSServiceRefDeallocate(x
->aQuery
);
700 mDNSPlatformMemFree(x
);
703 static void DNSSD_API
DNSServiceGetAddrInfoResponse(
705 DNSServiceFlags inFlags
,
706 uint32_t inInterfaceIndex
,
707 DNSServiceErrorType inErrorCode
,
708 const char * inFullName
,
712 const void * inRData
,
716 mDNS_DirectOP_GetAddrInfo
* x
= (mDNS_DirectOP_GetAddrInfo
*)inContext
;
717 struct sockaddr_in sa4
;
719 mDNSPlatformMemZero(&sa4
, sizeof(sa4
));
720 if (inErrorCode
== kDNSServiceErr_NoError
&& inRRType
== kDNSServiceType_A
)
722 sa4
.sin_family
= AF_INET
;
723 mDNSPlatformMemCopy(&sa4
.sin_addr
.s_addr
, inRData
, 4);
726 x
->callback((DNSServiceRef
)x
, inFlags
, inInterfaceIndex
, inErrorCode
, inFullName
,
727 (const struct sockaddr
*) &sa4
, inTTL
, x
->context
);
730 DNSServiceErrorType DNSSD_API
DNSServiceGetAddrInfo(
731 DNSServiceRef
* outRef
,
732 DNSServiceFlags inFlags
,
733 uint32_t inInterfaceIndex
,
734 DNSServiceProtocol inProtocol
,
735 const char * inHostName
,
736 DNSServiceGetAddrInfoReply inCallback
,
739 const char * errormsg
= "Unknown";
740 DNSServiceErrorType err
;
741 mDNS_DirectOP_GetAddrInfo
* x
;
743 // Allocate memory, and handle failure
744 x
= (mDNS_DirectOP_GetAddrInfo
*)mDNSPlatformMemAllocate(sizeof(*x
));
745 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
748 x
->disposefn
= DNSServiceGetAddrInfoDispose
;
749 x
->callback
= inCallback
;
750 x
->context
= inContext
;
751 x
->aQuery
= mDNSNULL
;
754 // (It would probably be more efficient to code this using mDNS_StartQuery directly,
755 // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
756 // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
757 err
= DNSServiceQueryRecord(&x
->aQuery
, inFlags
, inInterfaceIndex
, inHostName
, kDNSServiceType_A
,
758 kDNSServiceClass_IN
, DNSServiceGetAddrInfoResponse
, x
);
759 if (err
) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP
*)x
); errormsg
= "DNSServiceQueryRecord"; goto fail
; }
761 *outRef
= (DNSServiceRef
)x
;
762 return(mStatus_NoError
);
765 LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName
, inProtocol
, errormsg
, err
);
769 //*************************************************************************************************************
770 // DNSServiceReconfirmRecord
772 // Not yet implemented, so don't include in stub library
773 // We DO include it in the actual Extension, so that if a later client compiled to use this
774 // is run against this Extension, it will get a reasonable error code instead of just
775 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
776 #if !MDNS_BUILDINGSTUBLIBRARY
777 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
779 DNSServiceFlags flags
,
780 uint32_t interfaceIndex
,
781 const char *fullname
,
788 (void)flags
; // Unused
789 (void)interfaceIndex
; // Unused
790 (void)fullname
; // Unused
791 (void)rrtype
; // Unused
792 (void)rrclass
; // Unused
793 (void)rdlen
; // Unused
794 (void)rdata
; // Unused
795 return(kDNSServiceErr_Unsupported
);
798 #endif // !MDNS_BUILDINGSTUBLIBRARY