Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / mDNSMacOSX / uDNSPathEvalulation.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2013, 2015 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 #include <network/private.h>
21 #include "dns_sd_internal.h"
22
23 //Gets the DNSPolicy from NW PATH EVALUATOR
24 mDNSexport void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked)
25 {
26     q->ServiceID = -1; // initialize the ServiceID to default value of -1
27
28     // Return for non-unicast DNS queries, invalid pid, if NWPathEvaluation is already done by the client, or NWPathEvaluation not available on this OS
29     if (mDNSOpaque16IsZero(q->TargetQID) || (q->pid < 0) || (q->flags & kDNSServiceFlagsPathEvaluationDone) || !nw_endpoint_create_host)
30     {
31         *isBlocked = mDNSfalse;
32         return;
33     }
34     
35     mDNSs32 service_id;
36     mDNSu32 client_ifindex, dnspol_ifindex;
37     int retval;
38     struct proc_uniqidentifierinfo info;
39     mDNSBool isUUIDSet;
40     
41     char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
42     ConvertDomainNameToCString(&q->qname, unenc_name);
43     
44     nw_endpoint_t host = nw_endpoint_create_host(unenc_name, "0");
45     if (host == NULL)
46         LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_endpoint_t host is NULL", q->qname.c,
47                DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
48     
49     nw_parameters_t parameters = nw_parameters_create();
50     if (parameters == NULL)
51         LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_endpoint_t parameters is NULL", q->qname.c,
52                DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
53     
54     // Check for all the special (negative) internal value interface indices before initializing client_ifindex
55     if (   (q->InterfaceID == mDNSInterface_Any)
56         || (q->InterfaceID == mDNSInterface_Unicast)
57         || (q->InterfaceID == mDNSInterface_LocalOnly)
58         || (q->InterfaceID == mDNSInterfaceMark)
59         || (q->InterfaceID == mDNSInterface_P2P)
60         || (q->InterfaceID == mDNSInterface_BLE)
61         || (q->InterfaceID == uDNSInterfaceMark))
62     {
63         client_ifindex = 0;
64     }
65     else
66     {
67         client_ifindex = (mDNSu32)(uintptr_t)q->InterfaceID;
68     }
69
70     
71     if (client_ifindex > 0)
72     {
73         nw_interface_t client_intf = nw_interface_create_with_index(client_ifindex);
74         nw_parameters_require_interface(parameters, client_intf);
75         if (client_intf != NULL)
76             network_release(client_intf);
77         else
78             LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: client_intf returned by nw_interface_create_with_index() is NULL");
79     }
80     
81     nw_parameters_set_uid(parameters,(uid_t)q->euid);
82
83     if (q->pid != 0)
84     {
85         nw_parameters_set_pid(parameters, q->pid);
86         retval = proc_pidinfo(q->pid, PROC_PIDUNIQIDENTIFIERINFO, 1, &info, sizeof(info));
87         if (retval == (int)sizeof(info))
88         {
89             nw_parameters_set_e_proc_uuid(parameters, info.p_uuid);
90             isUUIDSet = mDNStrue;
91         }
92         else
93         {
94             debugf("mDNSPlatformGetDNSRoutePolicy: proc_pidinfo returned %d", retval);
95             isUUIDSet = mDNSfalse;
96         }
97     }
98     else
99     {
100         nw_parameters_set_e_proc_uuid(parameters, q->uuid);
101         isUUIDSet = mDNStrue;
102     }
103     
104     nw_path_evaluator_t evaluator = nw_path_create_evaluator_for_endpoint(host, parameters);
105     if (evaluator == NULL)
106         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, 
107                 DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
108     
109     if (host != NULL)
110         network_release(host);
111     if (parameters != NULL)
112         network_release(parameters);
113     
114     nw_path_t path = nw_path_evaluator_copy_path(evaluator);
115     if (path == NULL)
116         LogMsg("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_path_t path is NULL", q->qname.c,
117                DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
118     
119     service_id = nw_path_get_flow_divert_unit(path);
120     if (service_id != 0)
121     {
122         q->ServiceID = service_id;
123         LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: Query for %##s service ID is set ->service_ID:[%d] ", q->qname.c, service_id);
124     }
125     else
126     {
127         nw_interface_t nwpath_intf = nw_path_copy_scoped_interface(path);
128         if (nwpath_intf != NULL)
129         {
130             // Use the new scoped interface given by NW PATH EVALUATOR
131             dnspol_ifindex = nw_interface_get_index(nwpath_intf);
132             q->InterfaceID = (mDNSInterfaceID)(uintptr_t)dnspol_ifindex;
133             
134             network_release(nwpath_intf);
135             
136             if (dnspol_ifindex != client_ifindex)
137                 LogInfo("mDNSPlatformGetDNSRoutePolicy: DNS Route Policy has changed the scoped ifindex from [%d] to [%d]",
138                         client_ifindex, dnspol_ifindex);
139         }
140         else
141         {
142             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);
143         }
144     }
145     
146     if (isUUIDSet && (nw_path_get_status(path) == nw_path_status_unsatisfied) && (nw_path_get_reason(path) == nw_path_reason_policy_drop))
147         *isBlocked = mDNStrue;
148     else
149         *isBlocked = mDNSfalse;
150
151     if (path != NULL)
152         network_release(path);
153     if (evaluator != NULL)
154         network_release(evaluator);
155
156 }