2 * Copyright (c) 2013-2020 Apple Inc. All rights reserved.
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
8 * https://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "mDNSMacOSX.h"
19 #include <nw/private.h>
21 #include "dns_sd_internal.h"
23 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
24 #include "QuerierSupport.h"
27 #define _nw_forget(PTR) \
37 //Gets the DNSPolicy from NW PATH EVALUATOR
38 mDNSexport
void mDNSPlatformGetDNSRoutePolicy(DNSQuestion
*q
)
40 nw_endpoint_t host
= NULL
;
41 nw_parameters_t parameters
= NULL
;
42 nw_path_evaluator_t evaluator
= NULL
;
43 nw_path_t path
= NULL
;
44 mDNSBool isBlocked
= mDNSfalse
;
45 q
->ServiceID
= -1; // initialize the ServiceID to default value of -1
47 // Return for non-unicast DNS queries, or invalid PID.
48 if (mDNSOpaque16IsZero(q
->TargetQID
) || (q
->pid
< 0))
54 mDNSu32 client_ifindex
, dnspol_ifindex
;
56 struct proc_uniqidentifierinfo info
;
59 char unenc_name
[MAX_ESCAPED_DOMAIN_NAME
];
60 ConvertDomainNameToCString(&q
->qname
, unenc_name
);
62 host
= nw_endpoint_create_host(unenc_name
, "0");
65 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
66 "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME
" (" PUB_S
"), PID[%d], EUID[%d], ServiceID[%d]"
68 mDNSVal16(q
->TargetQID
), DM_NAME_PARAM(&q
->qname
), DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
71 parameters
= nw_parameters_create();
72 if (parameters
== NULL
)
74 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
75 "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME
" (" PUB_S
"), PID[%d], EUID[%d], ServiceID[%d]"
76 " parameters is NULL",
77 mDNSVal16(q
->TargetQID
), DM_NAME_PARAM(&q
->qname
), DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
81 static xpc_object_t prohibited_interface_subtypes
= NULL
;
82 // Companion interface on watchOS does not support DNS, so we don't want path evalution to return it to us.
83 if (prohibited_interface_subtypes
== NULL
)
85 prohibited_interface_subtypes
= xpc_array_create(NULL
, 0);
86 if (prohibited_interface_subtypes
!= NULL
)
88 xpc_array_set_uint64(prohibited_interface_subtypes
, XPC_ARRAY_APPEND
, nw_interface_subtype_companion
);
91 if (prohibited_interface_subtypes
== NULL
)
93 LogRedact(MDNS_LOG_CATEGORY_UDNS
, MDNS_LOG_ERROR
,
94 "mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: prohibited_interface_subtypes returned by xpc_array_create() is NULL");
98 nw_parameters_set_prohibited_interface_subtypes(parameters
, prohibited_interface_subtypes
);
100 #endif // TARGET_OS_WATCH
102 // Check for all the special (negative) internal value interface indices before initializing client_ifindex
103 if ( (q
->InterfaceID
== mDNSInterface_Any
)
104 || (q
->InterfaceID
== mDNSInterface_LocalOnly
)
105 || (q
->InterfaceID
== mDNSInterfaceMark
)
106 || (q
->InterfaceID
== mDNSInterface_P2P
)
107 || (q
->InterfaceID
== mDNSInterface_BLE
)
108 || (q
->InterfaceID
== uDNSInterfaceMark
))
114 client_ifindex
= (mDNSu32
)(uintptr_t)q
->InterfaceID
;
117 if (client_ifindex
> 0)
119 nw_interface_t client_intf
= nw_interface_create_with_index(client_ifindex
);
122 nw_parameters_require_interface(parameters
, client_intf
);
123 _nw_forget(&client_intf
);
127 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
128 "[Q%u] mDNSPlatformGetDNSRoutePolicy: nw_interface_create_with_index() returned NULL for index %u",
129 mDNSVal16(q
->TargetQID
), client_ifindex
);
133 nw_parameters_set_uid(parameters
,(uid_t
)q
->euid
);
137 nw_parameters_set_pid(parameters
, q
->pid
);
138 retval
= proc_pidinfo(q
->pid
, PROC_PIDUNIQIDENTIFIERINFO
, 1, &info
, sizeof(info
));
139 if (retval
== (int)sizeof(info
))
141 nw_parameters_set_e_proc_uuid(parameters
, info
.p_uuid
);
142 isUUIDSet
= mDNStrue
;
146 debugf("mDNSPlatformGetDNSRoutePolicy: proc_pidinfo returned %d", retval
);
147 isUUIDSet
= mDNSfalse
;
152 nw_parameters_set_e_proc_uuid(parameters
, q
->uuid
);
153 isUUIDSet
= mDNStrue
;
156 evaluator
= nw_path_create_evaluator_for_endpoint(host
, parameters
);
157 if (evaluator
== NULL
)
159 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
160 "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME
" (" PUB_S
"), PID[%d], EUID[%d], ServiceID[%d]"
161 " evaluator is NULL",
162 mDNSVal16(q
->TargetQID
), DM_NAME_PARAM(&q
->qname
), DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
166 _nw_forget(¶meters
);
168 path
= nw_path_evaluator_copy_path(evaluator
);
171 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
172 "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME
" (" PUB_S
"), PID[%d], EUID[%d], ServiceID[%d]"
174 mDNSVal16(q
->TargetQID
), DM_NAME_PARAM(&q
->qname
), DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
177 service_id
= nw_path_get_flow_divert_unit(path
);
180 q
->ServiceID
= service_id
;
181 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
182 "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME
" service ID is set ->service_ID:[%d] ",
183 mDNSVal16(q
->TargetQID
), DM_NAME_PARAM(&q
->qname
), service_id
);
187 nw_interface_t nwpath_intf
= nw_path_copy_scoped_interface(path
);
188 if (nwpath_intf
!= NULL
)
190 // Use the new scoped interface given by NW PATH EVALUATOR
191 dnspol_ifindex
= nw_interface_get_index(nwpath_intf
);
192 q
->InterfaceID
= (mDNSInterfaceID
)(uintptr_t)dnspol_ifindex
;
194 _nw_forget(&nwpath_intf
);
196 if (dnspol_ifindex
!= client_ifindex
)
198 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
199 "[Q%u] mDNSPlatformGetDNSRoutePolicy: DNS Route Policy has changed the scoped ifindex from [%d] to [%d]",
200 mDNSVal16(q
->TargetQID
), client_ifindex
, dnspol_ifindex
);
205 debugf("mDNSPlatformGetDNSRoutePolicy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_interface_t nwpath_intf is NULL ", q
->qname
.c
, DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
209 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
210 uuid_clear(q
->ResolverUUID
);
211 if (__builtin_available(macOS
10.16, iOS
14.0, watchOS
7.0, tvOS
14.0, *))
215 __block nw_resolver_config_t best_config
= NULL
;
216 __block nw_resolver_class_t best_class
= nw_resolver_class_default_direct
;
217 nw_path_enumerate_resolver_configs(path
,
218 ^bool(nw_resolver_config_t config
)
220 const nw_resolver_class_t
class = nw_resolver_config_get_class(config
);
221 if (class != nw_resolver_class_default_direct
&&
222 (best_class
== nw_resolver_class_default_direct
|| class < best_class
))
225 best_config
= config
;
229 if (best_config
!= NULL
)
231 nw_resolver_config_get_identifier(best_config
, q
->ResolverUUID
);
235 if (!uuid_is_null(q
->ResolverUUID
))
237 Querier_RegisterPathResolver(q
->ResolverUUID
);
240 if (isUUIDSet
&& path
&& (nw_path_get_status(path
) == nw_path_status_unsatisfied
) && (nw_path_get_reason(path
) != nw_path_reason_no_route
))
242 isBlocked
= mDNStrue
;
247 _nw_forget(¶meters
);
249 _nw_forget(&evaluator
);
250 q
->BlockedByPolicy
= isBlocked
;