]>
Commit | Line | Data |
---|---|---|
f0cc3e7b A |
1 | /* |
2 | * Copyright (c) 2003-2019 Apple Inc. All rights reserved. | |
83fb1e36 | 3 | * |
67c8f8a1 A |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
83fb1e36 | 7 | * |
67c8f8a1 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
83fb1e36 | 9 | * |
67c8f8a1 A |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
8e92c31c | 14 | * limitations under the License. |
8e92c31c A |
15 | |
16 | * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs | |
7f0064bd A |
17 | * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space. |
18 | * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h | |
8e92c31c A |
19 | * function, and when mDNSCore calls the shim's callback, we call through to the client's callback. |
20 | * The shim is responsible for two main things: | |
21 | * - converting string parameters between C string format and native DNS format, | |
22 | * - and for allocating and freeing memory. | |
8e92c31c A |
23 | */ |
24 | ||
83fb1e36 A |
25 | #include "dns_sd.h" // Defines the interface to the client layer above |
26 | #include "mDNSEmbeddedAPI.h" // The interface we're building on top of | |
f0cc3e7b A |
27 | #include <sys/socket.h> |
28 | #include <netinet/in.h> | |
83fb1e36 | 29 | extern mDNS mDNSStorage; // We need to pass the address of this storage to the lower-layer functions |
8e92c31c A |
30 | |
31 | #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY | |
32 | #pragma export on | |
33 | #endif | |
34 | ||
35 | //************************************************************************************************************* | |
36 | // General Utility Functions | |
37 | ||
38 | // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function. | |
39 | // Optional type-specific data follows these three fields | |
40 | // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP | |
41 | // as the DNSServiceRef for the operation | |
42 | // We stash the value in core context fields so we can get it back to recover our state in our callbacks, | |
43 | // and pass it though to the client for it to recover its state | |
44 | ||
45 | typedef struct mDNS_DirectOP_struct mDNS_DirectOP; | |
83fb1e36 | 46 | typedef void mDNS_DirectOP_Dispose (mDNS_DirectOP *op); |
8e92c31c | 47 | struct mDNS_DirectOP_struct |
83fb1e36 A |
48 | { |
49 | mDNS_DirectOP_Dispose *disposefn; | |
50 | }; | |
8e92c31c A |
51 | |
52 | typedef struct | |
83fb1e36 A |
53 | { |
54 | mDNS_DirectOP_Dispose *disposefn; | |
55 | DNSServiceRegisterReply callback; | |
56 | void *context; | |
57 | mDNSBool autoname; // Set if this name is tied to the Computer Name | |
58 | mDNSBool autorename; // Set if we just got a name conflict and now need to automatically pick a new name | |
59 | domainlabel name; | |
60 | domainname host; | |
61 | ServiceRecordSet s; | |
62 | } mDNS_DirectOP_Register; | |
8e92c31c A |
63 | |
64 | typedef struct | |
83fb1e36 A |
65 | { |
66 | mDNS_DirectOP_Dispose *disposefn; | |
67 | DNSServiceBrowseReply callback; | |
68 | void *context; | |
69 | DNSQuestion q; | |
70 | } mDNS_DirectOP_Browse; | |
8e92c31c A |
71 | |
72 | typedef struct | |
83fb1e36 A |
73 | { |
74 | mDNS_DirectOP_Dispose *disposefn; | |
75 | DNSServiceResolveReply callback; | |
76 | void *context; | |
77 | const ResourceRecord *SRV; | |
78 | const ResourceRecord *TXT; | |
79 | DNSQuestion qSRV; | |
80 | DNSQuestion qTXT; | |
81 | } mDNS_DirectOP_Resolve; | |
8e92c31c A |
82 | |
83 | typedef struct | |
83fb1e36 A |
84 | { |
85 | mDNS_DirectOP_Dispose *disposefn; | |
86 | DNSServiceQueryRecordReply callback; | |
87 | void *context; | |
88 | DNSQuestion q; | |
89 | } mDNS_DirectOP_QueryRecord; | |
8e92c31c | 90 | |
f0cc3e7b A |
91 | typedef struct |
92 | { | |
93 | mDNS_DirectOP_Dispose *disposefn; | |
94 | DNSServiceGetAddrInfoReply callback; | |
95 | void *context; | |
96 | mDNSu32 interfaceIndex; | |
97 | DNSQuestion a; | |
98 | DNSQuestion aaaa; | |
99 | } mDNS_DirectOP_GetAddrInfo; | |
100 | ||
9f221bca | 101 | dnssd_sock_t DNSServiceRefSockFD(DNSServiceRef sdRef) |
83fb1e36 A |
102 | { |
103 | (void)sdRef; // Unused | |
104 | return(0); | |
105 | } | |
8e92c31c A |
106 | |
107 | DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef) | |
83fb1e36 A |
108 | { |
109 | (void)sdRef; // Unused | |
110 | return(kDNSServiceErr_NoError); | |
111 | } | |
8e92c31c A |
112 | |
113 | void DNSServiceRefDeallocate(DNSServiceRef sdRef) | |
83fb1e36 A |
114 | { |
115 | mDNS_DirectOP *op = (mDNS_DirectOP *)sdRef; | |
116 | //LogMsg("DNSServiceRefDeallocate"); | |
117 | op->disposefn(op); | |
118 | } | |
8e92c31c | 119 | |
f0cc3e7b A |
120 | static mDNSInterfaceID DNSServiceInterfaceIndexToID(mDNSu32 interfaceIndex, DNSServiceFlags *flags) |
121 | { | |
122 | // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P | |
123 | // flag set so that the resolve will run over P2P interfaces that are not yet created. | |
124 | if (interfaceIndex == kDNSServiceInterfaceIndexP2P) | |
125 | { | |
126 | LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P"); | |
127 | if (flags != mDNSNULL) *flags |= kDNSServiceFlagsIncludeP2P; | |
128 | interfaceIndex = kDNSServiceInterfaceIndexAny; | |
129 | } | |
130 | return mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); | |
131 | } | |
132 | ||
8e92c31c A |
133 | //************************************************************************************************************* |
134 | // Domain Enumeration | |
135 | ||
136 | // Not yet implemented, so don't include in stub library | |
137 | // We DO include it in the actual Extension, so that if a later client compiled to use this | |
138 | // is run against this Extension, it will get a reasonable error code instead of just | |
139 | // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link) | |
140 | #if !MDNS_BUILDINGSTUBLIBRARY | |
141 | DNSServiceErrorType DNSServiceEnumerateDomains | |
83fb1e36 A |
142 | ( |
143 | DNSServiceRef *sdRef, | |
144 | DNSServiceFlags flags, | |
145 | uint32_t interfaceIndex, | |
146 | DNSServiceDomainEnumReply callback, | |
147 | void *context /* may be NULL */ | |
148 | ) | |
149 | { | |
150 | (void)sdRef; // Unused | |
151 | (void)flags; // Unused | |
152 | (void)interfaceIndex; // Unused | |
153 | (void)callback; // Unused | |
154 | (void)context; // Unused | |
155 | return(kDNSServiceErr_Unsupported); | |
156 | } | |
8e92c31c A |
157 | #endif |
158 | ||
159 | //************************************************************************************************************* | |
160 | // Register Service | |
161 | ||
162 | mDNSlocal void FreeDNSServiceRegistration(mDNS_DirectOP_Register *x) | |
83fb1e36 A |
163 | { |
164 | while (x->s.Extras) | |
165 | { | |
166 | ExtraResourceRecord *extras = x->s.Extras; | |
167 | x->s.Extras = x->s.Extras->next; | |
168 | if (extras->r.resrec.rdata != &extras->r.rdatastorage) | |
169 | mDNSPlatformMemFree(extras->r.resrec.rdata); | |
170 | mDNSPlatformMemFree(extras); | |
171 | } | |
172 | ||
173 | if (x->s.RR_TXT.resrec.rdata != &x->s.RR_TXT.rdatastorage) | |
174 | mDNSPlatformMemFree(x->s.RR_TXT.resrec.rdata); | |
175 | ||
176 | if (x->s.SubTypes) mDNSPlatformMemFree(x->s.SubTypes); | |
177 | ||
178 | mDNSPlatformMemFree(x); | |
179 | } | |
8e92c31c A |
180 | |
181 | static void DNSServiceRegisterDispose(mDNS_DirectOP *op) | |
83fb1e36 A |
182 | { |
183 | mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)op; | |
184 | x->autorename = mDNSfalse; | |
185 | // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list, | |
186 | // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory. | |
187 | // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from | |
188 | // the list, so we should go ahead and free the memory right now | |
189 | if (mDNS_DeregisterService(&mDNSStorage, &x->s) != mStatus_NoError) | |
190 | FreeDNSServiceRegistration(x); | |
191 | } | |
8e92c31c A |
192 | |
193 | mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result) | |
83fb1e36 A |
194 | { |
195 | mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)sr->ServiceContext; | |
8e92c31c A |
196 | |
197 | domainlabel name; | |
198 | domainname type, dom; | |
83fb1e36 A |
199 | char namestr[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL. |
200 | char typestr[MAX_ESCAPED_DOMAIN_NAME]; | |
201 | char domstr [MAX_ESCAPED_DOMAIN_NAME]; | |
283ee3ff | 202 | if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return; |
8e92c31c A |
203 | if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return; |
204 | if (!ConvertDomainNameToCString(&type, typestr)) return; | |
205 | if (!ConvertDomainNameToCString(&dom, domstr)) return; | |
206 | ||
83fb1e36 A |
207 | if (result == mStatus_NoError) |
208 | { | |
209 | if (x->callback) | |
210 | x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context); | |
211 | } | |
212 | else if (result == mStatus_NameConflict) | |
213 | { | |
214 | if (x->autoname) mDNS_RenameAndReregisterService(m, sr, mDNSNULL); | |
215 | else if (x->callback) | |
216 | x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context); | |
217 | } | |
218 | else if (result == mStatus_MemFree) | |
219 | { | |
220 | if (x->autorename) | |
221 | { | |
222 | x->autorename = mDNSfalse; | |
223 | x->name = mDNSStorage.nicelabel; | |
224 | mDNS_RenameAndReregisterService(m, &x->s, &x->name); | |
225 | } | |
226 | else | |
227 | FreeDNSServiceRegistration(x); | |
228 | } | |
229 | } | |
8e92c31c A |
230 | |
231 | DNSServiceErrorType DNSServiceRegister | |
83fb1e36 A |
232 | ( |
233 | DNSServiceRef *sdRef, | |
234 | DNSServiceFlags flags, | |
235 | uint32_t interfaceIndex, | |
236 | const char *name, /* may be NULL */ | |
237 | const char *regtype, | |
238 | const char *domain, /* may be NULL */ | |
239 | const char *host, /* may be NULL */ | |
240 | uint16_t notAnIntPort, | |
241 | uint16_t txtLen, | |
242 | const void *txtRecord, /* may be NULL */ | |
243 | DNSServiceRegisterReply callback, /* may be NULL */ | |
244 | void *context /* may be NULL */ | |
245 | ) | |
246 | { | |
247 | mStatus err = mStatus_NoError; | |
248 | const char *errormsg = "Unknown"; | |
249 | domainlabel n; | |
250 | domainname t, d, h, srv; | |
251 | mDNSIPPort port; | |
252 | unsigned int size = sizeof(RDataBody); | |
253 | AuthRecord *SubTypes = mDNSNULL; | |
254 | mDNSu32 NumSubTypes = 0; | |
255 | mDNS_DirectOP_Register *x; | |
256 | (void)flags; // Unused | |
257 | (void)interfaceIndex; // Unused | |
258 | ||
259 | // Check parameters | |
260 | if (!name) name = ""; | |
261 | if (!name[0]) n = mDNSStorage.nicelabel; | |
262 | else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; } | |
263 | if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } | |
264 | if (!MakeDomainNameFromDNSNameString(&d, (domain && *domain) ? domain : "local.")) { errormsg = "Bad Domain"; goto badparam; } | |
265 | if (!MakeDomainNameFromDNSNameString(&h, (host && *host ) ? host : "")) { errormsg = "Bad Target Host"; goto badparam; } | |
266 | if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } | |
267 | port.NotAnInteger = notAnIntPort; | |
268 | ||
269 | // Allocate memory, and handle failure | |
270 | if (size < txtLen) | |
271 | size = txtLen; | |
f0cc3e7b | 272 | x = (mDNS_DirectOP_Register *) mDNSPlatformMemAllocateClear(sizeof(*x) - sizeof(RDataBody) + size); |
83fb1e36 A |
273 | if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } |
274 | ||
275 | // Set up object | |
276 | x->disposefn = DNSServiceRegisterDispose; | |
277 | x->callback = callback; | |
278 | x->context = context; | |
279 | x->autoname = (!name[0]); | |
280 | x->autorename = mDNSfalse; | |
281 | x->name = n; | |
282 | x->host = h; | |
283 | ||
284 | // Do the operation | |
285 | err = mDNS_RegisterService(&mDNSStorage, &x->s, | |
286 | &x->name, &t, &d, // Name, type, domain | |
287 | &x->host, port, // Host and port | |
f0cc3e7b | 288 | mDNSNULL, |
83fb1e36 A |
289 | txtRecord, txtLen, // TXT data, length |
290 | SubTypes, NumSubTypes, // Subtypes | |
291 | mDNSInterface_Any, // Interface ID | |
292 | RegCallback, x, 0); // Callback, context, flags | |
293 | if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_RegisterService"; goto fail; } | |
294 | ||
295 | // Succeeded: Wrap up and return | |
296 | *sdRef = (DNSServiceRef)x; | |
297 | return(mStatus_NoError); | |
8e92c31c A |
298 | |
299 | badparam: | |
83fb1e36 | 300 | err = mStatus_BadParamErr; |
8e92c31c | 301 | fail: |
83fb1e36 A |
302 | LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err); |
303 | return(err); | |
304 | } | |
8e92c31c A |
305 | |
306 | //************************************************************************************************************* | |
307 | // Add / Update / Remove records from existing Registration | |
308 | ||
309 | // Not yet implemented, so don't include in stub library | |
310 | // We DO include it in the actual Extension, so that if a later client compiled to use this | |
311 | // is run against this Extension, it will get a reasonable error code instead of just | |
312 | // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link) | |
313 | #if !MDNS_BUILDINGSTUBLIBRARY | |
314 | DNSServiceErrorType DNSServiceAddRecord | |
83fb1e36 A |
315 | ( |
316 | DNSServiceRef sdRef, | |
317 | DNSRecordRef *RecordRef, | |
318 | DNSServiceFlags flags, | |
319 | uint16_t rrtype, | |
320 | uint16_t rdlen, | |
321 | const void *rdata, | |
322 | uint32_t ttl | |
323 | ) | |
324 | { | |
325 | (void)sdRef; // Unused | |
326 | (void)RecordRef; // Unused | |
327 | (void)flags; // Unused | |
328 | (void)rrtype; // Unused | |
329 | (void)rdlen; // Unused | |
330 | (void)rdata; // Unused | |
331 | (void)ttl; // Unused | |
332 | return(kDNSServiceErr_Unsupported); | |
333 | } | |
8e92c31c A |
334 | |
335 | DNSServiceErrorType DNSServiceUpdateRecord | |
83fb1e36 A |
336 | ( |
337 | DNSServiceRef sdRef, | |
338 | DNSRecordRef RecordRef, /* may be NULL */ | |
339 | DNSServiceFlags flags, | |
340 | uint16_t rdlen, | |
341 | const void *rdata, | |
342 | uint32_t ttl | |
343 | ) | |
344 | { | |
345 | (void)sdRef; // Unused | |
346 | (void)RecordRef; // Unused | |
347 | (void)flags; // Unused | |
348 | (void)rdlen; // Unused | |
349 | (void)rdata; // Unused | |
350 | (void)ttl; // Unused | |
351 | return(kDNSServiceErr_Unsupported); | |
352 | } | |
8e92c31c A |
353 | |
354 | DNSServiceErrorType DNSServiceRemoveRecord | |
83fb1e36 A |
355 | ( |
356 | DNSServiceRef sdRef, | |
357 | DNSRecordRef RecordRef, | |
358 | DNSServiceFlags flags | |
359 | ) | |
360 | { | |
361 | (void)sdRef; // Unused | |
362 | (void)RecordRef; // Unused | |
363 | (void)flags; // Unused | |
364 | return(kDNSServiceErr_Unsupported); | |
365 | } | |
8e92c31c A |
366 | #endif |
367 | ||
368 | //************************************************************************************************************* | |
369 | // Browse for services | |
370 | ||
371 | static void DNSServiceBrowseDispose(mDNS_DirectOP *op) | |
83fb1e36 A |
372 | { |
373 | mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)op; | |
374 | //LogMsg("DNSServiceBrowseDispose"); | |
375 | mDNS_StopBrowse(&mDNSStorage, &x->q); | |
376 | mDNSPlatformMemFree(x); | |
377 | } | |
8e92c31c | 378 | |
67c8f8a1 | 379 | mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) |
83fb1e36 A |
380 | { |
381 | DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0; | |
382 | domainlabel name; | |
383 | domainname type, domain; | |
384 | char cname[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL. | |
385 | char ctype[MAX_ESCAPED_DOMAIN_NAME]; | |
386 | char cdom [MAX_ESCAPED_DOMAIN_NAME]; | |
387 | mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)question->QuestionContext; | |
388 | (void)m; // Unused | |
389 | ||
390 | if (answer->rrtype != kDNSType_PTR) | |
391 | { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; } | |
392 | ||
393 | if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain)) | |
394 | { | |
395 | LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer", | |
396 | answer->name->c, answer->rdata->u.name.c); | |
397 | return; | |
398 | } | |
399 | ||
400 | ConvertDomainLabelToCString_unescaped(&name, cname); | |
401 | ConvertDomainNameToCString(&type, ctype); | |
402 | ConvertDomainNameToCString(&domain, cdom); | |
403 | if (x->callback) | |
404 | x->callback((DNSServiceRef)x, flags, 0, 0, cname, ctype, cdom, x->context); | |
405 | } | |
8e92c31c A |
406 | |
407 | DNSServiceErrorType DNSServiceBrowse | |
83fb1e36 A |
408 | ( |
409 | DNSServiceRef *sdRef, | |
410 | DNSServiceFlags flags, | |
411 | uint32_t interfaceIndex, | |
412 | const char *regtype, | |
413 | const char *domain, /* may be NULL */ | |
414 | DNSServiceBrowseReply callback, | |
415 | void *context /* may be NULL */ | |
416 | ) | |
417 | { | |
418 | mStatus err = mStatus_NoError; | |
419 | const char *errormsg = "Unknown"; | |
420 | domainname t, d; | |
421 | mDNS_DirectOP_Browse *x; | |
422 | (void)flags; // Unused | |
423 | (void)interfaceIndex; // Unused | |
424 | ||
425 | // Check parameters | |
426 | if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; } | |
427 | if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; } | |
428 | ||
429 | // Allocate memory, and handle failure | |
f0cc3e7b | 430 | x = (mDNS_DirectOP_Browse *) mDNSPlatformMemAllocateClear(sizeof(*x)); |
83fb1e36 A |
431 | if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } |
432 | ||
433 | // Set up object | |
434 | x->disposefn = DNSServiceBrowseDispose; | |
435 | x->callback = callback; | |
436 | x->context = context; | |
437 | x->q.QuestionContext = x; | |
438 | ||
439 | // Do the operation | |
f0cc3e7b | 440 | err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, flags, (flags & kDNSServiceFlagsForceMulticast) != 0, (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, x); |
83fb1e36 A |
441 | if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; } |
442 | ||
443 | // Succeeded: Wrap up and return | |
444 | *sdRef = (DNSServiceRef)x; | |
445 | return(mStatus_NoError); | |
8e92c31c A |
446 | |
447 | badparam: | |
83fb1e36 | 448 | err = mStatus_BadParamErr; |
8e92c31c | 449 | fail: |
83fb1e36 A |
450 | LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err); |
451 | return(err); | |
452 | } | |
8e92c31c A |
453 | |
454 | //************************************************************************************************************* | |
455 | // Resolve Service Info | |
456 | ||
457 | static void DNSServiceResolveDispose(mDNS_DirectOP *op) | |
83fb1e36 A |
458 | { |
459 | mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)op; | |
460 | if (x->qSRV.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qSRV); | |
461 | if (x->qTXT.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qTXT); | |
462 | mDNSPlatformMemFree(x); | |
463 | } | |
8e92c31c | 464 | |
67c8f8a1 | 465 | mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) |
83fb1e36 A |
466 | { |
467 | mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext; | |
468 | (void)m; // Unused | |
469 | if (!AddRecord) | |
470 | { | |
471 | if (answer->rrtype == kDNSType_SRV && x->SRV == answer) x->SRV = mDNSNULL; | |
472 | if (answer->rrtype == kDNSType_TXT && x->TXT == answer) x->TXT = mDNSNULL; | |
473 | } | |
474 | else | |
475 | { | |
476 | if (answer->rrtype == kDNSType_SRV) x->SRV = answer; | |
477 | if (answer->rrtype == kDNSType_TXT) x->TXT = answer; | |
478 | if (x->SRV && x->TXT && x->callback) | |
479 | { | |
480 | char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME]; | |
481 | ConvertDomainNameToCString(answer->name, fullname); | |
482 | ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost); | |
483 | x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost, | |
484 | x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (unsigned char*)x->TXT->rdata->u.txt.c, x->context); | |
485 | } | |
486 | } | |
487 | } | |
8e92c31c A |
488 | |
489 | DNSServiceErrorType DNSServiceResolve | |
83fb1e36 A |
490 | ( |
491 | DNSServiceRef *sdRef, | |
492 | DNSServiceFlags flags, | |
493 | uint32_t interfaceIndex, | |
494 | const char *name, | |
495 | const char *regtype, | |
496 | const char *domain, | |
497 | DNSServiceResolveReply callback, | |
498 | void *context /* may be NULL */ | |
499 | ) | |
500 | { | |
501 | mStatus err = mStatus_NoError; | |
502 | const char *errormsg = "Unknown"; | |
503 | domainlabel n; | |
504 | domainname t, d, srv; | |
505 | mDNS_DirectOP_Resolve *x; | |
506 | ||
83fb1e36 A |
507 | // Check parameters |
508 | if (!name[0] || !MakeDomainLabelFromLiteralString(&n, name )) { errormsg = "Bad Instance Name"; goto badparam; } | |
509 | if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } | |
510 | if (!domain[0] || !MakeDomainNameFromDNSNameString(&d, domain )) { errormsg = "Bad Domain"; goto badparam; } | |
511 | if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } | |
512 | ||
513 | // Allocate memory, and handle failure | |
f0cc3e7b | 514 | x = (mDNS_DirectOP_Resolve *) mDNSPlatformMemAllocateClear(sizeof(*x)); |
83fb1e36 A |
515 | if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } |
516 | ||
517 | // Set up object | |
518 | x->disposefn = DNSServiceResolveDispose; | |
519 | x->callback = callback; | |
520 | x->context = context; | |
521 | x->SRV = mDNSNULL; | |
522 | x->TXT = mDNSNULL; | |
523 | ||
524 | x->qSRV.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question | |
f0cc3e7b A |
525 | x->qSRV.InterfaceID = DNSServiceInterfaceIndexToID(interfaceIndex, &flags); |
526 | x->qSRV.flags = flags; | |
83fb1e36 A |
527 | AssignDomainName(&x->qSRV.qname, &srv); |
528 | x->qSRV.qtype = kDNSType_SRV; | |
529 | x->qSRV.qclass = kDNSClass_IN; | |
530 | x->qSRV.LongLived = mDNSfalse; | |
531 | x->qSRV.ExpectUnique = mDNStrue; | |
532 | x->qSRV.ForceMCast = mDNSfalse; | |
533 | x->qSRV.ReturnIntermed = mDNSfalse; | |
534 | x->qSRV.SuppressUnusable = mDNSfalse; | |
83fb1e36 | 535 | x->qSRV.AppendSearchDomains = 0; |
83fb1e36 A |
536 | x->qSRV.TimeoutQuestion = 0; |
537 | x->qSRV.WakeOnResolve = 0; | |
f0cc3e7b | 538 | x->qSRV.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0; |
51601d48 | 539 | x->qSRV.ProxyQuestion = 0; |
51601d48 | 540 | x->qSRV.pid = mDNSPlatformGetPID(); |
83fb1e36 A |
541 | x->qSRV.QuestionCallback = FoundServiceInfo; |
542 | x->qSRV.QuestionContext = x; | |
543 | ||
544 | x->qTXT.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question | |
f0cc3e7b A |
545 | x->qTXT.InterfaceID = DNSServiceInterfaceIndexToID(interfaceIndex, mDNSNULL); |
546 | x->qTXT.flags = flags; | |
83fb1e36 A |
547 | AssignDomainName(&x->qTXT.qname, &srv); |
548 | x->qTXT.qtype = kDNSType_TXT; | |
549 | x->qTXT.qclass = kDNSClass_IN; | |
550 | x->qTXT.LongLived = mDNSfalse; | |
551 | x->qTXT.ExpectUnique = mDNStrue; | |
552 | x->qTXT.ForceMCast = mDNSfalse; | |
553 | x->qTXT.ReturnIntermed = mDNSfalse; | |
554 | x->qTXT.SuppressUnusable = mDNSfalse; | |
83fb1e36 | 555 | x->qTXT.AppendSearchDomains = 0; |
83fb1e36 A |
556 | x->qTXT.TimeoutQuestion = 0; |
557 | x->qTXT.WakeOnResolve = 0; | |
f0cc3e7b | 558 | x->qTXT.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0; |
51601d48 | 559 | x->qTXT.ProxyQuestion = 0; |
51601d48 | 560 | x->qTXT.pid = mDNSPlatformGetPID(); |
83fb1e36 A |
561 | x->qTXT.QuestionCallback = FoundServiceInfo; |
562 | x->qTXT.QuestionContext = x; | |
563 | ||
564 | err = mDNS_StartQuery(&mDNSStorage, &x->qSRV); | |
565 | if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qSRV"; goto fail; } | |
566 | err = mDNS_StartQuery(&mDNSStorage, &x->qTXT); | |
567 | if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qTXT"; goto fail; } | |
568 | ||
569 | // Succeeded: Wrap up and return | |
570 | *sdRef = (DNSServiceRef)x; | |
571 | return(mStatus_NoError); | |
8e92c31c A |
572 | |
573 | badparam: | |
83fb1e36 | 574 | err = mStatus_BadParamErr; |
8e92c31c | 575 | fail: |
83fb1e36 A |
576 | LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name, regtype, domain, errormsg, err); |
577 | return(err); | |
578 | } | |
8e92c31c A |
579 | |
580 | //************************************************************************************************************* | |
581 | // Connection-oriented calls | |
582 | ||
583 | // Not yet implemented, so don't include in stub library | |
584 | // We DO include it in the actual Extension, so that if a later client compiled to use this | |
585 | // is run against this Extension, it will get a reasonable error code instead of just | |
586 | // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link) | |
587 | #if !MDNS_BUILDINGSTUBLIBRARY | |
588 | DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef) | |
83fb1e36 A |
589 | { |
590 | (void)sdRef; // Unused | |
591 | return(kDNSServiceErr_Unsupported); | |
592 | } | |
8e92c31c A |
593 | |
594 | DNSServiceErrorType DNSServiceRegisterRecord | |
83fb1e36 A |
595 | ( |
596 | DNSServiceRef sdRef, | |
597 | DNSRecordRef *RecordRef, | |
598 | DNSServiceFlags flags, | |
599 | uint32_t interfaceIndex, | |
600 | const char *fullname, | |
601 | uint16_t rrtype, | |
602 | uint16_t rrclass, | |
603 | uint16_t rdlen, | |
604 | const void *rdata, | |
605 | uint32_t ttl, | |
606 | DNSServiceRegisterRecordReply callback, | |
607 | void *context /* may be NULL */ | |
608 | ) | |
609 | { | |
610 | (void)sdRef; // Unused | |
611 | (void)RecordRef; // Unused | |
612 | (void)flags; // Unused | |
613 | (void)interfaceIndex; // Unused | |
614 | (void)fullname; // Unused | |
615 | (void)rrtype; // Unused | |
616 | (void)rrclass; // Unused | |
617 | (void)rdlen; // Unused | |
618 | (void)rdata; // Unused | |
619 | (void)ttl; // Unused | |
620 | (void)callback; // Unused | |
621 | (void)context; // Unused | |
622 | return(kDNSServiceErr_Unsupported); | |
623 | } | |
8e92c31c A |
624 | #endif |
625 | ||
626 | //************************************************************************************************************* | |
627 | // DNSServiceQueryRecord | |
628 | ||
629 | static void DNSServiceQueryRecordDispose(mDNS_DirectOP *op) | |
83fb1e36 A |
630 | { |
631 | mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)op; | |
632 | if (x->q.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->q); | |
633 | mDNSPlatformMemFree(x); | |
634 | } | |
8e92c31c | 635 | |
67c8f8a1 | 636 | mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) |
83fb1e36 A |
637 | { |
638 | mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext; | |
639 | char fullname[MAX_ESCAPED_DOMAIN_NAME]; | |
640 | (void)m; // Unused | |
641 | ConvertDomainNameToCString(answer->name, fullname); | |
642 | x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError, | |
643 | fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context); | |
644 | } | |
8e92c31c A |
645 | |
646 | DNSServiceErrorType DNSServiceQueryRecord | |
83fb1e36 | 647 | ( |
f0cc3e7b A |
648 | DNSServiceRef *sdRef, |
649 | DNSServiceFlags flags, | |
650 | uint32_t interfaceIndex, | |
651 | const char *fullname, | |
652 | uint16_t rrtype, | |
653 | uint16_t rrclass, | |
83fb1e36 | 654 | DNSServiceQueryRecordReply callback, |
f0cc3e7b | 655 | void *context /* may be NULL */ |
83fb1e36 A |
656 | ) |
657 | { | |
658 | mStatus err = mStatus_NoError; | |
659 | const char *errormsg = "Unknown"; | |
660 | mDNS_DirectOP_QueryRecord *x; | |
661 | ||
83fb1e36 | 662 | // Allocate memory, and handle failure |
f0cc3e7b | 663 | x = (mDNS_DirectOP_QueryRecord *) mDNSPlatformMemAllocateClear(sizeof(*x)); |
83fb1e36 A |
664 | if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } |
665 | ||
666 | // Set up object | |
667 | x->disposefn = DNSServiceQueryRecordDispose; | |
668 | x->callback = callback; | |
669 | x->context = context; | |
670 | ||
f0cc3e7b A |
671 | x->q.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question |
672 | x->q.InterfaceID = DNSServiceInterfaceIndexToID(interfaceIndex, &flags); | |
673 | x->q.flags = flags; | |
83fb1e36 | 674 | MakeDomainNameFromDNSNameString(&x->q.qname, fullname); |
f0cc3e7b A |
675 | x->q.qtype = rrtype; |
676 | x->q.qclass = rrclass; | |
677 | x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0; | |
678 | x->q.ExpectUnique = mDNSfalse; | |
679 | x->q.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0; | |
680 | x->q.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0; | |
681 | x->q.SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable) != 0; | |
682 | x->q.AppendSearchDomains = 0; | |
683 | x->q.TimeoutQuestion = 0; | |
684 | x->q.WakeOnResolve = 0; | |
685 | x->q.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0; | |
f0cc3e7b A |
686 | x->q.ProxyQuestion = 0; |
687 | x->q.pid = mDNSPlatformGetPID(); | |
688 | x->q.QuestionCallback = DNSServiceQueryRecordResponse; | |
689 | x->q.QuestionContext = x; | |
83fb1e36 A |
690 | |
691 | err = mDNS_StartQuery(&mDNSStorage, &x->q); | |
692 | if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; } | |
693 | ||
694 | // Succeeded: Wrap up and return | |
695 | *sdRef = (DNSServiceRef)x; | |
696 | return(mStatus_NoError); | |
8e92c31c | 697 | |
8e92c31c | 698 | fail: |
83fb1e36 A |
699 | LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err); |
700 | return(err); | |
701 | } | |
8e92c31c A |
702 | |
703 | //************************************************************************************************************* | |
263eeeab | 704 | // DNSServiceGetAddrInfo |
f0cc3e7b | 705 | // |
263eeeab A |
706 | |
707 | static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op) | |
83fb1e36 A |
708 | { |
709 | mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op; | |
f0cc3e7b A |
710 | if (x->a.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->a); |
711 | if (x->aaaa.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->aaaa); | |
83fb1e36 A |
712 | mDNSPlatformMemFree(x); |
713 | } | |
263eeeab | 714 | |
f0cc3e7b A |
715 | mDNSlocal void DNSServiceGetAddrInfoResponse(mDNS *const m, DNSQuestion *question, |
716 | const ResourceRecord *const answer, QC_result addRecord) | |
717 | { | |
718 | mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)question->QuestionContext; | |
719 | char fullname[MAX_ESCAPED_DOMAIN_NAME]; | |
720 | ||
721 | struct sockaddr_storage sas; | |
722 | struct sockaddr_in *sin = (struct sockaddr_in *)&sas; | |
723 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sas; | |
724 | void *sa_ap = mDNSNULL; | |
725 | int sa_as = 0; | |
726 | mStatus err = mStatus_NoError; | |
727 | ||
728 | (void)m; // Unused | |
729 | ||
730 | mDNSPlatformMemZero(&sas, sizeof sas); | |
731 | ||
732 | ConvertDomainNameToCString(answer->name, fullname); | |
733 | ||
734 | if (addRecord == QC_suppressed || answer->RecordType == kDNSRecordTypePacketNegative) | |
83fb1e36 | 735 | { |
f0cc3e7b A |
736 | err = mStatus_NoSuchRecord; |
737 | } | |
738 | ||
739 | // There are three checks here for bad data: class != IN, RRTYPE not in {A,AAAA} and wrong length. | |
740 | // None of these should be possible, because the cache code wouldn't cache malformed data and wouldn't | |
741 | // return records we didn't ask for, but it doesn't hurt to check. | |
742 | if (answer->rrclass != kDNSServiceClass_IN) | |
743 | { | |
744 | LogMsg("DNSServiceGetAddrInfoResponse: response of class %d received, which is bogus", answer->rrclass); | |
745 | totally_invalid: | |
746 | if (x->a.ThisQInterval >= 0) | |
747 | { | |
748 | sin->sin_family = AF_INET; | |
749 | #ifndef NOT_HAVE_SA_LEN | |
750 | sin->sin_len = sizeof *sin; | |
751 | #endif | |
752 | x->callback((DNSServiceRef)x, 0, x->interfaceIndex, kDNSServiceErr_Invalid, fullname, | |
753 | (const struct sockaddr *)&sas, 0, x->context); | |
754 | } | |
755 | if (x->aaaa.ThisQInterval >= 0) | |
756 | { | |
757 | sin6->sin6_family = AF_INET6; | |
758 | #ifndef NOT_HAVE_SA_LEN | |
759 | sin6->sin6_len = sizeof *sin6; | |
760 | #endif | |
761 | x->callback((DNSServiceRef)x, 0, x->interfaceIndex, kDNSServiceErr_Invalid, fullname, | |
762 | (const struct sockaddr *)&sas, 0, x->context); | |
763 | } | |
764 | return; | |
765 | } | |
766 | else if (answer->rrtype == kDNSServiceType_A) | |
767 | { | |
768 | sin->sin_family = AF_INET; | |
769 | #ifndef NOT_HAVE_SA_LEN | |
770 | sin->sin_len = sizeof *sin; | |
771 | #endif | |
772 | sa_ap = &sin->sin_addr; | |
773 | sa_as = sizeof sin->sin_addr.s_addr; | |
774 | } | |
775 | else if (answer->rrtype == kDNSServiceType_AAAA) | |
776 | { | |
777 | sin6->sin6_family = AF_INET6; | |
778 | #ifndef NOT_HAVE_SA_LEN | |
779 | sin6->sin6_len = sizeof *sin6; | |
780 | #endif | |
781 | sa_ap = &sin6->sin6_addr; | |
782 | sa_as = sizeof sin6->sin6_addr.s6_addr; | |
783 | } | |
784 | else | |
785 | { | |
786 | LogMsg("DNSServiceGetAddrInfoResponse: response of type %d received, which is bogus", answer->rrtype); | |
787 | goto totally_invalid; | |
788 | } | |
789 | ||
790 | if (err == kDNSServiceErr_NoError && sa_ap != mDNSNULL) | |
791 | { | |
792 | if (err == mStatus_NoError) | |
793 | { | |
794 | if (answer->rdlength == sa_as) | |
795 | { | |
796 | mDNSPlatformMemCopy(sa_ap, answer->rdata->u.data, answer->rdlength); | |
797 | } | |
798 | else | |
799 | { | |
800 | LogMsg("DNSServiceGetAddrInfoResponse: %s rrtype with length %d received", | |
801 | answer->rrtype == kDNSServiceType_A ? "A" : "AAAA", answer->rdlength); | |
802 | goto totally_invalid; | |
803 | } | |
804 | } | |
83fb1e36 A |
805 | } |
806 | ||
f0cc3e7b A |
807 | x->callback((DNSServiceRef)x, addRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, x->interfaceIndex, err, |
808 | fullname, (const struct sockaddr *)&sas, answer->rroriginalttl, x->context); | |
83fb1e36 | 809 | } |
263eeeab A |
810 | |
811 | DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo( | |
f0cc3e7b A |
812 | DNSServiceRef *outRef, |
813 | DNSServiceFlags inFlags, | |
814 | uint32_t inInterfaceIndex, | |
815 | DNSServiceProtocol inProtocol, | |
816 | const char *inHostName, | |
83fb1e36 | 817 | DNSServiceGetAddrInfoReply inCallback, |
f0cc3e7b | 818 | void *inContext ) |
83fb1e36 | 819 | { |
f0cc3e7b A |
820 | const char *errormsg = "Unknown"; |
821 | DNSServiceErrorType err; | |
822 | mDNS_DirectOP_GetAddrInfo *x; | |
83fb1e36 A |
823 | |
824 | // Allocate memory, and handle failure | |
f0cc3e7b | 825 | x = (mDNS_DirectOP_GetAddrInfo *) mDNSPlatformMemAllocateClear(sizeof(*x)); |
83fb1e36 A |
826 | if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } |
827 | ||
828 | // Set up object | |
f0cc3e7b A |
829 | x->disposefn = DNSServiceGetAddrInfoDispose; |
830 | x->callback = inCallback; | |
831 | x->context = inContext; | |
832 | x->interfaceIndex = inInterfaceIndex; | |
833 | ||
834 | // Validate and default the protocols. | |
835 | if ((inProtocol & ~(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6)) != 0) | |
836 | { | |
837 | err = mStatus_BadParamErr; | |
838 | errormsg = "Unsupported protocol"; | |
839 | goto fail; | |
840 | } | |
841 | // In theory this API checks to see if we have a routable IPv6 address, but | |
842 | if ((inProtocol & (kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6)) == 0) | |
843 | { | |
844 | inProtocol = kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6; | |
845 | inFlags |= kDNSServiceFlagsSuppressUnusable; | |
846 | } | |
847 | ||
848 | x->a.ThisQInterval = -1; // So we know whether to cancel this question | |
849 | x->a.InterfaceID = DNSServiceInterfaceIndexToID(inInterfaceIndex, &inFlags); | |
850 | x->a.flags = inFlags; | |
851 | MakeDomainNameFromDNSNameString(&x->a.qname, inHostName); | |
852 | x->a.qtype = kDNSType_A; | |
853 | x->a.qclass = kDNSClass_IN; | |
854 | x->a.LongLived = (inFlags & kDNSServiceFlagsLongLivedQuery) != 0; | |
855 | x->a.ExpectUnique = mDNSfalse; | |
856 | x->a.ForceMCast = (inFlags & kDNSServiceFlagsForceMulticast) != 0; | |
857 | x->a.ReturnIntermed = (inFlags & kDNSServiceFlagsReturnIntermediates) != 0; | |
858 | x->a.SuppressUnusable = (inFlags & kDNSServiceFlagsSuppressUnusable) != 0; | |
859 | x->a.AppendSearchDomains = 0; | |
860 | x->a.TimeoutQuestion = 0; | |
861 | x->a.WakeOnResolve = 0; | |
862 | x->a.UseBackgroundTraffic = (inFlags & kDNSServiceFlagsBackgroundTrafficClass) != 0; | |
f0cc3e7b A |
863 | x->a.ProxyQuestion = 0; |
864 | x->a.pid = mDNSPlatformGetPID(); | |
865 | x->a.QuestionCallback = DNSServiceGetAddrInfoResponse; | |
866 | x->a.QuestionContext = x; | |
867 | ||
868 | x->aaaa = x->a; | |
869 | x->aaaa.qtype = kDNSType_AAAA; | |
870 | ||
871 | if (inProtocol & kDNSServiceProtocol_IPv4) | |
872 | { | |
873 | err = mDNS_StartQuery(&mDNSStorage, &x->a); | |
874 | if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; } | |
875 | } | |
876 | if (inProtocol & kDNSServiceProtocol_IPv6) | |
877 | { | |
878 | err = mDNS_StartQuery(&mDNSStorage, &x->aaaa); | |
879 | if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; } | |
880 | } | |
83fb1e36 A |
881 | |
882 | *outRef = (DNSServiceRef)x; | |
883 | return(mStatus_NoError); | |
884 | ||
263eeeab | 885 | fail: |
83fb1e36 A |
886 | LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err); |
887 | return(err); | |
888 | } | |
263eeeab A |
889 | |
890 | //************************************************************************************************************* | |
8e92c31c A |
891 | // DNSServiceReconfirmRecord |
892 | ||
893 | // Not yet implemented, so don't include in stub library | |
894 | // We DO include it in the actual Extension, so that if a later client compiled to use this | |
895 | // is run against this Extension, it will get a reasonable error code instead of just | |
896 | // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link) | |
897 | #if !MDNS_BUILDINGSTUBLIBRARY | |
67c8f8a1 | 898 | DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord |
83fb1e36 A |
899 | ( |
900 | DNSServiceFlags flags, | |
901 | uint32_t interfaceIndex, | |
902 | const char *fullname, | |
903 | uint16_t rrtype, | |
904 | uint16_t rrclass, | |
905 | uint16_t rdlen, | |
906 | const void *rdata | |
907 | ) | |
908 | { | |
909 | (void)flags; // Unused | |
910 | (void)interfaceIndex; // Unused | |
911 | (void)fullname; // Unused | |
912 | (void)rrtype; // Unused | |
913 | (void)rrclass; // Unused | |
914 | (void)rdlen; // Unused | |
915 | (void)rdata; // Unused | |
916 | return(kDNSServiceErr_Unsupported); | |
917 | } | |
509d285a | 918 | |
f0cc3e7b | 919 | #endif // !MDNS_BUILDINGSTUBLIBRARY |
b8d5688b | 920 | |
f0cc3e7b A |
921 | // Local Variables: |
922 | // mode: C | |
923 | // tab-width: 4 | |
924 | // c-file-style: "bsd" | |
925 | // c-basic-offset: 4 | |
926 | // fill-column: 108 | |
927 | // indent-tabs-mode: nil | |
928 | // End: |