1 /*
2  * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
3  *
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
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
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
14  * limitations under the License.
15  */
16 
17 #ifndef __DNSSD_PRIVATE_H__
18 #define __DNSSD_PRIVATE_H__
19 
20 #include <dispatch/dispatch.h>
21 #include <xpc/xpc.h>
22 #include <dns_sd.h>
23 #include <os/object.h>
24 
25 #if OS_OBJECT_USE_OBJC
26 	#define DNSSD_DECL(NAME)		OS_OBJECT_DECL_SUBCLASS(dnssd_ ## NAME, dnssd_object)
27 	#define DNSSD_RETURNS_RETAINED	OS_OBJECT_RETURNS_RETAINED
28 
29 	OS_OBJECT_DECL(dnssd_object,);
30 #else
31 	#define DNSSD_DECL(NAME)		typedef struct dnssd_ ## NAME ## _s *	dnssd_ ## NAME ## _t
32 	#define DNSSD_RETURNS_RETAINED
33 
34 	DNSSD_DECL(object);
35 #endif
36 
37 #define DNSSD_ASSUME_NONNULL_BEGIN	OS_ASSUME_NONNULL_BEGIN
38 #define DNSSD_ASSUME_NONNULL_END	OS_ASSUME_NONNULL_END
39 
40 DNSSD_DECL(getaddrinfo);
41 DNSSD_DECL(getaddrinfo_result);
42 DNSSD_DECL(cname_array);
43 
44 DNSSD_ASSUME_NONNULL_BEGIN
45 
46 #if OS_OBJECT_USE_OBJC
47 	typedef dnssd_object_t	dnssd_any_t;
48 #else
49 	#if !defined(__cplusplus)
50 		typedef union {
51 			dnssd_object_t				object;
52 			dnssd_getaddrinfo_t			gai;
53 			dnssd_getaddrinfo_result_t	gai_result;
54 			dnssd_cname_array_t			cname_array;
55 		} dnssd_any_t __attribute__((__transparent_union__));
56 	#else
57 		typedef void *	dnssd_any_t;
58 	#endif
59 #endif
60 
61 #define DNSSD_MALLOC	__attribute__((__malloc__))
62 #define DNSSD_AVAILABLE	SPI_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0))
63 
64 #if __has_attribute(noescape)
65 #define DNSSD_NOESCAPE __attribute__((__noescape__))
66 #else // noescape
67 #define DNSSD_NOESCAPE
68 #endif // noescape
69 
70 __BEGIN_DECLS
71 
72 /*!
73  *	@brief
74  *		Increments the reference count of a dnssd object.
75  *
76  *	@param object
77  *		The dnssd object.
78  *
79  *	@discussion
80  *		Calls to dnssd_retain() must be balanced with calls to dnssd_release().
81  */
82 DNSSD_AVAILABLE
83 void
84 dnssd_retain(dnssd_any_t object);
85 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
86 #undef dnssd_retain
87 #define dnssd_retain(object)	[(object) retain]
88 #endif
89 
90 /*!
91  *	@brief
92  *		Decrements the reference count of a dnssd object.
93  *
94  *	@param object
95  *		The dnssd object.
96  *
97  *	@discussion
98  *		Calls to dnssd_retain() must be balanced with calls to dnssd_release().
99  */
100 DNSSD_AVAILABLE
101 void
102 dnssd_release(dnssd_any_t object);
103 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
104 #undef dnssd_release
105 #define dnssd_release(object)	[(object) release]
106 #endif
107 
108 
109 /*!
110  *	@brief
111  *		Provides a textual description of a dnssd object.
112  *
113  *	@param object
114  *		The dnssd object.
115  *
116  *	@result
117  *		Textual description of the object as a C string.
118  *
119  *	@discussion
120  *		The string returned by this function must be released with <code>free(3)</code>.
121  */
122 DNSSD_AVAILABLE
123 DNSSD_MALLOC char * _Nullable
124 dnssd_copy_description(dnssd_any_t object);
125 
126 /*!
127  *	@brief
128  *		Creates a getaddrinfo object.
129  *
130  *	@result
131  *		A new getaddrinfo object.
132  *
133  *	@discussion
134  *		A getaddrinfo object resolves a hostname to its IPv4 and IPv6 addresses.
135  */
136 DNSSD_AVAILABLE
137 DNSSD_RETURNS_RETAINED dnssd_getaddrinfo_t _Nullable
138 dnssd_getaddrinfo_create(void);
139 
140 /*!
141  *	@brief
142  *		Specifies the queue on which to invoke the getaddrinfo object's result and event blocks.
143  *
144  *	@param gai
145  *		The getaddrinfo object.
146  *
147  *	@param queue
148  *		A serial queue.
149  *
150  *	@discussion
151  *		This call must be made before activating the getaddrinfo object.
152  *
153  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
154  */
155 DNSSD_AVAILABLE
156 void
157 dnssd_getaddrinfo_set_queue(dnssd_getaddrinfo_t gai, dispatch_queue_t queue);
158 
159 /*!
160  *	@brief
161  *		Specifies the DNSServiceFlags to use for the getaddrinfo operation.
162  *
163  *	@param gai
164  *		The getaddrinfo object.
165  *
166  *	@param flags
167  *		Flags.
168  *
169  *	@discussion
170  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
171  */
172 DNSSD_AVAILABLE
173 void
174 dnssd_getaddrinfo_set_flags(dnssd_getaddrinfo_t gai, DNSServiceFlags flags);
175 
176 #define DNSSD_GETADDRINFO_SUPPORTS_ACCOUNT_ID 1
177 
178 /*!
179  *	@brief
180  *		Specifies the account id to use for the getaddrinfo operation.
181  *
182  *	@param gai
183  *		The getaddrinfo object.
184  *
185  *	@param account_id
186  *		The account id.
187  *
188  *	@discussion
189  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
190  */
191 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
192 void
193 dnssd_getaddrinfo_set_account_id(dnssd_getaddrinfo_t gai, const char * account_id);
194 
195 /*!
196  *	@brief
197  *		Specifies the hostname to resolve.
198  *
199  *	@param gai
200  *		The getaddrinfo object.
201  *
202  *	@param hostname
203  *		Hostname as a fully-qualified domain name.
204  *
205  *	@discussion
206  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
207  */
208 DNSSD_AVAILABLE
209 void
210 dnssd_getaddrinfo_set_hostname(dnssd_getaddrinfo_t gai, const char *hostname);
211 
212 #define DNSSD_GETADDRINFO_SUPPORTS_SERVICE_SCHEME 1
213 
214 /*!
215  *	@brief
216  *		Specifies the optional service scheme to resolve.
217  *
218  *	@param gai
219  *		The getaddrinfo object.
220  *
221  *	@param service_scheme
222  *		Service scheme as a string, such as "_443._https".
223  *
224  *	@discussion
225  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
226  */
227 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
228 void
229 dnssd_getaddrinfo_set_service_scheme(dnssd_getaddrinfo_t gai, const char * _Nullable service_scheme);
230 
231 /*!
232  *	@brief
233  *		Specifies the index of the interface via which to resolve the hostname.
234  *
235  *	@param gai
236  *		The getaddrinfo object.
237  *
238  *	@param interface_index
239  *		Interface index.
240  *
241  *	@discussion
242  *		If <code>kDNSServiceInterfaceIndexAny</code> is used as the interface index, then special behavior applies. If
243  *		the hostname is in the "local." domain, then an attempt will be made to resolve the hostname via all active
244  *		mDNS-capable interfaces. If the hostname is in any other domain, then the hostname will be resolved via the
245  *		primary interface.
246  *
247  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
248  */
249 DNSSD_AVAILABLE
250 void
251 dnssd_getaddrinfo_set_interface_index(dnssd_getaddrinfo_t gai, uint32_t interface_index);
252 
253 /*!
254  *	@brief
255  *		Specifies the types of addresses to which to resolve the hostname.
256  *
257  *	@param gai
258  *		The getaddrinfo object.
259  *
260  *	@param protocols
261  *		Protocols.
262  *
263  *	@discussion
264  *		Set <code>protocols</code> to <code>kDNSServiceProtocol_IPv4</code> to resolve the hostname to IPv4 addresses.
265  *
266  *		Set <code>protocols</code> to <code>kDNSServiceProtocol_IPv6</code> to resolve the hostname to IPv6 addresses.
267  *
268  *		Set <code>protocols</code> to <code>kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6</code> to resolve the
269  *		hostname to both IPv4 and IPv6 addresses.
270  *
271  *		Set <code>protocols</code> to 0 to limit resolution to addresses of protocols of which the host has routable
272  *		addresses. That is, an attempt will be made to resolve the hostname to IPv4 addresses if and only if the host
273  *		has a routable IPv4 address. Likewise, an attempt will be made to resolve the hostname to IPv6 addresses if and
274  *		only if the host has a routable IPv6 address.
275  *
276  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
277  */
278 DNSSD_AVAILABLE
279 void
280 dnssd_getaddrinfo_set_protocols(dnssd_getaddrinfo_t gai, DNSServiceProtocol protocols);
281 
282 /*!
283  *	@brief
284  *		Sets the process ID (PID) of the process on whose behalf the getaddrinfo operation is being performed.
285  *
286  *	@param gai
287  *		The getaddrinfo object.
288  *
289  *	@param pid
290  *		PID of the process being represented.
291  *
292  *	@discussion
293  *		If a delegate PID is set, then the calling process must have the proper entitlement in order for the
294  *		getaddrinfo operation to not fail with a kDNSServiceErr_NotAuth error.
295  *
296  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_uuid()</code>.
297  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_audit_token()</code>.
298  *
299  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
300  */
301 DNSSD_AVAILABLE
302 void
303 dnssd_getaddrinfo_set_delegate_pid(dnssd_getaddrinfo_t gai, pid_t pid);
304 
305 /*!
306  *	@brief
307  *		Sets the UUID of the process on whose behalf the getaddrinfo operation is being performed.
308  *
309  *	@param gai
310  *		The getaddrinfo object.
311  *
312  *	@param uuid
313  *		UUID of the process being represented.
314  *
315  *	@discussion
316  *		If a delegate UUID is set, then the calling process must have the proper entitlement in order for the
317  *		getaddrinfo operation to not fail with the <code>kDNSServiceErr_NotAuth</code> error.
318  *
319  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_pid()</code>.
320  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_audit_token()</code>.
321  *
322  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
323  */
324 DNSSD_AVAILABLE
325 void
326 dnssd_getaddrinfo_set_delegate_uuid(dnssd_getaddrinfo_t gai, uuid_t _Nonnull uuid);
327 
328 #define DNSSD_GETADDRINFO_SUPPORTS_DELEGATE_AUDIT_TOKEN 1
329 
330 /*!
331  *	@brief
332  *		Sets the audit token of the process on whose behalf the getaddrinfo operation is being performed.
333  *
334  *	@param gai
335  *		The getaddrinfo object.
336  *
337  *	@param audit_token
338  *		audit token of the process being represented.
339  *
340  *	@discussion
341  *		If a delegate audit token is set, then the calling process must have the proper entitlement in order for the
342  *		getaddrinfo operation to not fail with the <code>kDNSServiceErr_NotAuth</code> error.
343  *
344  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_pid()</code>.
345  *		This function is an alternative to <code>dnssd_getaddrinfo_set_delegate_uuid()</code>.
346  *
347  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
348  */
349 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
350 void
351 dnssd_getaddrinfo_set_delegate_audit_token(dnssd_getaddrinfo_t gai, audit_token_t audit_token);
352 
353 /*!
354  *	@brief
355  *		Specifies whether or not getaddrinfo results (of types <code>dnssd_getaddrinfo_result_type_add</code> and
356  *		<code>dnssd_getaddrinfo_result_type_expired</code>) should include authentication tags from the stub resolver.
357  *
358  *	@param gai
359  *		The getaddrinfo object.
360  *
361  *	@param need
362  *		Pass <code>true</code> if authenticated results are needed, otherwise, pass <code>false</code>.
363  *
364  *	@discussion
365  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
366  */
367 DNSSD_AVAILABLE
368 void
369 dnssd_getaddrinfo_set_need_authenticated_results(dnssd_getaddrinfo_t gai, bool need);
370 
371 #define DNSSD_GETADDRINFO_SUPPORTS_ENCRYPTED_QUERIES 1
372 
373 /*!
374  *	@brief
375  *		Specifies whether or not getaddrinfo queries must use encrypted transports to the next DNS server.
376  *
377  *	@param gai
378  *		The getaddrinfo object.
379  *
380  *	@param need
381  *		Pass <code>true</code> if encrypted queries are required, otherwise, pass <code>false</code>.
382  *
383  *	@param fallback_config
384  *		If not NULL, specify a custom resolver configuration to use if no encrypted resolver configuation is otherwise
385  *		available.
386  *
387  *	@discussion
388  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
389  */
390 DNSSD_AVAILABLE
391 void
392 dnssd_getaddrinfo_set_need_encrypted_query(dnssd_getaddrinfo_t gai, bool need, _Nullable xpc_object_t fallback_config);
393 
394 /*!
395  *	@brief
396  *		Add a resolver UUID that represents a resolver configuration registered with the system that should
397  *		be applied to this resolution. Multiple UUIDs can be set.
398  *
399  *	@param gai
400  *		The getaddrinfo object.
401  *
402  *	@param uuid
403  *		UUID of a resolver configuration registered with the system.
404  *
405  *	@discussion
406  *		This function has no effect on a getaddrinfo object that has been activated or invalidated.
407 
408  */
409 DNSSD_AVAILABLE
410 void
411 dnssd_getaddrinfo_add_resolver_uuid(dnssd_getaddrinfo_t gai, uuid_t _Nonnull uuid);
412 
413 /*!
414  *	@brief
415  *		Activates a getaddrinfo object.
416  *
417  *	@param gai
418  *		The getaddrinfo object.
419  *
420  *	@discussion
421  *		This function has no effect on a getaddrinfo object that has already been activated or has been invalidated.
422  */
423 DNSSD_AVAILABLE
424 void
425 dnssd_getaddrinfo_activate(dnssd_getaddrinfo_t gai);
426 
427 /*!
428  *	@brief
429  *		Asynchronously invalidates a getaddrinfo object.
430  *
431  *	@param gai
432  *		The getaddrinfo object.
433  *
434  *	@discussion
435  *		As a result of calling this function, the getaddrinfo object's event handler will be invoked with a
436  *		<code>dnssd_event_invalidated</code> event. After this, the object's event and result handlers will never be
437  *		invoked again.
438  *
439  *		This function has no effect on a getaddrinfo object that has already been invalidated.
440  */
441 DNSSD_AVAILABLE
442 void
443 dnssd_getaddrinfo_invalidate(dnssd_getaddrinfo_t gai);
444 
445 /*!
446  *	@brief
447  *		Handler for getaddrinfo results.
448  *
449  *	@param result_array
450  *		C array of getaddrinfo results.
451  *
452  *	@param result_count
453  *		Size of the array in terms of number of results.
454  */
455 typedef void (^dnssd_getaddrinfo_result_handler_t)(dnssd_getaddrinfo_result_t _Nonnull * _Nonnull result_array,
456 												   size_t result_count);
457 
458 /*!
459  *	@brief
460  *		Specifies a getaddrinfo object's result handler.
461  *
462  *	@param gai
463  *		The getaddrinfo object.
464  *
465  *	@param handler
466  *		Result handler.
467  */
468 DNSSD_AVAILABLE
469 void
470 dnssd_getaddrinfo_set_result_handler(dnssd_getaddrinfo_t gai, dnssd_getaddrinfo_result_handler_t _Nullable handler);
471 
472 /*!
473  *	@brief
474  *		Events that can occur during the lifetime of a getaddrinfo object.
475  */
476 typedef enum {
477 	/*! @const dnssd_event_error An error occurred. */
478 	dnssd_event_error		= 1,
479 	/*! @const dnssd_event_remove_all All results prior to this event are no longer valid. */
480 	dnssd_event_remove_all	= 2,
481 	/*! @const dnssd_event_invalidated The object has been invalidated. */
482 	dnssd_event_invalidated	= 3,
483 } dnssd_event_t;
484 
485 /*!
486  *	@brief
487  *		Handler for getaddrinfo events.
488  *
489  *	@param event
490  *		Event.
491  *
492  *	@param error
493  *		The error associated with a <code>dnssd_event_error</code> event. Ignore for all other types of events.
494  *
495  *	@discussion
496  *		After a <code>dnssd_event_invalidated</code> event, a getaddrinfo object's result and event handlers will never
497  *		be invoked again.
498  */
499 typedef void (^dnssd_event_handler_t)(dnssd_event_t event, DNSServiceErrorType error);
500 
501 /*!
502  *	@brief
503  *		Sets a getaddrinfo object's event handler.
504  *
505  *	@param gai
506  *		The getaddrinfo object.
507  *
508  *	@param handler
509  *		Event handler.
510  */
511 DNSSD_AVAILABLE
512 void
513 dnssd_getaddrinfo_set_event_handler(dnssd_getaddrinfo_t gai, dnssd_event_handler_t _Nullable handler);
514 
515 /*!
516  *	@brief
517  *		Types of getaddrinfo results.
518  */
519 typedef enum {
520 	/*! @const dnssd_getaddrinfo_result_type_add The contained hostname and address pair is valid. */
521 	dnssd_getaddrinfo_result_type_add				= 1,
522 	/*! @const dnssd_getaddrinfo_result_type_remove The contained hostname and address pair is no longer valid. */
523 	dnssd_getaddrinfo_result_type_remove			= 2,
524 	/*! @const dnssd_getaddrinfo_result_type_no_address The contained hostname has no address of a particular type. */
525 	dnssd_getaddrinfo_result_type_no_address		= 3,
526 	/*! @const dnssd_getaddrinfo_result_type_expired A hostname and address pair contained came from an expired cached record and may no longer be valid. */
527 	dnssd_getaddrinfo_result_type_expired			= 4,
528 	/*! @const dnssd_getaddrinfo_result_type_service_binding A hostname has associated service binding information. */
529 	dnssd_getaddrinfo_result_type_service_binding	= 5,
530 } dnssd_getaddrinfo_result_type_t;
531 
532 /*!
533  *	@brief
534  *		Gets a getaddrinfo result's type.
535  *
536  *	@param gai_result
537  *		The getaddrinfo result.
538  *
539  *	@result
540  *		Result type.
541  */
542 DNSSD_AVAILABLE
543 dnssd_getaddrinfo_result_type_t
544 dnssd_getaddrinfo_result_get_type(dnssd_getaddrinfo_result_t gai_result);
545 
546 /*!
547  *	@brief
548  *		Gets a getaddrinfo result's actual hostname.
549  *
550  *	@param gai_result
551  *		The getaddrinfo result.
552  *
553  *	@result
554  *		The getaddrinfo result's actual hostname.
555  *
556  *	@discussion
557  *		The hostname returned by this function is the canonical name of the hostname that was requested. In other
558  *		words, it's the canonical name of the hostname set with <code>dnssd_getaddrinfo_set_hostname()</code>.
559  *
560  *		The pointer returned by this function is valid until the getaddrinfo result is released.
561  */
562 DNSSD_AVAILABLE
563 const char *
564 dnssd_getaddrinfo_result_get_actual_hostname(dnssd_getaddrinfo_result_t gai_result);
565 
566 /*!
567  *	@brief
568  *		Gets a getaddrinfo result's address.
569  *
570  *	@param gai_result
571  *		The getaddrinfo result.
572  *
573  *	@result
574  *		The getaddrinfo result's address as a sockaddr structure.
575  *
576  *	@discussion
577  *		For getaddrinfo results of type <code>dnssd_getaddrinfo_result_type_no_address</code>, the sockaddr structure's
578  *		sa_family member variable can be used to determine the type of address that the hostname lacks.
579  */
580 DNSSD_AVAILABLE
581 const struct sockaddr *
582 dnssd_getaddrinfo_result_get_address(dnssd_getaddrinfo_result_t gai_result);
583 
584 /*!
585  *	@brief
586  *		Gets a getaddrinfo result's hostname.
587  *
588  *	@param gai_result
589  *		The getaddrinfo result.
590  *
591  *	@result
592  *		The getaddrinfo result's hostname.
593  *
594  *	@discussion
595  *		The hostname returned by this function is the hostname whose resolution was requested. In other words, it's
596  *		equal to the hostname set with <code>dnssd_getaddrinfo_set_hostname()</code>.
597  *
598  *		The pointer returned by this function is valid until the getaddrinfo result is released.
599  */
600 DNSSD_AVAILABLE
601 const char *
602 dnssd_getaddrinfo_result_get_hostname(dnssd_getaddrinfo_result_t gai_result);
603 
604 /*!
605  *	@brief
606  *		Gets the interface index to which a getaddrinfo result pertains.
607  *
608  *	@param gai_result
609  *		The getaddrinfo result.
610  *
611  *	@result
612  *		For hostnames that were resolved via mDNS, the return value is the index of the interface via which the
613  *		hostname was resolved. For hostnames that were resolved via DNS, the return value is 0.
614  */
615 DNSSD_AVAILABLE
616 uint32_t
617 dnssd_getaddrinfo_result_get_interface_index(dnssd_getaddrinfo_result_t gai_result);
618 
619 /*!
620  *	@brief
621  *		Gets a getaddrinfo result's authentication tag.
622  *
623  *	@param gai_result
624  *		The getaddrinfo result.
625  *
626  *	@param out_length
627  *		If non-NULL, gets set to the length of the authentication tag.
628  *
629  *	@result
630  *		A pointer to the getaddrinfo result's authentication tag, if it has one. Otherwise, NULL.
631  *
632  *	@discussion
633  *		The returned pointer, if non-NULL, is valid until the getaddrinfo result is released.
634  */
635 DNSSD_AVAILABLE
636 const void * _Nullable
637 dnssd_getaddrinfo_result_get_authentication_tag(dnssd_getaddrinfo_result_t gai_result, size_t *_Nullable out_length);
638 
639 /*!
640  *	@brief
641  *		Types of protocols used for getaddrinfo results.
642  */
643 typedef enum {
644 	/*! @const dnssd_getaddrinfo_result_protocol_udp The answers were retrieved using UDP. */
645 	dnssd_getaddrinfo_result_protocol_udp		= 1,
646 	/*! @const dnssd_getaddrinfo_result_protocol_tcp The answers were retrieved using TCP. */
647 	dnssd_getaddrinfo_result_protocol_tcp		= 2,
648 	/*! @const dnssd_getaddrinfo_result_protocol_tls The answers were retrieved using DNS over TLS. */
649 	dnssd_getaddrinfo_result_protocol_tls		= 3,
650 	/*! @const dnssd_getaddrinfo_result_protocol_https The answers were retrieved using DNS over HTTPS. */
651 	dnssd_getaddrinfo_result_protocol_https		= 4,
652 } dnssd_getaddrinfo_result_protocol_t;
653 
654 #define DNSSD_GETADDRINFO_HAS_GET_PROTOCOL 1
655 
656 /*!
657  *	@brief
658  *		Gets a getaddrinfo result's protocol.
659  *
660  *	@param gai_result
661  *		The getaddrinfo result.
662  *
663  *	@result
664  *		Result protocol.
665  */
666 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
667 dnssd_getaddrinfo_result_protocol_t
668 dnssd_getaddrinfo_result_get_protocol(dnssd_getaddrinfo_result_t gai_result);
669 
670 #define DNSSD_GETADDRINFO_HAS_GET_PROVIDER_NAME 1
671 
672 /*!
673  *	@brief
674  *		Gets a getaddrinfo result's DNS provider name, if applicable.
675  *
676  *	@param gai_result
677  *		The getaddrinfo result.
678  *
679  *	@result
680  *		DNS provider name.
681  */
682 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
683 const char * _Nullable
684 dnssd_getaddrinfo_result_get_provider_name(dnssd_getaddrinfo_result_t gai_result);
685 
686 /*!
687  *	@brief
688  *		Checks if a getaddrinfo result has valid service binding information.
689  *
690  *	@param gai_result
691  *		The getaddrinfo result.
692  *
693  *	@result
694  *		Returns true if service binding information is valid.
695  */
696 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
697 bool
698 dnssd_getaddrinfo_result_service_is_valid(dnssd_getaddrinfo_result_t gai_result);
699 
700 #define DNSSD_GETADDRINFO_SERVICE_PRIORITY_ALIAS 0
701 
702 /*!
703  *	@brief
704  *		Gets a getaddrinfo result's service binding priority.
705  *
706  *	@param gai_result
707  *		The getaddrinfo result.
708  *
709  *	@result
710  *		Service binding priority.
711  */
712 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
713 uint16_t
714 dnssd_getaddrinfo_result_get_service_priority(dnssd_getaddrinfo_result_t gai_result);
715 
716 /*!
717  *	@brief
718  *		Gets a getaddrinfo result's service binding port.
719  *
720  *	@param gai_result
721  *		The getaddrinfo result.
722  *
723  *	@result
724  *		Service binding port.
725  */
726 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
727 uint16_t
728 dnssd_getaddrinfo_result_get_service_port(dnssd_getaddrinfo_result_t gai_result);
729 
730 /*!
731  *	@brief
732  *		Gets a getaddrinfo result's service name.
733  *
734  *	@param gai_result
735  *		The getaddrinfo result.
736  *
737  *	@result
738  *		String containing the service binding name.
739  */
740 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
741 const char * _Nullable
742 dnssd_getaddrinfo_result_get_service_name(dnssd_getaddrinfo_result_t gai_result);
743 
744 /*!
745  *	@brief
746  *		Gets a getaddrinfo result's associated DoH URI if present.
747  *
748  *	@param gai_result
749  *		The getaddrinfo result.
750  *
751  *	@result
752  *		String containing a DoH URI, if present.
753  */
754 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
755 const char * _Nullable
756 dnssd_getaddrinfo_result_get_doh_uri(dnssd_getaddrinfo_result_t gai_result);
757 
758 /*!
759  *	@brief
760  *		Gets a getaddrinfo result's ECH (Encrypted Client Hello) configuration.
761  *
762  *	@param gai_result
763  *		The getaddrinfo result.
764  *
765  *	@param out_length
766  *		If non-NULL, gets set to the length of the ECH config.
767  *
768  *	@result
769  *		A pointer to the getaddrinfo result's ECH config, if it has one. Otherwise, NULL.
770  *
771  *	@discussion
772  *		The returned pointer, if non-NULL, is valid until the getaddrinfo result is released.
773  */
774 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
775 const void * _Nullable
776 dnssd_getaddrinfo_result_get_ech_config(dnssd_getaddrinfo_result_t gai_result, size_t *_Nullable out_length);
777 
778 #ifdef __BLOCKS__
779 
780 typedef bool (^dnssd_getaddrinfo_enumerate_alpn_values_block_t)(const char *alpn);
781 
782 /*!
783  *	@brief
784  *		Enumerates a getaddrinfo result's service binding ALPN (application layer protocol negotiation) hints.
785  *
786  *	@param gai_result
787  *		The getaddrinfo result.
788  *
789  *	@param enumerator
790  *		A block to invoke for each ALPN hint.
791  */
792 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
793 void
794 dnssd_getaddrinfo_result_enumerate_alpn_values(dnssd_getaddrinfo_result_t gai_result,
795 											   DNSSD_NOESCAPE dnssd_getaddrinfo_enumerate_alpn_values_block_t enumerator);
796 
797 typedef bool (^dnssd_getaddrinfo_enumerate_addresses_block_t)(const struct sockaddr *address);
798 
799 /*!
800  *	@brief
801  *		Enumerates a getaddrinfo result's service address hints.
802  *
803  *	@param gai_result
804  *		The getaddrinfo result.
805  *
806  *	@param enumerator
807  *		A block to invoke for each address hint.
808  */
809 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
810 void
811 dnssd_getaddrinfo_result_enumerate_service_address_hints(dnssd_getaddrinfo_result_t gai_result,
812 														 DNSSD_NOESCAPE dnssd_getaddrinfo_enumerate_addresses_block_t enumerator);
813 
814 #endif // __BLOCKS__
815 
816 
817 /*!
818  *	@brief
819  *		Gets the canonical names, if any, of a getaddrinfo result's hostname.
820  *
821  *	@param gai_result
822  *		The getaddrinfo result.
823  *
824  *	@result
825  *		An array containing zero or more canonical names.
826  *
827  *	@discussion
828  *		Canonical names will not be provided for a getaddrinfo objects's results unless the
829  *		<code>kDNSServiceFlagsReturnIntermediates</code> flag was set for the getaddrinfo object with
830  *		<code>dnssd_getaddrinfo_set_flags()</code>.
831  *
832  *		The canonical names in the array are ordered in the following way. For non-empty arrays, the first
833  *		canonical name in the array is the immediate canonical name of the getaddrinfo operation's hostname.
834  *		For all canonical names beyond the first, a canonical name is the immediate canonical name of the
835  *		canonical name that precedes it in the array.
836  *
837  *		For hostnames that have no canonical names, i.e., hostnames that aren't aliases, an empty array will be
838  *		returned.
839  *
840  *		The array returned by this function is guaranteed to be valid during the lifetime of the getaddrinfo
841  *		result. If the array is needed beyond the lifetime of the getaddrinfo result, then the array must be
842  *		retained.
843  */
844 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
845 dnssd_cname_array_t
846 dnssd_getaddrinfo_result_get_cnames(dnssd_getaddrinfo_result_t gai_result);
847 
848 /*!
849  *	@brief
850  *		Determines whether a getaddrinfo result was the product of cached DNS records, i.e., no additional DNS
851  *		queries needed to be sent by mDNSResponder to provide the result.
852  *
853  *	@param gai_result
854  *		The getaddrinfo result.
855  *
856  *	@result
857  *		Returns <code>true</code> if the result came from cached DNS records, otherwise, returns
858  *		<code>false</code>.
859  */
860 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
861 bool
862 dnssd_getaddrinfo_result_is_from_cache(dnssd_getaddrinfo_result_t gai_result);
863 
864 /*!
865  *	@brief
866  *		Gets the count of canonical names in a canonical name array.
867  *
868  *	@param cname_array
869  *		The canonical name array.
870  *
871  *	@result
872  *		The count of canonical names in the canonical name array.
873  */
874 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
875 size_t
876 dnssd_cname_array_get_count(dnssd_cname_array_t cname_array);
877 
878 /*!
879  *	@brief
880  *		Gets the canonical name at a specific index in a canonical name array.
881  *
882  *	@param cname_array
883  *		The canonical name array.
884  *
885  *	@param index
886  *		The zero-based index of the canonical name to get. The index must be no greater than the array's count,
887  *		i.e., the value returned by <code>dnssd_cname_array_get_count()</code> for the array.
888  *
889  *	@result
890  *		The canonical name at the specified index as a C string.
891  *
892  *	@discussion
893  *		The pointer returned by this function is guaranteed to be valid until the array is released.
894  */
895 SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0))
896 const char * _Nullable
897 dnssd_cname_array_get_cname(dnssd_cname_array_t cname_array, size_t index);
898 
899 static inline const char *
dnssd_getaddrinfo_result_type_to_string(dnssd_getaddrinfo_result_type_t result)900 dnssd_getaddrinfo_result_type_to_string(dnssd_getaddrinfo_result_type_t result)
901 {
902 	switch (result) {
903 		case dnssd_getaddrinfo_result_type_add:				return "Add";
904 		case dnssd_getaddrinfo_result_type_remove:			return "Remove";
905 		case dnssd_getaddrinfo_result_type_no_address:		return "NoAddress";
906 		case dnssd_getaddrinfo_result_type_expired:			return "Expired";
907 		case dnssd_getaddrinfo_result_type_service_binding:	return "ServiceBinding";
908 		default:											return "?";
909 	}
910 }
911 
912 static inline const char *
dnssd_getaddrinfo_result_protocol_to_string(dnssd_getaddrinfo_result_protocol_t protocol)913 dnssd_getaddrinfo_result_protocol_to_string(dnssd_getaddrinfo_result_protocol_t protocol)
914 {
915 	switch (protocol) {
916 		case dnssd_getaddrinfo_result_protocol_udp:		return "UDP";
917 		case dnssd_getaddrinfo_result_protocol_tcp:		return "TCP";
918 		case dnssd_getaddrinfo_result_protocol_tls:		return "TLS";
919 		case dnssd_getaddrinfo_result_protocol_https:	return "HTTPS";
920 		default:										return "?";
921 	}
922 }
923 
924 static inline const char *
dnssd_event_to_string(dnssd_event_t event)925 dnssd_event_to_string(dnssd_event_t event)
926 {
927 	switch (event) {
928 		case dnssd_event_remove_all:	return "RemoveAll";
929 		case dnssd_event_error:			return "Error";
930 		case dnssd_event_invalidated:	return "Invalidated";
931 		default:						return "?";
932 	}
933 }
934 
935 __END_DECLS
936 
937 DNSSD_ASSUME_NONNULL_END
938 
939 
940 #if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
941 	#define dnssd_retain_arc_safe(OBJ)	(OBJ)
942 	#define dnssd_release_arc_safe(OBJ)	do {} while (0)
943 #else
944 	#define dnssd_retain_arc_safe(OBJ)	dnssd_retain(OBJ)
945 	#define dnssd_release_arc_safe(OBJ)	dnssd_release(OBJ)
946 #endif
947 
948 #define dnssd_getaddrinfo_forget(X)				\
949 	do {										\
950 		if (*(X)) {								\
951 			dnssd_getaddrinfo_invalidate(*(X));	\
952 			dnssd_release_arc_safe(*(X));		\
953 			*(X) = NULL;						\
954 		}										\
955 	} while (0)
956 
957 #endif	// __DNSSD_PRIVATE_H__
958