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 #include "dnssd_xpc.h"
18 
19 //======================================================================================================================
20 // MARK: - XPC Dictionary Helper Declarations
21 
22 static int32_t
23 _dnssd_xpc_dictionary_get_int32(xpc_object_t dict, const char *key, bool *out_valid);
24 
25 static int64_t
26 _dnssd_xpc_dictionary_get_int64(xpc_object_t dict, const char *key, bool *out_valid);
27 
28 static int64_t
29 _dnssd_xpc_dictionary_get_int64_limited(xpc_object_t dict, const char *key, int64_t min, int64_t max, bool *out_valid);
30 
31 static uint16_t
32 _dnssd_xpc_dictionary_get_uint16(xpc_object_t dict, const char *key, bool *out_valid);
33 
34 static uint32_t
35 _dnssd_xpc_dictionary_get_uint32(xpc_object_t dict, const char *key, bool *out_valid);
36 
37 static uint64_t
38 _dnssd_xpc_dictionary_get_uint64(xpc_object_t dict, const char *key, bool *out_valid);
39 
40 static uint64_t
41 _dnssd_xpc_dictionary_get_uint64_limited(xpc_object_t dict, const char *key, uint64_t min, uint64_t max,
42 	bool *out_valid);
43 
44 static xpc_object_t
45 _dnssd_xpc_dictionary_get_value(xpc_object_t dict, const char *key, xpc_type_t type);
46 
47 //======================================================================================================================
48 // MARK: - Top-Level Message Dictionaries
49 
50 #define DNSSD_XPC_MESSAGE_KEY_COMMAND	"command"
51 #define DNSSD_XPC_MESSAGE_KEY_ERROR		"error"
52 #define DNSSD_XPC_MESSAGE_KEY_ID		"id"
53 #define DNSSD_XPC_MESSAGE_KEY_PARAMS	"params"
54 #define DNSSD_XPC_MESSAGE_KEY_RESULTS	"results"
55 
56 //======================================================================================================================
57 
58 const char * _Nullable
dnssd_xpc_message_get_command(xpc_object_t msg)59 dnssd_xpc_message_get_command(xpc_object_t msg)
60 {
61 	return xpc_dictionary_get_string(msg, DNSSD_XPC_MESSAGE_KEY_COMMAND);
62 }
63 
64 //======================================================================================================================
65 
66 void
dnssd_xpc_message_set_command(xpc_object_t msg,const char * command)67 dnssd_xpc_message_set_command(xpc_object_t msg, const char *command)
68 {
69 	xpc_dictionary_set_string(msg, DNSSD_XPC_MESSAGE_KEY_COMMAND, command);
70 }
71 
72 //======================================================================================================================
73 
74 DNSServiceErrorType
dnssd_xpc_message_get_error(xpc_object_t msg,bool * out_valid)75 dnssd_xpc_message_get_error(xpc_object_t msg, bool *out_valid)
76 {
77 	return _dnssd_xpc_dictionary_get_int32(msg, DNSSD_XPC_MESSAGE_KEY_ERROR, out_valid);
78 }
79 
80 //======================================================================================================================
81 
82 void
dnssd_xpc_message_set_error(xpc_object_t msg,DNSServiceErrorType error)83 dnssd_xpc_message_set_error(xpc_object_t msg, DNSServiceErrorType error)
84 {
85 	xpc_dictionary_set_int64(msg, DNSSD_XPC_MESSAGE_KEY_ERROR, error);
86 }
87 
88 //======================================================================================================================
89 
90 uint64_t
dnssd_xpc_message_get_id(xpc_object_t msg,bool * out_valid)91 dnssd_xpc_message_get_id(xpc_object_t msg, bool *out_valid)
92 {
93 	return _dnssd_xpc_dictionary_get_uint64(msg, DNSSD_XPC_MESSAGE_KEY_ID, out_valid);
94 }
95 
96 //======================================================================================================================
97 
98 void
dnssd_xpc_message_set_id(xpc_object_t msg,uint64_t ident)99 dnssd_xpc_message_set_id(xpc_object_t msg, uint64_t ident)
100 {
101 	xpc_dictionary_set_uint64(msg, DNSSD_XPC_MESSAGE_KEY_ID, ident);
102 }
103 
104 //======================================================================================================================
105 
106 xpc_object_t
dnssd_xpc_message_get_parameters(xpc_object_t msg)107 dnssd_xpc_message_get_parameters(xpc_object_t msg)
108 {
109 	return xpc_dictionary_get_dictionary(msg, DNSSD_XPC_MESSAGE_KEY_PARAMS);
110 }
111 
112 //======================================================================================================================
113 
114 void
dnssd_xpc_message_set_parameters(xpc_object_t msg,xpc_object_t params)115 dnssd_xpc_message_set_parameters(xpc_object_t msg, xpc_object_t params)
116 {
117 	xpc_dictionary_set_value(msg, DNSSD_XPC_MESSAGE_KEY_PARAMS, params);
118 }
119 
120 //======================================================================================================================
121 
122 xpc_object_t
dnssd_xpc_message_get_results(xpc_object_t msg)123 dnssd_xpc_message_get_results(xpc_object_t msg)
124 {
125 	return xpc_dictionary_get_array(msg, DNSSD_XPC_MESSAGE_KEY_RESULTS);
126 }
127 
128 //======================================================================================================================
129 
130 void
dnssd_xpc_message_set_results(xpc_object_t msg,xpc_object_t results)131 dnssd_xpc_message_set_results(xpc_object_t msg, xpc_object_t results)
132 {
133 	xpc_dictionary_set_value(msg, DNSSD_XPC_MESSAGE_KEY_RESULTS, results);
134 }
135 
136 //======================================================================================================================
137 // MARK: - Parameter Dictionaries
138 
139 #define DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID		"delegate_id"
140 #define DNSSD_XPC_PARAMETERS_KEY_FLAGS				"flags"
141 #define DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID			"account_id"
142 #define DNSSD_XPC_PARAMETERS_KEY_HOSTNAME			"hostname"
143 #define DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX	"interface_index"
144 #define DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS		"need_auth_tags"
145 #define DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS			"protocols"
146 #define DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION	"need_encryption"
147 #define DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG	"fallback_config"
148 #define DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS		"resolver_uuids"
149 #define DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME		"service_scheme"
150 
151 //======================================================================================================================
152 
153 pid_t
dnssd_xpc_parameters_get_delegate_pid(xpc_object_t params,bool * out_valid)154 dnssd_xpc_parameters_get_delegate_pid(xpc_object_t params, bool *out_valid)
155 {
156 	return (pid_t)_dnssd_xpc_dictionary_get_int64(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, out_valid);
157 }
158 
159 //======================================================================================================================
160 
161 void
dnssd_xpc_parameters_set_delegate_pid(xpc_object_t params,pid_t pid)162 dnssd_xpc_parameters_set_delegate_pid(xpc_object_t params, pid_t pid)
163 {
164 	xpc_dictionary_set_int64(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, pid);
165 }
166 
167 //======================================================================================================================
168 
169 const uint8_t *
dnssd_xpc_parameters_get_delegate_uuid(xpc_object_t params)170 dnssd_xpc_parameters_get_delegate_uuid(xpc_object_t params)
171 {
172 	return xpc_dictionary_get_uuid(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID);
173 }
174 
175 //======================================================================================================================
176 
177 void
dnssd_xpc_parameters_set_delegate_uuid(xpc_object_t params,uuid_t uuid)178 dnssd_xpc_parameters_set_delegate_uuid(xpc_object_t params, uuid_t uuid)
179 {
180 	xpc_dictionary_set_uuid(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, uuid);
181 }
182 
183 //======================================================================================================================
184 
185 audit_token_t * _Nullable
dnssd_xpc_parameters_get_delegate_audit_token(const xpc_object_t params,audit_token_t * const audit_token_storage)186 dnssd_xpc_parameters_get_delegate_audit_token(const xpc_object_t params, audit_token_t * const audit_token_storage)
187 {
188 	size_t size;
189 	const void * const data = xpc_dictionary_get_data(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, &size);
190 	if (data && (size == sizeof(*audit_token_storage))) {
191 		memcpy(audit_token_storage, data, size);
192 		return audit_token_storage;
193 	} else {
194 		return NULL;
195 	}
196 }
197 
198 //======================================================================================================================
199 
200 void
dnssd_xpc_parameters_set_delegate_audit_token(const xpc_object_t params,const audit_token_t * const audit_token)201 dnssd_xpc_parameters_set_delegate_audit_token(const xpc_object_t params, const audit_token_t * const audit_token)
202 {
203 	xpc_dictionary_set_data(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, audit_token, sizeof(*audit_token));
204 }
205 
206 //======================================================================================================================
207 
208 DNSServiceFlags
dnssd_xpc_parameters_get_flags(xpc_object_t params,bool * out_valid)209 dnssd_xpc_parameters_get_flags(xpc_object_t params, bool *out_valid)
210 {
211 	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_FLAGS, out_valid);
212 }
213 
214 //======================================================================================================================
215 
216 void
dnssd_xpc_parameters_set_flags(xpc_object_t params,DNSServiceFlags flags)217 dnssd_xpc_parameters_set_flags(xpc_object_t params, DNSServiceFlags flags)
218 {
219 	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_FLAGS, flags);
220 }
221 
222 //======================================================================================================================
223 
224 const char *
dnssd_xpc_parameters_get_account_id(xpc_object_t params)225 dnssd_xpc_parameters_get_account_id(xpc_object_t params)
226 {
227 	return xpc_dictionary_get_string(params, DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID);
228 }
229 
230 //======================================================================================================================
231 
232 void
dnssd_xpc_parameters_set_account_id(xpc_object_t params,const char * account_id)233 dnssd_xpc_parameters_set_account_id(xpc_object_t params, const char *account_id)
234 {
235 	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID, account_id);
236 }
237 
238 //======================================================================================================================
239 
240 xpc_object_t
dnssd_xpc_parameters_get_hostname_object(xpc_object_t params)241 dnssd_xpc_parameters_get_hostname_object(xpc_object_t params)
242 {
243 	return _dnssd_xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_HOSTNAME, XPC_TYPE_STRING);
244 }
245 
246 //======================================================================================================================
247 
248 void
dnssd_xpc_parameters_set_hostname(xpc_object_t params,const char * hostname)249 dnssd_xpc_parameters_set_hostname(xpc_object_t params, const char *hostname)
250 {
251 	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_HOSTNAME, hostname);
252 }
253 
254 //======================================================================================================================
255 
256 uint32_t
dnssd_xpc_parameters_get_interface_index(xpc_object_t params,bool * out_valid)257 dnssd_xpc_parameters_get_interface_index(xpc_object_t params, bool *out_valid)
258 {
259 	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX, out_valid);
260 }
261 
262 //======================================================================================================================
263 
264 void
dnssd_xpc_parameters_set_interface_index(xpc_object_t params,uint32_t interface_index)265 dnssd_xpc_parameters_set_interface_index(xpc_object_t params, uint32_t interface_index)
266 {
267 	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX, interface_index);
268 }
269 
270 //======================================================================================================================
271 
272 bool
dnssd_xpc_parameters_get_need_authentication_tags(xpc_object_t params)273 dnssd_xpc_parameters_get_need_authentication_tags(xpc_object_t params)
274 {
275 	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS);
276 }
277 
278 //======================================================================================================================
279 
280 void
dnssd_xpc_parameters_set_need_authentication_tags(xpc_object_t params,bool need_auth_tags)281 dnssd_xpc_parameters_set_need_authentication_tags(xpc_object_t params, bool need_auth_tags)
282 {
283 	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS, need_auth_tags);
284 }
285 
286 //======================================================================================================================
287 
288 void
dnssd_xpc_parameters_set_need_encrypted_query(xpc_object_t params,bool need,_Nullable xpc_object_t fallback_config)289 dnssd_xpc_parameters_set_need_encrypted_query(xpc_object_t params, bool need, _Nullable xpc_object_t fallback_config)
290 {
291 	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION, need);
292 	if (fallback_config != NULL) {
293 		xpc_dictionary_set_value(params, DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG, fallback_config);
294 	}
295 }
296 
297 //======================================================================================================================
298 
299 bool
dnssd_xpc_parameters_get_need_encrypted_query(xpc_object_t params)300 dnssd_xpc_parameters_get_need_encrypted_query(xpc_object_t params)
301 {
302 	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION);
303 }
304 
305 //======================================================================================================================
306 
307 xpc_object_t _Nullable
dnssd_xpc_parameters_get_fallback_config(xpc_object_t params)308 dnssd_xpc_parameters_get_fallback_config(xpc_object_t params)
309 {
310 	return xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG);
311 }
312 
313 //======================================================================================================================
314 
315 xpc_object_t _Nullable
dnssd_xpc_parameters_get_resolver_uuid_array(xpc_object_t params)316 dnssd_xpc_parameters_get_resolver_uuid_array(xpc_object_t params)
317 {
318 	return xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS);
319 }
320 
321 //======================================================================================================================
322 
323 void
dnssd_xpc_parameters_add_resolver_uuid(xpc_object_t params,uuid_t _Nonnull uuid)324 dnssd_xpc_parameters_add_resolver_uuid(xpc_object_t params, uuid_t _Nonnull uuid)
325 {
326 	xpc_object_t resolver_uuid_array = xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS);
327 	if (resolver_uuid_array == NULL) {
328 		resolver_uuid_array = xpc_array_create(NULL, 0);
329 		xpc_dictionary_set_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS, resolver_uuid_array);
330 		xpc_release(resolver_uuid_array);
331 	}
332 	xpc_array_set_uuid(resolver_uuid_array, XPC_ARRAY_APPEND, uuid);
333 }
334 
335 //======================================================================================================================
336 
337 DNSServiceProtocol
dnssd_xpc_parameters_get_protocols(xpc_object_t params,bool * out_valid)338 dnssd_xpc_parameters_get_protocols(xpc_object_t params, bool *out_valid)
339 {
340 	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS, out_valid);
341 }
342 
343 //======================================================================================================================
344 
345 void
dnssd_xpc_parameters_set_protocols(xpc_object_t params,DNSServiceProtocol protocols)346 dnssd_xpc_parameters_set_protocols(xpc_object_t params, DNSServiceProtocol protocols)
347 {
348 	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS, protocols);
349 }
350 
351 //======================================================================================================================
352 
353 const char * _Nullable
dnssd_xpc_parameters_get_service_scheme(xpc_object_t params)354 dnssd_xpc_parameters_get_service_scheme(xpc_object_t params)
355 {
356 	return xpc_dictionary_get_string(params, DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME);
357 }
358 
359 //======================================================================================================================
360 
361 void
dnssd_xpc_parameters_set_service_scheme(xpc_object_t params,const char * service_scheme)362 dnssd_xpc_parameters_set_service_scheme(xpc_object_t params, const char *service_scheme)
363 {
364 	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME, service_scheme);
365 }
366 
367 //======================================================================================================================
368 // MARK: - Result Dictionaries
369 
370 #define DNSSD_XPC_RESULT_KEY_AUTH_TAG			"auth_tag"
371 #define DNSSD_XPC_RESULT_KEY_CNAME_UPDATE		"cname_update"
372 #define DNSSD_XPC_RESULT_KEY_ERROR				"error"
373 #define DNSSD_XPC_RESULT_KEY_FLAGS				"flags"
374 #define DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX	"interface_index"
375 #define DNSSD_XPC_RESULT_KEY_PROVIDER_NAME		"provider_name"
376 #define DNSSD_XPC_RESULT_KEY_RECORD_CLASS		"rclass"
377 #define DNSSD_XPC_RESULT_KEY_RECORD_DATA		"rdata"
378 #define DNSSD_XPC_RESULT_KEY_RECORD_NAME		"rname"
379 #define DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL	"rprotocol"
380 #define DNSSD_XPC_RESULT_KEY_RECORD_TYPE		"rtype"
381 
382 //======================================================================================================================
383 
384 xpc_object_t
dnssd_xpc_result_get_authentication_tag_object(xpc_object_t result)385 dnssd_xpc_result_get_authentication_tag_object(xpc_object_t result)
386 {
387 	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_AUTH_TAG, XPC_TYPE_DATA);
388 }
389 
390 //======================================================================================================================
391 
392 void
dnssd_xpc_result_set_authentication_tag(xpc_object_t result,const void * auth_tag_ptr,size_t auth_tag_len)393 dnssd_xpc_result_set_authentication_tag(xpc_object_t result, const void *auth_tag_ptr, size_t auth_tag_len)
394 {
395 	xpc_dictionary_set_data(result, DNSSD_XPC_RESULT_KEY_AUTH_TAG, auth_tag_ptr, auth_tag_len);
396 }
397 
398 //======================================================================================================================
399 
400 DNSServiceErrorType
dnssd_xpc_result_get_error(xpc_object_t result,bool * out_valid)401 dnssd_xpc_result_get_error(xpc_object_t result, bool *out_valid)
402 {
403 	return _dnssd_xpc_dictionary_get_int32(result, DNSSD_XPC_RESULT_KEY_ERROR, out_valid);
404 }
405 
406 //======================================================================================================================
407 
408 void
dnssd_xpc_result_set_error(xpc_object_t result,DNSServiceErrorType error)409 dnssd_xpc_result_set_error(xpc_object_t result, DNSServiceErrorType error)
410 {
411 	xpc_dictionary_set_int64(result, DNSSD_XPC_RESULT_KEY_ERROR, error);
412 }
413 
414 //======================================================================================================================
415 
416 DNSServiceFlags
dnssd_xpc_result_get_flags(xpc_object_t result,bool * out_valid)417 dnssd_xpc_result_get_flags(xpc_object_t result, bool *out_valid)
418 {
419 	return _dnssd_xpc_dictionary_get_uint32(result, DNSSD_XPC_RESULT_KEY_FLAGS, out_valid);
420 }
421 
422 //======================================================================================================================
423 
424 void
dnssd_xpc_result_set_flags(xpc_object_t result,DNSServiceFlags flags)425 dnssd_xpc_result_set_flags(xpc_object_t result, DNSServiceFlags flags)
426 {
427 	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_FLAGS, flags);
428 }
429 
430 //======================================================================================================================
431 
432 uint32_t
dnssd_xpc_result_get_interface_index(xpc_object_t result,bool * out_valid)433 dnssd_xpc_result_get_interface_index(xpc_object_t result, bool *out_valid)
434 {
435 	return _dnssd_xpc_dictionary_get_uint32(result, DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX, out_valid);
436 }
437 
438 //======================================================================================================================
439 
440 void
dnssd_xpc_result_set_interface_index(xpc_object_t result,uint32_t interface_index)441 dnssd_xpc_result_set_interface_index(xpc_object_t result, uint32_t interface_index)
442 {
443 	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX, interface_index);
444 }
445 
446 //======================================================================================================================
447 
448 uint16_t
dnssd_xpc_result_get_record_class(xpc_object_t result,bool * out_valid)449 dnssd_xpc_result_get_record_class(xpc_object_t result, bool *out_valid)
450 {
451 	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_CLASS, out_valid);
452 }
453 
454 //======================================================================================================================
455 
456 void
dnssd_xpc_result_set_record_class(xpc_object_t result,uint16_t class)457 dnssd_xpc_result_set_record_class(xpc_object_t result, uint16_t class)
458 {
459 	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_CLASS, class);
460 }
461 
462 //======================================================================================================================
463 
464 xpc_object_t
dnssd_xpc_result_get_record_data_object(xpc_object_t result)465 dnssd_xpc_result_get_record_data_object(xpc_object_t result)
466 {
467 	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_RECORD_DATA, XPC_TYPE_DATA);
468 }
469 
470 //======================================================================================================================
471 
472 void
dnssd_xpc_result_set_record_data(xpc_object_t result,const void * data_ptr,size_t data_len)473 dnssd_xpc_result_set_record_data(xpc_object_t result, const void *data_ptr, size_t data_len)
474 {
475 	xpc_dictionary_set_data(result, DNSSD_XPC_RESULT_KEY_RECORD_DATA, data_ptr, data_len);
476 }
477 
478 //======================================================================================================================
479 
480 xpc_object_t
dnssd_xpc_result_get_record_name_object(xpc_object_t result)481 dnssd_xpc_result_get_record_name_object(xpc_object_t result)
482 {
483 	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_RECORD_NAME, XPC_TYPE_STRING);
484 }
485 
486 //======================================================================================================================
487 
488 void
dnssd_xpc_result_set_record_name(xpc_object_t result,const char * name)489 dnssd_xpc_result_set_record_name(xpc_object_t result, const char *name)
490 {
491 	xpc_dictionary_set_string(result, DNSSD_XPC_RESULT_KEY_RECORD_NAME, name);
492 }
493 
494 //======================================================================================================================
495 
496 uint16_t
dnssd_xpc_result_get_record_type(xpc_object_t result,bool * out_valid)497 dnssd_xpc_result_get_record_type(xpc_object_t result, bool *out_valid)
498 {
499 	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_TYPE, out_valid);
500 }
501 
502 //======================================================================================================================
503 
504 void
dnssd_xpc_result_set_record_type(xpc_object_t result,uint16_t type)505 dnssd_xpc_result_set_record_type(xpc_object_t result, uint16_t type)
506 {
507 	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_TYPE, type);
508 }
509 
510 //======================================================================================================================
511 
512 uint16_t
dnssd_xpc_result_get_record_protocol(xpc_object_t result,bool * out_valid)513 dnssd_xpc_result_get_record_protocol(xpc_object_t result, bool * out_valid)
514 {
515 	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL, out_valid);
516 }
517 
518 //======================================================================================================================
519 
520 void
dnssd_xpc_result_set_record_protocol(xpc_object_t result,uint16_t protocol)521 dnssd_xpc_result_set_record_protocol(xpc_object_t result, uint16_t protocol)
522 {
523 	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL, protocol);
524 }
525 
526 //======================================================================================================================
527 
528 xpc_object_t
dnssd_xpc_result_get_provider_name_object(xpc_object_t result)529 dnssd_xpc_result_get_provider_name_object(xpc_object_t result)
530 {
531 	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_PROVIDER_NAME, XPC_TYPE_STRING);
532 }
533 
534 //======================================================================================================================
535 
536 void
dnssd_xpc_result_set_provider_name(xpc_object_t result,const char * name)537 dnssd_xpc_result_set_provider_name(xpc_object_t result, const char *name)
538 {
539 	xpc_dictionary_set_string(result, DNSSD_XPC_RESULT_KEY_PROVIDER_NAME, name);
540 }
541 
542 //======================================================================================================================
543 
544 xpc_object_t
dnssd_xpc_result_get_cname_update(xpc_object_t result)545 dnssd_xpc_result_get_cname_update(xpc_object_t result)
546 {
547 	return xpc_dictionary_get_array(result, DNSSD_XPC_RESULT_KEY_CNAME_UPDATE);
548 }
549 
550 //======================================================================================================================
551 
552 void
dnssd_xpc_result_set_cname_update(xpc_object_t result,xpc_object_t cname_update)553 dnssd_xpc_result_set_cname_update(xpc_object_t result, xpc_object_t cname_update)
554 {
555 	xpc_dictionary_set_value(result, DNSSD_XPC_RESULT_KEY_CNAME_UPDATE, cname_update);
556 }
557 
558 //======================================================================================================================
559 // MARK: - XPC Dictionary Helpers
560 
561 static int32_t
_dnssd_xpc_dictionary_get_int32(xpc_object_t dict,const char * key,bool * out_valid)562 _dnssd_xpc_dictionary_get_int32(xpc_object_t dict, const char *key, bool *out_valid)
563 {
564 	return (int32_t)_dnssd_xpc_dictionary_get_int64_limited(dict, key, INT32_MIN, INT32_MAX, out_valid);
565 }
566 
567 //======================================================================================================================
568 
569 static int64_t
_dnssd_xpc_dictionary_get_int64(xpc_object_t dict,const char * key,bool * out_valid)570 _dnssd_xpc_dictionary_get_int64(xpc_object_t dict, const char *key, bool *out_valid)
571 {
572 	return _dnssd_xpc_dictionary_get_int64_limited(dict, key, INT64_MIN, INT64_MAX, out_valid);
573 }
574 
575 //======================================================================================================================
576 
577 static int64_t
_dnssd_xpc_dictionary_get_int64_limited(xpc_object_t dict,const char * key,int64_t min,int64_t max,bool * out_valid)578 _dnssd_xpc_dictionary_get_int64_limited(xpc_object_t dict, const char *key, int64_t min, int64_t max, bool *out_valid)
579 {
580 	int64_t	i64;
581 	bool	valid;
582 
583 	xpc_object_t const value = _dnssd_xpc_dictionary_get_value(dict, key, XPC_TYPE_INT64);
584 	if (value) {
585 		i64 = xpc_int64_get_value(value);
586 		if ((i64 >= min) && (i64 <= max)) {
587 			valid	= true;
588 		} else {
589 			i64		= 0;
590 			valid	= false;
591 		}
592 	} else {
593 		i64		= 0;
594 		valid	= false;
595 	}
596 	if (out_valid) {
597 		*out_valid = valid;
598 	}
599 	return i64;
600 }
601 
602 //======================================================================================================================
603 
604 static uint16_t
_dnssd_xpc_dictionary_get_uint16(xpc_object_t dict,const char * key,bool * out_valid)605 _dnssd_xpc_dictionary_get_uint16(xpc_object_t dict, const char *key, bool *out_valid)
606 {
607 	return (uint16_t)_dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT16_MAX, out_valid);
608 }
609 
610 //======================================================================================================================
611 
612 static uint32_t
_dnssd_xpc_dictionary_get_uint32(xpc_object_t dict,const char * key,bool * out_valid)613 _dnssd_xpc_dictionary_get_uint32(xpc_object_t dict, const char *key, bool *out_valid)
614 {
615 	return (uint32_t)_dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT32_MAX, out_valid);
616 }
617 
618 //======================================================================================================================
619 
620 static uint64_t
_dnssd_xpc_dictionary_get_uint64(xpc_object_t dict,const char * key,bool * out_valid)621 _dnssd_xpc_dictionary_get_uint64(xpc_object_t dict, const char *key, bool *out_valid)
622 {
623 	return _dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT64_MAX, out_valid);
624 }
625 
626 //======================================================================================================================
627 
628 static uint64_t
_dnssd_xpc_dictionary_get_uint64_limited(xpc_object_t dict,const char * key,uint64_t min,uint64_t max,bool * out_valid)629 _dnssd_xpc_dictionary_get_uint64_limited(xpc_object_t dict, const char *key, uint64_t min, uint64_t max,
630 	bool *out_valid)
631 {
632 	uint64_t	u64;
633 	bool		valid;
634 
635 	xpc_object_t const value = _dnssd_xpc_dictionary_get_value(dict, key, XPC_TYPE_UINT64);
636 	if (value) {
637 		u64 = xpc_uint64_get_value(value);
638 		if ((u64 >= min) && (u64 <= max)) {
639 			valid	= true;
640 		} else {
641 			u64		= 0;
642 			valid	= false;
643 		}
644 	} else {
645 		u64		= 0;
646 		valid	= false;
647 	}
648 	if (out_valid) {
649 		*out_valid = valid;
650 	}
651 	return u64;
652 }
653 
654 //======================================================================================================================
655 
656 static xpc_object_t
_dnssd_xpc_dictionary_get_value(xpc_object_t dict,const char * key,xpc_type_t type)657 _dnssd_xpc_dictionary_get_value(xpc_object_t dict, const char *key, xpc_type_t type)
658 {
659 	xpc_object_t value = xpc_dictionary_get_value(dict, key);
660 	return (value && (xpc_get_type(value) == type)) ? value : NULL;
661 }
662