]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/uDNSPathEvalulation.c
mDNSResponder-1096.60.2.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / uDNSPathEvalulation.c
1 /* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
2 *
3 * Copyright (c) 2013-2018 Apple Inc. All rights reserved.
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 */
17
18 #include "mDNSMacOSX.h"
19 #include <libproc.h>
20
21 #if __has_include(<nw/private.h>)
22 #include <nw/private.h>
23 #else
24 #include <network/private.h>
25 #define nw_release(X) network_release(X)
26 #endif
27
28 #include "dns_sd_internal.h"
29
30 //Gets the DNSPolicy from NW PATH EVALUATOR
31 mDNSexport void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked)
32 {
33 if (__builtin_available(macOS 10.14, *))
34 {
35 q->ServiceID = -1; // initialize the ServiceID to default value of -1
36
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)
39 {
40 *isBlocked = mDNSfalse;
41 return;
42 }
43
44 mDNSs32 service_id;
45 mDNSu32 client_ifindex, dnspol_ifindex;
46 int retval;
47 struct proc_uniqidentifierinfo info;
48 mDNSBool isUUIDSet;
49
50 char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
51 ConvertDomainNameToCString(&q->qname, unenc_name);
52
53 nw_endpoint_t host = nw_endpoint_create_host(unenc_name, "0");
54 if (host == NULL)
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);
57
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);
62
63 #if TARGET_OS_WATCH
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
67
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))
75 {
76 client_ifindex = 0;
77 }
78 else
79 {
80 client_ifindex = (mDNSu32)(uintptr_t)q->InterfaceID;
81 }
82
83 if (client_ifindex > 0)
84 {
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);
89 else
90 LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: client_intf returned by nw_interface_create_with_index() is NULL");
91 }
92
93 nw_parameters_set_uid(parameters,(uid_t)q->euid);
94
95 if (q->pid != 0)
96 {
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))
100 {
101 nw_parameters_set_e_proc_uuid(parameters, info.p_uuid);
102 isUUIDSet = mDNStrue;
103 }
104 else
105 {
106 debugf("mDNSPlatformGetDNSRoutePolicy: proc_pidinfo returned %d", retval);
107 isUUIDSet = mDNSfalse;
108 }
109 }
110 else
111 {
112 nw_parameters_set_e_proc_uuid(parameters, q->uuid);
113 isUUIDSet = mDNStrue;
114 }
115
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);
120
121 if (host != NULL)
122 nw_release(host);
123 if (parameters != NULL)
124 nw_release(parameters);
125
126 nw_path_t path = nw_path_evaluator_copy_path(evaluator);
127 if (path == NULL)
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);
130
131 service_id = nw_path_get_flow_divert_unit(path);
132 if (service_id != 0)
133 {
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);
136 }
137 else
138 {
139 nw_interface_t nwpath_intf = nw_path_copy_scoped_interface(path);
140 if (nwpath_intf != NULL)
141 {
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;
145
146 nw_release(nwpath_intf);
147
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);
151 }
152 else
153 {
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);
155 }
156 }
157
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;
160 else
161 *isBlocked = mDNSfalse;
162
163 if (path != NULL)
164 nw_release(path);
165 if (evaluator != NULL)
166 nw_release(evaluator);
167 }
168 else
169 {
170 *isBlocked = mDNSfalse;
171 }
172 }