1 /* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
3 * Copyright (c) 2013-2018 Apple Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "mDNSMacOSX.h"
21 #if __has_include(<nw/private.h>)
22 #include <nw/private.h>
24 #include <network/private.h>
25 #define nw_release(X) network_release(X)
28 #include "dns_sd_internal.h"
30 //Gets the DNSPolicy from NW PATH EVALUATOR
31 mDNSexport
void mDNSPlatformGetDNSRoutePolicy(DNSQuestion
*q
, mDNSBool
*isBlocked
)
33 if (__builtin_available(macOS
10.14, *))
35 q
->ServiceID
= -1; // initialize the ServiceID to default value of -1
37 // Return for non-unicast DNS queries, invalid pid, if NWPathEvaluation is already done by the client, or NWPathEvaluation not available on this OS
38 if (mDNSOpaque16IsZero(q
->TargetQID
) || (q
->pid
< 0) || (q
->flags
& kDNSServiceFlagsPathEvaluationDone
) || !nw_endpoint_create_host
)
40 *isBlocked
= mDNSfalse
;
45 mDNSu32 client_ifindex
, dnspol_ifindex
;
47 struct proc_uniqidentifierinfo info
;
50 char unenc_name
[MAX_ESCAPED_DOMAIN_NAME
];
51 ConvertDomainNameToCString(&q
->qname
, unenc_name
);
53 nw_endpoint_t host
= nw_endpoint_create_host(unenc_name
, "0");
55 LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_endpoint_t host is NULL", q
->qname
.c
,
56 DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
58 nw_parameters_t parameters
= nw_parameters_create();
59 if (parameters
== NULL
)
60 LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_endpoint_t parameters is NULL", q
->qname
.c
,
61 DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
64 // Companion interface on watchOS does not support DNS, so we don't want path evalution to return it to us.
65 nw_parameters_set_companion_preference(parameters
, nw_parameters_agent_preference_avoid
);
66 #endif // TARGET_OS_WATCH
68 // Check for all the special (negative) internal value interface indices before initializing client_ifindex
69 if ( (q
->InterfaceID
== mDNSInterface_Any
)
70 || (q
->InterfaceID
== mDNSInterface_LocalOnly
)
71 || (q
->InterfaceID
== mDNSInterfaceMark
)
72 || (q
->InterfaceID
== mDNSInterface_P2P
)
73 || (q
->InterfaceID
== mDNSInterface_BLE
)
74 || (q
->InterfaceID
== uDNSInterfaceMark
))
80 client_ifindex
= (mDNSu32
)(uintptr_t)q
->InterfaceID
;
83 if (client_ifindex
> 0)
85 nw_interface_t client_intf
= nw_interface_create_with_index(client_ifindex
);
86 nw_parameters_require_interface(parameters
, client_intf
);
87 if (client_intf
!= NULL
)
88 nw_release(client_intf
);
90 LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: client_intf returned by nw_interface_create_with_index() is NULL");
93 nw_parameters_set_uid(parameters
,(uid_t
)q
->euid
);
97 nw_parameters_set_pid(parameters
, q
->pid
);
98 retval
= proc_pidinfo(q
->pid
, PROC_PIDUNIQIDENTIFIERINFO
, 1, &info
, sizeof(info
));
99 if (retval
== (int)sizeof(info
))
101 nw_parameters_set_e_proc_uuid(parameters
, info
.p_uuid
);
102 isUUIDSet
= mDNStrue
;
106 debugf("mDNSPlatformGetDNSRoutePolicy: proc_pidinfo returned %d", retval
);
107 isUUIDSet
= mDNSfalse
;
112 nw_parameters_set_e_proc_uuid(parameters
, q
->uuid
);
113 isUUIDSet
= mDNStrue
;
116 nw_path_evaluator_t evaluator
= nw_path_create_evaluator_for_endpoint(host
, parameters
);
117 if (evaluator
== NULL
)
118 LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_path_evaluator_t evaluator is NULL", q
->qname
.c
,
119 DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
123 if (parameters
!= NULL
)
124 nw_release(parameters
);
126 nw_path_t path
= nw_path_evaluator_copy_path(evaluator
);
128 LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_path_t path is NULL", q
->qname
.c
,
129 DNSTypeName(q
->qtype
), q
->pid
, q
->euid
, q
->ServiceID
);
131 service_id
= nw_path_get_flow_divert_unit(path
);
134 q
->ServiceID
= service_id
;
135 LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s service ID is set ->service_ID:[%d] ", q
->qname
.c
, service_id
);
139 nw_interface_t nwpath_intf
= nw_path_copy_scoped_interface(path
);
140 if (nwpath_intf
!= NULL
)
142 // Use the new scoped interface given by NW PATH EVALUATOR
143 dnspol_ifindex
= nw_interface_get_index(nwpath_intf
);
144 q
->InterfaceID
= (mDNSInterfaceID
)(uintptr_t)dnspol_ifindex
;
146 nw_release(nwpath_intf
);
148 if (dnspol_ifindex
!= client_ifindex
)
149 LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy has changed the scoped ifindex from [%d] to [%d]",
150 client_ifindex
, dnspol_ifindex
);
154 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
);
158 if (isUUIDSet
&& path
&& (nw_path_get_status(path
) == nw_path_status_unsatisfied
) && (nw_path_get_reason(path
) != nw_path_reason_no_route
))
159 *isBlocked
= mDNStrue
;
161 *isBlocked
= mDNSfalse
;
165 if (evaluator
!= NULL
)
166 nw_release(evaluator
);
170 *isBlocked
= mDNSfalse
;