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
); // Callback and context
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
& kDNSServiceFlagsForceMulticast
) != 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
;
504 x
->qSRV
.Target
= zeroAddr
;
505 AssignDomainName(&x
->qSRV
.qname
, &srv
);
506 x
->qSRV
.qtype
= kDNSType_SRV
;
507 x
->qSRV
.qclass
= kDNSClass_IN
;
508 x
->qSRV
.LongLived
= mDNSfalse
;
509 x
->qSRV
.ExpectUnique
= mDNStrue
;
510 x
->qSRV
.ForceMCast
= mDNSfalse
;
511 x
->qSRV
.ReturnIntermed
= mDNSfalse
;
512 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
513 x
->qSRV
.QuestionContext
= x
;
515 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
516 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
517 x
->qTXT
.Target
= zeroAddr
;
518 AssignDomainName(&x
->qTXT
.qname
, &srv
);
519 x
->qTXT
.qtype
= kDNSType_TXT
;
520 x
->qTXT
.qclass
= kDNSClass_IN
;
521 x
->qTXT
.LongLived
= mDNSfalse
;
522 x
->qTXT
.ExpectUnique
= mDNStrue
;
523 x
->qTXT
.ForceMCast
= mDNSfalse
;
524 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
525 x
->qTXT
.SuppressUnusable
= mDNSfalse
;
526 x
->qTXT
.WakeOnResolve
= mDNSfalse
;
527 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
528 x
->qTXT
.QuestionContext
= x
;
530 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
531 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
532 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
533 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
535 // Succeeded: Wrap up and return
536 *sdRef
= (DNSServiceRef
)x
;
537 return(mStatus_NoError
);
540 err
= mStatus_BadParamErr
;
542 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
546 //*************************************************************************************************************
547 // Connection-oriented calls
549 // Not yet implemented, so don't include in stub library
550 // We DO include it in the actual Extension, so that if a later client compiled to use this
551 // is run against this Extension, it will get a reasonable error code instead of just
552 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
553 #if !MDNS_BUILDINGSTUBLIBRARY
554 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
556 (void)sdRef
; // Unused
557 return(kDNSServiceErr_Unsupported
);
560 DNSServiceErrorType DNSServiceRegisterRecord
563 DNSRecordRef
*RecordRef
,
564 DNSServiceFlags flags
,
565 uint32_t interfaceIndex
,
566 const char *fullname
,
572 DNSServiceRegisterRecordReply callback
,
573 void *context
/* may be NULL */
576 (void)sdRef
; // Unused
577 (void)RecordRef
; // Unused
578 (void)flags
; // Unused
579 (void)interfaceIndex
; // Unused
580 (void)fullname
; // Unused
581 (void)rrtype
; // Unused
582 (void)rrclass
; // Unused
583 (void)rdlen
; // Unused
584 (void)rdata
; // Unused
586 (void)callback
; // Unused
587 (void)context
; // Unused
588 return(kDNSServiceErr_Unsupported
);
592 //*************************************************************************************************************
593 // DNSServiceQueryRecord
595 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
597 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
598 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
599 mDNSPlatformMemFree(x
);
602 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
604 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
605 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
607 ConvertDomainNameToCString(answer
->name
, fullname
);
608 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
609 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
612 DNSServiceErrorType DNSServiceQueryRecord
614 DNSServiceRef
*sdRef
,
615 DNSServiceFlags flags
,
616 uint32_t interfaceIndex
,
617 const char *fullname
,
620 DNSServiceQueryRecordReply callback
,
621 void *context
/* may be NULL */
624 mStatus err
= mStatus_NoError
;
625 const char *errormsg
= "Unknown";
626 mDNS_DirectOP_QueryRecord
*x
;
628 (void)flags
; // Unused
629 (void)interfaceIndex
; // Unused
631 // Allocate memory, and handle failure
632 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
633 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
636 x
->disposefn
= DNSServiceQueryRecordDispose
;
637 x
->callback
= callback
;
638 x
->context
= context
;
640 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
641 x
->q
.InterfaceID
= mDNSInterface_Any
;
642 x
->q
.Target
= zeroAddr
;
643 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
645 x
->q
.qclass
= rrclass
;
646 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
647 x
->q
.ExpectUnique
= mDNSfalse
;
648 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
649 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
650 x
->q
.SuppressUnsable
= (flags
& kDNSServiceFlagsSuppressUnusable
) != 0;
651 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
652 x
->q
.QuestionContext
= x
;
654 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
655 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
657 // Succeeded: Wrap up and return
658 *sdRef
= (DNSServiceRef
)x
;
659 return(mStatus_NoError
);
662 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
666 //*************************************************************************************************************
667 // DNSServiceGetAddrInfo
669 static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP
*op
)
671 mDNS_DirectOP_GetAddrInfo
*x
= (mDNS_DirectOP_GetAddrInfo
*)op
;
672 if (x
->aQuery
) DNSServiceRefDeallocate(x
->aQuery
);
673 mDNSPlatformMemFree(x
);
676 static void DNSSD_API
DNSServiceGetAddrInfoResponse(
678 DNSServiceFlags inFlags
,
679 uint32_t inInterfaceIndex
,
680 DNSServiceErrorType inErrorCode
,
681 const char * inFullName
,
685 const void * inRData
,
689 mDNS_DirectOP_GetAddrInfo
* x
= (mDNS_DirectOP_GetAddrInfo
*)inContext
;
690 struct sockaddr_in sa4
;
692 mDNSPlatformMemZero(&sa4
, sizeof(sa4
));
693 if (inErrorCode
== kDNSServiceErr_NoError
&& inRRType
== kDNSServiceType_A
)
695 sa4
.sin_family
= AF_INET
;
696 mDNSPlatformMemCopy(&sa4
.sin_addr
.s_addr
, inRData
, 4);
699 x
->callback((DNSServiceRef
)x
, inFlags
, inInterfaceIndex
, inErrorCode
, inFullName
,
700 (const struct sockaddr
*) &sa4
, inTTL
, x
->context
);
703 DNSServiceErrorType DNSSD_API
DNSServiceGetAddrInfo(
704 DNSServiceRef
* outRef
,
705 DNSServiceFlags inFlags
,
706 uint32_t inInterfaceIndex
,
707 DNSServiceProtocol inProtocol
,
708 const char * inHostName
,
709 DNSServiceGetAddrInfoReply inCallback
,
712 const char * errormsg
= "Unknown";
713 DNSServiceErrorType err
;
714 mDNS_DirectOP_GetAddrInfo
* x
;
716 // Allocate memory, and handle failure
717 x
= (mDNS_DirectOP_GetAddrInfo
*)mDNSPlatformMemAllocate(sizeof(*x
));
718 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
721 x
->disposefn
= DNSServiceGetAddrInfoDispose
;
722 x
->callback
= inCallback
;
723 x
->context
= inContext
;
724 x
->aQuery
= mDNSNULL
;
727 // (It would probably be more efficient to code this using mDNS_StartQuery directly,
728 // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
729 // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
730 err
= DNSServiceQueryRecord(&x
->aQuery
, inFlags
, inInterfaceIndex
, inHostName
, kDNSServiceType_A
,
731 kDNSServiceClass_IN
, DNSServiceGetAddrInfoResponse
, x
);
732 if (err
) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP
*)x
); errormsg
= "DNSServiceQueryRecord"; goto fail
; }
734 *outRef
= (DNSServiceRef
)x
;
735 return(mStatus_NoError
);
738 LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName
, inProtocol
, errormsg
, err
);
742 //*************************************************************************************************************
743 // DNSServiceReconfirmRecord
745 // Not yet implemented, so don't include in stub library
746 // We DO include it in the actual Extension, so that if a later client compiled to use this
747 // is run against this Extension, it will get a reasonable error code instead of just
748 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
749 #if !MDNS_BUILDINGSTUBLIBRARY
750 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
752 DNSServiceFlags flags
,
753 uint32_t interfaceIndex
,
754 const char *fullname
,
761 (void)flags
; // Unused
762 (void)interfaceIndex
; // Unused
763 (void)fullname
; // Unused
764 (void)rrtype
; // Unused
765 (void)rrclass
; // Unused
766 (void)rdlen
; // Unused
767 (void)rdata
; // Unused
768 return(kDNSServiceErr_Unsupported
);