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
& 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
.SuppressUnusable
= mDNSfalse
;
513 x
->qSRV
.SearchListIndex
= 0;
514 x
->qSRV
.AppendSearchDomains
= 0;
515 x
->qSRV
.RetryWithSearchDomains
= mDNSfalse
;
516 x
->qSRV
.TimeoutQuestion
= 0;
517 x
->qSRV
.WakeOnResolve
= 0;
518 x
->qSRV
.qnameOrig
= mDNSNULL
;
519 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
520 x
->qSRV
.QuestionContext
= x
;
522 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
523 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
524 x
->qTXT
.Target
= zeroAddr
;
525 AssignDomainName(&x
->qTXT
.qname
, &srv
);
526 x
->qTXT
.qtype
= kDNSType_TXT
;
527 x
->qTXT
.qclass
= kDNSClass_IN
;
528 x
->qTXT
.LongLived
= mDNSfalse
;
529 x
->qTXT
.ExpectUnique
= mDNStrue
;
530 x
->qTXT
.ForceMCast
= mDNSfalse
;
531 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
532 x
->qTXT
.SuppressUnusable
= mDNSfalse
;
533 x
->qTXT
.SearchListIndex
= 0;
534 x
->qTXT
.AppendSearchDomains
= 0;
535 x
->qTXT
.RetryWithSearchDomains
= mDNSfalse
;
536 x
->qTXT
.TimeoutQuestion
= 0;
537 x
->qTXT
.WakeOnResolve
= 0;
538 x
->qTXT
.qnameOrig
= mDNSNULL
;
539 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
540 x
->qTXT
.QuestionContext
= x
;
542 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
543 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
544 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
545 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
547 // Succeeded: Wrap up and return
548 *sdRef
= (DNSServiceRef
)x
;
549 return(mStatus_NoError
);
552 err
= mStatus_BadParamErr
;
554 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
558 //*************************************************************************************************************
559 // Connection-oriented calls
561 // Not yet implemented, so don't include in stub library
562 // We DO include it in the actual Extension, so that if a later client compiled to use this
563 // is run against this Extension, it will get a reasonable error code instead of just
564 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
565 #if !MDNS_BUILDINGSTUBLIBRARY
566 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
568 (void)sdRef
; // Unused
569 return(kDNSServiceErr_Unsupported
);
572 DNSServiceErrorType DNSServiceRegisterRecord
575 DNSRecordRef
*RecordRef
,
576 DNSServiceFlags flags
,
577 uint32_t interfaceIndex
,
578 const char *fullname
,
584 DNSServiceRegisterRecordReply callback
,
585 void *context
/* may be NULL */
588 (void)sdRef
; // Unused
589 (void)RecordRef
; // Unused
590 (void)flags
; // Unused
591 (void)interfaceIndex
; // Unused
592 (void)fullname
; // Unused
593 (void)rrtype
; // Unused
594 (void)rrclass
; // Unused
595 (void)rdlen
; // Unused
596 (void)rdata
; // Unused
598 (void)callback
; // Unused
599 (void)context
; // Unused
600 return(kDNSServiceErr_Unsupported
);
604 //*************************************************************************************************************
605 // DNSServiceQueryRecord
607 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
609 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
610 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
611 mDNSPlatformMemFree(x
);
614 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
616 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
617 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
619 ConvertDomainNameToCString(answer
->name
, fullname
);
620 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
621 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
624 DNSServiceErrorType DNSServiceQueryRecord
626 DNSServiceRef
*sdRef
,
627 DNSServiceFlags flags
,
628 uint32_t interfaceIndex
,
629 const char *fullname
,
632 DNSServiceQueryRecordReply callback
,
633 void *context
/* may be NULL */
636 mStatus err
= mStatus_NoError
;
637 const char *errormsg
= "Unknown";
638 mDNS_DirectOP_QueryRecord
*x
;
640 (void)flags
; // Unused
641 (void)interfaceIndex
; // Unused
643 // Allocate memory, and handle failure
644 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
645 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
648 x
->disposefn
= DNSServiceQueryRecordDispose
;
649 x
->callback
= callback
;
650 x
->context
= context
;
652 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
653 x
->q
.InterfaceID
= mDNSInterface_Any
;
654 x
->q
.Target
= zeroAddr
;
655 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
657 x
->q
.qclass
= rrclass
;
658 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
659 x
->q
.ExpectUnique
= mDNSfalse
;
660 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
661 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
662 x
->q
.SuppressUnsable
= (flags
& kDNSServiceFlagsSuppressUnusable
) != 0;
663 x
->q
.SearchListIndex
= 0;
664 x
->q
.AppendSearchDomains
= 0;
665 x
->q
.RetryWithSearchDomains
= mDNSfalse
;
666 x
->q
.WakeOnResolve
= 0;
667 x
->q
.qnameOrig
= mDNSNULL
;
668 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
669 x
->q
.QuestionContext
= x
;
671 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
672 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
674 // Succeeded: Wrap up and return
675 *sdRef
= (DNSServiceRef
)x
;
676 return(mStatus_NoError
);
679 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
683 //*************************************************************************************************************
684 // DNSServiceGetAddrInfo
686 static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP
*op
)
688 mDNS_DirectOP_GetAddrInfo
*x
= (mDNS_DirectOP_GetAddrInfo
*)op
;
689 if (x
->aQuery
) DNSServiceRefDeallocate(x
->aQuery
);
690 mDNSPlatformMemFree(x
);
693 static void DNSSD_API
DNSServiceGetAddrInfoResponse(
695 DNSServiceFlags inFlags
,
696 uint32_t inInterfaceIndex
,
697 DNSServiceErrorType inErrorCode
,
698 const char * inFullName
,
702 const void * inRData
,
706 mDNS_DirectOP_GetAddrInfo
* x
= (mDNS_DirectOP_GetAddrInfo
*)inContext
;
707 struct sockaddr_in sa4
;
709 mDNSPlatformMemZero(&sa4
, sizeof(sa4
));
710 if (inErrorCode
== kDNSServiceErr_NoError
&& inRRType
== kDNSServiceType_A
)
712 sa4
.sin_family
= AF_INET
;
713 mDNSPlatformMemCopy(&sa4
.sin_addr
.s_addr
, inRData
, 4);
716 x
->callback((DNSServiceRef
)x
, inFlags
, inInterfaceIndex
, inErrorCode
, inFullName
,
717 (const struct sockaddr
*) &sa4
, inTTL
, x
->context
);
720 DNSServiceErrorType DNSSD_API
DNSServiceGetAddrInfo(
721 DNSServiceRef
* outRef
,
722 DNSServiceFlags inFlags
,
723 uint32_t inInterfaceIndex
,
724 DNSServiceProtocol inProtocol
,
725 const char * inHostName
,
726 DNSServiceGetAddrInfoReply inCallback
,
729 const char * errormsg
= "Unknown";
730 DNSServiceErrorType err
;
731 mDNS_DirectOP_GetAddrInfo
* x
;
733 // Allocate memory, and handle failure
734 x
= (mDNS_DirectOP_GetAddrInfo
*)mDNSPlatformMemAllocate(sizeof(*x
));
735 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
738 x
->disposefn
= DNSServiceGetAddrInfoDispose
;
739 x
->callback
= inCallback
;
740 x
->context
= inContext
;
741 x
->aQuery
= mDNSNULL
;
744 // (It would probably be more efficient to code this using mDNS_StartQuery directly,
745 // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
746 // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
747 err
= DNSServiceQueryRecord(&x
->aQuery
, inFlags
, inInterfaceIndex
, inHostName
, kDNSServiceType_A
,
748 kDNSServiceClass_IN
, DNSServiceGetAddrInfoResponse
, x
);
749 if (err
) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP
*)x
); errormsg
= "DNSServiceQueryRecord"; goto fail
; }
751 *outRef
= (DNSServiceRef
)x
;
752 return(mStatus_NoError
);
755 LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName
, inProtocol
, errormsg
, err
);
759 //*************************************************************************************************************
760 // DNSServiceReconfirmRecord
762 // Not yet implemented, so don't include in stub library
763 // We DO include it in the actual Extension, so that if a later client compiled to use this
764 // is run against this Extension, it will get a reasonable error code instead of just
765 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
766 #if !MDNS_BUILDINGSTUBLIBRARY
767 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
769 DNSServiceFlags flags
,
770 uint32_t interfaceIndex
,
771 const char *fullname
,
778 (void)flags
; // Unused
779 (void)interfaceIndex
; // Unused
780 (void)fullname
; // Unused
781 (void)rrtype
; // Unused
782 (void)rrclass
; // Unused
783 (void)rdlen
; // Unused
784 (void)rdata
; // Unused
785 return(kDNSServiceErr_Unsupported
);