1 /*
2 * Dynamic wrapper for Bonjour SDK for Windows.
3 *
4 * Copyright © 2020-2024 by OpenPrinting.
5 * Copyright 2018 by Apple Inc.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
8 * information.
9 */
10
11 //#include <cups/http-private.h>
12 #include <cups/thread-private.h>
13 #include "dns_sd.h"
14
15
16 /*
17 * Pointers for functions...
18 */
19
20 static int dnssd_initialized = 0;
21 static _cups_mutex_t dnssd_mutex = _CUPS_MUTEX_INITIALIZER;
22 static DNSServiceErrorType (*dnssd_add_record)(DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint16_t rrtype, uint16_t rdlen, const void *rdata, uint32_t ttl);
23 static DNSServiceErrorType (*dnssd_browse)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, DNSServiceBrowseReply callBack, void *context);
24 static DNSServiceErrorType (*dnssd_construct_full_name)(char * const fullName, const char * const service, const char * const regtype, const char * const domain);
25 static DNSServiceErrorType (*dnssd_create_connection)(DNSServiceRef *sdRef);
26 static DNSServiceErrorType (*dnssd_process_result)(DNSServiceRef sdRef);
27 static DNSServiceErrorType (*dnssd_query_record)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callBack, void *context);
28 static void (*dnssd_deallocate)(DNSServiceRef sdRef);
29 static int (*dnssd_sock_fd)(DNSServiceRef sdRef);
30 static DNSServiceErrorType (*dnssd_register)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, const char *host, uint16_t port, uint16_t txtLen, const void *txtRecord, DNSServiceRegisterReply callBack, void *context);
31 static DNSServiceErrorType (*dnssd_remove_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags);
32 static DNSServiceErrorType (*dnssd_resolve)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, DNSServiceResolveReply callBack, void *context);
33 static DNSServiceErrorType (*dnssd_update_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, uint16_t rdlen, const void *rdata, uint32_t ttl);
34
35 static void (*dnssd_txt_create)(TXTRecordRef *txtRecord, uint16_t bufferLen, void *buffer);
36 static void (*dnssd_txt_deallocate)(TXTRecordRef *txtRecord);
37 static const void *(*dnssd_txt_get_bytes_ptr)(const TXTRecordRef *txtRecord);
38 static uint16_t (*dnssd_txt_get_count)(uint16_t txtLen, const void *txtRecord);
39 static uint16_t (*dnssd_txt_get_length)(const TXTRecordRef *txtRecord);
40 static DNSServiceErrorType (*dnssd_txt_get_item_at_index)(uint16_t txtLen, const void *txtRecord, uint16_t itemIndex, uint16_t keyBufLen, char *key, uint8_t *valueLen, const void **value);
41 static const void *(*dnssd_txt_get_value_ptr)(uint16_t txtLen, const void *txtRecord, const char *key, uint8_t *valueLen);
42 static DNSServiceErrorType (*dnssd_txt_set_value)(TXTRecordRef *txtRecord, const char *key, uint8_t valueSize, const void *value);
43
44
45 /*
46 * Function to initialize pointers...
47 */
48
49 static void
dnssd_init(void)50 dnssd_init(void)
51 {
52 _cupsMutexLock(&dnssd_mutex);
53 if (!dnssd_initialized)
54 {
55 HINSTANCE dll_handle = LoadLibraryA("dnssd.dll");
56
57 if (dll_handle)
58 {
59 dnssd_add_record = (DNSServiceErrorType (*)(DNSServiceRef, DNSRecordRef *, DNSServiceFlags, uint16_t, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceAddRecord");
60 dnssd_browse = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, DNSServiceBrowseReply, void *))GetProcAddress(dll_handle, "DNSServiceBrowse");
61 dnssd_construct_full_name = (DNSServiceErrorType(*)(char * const, const char * const, const char * const, const char * const))GetProcAddress(dll_handle, "DNSServiceConstructFullName");
62 dnssd_create_connection = (DNSServiceErrorType(*)(DNSServiceRef *))GetProcAddress(dll_handle, "DNSServiceCreateConnection");
63 dnssd_deallocate = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefDeallocate");
64 dnssd_process_result = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceProcessResult");
65 dnssd_query_record = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, uint16_t, uint16_t, DNSServiceQueryRecordReply, void *))GetProcAddress(dll_handle, "DNSServiceQueryRecord");
66 dnssd_register = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, const char *, uint16_t, uint16_t, const void *, DNSServiceRegisterReply, void *))GetProcAddress(dll_handle, "DNSServiceRegister");
67 dnssd_remove_record = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags))GetProcAddress(dll_handle, "DNSServiceRemoveRecord");
68 dnssd_resolve = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, DNSServiceResolveReply, void *))GetProcAddress(dll_handle, "DNSServiceResolve");
69 dnssd_sock_fd = (int(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefSockFD");
70 dnssd_update_record = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceUpdateRecord");
71
72 dnssd_txt_create = (void (*)(TXTRecordRef *, uint16_t, void *))GetProcAddress(dll_handle, "TXTRecordCreate");
73 dnssd_txt_deallocate = (void (*)(TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordDeallocate");
74 dnssd_txt_get_bytes_ptr = (const void *(*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetBytesPtr");
75 dnssd_txt_get_count = (uint16_t (*)(uint16_t, const void *))GetProcAddress(dll_handle, "TXTRecordGetCount");
76 dnssd_txt_get_item_at_index = (DNSServiceErrorType (*)(uint16_t, const void *, uint16_t, uint16_t, char *, uint8_t *, const void **))GetProcAddress(dll_handle, "TXTRecordGetItemAtIndex");
77 dnssd_txt_get_length = (uint16_t (*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetLength");
78 dnssd_txt_get_value_ptr = (const void *(*)(uint16_t, const void *, const char *, uint8_t *))GetProcAddress(dll_handle, "TXTRecordGetValuePtr");
79 dnssd_txt_set_value = (DNSServiceErrorType (*)(TXTRecordRef *, const char *, uint8_t, const void *))GetProcAddress(dll_handle, "TXTRecordSetValue");
80 }
81
82 dnssd_initialized = 1;
83 }
84 _cupsMutexUnlock(&dnssd_mutex);
85 }
86
87
88 // DNSServiceAddRecord
DNSServiceAddRecord(DNSServiceRef sdRef,DNSRecordRef * RecordRef,DNSServiceFlags flags,uint16_t rrtype,uint16_t rdlen,const void * rdata,uint32_t ttl)89 DNSServiceErrorType DNSSD_API DNSServiceAddRecord
90 (
91 DNSServiceRef sdRef,
92 DNSRecordRef *RecordRef,
93 DNSServiceFlags flags,
94 uint16_t rrtype,
95 uint16_t rdlen,
96 const void *rdata,
97 uint32_t ttl
98 )
99 {
100 if (!dnssd_initialized)
101 dnssd_init();
102
103 if (dnssd_add_record)
104 return (*dnssd_add_record)(sdRef, RecordRef, flags, rrtype, rdlen, rdata, ttl);
105 else
106 return (kDNSServiceErr_ServiceNotRunning);
107 }
108
109
110 // DNSServiceBrowse
DNSServiceBrowse(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * regtype,const char * domain,DNSServiceBrowseReply callBack,void * context)111 DNSServiceErrorType DNSSD_API DNSServiceBrowse
112 (
113 DNSServiceRef *sdRef,
114 DNSServiceFlags flags,
115 uint32_t interfaceIndex,
116 const char *regtype,
117 const char *domain, /* may be NULL */
118 DNSServiceBrowseReply callBack,
119 void *context /* may be NULL */
120 )
121 {
122 if (!dnssd_initialized)
123 dnssd_init();
124
125 if (dnssd_browse)
126 return (*dnssd_browse)(sdRef, flags, interfaceIndex, regtype, domain, callBack, context);
127 else
128 return (kDNSServiceErr_ServiceNotRunning);
129 }
130
131
132 // DNSServiceConstructFullName
DNSServiceConstructFullName(char * const fullName,const char * const service,const char * const regtype,const char * const domain)133 DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
134 (
135 char * const fullName,
136 const char * const service, /* may be NULL */
137 const char * const regtype,
138 const char * const domain
139 )
140 {
141 if (!dnssd_initialized)
142 dnssd_init();
143
144 if (dnssd_construct_full_name)
145 return (*dnssd_construct_full_name)(fullName, service, regtype, domain);
146 else
147 return (-1);
148 }
149
150
151 // DNSServiceCreateConnection
DNSServiceCreateConnection(DNSServiceRef * sdRef)152 DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
153 {
154 if (!dnssd_initialized)
155 dnssd_init();
156
157 if (dnssd_create_connection)
158 return (*dnssd_create_connection)(sdRef);
159 else
160 return (kDNSServiceErr_ServiceNotRunning);
161 }
162
163
164 // DNSServiceProcessResult
DNSServiceProcessResult(DNSServiceRef sdRef)165 DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
166 {
167 if (!dnssd_initialized)
168 dnssd_init();
169
170 if (dnssd_process_result)
171 return (*dnssd_process_result)(sdRef);
172 else
173 return (kDNSServiceErr_ServiceNotRunning);
174 }
175
176
177 // DNSServiceQueryRecord
DNSServiceQueryRecord(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * fullname,uint16_t rrtype,uint16_t rrclass,DNSServiceQueryRecordReply callBack,void * context)178 DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
179 (
180 DNSServiceRef *sdRef,
181 DNSServiceFlags flags,
182 uint32_t interfaceIndex,
183 const char *fullname,
184 uint16_t rrtype,
185 uint16_t rrclass,
186 DNSServiceQueryRecordReply callBack,
187 void *context /* may be NULL */
188 )
189 {
190 if (!dnssd_initialized)
191 dnssd_init();
192
193 if (dnssd_query_record)
194 return (*dnssd_query_record)(sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context);
195 else
196 return (kDNSServiceErr_ServiceNotRunning);
197 }
198
199
200 // DNSServiceRefDeallocate
DNSServiceRefDeallocate(DNSServiceRef sdRef)201 void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
202 {
203 if (!dnssd_initialized)
204 dnssd_init();
205
206 if (dnssd_deallocate)
207 (*dnssd_deallocate)(sdRef);
208 }
209
210
211 // DNSServiceRefSockFD
DNSServiceRefSockFD(DNSServiceRef sdRef)212 int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
213 {
214 if (!dnssd_initialized)
215 dnssd_init();
216
217 if (dnssd_sock_fd)
218 return (*dnssd_sock_fd)(sdRef);
219 else
220 return (kDNSServiceErr_ServiceNotRunning);
221 }
222
223
224 // DNSServiceRegister
DNSServiceRegister(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,const char * regtype,const char * domain,const char * host,uint16_t port,uint16_t txtLen,const void * txtRecord,DNSServiceRegisterReply callBack,void * context)225 DNSServiceErrorType DNSSD_API DNSServiceRegister
226 (
227 DNSServiceRef *sdRef,
228 DNSServiceFlags flags,
229 uint32_t interfaceIndex,
230 const char *name, /* may be NULL */
231 const char *regtype,
232 const char *domain, /* may be NULL */
233 const char *host, /* may be NULL */
234 uint16_t port, /* In network byte order */
235 uint16_t txtLen,
236 const void *txtRecord, /* may be NULL */
237 DNSServiceRegisterReply callBack, /* may be NULL */
238 void *context /* may be NULL */
239 )
240 {
241 if (!dnssd_initialized)
242 dnssd_init();
243
244 if (dnssd_register)
245 return (*dnssd_register)(sdRef, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context);
246 else
247 return (kDNSServiceErr_ServiceNotRunning);
248 }
249
250
251 // DNSServiceRemoveRecord
DNSServiceRemoveRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags)252 DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
253 (
254 DNSServiceRef sdRef,
255 DNSRecordRef RecordRef,
256 DNSServiceFlags flags
257 )
258 {
259 if (!dnssd_initialized)
260 dnssd_init();
261
262 if (dnssd_remove_record)
263 return (*dnssd_remove_record)(sdRef, RecordRef, flags);
264 else
265 return (kDNSServiceErr_ServiceNotRunning);
266 }
267
268
269 // DNSServiceResolve
DNSServiceResolve(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,const char * regtype,const char * domain,DNSServiceResolveReply callBack,void * context)270 DNSServiceErrorType DNSSD_API DNSServiceResolve
271 (
272 DNSServiceRef *sdRef,
273 DNSServiceFlags flags,
274 uint32_t interfaceIndex,
275 const char *name,
276 const char *regtype,
277 const char *domain,
278 DNSServiceResolveReply callBack,
279 void *context /* may be NULL */
280 )
281 {
282 if (!dnssd_initialized)
283 dnssd_init();
284
285 if (dnssd_resolve)
286 return (*dnssd_resolve)(sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context);
287 else
288 return (kDNSServiceErr_ServiceNotRunning);
289 }
290
291
292 // DNSServiceUpdateRecord
DNSServiceUpdateRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags,uint16_t rdlen,const void * rdata,uint32_t ttl)293 DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
294 (
295 DNSServiceRef sdRef,
296 DNSRecordRef RecordRef, /* may be NULL */
297 DNSServiceFlags flags,
298 uint16_t rdlen,
299 const void *rdata,
300 uint32_t ttl
301 )
302 {
303 if (!dnssd_initialized)
304 dnssd_init();
305
306 if (dnssd_update_record)
307 return (*dnssd_update_record)(sdRef, RecordRef, flags, rdlen, rdata, ttl);
308 else
309 return (kDNSServiceErr_ServiceNotRunning);
310 }
311
312
313 // TXTRecordCreate
314 void DNSSD_API
TXTRecordCreate(TXTRecordRef * txtRecord,uint16_t bufferLen,void * buffer)315 TXTRecordCreate(
316 TXTRecordRef *txtRecord,
317 uint16_t bufferLen,
318 void *buffer)
319 {
320 if (!dnssd_initialized)
321 dnssd_init();
322
323 if (dnssd_txt_create)
324 (*dnssd_txt_create)(txtRecord, bufferLen, buffer);
325 }
326
327
328 // TXTRecordDeallocate
TXTRecordDeallocate(TXTRecordRef * txtRecord)329 void DNSSD_API TXTRecordDeallocate
330 (
331 TXTRecordRef *txtRecord
332 )
333 {
334 if (!dnssd_initialized)
335 dnssd_init();
336
337 if (dnssd_txt_deallocate)
338 (*dnssd_txt_deallocate)(txtRecord);
339 }
340
341
342 // TXTRecordGetBytesPtr
TXTRecordGetBytesPtr(const TXTRecordRef * txtRecord)343 const void * DNSSD_API TXTRecordGetBytesPtr
344 (
345 const TXTRecordRef *txtRecord
346 )
347 {
348 if (!dnssd_initialized)
349 dnssd_init();
350
351 if (dnssd_txt_get_bytes_ptr)
352 return (*dnssd_txt_get_bytes_ptr)(txtRecord);
353 else
354 return (NULL);
355 }
356
357
358 // TXTRecordGetLength
TXTRecordGetLength(const TXTRecordRef * txtRecord)359 uint16_t DNSSD_API TXTRecordGetLength
360 (
361 const TXTRecordRef *txtRecord
362 )
363 {
364 if (!dnssd_initialized)
365 dnssd_init();
366
367 if (dnssd_txt_get_length)
368 return (*dnssd_txt_get_length)(txtRecord);
369 else
370 return (0);
371 }
372
373
374 // TXTRecordSetValue
TXTRecordSetValue(TXTRecordRef * txtRecord,const char * key,uint8_t valueSize,const void * value)375 DNSServiceErrorType DNSSD_API TXTRecordSetValue
376 (
377 TXTRecordRef *txtRecord,
378 const char *key,
379 uint8_t valueSize, /* may be zero */
380 const void *value /* may be NULL */
381 )
382 {
383 if (!dnssd_initialized)
384 dnssd_init();
385
386 if (dnssd_txt_set_value)
387 return (*dnssd_txt_set_value)(txtRecord, key, valueSize, value);
388 else
389 return (-1);
390 }
391
392
393 // TXTRecordGetCount
394 uint16_t DNSSD_API
TXTRecordGetCount(uint16_t txtLen,const void * txtRecord)395 TXTRecordGetCount(
396 uint16_t txtLen,
397 const void *txtRecord)
398 {
399 if (!dnssd_initialized)
400 dnssd_init();
401
402 if (dnssd_txt_get_count)
403 return (*dnssd_txt_get_count)(txtLen, txtRecord);
404 else
405 return (0);
406 }
407
408
409 // TXTRecordGetItemAtIndex
410 DNSServiceErrorType DNSSD_API
TXTRecordGetItemAtIndex(uint16_t txtLen,const void * txtRecord,uint16_t itemIndex,uint16_t keyBufLen,char * key,uint8_t * valueLen,const void ** value)411 TXTRecordGetItemAtIndex(
412 uint16_t txtLen,
413 const void *txtRecord,
414 uint16_t itemIndex,
415 uint16_t keyBufLen,
416 char *key,
417 uint8_t *valueLen,
418 const void **value)
419 {
420 if (!dnssd_initialized)
421 dnssd_init();
422
423 if (dnssd_txt_get_item_at_index)
424 return (*dnssd_txt_get_item_at_index)(txtLen, txtRecord, itemIndex, keyBufLen, key, valueLen, value);
425 else
426 return (-1);
427 }
428
429
430 // TXTRecordGetValuePtr
431 const void * DNSSD_API
TXTRecordGetValuePtr(uint16_t txtLen,const void * txtRecord,const char * key,uint8_t * valueLen)432 TXTRecordGetValuePtr(
433 uint16_t txtLen,
434 const void *txtRecord,
435 const char *key,
436 uint8_t *valueLen)
437 {
438 if (!dnssd_initialized)
439 dnssd_init();
440
441 if (dnssd_txt_get_value_ptr)
442 return (*dnssd_txt_get_value_ptr)(txtLen, txtRecord, key, valueLen);
443 else
444 return (NULL);
445 }
446