1 /*
2  * Copyright (C) 2019 The Android Open Source Project
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  *      http://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 package android.net.ip;
18 
19 import android.content.Context;
20 import android.net.DhcpResultsParcelable;
21 import android.net.Layer2PacketParcelable;
22 import android.net.LinkProperties;
23 import android.net.networkstack.ModuleNetworkStackClient;
24 import android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable;
25 import android.os.ConditionVariable;
26 
27 import java.io.FileDescriptor;
28 import java.io.PrintWriter;
29 import java.util.List;
30 
31 
32 /**
33  * Utilities and wrappers to simplify communication with IpClient, which lives in the NetworkStack
34  * process.
35  *
36  * @hide
37  */
38 public class IpClientUtil {
39     // TODO: remove with its callers
40     public static final String DUMP_ARG = "ipclient";
41 
42     /**
43      * Subclass of {@link IpClientCallbacks} allowing clients to block until provisioning is
44      * complete with {@link WaitForProvisioningCallbacks#waitForProvisioning()}.
45      */
46     public static class WaitForProvisioningCallbacks extends IpClientCallbacks {
47         private final ConditionVariable mCV = new ConditionVariable();
48         private LinkProperties mCallbackLinkProperties;
49 
50         /**
51          * Block until either {@link #onProvisioningSuccess(LinkProperties)} or
52          * {@link #onProvisioningFailure(LinkProperties)} is called.
53          */
waitForProvisioning()54         public LinkProperties waitForProvisioning() {
55             mCV.block();
56             return mCallbackLinkProperties;
57         }
58 
59         @Override
onProvisioningSuccess(LinkProperties newLp)60         public void onProvisioningSuccess(LinkProperties newLp) {
61             mCallbackLinkProperties = newLp;
62             mCV.open();
63         }
64 
65         @Override
onProvisioningFailure(LinkProperties newLp)66         public void onProvisioningFailure(LinkProperties newLp) {
67             mCallbackLinkProperties = null;
68             mCV.open();
69         }
70     }
71 
72     /**
73      * Create a new IpClient.
74      *
75      * <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of
76      * {@link IIpClientCallbacks}.
77      * @see {@link ModuleNetworkStackClient#makeIpClient(String, IIpClientCallbacks)}
78      */
makeIpClient(Context context, String ifName, IpClientCallbacks callback)79     public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) {
80         ModuleNetworkStackClient.getInstance(context)
81                 .makeIpClient(ifName, new IpClientCallbacksProxy(callback));
82     }
83 
84     /**
85      * Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}.
86      */
87     private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
88         protected final IpClientCallbacks mCb;
89 
90         /**
91          * Create a new IpClientCallbacksProxy.
92          */
IpClientCallbacksProxy(IpClientCallbacks cb)93         IpClientCallbacksProxy(IpClientCallbacks cb) {
94             mCb = cb;
95         }
96 
97         @Override
onIpClientCreated(IIpClient ipClient)98         public void onIpClientCreated(IIpClient ipClient) {
99             mCb.onIpClientCreated(ipClient);
100         }
101 
102         @Override
onPreDhcpAction()103         public void onPreDhcpAction() {
104             mCb.onPreDhcpAction();
105         }
106 
107         @Override
onPostDhcpAction()108         public void onPostDhcpAction() {
109             mCb.onPostDhcpAction();
110         }
111 
112         // This is purely advisory and not an indication of provisioning
113         // success or failure.  This is only here for callers that want to
114         // expose DHCPv4 results to other APIs (e.g., WifiInfo#setInetAddress).
115         // DHCPv4 or static IPv4 configuration failure or success can be
116         // determined by whether or not the passed-in DhcpResults object is
117         // null or not.
118         @Override
onNewDhcpResults(DhcpResultsParcelable dhcpResults)119         public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
120             mCb.onNewDhcpResults(dhcpResults);
121         }
122 
123         // LinkProperties always have parcelSensitiveFields=false after parceling
124         // and unparceling, so the IIpClientCallback caller's side will always receive
125         // LinkProperties that do not have the flag set, except on Go devices where
126         // IpClient is running in the system_server, it's possible that no parceling
127         // happens and the object is sent as true, which results in wifi throws the
128         // UnsupportedOperationException when calling LinkProperties.clear() and then
129         // reboot. To keep the consistent behavior, deliver LinkProperties with
130         // mParcelSensitiveFields=false to wifi upon callback is triggered.
131         @Override
onProvisioningSuccess(LinkProperties newLp)132         public void onProvisioningSuccess(LinkProperties newLp) {
133             mCb.onProvisioningSuccess(new LinkProperties(newLp));
134         }
135         @Override
onProvisioningFailure(LinkProperties newLp)136         public void onProvisioningFailure(LinkProperties newLp) {
137             mCb.onProvisioningFailure(new LinkProperties(newLp));
138         }
139 
140         // Invoked on LinkProperties changes.
141         @Override
onLinkPropertiesChange(LinkProperties newLp)142         public void onLinkPropertiesChange(LinkProperties newLp) {
143             mCb.onLinkPropertiesChange(new LinkProperties(newLp));
144         }
145 
146         // Called when the internal IpReachabilityMonitor (if enabled) has
147         // detected the loss of a critical number of required neighbors.
148         @Override
onReachabilityLost(String logMsg)149         public void onReachabilityLost(String logMsg) {
150             mCb.onReachabilityLost(logMsg);
151         }
152 
153         // Called when the IpClient state machine terminates.
154         @Override
onQuit()155         public void onQuit() {
156             mCb.onQuit();
157         }
158 
159         // Install an APF program to filter incoming packets.
160         @Override
installPacketFilter(byte[] filter)161         public void installPacketFilter(byte[] filter) {
162             mCb.installPacketFilter(filter);
163         }
164 
165         // Asynchronously read back the APF program & data buffer from the wifi driver.
166         // Due to Wifi HAL limitations, the current implementation only supports dumping the entire
167         // buffer. In response to this request, the driver returns the data buffer asynchronously
168         // by sending an IpClient#EVENT_READ_PACKET_FILTER_COMPLETE message.
169         @Override
startReadPacketFilter()170         public void startReadPacketFilter() {
171             mCb.startReadPacketFilter();
172         }
173 
174         // If multicast filtering cannot be accomplished with APF, this function will be called to
175         // actuate multicast filtering using another means.
176         @Override
setFallbackMulticastFilter(boolean enabled)177         public void setFallbackMulticastFilter(boolean enabled) {
178             mCb.setFallbackMulticastFilter(enabled);
179         }
180 
181         // Enabled/disable Neighbor Discover offload functionality. This is
182         // called, for example, whenever 464xlat is being started or stopped.
183         @Override
setNeighborDiscoveryOffload(boolean enable)184         public void setNeighborDiscoveryOffload(boolean enable) {
185             mCb.setNeighborDiscoveryOffload(enable);
186         }
187 
188         // Invoked on starting preconnection process.
189         @Override
onPreconnectionStart(List<Layer2PacketParcelable> packets)190         public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
191             mCb.onPreconnectionStart(packets);
192         }
193 
194         // Called when the internal IpReachabilityMonitor (if enabled) has detected the loss of a
195         // critical number of required neighbors or DHCP roaming fails.
196         @Override
onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo)197         public void onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo) {
198             mCb.onReachabilityFailure(lossInfo);
199         }
200 
201         // Set maximum acceptable DTIM multiplier to hardware driver.
202         @Override
setMaxDtimMultiplier(int multiplier)203         public void setMaxDtimMultiplier(int multiplier) {
204             mCb.setMaxDtimMultiplier(multiplier);
205         }
206 
207         @Override
getInterfaceVersion()208         public int getInterfaceVersion() {
209             return this.VERSION;
210         }
211 
212         @Override
getInterfaceHash()213         public String getInterfaceHash() {
214             return this.HASH;
215         }
216     }
217 
218     /**
219      * Dump logs for the specified IpClient.
220      * TODO: remove callers and delete
221      */
dumpIpClient( IIpClient connector, FileDescriptor fd, PrintWriter pw, String[] args)222     public static void dumpIpClient(
223             IIpClient connector, FileDescriptor fd, PrintWriter pw, String[] args) {
224         pw.println("IpClient logs have moved to dumpsys network_stack");
225     }
226 }
227