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 dnssd_sock_t
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
, mDNSNULL
, 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
.UseBackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
520 x
->qSRV
.ValidationRequired
= 0;
521 x
->qSRV
.ValidatingResponse
= 0;
522 x
->qSRV
.ProxyQuestion
= 0;
523 x
->qSRV
.qnameOrig
= mDNSNULL
;
524 x
->qSRV
.AnonInfo
= mDNSNULL
;
525 x
->qSRV
.pid
= mDNSPlatformGetPID();
526 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
527 x
->qSRV
.QuestionContext
= x
;
529 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
530 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
532 x
->qTXT
.Target
= zeroAddr
;
533 AssignDomainName(&x
->qTXT
.qname
, &srv
);
534 x
->qTXT
.qtype
= kDNSType_TXT
;
535 x
->qTXT
.qclass
= kDNSClass_IN
;
536 x
->qTXT
.LongLived
= mDNSfalse
;
537 x
->qTXT
.ExpectUnique
= mDNStrue
;
538 x
->qTXT
.ForceMCast
= mDNSfalse
;
539 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
540 x
->qTXT
.SuppressUnusable
= mDNSfalse
;
541 x
->qTXT
.SearchListIndex
= 0;
542 x
->qTXT
.AppendSearchDomains
= 0;
543 x
->qTXT
.RetryWithSearchDomains
= mDNSfalse
;
544 x
->qTXT
.TimeoutQuestion
= 0;
545 x
->qTXT
.WakeOnResolve
= 0;
546 x
->qTXT
.UseBackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
547 x
->qTXT
.ValidationRequired
= 0;
548 x
->qTXT
.ValidatingResponse
= 0;
549 x
->qTXT
.ProxyQuestion
= 0;
550 x
->qTXT
.qnameOrig
= mDNSNULL
;
551 x
->qTXT
.AnonInfo
= mDNSNULL
;
552 x
->qTXT
.pid
= mDNSPlatformGetPID();
553 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
554 x
->qTXT
.QuestionContext
= x
;
556 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
557 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
558 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
559 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
561 // Succeeded: Wrap up and return
562 *sdRef
= (DNSServiceRef
)x
;
563 return(mStatus_NoError
);
566 err
= mStatus_BadParamErr
;
568 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
572 //*************************************************************************************************************
573 // Connection-oriented calls
575 // Not yet implemented, so don't include in stub library
576 // We DO include it in the actual Extension, so that if a later client compiled to use this
577 // is run against this Extension, it will get a reasonable error code instead of just
578 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
579 #if !MDNS_BUILDINGSTUBLIBRARY
580 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
582 (void)sdRef
; // Unused
583 return(kDNSServiceErr_Unsupported
);
586 DNSServiceErrorType DNSServiceRegisterRecord
589 DNSRecordRef
*RecordRef
,
590 DNSServiceFlags flags
,
591 uint32_t interfaceIndex
,
592 const char *fullname
,
598 DNSServiceRegisterRecordReply callback
,
599 void *context
/* may be NULL */
602 (void)sdRef
; // Unused
603 (void)RecordRef
; // Unused
604 (void)flags
; // Unused
605 (void)interfaceIndex
; // Unused
606 (void)fullname
; // Unused
607 (void)rrtype
; // Unused
608 (void)rrclass
; // Unused
609 (void)rdlen
; // Unused
610 (void)rdata
; // Unused
612 (void)callback
; // Unused
613 (void)context
; // Unused
614 return(kDNSServiceErr_Unsupported
);
618 //*************************************************************************************************************
619 // DNSServiceQueryRecord
621 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
623 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
624 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
625 mDNSPlatformMemFree(x
);
628 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
630 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
631 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
633 ConvertDomainNameToCString(answer
->name
, fullname
);
634 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
635 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
638 DNSServiceErrorType DNSServiceQueryRecord
640 DNSServiceRef
*sdRef
,
641 DNSServiceFlags flags
,
642 uint32_t interfaceIndex
,
643 const char *fullname
,
646 DNSServiceQueryRecordReply callback
,
647 void *context
/* may be NULL */
650 mStatus err
= mStatus_NoError
;
651 const char *errormsg
= "Unknown";
652 mDNS_DirectOP_QueryRecord
*x
;
654 (void)flags
; // Unused
655 (void)interfaceIndex
; // Unused
657 // Allocate memory, and handle failure
658 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
659 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
662 x
->disposefn
= DNSServiceQueryRecordDispose
;
663 x
->callback
= callback
;
664 x
->context
= context
;
666 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
667 x
->q
.InterfaceID
= mDNSInterface_Any
;
669 x
->q
.Target
= zeroAddr
;
670 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
672 x
->q
.qclass
= rrclass
;
673 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
674 x
->q
.ExpectUnique
= mDNSfalse
;
675 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
676 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
677 x
->q
.SuppressUnsable
= (flags
& kDNSServiceFlagsSuppressUnusable
) != 0;
678 x
->q
.SearchListIndex
= 0;
679 x
->q
.AppendSearchDomains
= 0;
680 x
->q
.RetryWithSearchDomains
= mDNSfalse
;
681 x
->q
.TimeoutQuestion
= 0;
682 x
->q
.WakeOnResolve
= 0;
683 x
->q
.UseBackgroundTrafficClass
= (flags
& kDNSServiceFlagsBackgroundTrafficClass
) != 0;
684 x
->q
.ValidationRequired
= 0;
685 x
->q
.ValidatingResponse
= 0;
686 x
->q
.ProxyQuestion
= 0;
687 x
->q
.qnameOrig
= mDNSNULL
;
688 x
->q
.AnonInfo
= mDNSNULL
;
689 x
->q
.pid
= mDNSPlatformGetPID();
690 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
691 x
->q
.QuestionContext
= x
;
693 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
694 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
696 // Succeeded: Wrap up and return
697 *sdRef
= (DNSServiceRef
)x
;
698 return(mStatus_NoError
);
701 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
705 //*************************************************************************************************************
706 // DNSServiceGetAddrInfo
708 static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP
*op
)
710 mDNS_DirectOP_GetAddrInfo
*x
= (mDNS_DirectOP_GetAddrInfo
*)op
;
711 if (x
->aQuery
) DNSServiceRefDeallocate(x
->aQuery
);
712 mDNSPlatformMemFree(x
);
715 static void DNSSD_API
DNSServiceGetAddrInfoResponse(
717 DNSServiceFlags inFlags
,
718 uint32_t inInterfaceIndex
,
719 DNSServiceErrorType inErrorCode
,
720 const char * inFullName
,
724 const void * inRData
,
728 mDNS_DirectOP_GetAddrInfo
* x
= (mDNS_DirectOP_GetAddrInfo
*)inContext
;
729 struct sockaddr_in sa4
;
731 mDNSPlatformMemZero(&sa4
, sizeof(sa4
));
732 if (inErrorCode
== kDNSServiceErr_NoError
&& inRRType
== kDNSServiceType_A
)
734 sa4
.sin_family
= AF_INET
;
735 mDNSPlatformMemCopy(&sa4
.sin_addr
.s_addr
, inRData
, 4);
738 x
->callback((DNSServiceRef
)x
, inFlags
, inInterfaceIndex
, inErrorCode
, inFullName
,
739 (const struct sockaddr
*) &sa4
, inTTL
, x
->context
);
742 DNSServiceErrorType DNSSD_API
DNSServiceGetAddrInfo(
743 DNSServiceRef
* outRef
,
744 DNSServiceFlags inFlags
,
745 uint32_t inInterfaceIndex
,
746 DNSServiceProtocol inProtocol
,
747 const char * inHostName
,
748 DNSServiceGetAddrInfoReply inCallback
,
751 const char * errormsg
= "Unknown";
752 DNSServiceErrorType err
;
753 mDNS_DirectOP_GetAddrInfo
* x
;
755 // Allocate memory, and handle failure
756 x
= (mDNS_DirectOP_GetAddrInfo
*)mDNSPlatformMemAllocate(sizeof(*x
));
757 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
760 x
->disposefn
= DNSServiceGetAddrInfoDispose
;
761 x
->callback
= inCallback
;
762 x
->context
= inContext
;
763 x
->aQuery
= mDNSNULL
;
766 // (It would probably be more efficient to code this using mDNS_StartQuery directly,
767 // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
768 // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
769 err
= DNSServiceQueryRecord(&x
->aQuery
, inFlags
, inInterfaceIndex
, inHostName
, kDNSServiceType_A
,
770 kDNSServiceClass_IN
, DNSServiceGetAddrInfoResponse
, x
);
771 if (err
) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP
*)x
); errormsg
= "DNSServiceQueryRecord"; goto fail
; }
773 *outRef
= (DNSServiceRef
)x
;
774 return(mStatus_NoError
);
777 LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName
, inProtocol
, errormsg
, err
);
781 //*************************************************************************************************************
782 // DNSServiceReconfirmRecord
784 // Not yet implemented, so don't include in stub library
785 // We DO include it in the actual Extension, so that if a later client compiled to use this
786 // is run against this Extension, it will get a reasonable error code instead of just
787 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
788 #if !MDNS_BUILDINGSTUBLIBRARY
789 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
791 DNSServiceFlags flags
,
792 uint32_t interfaceIndex
,
793 const char *fullname
,
800 (void)flags
; // Unused
801 (void)interfaceIndex
; // Unused
802 (void)fullname
; // Unused
803 (void)rrtype
; // Unused
804 (void)rrclass
; // Unused
805 (void)rdlen
; // Unused
806 (void)rdata
; // Unused
807 return(kDNSServiceErr_Unsupported
);
811 #endif // !MDNS_BUILDINGSTUBLIBRARY