summaryrefslogtreecommitdiff
path: root/common/device
diff options
context:
space:
mode:
Diffstat (limited to 'common/device')
-rw-r--r--common/device/android/net/NetworkFactory.java215
-rw-r--r--common/device/android/net/NetworkFactoryImpl.java322
-rw-r--r--common/device/android/net/NetworkFactoryLegacyImpl.java397
-rw-r--r--common/device/android/net/NetworkFactoryShim.java71
-rw-r--r--common/device/com/android/net/module/util/BpfBitmap.java126
-rw-r--r--common/device/com/android/net/module/util/BpfDump.java136
-rw-r--r--common/device/com/android/net/module/util/BpfMap.java312
-rw-r--r--common/device/com/android/net/module/util/BpfUtils.java69
-rw-r--r--common/device/com/android/net/module/util/DeviceConfigUtils.java422
-rw-r--r--common/device/com/android/net/module/util/DomainUtils.java143
-rw-r--r--common/device/com/android/net/module/util/FdEventsReader.java294
-rw-r--r--common/device/com/android/net/module/util/FeatureVersions.java45
-rw-r--r--common/device/com/android/net/module/util/IBpfMap.java82
-rw-r--r--common/device/com/android/net/module/util/Ipv6Utils.java187
-rw-r--r--common/device/com/android/net/module/util/JniUtil.java35
-rw-r--r--common/device/com/android/net/module/util/NetworkMonitorUtils.java117
-rw-r--r--common/device/com/android/net/module/util/PacketBuilder.java302
-rw-r--r--common/device/com/android/net/module/util/PacketReader.java59
-rw-r--r--common/device/com/android/net/module/util/SharedLog.java286
-rw-r--r--common/device/com/android/net/module/util/SocketUtils.java58
-rw-r--r--common/device/com/android/net/module/util/Struct.java774
-rw-r--r--common/device/com/android/net/module/util/TcUtils.java104
-rw-r--r--common/device/com/android/net/module/util/arp/ArpPacket.java171
-rw-r--r--common/device/com/android/net/module/util/async/Assertions.java41
-rw-r--r--common/device/com/android/net/module/util/async/AsyncFile.java78
-rw-r--r--common/device/com/android/net/module/util/async/BufferedFile.java292
-rw-r--r--common/device/com/android/net/module/util/async/CircularByteBuffer.java210
-rw-r--r--common/device/com/android/net/module/util/async/EventManager.java75
-rw-r--r--common/device/com/android/net/module/util/async/FileHandle.java74
-rw-r--r--common/device/com/android/net/module/util/async/OsAccess.java66
-rw-r--r--common/device/com/android/net/module/util/async/ReadableByteBuffer.java60
-rw-r--r--common/device/com/android/net/module/util/ip/ConntrackMonitor.java203
-rw-r--r--common/device/com/android/net/module/util/ip/InterfaceController.java211
-rw-r--r--common/device/com/android/net/module/util/ip/IpNeighborMonitor.java192
-rw-r--r--common/device/com/android/net/module/util/ip/NetlinkMonitor.java188
-rw-r--r--common/device/com/android/net/module/util/netlink/ConntrackMessage.java560
-rw-r--r--common/device/com/android/net/module/util/netlink/InetDiagMessage.java505
-rw-r--r--common/device/com/android/net/module/util/netlink/NdOption.java88
-rw-r--r--common/device/com/android/net/module/util/netlink/NduseroptMessage.java148
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkConstants.java283
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java69
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkMessage.java171
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkUtils.java311
-rw-r--r--common/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java263
-rw-r--r--common/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java151
-rw-r--r--common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java242
-rw-r--r--common/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java217
-rw-r--r--common/device/com/android/net/module/util/netlink/StructIfacacheInfo.java79
-rw-r--r--common/device/com/android/net/module/util/netlink/StructIfaddrMsg.java82
-rw-r--r--common/device/com/android/net/module/util/netlink/StructIfinfoMsg.java82
-rw-r--r--common/device/com/android/net/module/util/netlink/StructInetDiagMsg.java103
-rw-r--r--common/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java87
-rw-r--r--common/device/com/android/net/module/util/netlink/StructInetDiagSockId.java174
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdMsg.java198
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdOptPref64.java171
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java134
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdaCacheInfo.java123
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNfGenMsg.java105
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNlAttr.java394
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNlMsgErr.java77
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java174
-rw-r--r--common/device/com/android/net/module/util/netlink/StructRtMsg.java95
-rw-r--r--common/device/com/android/net/module/util/netlink/StructRtaCacheInfo.java92
-rw-r--r--common/device/com/android/net/module/util/structs/EthernetHeader.java60
-rw-r--r--common/device/com/android/net/module/util/structs/IaPdOption.java81
-rw-r--r--common/device/com/android/net/module/util/structs/IaPrefixOption.java92
-rw-r--r--common/device/com/android/net/module/util/structs/Icmpv4Header.java43
-rw-r--r--common/device/com/android/net/module/util/structs/Icmpv6Header.java45
-rw-r--r--common/device/com/android/net/module/util/structs/Ipv4Header.java94
-rw-r--r--common/device/com/android/net/module/util/structs/Ipv6Header.java75
-rw-r--r--common/device/com/android/net/module/util/structs/Ipv6PktInfo.java42
-rw-r--r--common/device/com/android/net/module/util/structs/LlaOption.java61
-rw-r--r--common/device/com/android/net/module/util/structs/MtuOption.java65
-rw-r--r--common/device/com/android/net/module/util/structs/NaHeader.java57
-rw-r--r--common/device/com/android/net/module/util/structs/NsHeader.java61
-rw-r--r--common/device/com/android/net/module/util/structs/PrefixInformationOption.java98
-rw-r--r--common/device/com/android/net/module/util/structs/RaHeader.java62
-rw-r--r--common/device/com/android/net/module/util/structs/RdnssOption.java92
-rw-r--r--common/device/com/android/net/module/util/structs/RouteInformationOption.java97
-rw-r--r--common/device/com/android/net/module/util/structs/RsHeader.java44
-rw-r--r--common/device/com/android/net/module/util/structs/TcpHeader.java79
-rw-r--r--common/device/com/android/net/module/util/structs/UdpHeader.java53
-rw-r--r--common/device/com/android/net/module/util/wear/NetPacketHelpers.java41
-rw-r--r--common/device/com/android/net/module/util/wear/PacketFile.java85
-rw-r--r--common/device/com/android/net/module/util/wear/StreamingPacketFile.java221
85 files changed, 0 insertions, 13243 deletions
diff --git a/common/device/android/net/NetworkFactory.java b/common/device/android/net/NetworkFactory.java
deleted file mode 100644
index 87f6dee6..00000000
--- a/common/device/android/net/NetworkFactory.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * A NetworkFactory is an entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using {@link #register} and
- * their factory will start receiving scored NetworkRequests. NetworkRequests
- * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
- * overridden function. All of these can be dynamic - changing NetworkCapabilities
- * or score forces re-evaluation of all current requests.
- *
- * If any requests pass the filter some overrideable functions will be called.
- * If the bearer only cares about very simple start/stopNetwork callbacks, those
- * functions can be overridden. If the bearer needs more interaction, it can
- * override addNetworkRequest and removeNetworkRequest which will give it each
- * request that passes their current filters.
- *
- * This class is mostly a shim which delegates to one of two implementations depending
- * on the SDK level of the device it's running on.
- *
- * @hide
- **/
-public class NetworkFactory {
- static final boolean DBG = true;
- static final boolean VDBG = false;
-
- final NetworkFactoryShim mImpl;
-
- private final String LOG_TAG;
-
- // Ideally the filter argument would be non-null, but null has historically meant to see
- // no requests and telephony passes null.
- public NetworkFactory(Looper looper, Context context, String logTag,
- @Nullable final NetworkCapabilities filter) {
- LOG_TAG = logTag;
- if (isAtLeastS()) {
- mImpl = new NetworkFactoryImpl(this, looper, context, filter);
- } else {
- mImpl = new NetworkFactoryLegacyImpl(this, looper, context, filter);
- }
- }
-
- // TODO : these two constants and the method are only used by telephony tests. Replace it in
- // the tests and remove them and the associated code.
- public static final int CMD_REQUEST_NETWORK = 1;
- public static final int CMD_CANCEL_REQUEST = 2;
- /** Like Handler#obtainMessage */
- @VisibleForTesting
- public Message obtainMessage(final int what, final int arg1, final int arg2,
- final @Nullable Object obj) {
- return mImpl.obtainMessage(what, arg1, arg2, obj);
- }
-
- // Called by BluetoothNetworkFactory
- public final Looper getLooper() {
- return mImpl.getLooper();
- }
-
- // Refcount for simple mode requests
- private int mRefCount = 0;
-
- /* Registers this NetworkFactory with the system. May only be called once per factory. */
- public void register() {
- mImpl.register(LOG_TAG);
- }
-
- /**
- * Registers this NetworkFactory with the system ignoring the score filter. This will let
- * the factory always see all network requests matching its capabilities filter.
- * May only be called once per factory.
- */
- public void registerIgnoringScore() {
- mImpl.registerIgnoringScore(LOG_TAG);
- }
-
- /** Unregisters this NetworkFactory. After this call, the object can no longer be used. */
- public void terminate() {
- mImpl.terminate();
- }
-
- protected final void reevaluateAllRequests() {
- mImpl.reevaluateAllRequests();
- }
-
- /**
- * Overridable function to provide complex filtering.
- * Called for every request every time a new NetworkRequest is seen
- * and whenever the filterScore or filterNetworkCapabilities change.
- *
- * acceptRequest can be overridden to provide complex filter behavior
- * for the incoming requests
- *
- * For output, this class will call {@link #needNetworkFor} and
- * {@link #releaseNetworkFor} for every request that passes the filters.
- * If you don't need to see every request, you can leave the base
- * implementations of those two functions and instead override
- * {@link #startNetwork} and {@link #stopNetwork}.
- *
- * If you want to see every score fluctuation on every request, set
- * your score filter to a very high number and watch {@link #needNetworkFor}.
- *
- * @return {@code true} to accept the request.
- */
- public boolean acceptRequest(@NonNull final NetworkRequest request) {
- return true;
- }
-
- /**
- * Can be called by a factory to release a request as unfulfillable: the request will be
- * removed, and the caller will get a
- * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
- * returns.
- *
- * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
- * is able to fulfill this request!
- */
- protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
- mImpl.releaseRequestAsUnfulfillableByAnyFactory(r);
- }
-
- // override to do simple mode (request independent)
- protected void startNetwork() { }
- protected void stopNetwork() { }
-
- // override to do fancier stuff
- protected void needNetworkFor(@NonNull final NetworkRequest networkRequest) {
- if (++mRefCount == 1) startNetwork();
- }
-
- protected void releaseNetworkFor(@NonNull final NetworkRequest networkRequest) {
- if (--mRefCount == 0) stopNetwork();
- }
-
- /**
- * @deprecated this method was never part of the API (system or public) and is only added
- * for migration of existing clients.
- */
- @Deprecated
- public void setScoreFilter(final int score) {
- mImpl.setScoreFilter(score);
- }
-
- /**
- * Set a score filter for this factory.
- *
- * This should include the transports the factory knows its networks will have, and
- * an optimistic view of the attributes it may have. This does not commit the factory
- * to being able to bring up such a network ; it only lets it avoid hearing about
- * requests that it has no chance of fulfilling.
- *
- * @param score the filter
- */
- public void setScoreFilter(@NonNull final NetworkScore score) {
- mImpl.setScoreFilter(score);
- }
-
- public void setCapabilityFilter(NetworkCapabilities netCap) {
- mImpl.setCapabilityFilter(netCap);
- }
-
- @VisibleForTesting
- protected int getRequestCount() {
- return mImpl.getRequestCount();
- }
-
- public int getSerialNumber() {
- return mImpl.getSerialNumber();
- }
-
- public NetworkProvider getProvider() {
- return mImpl.getProvider();
- }
-
- protected void log(String s) {
- Log.d(LOG_TAG, s);
- }
-
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mImpl.dump(fd, writer, args);
- }
-
- @Override
- public String toString() {
- return "{" + LOG_TAG + " " + mImpl.toString() + "}";
- }
-}
diff --git a/common/device/android/net/NetworkFactoryImpl.java b/common/device/android/net/NetworkFactoryImpl.java
deleted file mode 100644
index 9c1190c2..00000000
--- a/common/device/android/net/NetworkFactoryImpl.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.net.NetworkProvider.NetworkOfferCallback;
-import android.os.Looper;
-import android.os.Message;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * A NetworkFactory is an entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using {@link #register} and
- * their factory will start receiving scored NetworkRequests. NetworkRequests
- * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
- * overridden function. All of these can be dynamic - changing NetworkCapabilities
- * or score forces re-evaluation of all current requests.
- *
- * If any requests pass the filter some overrideable functions will be called.
- * If the bearer only cares about very simple start/stopNetwork callbacks, those
- * functions can be overridden. If the bearer needs more interaction, it can
- * override addNetworkRequest and removeNetworkRequest which will give it each
- * request that passes their current filters.
- * @hide
- **/
-// TODO(b/187083878): factor out common code between this and NetworkFactoryLegacyImpl
-class NetworkFactoryImpl extends NetworkFactoryLegacyImpl {
- private static final boolean DBG = NetworkFactory.DBG;
- private static final boolean VDBG = NetworkFactory.VDBG;
-
- // A score that will win against everything, so that score filtering will let all requests
- // through
- // TODO : remove this and replace with an API to listen to all requests.
- @NonNull
- private static final NetworkScore INVINCIBLE_SCORE =
- new NetworkScore.Builder().setLegacyInt(1000).build();
-
- // TODO(b/187082970): Replace CMD_* with Handler.post(() -> { ... }) since all the CMDs do is to
- // run the tasks asynchronously on the Handler thread.
-
- /**
- * Pass a network request to the bearer. If the bearer believes it can
- * satisfy the request it should connect to the network and create a
- * NetworkAgent. Once the NetworkAgent is fully functional it will
- * register itself with ConnectivityService using registerNetworkAgent.
- * If the bearer cannot immediately satisfy the request (no network,
- * user disabled the radio, lower-scored network) it should remember
- * any NetworkRequests it may be able to satisfy in the future. It may
- * disregard any that it will never be able to service, for example
- * those requiring a different bearer.
- * msg.obj = NetworkRequest
- */
- // TODO : this and CANCEL_REQUEST are only used by telephony tests. Replace it in the tests
- // and remove them and the associated code.
- private static final int CMD_REQUEST_NETWORK = NetworkFactory.CMD_REQUEST_NETWORK;
-
- /**
- * Cancel a network request
- * msg.obj = NetworkRequest
- */
- private static final int CMD_CANCEL_REQUEST = NetworkFactory.CMD_CANCEL_REQUEST;
-
- /**
- * Internally used to set our best-guess score.
- * msg.obj = new score
- */
- private static final int CMD_SET_SCORE = 3;
-
- /**
- * Internally used to set our current filter for coarse bandwidth changes with
- * technology changes.
- * msg.obj = new filter
- */
- private static final int CMD_SET_FILTER = 4;
-
- /**
- * Internally used to send the network offer associated with this factory.
- * No arguments, will read from members
- */
- private static final int CMD_OFFER_NETWORK = 5;
-
- /**
- * Internally used to send the request to listen to all requests.
- * No arguments, will read from members
- */
- private static final int CMD_LISTEN_TO_ALL_REQUESTS = 6;
-
- private final Map<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
- new LinkedHashMap<>();
-
- @NonNull private NetworkScore mScore = new NetworkScore.Builder().setLegacyInt(0).build();
-
- private final NetworkOfferCallback mRequestCallback = new NetworkOfferCallback() {
- @Override
- public void onNetworkNeeded(@NonNull final NetworkRequest request) {
- handleAddRequest(request);
- }
-
- @Override
- public void onNetworkUnneeded(@NonNull final NetworkRequest request) {
- handleRemoveRequest(request);
- }
- };
- @NonNull private final Executor mExecutor = command -> post(command);
-
-
- // Ideally the filter argument would be non-null, but null has historically meant to see
- // no requests and telephony passes null.
- NetworkFactoryImpl(NetworkFactory parent, Looper looper, Context context,
- @Nullable final NetworkCapabilities filter) {
- super(parent, looper, context,
- null != filter ? filter :
- NetworkCapabilities.Builder.withoutDefaultCapabilities().build());
- }
-
- /* Registers this NetworkFactory with the system. May only be called once per factory. */
- @Override public void register(final String logTag) {
- register(logTag, false);
- }
-
- /**
- * Registers this NetworkFactory with the system ignoring the score filter. This will let
- * the factory always see all network requests matching its capabilities filter.
- * May only be called once per factory.
- */
- @Override public void registerIgnoringScore(final String logTag) {
- register(logTag, true);
- }
-
- private void register(final String logTag, final boolean listenToAllRequests) {
- if (mProvider != null) {
- throw new IllegalStateException("A NetworkFactory must only be registered once");
- }
- if (DBG) mParent.log("Registering NetworkFactory");
-
- mProvider = new NetworkProvider(mContext, NetworkFactoryImpl.this.getLooper(), logTag) {
- @Override
- public void onNetworkRequested(@NonNull NetworkRequest request, int score,
- int servingProviderId) {
- handleAddRequest(request);
- }
-
- @Override
- public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
- handleRemoveRequest(request);
- }
- };
-
- ((ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);
-
- // The mScore and mCapabilityFilter members can only be accessed on the handler thread.
- // TODO : offer a separate API to listen to all requests instead
- if (listenToAllRequests) {
- sendMessage(obtainMessage(CMD_LISTEN_TO_ALL_REQUESTS));
- } else {
- sendMessage(obtainMessage(CMD_OFFER_NETWORK));
- }
- }
-
- private void handleOfferNetwork(@NonNull final NetworkScore score) {
- mProvider.registerNetworkOffer(score, mCapabilityFilter, mExecutor, mRequestCallback);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case CMD_REQUEST_NETWORK: {
- handleAddRequest((NetworkRequest) msg.obj);
- break;
- }
- case CMD_CANCEL_REQUEST: {
- handleRemoveRequest((NetworkRequest) msg.obj);
- break;
- }
- case CMD_SET_SCORE: {
- handleSetScore((NetworkScore) msg.obj);
- break;
- }
- case CMD_SET_FILTER: {
- handleSetFilter((NetworkCapabilities) msg.obj);
- break;
- }
- case CMD_OFFER_NETWORK: {
- handleOfferNetwork(mScore);
- break;
- }
- case CMD_LISTEN_TO_ALL_REQUESTS: {
- handleOfferNetwork(INVINCIBLE_SCORE);
- break;
- }
- }
- }
-
- private static class NetworkRequestInfo {
- @NonNull public final NetworkRequest request;
- public boolean requested; // do we have a request outstanding, limited by score
-
- NetworkRequestInfo(@NonNull final NetworkRequest request) {
- this.request = request;
- this.requested = false;
- }
-
- @Override
- public String toString() {
- return "{" + request + ", requested=" + requested + "}";
- }
- }
-
- /**
- * Add a NetworkRequest that the bearer may want to attempt to satisfy.
- * @see #CMD_REQUEST_NETWORK
- *
- * @param request the request to handle.
- */
- private void handleAddRequest(@NonNull final NetworkRequest request) {
- NetworkRequestInfo n = mNetworkRequests.get(request);
- if (n == null) {
- if (DBG) mParent.log("got request " + request);
- n = new NetworkRequestInfo(request);
- mNetworkRequests.put(n.request, n);
- } else {
- if (VDBG) mParent.log("handle existing request " + request);
- }
- if (VDBG) mParent.log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
-
- if (mParent.acceptRequest(request)) {
- n.requested = true;
- mParent.needNetworkFor(request);
- }
- }
-
- private void handleRemoveRequest(NetworkRequest request) {
- NetworkRequestInfo n = mNetworkRequests.get(request);
- if (n != null) {
- mNetworkRequests.remove(request);
- if (n.requested) mParent.releaseNetworkFor(n.request);
- }
- }
-
- private void handleSetScore(@NonNull final NetworkScore score) {
- if (mScore.equals(score)) return;
- mScore = score;
- mParent.reevaluateAllRequests();
- }
-
- private void handleSetFilter(@NonNull final NetworkCapabilities netCap) {
- if (netCap.equals(mCapabilityFilter)) return;
- mCapabilityFilter = netCap;
- mParent.reevaluateAllRequests();
- }
-
- @Override public final void reevaluateAllRequests() {
- if (mProvider == null) return;
- mProvider.registerNetworkOffer(mScore, mCapabilityFilter, mExecutor, mRequestCallback);
- }
-
- /**
- * @deprecated this method was never part of the API (system or public) and is only added
- * for migration of existing clients.
- */
- @Deprecated
- public void setScoreFilter(final int score) {
- setScoreFilter(new NetworkScore.Builder().setLegacyInt(score).build());
- }
-
- /**
- * Set a score filter for this factory.
- *
- * This should include the transports the factory knows its networks will have, and
- * an optimistic view of the attributes it may have. This does not commit the factory
- * to being able to bring up such a network ; it only lets it avoid hearing about
- * requests that it has no chance of fulfilling.
- *
- * @param score the filter
- */
- @Override public void setScoreFilter(@NonNull final NetworkScore score) {
- sendMessage(obtainMessage(CMD_SET_SCORE, score));
- }
-
- @Override public void setCapabilityFilter(NetworkCapabilities netCap) {
- sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
- }
-
- @Override public int getRequestCount() {
- return mNetworkRequests.size();
- }
-
- @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println(toString());
- for (NetworkRequestInfo n : mNetworkRequests.values()) {
- writer.println(" " + n);
- }
- }
-
- @Override public String toString() {
- return "providerId=" + (mProvider != null ? mProvider.getProviderId() : "null")
- + ", ScoreFilter=" + mScore + ", Filter=" + mCapabilityFilter
- + ", requests=" + mNetworkRequests.size();
- }
-}
diff --git a/common/device/android/net/NetworkFactoryLegacyImpl.java b/common/device/android/net/NetworkFactoryLegacyImpl.java
deleted file mode 100644
index 6cba6258..00000000
--- a/common/device/android/net/NetworkFactoryLegacyImpl.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * A NetworkFactory is an entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using {@link #register} and
- * their factory will start receiving scored NetworkRequests. NetworkRequests
- * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
- * overridden function. All of these can be dynamic - changing NetworkCapabilities
- * or score forces re-evaluation of all current requests.
- *
- * If any requests pass the filter some overrideable functions will be called.
- * If the bearer only cares about very simple start/stopNetwork callbacks, those
- * functions can be overridden. If the bearer needs more interaction, it can
- * override addNetworkRequest and removeNetworkRequest which will give it each
- * request that passes their current filters.
- * @hide
- **/
-// TODO(b/187083878): factor out common code between this and NetworkFactoryImpl
-class NetworkFactoryLegacyImpl extends Handler
- implements NetworkFactoryShim {
- private static final boolean DBG = NetworkFactory.DBG;
- private static final boolean VDBG = NetworkFactory.VDBG;
-
- // TODO(b/187082970): Replace CMD_* with Handler.post(() -> { ... }) since all the CMDs do is to
- // run the tasks asynchronously on the Handler thread.
-
- /**
- * Pass a network request to the bearer. If the bearer believes it can
- * satisfy the request it should connect to the network and create a
- * NetworkAgent. Once the NetworkAgent is fully functional it will
- * register itself with ConnectivityService using registerNetworkAgent.
- * If the bearer cannot immediately satisfy the request (no network,
- * user disabled the radio, lower-scored network) it should remember
- * any NetworkRequests it may be able to satisfy in the future. It may
- * disregard any that it will never be able to service, for example
- * those requiring a different bearer.
- * msg.obj = NetworkRequest
- * msg.arg1 = score - the score of the network currently satisfying this
- * request. If this bearer knows in advance it cannot
- * exceed this score it should not try to connect, holding the request
- * for the future.
- * Note that subsequent events may give a different (lower
- * or higher) score for this request, transmitted to each
- * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
- * with the same NetworkRequest but an updated score.
- * Also, network conditions may change for this bearer
- * allowing for a better score in the future.
- * msg.arg2 = the ID of the NetworkProvider currently responsible for the
- * NetworkAgent handling this request, or NetworkProvider.ID_NONE if none.
- */
- public static final int CMD_REQUEST_NETWORK = 1;
-
- /**
- * Cancel a network request
- * msg.obj = NetworkRequest
- */
- public static final int CMD_CANCEL_REQUEST = 2;
-
- /**
- * Internally used to set our best-guess score.
- * msg.arg1 = new score
- */
- private static final int CMD_SET_SCORE = 3;
-
- /**
- * Internally used to set our current filter for coarse bandwidth changes with
- * technology changes.
- * msg.obj = new filter
- */
- private static final int CMD_SET_FILTER = 4;
-
- final Context mContext;
- final NetworkFactory mParent;
-
- private final Map<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
- new LinkedHashMap<>();
-
- private int mScore;
- NetworkCapabilities mCapabilityFilter;
-
- NetworkProvider mProvider = null;
-
- NetworkFactoryLegacyImpl(NetworkFactory parent, Looper looper, Context context,
- NetworkCapabilities filter) {
- super(looper);
- mParent = parent;
- mContext = context;
- mCapabilityFilter = filter;
- }
-
- /* Registers this NetworkFactory with the system. May only be called once per factory. */
- @Override public void register(final String logTag) {
- if (mProvider != null) {
- throw new IllegalStateException("A NetworkFactory must only be registered once");
- }
- if (DBG) mParent.log("Registering NetworkFactory");
-
- mProvider = new NetworkProvider(mContext, NetworkFactoryLegacyImpl.this.getLooper(),
- logTag) {
- @Override
- public void onNetworkRequested(@NonNull NetworkRequest request, int score,
- int servingProviderId) {
- handleAddRequest(request, score, servingProviderId);
- }
-
- @Override
- public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
- handleRemoveRequest(request);
- }
- };
-
- ((ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);
- }
-
- /** Unregisters this NetworkFactory. After this call, the object can no longer be used. */
- @Override public void terminate() {
- if (mProvider == null) {
- throw new IllegalStateException("This NetworkFactory was never registered");
- }
- if (DBG) mParent.log("Unregistering NetworkFactory");
-
- ((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
- .unregisterNetworkProvider(mProvider);
-
- // Remove all pending messages, since this object cannot be reused. Any message currently
- // being processed will continue to run.
- removeCallbacksAndMessages(null);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case CMD_REQUEST_NETWORK: {
- handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case CMD_CANCEL_REQUEST: {
- handleRemoveRequest((NetworkRequest) msg.obj);
- break;
- }
- case CMD_SET_SCORE: {
- handleSetScore(msg.arg1);
- break;
- }
- case CMD_SET_FILTER: {
- handleSetFilter((NetworkCapabilities) msg.obj);
- break;
- }
- }
- }
-
- private static class NetworkRequestInfo {
- public final NetworkRequest request;
- public int score;
- public boolean requested; // do we have a request outstanding, limited by score
- public int providerId;
-
- NetworkRequestInfo(NetworkRequest request, int score, int providerId) {
- this.request = request;
- this.score = score;
- this.requested = false;
- this.providerId = providerId;
- }
-
- @Override
- public String toString() {
- return "{" + request + ", score=" + score + ", requested=" + requested + "}";
- }
- }
-
- /**
- * Add a NetworkRequest that the bearer may want to attempt to satisfy.
- * @see #CMD_REQUEST_NETWORK
- *
- * @param request the request to handle.
- * @param score the score of the NetworkAgent currently satisfying this request.
- * @param servingProviderId the ID of the NetworkProvider that created the NetworkAgent
- * currently satisfying this request.
- */
- @VisibleForTesting
- protected void handleAddRequest(NetworkRequest request, int score, int servingProviderId) {
- NetworkRequestInfo n = mNetworkRequests.get(request);
- if (n == null) {
- if (DBG) {
- mParent.log("got request " + request + " with score " + score
- + " and providerId " + servingProviderId);
- }
- n = new NetworkRequestInfo(request, score, servingProviderId);
- mNetworkRequests.put(n.request, n);
- } else {
- if (VDBG) {
- mParent.log("new score " + score + " for existing request " + request
- + " and providerId " + servingProviderId);
- }
- n.score = score;
- n.providerId = servingProviderId;
- }
- if (VDBG) mParent.log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
-
- evalRequest(n);
- }
-
- private void handleRemoveRequest(NetworkRequest request) {
- NetworkRequestInfo n = mNetworkRequests.get(request);
- if (n != null) {
- mNetworkRequests.remove(request);
- if (n.requested) mParent.releaseNetworkFor(n.request);
- }
- }
-
- private void handleSetScore(int score) {
- mScore = score;
- evalRequests();
- }
-
- private void handleSetFilter(NetworkCapabilities netCap) {
- mCapabilityFilter = netCap;
- evalRequests();
- }
-
- /**
- * Overridable function to provide complex filtering.
- * Called for every request every time a new NetworkRequest is seen
- * and whenever the filterScore or filterNetworkCapabilities change.
- *
- * acceptRequest can be overridden to provide complex filter behavior
- * for the incoming requests
- *
- * For output, this class will call {@link NetworkFactory#needNetworkFor} and
- * {@link NetworkFactory#releaseNetworkFor} for every request that passes the filters.
- * If you don't need to see every request, you can leave the base
- * implementations of those two functions and instead override
- * {@link NetworkFactory#startNetwork} and {@link NetworkFactory#stopNetwork}.
- *
- * If you want to see every score fluctuation on every request, set
- * your score filter to a very high number and watch {@link NetworkFactory#needNetworkFor}.
- *
- * @return {@code true} to accept the request.
- */
- public boolean acceptRequest(NetworkRequest request) {
- return mParent.acceptRequest(request);
- }
-
- private void evalRequest(NetworkRequestInfo n) {
- if (VDBG) {
- mParent.log("evalRequest");
- mParent.log(" n.requests = " + n.requested);
- mParent.log(" n.score = " + n.score);
- mParent.log(" mScore = " + mScore);
- mParent.log(" request.providerId = " + n.providerId);
- mParent.log(" mProvider.id = " + mProvider.getProviderId());
- }
- if (shouldNeedNetworkFor(n)) {
- if (VDBG) mParent.log(" needNetworkFor");
- mParent.needNetworkFor(n.request);
- n.requested = true;
- } else if (shouldReleaseNetworkFor(n)) {
- if (VDBG) mParent.log(" releaseNetworkFor");
- mParent.releaseNetworkFor(n.request);
- n.requested = false;
- } else {
- if (VDBG) mParent.log(" done");
- }
- }
-
- private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
- // If this request is already tracked, it doesn't qualify for need
- return !n.requested
- // If the score of this request is higher or equal to that of this factory and some
- // other factory is responsible for it, then this factory should not track the request
- // because it has no hope of satisfying it.
- && (n.score < mScore || n.providerId == mProvider.getProviderId())
- // If this factory can't satisfy the capability needs of this request, then it
- // should not be tracked.
- && n.request.canBeSatisfiedBy(mCapabilityFilter)
- // Finally if the concrete implementation of the factory rejects the request, then
- // don't track it.
- && acceptRequest(n.request);
- }
-
- private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
- // Don't release a request that's not tracked.
- return n.requested
- // The request should be released if it can't be satisfied by this factory. That
- // means either of the following conditions are met :
- // - Its score is too high to be satisfied by this factory and it's not already
- // assigned to the factory
- // - This factory can't satisfy the capability needs of the request
- // - The concrete implementation of the factory rejects the request
- && ((n.score > mScore && n.providerId != mProvider.getProviderId())
- || !n.request.canBeSatisfiedBy(mCapabilityFilter)
- || !acceptRequest(n.request));
- }
-
- private void evalRequests() {
- for (NetworkRequestInfo n : mNetworkRequests.values()) {
- evalRequest(n);
- }
- }
-
- /**
- * Post a command, on this NetworkFactory Handler, to re-evaluate all
- * outstanding requests. Can be called from a factory implementation.
- */
- @Override public void reevaluateAllRequests() {
- post(this::evalRequests);
- }
-
- /**
- * Can be called by a factory to release a request as unfulfillable: the request will be
- * removed, and the caller will get a
- * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
- * returns.
- *
- * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
- * is able to fulfill this request!
- */
- @Override public void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
- post(() -> {
- if (DBG) mParent.log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
- final NetworkProvider provider = mProvider;
- if (provider == null) {
- mParent.log("Ignoring attempt to release unregistered request as unfulfillable");
- return;
- }
- provider.declareNetworkRequestUnfulfillable(r);
- });
- }
-
- @Override public void setScoreFilter(int score) {
- sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
- }
-
- @Override public void setScoreFilter(@NonNull final NetworkScore score) {
- setScoreFilter(score.getLegacyInt());
- }
-
- @Override public void setCapabilityFilter(NetworkCapabilities netCap) {
- sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
- }
-
- @Override public int getRequestCount() {
- return mNetworkRequests.size();
- }
-
- /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
- @Override public int getSerialNumber() {
- return mProvider.getProviderId();
- }
-
- @Override public NetworkProvider getProvider() {
- return mProvider;
- }
-
- @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println(toString());
- for (NetworkRequestInfo n : mNetworkRequests.values()) {
- writer.println(" " + n);
- }
- }
-
- @Override public String toString() {
- return "providerId=" + (mProvider != null ? mProvider.getProviderId() : "null")
- + ", ScoreFilter=" + mScore + ", Filter=" + mCapabilityFilter
- + ", requests=" + mNetworkRequests.size();
- }
-}
diff --git a/common/device/android/net/NetworkFactoryShim.java b/common/device/android/net/NetworkFactoryShim.java
deleted file mode 100644
index dfbb5ec1..00000000
--- a/common/device/android/net/NetworkFactoryShim.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Looper;
-import android.os.Message;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Extract an interface for multiple implementation of {@link NetworkFactory}, depending on the SDK
- * version.
- *
- * Known implementations:
- * - {@link NetworkFactoryImpl}: For Android S+
- * - {@link NetworkFactoryLegacyImpl}: For Android R-
- *
- * @hide
- */
-interface NetworkFactoryShim {
- void register(String logTag);
-
- default void registerIgnoringScore(String logTag) {
- throw new UnsupportedOperationException();
- }
-
- void terminate();
-
- void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r);
-
- void reevaluateAllRequests();
-
- void setScoreFilter(int score);
-
- void setScoreFilter(@NonNull NetworkScore score);
-
- void setCapabilityFilter(NetworkCapabilities netCap);
-
- int getRequestCount();
-
- int getSerialNumber();
-
- NetworkProvider getProvider();
-
- void dump(FileDescriptor fd, PrintWriter writer, String[] args);
-
- // All impls inherit Handler
- @VisibleForTesting
- Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj);
-
- Looper getLooper();
-}
diff --git a/common/device/com/android/net/module/util/BpfBitmap.java b/common/device/com/android/net/module/util/BpfBitmap.java
deleted file mode 100644
index d2a5b654..00000000
--- a/common/device/com/android/net/module/util/BpfBitmap.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import android.system.ErrnoException;
-
-import androidx.annotation.NonNull;
-
- /**
- *
- * Generic bitmap class for use with BPF programs. Corresponds to a BpfMap
- * array type with key->int and value->uint64_t defined in the bpf program.
- *
- */
-public class BpfBitmap {
- private BpfMap<Struct.S32, Struct.S64> mBpfMap;
-
- /**
- * Create a BpfBitmap map wrapper with "path" of filesystem.
- *
- * @param path The path of the BPF map.
- */
- public BpfBitmap(@NonNull String path) throws ErrnoException {
- mBpfMap = new BpfMap<Struct.S32, Struct.S64>(path, BpfMap.BPF_F_RDWR,
- Struct.S32.class, Struct.S64.class);
- }
-
- /**
- * Retrieves the value from BpfMap for the given key.
- *
- * @param key The key in the map corresponding to the value to return.
- */
- private long getBpfMapValue(Struct.S32 key) throws ErrnoException {
- Struct.S64 curVal = mBpfMap.getValue(key);
- if (curVal != null) {
- return curVal.val;
- } else {
- return 0;
- }
- }
-
- /**
- * Retrieves the bit for the given index in the bitmap.
- *
- * @param index Position in bitmap.
- */
- public boolean get(int index) throws ErrnoException {
- if (index < 0) return false;
-
- Struct.S32 key = new Struct.S32(index >> 6);
- return ((getBpfMapValue(key) >>> (index & 63)) & 1L) != 0;
- }
-
- /**
- * Set the specified index in the bitmap.
- *
- * @param index Position to set in bitmap.
- */
- public void set(int index) throws ErrnoException {
- set(index, true);
- }
-
- /**
- * Unset the specified index in the bitmap.
- *
- * @param index Position to unset in bitmap.
- */
- public void unset(int index) throws ErrnoException {
- set(index, false);
- }
-
- /**
- * Change the specified index in the bitmap to set value.
- *
- * @param index Position to unset in bitmap.
- * @param set Boolean indicating to set or unset index.
- */
- public void set(int index, boolean set) throws ErrnoException {
- if (index < 0) throw new IllegalArgumentException("Index out of bounds.");
-
- Struct.S32 key = new Struct.S32(index >> 6);
- long mask = (1L << (index & 63));
- long val = getBpfMapValue(key);
- if (set) val |= mask; else val &= ~mask;
- mBpfMap.updateEntry(key, new Struct.S64(val));
- }
-
- /**
- * Clears the map. The map may already be empty.
- *
- * @throws ErrnoException if updating entry to 0 fails.
- */
- public void clear() throws ErrnoException {
- mBpfMap.forEach((key, value) -> {
- mBpfMap.updateEntry(key, new Struct.S64(0));
- });
- }
-
- /**
- * Checks if all bitmap values are 0.
- */
- public boolean isEmpty() throws ErrnoException {
- Struct.S32 key = mBpfMap.getFirstKey();
- while (key != null) {
- if (getBpfMapValue(key) != 0) {
- return false;
- }
- key = mBpfMap.getNextKey(key);
- }
- return true;
- }
-}
diff --git a/common/device/com/android/net/module/util/BpfDump.java b/common/device/com/android/net/module/util/BpfDump.java
deleted file mode 100644
index 7549e712..00000000
--- a/common/device/com/android/net/module/util/BpfDump.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.net.module.util;
-
-import static android.system.OsConstants.R_OK;
-
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Base64;
-import android.util.Pair;
-
-import androidx.annotation.NonNull;
-
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.function.BiFunction;
-
-/**
- * The classes and the methods for BPF dump utilization.
- */
-public class BpfDump {
- // Using "," as a separator between base64 encoded key and value is safe because base64
- // characters are [0-9a-zA-Z/=+].
- private static final String BASE64_DELIMITER = ",";
-
- /**
- * Encode BPF key and value into a base64 format string which uses the delimiter ',':
- * <base64 encoded key>,<base64 encoded value>
- */
- public static <K extends Struct, V extends Struct> String toBase64EncodedString(
- @NonNull final K key, @NonNull final V value) {
- final byte[] keyBytes = key.writeToBytes();
- final String keyBase64Str = Base64.encodeToString(keyBytes, Base64.DEFAULT)
- .replace("\n", "");
- final byte[] valueBytes = value.writeToBytes();
- final String valueBase64Str = Base64.encodeToString(valueBytes, Base64.DEFAULT)
- .replace("\n", "");
-
- return keyBase64Str + BASE64_DELIMITER + valueBase64Str;
- }
-
- /**
- * Decode Struct from a base64 format string
- */
- private static <T extends Struct> T parseStruct(
- Class<T> structClass, @NonNull String base64Str) {
- final byte[] bytes = Base64.decode(base64Str, Base64.DEFAULT);
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
- return Struct.parse(structClass, byteBuffer);
- }
-
- /**
- * Decode BPF key and value from a base64 format string which uses the delimiter ',':
- * <base64 encoded key>,<base64 encoded value>
- */
- public static <K extends Struct, V extends Struct> Pair<K, V> fromBase64EncodedString(
- Class<K> keyClass, Class<V> valueClass, @NonNull String base64Str) {
- String[] keyValueStrs = base64Str.split(BASE64_DELIMITER);
- if (keyValueStrs.length != 2 /* key + value */) {
- throw new IllegalArgumentException("Invalid base64Str (" + base64Str + "), base64Str"
- + " must contain exactly one delimiter '" + BASE64_DELIMITER + "'");
- }
- final K k = parseStruct(keyClass, keyValueStrs[0]);
- final V v = parseStruct(valueClass, keyValueStrs[1]);
- return new Pair<>(k, v);
- }
-
- /**
- * Dump the BpfMap name and entries
- */
- public static <K extends Struct, V extends Struct> void dumpMap(IBpfMap<K, V> map,
- PrintWriter pw, String mapName, BiFunction<K, V, String> entryToString) {
- dumpMap(map, pw, mapName, "" /* header */, entryToString);
- }
-
- /**
- * Dump the BpfMap name, header, and entries
- */
- public static <K extends Struct, V extends Struct> void dumpMap(IBpfMap<K, V> map,
- PrintWriter pw, String mapName, String header, BiFunction<K, V, String> entryToString) {
- pw.println(mapName + ":");
- if (!header.isEmpty()) {
- pw.println(" " + header);
- }
- try {
- map.forEach((key, value) -> {
- // Value could be null if there is a concurrent entry deletion.
- // http://b/220084230.
- if (value != null) {
- pw.println(" " + entryToString.apply(key, value));
- } else {
- pw.println("Entry is deleted while dumping, iterating from first entry");
- }
- });
- } catch (ErrnoException e) {
- pw.println("Map dump end with error: " + Os.strerror(e.errno));
- }
- }
-
- /**
- * Dump the BpfMap status
- */
- public static <K extends Struct, V extends Struct> void dumpMapStatus(IBpfMap<K, V> map,
- PrintWriter pw, String mapName, String path) {
- if (map != null) {
- pw.println(mapName + ": OK");
- return;
- }
- try {
- Os.access(path, R_OK);
- pw.println(mapName + ": NULL(map is pinned to " + path + ")");
- } catch (ErrnoException e) {
- pw.println(mapName + ": NULL(map is not pinned to " + path + ": "
- + Os.strerror(e.errno) + ")");
- }
- }
-
- // TODO: add a helper to dump bpf map content with the map name, the header line
- // (ex: "BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif"), a lambda that
- // knows how to dump each line, and the PrintWriter.
-}
diff --git a/common/device/com/android/net/module/util/BpfMap.java b/common/device/com/android/net/module/util/BpfMap.java
deleted file mode 100644
index d45caceb..00000000
--- a/common/device/com/android/net/module/util/BpfMap.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.net.module.util;
-
-import static android.system.OsConstants.EEXIST;
-import static android.system.OsConstants.ENOENT;
-
-import android.os.ParcelFileDescriptor;
-import android.system.ErrnoException;
-import android.util.Pair;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * BpfMap is a key -> value mapping structure that is designed to maintained the bpf map entries.
- * This is a wrapper class of in-kernel data structure. The in-kernel data can be read/written by
- * passing syscalls with map file descriptor.
- *
- * @param <K> the key of the map.
- * @param <V> the value of the map.
- */
-public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V> {
- static {
- System.loadLibrary(JniUtil.getJniLibraryName(BpfMap.class.getPackage()));
- }
-
- // Following definitions from kernel include/uapi/linux/bpf.h
- public static final int BPF_F_RDWR = 0;
- public static final int BPF_F_RDONLY = 1 << 3;
- public static final int BPF_F_WRONLY = 1 << 4;
-
- public static final int BPF_MAP_TYPE_HASH = 1;
-
- private static final int BPF_F_NO_PREALLOC = 1;
-
- private static final int BPF_ANY = 0;
- private static final int BPF_NOEXIST = 1;
- private static final int BPF_EXIST = 2;
-
- private final ParcelFileDescriptor mMapFd;
- private final Class<K> mKeyClass;
- private final Class<V> mValueClass;
- private final int mKeySize;
- private final int mValueSize;
-
- private static ConcurrentHashMap<Pair<String, Integer>, ParcelFileDescriptor> sFdCache =
- new ConcurrentHashMap<>();
-
- private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode,
- int keySize, int valueSize)
- throws ErrnoException, NullPointerException {
- // Supports up to 1023 byte key and 65535 byte values
- // Creating a BpfMap with larger keys/values seems like a bad idea any way...
- keySize &= 1023; // 10-bits
- valueSize &= 65535; // 16-bits
- var key = Pair.create(path, (mode << 26) ^ (keySize << 16) ^ valueSize);
- // unlocked fetch is safe: map is concurrent read capable, and only inserted into
- ParcelFileDescriptor fd = sFdCache.get(key);
- if (fd != null) return fd;
- // ok, no cached fd present, need to grab a lock
- synchronized (BpfMap.class) {
- // need to redo the check
- fd = sFdCache.get(key);
- if (fd != null) return fd;
- // okay, we really haven't opened this before...
- fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode, keySize, valueSize));
- sFdCache.put(key, fd);
- return fd;
- }
- }
-
- /**
- * Create a BpfMap map wrapper with "path" of filesystem.
- *
- * @param flag the access mode, one of BPF_F_RDWR, BPF_F_RDONLY, or BPF_F_WRONLY.
- * @throws ErrnoException if the BPF map associated with {@code path} cannot be retrieved.
- * @throws NullPointerException if {@code path} is null.
- */
- public BpfMap(@NonNull final String path, final int flag, final Class<K> key,
- final Class<V> value) throws ErrnoException, NullPointerException {
- mKeyClass = key;
- mValueClass = value;
- mKeySize = Struct.getSize(key);
- mValueSize = Struct.getSize(value);
- mMapFd = cachedBpfFdGet(path, flag, mKeySize, mValueSize);
- }
-
- /**
- * Update an existing or create a new key -> value entry in an eBbpf map.
- * (use insertOrReplaceEntry() if you need to know whether insert or replace happened)
- */
- @Override
- public void updateEntry(K key, V value) throws ErrnoException {
- nativeWriteToMapEntry(mMapFd.getFd(), key.writeToBytes(), value.writeToBytes(), BPF_ANY);
- }
-
- /**
- * If the key does not exist in the map, insert key -> value entry into eBpf map.
- * Otherwise IllegalStateException will be thrown.
- */
- @Override
- public void insertEntry(K key, V value)
- throws ErrnoException, IllegalStateException {
- try {
- nativeWriteToMapEntry(mMapFd.getFd(), key.writeToBytes(), value.writeToBytes(),
- BPF_NOEXIST);
- } catch (ErrnoException e) {
- if (e.errno == EEXIST) throw new IllegalStateException(key + " already exists");
-
- throw e;
- }
- }
-
- /**
- * If the key already exists in the map, replace its value. Otherwise NoSuchElementException
- * will be thrown.
- */
- @Override
- public void replaceEntry(K key, V value)
- throws ErrnoException, NoSuchElementException {
- try {
- nativeWriteToMapEntry(mMapFd.getFd(), key.writeToBytes(), value.writeToBytes(),
- BPF_EXIST);
- } catch (ErrnoException e) {
- if (e.errno == ENOENT) throw new NoSuchElementException(key + " not found");
-
- throw e;
- }
- }
-
- /**
- * Update an existing or create a new key -> value entry in an eBbpf map.
- * Returns true if inserted, false if replaced.
- * (use updateEntry() if you don't care whether insert or replace happened)
- * Note: see inline comment below if running concurrently with delete operations.
- */
- @Override
- public boolean insertOrReplaceEntry(K key, V value)
- throws ErrnoException {
- try {
- nativeWriteToMapEntry(mMapFd.getFd(), key.writeToBytes(), value.writeToBytes(),
- BPF_NOEXIST);
- return true; /* insert succeeded */
- } catch (ErrnoException e) {
- if (e.errno != EEXIST) throw e;
- }
- try {
- nativeWriteToMapEntry(mMapFd.getFd(), key.writeToBytes(), value.writeToBytes(),
- BPF_EXIST);
- return false; /* replace succeeded */
- } catch (ErrnoException e) {
- if (e.errno != ENOENT) throw e;
- }
- /* If we reach here somebody deleted after our insert attempt and before our replace:
- * this implies a race happened. The kernel bpf delete interface only takes a key,
- * and not the value, so we can safely pretend the replace actually succeeded and
- * was immediately followed by the other thread's delete, since the delete cannot
- * observe the potential change to the value.
- */
- return false; /* pretend replace succeeded */
- }
-
- /** Remove existing key from eBpf map. Return false if map was not modified. */
- @Override
- public boolean deleteEntry(K key) throws ErrnoException {
- return nativeDeleteMapEntry(mMapFd.getFd(), key.writeToBytes());
- }
-
- /** Returns {@code true} if this map contains no elements. */
- @Override
- public boolean isEmpty() throws ErrnoException {
- return getFirstKey() == null;
- }
-
- private K getNextKeyInternal(@Nullable K key) throws ErrnoException {
- byte[] rawKey = new byte[mKeySize];
-
- if (!nativeGetNextMapKey(mMapFd.getFd(),
- key == null ? null : key.writeToBytes(),
- rawKey)) return null;
-
- final ByteBuffer buffer = ByteBuffer.wrap(rawKey);
- buffer.order(ByteOrder.nativeOrder());
- return Struct.parse(mKeyClass, buffer);
- }
-
- /**
- * Get the next key of the passed-in key. If the passed-in key is not found, return the first
- * key. If the passed-in key is the last one, return null.
- *
- * TODO: consider allowing null passed-in key.
- */
- @Override
- public K getNextKey(@NonNull K key) throws ErrnoException {
- Objects.requireNonNull(key);
- return getNextKeyInternal(key);
- }
-
- /** Get the first key of eBpf map. */
- @Override
- public K getFirstKey() throws ErrnoException {
- return getNextKeyInternal(null);
- }
-
- /** Check whether a key exists in the map. */
- @Override
- public boolean containsKey(@NonNull K key) throws ErrnoException {
- Objects.requireNonNull(key);
-
- byte[] rawValue = new byte[mValueSize];
- return nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue);
- }
-
- /** Retrieve a value from the map. Return null if there is no such key. */
- @Override
- public V getValue(@NonNull K key) throws ErrnoException {
- Objects.requireNonNull(key);
-
- byte[] rawValue = new byte[mValueSize];
- if (!nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue)) return null;
-
- final ByteBuffer buffer = ByteBuffer.wrap(rawValue);
- buffer.order(ByteOrder.nativeOrder());
- return Struct.parse(mValueClass, buffer);
- }
-
- /**
- * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
- * The given BiConsumer may to delete the passed-in entry, but is not allowed to perform any
- * other structural modifications to the map, such as adding entries or deleting other entries.
- * Otherwise, iteration will result in undefined behaviour.
- */
- @Override
- public void forEach(ThrowingBiConsumer<K, V> action) throws ErrnoException {
- @Nullable K nextKey = getFirstKey();
-
- while (nextKey != null) {
- @NonNull final K curKey = nextKey;
- @NonNull final V value = getValue(curKey);
-
- nextKey = getNextKey(curKey);
- action.accept(curKey, value);
- }
- }
-
- /* Empty implementation to implement AutoCloseable, so we can use BpfMaps
- * with try with resources, but due to persistent FD cache, there is no actual
- * need to close anything. File descriptors will actually be closed when we
- * unlock the BpfMap class and destroy the ParcelFileDescriptor objects.
- */
- @Override
- public void close() throws IOException {
- }
-
- /**
- * Clears the map. The map may already be empty.
- *
- * @throws ErrnoException if the map is already closed, if an error occurred during iteration,
- * or if a non-ENOENT error occurred when deleting a key.
- */
- @Override
- public void clear() throws ErrnoException {
- K key = getFirstKey();
- while (key != null) {
- deleteEntry(key); // ignores ENOENT.
- key = getFirstKey();
- }
- }
-
- private static native int nativeBpfFdGet(String path, int mode, int keySize, int valueSize)
- throws ErrnoException, NullPointerException;
-
- // Note: the following methods appear to not require the object by virtue of taking the
- // fd as an int argument, but the hidden reference to this is actually what prevents
- // the object from being garbage collected (and thus potentially maps closed) prior
- // to the native code actually running (with a possibly already closed fd).
-
- private native void nativeWriteToMapEntry(int fd, byte[] key, byte[] value, int flags)
- throws ErrnoException;
-
- private native boolean nativeDeleteMapEntry(int fd, byte[] key) throws ErrnoException;
-
- // If key is found, the operation returns true and the nextKey would reference to the next
- // element. If key is not found, the operation returns true and the nextKey would reference to
- // the first element. If key is the last element, false is returned.
- private native boolean nativeGetNextMapKey(int fd, byte[] key, byte[] nextKey)
- throws ErrnoException;
-
- private native boolean nativeFindMapEntry(int fd, byte[] key, byte[] value)
- throws ErrnoException;
-}
diff --git a/common/device/com/android/net/module/util/BpfUtils.java b/common/device/com/android/net/module/util/BpfUtils.java
deleted file mode 100644
index 94af11b3..00000000
--- a/common/device/com/android/net/module/util/BpfUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.net.module.util;
-
-import androidx.annotation.NonNull;
-
-import java.io.IOException;
-
-/**
- * The classes and the methods for BPF utilization.
- *
- * {@hide}
- */
-public class BpfUtils {
- static {
- System.loadLibrary(JniUtil.getJniLibraryName(BpfUtils.class.getPackage()));
- }
-
- // Defined in include/uapi/linux/bpf.h. Only adding the CGROUPS currently being used for now.
- public static final int BPF_CGROUP_INET_INGRESS = 0;
- public static final int BPF_CGROUP_INET_EGRESS = 1;
- public static final int BPF_CGROUP_INET4_BIND = 8;
- public static final int BPF_CGROUP_INET6_BIND = 9;
-
-
- /**
- * Attach BPF program to CGROUP
- */
- public static void attachProgram(int type, @NonNull String programPath,
- @NonNull String cgroupPath, int flags) throws IOException {
- native_attachProgramToCgroup(type, programPath, cgroupPath, flags);
- }
-
- /**
- * Detach BPF program from CGROUP
- */
- public static void detachProgram(int type, @NonNull String cgroupPath)
- throws IOException {
- native_detachProgramFromCgroup(type, cgroupPath);
- }
-
- /**
- * Detach single BPF program from CGROUP
- */
- public static void detachSingleProgram(int type, @NonNull String programPath,
- @NonNull String cgroupPath) throws IOException {
- native_detachSingleProgramFromCgroup(type, programPath, cgroupPath);
- }
-
- private static native boolean native_attachProgramToCgroup(int type, String programPath,
- String cgroupPath, int flags) throws IOException;
- private static native boolean native_detachProgramFromCgroup(int type, String cgroupPath)
- throws IOException;
- private static native boolean native_detachSingleProgramFromCgroup(int type,
- String programPath, String cgroupPath) throws IOException;
-}
diff --git a/common/device/com/android/net/module/util/DeviceConfigUtils.java b/common/device/com/android/net/module/util/DeviceConfigUtils.java
deleted file mode 100644
index fb130f67..00000000
--- a/common/device/com/android/net/module/util/DeviceConfigUtils.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
-
-import static com.android.net.module.util.FeatureVersions.CONNECTIVITY_MODULE_ID;
-import static com.android.net.module.util.FeatureVersions.MODULE_MASK;
-import static com.android.net.module.util.FeatureVersions.NETWORK_STACK_MODULE_ID;
-import static com.android.net.module.util.FeatureVersions.VERSION_MASK;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.provider.DeviceConfig;
-import android.util.Log;
-
-import androidx.annotation.BoolRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utilities for modules to query {@link DeviceConfig} and flags.
- */
-public final class DeviceConfigUtils {
- private DeviceConfigUtils() {}
-
- private static final String TAG = DeviceConfigUtils.class.getSimpleName();
- /**
- * DO NOT MODIFY: this may be used by multiple modules that will not see the updated value
- * until they are recompiled, so modifying this constant means that different modules may
- * be referencing a different tethering module variant, or having a stale reference.
- */
- public static final String TETHERING_MODULE_NAME = "com.android.tethering";
-
- @VisibleForTesting
- public static final String RESOURCES_APK_INTENT =
- "com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK";
- private static final String CONNECTIVITY_RES_PKG_DIR = "/apex/" + TETHERING_MODULE_NAME + "/";
-
- @VisibleForTesting
- public static final long DEFAULT_PACKAGE_VERSION = 1000;
-
- @VisibleForTesting
- public static void resetPackageVersionCacheForTest() {
- sPackageVersion = -1;
- sModuleVersion = -1;
- sNetworkStackModuleVersion = -1;
- }
-
- private static volatile long sPackageVersion = -1;
- private static long getPackageVersion(@NonNull final Context context) {
- // sPackageVersion may be set by another thread just after this check, but querying the
- // package version several times on rare occasions is fine.
- if (sPackageVersion >= 0) {
- return sPackageVersion;
- }
- try {
- final long version = context.getPackageManager().getPackageInfo(
- context.getPackageName(), 0).getLongVersionCode();
- sPackageVersion = version;
- return version;
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Failed to get package info: " + e);
- return DEFAULT_PACKAGE_VERSION;
- }
- }
-
- /**
- * Look up the value of a property for a particular namespace from {@link DeviceConfig}.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param defaultValue The value to return if the property does not exist or has no valid value.
- * @return the corresponding value, or defaultValue if none exists.
- */
- @Nullable
- public static String getDeviceConfigProperty(@NonNull String namespace, @NonNull String name,
- @Nullable String defaultValue) {
- String value = DeviceConfig.getProperty(namespace, name);
- return value != null ? value : defaultValue;
- }
-
- /**
- * Look up the value of a property for a particular namespace from {@link DeviceConfig}.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param defaultValue The value to return if the property does not exist or its value is null.
- * @return the corresponding value, or defaultValue if none exists.
- */
- public static int getDeviceConfigPropertyInt(@NonNull String namespace, @NonNull String name,
- int defaultValue) {
- String value = getDeviceConfigProperty(namespace, name, null /* defaultValue */);
- try {
- return (value != null) ? Integer.parseInt(value) : defaultValue;
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- /**
- * Look up the value of a property for a particular namespace from {@link DeviceConfig}.
- *
- * Flags like timeouts should use this method and set an appropriate min/max range: if invalid
- * values like "0" or "1" are pushed to devices, everything would timeout. The min/max range
- * protects against this kind of breakage.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param minimumValue The minimum value of a property.
- * @param maximumValue The maximum value of a property.
- * @param defaultValue The value to return if the property does not exist or its value is null.
- * @return the corresponding value, or defaultValue if none exists or the fetched value is
- * not in the provided range.
- */
- public static int getDeviceConfigPropertyInt(@NonNull String namespace, @NonNull String name,
- int minimumValue, int maximumValue, int defaultValue) {
- int value = getDeviceConfigPropertyInt(namespace, name, defaultValue);
- if (value < minimumValue || value > maximumValue) return defaultValue;
- return value;
- }
-
- /**
- * Look up the value of a property for a particular namespace from {@link DeviceConfig}.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param defaultValue The value to return if the property does not exist or its value is null.
- * @return the corresponding value, or defaultValue if none exists.
- */
- public static boolean getDeviceConfigPropertyBoolean(@NonNull String namespace,
- @NonNull String name, boolean defaultValue) {
- String value = getDeviceConfigProperty(namespace, name, null /* defaultValue */);
- return (value != null) ? Boolean.parseBoolean(value) : defaultValue;
- }
-
- /**
- * Check whether or not one specific experimental feature for a particular namespace from
- * {@link DeviceConfig} is enabled by comparing module package version
- * with current version of property. If this property version is valid, the corresponding
- * experimental feature would be enabled, otherwise disabled.
- *
- * This is useful to ensure that if a module install is rolled back, flags are not left fully
- * rolled out on a version where they have not been well tested.
- * @param context The global context information about an app environment.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @return true if this feature is enabled, or false if disabled.
- */
- public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace,
- @NonNull String name) {
- return isFeatureEnabled(context, namespace, name, false /* defaultEnabled */);
- }
-
- /**
- * Check whether or not one specific experimental feature for a particular namespace from
- * {@link DeviceConfig} is enabled by comparing module package version
- * with current version of property. If this property version is valid, the corresponding
- * experimental feature would be enabled, otherwise disabled.
- *
- * This is useful to ensure that if a module install is rolled back, flags are not left fully
- * rolled out on a version where they have not been well tested.
- * @param context The global context information about an app environment.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param defaultEnabled The value to return if the property does not exist or its value is
- * null.
- * @return true if this feature is enabled, or false if disabled.
- */
- public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace,
- @NonNull String name, boolean defaultEnabled) {
- final long packageVersion = getPackageVersion(context);
- return isFeatureEnabled(context, packageVersion, namespace, name, defaultEnabled);
- }
-
- /**
- * Check whether or not one specific experimental feature for a particular namespace from
- * {@link DeviceConfig} is enabled by comparing module package version
- * with current version of property. If this property version is valid, the corresponding
- * experimental feature would be enabled, otherwise disabled.
- *
- * This is useful to ensure that if a module install is rolled back, flags are not left fully
- * rolled out on a version where they have not been well tested.
- * @param context The global context information about an app environment.
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @param moduleName The mainline module name which is released as apex.
- * @param defaultEnabled The value to return if the property does not exist or its value is
- * null.
- * @return true if this feature is enabled, or false if disabled.
- */
- public static boolean isTetheringFeatureEnabled(@NonNull Context context,
- @NonNull String namespace, @NonNull String name, @NonNull String moduleName,
- boolean defaultEnabled) {
- // TODO: migrate callers to a non-generic isTetheringFeatureEnabled method.
- if (!TETHERING_MODULE_NAME.equals(moduleName)) {
- throw new IllegalArgumentException(
- "This method is only usable by the tethering module");
- }
- final long packageVersion = getTetheringModuleVersion(context);
- return isFeatureEnabled(context, packageVersion, namespace, name, defaultEnabled);
- }
-
- private static boolean isFeatureEnabled(@NonNull Context context, long packageVersion,
- @NonNull String namespace, String name, boolean defaultEnabled) {
- final int propertyVersion = getDeviceConfigPropertyInt(namespace, name,
- 0 /* default value */);
- return (propertyVersion == 0 && defaultEnabled)
- || (propertyVersion != 0 && packageVersion >= (long) propertyVersion);
- }
-
- // Guess the tethering module name based on the package prefix of the connectivity resources
- // Take the resource package name, cut it before "connectivity" and append "tethering".
- // Then resolve that package version number with packageManager.
- // If that fails retry by appending "go.tethering" instead
- private static long resolveTetheringModuleVersion(@NonNull Context context)
- throws PackageManager.NameNotFoundException {
- final String pkgPrefix = resolvePkgPrefix(context);
- final PackageManager packageManager = context.getPackageManager();
- try {
- return packageManager.getPackageInfo(pkgPrefix + "tethering",
- PackageManager.MATCH_APEX).getLongVersionCode();
- } catch (PackageManager.NameNotFoundException e) {
- Log.d(TAG, "Device is using go modules");
- // fall through
- }
-
- return packageManager.getPackageInfo(pkgPrefix + "go.tethering",
- PackageManager.MATCH_APEX).getLongVersionCode();
- }
-
- private static String resolvePkgPrefix(Context context) {
- final String connResourcesPackage = getConnectivityResourcesPackageName(context);
- final int pkgPrefixLen = connResourcesPackage.indexOf("connectivity");
- if (pkgPrefixLen < 0) {
- throw new IllegalStateException(
- "Invalid connectivity resources package: " + connResourcesPackage);
- }
-
- return connResourcesPackage.substring(0, pkgPrefixLen);
- }
-
- private static volatile long sModuleVersion = -1;
- private static long getTetheringModuleVersion(@NonNull Context context) {
- if (sModuleVersion >= 0) return sModuleVersion;
-
- try {
- sModuleVersion = resolveTetheringModuleVersion(context);
- } catch (PackageManager.NameNotFoundException e) {
- // It's expected to fail tethering module version resolution on the devices with
- // flattened apex
- Log.e(TAG, "Failed to resolve tethering module version: " + e);
- return DEFAULT_PACKAGE_VERSION;
- }
- return sModuleVersion;
- }
-
- private static volatile long sNetworkStackModuleVersion = -1;
-
- /**
- * Get networkstack module version.
- */
- @VisibleForTesting
- static long getNetworkStackModuleVersion(@NonNull Context context) {
- if (sNetworkStackModuleVersion >= 0) return sNetworkStackModuleVersion;
-
- try {
- sNetworkStackModuleVersion = resolveNetworkStackModuleVersion(context);
- } catch (PackageManager.NameNotFoundException e) {
- Log.wtf(TAG, "Failed to resolve networkstack module version: " + e);
- return DEFAULT_PACKAGE_VERSION;
- }
- return sNetworkStackModuleVersion;
- }
-
- private static long resolveNetworkStackModuleVersion(@NonNull Context context)
- throws PackageManager.NameNotFoundException {
- // TODO(b/293975546): Strictly speaking this is the prefix for connectivity and not
- // network stack. In practice, it's the same. Read the prefix from network stack instead.
- final String pkgPrefix = resolvePkgPrefix(context);
- final PackageManager packageManager = context.getPackageManager();
- try {
- return packageManager.getPackageInfo(pkgPrefix + "networkstack",
- PackageManager.MATCH_SYSTEM_ONLY).getLongVersionCode();
- } catch (PackageManager.NameNotFoundException e) {
- Log.d(TAG, "Device is using go or non-mainline modules");
- // fall through
- }
-
- return packageManager.getPackageInfo(pkgPrefix + "go.networkstack",
- PackageManager.MATCH_ALL).getLongVersionCode();
- }
-
- /**
- * Check whether one specific feature is supported from the feature Id. The feature Id is
- * composed by a module package Id and version Id from {@link FeatureVersions}.
- *
- * This is useful when a feature required minimal module version supported and cannot function
- * well with a standalone newer module.
- * @param context The global context information about an app environment.
- * @param featureId The feature id that contains required module id and minimal module version
- * @return true if this feature is supported, or false if not supported.
- **/
- public static boolean isFeatureSupported(@NonNull Context context, long featureId) {
- final long moduleVersion;
- final long moduleId = featureId & MODULE_MASK;
- if (moduleId == CONNECTIVITY_MODULE_ID) {
- moduleVersion = getTetheringModuleVersion(context);
- } else if (moduleId == NETWORK_STACK_MODULE_ID) {
- moduleVersion = getNetworkStackModuleVersion(context);
- } else {
- throw new IllegalArgumentException("Unknown module " + moduleId);
- }
- // Support by default if no module version is available.
- return moduleVersion == DEFAULT_PACKAGE_VERSION
- || moduleVersion >= (featureId & VERSION_MASK);
- }
-
- /**
- * Check whether one specific experimental feature in specific namespace from
- * {@link DeviceConfig} is not disabled. Feature can be disabled by setting a non-zero
- * value in the property. If the feature is enabled by default and disabled by flag push
- * (kill switch), this method should be used. If the feature is disabled by default and
- * enabled by flag push, {@link #isFeatureEnabled} should be used.
- *
- * @param namespace The namespace containing the property to look up.
- * @param name The name of the property to look up.
- * @return true if this feature is enabled, or false if disabled.
- */
- private static boolean isFeatureNotChickenedOut(String namespace, String name) {
- final int propertyVersion = getDeviceConfigPropertyInt(namespace, name,
- 0 /* default value */);
- return propertyVersion == 0;
- }
-
- /**
- * Check whether one specific experimental feature in Tethering module from {@link DeviceConfig}
- * is not disabled.
- *
- * @param name The name of the property in tethering module to look up.
- * @return true if this feature is enabled, or false if disabled.
- */
- public static boolean isTetheringFeatureNotChickenedOut(String name) {
- return isFeatureNotChickenedOut(NAMESPACE_TETHERING, name);
- }
-
- /**
- * Check whether one specific experimental feature in NetworkStack module from
- * {@link DeviceConfig} is not disabled.
- *
- * @param name The name of the property in NetworkStack module to look up.
- * @return true if this feature is enabled, or false if disabled.
- */
- public static boolean isNetworkStackFeatureNotChickenedOut(String name) {
- return isFeatureNotChickenedOut(NAMESPACE_CONNECTIVITY, name);
- }
-
- /**
- * Gets boolean config from resources.
- */
- public static boolean getResBooleanConfig(@NonNull final Context context,
- @BoolRes int configResource, final boolean defaultValue) {
- final Resources res = context.getResources();
- try {
- return res.getBoolean(configResource);
- } catch (Resources.NotFoundException e) {
- return defaultValue;
- }
- }
-
- /**
- * Gets int config from resources.
- */
- public static int getResIntegerConfig(@NonNull final Context context,
- @BoolRes int configResource, final int defaultValue) {
- final Resources res = context.getResources();
- try {
- return res.getInteger(configResource);
- } catch (Resources.NotFoundException e) {
- return defaultValue;
- }
- }
-
- /**
- * Get the package name of the ServiceConnectivityResources package, used to provide resources
- * for service-connectivity.
- */
- @NonNull
- public static String getConnectivityResourcesPackageName(@NonNull Context context) {
- final List<ResolveInfo> pkgs = new ArrayList<>(context.getPackageManager()
- .queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY));
- pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(
- CONNECTIVITY_RES_PKG_DIR));
- if (pkgs.size() > 1) {
- Log.wtf(TAG, "More than one connectivity resources package found: " + pkgs);
- }
- if (pkgs.isEmpty()) {
- throw new IllegalStateException("No connectivity resource package found");
- }
-
- return pkgs.get(0).activityInfo.applicationInfo.packageName;
- }
-}
diff --git a/common/device/com/android/net/module/util/DomainUtils.java b/common/device/com/android/net/module/util/DomainUtils.java
deleted file mode 100644
index b327fd08..00000000
--- a/common/device/com/android/net/module/util/DomainUtils.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import android.util.ArrayMap;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.DnsPacketUtils.DnsRecordParser;
-
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-
-/**
- * Utilities for encoding/decoding the domain name or domain search list.
- *
- * @hide
- */
-public final class DomainUtils {
- private static final String TAG = "DomainUtils";
- private static final int MAX_OPTION_LEN = 255;
-
- @NonNull
- private static String getSubstring(@NonNull final String string, @NonNull final String[] labels,
- int index) {
- int beginIndex = 0;
- for (int i = 0; i < index; i++) {
- beginIndex += labels[i].length() + 1; // include the dot
- }
- return string.substring(beginIndex);
- }
-
- /**
- * Encode the given single domain name to byte array, comply with RFC1035 section-3.1.
- *
- * @return null if the given domain string is invalid, otherwise, return a byte array
- * wrapping the encoded domain, not including any padded octets, caller should
- * pad zero octets at the end if needed.
- */
- @Nullable
- public static byte[] encode(@NonNull final String domain) {
- if (!DnsRecordParser.isHostName(domain)) return null;
- return encode(new String[]{ domain }, false /* compression */);
- }
-
- /**
- * Encode the given multiple domain names to byte array, comply with RFC1035 section-3.1
- * and section 4.1.4 (message compression) if enabled.
- *
- * @return Null if encode fails due to BufferOverflowException, otherwise, return a byte
- * array wrapping the encoded domains, not including any padded octets, caller
- * should pad zero octets at the end if needed. The byte array may be empty if
- * the given domain strings are invalid.
- */
- @Nullable
- public static byte[] encode(@NonNull final String[] domains, boolean compression) {
- try {
- final ByteBuffer buffer = ByteBuffer.allocate(MAX_OPTION_LEN);
- final ArrayMap<String, Integer> offsetMap = new ArrayMap<>();
- for (int i = 0; i < domains.length; i++) {
- if (!DnsRecordParser.isHostName(domains[i])) {
- Log.e(TAG, "Skip invalid domain name " + domains[i]);
- continue;
- }
- final String[] labels = domains[i].split("\\.");
- for (int j = 0; j < labels.length; j++) {
- if (compression) {
- final String suffix = getSubstring(domains[i], labels, j);
- if (offsetMap.containsKey(suffix)) {
- int offsetOfSuffix = offsetMap.get(suffix);
- offsetOfSuffix |= 0xC000;
- buffer.putShort((short) offsetOfSuffix);
- break; // unnecessary to put the compressed string into map
- } else {
- offsetMap.put(suffix, buffer.position());
- }
- }
- // encode the domain name string without compression when:
- // - compression feature isn't enabled,
- // - suffix does not match any string in the map.
- final byte[] labelBytes = labels[j].getBytes(StandardCharsets.UTF_8);
- buffer.put((byte) labelBytes.length);
- buffer.put(labelBytes);
- if (j == labels.length - 1) {
- // Pad terminate label at the end of last label.
- buffer.put((byte) 0);
- }
- }
- }
- buffer.flip();
- final byte[] out = new byte[buffer.limit()];
- buffer.get(out);
- return out;
- } catch (BufferOverflowException e) {
- Log.e(TAG, "Fail to encode domain name and stop encoding", e);
- return null;
- }
- }
-
- /**
- * Decode domain name(s) from the given byteBuffer. Decode follows RFC1035 section 3.1 and
- * section 4.1.4(message compression).
- *
- * @return domain name(s) string array with space separated, or empty string if decode fails.
- */
- @NonNull
- public static ArrayList<String> decode(@NonNull final ByteBuffer buffer, boolean compression) {
- final ArrayList<String> domainList = new ArrayList<>();
- while (buffer.remaining() > 0) {
- try {
- // TODO: replace the recursion with loop in parseName and don't need to pass in the
- // maxLabelCount parameter to prevent recursion from overflowing stack.
- final String domain = DnsRecordParser.parseName(buffer, 0 /* depth */,
- 15 /* maxLabelCount */, compression);
- if (!DnsRecordParser.isHostName(domain)) continue;
- domainList.add(domain);
- } catch (BufferUnderflowException | DnsPacket.ParseException e) {
- Log.e(TAG, "Fail to parse domain name and stop parsing", e);
- break;
- }
- }
- return domainList;
- }
-}
diff --git a/common/device/com/android/net/module/util/FdEventsReader.java b/common/device/com/android/net/module/util/FdEventsReader.java
deleted file mode 100644
index f88883bf..00000000
--- a/common/device/com/android/net/module/util/FdEventsReader.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.util.SocketUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-
-/**
- * This class encapsulates the mechanics of registering a file descriptor
- * with a thread's Looper and handling read events (and errors).
- *
- * Subclasses MUST implement createFd() and SHOULD override handlePacket(). They MAY override
- * onStop() and onStart().
- *
- * Subclasses can expect a call life-cycle like the following:
- *
- * [1] when a client calls start(), createFd() is called, followed by the onStart() hook if all
- * goes well. Implementations may override onStart() for additional initialization.
- *
- * [2] yield, waiting for read event or error notification:
- *
- * [a] readPacket() && handlePacket()
- *
- * [b] if (no error):
- * goto 2
- * else:
- * goto 3
- *
- * [3] when a client calls stop(), the onStop() hook is called (unless already stopped or never
- * started). Implementations may override onStop() for additional cleanup.
- *
- * The packet receive buffer is recycled on every read call, so subclasses
- * should make any copies they would like inside their handlePacket()
- * implementation.
- *
- * All public methods MUST only be called from the same thread with which
- * the Handler constructor argument is associated.
- *
- * @param <BufferType> the type of the buffer used to read data.
- */
-public abstract class FdEventsReader<BufferType> {
- private static final String TAG = FdEventsReader.class.getSimpleName();
- private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
- private static final int UNREGISTER_THIS_FD = 0;
-
- @NonNull
- private final Handler mHandler;
- @NonNull
- private final MessageQueue mQueue;
- @NonNull
- private final BufferType mBuffer;
- @Nullable
- private FileDescriptor mFd;
- private long mPacketsReceived;
-
- protected static void closeFd(FileDescriptor fd) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
-
- protected FdEventsReader(@NonNull Handler h, @NonNull BufferType buffer) {
- mHandler = h;
- mQueue = mHandler.getLooper().getQueue();
- mBuffer = buffer;
- }
-
- @VisibleForTesting
- @NonNull
- protected MessageQueue getMessageQueue() {
- return mQueue;
- }
-
- /** Start this FdEventsReader. */
- public boolean start() {
- if (!onCorrectThread()) {
- throw new IllegalStateException("start() called from off-thread");
- }
-
- return createAndRegisterFd();
- }
-
- /** Stop this FdEventsReader and destroy the file descriptor. */
- public void stop() {
- if (!onCorrectThread()) {
- throw new IllegalStateException("stop() called from off-thread");
- }
-
- unregisterAndDestroyFd();
- }
-
- @NonNull
- public Handler getHandler() {
- return mHandler;
- }
-
- protected abstract int recvBufSize(@NonNull BufferType buffer);
-
- /** Returns the size of the receive buffer. */
- public int recvBufSize() {
- return recvBufSize(mBuffer);
- }
-
- /**
- * Get the number of successful calls to {@link #readPacket(FileDescriptor, Object)}.
- *
- * <p>A call was successful if {@link #readPacket(FileDescriptor, Object)} returned a value > 0.
- */
- public final long numPacketsReceived() {
- return mPacketsReceived;
- }
-
- /**
- * Subclasses MUST create the listening socket here, including setting all desired socket
- * options, interface or address/port binding, etc. The socket MUST be created nonblocking.
- */
- @Nullable
- protected abstract FileDescriptor createFd();
-
- /**
- * Implementations MUST return the bytes read or throw an Exception.
- *
- * <p>The caller may throw a {@link ErrnoException} with {@link OsConstants#EAGAIN} or
- * {@link OsConstants#EINTR}, in which case {@link FdEventsReader} will ignore the buffer
- * contents and respectively wait for further input or retry the read immediately. For all other
- * exceptions, the {@link FdEventsReader} will be stopped with no more interactions with this
- * method.
- */
- protected abstract int readPacket(@NonNull FileDescriptor fd, @NonNull BufferType buffer)
- throws Exception;
-
- /**
- * Called by the main loop for every packet. Any desired copies of
- * |recvbuf| should be made in here, as the underlying byte array is
- * reused across all reads.
- */
- protected void handlePacket(@NonNull BufferType recvbuf, int length) {}
-
- /**
- * Called by the subclasses of FdEventsReader, decide whether it should stop reading packet or
- * just ignore the specific error other than EAGAIN or EINTR.
- *
- * @return {@code true} if this FdEventsReader should stop reading from the socket.
- * {@code false} if it should continue.
- */
- protected boolean handleReadError(@NonNull ErrnoException e) {
- logError("readPacket error: ", e);
- return true; // by default, stop reading on any error.
- }
-
- /**
- * Called by the subclasses of FdEventsReader, decide whether it should stop reading from the
- * socket or process the packet and continue to read upon receiving a zero-length packet.
- *
- * @return {@code true} if this FdEventsReader should process the zero-length packet.
- * {@code false} if it should stop reading from the socket.
- */
- protected boolean shouldProcessZeroLengthPacket() {
- return false; // by default, stop reading upon receiving zero-length packet.
- }
-
- /**
- * Called by the main loop to log errors. In some cases |e| may be null.
- */
- protected void logError(@NonNull String msg, @Nullable Exception e) {}
-
- /**
- * Called by start(), if successful, just prior to returning.
- */
- protected void onStart() {}
-
- /**
- * Called by stop() just prior to returning.
- */
- protected void onStop() {}
-
- private boolean createAndRegisterFd() {
- if (mFd != null) return true;
-
- try {
- mFd = createFd();
- } catch (Exception e) {
- logError("Failed to create socket: ", e);
- closeFd(mFd);
- mFd = null;
- }
-
- if (mFd == null) return false;
-
- getMessageQueue().addOnFileDescriptorEventListener(
- mFd,
- FD_EVENTS,
- (fd, events) -> {
- // Always call handleInput() so read/recvfrom are given
- // a proper chance to encounter a meaningful errno and
- // perhaps log a useful error message.
- if (!isRunning() || !handleInput()) {
- unregisterAndDestroyFd();
- return UNREGISTER_THIS_FD;
- }
- return FD_EVENTS;
- });
- onStart();
- return true;
- }
-
- protected boolean isRunning() {
- return (mFd != null) && mFd.valid();
- }
-
- // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
- private boolean handleInput() {
- while (isRunning()) {
- final int bytesRead;
-
- try {
- bytesRead = readPacket(mFd, mBuffer);
- if (bytesRead == 0 && !shouldProcessZeroLengthPacket()) {
- if (isRunning()) logError("Socket closed, exiting", null);
- break;
- }
- mPacketsReceived++;
- } catch (ErrnoException e) {
- if (e.errno == OsConstants.EAGAIN) {
- // We've read everything there is to read this time around.
- return true;
- } else if (e.errno == OsConstants.EINTR) {
- continue;
- } else {
- if (!isRunning()) break;
- final boolean shouldStop = handleReadError(e);
- if (shouldStop) break;
- continue;
- }
- } catch (Exception e) {
- if (isRunning()) logError("readPacket error: ", e);
- break;
- }
-
- try {
- handlePacket(mBuffer, bytesRead);
- } catch (Exception e) {
- logError("handlePacket error: ", e);
- Log.wtf(TAG, "Error handling packet", e);
- }
- }
-
- return false;
- }
-
- private void unregisterAndDestroyFd() {
- if (mFd == null) return;
-
- getMessageQueue().removeOnFileDescriptorEventListener(mFd);
- closeFd(mFd);
- mFd = null;
- onStop();
- }
-
- private boolean onCorrectThread() {
- return (mHandler.getLooper() == Looper.myLooper());
- }
-}
diff --git a/common/device/com/android/net/module/util/FeatureVersions.java b/common/device/com/android/net/module/util/FeatureVersions.java
deleted file mode 100644
index 149756c3..00000000
--- a/common/device/com/android/net/module/util/FeatureVersions.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-/**
- * Class to centralize feature version control that requires a specific module or a specific
- * module version.
- * @hide
- */
-public class FeatureVersions {
- /**
- * This constant is used to do bitwise shift operation to create module ids.
- * The module version is composed with 9 digits which is placed in the lower 36 bits.
- */
- private static final int MODULE_SHIFT = 36;
- /**
- * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module id.
- */
- public static final long MODULE_MASK = 0xFF0_0000_0000L;
- /**
- * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module version.
- */
- public static final long VERSION_MASK = 0x00F_FFFF_FFFFL;
- public static final long CONNECTIVITY_MODULE_ID = 0x01L << MODULE_SHIFT;
- public static final long NETWORK_STACK_MODULE_ID = 0x02L << MODULE_SHIFT;
- // CLAT_ADDRESS_TRANSLATE is a feature of the network stack, which doesn't throw when system
- // try to add a NAT-T keepalive packet filter with v6 address, introduced in version
- // M-2023-Sept on July 3rd, 2023.
- public static final long FEATURE_CLAT_ADDRESS_TRANSLATE =
- NETWORK_STACK_MODULE_ID + 34_09_00_000L;
-}
diff --git a/common/device/com/android/net/module/util/IBpfMap.java b/common/device/com/android/net/module/util/IBpfMap.java
deleted file mode 100644
index 83ff875c..00000000
--- a/common/device/com/android/net/module/util/IBpfMap.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.net.module.util;
-
-import android.system.ErrnoException;
-
-import androidx.annotation.NonNull;
-
-import java.io.IOException;
-import java.util.NoSuchElementException;
-
-/**
- * The interface of BpfMap. This could be used to inject for testing.
- * So the testing code won't load the JNI and update the entries to kernel.
- *
- * @param <K> the key of the map.
- * @param <V> the value of the map.
- */
-public interface IBpfMap<K extends Struct, V extends Struct> extends AutoCloseable {
- /** Update an existing or create a new key -> value entry in an eBbpf map. */
- void updateEntry(K key, V value) throws ErrnoException;
-
- /** If the key does not exist in the map, insert key -> value entry into eBpf map. */
- void insertEntry(K key, V value) throws ErrnoException, IllegalStateException;
-
- /** If the key already exists in the map, replace its value. */
- void replaceEntry(K key, V value) throws ErrnoException, NoSuchElementException;
-
- /**
- * Update an existing or create a new key -> value entry in an eBbpf map. Returns true if
- * inserted, false if replaced. (use updateEntry() if you don't care whether insert or replace
- * happened).
- */
- boolean insertOrReplaceEntry(K key, V value) throws ErrnoException;
-
- /** Remove existing key from eBpf map. Return true if something was deleted. */
- boolean deleteEntry(K key) throws ErrnoException;
-
- /** Returns {@code true} if this map contains no elements. */
- boolean isEmpty() throws ErrnoException;
-
- /** Get the key after the passed-in key. */
- K getNextKey(@NonNull K key) throws ErrnoException;
-
- /** Get the first key of the eBpf map. */
- K getFirstKey() throws ErrnoException;
-
- /** Check whether a key exists in the map. */
- boolean containsKey(@NonNull K key) throws ErrnoException;
-
- /** Retrieve a value from the map. */
- V getValue(@NonNull K key) throws ErrnoException;
-
- public interface ThrowingBiConsumer<T,U> {
- void accept(T t, U u) throws ErrnoException;
- }
-
- /**
- * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
- */
- void forEach(ThrowingBiConsumer<K, V> action) throws ErrnoException;
-
- /** Clears the map. */
- void clear() throws ErrnoException;
-
- /** Close for AutoCloseable. */
- @Override
- void close() throws IOException;
-}
diff --git a/common/device/com/android/net/module/util/Ipv6Utils.java b/common/device/com/android/net/module/util/Ipv6Utils.java
deleted file mode 100644
index d5382215..00000000
--- a/common/device/com/android/net/module/util/Ipv6Utils.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.system.OsConstants.IPPROTO_ICMPV6;
-
-import static com.android.net.module.util.IpUtils.icmpv6Checksum;
-import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REPLY_TYPE;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;
-
-import android.net.MacAddress;
-
-import com.android.net.module.util.structs.EthernetHeader;
-import com.android.net.module.util.structs.Icmpv6Header;
-import com.android.net.module.util.structs.Ipv6Header;
-import com.android.net.module.util.structs.NaHeader;
-import com.android.net.module.util.structs.NsHeader;
-import com.android.net.module.util.structs.RaHeader;
-import com.android.net.module.util.structs.RsHeader;
-
-import java.net.Inet6Address;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Utilities for IPv6 packets.
- */
-public class Ipv6Utils {
- /**
- * Build a generic ICMPv6 packet without Ethernet header.
- */
- public static ByteBuffer buildIcmpv6Packet(final Inet6Address srcIp, final Inet6Address dstIp,
- short type, short code, final ByteBuffer... options) {
- final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
- final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
- int payloadLen = 0;
- for (ByteBuffer option: options) {
- payloadLen += option.limit();
- }
- final ByteBuffer packet = ByteBuffer.allocate(ipv6HeaderLen + icmpv6HeaderLen + payloadLen);
- final Ipv6Header ipv6Header =
- new Ipv6Header((int) 0x60000000 /* version, traffic class, flowlabel */,
- icmpv6HeaderLen + payloadLen /* payload length */,
- (byte) IPPROTO_ICMPV6 /* next header */, (byte) 0xff /* hop limit */, srcIp, dstIp);
- final Icmpv6Header icmpv6Header = new Icmpv6Header(type, code, (short) 0 /* checksum */);
-
- ipv6Header.writeToByteBuffer(packet);
- icmpv6Header.writeToByteBuffer(packet);
- for (ByteBuffer option : options) {
- packet.put(option);
- // in case option might be reused by caller, restore the position and
- // limit of bytebuffer.
- option.clear();
- }
- packet.flip();
-
- // Populate the ICMPv6 checksum field.
- packet.putShort(ipv6HeaderLen + 2, icmpv6Checksum(packet, 0 /* ipOffset */,
- ipv6HeaderLen /* transportOffset */,
- (short) (icmpv6HeaderLen + payloadLen) /* transportLen */));
- return packet;
-
- }
-
- /**
- * Build a generic ICMPv6 packet(e.g., packet used in the neighbor discovery protocol).
- */
- public static ByteBuffer buildIcmpv6Packet(final MacAddress srcMac, final MacAddress dstMac,
- final Inet6Address srcIp, final Inet6Address dstIp, short type, short code,
- final ByteBuffer... options) {
- final ByteBuffer payload = buildIcmpv6Packet(srcIp, dstIp, type, code, options);
-
- final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
- final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + payload.limit());
- final EthernetHeader ethHeader =
- new EthernetHeader(dstMac, srcMac, (short) ETHER_TYPE_IPV6);
-
- ethHeader.writeToByteBuffer(packet);
- packet.put(payload);
- packet.flip();
-
- return packet;
- }
-
- /**
- * Build the ICMPv6 packet payload including payload header and specific options.
- */
- private static ByteBuffer[] buildIcmpv6Payload(final ByteBuffer payloadHeader,
- final ByteBuffer... options) {
- final ByteBuffer[] payload = new ByteBuffer[options.length + 1];
- payload[0] = payloadHeader;
- System.arraycopy(options, 0, payload, 1, options.length);
- return payload;
- }
-
- /**
- * Build an ICMPv6 Router Advertisement packet from the required specified parameters.
- */
- public static ByteBuffer buildRaPacket(final MacAddress srcMac, final MacAddress dstMac,
- final Inet6Address srcIp, final Inet6Address dstIp, final byte flags,
- final int lifetime, final long reachableTime, final long retransTimer,
- final ByteBuffer... options) {
- final RaHeader raHeader = new RaHeader((byte) 0 /* hopLimit, unspecified */,
- flags, lifetime, reachableTime, retransTimer);
- final ByteBuffer[] payload = buildIcmpv6Payload(
- ByteBuffer.wrap(raHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
- return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
- (byte) ICMPV6_ROUTER_ADVERTISEMENT /* type */, (byte) 0 /* code */, payload);
- }
-
- /**
- * Build an ICMPv6 Neighbor Advertisement packet from the required specified parameters.
- */
- public static ByteBuffer buildNaPacket(final MacAddress srcMac, final MacAddress dstMac,
- final Inet6Address srcIp, final Inet6Address dstIp, final int flags,
- final Inet6Address target, final ByteBuffer... options) {
- final NaHeader naHeader = new NaHeader(flags, target);
- final ByteBuffer[] payload = buildIcmpv6Payload(
- ByteBuffer.wrap(naHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
- return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
- (byte) ICMPV6_NEIGHBOR_ADVERTISEMENT /* type */, (byte) 0 /* code */, payload);
- }
-
- /**
- * Build an ICMPv6 Neighbor Solicitation packet from the required specified parameters.
- */
- public static ByteBuffer buildNsPacket(final MacAddress srcMac, final MacAddress dstMac,
- final Inet6Address srcIp, final Inet6Address dstIp,
- final Inet6Address target, final ByteBuffer... options) {
- final NsHeader nsHeader = new NsHeader(target);
- final ByteBuffer[] payload = buildIcmpv6Payload(
- ByteBuffer.wrap(nsHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
- return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
- (byte) ICMPV6_NEIGHBOR_SOLICITATION /* type */, (byte) 0 /* code */, payload);
- }
-
- /**
- * Build an ICMPv6 Router Solicitation packet from the required specified parameters.
- */
- public static ByteBuffer buildRsPacket(final MacAddress srcMac, final MacAddress dstMac,
- final Inet6Address srcIp, final Inet6Address dstIp, final ByteBuffer... options) {
- final RsHeader rsHeader = new RsHeader((int) 0 /* reserved */);
- final ByteBuffer[] payload = buildIcmpv6Payload(
- ByteBuffer.wrap(rsHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
- return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
- (byte) ICMPV6_ROUTER_SOLICITATION /* type */, (byte) 0 /* code */, payload);
- }
-
- /**
- * Build an ICMPv6 Echo Request packet from the required specified parameters.
- */
- public static ByteBuffer buildEchoRequestPacket(final MacAddress srcMac,
- final MacAddress dstMac, final Inet6Address srcIp, final Inet6Address dstIp) {
- final ByteBuffer payload = ByteBuffer.allocate(4); // ID and Sequence number may be zero.
- return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
- (byte) ICMPV6_ECHO_REQUEST_TYPE /* type */, (byte) 0 /* code */, payload);
- }
-
- /**
- * Build an ICMPv6 Echo Reply packet without ethernet header.
- */
- public static ByteBuffer buildEchoReplyPacket(final Inet6Address srcIp,
- final Inet6Address dstIp) {
- final ByteBuffer payload = ByteBuffer.allocate(4); // ID and Sequence number may be zero.
- return buildIcmpv6Packet(srcIp, dstIp, (byte) ICMPV6_ECHO_REPLY_TYPE /* type */,
- (byte) 0 /* code */, payload);
- }
-}
diff --git a/common/device/com/android/net/module/util/JniUtil.java b/common/device/com/android/net/module/util/JniUtil.java
deleted file mode 100644
index 5210a3ef..00000000
--- a/common/device/com/android/net/module/util/JniUtil.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-/**
- * Utilities for modules to use jni.
- */
-public final class JniUtil {
- /**
- * The method to find jni library accroding to the giving package name.
- *
- * The jni library name would be packageName + _jni.so. E.g.
- * com_android_networkstack_tethering_util_jni for tethering,
- * com_android_connectivity_util_jni for connectivity.
- */
- public static String getJniLibraryName(final Package pkg) {
- final String libPrefix = pkg.getName().replaceAll("\\.", "_");
-
- return libPrefix + "_jni";
- }
-}
diff --git a/common/device/com/android/net/module/util/NetworkMonitorUtils.java b/common/device/com/android/net/module/util/NetworkMonitorUtils.java
deleted file mode 100644
index 5a4412f5..00000000
--- a/common/device/com/android/net/module/util/NetworkMonitorUtils.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
-import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-
-import android.annotation.NonNull;
-import android.net.NetworkCapabilities;
-import android.os.Build;
-
-/** @hide */
-public class NetworkMonitorUtils {
- // This class is used by both NetworkMonitor and ConnectivityService, so it cannot use
- // NetworkStack shims, but at the same time cannot use non-system APIs.
- // TRANSPORT_TEST is test API as of R (so it is enforced to always be 7 and can't be changed),
- // and it is being added as a system API in S.
- // TODO: use NetworkCapabilities.TRANSPORT_TEST once NetworkStack builds against API 31.
- private static final int TRANSPORT_TEST = 7;
-
- // This class is used by both NetworkMonitor and ConnectivityService, so it cannot use
- // NetworkStack shims, but at the same time cannot use non-system APIs.
- // NET_CAPABILITY_NOT_VCN_MANAGED is system API as of S (so it is enforced to always be 28 and
- // can't be changed).
- // TODO: use NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED once NetworkStack builds against
- // API 31.
- public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
-
- // Network conditions broadcast constants
- public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
- "android.net.conn.NETWORK_CONDITIONS_MEASURED";
- public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
- public static final String EXTRA_NETWORK_TYPE = "extra_network_type";
- public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received";
- public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal";
- public static final String EXTRA_CELL_ID = "extra_cellid";
- public static final String EXTRA_SSID = "extra_ssid";
- public static final String EXTRA_BSSID = "extra_bssid";
- /** real time since boot */
- public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms";
- public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms";
- public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
- "android.permission.ACCESS_NETWORK_CONDITIONS";
-
- /**
- * Return whether validation is required for private DNS in strict mode.
- * @param nc Network capabilities of the network to test.
- */
- public static boolean isPrivateDnsValidationRequired(@NonNull final NetworkCapabilities nc) {
- final boolean isVcnManaged = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
- && !nc.hasCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
- final boolean isOemPaid = nc.hasCapability(NET_CAPABILITY_OEM_PAID)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED);
- final boolean isDefaultCapable = nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED);
-
- // TODO: Consider requiring validation for DUN networks.
- if (nc.hasCapability(NET_CAPABILITY_INTERNET)
- && (isVcnManaged || isOemPaid || isDefaultCapable)) {
- return true;
- }
-
- // Test networks that also have one of the major transport types are attempting to replicate
- // that transport on a test interface (for example, test ethernet networks with
- // EthernetManager#setIncludeTestInterfaces). Run validation on them for realistic tests.
- // See also comments on EthernetManager#setIncludeTestInterfaces and on TestNetworkManager.
- if (nc.hasTransport(TRANSPORT_TEST) && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) && (
- nc.hasTransport(TRANSPORT_WIFI)
- || nc.hasTransport(TRANSPORT_CELLULAR)
- || nc.hasTransport(TRANSPORT_BLUETOOTH)
- || nc.hasTransport(TRANSPORT_ETHERNET))) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Return whether validation is required for a network.
- * @param isVpnValidationRequired Whether network validation should be performed for VPN
- * networks.
- * @param nc Network capabilities of the network to test.
- */
- public static boolean isValidationRequired(boolean isDunValidationRequired,
- boolean isVpnValidationRequired,
- @NonNull final NetworkCapabilities nc) {
- if (isDunValidationRequired && nc.hasCapability(NET_CAPABILITY_DUN)) {
- return true;
- }
- if (!nc.hasCapability(NET_CAPABILITY_NOT_VPN)) {
- return isVpnValidationRequired;
- }
- return isPrivateDnsValidationRequired(nc);
- }
-}
diff --git a/common/device/com/android/net/module/util/PacketBuilder.java b/common/device/com/android/net/module/util/PacketBuilder.java
deleted file mode 100644
index 33e5bfad..00000000
--- a/common/device/com/android/net/module/util/PacketBuilder.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.system.OsConstants.IPPROTO_IP;
-import static android.system.OsConstants.IPPROTO_IPV6;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-import static com.android.net.module.util.IpUtils.ipChecksum;
-import static com.android.net.module.util.IpUtils.tcpChecksum;
-import static com.android.net.module.util.IpUtils.udpChecksum;
-import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
-import static com.android.net.module.util.NetworkStackConstants.IPV6_LEN_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.TCP_CHECKSUM_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.UDP_CHECKSUM_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.UDP_LENGTH_OFFSET;
-
-import android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.structs.EthernetHeader;
-import com.android.net.module.util.structs.Ipv4Header;
-import com.android.net.module.util.structs.Ipv6Header;
-import com.android.net.module.util.structs.TcpHeader;
-import com.android.net.module.util.structs.UdpHeader;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-
-/**
- * The class is used to build a packet.
- *
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Layer 2 header (EthernetHeader) | (optional)
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Layer 3 header (Ipv4Header, Ipv6Header) |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Layer 4 header (TcpHeader, UdpHeader) |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Payload | (optional)
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * Below is a sample code to build a packet.
- *
- * // Initialize builder
- * final ByteBuffer buf = ByteBuffer.allocate(...);
- * final PacketBuilder pb = new PacketBuilder(buf);
- * // Write headers
- * pb.writeL2Header(...);
- * pb.writeIpHeader(...);
- * pb.writeTcpHeader(...);
- * // Write payload
- * buf.putInt(...);
- * buf.putShort(...);
- * buf.putByte(...);
- * // Finalize and use the packet
- * pb.finalizePacket();
- * sendPacket(buf);
- */
-public class PacketBuilder {
- private static final int INVALID_OFFSET = -1;
-
- private final ByteBuffer mBuffer;
-
- private int mIpv4HeaderOffset = INVALID_OFFSET;
- private int mIpv6HeaderOffset = INVALID_OFFSET;
- private int mTcpHeaderOffset = INVALID_OFFSET;
- private int mUdpHeaderOffset = INVALID_OFFSET;
-
- public PacketBuilder(@NonNull ByteBuffer buffer) {
- mBuffer = buffer;
- }
-
- /**
- * Write an ethernet header.
- *
- * @param srcMac source MAC address
- * @param dstMac destination MAC address
- * @param etherType ether type
- */
- public void writeL2Header(MacAddress srcMac, MacAddress dstMac, short etherType) throws
- IOException {
- final EthernetHeader ethHeader = new EthernetHeader(dstMac, srcMac, etherType);
- try {
- ethHeader.writeToByteBuffer(mBuffer);
- } catch (IllegalArgumentException | BufferOverflowException e) {
- throw new IOException("Error writing to buffer: ", e);
- }
- }
-
- /**
- * Write an IPv4 header.
- * The IP header length and checksum are calculated and written back in #finalizePacket.
- *
- * @param tos type of service
- * @param id the identification
- * @param flagsAndFragmentOffset flags and fragment offset
- * @param ttl time to live
- * @param protocol protocol
- * @param srcIp source IP address
- * @param dstIp destination IP address
- */
- public void writeIpv4Header(byte tos, short id, short flagsAndFragmentOffset, byte ttl,
- byte protocol, @NonNull final Inet4Address srcIp, @NonNull final Inet4Address dstIp)
- throws IOException {
- mIpv4HeaderOffset = mBuffer.position();
- final Ipv4Header ipv4Header = new Ipv4Header(tos,
- (short) 0 /* totalLength, calculate in #finalizePacket */, id,
- flagsAndFragmentOffset, ttl, protocol,
- (short) 0 /* checksum, calculate in #finalizePacket */, srcIp, dstIp);
-
- try {
- ipv4Header.writeToByteBuffer(mBuffer);
- } catch (IllegalArgumentException | BufferOverflowException e) {
- throw new IOException("Error writing to buffer: ", e);
- }
- }
-
- /**
- * Write an IPv6 header.
- * The IP header length is calculated and written back in #finalizePacket.
- *
- * @param vtf version, traffic class and flow label
- * @param nextHeader the transport layer protocol
- * @param hopLimit hop limit
- * @param srcIp source IP address
- * @param dstIp destination IP address
- */
- public void writeIpv6Header(int vtf, byte nextHeader, short hopLimit,
- @NonNull final Inet6Address srcIp, @NonNull final Inet6Address dstIp)
- throws IOException {
- mIpv6HeaderOffset = mBuffer.position();
- final Ipv6Header ipv6Header = new Ipv6Header(vtf,
- (short) 0 /* payloadLength, calculate in #finalizePacket */, nextHeader,
- hopLimit, srcIp, dstIp);
-
- try {
- ipv6Header.writeToByteBuffer(mBuffer);
- } catch (IllegalArgumentException | BufferOverflowException e) {
- throw new IOException("Error writing to buffer: ", e);
- }
- }
-
- /**
- * Write a TCP header.
- * The TCP header checksum is calculated and written back in #finalizePacket.
- *
- * @param srcPort source port
- * @param dstPort destination port
- * @param seq sequence number
- * @param ack acknowledgement number
- * @param tcpFlags tcp flags
- * @param window window size
- * @param urgentPointer urgent pointer
- */
- public void writeTcpHeader(short srcPort, short dstPort, short seq, short ack,
- byte tcpFlags, short window, short urgentPointer) throws IOException {
- mTcpHeaderOffset = mBuffer.position();
- final TcpHeader tcpHeader = new TcpHeader(srcPort, dstPort, seq, ack,
- (short) ((short) 0x5000 | ((byte) 0x3f & tcpFlags)) /* dataOffsetAndControlBits,
- dataOffset is always 5(*4bytes) because options not supported */, window,
- (short) 0 /* checksum, calculate in #finalizePacket */,
- urgentPointer);
-
- try {
- tcpHeader.writeToByteBuffer(mBuffer);
- } catch (IllegalArgumentException | BufferOverflowException e) {
- throw new IOException("Error writing to buffer: ", e);
- }
- }
-
- /**
- * Write a UDP header.
- * The UDP header length and checksum are calculated and written back in #finalizePacket.
- *
- * @param srcPort source port
- * @param dstPort destination port
- */
- public void writeUdpHeader(short srcPort, short dstPort) throws IOException {
- mUdpHeaderOffset = mBuffer.position();
- final UdpHeader udpHeader = new UdpHeader(srcPort, dstPort,
- (short) 0 /* length, calculate in #finalizePacket */,
- (short) 0 /* checksum, calculate in #finalizePacket */);
-
- try {
- udpHeader.writeToByteBuffer(mBuffer);
- } catch (IllegalArgumentException | BufferOverflowException e) {
- throw new IOException("Error writing to buffer: ", e);
- }
- }
-
- /**
- * Finalize the packet.
- *
- * Call after writing L4 header (no payload) or payload to the buffer used by the builder.
- * L3 header length, L3 header checksum and L4 header checksum are calculated and written back
- * after finalization.
- */
- @NonNull
- public ByteBuffer finalizePacket() throws IOException {
- // [1] Finalize IPv4 or IPv6 header.
- int ipHeaderOffset = INVALID_OFFSET;
- if (mIpv4HeaderOffset != INVALID_OFFSET) {
- ipHeaderOffset = mIpv4HeaderOffset;
-
- // Populate the IPv4 totalLength field.
- mBuffer.putShort(mIpv4HeaderOffset + IPV4_LENGTH_OFFSET,
- (short) (mBuffer.position() - mIpv4HeaderOffset));
-
- // Populate the IPv4 header checksum field.
- mBuffer.putShort(mIpv4HeaderOffset + IPV4_CHECKSUM_OFFSET,
- ipChecksum(mBuffer, mIpv4HeaderOffset /* headerOffset */));
- } else if (mIpv6HeaderOffset != INVALID_OFFSET) {
- ipHeaderOffset = mIpv6HeaderOffset;
-
- // Populate the IPv6 payloadLength field.
- // The payload length doesn't include IPv6 header length. See rfc8200 section 3.
- mBuffer.putShort(mIpv6HeaderOffset + IPV6_LEN_OFFSET,
- (short) (mBuffer.position() - mIpv6HeaderOffset - IPV6_HEADER_LEN));
- } else {
- throw new IOException("Packet is missing neither IPv4 nor IPv6 header");
- }
-
- // [2] Finalize TCP or UDP header.
- if (mTcpHeaderOffset != INVALID_OFFSET) {
- // Populate the TCP header checksum field.
- mBuffer.putShort(mTcpHeaderOffset + TCP_CHECKSUM_OFFSET, tcpChecksum(mBuffer,
- ipHeaderOffset /* ipOffset */, mTcpHeaderOffset /* transportOffset */,
- mBuffer.position() - mTcpHeaderOffset /* transportLen */));
- } else if (mUdpHeaderOffset != INVALID_OFFSET) {
- // Populate the UDP header length field.
- mBuffer.putShort(mUdpHeaderOffset + UDP_LENGTH_OFFSET,
- (short) (mBuffer.position() - mUdpHeaderOffset));
-
- // Populate the UDP header checksum field.
- mBuffer.putShort(mUdpHeaderOffset + UDP_CHECKSUM_OFFSET, udpChecksum(mBuffer,
- ipHeaderOffset /* ipOffset */, mUdpHeaderOffset /* transportOffset */));
- } else {
- throw new IOException("Packet is missing neither TCP nor UDP header");
- }
-
- mBuffer.flip();
- return mBuffer;
- }
-
- /**
- * Allocate bytebuffer for building the packet.
- *
- * @param hasEther has ethernet header. Set this flag to indicate that the packet has an
- * ethernet header.
- * @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
- * currently supported.
- * @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
- * currently supported.
- * @param payloadLen length of the payload.
- */
- @NonNull
- public static ByteBuffer allocate(boolean hasEther, int l3proto, int l4proto, int payloadLen) {
- if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
- throw new IllegalArgumentException("Unsupported layer 3 protocol " + l3proto);
- }
-
- if (l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP) {
- throw new IllegalArgumentException("Unsupported layer 4 protocol " + l4proto);
- }
-
- if (payloadLen < 0) {
- throw new IllegalArgumentException("Invalid payload length " + payloadLen);
- }
-
- int packetLen = 0;
- if (hasEther) packetLen += Struct.getSize(EthernetHeader.class);
- packetLen += (l3proto == IPPROTO_IP) ? Struct.getSize(Ipv4Header.class)
- : Struct.getSize(Ipv6Header.class);
- packetLen += (l4proto == IPPROTO_TCP) ? Struct.getSize(TcpHeader.class)
- : Struct.getSize(UdpHeader.class);
- packetLen += payloadLen;
-
- return ByteBuffer.allocate(packetLen);
- }
-}
diff --git a/common/device/com/android/net/module/util/PacketReader.java b/common/device/com/android/net/module/util/PacketReader.java
deleted file mode 100644
index 66c47888..00000000
--- a/common/device/com/android/net/module/util/PacketReader.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static java.lang.Math.max;
-
-import android.os.Handler;
-import android.system.Os;
-
-import java.io.FileDescriptor;
-
-/**
- * Specialization of {@link FdEventsReader} that reads packets into a byte array.
- *
- * TODO: rename this class to something more correctly descriptive (something
- * like [or less horrible than] FdReadEventsHandler?).
- */
-public abstract class PacketReader extends FdEventsReader<byte[]> {
-
- public static final int DEFAULT_RECV_BUF_SIZE = 2 * 1024;
-
- protected PacketReader(Handler h) {
- this(h, DEFAULT_RECV_BUF_SIZE);
- }
-
- protected PacketReader(Handler h, int recvBufSize) {
- super(h, new byte[max(recvBufSize, DEFAULT_RECV_BUF_SIZE)]);
- }
-
- @Override
- protected final int recvBufSize(byte[] buffer) {
- return buffer.length;
- }
-
- /**
- * Subclasses MAY override this to change the default read() implementation
- * in favour of, say, recvfrom().
- *
- * Implementations MUST return the bytes read or throw an Exception.
- */
- @Override
- protected int readPacket(FileDescriptor fd, byte[] packetBuffer) throws Exception {
- return Os.read(fd, packetBuffer, 0, packetBuffer.length);
- }
-}
diff --git a/common/device/com/android/net/module/util/SharedLog.java b/common/device/com/android/net/module/util/SharedLog.java
deleted file mode 100644
index 6b12c80d..00000000
--- a/common/device/com/android/net/module/util/SharedLog.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.time.LocalDateTime;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.StringJoiner;
-
-
-/**
- * Class to centralize logging functionality for tethering.
- *
- * All access to class methods other than dump() must be on the same thread.
- *
- * @hide
- */
-public class SharedLog {
- private static final int DEFAULT_MAX_RECORDS = 500;
- private static final String COMPONENT_DELIMITER = ".";
-
- private enum Category {
- NONE,
- ERROR,
- MARK,
- WARN,
- VERBOSE,
- TERRIBLE,
- }
-
- private final LocalLog mLocalLog;
- // The tag to use for output to the system log. This is not output to the
- // LocalLog because that would be redundant.
- private final String mTag;
- // The component (or subcomponent) of a system that is sharing this log.
- // This can grow in depth if components call forSubComponent() to obtain
- // their SharedLog instance. The tag is not included in the component for
- // brevity.
- private final String mComponent;
-
- public SharedLog(String tag) {
- this(DEFAULT_MAX_RECORDS, tag);
- }
-
- public SharedLog(int maxRecords, String tag) {
- this(new LocalLog(maxRecords), tag, tag);
- }
-
- private SharedLog(LocalLog localLog, String tag, String component) {
- mLocalLog = localLog;
- mTag = tag;
- mComponent = component;
- }
-
- public String getTag() {
- return mTag;
- }
-
- /**
- * Create a SharedLog based on this log with an additional component prefix on each logged line.
- */
- public SharedLog forSubComponent(String component) {
- if (!isRootLogInstance()) {
- component = mComponent + COMPONENT_DELIMITER + component;
- }
- return new SharedLog(mLocalLog, mTag, component);
- }
-
- /**
- * Dump the contents of this log.
- *
- * <p>This method may be called on any thread.
- */
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mLocalLog.dump(writer);
- }
-
- /**
- * Reverse dump the contents of this log.
- *
- * <p>This method may be called on any thread.
- */
- public void reverseDump(PrintWriter writer) {
- mLocalLog.reverseDump(writer);
- }
-
- //////
- // Methods that both log an entry and emit it to the system log.
- //////
-
- /**
- * Log an error due to an exception. This does not include the exception stacktrace.
- *
- * <p>The log entry will be also added to the system log.
- * @see #e(String, Throwable)
- */
- public void e(Exception e) {
- Log.e(mTag, record(Category.ERROR, e.toString()));
- }
-
- /**
- * Log an error message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void e(String msg) {
- Log.e(mTag, record(Category.ERROR, msg));
- }
-
- /**
- * Log an error due to an exception, with the exception stacktrace if provided.
- *
- * <p>The error and exception message appear in the shared log, but the stacktrace is only
- * logged in general log output (logcat). The log entry will be also added to the system log.
- */
- public void e(@NonNull String msg, @Nullable Throwable exception) {
- if (exception == null) {
- e(msg);
- return;
- }
- Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception);
- }
-
- /**
- * Log an informational message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void i(String msg) {
- Log.i(mTag, record(Category.NONE, msg));
- }
-
- /**
- * Log a warning message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void w(String msg) {
- Log.w(mTag, record(Category.WARN, msg));
- }
-
- /**
- * Log a verbose message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void v(String msg) {
- Log.v(mTag, record(Category.VERBOSE, msg));
- }
-
- /**
- * Log a terrible failure message.
- *
- * <p>The log entry will be also added to the system log and will trigger system reporting
- * for terrible failures.
- */
- public void wtf(String msg) {
- Log.wtf(mTag, record(Category.TERRIBLE, msg));
- }
-
- /**
- * Log a terrible failure due to an exception, with the exception stacktrace if provided.
- *
- * <p>The error and exception message appear in the shared log, but the stacktrace is only
- * logged in general log output (logcat). The log entry will be also added to the system log
- * and will trigger system reporting for terrible failures.
- */
- public void wtf(@NonNull String msg, @Nullable Throwable exception) {
- if (exception == null) {
- e(msg);
- return;
- }
- Log.wtf(mTag, record(Category.TERRIBLE, msg + ": " + exception.getMessage()), exception);
- }
-
-
- //////
- // Methods that only log an entry (and do NOT emit to the system log).
- //////
-
- /**
- * Log a general message to be only included in the in-memory log.
- *
- * <p>The log entry will *not* be added to the system log.
- */
- public void log(String msg) {
- record(Category.NONE, msg);
- }
-
- /**
- * Log a general, formatted message to be only included in the in-memory log.
- *
- * <p>The log entry will *not* be added to the system log.
- * @see String#format(String, Object...)
- */
- public void logf(String fmt, Object... args) {
- log(String.format(fmt, args));
- }
-
- /**
- * Log a message with MARK level.
- *
- * <p>The log entry will *not* be added to the system log.
- */
- public void mark(String msg) {
- record(Category.MARK, msg);
- }
-
- private String record(Category category, String msg) {
- final String entry = logLine(category, msg);
- mLocalLog.append(entry);
- return entry;
- }
-
- private String logLine(Category category, String msg) {
- final StringJoiner sj = new StringJoiner(" ");
- if (!isRootLogInstance()) sj.add("[" + mComponent + "]");
- if (category != Category.NONE) sj.add(category.toString());
- return sj.add(msg).toString();
- }
-
- // Check whether this SharedLog instance is nominally the top level in
- // a potential hierarchy of shared logs (the root of a tree),
- // or is a subcomponent within the hierarchy.
- private boolean isRootLogInstance() {
- return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
- }
-
- private static final class LocalLog {
- private final Deque<String> mLog;
- private final int mMaxLines;
-
- LocalLog(int maxLines) {
- mMaxLines = Math.max(0, maxLines);
- mLog = new ArrayDeque<>(mMaxLines);
- }
-
- synchronized void append(String logLine) {
- if (mMaxLines <= 0) return;
- while (mLog.size() >= mMaxLines) {
- mLog.remove();
- }
- mLog.add(LocalDateTime.now() + " - " + logLine);
- }
-
- /**
- * Dumps the content of local log to print writer with each log entry
- *
- * @param pw printer writer to write into
- */
- synchronized void dump(PrintWriter pw) {
- for (final String s : mLog) {
- pw.println(s);
- }
- }
-
- synchronized void reverseDump(PrintWriter pw) {
- final Iterator<String> itr = mLog.descendingIterator();
- while (itr.hasNext()) {
- pw.println(itr.next());
- }
- }
- }
-}
diff --git a/common/device/com/android/net/module/util/SocketUtils.java b/common/device/com/android/net/module/util/SocketUtils.java
deleted file mode 100644
index 9878ea5c..00000000
--- a/common/device/com/android/net/module/util/SocketUtils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import static android.net.util.SocketUtils.closeSocket;
-
-import android.annotation.NonNull;
-import android.system.NetlinkSocketAddress;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.SocketAddress;
-
-/**
- * Collection of utilities to interact with raw sockets.
- *
- * This class also provides utilities to interact with {@link android.net.util.SocketUtils}
- * because it is in the API surface could not be simply move the frameworks/libs/net/
- * to share with module.
- *
- * TODO: deprecate android.net.util.SocketUtils and replace with this class.
- */
-public class SocketUtils {
-
- /**
- * Make a socket address to communicate with netlink.
- */
- @NonNull
- public static SocketAddress makeNetlinkSocketAddress(int portId, int groupsMask) {
- return new NetlinkSocketAddress(portId, groupsMask);
- }
-
- /**
- * Close a socket, ignoring any exception while closing.
- */
- public static void closeSocketQuietly(FileDescriptor fd) {
- try {
- closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
-
- private SocketUtils() {}
-}
diff --git a/common/device/com/android/net/module/util/Struct.java b/common/device/com/android/net/module/util/Struct.java
deleted file mode 100644
index b638a461..00000000
--- a/common/device/com/android/net/module/util/Struct.java
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.math.BigInteger;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Define a generic class that helps to parse the structured message.
- *
- * Example usage:
- *
- * // C-style NduserOption message header definition in the kernel:
- * struct nduseroptmsg {
- * unsigned char nduseropt_family;
- * unsigned char nduseropt_pad1;
- * unsigned short nduseropt_opts_len;
- * int nduseropt_ifindex;
- * __u8 nduseropt_icmp_type;
- * __u8 nduseropt_icmp_code;
- * unsigned short nduseropt_pad2;
- * unsigned int nduseropt_pad3;
- * }
- *
- * - Declare a subclass with explicit constructor or not which extends from this class to parse
- * NduserOption header from raw bytes array.
- *
- * - Option w/ explicit constructor:
- * static class NduserOptHeaderMessage extends Struct {
- * @Field(order = 0, type = Type.U8, padding = 1)
- * final short family;
- * @Field(order = 1, type = Type.U16)
- * final int len;
- * @Field(order = 2, type = Type.S32)
- * final int ifindex;
- * @Field(order = 3, type = Type.U8)
- * final short type;
- * @Field(order = 4, type = Type.U8, padding = 6)
- * final short code;
- *
- * NduserOptHeaderMessage(final short family, final int len, final int ifindex,
- * final short type, final short code) {
- * this.family = family;
- * this.len = len;
- * this.ifindex = ifindex;
- * this.type = type;
- * this.code = code;
- * }
- * }
- *
- * - Option w/o explicit constructor:
- * static class NduserOptHeaderMessage extends Struct {
- * @Field(order = 0, type = Type.U8, padding = 1)
- * short family;
- * @Field(order = 1, type = Type.U16)
- * int len;
- * @Field(order = 2, type = Type.S32)
- * int ifindex;
- * @Field(order = 3, type = Type.U8)
- * short type;
- * @Field(order = 4, type = Type.U8, padding = 6)
- * short code;
- * }
- *
- * - Parse the target message and refer the members.
- * final ByteBuffer buf = ByteBuffer.wrap(RAW_BYTES_ARRAY);
- * buf.order(ByteOrder.nativeOrder());
- * final NduserOptHeaderMessage nduserHdrMsg = Struct.parse(NduserOptHeaderMessage.class, buf);
- * assertEquals(10, nduserHdrMsg.family);
- */
-public class Struct {
- public enum Type {
- U8, // unsigned byte, size = 1 byte
- U16, // unsigned short, size = 2 bytes
- U32, // unsigned int, size = 4 bytes
- U63, // unsigned long(MSB: 0), size = 8 bytes
- U64, // unsigned long, size = 8 bytes
- S8, // signed byte, size = 1 byte
- S16, // signed short, size = 2 bytes
- S32, // signed int, size = 4 bytes
- S64, // signed long, size = 8 bytes
- UBE16, // unsigned short in network order, size = 2 bytes
- UBE32, // unsigned int in network order, size = 4 bytes
- UBE63, // unsigned long(MSB: 0) in network order, size = 8 bytes
- UBE64, // unsigned long in network order, size = 8 bytes
- ByteArray, // byte array with predefined length
- EUI48, // IEEE Extended Unique Identifier, a 48-bits long MAC address in network order
- Ipv4Address, // IPv4 address in network order
- Ipv6Address, // IPv6 address in network order
- }
-
- /**
- * Indicate that the field marked with this annotation will automatically be managed by this
- * class (e.g., will be parsed by #parse).
- *
- * order: The placeholder associated with each field, consecutive order starting from zero.
- * type: The primitive data type listed in above Type enumeration.
- * padding: Padding bytes appear after the field for alignment.
- * arraysize: The length of byte array.
- *
- * Annotation associated with field MUST have order and type properties at least, padding
- * and arraysize properties depend on the specific usage, if these properties are absent,
- * then default value 0 will be applied.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public @interface Field {
- int order();
- Type type();
- int padding() default 0;
- int arraysize() default 0;
- }
-
- private static class FieldInfo {
- @NonNull
- public final Field annotation;
- @NonNull
- public final java.lang.reflect.Field field;
-
- FieldInfo(final Field annotation, final java.lang.reflect.Field field) {
- this.annotation = annotation;
- this.field = field;
- }
- }
- private static ConcurrentHashMap<Class, FieldInfo[]> sFieldCache = new ConcurrentHashMap();
-
- private static void checkAnnotationType(final Field annotation, final Class fieldType) {
- switch (annotation.type()) {
- case U8:
- case S16:
- if (fieldType == Short.TYPE) return;
- break;
- case U16:
- case S32:
- case UBE16:
- if (fieldType == Integer.TYPE) return;
- break;
- case U32:
- case U63:
- case S64:
- case UBE32:
- case UBE63:
- if (fieldType == Long.TYPE) return;
- break;
- case U64:
- case UBE64:
- if (fieldType == BigInteger.class) return;
- break;
- case S8:
- if (fieldType == Byte.TYPE) return;
- break;
- case ByteArray:
- if (fieldType != byte[].class) break;
- if (annotation.arraysize() <= 0) {
- throw new IllegalArgumentException("Invalid ByteArray size: "
- + annotation.arraysize());
- }
- return;
- case EUI48:
- if (fieldType == MacAddress.class) return;
- break;
- case Ipv4Address:
- if (fieldType == Inet4Address.class) return;
- break;
- case Ipv6Address:
- if (fieldType == Inet6Address.class) return;
- break;
- default:
- throw new IllegalArgumentException("Unknown type" + annotation.type());
- }
- throw new IllegalArgumentException("Invalid primitive data type: " + fieldType
- + " for annotation type: " + annotation.type());
- }
-
- private static int getFieldLength(final Field annotation) {
- int length = 0;
- switch (annotation.type()) {
- case U8:
- case S8:
- length = 1;
- break;
- case U16:
- case S16:
- case UBE16:
- length = 2;
- break;
- case U32:
- case S32:
- case UBE32:
- length = 4;
- break;
- case U63:
- case U64:
- case S64:
- case UBE63:
- case UBE64:
- length = 8;
- break;
- case ByteArray:
- length = annotation.arraysize();
- break;
- case EUI48:
- length = 6;
- break;
- case Ipv4Address:
- length = 4;
- break;
- case Ipv6Address:
- length = 16;
- break;
- default:
- throw new IllegalArgumentException("Unknown type" + annotation.type());
- }
- return length + annotation.padding();
- }
-
- private static boolean isStructSubclass(final Class clazz) {
- return clazz != null && Struct.class.isAssignableFrom(clazz) && Struct.class != clazz;
- }
-
- private static int getAnnotationFieldCount(final Class clazz) {
- int count = 0;
- for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
- if (field.isAnnotationPresent(Field.class)) count++;
- }
- return count;
- }
-
- private static boolean allFieldsFinal(final FieldInfo[] fields, boolean immutable) {
- for (FieldInfo fi : fields) {
- if (Modifier.isFinal(fi.field.getModifiers()) != immutable) return false;
- }
- return true;
- }
-
- private static boolean hasBothMutableAndImmutableFields(final FieldInfo[] fields) {
- return !allFieldsFinal(fields, true /* immutable */)
- && !allFieldsFinal(fields, false /* mutable */);
- }
-
- private static boolean matchConstructor(final Constructor cons, final FieldInfo[] fields) {
- final Class[] paramTypes = cons.getParameterTypes();
- if (paramTypes.length != fields.length) return false;
- for (int i = 0; i < paramTypes.length; i++) {
- if (!paramTypes[i].equals(fields[i].field.getType())) return false;
- }
- return true;
- }
-
- /**
- * Read U64/UBE64 type data from ByteBuffer and output a BigInteger instance.
- *
- * @param buf The byte buffer to read.
- * @param type The annotation type.
- *
- * The magnitude argument of BigInteger constructor is a byte array in big-endian order.
- * If BigInteger data is read from the byte buffer in little-endian, reverse the order of
- * the bytes is required; if BigInteger data is read from the byte buffer in big-endian,
- * then just keep it as-is.
- */
- private static BigInteger readBigInteger(final ByteBuffer buf, final Type type) {
- final byte[] input = new byte[8];
- boolean reverseBytes = (type == Type.U64 && buf.order() == ByteOrder.LITTLE_ENDIAN);
- for (int i = 0; i < 8; i++) {
- input[reverseBytes ? input.length - 1 - i : i] = buf.get();
- }
- return new BigInteger(1, input);
- }
-
- /**
- * Get the last 8 bytes of a byte array. If there are less than 8 bytes,
- * the first bytes are replaced with zeroes.
- */
- private static byte[] getLast8Bytes(final byte[] input) {
- final byte[] tmp = new byte[8];
- System.arraycopy(
- input,
- Math.max(0, input.length - 8), // srcPos: read at most last 8 bytes
- tmp,
- Math.max(0, 8 - input.length), // dstPos: pad output with that many zeroes
- Math.min(8, input.length)); // length
- return tmp;
- }
-
- /**
- * Convert U64/UBE64 type data interpreted by BigInteger class to bytes array, output are
- * always 8 bytes.
- *
- * @param bigInteger The number to convert.
- * @param order Indicate ByteBuffer is read as little-endian or big-endian.
- * @param type The annotation U64 type.
- *
- * BigInteger#toByteArray returns a byte array containing the 2's complement representation
- * of this BigInteger, in big-endian. If annotation type is U64 and ByteBuffer is read as
- * little-endian, then reversing the order of the bytes is required.
- */
- private static byte[] bigIntegerToU64Bytes(final BigInteger bigInteger, final ByteOrder order,
- final Type type) {
- final byte[] bigIntegerBytes = bigInteger.toByteArray();
- final byte[] output = getLast8Bytes(bigIntegerBytes);
-
- if (type == Type.U64 && order == ByteOrder.LITTLE_ENDIAN) {
- for (int i = 0; i < 4; i++) {
- byte tmp = output[i];
- output[i] = output[7 - i];
- output[7 - i] = tmp;
- }
- }
- return output;
- }
-
- private static Object getFieldValue(final ByteBuffer buf, final FieldInfo fieldInfo)
- throws BufferUnderflowException {
- final Object value;
- checkAnnotationType(fieldInfo.annotation, fieldInfo.field.getType());
- switch (fieldInfo.annotation.type()) {
- case U8:
- value = (short) (buf.get() & 0xFF);
- break;
- case U16:
- value = (int) (buf.getShort() & 0xFFFF);
- break;
- case U32:
- value = (long) (buf.getInt() & 0xFFFFFFFFL);
- break;
- case U64:
- value = readBigInteger(buf, Type.U64);
- break;
- case S8:
- value = buf.get();
- break;
- case S16:
- value = buf.getShort();
- break;
- case S32:
- value = buf.getInt();
- break;
- case U63:
- case S64:
- value = buf.getLong();
- break;
- case UBE16:
- if (buf.order() == ByteOrder.LITTLE_ENDIAN) {
- value = (int) (Short.reverseBytes(buf.getShort()) & 0xFFFF);
- } else {
- value = (int) (buf.getShort() & 0xFFFF);
- }
- break;
- case UBE32:
- if (buf.order() == ByteOrder.LITTLE_ENDIAN) {
- value = (long) (Integer.reverseBytes(buf.getInt()) & 0xFFFFFFFFL);
- } else {
- value = (long) (buf.getInt() & 0xFFFFFFFFL);
- }
- break;
- case UBE63:
- if (buf.order() == ByteOrder.LITTLE_ENDIAN) {
- value = Long.reverseBytes(buf.getLong());
- } else {
- value = buf.getLong();
- }
- break;
- case UBE64:
- value = readBigInteger(buf, Type.UBE64);
- break;
- case ByteArray:
- final byte[] array = new byte[fieldInfo.annotation.arraysize()];
- buf.get(array);
- value = array;
- break;
- case EUI48:
- final byte[] macAddress = new byte[6];
- buf.get(macAddress);
- value = MacAddress.fromBytes(macAddress);
- break;
- case Ipv4Address:
- case Ipv6Address:
- final boolean isIpv6 = (fieldInfo.annotation.type() == Type.Ipv6Address);
- final byte[] address = new byte[isIpv6 ? 16 : 4];
- buf.get(address);
- try {
- value = InetAddress.getByAddress(address);
- } catch (UnknownHostException e) {
- throw new IllegalArgumentException("illegal length of IP address", e);
- }
- break;
- default:
- throw new IllegalArgumentException("Unknown type:" + fieldInfo.annotation.type());
- }
-
- // Skip the padding data for alignment if any.
- if (fieldInfo.annotation.padding() > 0) {
- buf.position(buf.position() + fieldInfo.annotation.padding());
- }
- return value;
- }
-
- @Nullable
- private Object getFieldValue(@NonNull java.lang.reflect.Field field) {
- try {
- return field.get(this);
- } catch (IllegalAccessException e) {
- throw new IllegalStateException("Cannot access field: " + field, e);
- }
- }
-
- private static void putFieldValue(final ByteBuffer output, final FieldInfo fieldInfo,
- final Object value) throws BufferUnderflowException {
- switch (fieldInfo.annotation.type()) {
- case U8:
- output.put((byte) (((short) value) & 0xFF));
- break;
- case U16:
- output.putShort((short) (((int) value) & 0xFFFF));
- break;
- case U32:
- output.putInt((int) (((long) value) & 0xFFFFFFFFL));
- break;
- case U63:
- output.putLong((long) value);
- break;
- case U64:
- output.put(bigIntegerToU64Bytes((BigInteger) value, output.order(), Type.U64));
- break;
- case S8:
- output.put((byte) value);
- break;
- case S16:
- output.putShort((short) value);
- break;
- case S32:
- output.putInt((int) value);
- break;
- case S64:
- output.putLong((long) value);
- break;
- case UBE16:
- if (output.order() == ByteOrder.LITTLE_ENDIAN) {
- output.putShort(Short.reverseBytes((short) (((int) value) & 0xFFFF)));
- } else {
- output.putShort((short) (((int) value) & 0xFFFF));
- }
- break;
- case UBE32:
- if (output.order() == ByteOrder.LITTLE_ENDIAN) {
- output.putInt(Integer.reverseBytes(
- (int) (((long) value) & 0xFFFFFFFFL)));
- } else {
- output.putInt((int) (((long) value) & 0xFFFFFFFFL));
- }
- break;
- case UBE63:
- if (output.order() == ByteOrder.LITTLE_ENDIAN) {
- output.putLong(Long.reverseBytes((long) value));
- } else {
- output.putLong((long) value);
- }
- break;
- case UBE64:
- output.put(bigIntegerToU64Bytes((BigInteger) value, output.order(), Type.UBE64));
- break;
- case ByteArray:
- checkByteArraySize((byte[]) value, fieldInfo);
- output.put((byte[]) value);
- break;
- case EUI48:
- final byte[] macAddress = ((MacAddress) value).toByteArray();
- output.put(macAddress);
- break;
- case Ipv4Address:
- case Ipv6Address:
- final byte[] address = ((InetAddress) value).getAddress();
- output.put(address);
- break;
- default:
- throw new IllegalArgumentException("Unknown type:" + fieldInfo.annotation.type());
- }
-
- // padding zero after field value for alignment.
- for (int i = 0; i < fieldInfo.annotation.padding(); i++) output.put((byte) 0);
- }
-
- private static FieldInfo[] getClassFieldInfo(final Class clazz) {
- if (!isStructSubclass(clazz)) {
- throw new IllegalArgumentException(clazz.getName() + " is not a subclass of "
- + Struct.class.getName() + ", its superclass is "
- + clazz.getSuperclass().getName());
- }
-
- final FieldInfo[] cachedAnnotationFields = sFieldCache.get(clazz);
- if (cachedAnnotationFields != null) {
- return cachedAnnotationFields;
- }
-
- // Since array returned from Class#getDeclaredFields doesn't guarantee the actual order
- // of field appeared in the class, that is a problem when parsing raw data read from
- // ByteBuffer. Store the fields appeared by the order() defined in the Field annotation.
- final FieldInfo[] annotationFields = new FieldInfo[getAnnotationFieldCount(clazz)];
- for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
- if (Modifier.isStatic(field.getModifiers())) continue;
-
- final Field annotation = field.getAnnotation(Field.class);
- if (annotation == null) {
- throw new IllegalArgumentException("Field " + field.getName()
- + " is missing the " + Field.class.getSimpleName()
- + " annotation");
- }
- if (annotation.order() < 0 || annotation.order() >= annotationFields.length) {
- throw new IllegalArgumentException("Annotation order: " + annotation.order()
- + " is negative or non-consecutive");
- }
- if (annotationFields[annotation.order()] != null) {
- throw new IllegalArgumentException("Duplicated annotation order: "
- + annotation.order());
- }
- annotationFields[annotation.order()] = new FieldInfo(annotation, field);
- }
- sFieldCache.putIfAbsent(clazz, annotationFields);
- return annotationFields;
- }
-
- /**
- * Parse raw data from ByteBuffer according to the pre-defined annotation rule and return
- * the type-variable object which is subclass of Struct class.
- *
- * TODO:
- * 1. Support subclass inheritance.
- * 2. Introduce annotation processor to enforce the subclass naming schema.
- */
- public static <T> T parse(final Class<T> clazz, final ByteBuffer buf) {
- try {
- final FieldInfo[] foundFields = getClassFieldInfo(clazz);
- if (hasBothMutableAndImmutableFields(foundFields)) {
- throw new IllegalArgumentException("Class has both final and non-final fields");
- }
-
- Constructor<?> constructor = null;
- Constructor<?> defaultConstructor = null;
- final Constructor<?>[] constructors = clazz.getDeclaredConstructors();
- for (Constructor cons : constructors) {
- if (matchConstructor(cons, foundFields)) constructor = cons;
- if (cons.getParameterTypes().length == 0) defaultConstructor = cons;
- }
-
- if (constructor == null && defaultConstructor == null) {
- throw new IllegalArgumentException("Fail to find available constructor");
- }
- if (constructor != null) {
- final Object[] args = new Object[foundFields.length];
- for (int i = 0; i < args.length; i++) {
- args[i] = getFieldValue(buf, foundFields[i]);
- }
- return (T) constructor.newInstance(args);
- }
-
- final Object instance = defaultConstructor.newInstance();
- for (FieldInfo fi : foundFields) {
- fi.field.set(instance, getFieldValue(buf, fi));
- }
- return (T) instance;
- } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
- throw new IllegalArgumentException("Fail to create a instance from constructor", e);
- } catch (BufferUnderflowException e) {
- throw new IllegalArgumentException("Fail to read raw data from ByteBuffer", e);
- }
- }
-
- private static int getSizeInternal(final FieldInfo[] fieldInfos) {
- int size = 0;
- for (FieldInfo fi : fieldInfos) {
- size += getFieldLength(fi.annotation);
- }
- return size;
- }
-
- // Check whether the actual size of byte array matches the array size declared in
- // annotation. For other annotation types, the actual length of field could be always
- // deduced from annotation correctly.
- private static void checkByteArraySize(@Nullable final byte[] array,
- @NonNull final FieldInfo fieldInfo) {
- Objects.requireNonNull(array, "null byte array for field " + fieldInfo.field.getName());
- int annotationArraySize = fieldInfo.annotation.arraysize();
- if (array.length == annotationArraySize) return;
- throw new IllegalStateException("byte array actual length: "
- + array.length + " doesn't match the declared array size: " + annotationArraySize);
- }
-
- private void writeToByteBufferInternal(final ByteBuffer output, final FieldInfo[] fieldInfos) {
- for (FieldInfo fi : fieldInfos) {
- final Object value = getFieldValue(fi.field);
- try {
- putFieldValue(output, fi, value);
- } catch (BufferUnderflowException e) {
- throw new IllegalArgumentException("Fail to fill raw data to ByteBuffer", e);
- }
- }
- }
-
- /**
- * Get the size of Struct subclass object.
- */
- public static <T extends Struct> int getSize(final Class<T> clazz) {
- final FieldInfo[] fieldInfos = getClassFieldInfo(clazz);
- return getSizeInternal(fieldInfos);
- }
-
- /**
- * Convert the parsed Struct subclass object to ByteBuffer.
- *
- * @param output ByteBuffer passed-in from the caller.
- */
- public final void writeToByteBuffer(final ByteBuffer output) {
- final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass());
- writeToByteBufferInternal(output, fieldInfos);
- }
-
- /**
- * Convert the parsed Struct subclass object to byte array.
- *
- * @param order indicate ByteBuffer is outputted as little-endian or big-endian.
- */
- public final byte[] writeToBytes(final ByteOrder order) {
- final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass());
- final byte[] output = new byte[getSizeInternal(fieldInfos)];
- final ByteBuffer buffer = ByteBuffer.wrap(output);
- buffer.order(order);
- writeToByteBufferInternal(buffer, fieldInfos);
- return output;
- }
-
- /** Convert the parsed Struct subclass object to byte array with native order. */
- public final byte[] writeToBytes() {
- return writeToBytes(ByteOrder.nativeOrder());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || this.getClass() != obj.getClass()) return false;
-
- final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass());
- for (int i = 0; i < fieldInfos.length; i++) {
- try {
- final Object value = fieldInfos[i].field.get(this);
- final Object otherValue = fieldInfos[i].field.get(obj);
-
- // Use Objects#deepEquals because the equals method on arrays does not check the
- // contents of the array. The only difference between Objects#deepEquals and
- // Objects#equals is that the former will call Arrays#deepEquals when comparing
- // arrays. In turn, the only difference between Arrays#deepEquals is that it
- // supports nested arrays. Struct does not currently support these, and if it did,
- // Objects#deepEquals might be more correct.
- if (!Objects.deepEquals(value, otherValue)) return false;
- } catch (IllegalAccessException e) {
- throw new IllegalStateException("Cannot access field: " + fieldInfos[i].field, e);
- }
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass());
- final Object[] values = new Object[fieldInfos.length];
- for (int i = 0; i < fieldInfos.length; i++) {
- final Object value = getFieldValue(fieldInfos[i].field);
- // For byte array field, put the hash code generated based on the array content into
- // the Object array instead of the reference to byte array, which might change and cause
- // to get a different hash code even with the exact same elements.
- if (fieldInfos[i].field.getType() == byte[].class) {
- values[i] = Arrays.hashCode((byte[]) value);
- } else {
- values[i] = value;
- }
- }
- return Objects.hash(values);
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass());
- for (int i = 0; i < fieldInfos.length; i++) {
- sb.append(fieldInfos[i].field.getName()).append(": ");
- final Object value = getFieldValue(fieldInfos[i].field);
- if (value == null) {
- sb.append("null");
- } else if (fieldInfos[i].annotation.type() == Type.ByteArray) {
- sb.append("0x").append(HexDump.toHexString((byte[]) value));
- } else if (fieldInfos[i].annotation.type() == Type.Ipv4Address
- || fieldInfos[i].annotation.type() == Type.Ipv6Address) {
- sb.append(((InetAddress) value).getHostAddress());
- } else {
- sb.append(value.toString());
- }
- if (i != fieldInfos.length - 1) sb.append(", ");
- }
- return sb.toString();
- }
-
- /** A simple Struct which only contains a u8 field. */
- public static class U8 extends Struct {
- @Struct.Field(order = 0, type = Struct.Type.U8)
- public final short val;
-
- public U8(final short val) {
- this.val = val;
- }
- }
-
- /** A simple Struct which only contains an s32 field. */
- public static class S32 extends Struct {
- @Struct.Field(order = 0, type = Struct.Type.S32)
- public final int val;
-
- public S32(final int val) {
- this.val = val;
- }
- }
-
- /** A simple Struct which only contains a u32 field. */
- public static class U32 extends Struct {
- @Struct.Field(order = 0, type = Struct.Type.U32)
- public final long val;
-
- public U32(final long val) {
- this.val = val;
- }
- }
-
- /** A simple Struct which only contains an s64 field. */
- public static class S64 extends Struct {
- @Struct.Field(order = 0, type = Struct.Type.S64)
- public final long val;
-
- public S64(final long val) {
- this.val = val;
- }
- }
-}
diff --git a/common/device/com/android/net/module/util/TcUtils.java b/common/device/com/android/net/module/util/TcUtils.java
deleted file mode 100644
index 9d2fb7f9..00000000
--- a/common/device/com/android/net/module/util/TcUtils.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util;
-
-import java.io.IOException;
-
-/**
- * Contains mostly tc-related functionality.
- */
-public class TcUtils {
- static {
- System.loadLibrary(JniUtil.getJniLibraryName(TcUtils.class.getPackage()));
- }
-
- /**
- * Checks if the network interface uses an ethernet L2 header.
- *
- * @param iface the network interface.
- * @return true if the interface uses an ethernet L2 header.
- * @throws IOException
- */
- public static native boolean isEthernet(String iface) throws IOException;
-
- /**
- * Attach a tc bpf filter.
- *
- * Equivalent to the following 'tc' command:
- * tc filter add dev .. in/egress prio .. protocol ipv6/ip bpf object-pinned
- * /sys/fs/bpf/... direct-action
- *
- * @param ifIndex the network interface index.
- * @param ingress ingress or egress qdisc.
- * @param prio
- * @param proto
- * @param bpfProgPath
- * @throws IOException
- */
- public static native void tcFilterAddDevBpf(int ifIndex, boolean ingress, short prio,
- short proto, String bpfProgPath) throws IOException;
-
- /**
- * Attach a tc police action.
- *
- * Attaches a matchall filter to the clsact qdisc with a tc police and tc bpf action attached.
- * This causes the ingress rate to be limited and exceeding packets to be forwarded to a bpf
- * program (specified in bpfProgPah) that accounts for the packets before dropping them.
- *
- * Equivalent to the following 'tc' command:
- * tc filter add dev .. ingress prio .. protocol .. matchall \
- * action police rate .. burst .. conform-exceed pipe/continue \
- * action bpf object-pinned .. \
- * drop
- *
- * @param ifIndex the network interface index.
- * @param prio the filter preference.
- * @param proto protocol.
- * @param rateInBytesPerSec rate limit in bytes/s.
- * @param bpfProgPath bpg program that accounts for rate exceeding packets before they are
- * dropped.
- * @throws IOException
- */
- public static native void tcFilterAddDevIngressPolice(int ifIndex, short prio, short proto,
- int rateInBytesPerSec, String bpfProgPath) throws IOException;
-
- /**
- * Delete a tc filter.
- *
- * Equivalent to the following 'tc' command:
- * tc filter del dev .. in/egress prio .. protocol ..
- *
- * @param ifIndex the network interface index.
- * @param ingress ingress or egress qdisc.
- * @param prio the filter preference.
- * @param proto protocol.
- * @throws IOException
- */
- public static native void tcFilterDelDev(int ifIndex, boolean ingress, short prio,
- short proto) throws IOException;
-
- /**
- * Add a clsact qdisc.
- *
- * Equivalent to the following 'tc' command:
- * tc qdisc add dev .. clsact
- *
- * @param ifIndex the network interface index.
- * @throws IOException
- */
- public static native void tcQdiscAddDevClsact(int ifIndex) throws IOException;
-}
diff --git a/common/device/com/android/net/module/util/arp/ArpPacket.java b/common/device/com/android/net/module/util/arp/ArpPacket.java
deleted file mode 100644
index dab9694b..00000000
--- a/common/device/com/android/net/module/util/arp/ArpPacket.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.arp;
-
-import static android.system.OsConstants.ETH_P_ARP;
-import static android.system.OsConstants.ETH_P_IP;
-
-import static com.android.net.module.util.NetworkStackConstants.ARP_ETHER_IPV4_LEN;
-import static com.android.net.module.util.NetworkStackConstants.ARP_HWTYPE_ETHER;
-import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY;
-import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST;
-import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN;
-import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_LEN;
-
-import android.net.MacAddress;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-
-/**
- * Defines basic data and operations needed to build and parse packets for the
- * ARP protocol.
- *
- * @hide
- */
-public class ArpPacket {
- private static final String TAG = "ArpPacket";
-
- public final short opCode;
- public final Inet4Address senderIp;
- public final Inet4Address targetIp;
- public final MacAddress senderHwAddress;
- public final MacAddress targetHwAddress;
-
- ArpPacket(short opCode, MacAddress senderHwAddress, Inet4Address senderIp,
- MacAddress targetHwAddress, Inet4Address targetIp) {
- this.opCode = opCode;
- this.senderHwAddress = senderHwAddress;
- this.senderIp = senderIp;
- this.targetHwAddress = targetHwAddress;
- this.targetIp = targetIp;
- }
-
- /**
- * Build an ARP packet from the required specified parameters.
- */
- @VisibleForTesting
- public static ByteBuffer buildArpPacket(final byte[] dstMac, final byte[] srcMac,
- final byte[] targetIp, final byte[] targetHwAddress, byte[] senderIp,
- final short opCode) {
- final ByteBuffer buf = ByteBuffer.allocate(ARP_ETHER_IPV4_LEN);
-
- // Ether header
- buf.put(dstMac);
- buf.put(srcMac);
- buf.putShort((short) ETH_P_ARP);
-
- // ARP header
- buf.putShort((short) ARP_HWTYPE_ETHER); // hrd
- buf.putShort((short) ETH_P_IP); // pro
- buf.put((byte) ETHER_ADDR_LEN); // hln
- buf.put((byte) IPV4_ADDR_LEN); // pln
- buf.putShort(opCode); // op
- buf.put(srcMac); // sha
- buf.put(senderIp); // spa
- buf.put(targetHwAddress); // tha
- buf.put(targetIp); // tpa
- buf.flip();
- return buf;
- }
-
- /**
- * Parse an ARP packet from a ByteBuffer object.
- */
- @VisibleForTesting
- public static ArpPacket parseArpPacket(final byte[] recvbuf, final int length)
- throws ParseException {
- try {
- if (length < ARP_ETHER_IPV4_LEN || recvbuf.length < length) {
- throw new ParseException("Invalid packet length: " + length);
- }
-
- final ByteBuffer buffer = ByteBuffer.wrap(recvbuf, 0, length);
- byte[] l2dst = new byte[ETHER_ADDR_LEN];
- byte[] l2src = new byte[ETHER_ADDR_LEN];
- buffer.get(l2dst);
- buffer.get(l2src);
-
- final short etherType = buffer.getShort();
- if (etherType != ETH_P_ARP) {
- throw new ParseException("Incorrect Ether Type: " + etherType);
- }
-
- final short hwType = buffer.getShort();
- if (hwType != ARP_HWTYPE_ETHER) {
- throw new ParseException("Incorrect HW Type: " + hwType);
- }
-
- final short protoType = buffer.getShort();
- if (protoType != ETH_P_IP) {
- throw new ParseException("Incorrect Protocol Type: " + protoType);
- }
-
- final byte hwAddrLength = buffer.get();
- if (hwAddrLength != ETHER_ADDR_LEN) {
- throw new ParseException("Incorrect HW address length: " + hwAddrLength);
- }
-
- final byte ipAddrLength = buffer.get();
- if (ipAddrLength != IPV4_ADDR_LEN) {
- throw new ParseException("Incorrect Protocol address length: " + ipAddrLength);
- }
-
- final short opCode = buffer.getShort();
- if (opCode != ARP_REQUEST && opCode != ARP_REPLY) {
- throw new ParseException("Incorrect opCode: " + opCode);
- }
-
- byte[] senderHwAddress = new byte[ETHER_ADDR_LEN];
- byte[] senderIp = new byte[IPV4_ADDR_LEN];
- buffer.get(senderHwAddress);
- buffer.get(senderIp);
-
- byte[] targetHwAddress = new byte[ETHER_ADDR_LEN];
- byte[] targetIp = new byte[IPV4_ADDR_LEN];
- buffer.get(targetHwAddress);
- buffer.get(targetIp);
-
- return new ArpPacket(opCode, MacAddress.fromBytes(senderHwAddress),
- (Inet4Address) InetAddress.getByAddress(senderIp),
- MacAddress.fromBytes(targetHwAddress),
- (Inet4Address) InetAddress.getByAddress(targetIp));
- } catch (IndexOutOfBoundsException e) {
- throw new ParseException("Invalid index when wrapping a byte array into a buffer");
- } catch (BufferUnderflowException e) {
- throw new ParseException("Invalid buffer position");
- } catch (IllegalArgumentException e) {
- throw new ParseException("Invalid MAC address representation");
- } catch (UnknownHostException e) {
- throw new ParseException("Invalid IP address of Host");
- }
- }
-
- /**
- * Thrown when parsing ARP packet failed.
- */
- public static class ParseException extends Exception {
- ParseException(String message) {
- super(message);
- }
- }
-}
diff --git a/common/device/com/android/net/module/util/async/Assertions.java b/common/device/com/android/net/module/util/async/Assertions.java
deleted file mode 100644
index ce701d05..00000000
--- a/common/device/com/android/net/module/util/async/Assertions.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import android.os.Build;
-
-/**
- * Implements basic assert functions for runtime error-checking.
- *
- * @hide
- */
-public final class Assertions {
- public static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
-
- public static void throwsIfOutOfBounds(int totalLength, int pos, int len) {
- if (!IS_USER_BUILD && ((totalLength | pos | len) < 0 || pos > totalLength - len)) {
- throw new ArrayIndexOutOfBoundsException(
- "length=" + totalLength + "; regionStart=" + pos + "; regionLength=" + len);
- }
- }
-
- public static void throwsIfOutOfBounds(byte[] buffer, int pos, int len) {
- throwsIfOutOfBounds(buffer != null ? buffer.length : 0, pos, len);
- }
-
- private Assertions() {}
-}
diff --git a/common/device/com/android/net/module/util/async/AsyncFile.java b/common/device/com/android/net/module/util/async/AsyncFile.java
deleted file mode 100644
index 2a3231b7..00000000
--- a/common/device/com/android/net/module/util/async/AsyncFile.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import java.io.IOException;
-
-/**
- * Represents an EventManager-managed file with Async IO semantics.
- *
- * Implements level-based Asyn IO semantics. This means that:
- * - onReadReady() callback would keep happening as long as there's any remaining
- * data to read, or the user calls enableReadEvents(false)
- * - onWriteReady() callback would keep happening as long as there's remaining space
- * to write to, or the user calls enableWriteEvents(false)
- *
- * All operations except close() must be called on the EventManager thread.
- *
- * @hide
- */
-public interface AsyncFile {
- /**
- * Receives notifications when file readability or writeability changes.
- * @hide
- */
- public interface Listener {
- /** Invoked after the underlying file has been closed. */
- void onClosed(AsyncFile file);
-
- /** Invoked while the file has readable data and read notifications are enabled. */
- void onReadReady(AsyncFile file);
-
- /** Invoked while the file has writeable space and write notifications are enabled. */
- void onWriteReady(AsyncFile file);
- }
-
- /** Requests this file to be closed. */
- void close();
-
- /** Enables or disables onReadReady() events. */
- void enableReadEvents(boolean enable);
-
- /** Enables or disables onWriteReady() events. */
- void enableWriteEvents(boolean enable);
-
- /** Returns true if the input stream has reached its end, or has been closed. */
- boolean reachedEndOfFile();
-
- /**
- * Reads available data from the given non-blocking file descriptor.
- *
- * Returns zero if there's no data to read at this moment.
- * Returns -1 if the file has reached its end or the input stream has been closed.
- * Otherwise returns the number of bytes read.
- */
- int read(byte[] buffer, int pos, int len) throws IOException;
-
- /**
- * Writes data into the given non-blocking file descriptor.
- *
- * Returns zero if there's no buffer space to write to at this moment.
- * Otherwise returns the number of bytes written.
- */
- int write(byte[] buffer, int pos, int len) throws IOException;
-}
diff --git a/common/device/com/android/net/module/util/async/BufferedFile.java b/common/device/com/android/net/module/util/async/BufferedFile.java
deleted file mode 100644
index bb5736b0..00000000
--- a/common/device/com/android/net/module/util/async/BufferedFile.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Buffers inbound and outbound file data within given strict limits.
- *
- * Automatically manages all readability and writeability events in EventManager:
- * - When read buffer has more space - asks EventManager to notify on more data
- * - When write buffer has more space - asks the user to provide more data
- * - When underlying file cannot accept more data - registers EventManager callback
- *
- * @hide
- */
-public final class BufferedFile implements AsyncFile.Listener {
- /**
- * Receives notifications when new data or output space is available.
- * @hide
- */
- public interface Listener {
- /** Invoked after the underlying file has been closed. */
- void onBufferedFileClosed();
-
- /** Invoked when there's new data in the inbound buffer. */
- void onBufferedFileInboundData(int readByteCount);
-
- /** Notifies on data being flushed from output buffer. */
- void onBufferedFileOutboundSpace();
-
- /** Notifies on unrecoverable error in file access. */
- void onBufferedFileIoError(String message);
- }
-
- private final Listener mListener;
- private final EventManager mEventManager;
- private AsyncFile mFile;
-
- private final CircularByteBuffer mInboundBuffer;
- private final AtomicLong mTotalBytesRead = new AtomicLong();
- private boolean mIsReadingShutdown;
-
- private final CircularByteBuffer mOutboundBuffer;
- private final AtomicLong mTotalBytesWritten = new AtomicLong();
-
- /** Creates BufferedFile based on the given file descriptor. */
- public static BufferedFile create(
- EventManager eventManager,
- FileHandle fileHandle,
- Listener listener,
- int inboundBufferSize,
- int outboundBufferSize) throws IOException {
- if (fileHandle == null) {
- throw new NullPointerException();
- }
- BufferedFile file = new BufferedFile(
- eventManager, listener, inboundBufferSize, outboundBufferSize);
- file.mFile = eventManager.registerFile(fileHandle, file);
- return file;
- }
-
- private BufferedFile(
- EventManager eventManager,
- Listener listener,
- int inboundBufferSize,
- int outboundBufferSize) {
- if (eventManager == null || listener == null) {
- throw new NullPointerException();
- }
- mEventManager = eventManager;
- mListener = listener;
-
- mInboundBuffer = new CircularByteBuffer(inboundBufferSize);
- mOutboundBuffer = new CircularByteBuffer(outboundBufferSize);
- }
-
- /** Requests this file to be closed. */
- public void close() {
- mFile.close();
- }
-
- @Override
- public void onClosed(AsyncFile file) {
- mListener.onBufferedFileClosed();
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // READ PATH
- ///////////////////////////////////////////////////////////////////////////
-
- /** Returns buffer that is automatically filled with inbound data. */
- public ReadableByteBuffer getInboundBuffer() {
- return mInboundBuffer;
- }
-
- public int getInboundBufferFreeSizeForTest() {
- return mInboundBuffer.freeSize();
- }
-
- /** Permanently disables reading of this file, and clears all buffered data. */
- public void shutdownReading() {
- mIsReadingShutdown = true;
- mInboundBuffer.clear();
- mFile.enableReadEvents(false);
- }
-
- /** Returns true after shutdownReading() has been called. */
- public boolean isReadingShutdown() {
- return mIsReadingShutdown;
- }
-
- /** Starts or resumes async read operations on this file. */
- public void continueReading() {
- if (!mIsReadingShutdown && mInboundBuffer.freeSize() > 0) {
- mFile.enableReadEvents(true);
- }
- }
-
- @Override
- public void onReadReady(AsyncFile file) {
- if (mIsReadingShutdown) {
- return;
- }
-
- int readByteCount;
- try {
- readByteCount = bufferInputData();
- } catch (IOException e) {
- mListener.onBufferedFileIoError("IOException while reading: " + e.toString());
- return;
- }
-
- if (readByteCount > 0) {
- mListener.onBufferedFileInboundData(readByteCount);
- }
-
- continueReading();
- }
-
- private int bufferInputData() throws IOException {
- int totalReadCount = 0;
- while (true) {
- final int maxReadCount = mInboundBuffer.getDirectWriteSize();
- if (maxReadCount == 0) {
- mFile.enableReadEvents(false);
- break;
- }
-
- final int bufferOffset = mInboundBuffer.getDirectWritePos();
- final byte[] buffer = mInboundBuffer.getDirectWriteBuffer();
-
- final int readCount = mFile.read(buffer, bufferOffset, maxReadCount);
- if (readCount <= 0) {
- break;
- }
-
- mInboundBuffer.accountForDirectWrite(readCount);
- totalReadCount += readCount;
- }
-
- mTotalBytesRead.addAndGet(totalReadCount);
- return totalReadCount;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // WRITE PATH
- ///////////////////////////////////////////////////////////////////////////
-
- /** Returns the number of bytes currently buffered for output. */
- public int getOutboundBufferSize() {
- return mOutboundBuffer.size();
- }
-
- /** Returns the number of bytes currently available for buffering for output. */
- public int getOutboundBufferFreeSize() {
- return mOutboundBuffer.freeSize();
- }
-
- /**
- * Queues the given data for output.
- * Throws runtime exception if there is not enough space.
- */
- public boolean enqueueOutboundData(byte[] data, int pos, int len) {
- return enqueueOutboundData(data, pos, len, null, 0, 0);
- }
-
- /**
- * Queues data1, then data2 for output.
- * Throws runtime exception if there is not enough space.
- */
- public boolean enqueueOutboundData(
- byte[] data1, int pos1, int len1,
- byte[] buffer2, int pos2, int len2) {
- Assertions.throwsIfOutOfBounds(data1, pos1, len1);
- Assertions.throwsIfOutOfBounds(buffer2, pos2, len2);
-
- final int totalLen = len1 + len2;
-
- if (totalLen > mOutboundBuffer.freeSize()) {
- flushOutboundBuffer();
-
- if (totalLen > mOutboundBuffer.freeSize()) {
- return false;
- }
- }
-
- mOutboundBuffer.writeBytes(data1, pos1, len1);
-
- if (buffer2 != null) {
- mOutboundBuffer.writeBytes(buffer2, pos2, len2);
- }
-
- flushOutboundBuffer();
-
- return true;
- }
-
- private void flushOutboundBuffer() {
- try {
- while (mOutboundBuffer.getDirectReadSize() > 0) {
- final int maxReadSize = mOutboundBuffer.getDirectReadSize();
- final int writeCount = mFile.write(
- mOutboundBuffer.getDirectReadBuffer(),
- mOutboundBuffer.getDirectReadPos(),
- maxReadSize);
-
- if (writeCount == 0) {
- mFile.enableWriteEvents(true);
- break;
- }
-
- if (writeCount > maxReadSize) {
- throw new IllegalArgumentException(
- "Write count " + writeCount + " above max " + maxReadSize);
- }
-
- mOutboundBuffer.accountForDirectRead(writeCount);
- }
- } catch (IOException e) {
- scheduleOnIoError("IOException while writing: " + e.toString());
- }
- }
-
- private void scheduleOnIoError(String message) {
- mEventManager.execute(() -> {
- mListener.onBufferedFileIoError(message);
- });
- }
-
- @Override
- public void onWriteReady(AsyncFile file) {
- mFile.enableWriteEvents(false);
- flushOutboundBuffer();
- mListener.onBufferedFileOutboundSpace();
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("file={");
- sb.append(mFile);
- sb.append("}");
- if (mIsReadingShutdown) {
- sb.append(", readingShutdown");
- }
- sb.append("}, inboundBuffer={");
- sb.append(mInboundBuffer);
- sb.append("}, outboundBuffer={");
- sb.append(mOutboundBuffer);
- sb.append("}, totalBytesRead=");
- sb.append(mTotalBytesRead);
- sb.append(", totalBytesWritten=");
- sb.append(mTotalBytesWritten);
- return sb.toString();
- }
-}
diff --git a/common/device/com/android/net/module/util/async/CircularByteBuffer.java b/common/device/com/android/net/module/util/async/CircularByteBuffer.java
deleted file mode 100644
index 92daa08f..00000000
--- a/common/device/com/android/net/module/util/async/CircularByteBuffer.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import java.util.Arrays;
-
-/**
- * Implements a circular read-write byte buffer.
- *
- * @hide
- */
-public final class CircularByteBuffer implements ReadableByteBuffer {
- private final byte[] mBuffer;
- private final int mCapacity;
- private int mReadPos;
- private int mWritePos;
- private int mSize;
-
- public CircularByteBuffer(int capacity) {
- mCapacity = capacity;
- mBuffer = new byte[mCapacity];
- }
-
- @Override
- public void clear() {
- mReadPos = 0;
- mWritePos = 0;
- mSize = 0;
- Arrays.fill(mBuffer, (byte) 0);
- }
-
- @Override
- public int capacity() {
- return mCapacity;
- }
-
- @Override
- public int size() {
- return mSize;
- }
-
- /** Returns the amount of remaining writeable space in this buffer. */
- public int freeSize() {
- return mCapacity - mSize;
- }
-
- @Override
- public byte peek(int offset) {
- if (offset < 0 || offset >= size()) {
- throw new IllegalArgumentException("Invalid offset=" + offset + ", size=" + size());
- }
-
- return mBuffer[(mReadPos + offset) % mCapacity];
- }
-
- @Override
- public void readBytes(byte[] dst, int dstPos, int dstLen) {
- if (dst != null) {
- Assertions.throwsIfOutOfBounds(dst, dstPos, dstLen);
- }
- if (dstLen > size()) {
- throw new IllegalArgumentException("Invalid len=" + dstLen + ", size=" + size());
- }
-
- while (dstLen > 0) {
- final int copyLen = getCopyLen(mReadPos, mWritePos, dstLen);
- if (dst != null) {
- System.arraycopy(mBuffer, mReadPos, dst, dstPos, copyLen);
- }
- dstPos += copyLen;
- dstLen -= copyLen;
- mSize -= copyLen;
- mReadPos = (mReadPos + copyLen) % mCapacity;
- }
-
- if (mSize == 0) {
- // Reset to the beginning for better contiguous access.
- mReadPos = 0;
- mWritePos = 0;
- }
- }
-
- @Override
- public void peekBytes(int offset, byte[] dst, int dstPos, int dstLen) {
- Assertions.throwsIfOutOfBounds(dst, dstPos, dstLen);
- if (offset + dstLen > size()) {
- throw new IllegalArgumentException("Invalid len=" + dstLen
- + ", offset=" + offset + ", size=" + size());
- }
-
- int tmpReadPos = (mReadPos + offset) % mCapacity;
- while (dstLen > 0) {
- final int copyLen = getCopyLen(tmpReadPos, mWritePos, dstLen);
- System.arraycopy(mBuffer, tmpReadPos, dst, dstPos, copyLen);
- dstPos += copyLen;
- dstLen -= copyLen;
- tmpReadPos = (tmpReadPos + copyLen) % mCapacity;
- }
- }
-
- @Override
- public int getDirectReadSize() {
- if (size() == 0) {
- return 0;
- }
- return (mReadPos < mWritePos ? (mWritePos - mReadPos) : (mCapacity - mReadPos));
- }
-
- @Override
- public int getDirectReadPos() {
- return mReadPos;
- }
-
- @Override
- public byte[] getDirectReadBuffer() {
- return mBuffer;
- }
-
- @Override
- public void accountForDirectRead(int len) {
- if (len < 0 || len > size()) {
- throw new IllegalArgumentException("Invalid len=" + len + ", size=" + size());
- }
-
- mSize -= len;
- mReadPos = (mReadPos + len) % mCapacity;
- }
-
- /** Copies given data to the end of the buffer. */
- public void writeBytes(byte[] buffer, int pos, int len) {
- Assertions.throwsIfOutOfBounds(buffer, pos, len);
- if (len > freeSize()) {
- throw new IllegalArgumentException("Invalid len=" + len + ", size=" + freeSize());
- }
-
- while (len > 0) {
- final int copyLen = getCopyLen(mWritePos, mReadPos,len);
- System.arraycopy(buffer, pos, mBuffer, mWritePos, copyLen);
- pos += copyLen;
- len -= copyLen;
- mSize += copyLen;
- mWritePos = (mWritePos + copyLen) % mCapacity;
- }
- }
-
- private int getCopyLen(int startPos, int endPos, int len) {
- if (startPos < endPos) {
- return Math.min(len, endPos - startPos);
- } else {
- return Math.min(len, mCapacity - startPos);
- }
- }
-
- /** Returns the amount of contiguous writeable space. */
- public int getDirectWriteSize() {
- if (freeSize() == 0) {
- return 0; // Return zero in case buffer is full.
- }
- return (mWritePos < mReadPos ? (mReadPos - mWritePos) : (mCapacity - mWritePos));
- }
-
- /** Returns the position of contiguous writeable space. */
- public int getDirectWritePos() {
- return mWritePos;
- }
-
- /** Returns the buffer reference for direct write operation. */
- public byte[] getDirectWriteBuffer() {
- return mBuffer;
- }
-
- /** Must be called after performing a direct write using getDirectWriteBuffer(). */
- public void accountForDirectWrite(int len) {
- if (len < 0 || len > freeSize()) {
- throw new IllegalArgumentException("Invalid len=" + len + ", size=" + freeSize());
- }
-
- mSize += len;
- mWritePos = (mWritePos + len) % mCapacity;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("CircularByteBuffer{c=");
- sb.append(mCapacity);
- sb.append(",s=");
- sb.append(mSize);
- sb.append(",r=");
- sb.append(mReadPos);
- sb.append(",w=");
- sb.append(mWritePos);
- sb.append('}');
- return sb.toString();
- }
-}
diff --git a/common/device/com/android/net/module/util/async/EventManager.java b/common/device/com/android/net/module/util/async/EventManager.java
deleted file mode 100644
index 4ed4a704..00000000
--- a/common/device/com/android/net/module/util/async/EventManager.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import java.io.IOException;
-import java.util.concurrent.Executor;
-
-/**
- * Manages Async IO files and scheduled alarms, and executes all related callbacks
- * in its own thread.
- *
- * All callbacks of AsyncFile, Alarm and EventManager will execute on EventManager's thread.
- *
- * Methods of this interface can be called from any thread.
- *
- * @hide
- */
-public interface EventManager extends Executor {
- /**
- * Represents a scheduled alarm, allowing caller to attempt to cancel that alarm
- * before it executes.
- *
- * @hide
- */
- public interface Alarm {
- /** @hide */
- public interface Listener {
- void onAlarm(Alarm alarm, long elapsedTimeMs);
- void onAlarmCancelled(Alarm alarm);
- }
-
- /**
- * Attempts to cancel this alarm. Note that this request is inherently
- * racy if executed close to the alarm's expiration time.
- */
- void cancel();
- }
-
- /**
- * Requests EventManager to manage the given file.
- *
- * The file descriptors are not cloned, and EventManager takes ownership of all files passed.
- *
- * No event callbacks are enabled by this method.
- */
- AsyncFile registerFile(FileHandle fileHandle, AsyncFile.Listener listener) throws IOException;
-
- /**
- * Schedules Alarm with the given timeout.
- *
- * Timeout of zero can be used for immediate execution.
- */
- Alarm scheduleAlarm(long timeout, Alarm.Listener callback);
-
- /** Schedules Runnable for immediate execution. */
- @Override
- void execute(Runnable callback);
-
- /** Throws a runtime exception if the caller is not executing on this EventManager's thread. */
- void assertInThread();
-}
diff --git a/common/device/com/android/net/module/util/async/FileHandle.java b/common/device/com/android/net/module/util/async/FileHandle.java
deleted file mode 100644
index 9f7942d4..00000000
--- a/common/device/com/android/net/module/util/async/FileHandle.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import android.os.ParcelFileDescriptor;
-
-import java.io.Closeable;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Represents an file descriptor or another way to access a file.
- *
- * @hide
- */
-public final class FileHandle {
- private final ParcelFileDescriptor mFd;
- private final Closeable mCloseable;
- private final InputStream mInputStream;
- private final OutputStream mOutputStream;
-
- public static FileHandle fromFileDescriptor(ParcelFileDescriptor fd) {
- if (fd == null) {
- throw new NullPointerException();
- }
- return new FileHandle(fd, null, null, null);
- }
-
- public static FileHandle fromBlockingStream(
- Closeable closeable, InputStream is, OutputStream os) {
- if (closeable == null || is == null || os == null) {
- throw new NullPointerException();
- }
- return new FileHandle(null, closeable, is, os);
- }
-
- private FileHandle(ParcelFileDescriptor fd, Closeable closeable,
- InputStream is, OutputStream os) {
- mFd = fd;
- mCloseable = closeable;
- mInputStream = is;
- mOutputStream = os;
- }
-
- ParcelFileDescriptor getFileDescriptor() {
- return mFd;
- }
-
- Closeable getCloseable() {
- return mCloseable;
- }
-
- InputStream getInputStream() {
- return mInputStream;
- }
-
- OutputStream getOutputStream() {
- return mOutputStream;
- }
-}
diff --git a/common/device/com/android/net/module/util/async/OsAccess.java b/common/device/com/android/net/module/util/async/OsAccess.java
deleted file mode 100644
index df0ded21..00000000
--- a/common/device/com/android/net/module/util/async/OsAccess.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-import android.os.ParcelFileDescriptor;
-import android.system.StructPollfd;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * Provides access to all relevant OS functions..
- *
- * @hide
- */
-public abstract class OsAccess {
- /** Closes the given file, suppressing IO exceptions. */
- public abstract void close(ParcelFileDescriptor fd);
-
- /** Returns file name for debugging purposes. */
- public abstract String getFileDebugName(ParcelFileDescriptor fd);
-
- /** Returns inner FileDescriptor instance. */
- public abstract FileDescriptor getInnerFileDescriptor(ParcelFileDescriptor fd);
-
- /**
- * Reads available data from the given non-blocking file descriptor.
- *
- * Returns zero if there's no data to read at this moment.
- * Returns -1 if the file has reached its end or the input stream has been closed.
- * Otherwise returns the number of bytes read.
- */
- public abstract int read(FileDescriptor fd, byte[] buffer, int pos, int len)
- throws IOException;
-
- /**
- * Writes data into the given non-blocking file descriptor.
- *
- * Returns zero if there's no buffer space to write to at this moment.
- * Otherwise returns the number of bytes written.
- */
- public abstract int write(FileDescriptor fd, byte[] buffer, int pos, int len)
- throws IOException;
-
- public abstract long monotonicTimeMillis();
- public abstract void setNonBlocking(FileDescriptor fd) throws IOException;
- public abstract ParcelFileDescriptor[] pipe() throws IOException;
-
- public abstract int poll(StructPollfd[] fds, int timeoutMs) throws IOException;
- public abstract short getPollInMask();
- public abstract short getPollOutMask();
-}
diff --git a/common/device/com/android/net/module/util/async/ReadableByteBuffer.java b/common/device/com/android/net/module/util/async/ReadableByteBuffer.java
deleted file mode 100644
index 7f824049..00000000
--- a/common/device/com/android/net/module/util/async/ReadableByteBuffer.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.async;
-
-/**
- * Allows reading from a buffer of bytes. The data can be read and thus removed,
- * or peeked at without disturbing the buffer state.
- *
- * @hide
- */
-public interface ReadableByteBuffer {
- /** Returns the size of the buffered data. */
- int size();
-
- /**
- * Returns the maximum amount of the buffered data.
- *
- * The caller may use this method in combination with peekBytes()
- * to estimate when the buffer needs to be emptied using readData().
- */
- int capacity();
-
- /** Clears all buffered data. */
- void clear();
-
- /** Returns a single byte at the given offset. */
- byte peek(int offset);
-
- /** Copies an array of bytes from the given offset to "dst". */
- void peekBytes(int offset, byte[] dst, int dstPos, int dstLen);
-
- /** Reads and removes an array of bytes from the head of the buffer. */
- void readBytes(byte[] dst, int dstPos, int dstLen);
-
- /** Returns the amount of contiguous readable data. */
- int getDirectReadSize();
-
- /** Returns the position of contiguous readable data. */
- int getDirectReadPos();
-
- /** Returns the buffer reference for direct read operation. */
- byte[] getDirectReadBuffer();
-
- /** Must be called after performing a direct read using getDirectReadBuffer(). */
- void accountForDirectRead(int len);
-}
diff --git a/common/device/com/android/net/module/util/ip/ConntrackMonitor.java b/common/device/com/android/net/module/util/ip/ConntrackMonitor.java
deleted file mode 100644
index 420a5446..00000000
--- a/common/device/com/android/net/module/util/ip/ConntrackMonitor.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.ip;
-
-import static com.android.net.module.util.netlink.ConntrackMessage.DYING_MASK;
-import static com.android.net.module.util.netlink.ConntrackMessage.ESTABLISHED_MASK;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-import android.system.OsConstants;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.SharedLog;
-import com.android.net.module.util.netlink.ConntrackMessage;
-import com.android.net.module.util.netlink.NetlinkConstants;
-import com.android.net.module.util.netlink.NetlinkMessage;
-
-import java.util.Objects;
-
-
-/**
- * ConntrackMonitor.
- *
- * Monitors the netfilter conntrack notifications and presents to callers
- * ConntrackEvents describing each event.
- *
- * @hide
- */
-public class ConntrackMonitor extends NetlinkMonitor {
- private static final String TAG = ConntrackMonitor.class.getSimpleName();
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- // Reference kernel/uapi/linux/netfilter/nfnetlink_compat.h
- public static final int NF_NETLINK_CONNTRACK_NEW = 1;
- public static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
- public static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
-
- // The socket receive buffer size in bytes. If too many conntrack messages are sent too
- // quickly, the conntrack messages can overflow the socket receive buffer. This can happen
- // if too many connections are disconnected by losing network and so on. Use a large-enough
- // buffer to avoid the error ENOBUFS while listening to the conntrack messages.
- private static final int SOCKET_RECV_BUFSIZE = 6 * 1024 * 1024;
-
- /**
- * A class for describing parsed netfilter conntrack events.
- */
- public static class ConntrackEvent {
- /**
- * Conntrack event type.
- */
- public final short msgType;
- /**
- * Original direction conntrack tuple.
- */
- public final ConntrackMessage.Tuple tupleOrig;
- /**
- * Reply direction conntrack tuple.
- */
- public final ConntrackMessage.Tuple tupleReply;
- /**
- * Connection status. A bitmask of ip_conntrack_status enum flags.
- */
- public final int status;
- /**
- * Conntrack timeout.
- */
- public final int timeoutSec;
-
- public ConntrackEvent(ConntrackMessage msg) {
- this.msgType = msg.getHeader().nlmsg_type;
- this.tupleOrig = msg.tupleOrig;
- this.tupleReply = msg.tupleReply;
- this.status = msg.status;
- this.timeoutSec = msg.timeoutSec;
- }
-
- @VisibleForTesting
- public ConntrackEvent(short msgType, ConntrackMessage.Tuple tupleOrig,
- ConntrackMessage.Tuple tupleReply, int status, int timeoutSec) {
- this.msgType = msgType;
- this.tupleOrig = tupleOrig;
- this.tupleReply = tupleReply;
- this.status = status;
- this.timeoutSec = timeoutSec;
- }
-
- @Override
- @VisibleForTesting
- public boolean equals(Object o) {
- if (!(o instanceof ConntrackEvent)) return false;
- ConntrackEvent that = (ConntrackEvent) o;
- return this.msgType == that.msgType
- && Objects.equals(this.tupleOrig, that.tupleOrig)
- && Objects.equals(this.tupleReply, that.tupleReply)
- && this.status == that.status
- && this.timeoutSec == that.timeoutSec;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(msgType, tupleOrig, tupleReply, status, timeoutSec);
- }
-
- @Override
- public String toString() {
- return "ConntrackEvent{"
- + "msg_type{"
- + NetlinkConstants.stringForNlMsgType(msgType, OsConstants.NETLINK_NETFILTER)
- + "}, "
- + "tuple_orig{" + tupleOrig + "}, "
- + "tuple_reply{" + tupleReply + "}, "
- + "status{"
- + status + "(" + ConntrackMessage.stringForIpConntrackStatus(status) + ")"
- + "}, "
- + "timeout_sec{" + Integer.toUnsignedLong(timeoutSec) + "}"
- + "}";
- }
-
- /**
- * Check the established NAT session conntrack message.
- *
- * @param msg the conntrack message to check.
- * @return true if an established NAT message, false if not.
- */
- public static boolean isEstablishedNatSession(@NonNull ConntrackMessage msg) {
- if (msg.getMessageType() != NetlinkConstants.IPCTNL_MSG_CT_NEW) return false;
- if (msg.tupleOrig == null) return false;
- if (msg.tupleReply == null) return false;
- if (msg.timeoutSec == 0) return false;
- if ((msg.status & ESTABLISHED_MASK) != ESTABLISHED_MASK) return false;
-
- return true;
- }
-
- /**
- * Check the dying NAT session conntrack message.
- * Note that IPCTNL_MSG_CT_DELETE event has no CTA_TIMEOUT attribute.
- *
- * @param msg the conntrack message to check.
- * @return true if a dying NAT message, false if not.
- */
- public static boolean isDyingNatSession(@NonNull ConntrackMessage msg) {
- if (msg.getMessageType() != NetlinkConstants.IPCTNL_MSG_CT_DELETE) return false;
- if (msg.tupleOrig == null) return false;
- if (msg.tupleReply == null) return false;
- if (msg.timeoutSec != 0) return false;
- if ((msg.status & DYING_MASK) != DYING_MASK) return false;
-
- return true;
- }
- }
-
- /**
- * A callback to caller for conntrack event.
- */
- public interface ConntrackEventConsumer {
- /**
- * Every conntrack event received on the netlink socket is passed in
- * here.
- */
- void accept(@NonNull ConntrackEvent event);
- }
-
- private final ConntrackEventConsumer mConsumer;
-
- public ConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log,
- @NonNull ConntrackEventConsumer cb) {
- super(h, log, TAG, OsConstants.NETLINK_NETFILTER, NF_NETLINK_CONNTRACK_NEW
- | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY, SOCKET_RECV_BUFSIZE);
- mConsumer = cb;
- }
-
- @Override
- public void processNetlinkMessage(NetlinkMessage nlMsg, final long whenMs) {
- if (!(nlMsg instanceof ConntrackMessage)) {
- mLog.e("non-conntrack msg: " + nlMsg);
- return;
- }
-
- final ConntrackMessage conntrackMsg = (ConntrackMessage) nlMsg;
- if (!(ConntrackEvent.isEstablishedNatSession(conntrackMsg)
- || ConntrackEvent.isDyingNatSession(conntrackMsg))) {
- return;
- }
-
- mConsumer.accept(new ConntrackEvent(conntrackMsg));
- }
-}
diff --git a/common/device/com/android/net/module/util/ip/InterfaceController.java b/common/device/com/android/net/module/util/ip/InterfaceController.java
deleted file mode 100644
index 7277fec0..00000000
--- a/common/device/com/android/net/module/util/ip/InterfaceController.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.ip;
-
-import static android.net.INetd.IF_STATE_DOWN;
-import static android.net.INetd.IF_STATE_UP;
-
-import android.net.INetd;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.OsConstants;
-
-import com.android.net.module.util.SharedLog;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-/**
- * Encapsulates the multiple IP configuration operations performed on an interface.
- *
- * TODO: refactor/eliminate the redundant ways to set and clear addresses.
- *
- * @hide
- */
-public class InterfaceController {
- private static final boolean DBG = false;
-
- private final String mIfName;
- private final INetd mNetd;
- private final SharedLog mLog;
-
- public InterfaceController(String ifname, INetd netd, SharedLog log) {
- mIfName = ifname;
- mNetd = netd;
- mLog = log;
- }
-
- /**
- * Set the IPv4 address and also optionally bring the interface up or down.
- */
- public boolean setInterfaceConfiguration(final LinkAddress ipv4Addr,
- final Boolean setIfaceUp) {
- if (!(ipv4Addr.getAddress() instanceof Inet4Address)) {
- throw new IllegalArgumentException("Invalid or mismatched Inet4Address");
- }
- // Note: currently netd only support INetd#IF_STATE_UP and #IF_STATE_DOWN.
- // Other flags would be ignored.
-
- final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
- ifConfig.ifName = mIfName;
- ifConfig.ipv4Addr = ipv4Addr.getAddress().getHostAddress();
- ifConfig.prefixLength = ipv4Addr.getPrefixLength();
- // Netd ignores hwaddr in interfaceSetCfg.
- ifConfig.hwAddr = "";
- if (setIfaceUp == null) {
- // Empty array means no change.
- ifConfig.flags = new String[0];
- } else {
- // Netd ignores any flag that's not IF_STATE_UP or IF_STATE_DOWN in interfaceSetCfg.
- ifConfig.flags = setIfaceUp.booleanValue()
- ? new String[] {IF_STATE_UP} : new String[] {IF_STATE_DOWN};
- }
- try {
- mNetd.interfaceSetCfg(ifConfig);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("Setting IPv4 address to %s/%d failed: %s",
- ifConfig.ipv4Addr, ifConfig.prefixLength, e);
- return false;
- }
- return true;
- }
-
- /**
- * Set the IPv4 address of the interface.
- */
- public boolean setIPv4Address(final LinkAddress address) {
- return setInterfaceConfiguration(address, null);
- }
-
- /**
- * Clear the IPv4Address of the interface.
- */
- public boolean clearIPv4Address() {
- return setIPv4Address(new LinkAddress("0.0.0.0/0"));
- }
-
- private boolean setEnableIPv6(boolean enabled) {
- try {
- mNetd.interfaceSetEnableIPv6(mIfName, enabled);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("%s IPv6 failed: %s", (enabled ? "enabling" : "disabling"), e);
- return false;
- }
- return true;
- }
-
- /**
- * Enable IPv6 on the interface.
- */
- public boolean enableIPv6() {
- return setEnableIPv6(true);
- }
-
- /**
- * Disable IPv6 on the interface.
- */
- public boolean disableIPv6() {
- return setEnableIPv6(false);
- }
-
- /**
- * Enable or disable IPv6 privacy extensions on the interface.
- * @param enabled Whether the extensions should be enabled.
- */
- public boolean setIPv6PrivacyExtensions(boolean enabled) {
- try {
- mNetd.interfaceSetIPv6PrivacyExtensions(mIfName, enabled);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("error %s IPv6 privacy extensions: %s",
- (enabled ? "enabling" : "disabling"), e);
- return false;
- }
- return true;
- }
-
- /**
- * Set IPv6 address generation mode on the interface.
- *
- * <p>IPv6 should be disabled before changing the mode.
- */
- public boolean setIPv6AddrGenModeIfSupported(int mode) {
- try {
- mNetd.setIPv6AddrGenMode(mIfName, mode);
- } catch (RemoteException e) {
- logError("Unable to set IPv6 addrgen mode: %s", e);
- return false;
- } catch (ServiceSpecificException e) {
- if (e.errorCode != OsConstants.EOPNOTSUPP) {
- logError("Unable to set IPv6 addrgen mode: %s", e);
- return false;
- }
- }
- return true;
- }
-
- /**
- * Add an address to the interface.
- */
- public boolean addAddress(LinkAddress addr) {
- return addAddress(addr.getAddress(), addr.getPrefixLength());
- }
-
- /**
- * Add an address to the interface.
- */
- public boolean addAddress(InetAddress ip, int prefixLen) {
- try {
- mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen);
- } catch (ServiceSpecificException | RemoteException e) {
- logError("failed to add %s/%d: %s", ip, prefixLen, e);
- return false;
- }
- return true;
- }
-
- /**
- * Remove an address from the interface.
- */
- public boolean removeAddress(InetAddress ip, int prefixLen) {
- try {
- mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen);
- } catch (ServiceSpecificException | RemoteException e) {
- logError("failed to remove %s/%d: %s", ip, prefixLen, e);
- return false;
- }
- return true;
- }
-
- /**
- * Remove all addresses from the interface.
- */
- public boolean clearAllAddresses() {
- try {
- mNetd.interfaceClearAddrs(mIfName);
- } catch (Exception e) {
- logError("Failed to clear addresses: %s", e);
- return false;
- }
- return true;
- }
-
- private void logError(String fmt, Object... args) {
- mLog.e(String.format(fmt, args));
- }
-}
diff --git a/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java b/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java
deleted file mode 100644
index e88e7f0c..00000000
--- a/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.ip;
-
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH;
-import static com.android.net.module.util.netlink.NetlinkConstants.hexify;
-import static com.android.net.module.util.netlink.NetlinkConstants.stringForNlMsgType;
-
-import android.annotation.NonNull;
-import android.net.MacAddress;
-import android.os.Handler;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.util.Log;
-
-import com.android.net.module.util.SharedLog;
-import com.android.net.module.util.netlink.NetlinkMessage;
-import com.android.net.module.util.netlink.NetlinkUtils;
-import com.android.net.module.util.netlink.RtNetlinkNeighborMessage;
-import com.android.net.module.util.netlink.StructNdMsg;
-
-import java.net.InetAddress;
-import java.util.StringJoiner;
-
-/**
- * IpNeighborMonitor.
- *
- * Monitors the kernel rtnetlink neighbor notifications and presents to callers
- * NeighborEvents describing each event. Callers can provide a consumer instance
- * to both filter (e.g. by interface index and IP address) and handle the
- * generated NeighborEvents.
- *
- * @hide
- */
-public class IpNeighborMonitor extends NetlinkMonitor {
- private static final String TAG = IpNeighborMonitor.class.getSimpleName();
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- /**
- * Make the kernel perform neighbor reachability detection (IPv4 ARP or IPv6 ND)
- * for the given IP address on the specified interface index.
- *
- * @return 0 if the request was successfully passed to the kernel; otherwise return
- * a non-zero error code.
- */
- public static int startKernelNeighborProbe(int ifIndex, InetAddress ip) {
- final String msgSnippet = "probing ip=" + ip.getHostAddress() + "%" + ifIndex;
- if (DBG) Log.d(TAG, msgSnippet);
-
- final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage(
- 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
-
- try {
- NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
- } catch (ErrnoException e) {
- Log.e(TAG, "Error " + msgSnippet + ": " + e);
- return -e.errno;
- }
-
- return 0;
- }
-
- /**
- * An event about a neighbor.
- */
- public static class NeighborEvent {
- public final long elapsedMs;
- public final short msgType;
- public final int ifindex;
- @NonNull
- public final InetAddress ip;
- public final short nudState;
- @NonNull
- public final MacAddress macAddr;
-
- public NeighborEvent(long elapsedMs, short msgType, int ifindex, @NonNull InetAddress ip,
- short nudState, @NonNull MacAddress macAddr) {
- this.elapsedMs = elapsedMs;
- this.msgType = msgType;
- this.ifindex = ifindex;
- this.ip = ip;
- this.nudState = nudState;
- this.macAddr = macAddr;
- }
-
- boolean isConnected() {
- return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
- }
-
- public boolean isValid() {
- return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
- }
-
- @Override
- public String toString() {
- final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
- return j.add("@" + elapsedMs)
- .add(stringForNlMsgType(msgType, NETLINK_ROUTE))
- .add("if=" + ifindex)
- .add(ip.getHostAddress())
- .add(StructNdMsg.stringForNudState(nudState))
- .add("[" + macAddr + "]")
- .toString();
- }
- }
-
- /**
- * A client that consumes NeighborEvent instances.
- * Implement this to listen to neighbor events.
- */
- public interface NeighborEventConsumer {
- // Every neighbor event received on the netlink socket is passed in
- // here. Subclasses should filter for events of interest.
- /**
- * Consume a neighbor event
- * @param event the event
- */
- void accept(NeighborEvent event);
- }
-
- private final NeighborEventConsumer mConsumer;
-
- public IpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb) {
- super(h, log, TAG, NETLINK_ROUTE, OsConstants.RTMGRP_NEIGH);
- mConsumer = (cb != null) ? cb : (event) -> { /* discard */ };
- }
-
- @Override
- public void processNetlinkMessage(NetlinkMessage nlMsg, final long whenMs) {
- if (!(nlMsg instanceof RtNetlinkNeighborMessage)) {
- mLog.e("non-rtnetlink neighbor msg: " + nlMsg);
- return;
- }
-
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) nlMsg;
- final short msgType = neighMsg.getHeader().nlmsg_type;
- final StructNdMsg ndMsg = neighMsg.getNdHeader();
- if (ndMsg == null) {
- mLog.e("RtNetlinkNeighborMessage without ND message header!");
- return;
- }
-
- final int ifindex = ndMsg.ndm_ifindex;
- final InetAddress destination = neighMsg.getDestination();
- final short nudState =
- (msgType == RTM_DELNEIGH)
- ? StructNdMsg.NUD_NONE
- : ndMsg.ndm_state;
-
- final NeighborEvent event = new NeighborEvent(
- whenMs, msgType, ifindex, destination, nudState,
- getMacAddress(neighMsg.getLinkLayerAddress()));
-
- if (VDBG) {
- Log.d(TAG, neighMsg.toString());
- }
- if (DBG) {
- Log.d(TAG, event.toString());
- }
-
- mConsumer.accept(event);
- }
-
- private static MacAddress getMacAddress(byte[] linkLayerAddress) {
- if (linkLayerAddress != null) {
- try {
- return MacAddress.fromBytes(linkLayerAddress);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Failed to parse link-layer address: " + hexify(linkLayerAddress));
- }
- }
-
- return null;
- }
-}
diff --git a/common/device/com/android/net/module/util/ip/NetlinkMonitor.java b/common/device/com/android/net/module/util/ip/NetlinkMonitor.java
deleted file mode 100644
index f882483d..00000000
--- a/common/device/com/android/net/module/util/ip/NetlinkMonitor.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.ip;
-
-import static android.system.OsConstants.AF_NETLINK;
-import static android.system.OsConstants.ENOBUFS;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_NONBLOCK;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVBUF;
-
-import static com.android.net.module.util.SocketUtils.closeSocketQuietly;
-import static com.android.net.module.util.SocketUtils.makeNetlinkSocketAddress;
-import static com.android.net.module.util.netlink.NetlinkConstants.hexify;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Log;
-
-import com.android.net.module.util.PacketReader;
-import com.android.net.module.util.SharedLog;
-import com.android.net.module.util.netlink.NetlinkErrorMessage;
-import com.android.net.module.util.netlink.NetlinkMessage;
-import com.android.net.module.util.netlink.NetlinkUtils;
-
-import java.io.FileDescriptor;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A simple base class to listen for netlink broadcasts.
- *
- * Opens a netlink socket of the given family and binds to the specified groups. Polls the socket
- * from the event loop of the passed-in {@link Handler}, and calls the subclass-defined
- * {@link #processNetlinkMessage} method on the handler thread for each netlink message that
- * arrives. Currently ignores all netlink errors.
- * @hide
- */
-public class NetlinkMonitor extends PacketReader {
- protected final SharedLog mLog;
- protected final String mTag;
- private final int mFamily;
- private final int mBindGroups;
- private final int mSockRcvbufSize;
-
- private static final boolean DBG = false;
-
- // Default socket receive buffer size. This means the specific buffer size is not set.
- private static final int DEFAULT_SOCKET_RECV_BUFSIZE = -1;
-
- /**
- * Constructs a new {@code NetlinkMonitor} instance.
- *
- * @param h The Handler on which to poll for messages and on which to call
- * {@link #processNetlinkMessage}.
- * @param log A SharedLog to log to.
- * @param tag The log tag to use for log messages.
- * @param family the Netlink socket family to, e.g., {@code NETLINK_ROUTE}.
- * @param bindGroups the netlink groups to bind to.
- * @param sockRcvbufSize the specific socket receive buffer size in bytes. -1 means that don't
- * set the specific socket receive buffer size in #createFd and use the default value in
- * /proc/sys/net/core/rmem_default file. See SO_RCVBUF in man-pages/socket.
- */
- public NetlinkMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull String tag,
- int family, int bindGroups, int sockRcvbufSize) {
- super(h, NetlinkUtils.DEFAULT_RECV_BUFSIZE);
- mLog = log.forSubComponent(tag);
- mTag = tag;
- mFamily = family;
- mBindGroups = bindGroups;
- mSockRcvbufSize = sockRcvbufSize;
- }
-
- public NetlinkMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull String tag,
- int family, int bindGroups) {
- this(h, log, tag, family, bindGroups, DEFAULT_SOCKET_RECV_BUFSIZE);
- }
-
- @Override
- protected FileDescriptor createFd() {
- FileDescriptor fd = null;
-
- try {
- fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, mFamily);
- if (mSockRcvbufSize != DEFAULT_SOCKET_RECV_BUFSIZE) {
- try {
- Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, mSockRcvbufSize);
- } catch (ErrnoException e) {
- Log.wtf(mTag, "Failed to set SO_RCVBUF to " + mSockRcvbufSize, e);
- }
- }
- Os.bind(fd, makeNetlinkSocketAddress(0, mBindGroups));
- NetlinkUtils.connectSocketToNetlink(fd);
-
- if (DBG) {
- final SocketAddress nlAddr = Os.getsockname(fd);
- Log.d(mTag, "bound to sockaddr_nl{" + nlAddr.toString() + "}");
- }
- } catch (ErrnoException | SocketException e) {
- logError("Failed to create rtnetlink socket", e);
- closeSocketQuietly(fd);
- return null;
- }
-
- return fd;
- }
-
- @Override
- protected void handlePacket(byte[] recvbuf, int length) {
- final long whenMs = SystemClock.elapsedRealtime();
- final ByteBuffer byteBuffer = ByteBuffer.wrap(recvbuf, 0, length);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- while (byteBuffer.remaining() > 0) {
- try {
- final int position = byteBuffer.position();
- final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer, mFamily);
- if (nlMsg == null || nlMsg.getHeader() == null) {
- byteBuffer.position(position);
- mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
- break;
- }
-
- if (nlMsg instanceof NetlinkErrorMessage) {
- mLog.e("netlink error: " + nlMsg);
- continue;
- }
-
- processNetlinkMessage(nlMsg, whenMs);
- } catch (Exception e) {
- mLog.e("Error handling netlink message", e);
- }
- }
- }
-
- @Override
- protected void logError(String msg, Exception e) {
- mLog.e(msg, e);
- }
-
- // Ignoring ENOBUFS may miss any important netlink messages, there are some messages which
- // cannot be recovered by dumping current state once missed since kernel doesn't keep state
- // for it. In addition, dumping current state will not result in any RTM_DELxxx messages, so
- // reconstructing current state from a dump will be difficult. However, for those netlink
- // messages don't cause any state changes, e.g. RTM_NEWLINK with current link state, maybe
- // it's okay to ignore them, because these netlink messages won't cause any changes on the
- // LinkProperties. Given the above trade-offs, try to ignore ENOBUFS and that's similar to
- // what netd does today.
- //
- // TODO: log metrics when ENOBUFS occurs, or even force a disconnect, it will help see how
- // often this error occurs on fields with the associated socket receive buffer size.
- @Override
- protected boolean handleReadError(ErrnoException e) {
- logError("readPacket error: ", e);
- if (e.errno == ENOBUFS) {
- Log.wtf(mTag, "Errno: ENOBUFS");
- return false;
- }
- return true;
- }
-
- /**
- * Processes one netlink message. Must be overridden by subclasses.
- * @param nlMsg the message to process.
- * @param whenMs the timestamp, as measured by {@link SystemClock#elapsedRealtime}, when the
- * message was received.
- */
- protected void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) { }
-}
diff --git a/common/device/com/android/net/module/util/netlink/ConntrackMessage.java b/common/device/com/android/net/module/util/netlink/ConntrackMessage.java
deleted file mode 100644
index dfed3efb..00000000
--- a/common/device/com/android/net/module/util/netlink/ConntrackMessage.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-import static com.android.net.module.util.netlink.StructNlAttr.findNextAttrOfType;
-import static com.android.net.module.util.netlink.StructNlAttr.makeNestedType;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * A NetlinkMessage subclass for netlink conntrack messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink_conntrack.h
- *
- * @hide
- */
-public class ConntrackMessage extends NetlinkMessage {
- public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
-
- // enum ctattr_type
- public static final short CTA_TUPLE_ORIG = 1;
- public static final short CTA_TUPLE_REPLY = 2;
- public static final short CTA_STATUS = 3;
- public static final short CTA_TIMEOUT = 7;
-
- // enum ctattr_tuple
- public static final short CTA_TUPLE_IP = 1;
- public static final short CTA_TUPLE_PROTO = 2;
-
- // enum ctattr_ip
- public static final short CTA_IP_V4_SRC = 1;
- public static final short CTA_IP_V4_DST = 2;
-
- // enum ctattr_l4proto
- public static final short CTA_PROTO_NUM = 1;
- public static final short CTA_PROTO_SRC_PORT = 2;
- public static final short CTA_PROTO_DST_PORT = 3;
-
- // enum ip_conntrack_status
- public static final int IPS_EXPECTED = 0x00000001;
- public static final int IPS_SEEN_REPLY = 0x00000002;
- public static final int IPS_ASSURED = 0x00000004;
- public static final int IPS_CONFIRMED = 0x00000008;
- public static final int IPS_SRC_NAT = 0x00000010;
- public static final int IPS_DST_NAT = 0x00000020;
- public static final int IPS_SEQ_ADJUST = 0x00000040;
- public static final int IPS_SRC_NAT_DONE = 0x00000080;
- public static final int IPS_DST_NAT_DONE = 0x00000100;
- public static final int IPS_DYING = 0x00000200;
- public static final int IPS_FIXED_TIMEOUT = 0x00000400;
- public static final int IPS_TEMPLATE = 0x00000800;
- public static final int IPS_UNTRACKED = 0x00001000;
- public static final int IPS_HELPER = 0x00002000;
- public static final int IPS_OFFLOAD = 0x00004000;
- public static final int IPS_HW_OFFLOAD = 0x00008000;
-
- // ip_conntrack_status mask
- // Interesting on the NAT conntrack session which has already seen two direction traffic.
- // TODO: Probably IPS_{SRC, DST}_NAT_DONE are also interesting.
- public static final int ESTABLISHED_MASK = IPS_CONFIRMED | IPS_ASSURED | IPS_SEEN_REPLY
- | IPS_SRC_NAT;
- // Interesting on the established NAT conntrack session which is dying.
- public static final int DYING_MASK = ESTABLISHED_MASK | IPS_DYING;
-
- /**
- * A tuple for the conntrack connection information.
- *
- * see also CTA_TUPLE_ORIG and CTA_TUPLE_REPLY.
- */
- public static class Tuple {
- public final Inet4Address srcIp;
- public final Inet4Address dstIp;
-
- // Both port and protocol number are unsigned numbers stored in signed integers, and that
- // callers that want to compare them to integers should either cast those integers, or
- // convert them to unsigned using Byte.toUnsignedInt() and Short.toUnsignedInt().
- public final short srcPort;
- public final short dstPort;
- public final byte protoNum;
-
- public Tuple(TupleIpv4 ip, TupleProto proto) {
- this.srcIp = ip.src;
- this.dstIp = ip.dst;
- this.srcPort = proto.srcPort;
- this.dstPort = proto.dstPort;
- this.protoNum = proto.protoNum;
- }
-
- @Override
- @VisibleForTesting
- public boolean equals(Object o) {
- if (!(o instanceof Tuple)) return false;
- Tuple that = (Tuple) o;
- return Objects.equals(this.srcIp, that.srcIp)
- && Objects.equals(this.dstIp, that.dstIp)
- && this.srcPort == that.srcPort
- && this.dstPort == that.dstPort
- && this.protoNum == that.protoNum;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(srcIp, dstIp, srcPort, dstPort, protoNum);
- }
-
- @Override
- public String toString() {
- final String srcIpStr = (srcIp == null) ? "null" : srcIp.getHostAddress();
- final String dstIpStr = (dstIp == null) ? "null" : dstIp.getHostAddress();
- final String protoStr = NetlinkConstants.stringForProtocol(protoNum);
-
- return "Tuple{"
- + protoStr + ": "
- + srcIpStr + ":" + Short.toUnsignedInt(srcPort) + " -> "
- + dstIpStr + ":" + Short.toUnsignedInt(dstPort)
- + "}";
- }
- }
-
- /**
- * A tuple for the conntrack connection address.
- *
- * see also CTA_TUPLE_IP.
- */
- public static class TupleIpv4 {
- public final Inet4Address src;
- public final Inet4Address dst;
-
- public TupleIpv4(Inet4Address src, Inet4Address dst) {
- this.src = src;
- this.dst = dst;
- }
- }
-
- /**
- * A tuple for the conntrack connection protocol.
- *
- * see also CTA_TUPLE_PROTO.
- */
- public static class TupleProto {
- public final byte protoNum;
- public final short srcPort;
- public final short dstPort;
-
- public TupleProto(byte protoNum, short srcPort, short dstPort) {
- this.protoNum = protoNum;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- }
- }
-
- /**
- * Create a netlink message to refresh IPv4 conntrack entry timeout.
- */
- public static byte[] newIPv4TimeoutUpdateRequest(
- int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
- // *** STYLE WARNING ***
- //
- // Code below this point uses extra block indentation to highlight the
- // packing of nested tuple netlink attribute types.
- final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
- new StructNlAttr(CTA_TUPLE_IP,
- new StructNlAttr(CTA_IP_V4_SRC, src),
- new StructNlAttr(CTA_IP_V4_DST, dst)),
- new StructNlAttr(CTA_TUPLE_PROTO,
- new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
- new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
- new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
-
- final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
-
- final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
- final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final ConntrackMessage ctmsg = new ConntrackMessage();
- ctmsg.mHeader.nlmsg_len = bytes.length;
- ctmsg.mHeader.nlmsg_type = (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8)
- | NetlinkConstants.IPCTNL_MSG_CT_NEW;
- ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- ctmsg.mHeader.nlmsg_seq = 1;
- ctmsg.pack(byteBuffer);
-
- ctaTupleOrig.pack(byteBuffer);
- ctaTimeout.pack(byteBuffer);
-
- return bytes;
- }
-
- /**
- * Parses a netfilter conntrack message from a {@link ByteBuffer}.
- *
- * @param header the netlink message header.
- * @param byteBuffer The buffer from which to parse the netfilter conntrack message.
- * @return the parsed netfilter conntrack message, or {@code null} if the netfilter conntrack
- * message could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static ConntrackMessage parse(@NonNull StructNlMsgHdr header,
- @NonNull ByteBuffer byteBuffer) {
- // Just build the netlink header and netfilter header for now and pretend the whole message
- // was consumed.
- // TODO: Parse the conntrack attributes.
- final StructNfGenMsg nfGenMsg = StructNfGenMsg.parse(byteBuffer);
- if (nfGenMsg == null) {
- return null;
- }
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_STATUS, byteBuffer);
- int status = 0;
- if (nlAttr != null) {
- status = nlAttr.getValueAsBe32(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(CTA_TIMEOUT, byteBuffer);
- int timeoutSec = 0;
- if (nlAttr != null) {
- timeoutSec = nlAttr.getValueAsBe32(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_ORIG), byteBuffer);
- Tuple tupleOrig = null;
- if (nlAttr != null) {
- tupleOrig = parseTuple(nlAttr.getValueAsByteBuffer());
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_REPLY), byteBuffer);
- Tuple tupleReply = null;
- if (nlAttr != null) {
- tupleReply = parseTuple(nlAttr.getValueAsByteBuffer());
- }
-
- // Advance to the end of the message.
- byteBuffer.position(baseOffset);
- final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
- final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
- header.nlmsg_len - kMinConsumed);
- if (byteBuffer.remaining() < kAdditionalSpace) {
- return null;
- }
- byteBuffer.position(baseOffset + kAdditionalSpace);
-
- return new ConntrackMessage(header, nfGenMsg, tupleOrig, tupleReply, status, timeoutSec);
- }
-
- /**
- * Parses a conntrack tuple from a {@link ByteBuffer}.
- *
- * The attribute parsing is interesting on:
- * - CTA_TUPLE_IP
- * CTA_IP_V4_SRC
- * CTA_IP_V4_DST
- * - CTA_TUPLE_PROTO
- * CTA_PROTO_NUM
- * CTA_PROTO_SRC_PORT
- * CTA_PROTO_DST_PORT
- *
- * Assume that the minimum size is the sum of CTA_TUPLE_IP (size: 20) and CTA_TUPLE_PROTO
- * (size: 28). Here is an example for an expected CTA_TUPLE_ORIG message in raw data:
- * +--------------------------------------------------------------------------------------+
- * | CTA_TUPLE_ORIG |
- * +--------------------------+-----------------------------------------------------------+
- * | 1400 | nla_len = 20 |
- * | 0180 | nla_type = nested CTA_TUPLE_IP |
- * | 0800 0100 C0A8500C | nla_type=CTA_IP_V4_SRC, ip=192.168.80.12 |
- * | 0800 0200 8C700874 | nla_type=CTA_IP_V4_DST, ip=140.112.8.116 |
- * | 1C00 | nla_len = 28 |
- * | 0280 | nla_type = nested CTA_TUPLE_PROTO |
- * | 0500 0100 06 000000 | nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6) |
- * | 0600 0200 F3F1 0000 | nla_type=CTA_PROTO_SRC_PORT, port=62449 (big endian) |
- * | 0600 0300 01BB 0000 | nla_type=CTA_PROTO_DST_PORT, port=433 (big endian) |
- * +--------------------------+-----------------------------------------------------------+
- *
- * The position of the byte buffer doesn't set to the end when the function returns. It is okay
- * because the caller ConntrackMessage#parse has passed a copy which is used for this parser
- * only. Moreover, the parser behavior is the same as other existing netlink struct class
- * parser. Ex: StructInetDiagMsg#parse.
- */
- @Nullable
- private static Tuple parseTuple(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- TupleIpv4 tupleIpv4 = null;
- TupleProto tupleProto = null;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_IP), byteBuffer);
- if (nlAttr != null) {
- tupleIpv4 = parseTupleIpv4(nlAttr.getValueAsByteBuffer());
- }
- if (tupleIpv4 == null) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_PROTO), byteBuffer);
- if (nlAttr != null) {
- tupleProto = parseTupleProto(nlAttr.getValueAsByteBuffer());
- }
- if (tupleProto == null) return null;
-
- return new Tuple(tupleIpv4, tupleProto);
- }
-
- @Nullable
- private static Inet4Address castToInet4Address(@Nullable InetAddress address) {
- if (address == null || !(address instanceof Inet4Address)) return null;
- return (Inet4Address) address;
- }
-
- @Nullable
- private static TupleIpv4 parseTupleIpv4(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- Inet4Address src = null;
- Inet4Address dst = null;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_IP_V4_SRC, byteBuffer);
- if (nlAttr != null) {
- src = castToInet4Address(nlAttr.getValueAsInetAddress());
- }
- if (src == null) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(CTA_IP_V4_DST, byteBuffer);
- if (nlAttr != null) {
- dst = castToInet4Address(nlAttr.getValueAsInetAddress());
- }
- if (dst == null) return null;
-
- return new TupleIpv4(src, dst);
- }
-
- @Nullable
- private static TupleProto parseTupleProto(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- byte protoNum = 0;
- short srcPort = 0;
- short dstPort = 0;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_PROTO_NUM, byteBuffer);
- if (nlAttr != null) {
- protoNum = nlAttr.getValueAsByte((byte) 0);
- }
- if (!(protoNum == IPPROTO_TCP || protoNum == IPPROTO_UDP)) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(CTA_PROTO_SRC_PORT, byteBuffer);
- if (nlAttr != null) {
- srcPort = nlAttr.getValueAsBe16((short) 0);
- }
- if (srcPort == 0) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(CTA_PROTO_DST_PORT, byteBuffer);
- if (nlAttr != null) {
- dstPort = nlAttr.getValueAsBe16((short) 0);
- }
- if (dstPort == 0) return null;
-
- return new TupleProto(protoNum, srcPort, dstPort);
- }
-
- /**
- * Netfilter header.
- */
- public final StructNfGenMsg nfGenMsg;
- /**
- * Original direction conntrack tuple.
- *
- * The tuple is determined by the parsed attribute value CTA_TUPLE_ORIG, or null if the
- * tuple could not be parsed successfully (for example, if it was truncated or absent).
- */
- @Nullable
- public final Tuple tupleOrig;
- /**
- * Reply direction conntrack tuple.
- *
- * The tuple is determined by the parsed attribute value CTA_TUPLE_REPLY, or null if the
- * tuple could not be parsed successfully (for example, if it was truncated or absent).
- */
- @Nullable
- public final Tuple tupleReply;
- /**
- * Connection status. A bitmask of ip_conntrack_status enum flags.
- *
- * The status is determined by the parsed attribute value CTA_STATUS, or 0 if the status could
- * not be parsed successfully (for example, if it was truncated or absent). For the message
- * from kernel, the valid status is non-zero. For the message from user space, the status may
- * be 0 (absent).
- */
- public final int status;
- /**
- * Conntrack timeout.
- *
- * The timeout is determined by the parsed attribute value CTA_TIMEOUT, or 0 if the timeout
- * could not be parsed successfully (for example, if it was truncated or absent). For
- * IPCTNL_MSG_CT_NEW event, the valid timeout is non-zero. For IPCTNL_MSG_CT_DELETE event, the
- * timeout is 0 (absent).
- */
- public final int timeoutSec;
-
- private ConntrackMessage() {
- super(new StructNlMsgHdr());
- nfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
-
- // This constructor is only used by #newIPv4TimeoutUpdateRequest which doesn't use these
- // data member for packing message. Simply fill them to null or 0.
- tupleOrig = null;
- tupleReply = null;
- status = 0;
- timeoutSec = 0;
- }
-
- private ConntrackMessage(@NonNull StructNlMsgHdr header, @NonNull StructNfGenMsg nfGenMsg,
- @Nullable Tuple tupleOrig, @Nullable Tuple tupleReply, int status, int timeoutSec) {
- super(header);
- this.nfGenMsg = nfGenMsg;
- this.tupleOrig = tupleOrig;
- this.tupleReply = tupleReply;
- this.status = status;
- this.timeoutSec = timeoutSec;
- }
-
- /**
- * Write a netfilter message to {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- mHeader.pack(byteBuffer);
- nfGenMsg.pack(byteBuffer);
- }
-
- public short getMessageType() {
- return (short) (getHeader().nlmsg_type & ~(NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8));
- }
-
- /**
- * Convert an ip conntrack status to a string.
- */
- public static String stringForIpConntrackStatus(int flags) {
- final StringBuilder sb = new StringBuilder();
-
- if ((flags & IPS_EXPECTED) != 0) {
- sb.append("IPS_EXPECTED");
- }
- if ((flags & IPS_SEEN_REPLY) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SEEN_REPLY");
- }
- if ((flags & IPS_ASSURED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_ASSURED");
- }
- if ((flags & IPS_CONFIRMED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_CONFIRMED");
- }
- if ((flags & IPS_SRC_NAT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SRC_NAT");
- }
- if ((flags & IPS_DST_NAT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DST_NAT");
- }
- if ((flags & IPS_SEQ_ADJUST) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SEQ_ADJUST");
- }
- if ((flags & IPS_SRC_NAT_DONE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SRC_NAT_DONE");
- }
- if ((flags & IPS_DST_NAT_DONE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DST_NAT_DONE");
- }
- if ((flags & IPS_DYING) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DYING");
- }
- if ((flags & IPS_FIXED_TIMEOUT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_FIXED_TIMEOUT");
- }
- if ((flags & IPS_TEMPLATE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_TEMPLATE");
- }
- if ((flags & IPS_UNTRACKED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_UNTRACKED");
- }
- if ((flags & IPS_HELPER) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_HELPER");
- }
- if ((flags & IPS_OFFLOAD) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_OFFLOAD");
- }
- if ((flags & IPS_HW_OFFLOAD) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_HW_OFFLOAD");
- }
- return sb.toString();
- }
-
- @Override
- public String toString() {
- return "ConntrackMessage{"
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(OsConstants.NETLINK_NETFILTER))
- + "}, "
- + "nfgenmsg{" + nfGenMsg + "}, "
- + "tuple_orig{" + tupleOrig + "}, "
- + "tuple_reply{" + tupleReply + "}, "
- + "status{" + status + "(" + stringForIpConntrackStatus(status) + ")" + "}, "
- + "timeout_sec{" + Integer.toUnsignedLong(timeoutSec) + "}"
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/InetDiagMessage.java b/common/device/com/android/net/module/util/netlink/InetDiagMessage.java
deleted file mode 100644
index f8b47164..00000000
--- a/common/device/com/android/net/module/util/netlink/InetDiagMessage.java
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.os.Process.INVALID_UID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.ENOENT;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-
-import static com.android.net.module.util.netlink.NetlinkConstants.NLMSG_DONE;
-import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DESTROY;
-import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static com.android.net.module.util.netlink.NetlinkConstants.hexify;
-import static com.android.net.module.util.netlink.NetlinkConstants.stringForAddressFamily;
-import static com.android.net.module.util.netlink.NetlinkConstants.stringForProtocol;
-import static com.android.net.module.util.netlink.NetlinkUtils.DEFAULT_RECV_BUFSIZE;
-import static com.android.net.module.util.netlink.NetlinkUtils.IO_TIMEOUT_MS;
-import static com.android.net.module.util.netlink.NetlinkUtils.TCP_ALIVE_STATE_FILTER;
-import static com.android.net.module.util.netlink.NetlinkUtils.connectSocketToNetlink;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.net.util.SocketUtils;
-import android.os.Process;
-import android.os.SystemClock;
-import android.system.ErrnoException;
-import android.util.Log;
-import android.util.Range;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/**
- * A NetlinkMessage subclass for netlink inet_diag messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * @hide
- */
-public class InetDiagMessage extends NetlinkMessage {
- public static final String TAG = "InetDiagMessage";
- private static final int TIMEOUT_MS = 500;
-
- /**
- * Construct an inet_diag_req_v2 message. This method will throw
- * {@link IllegalArgumentException} if local and remote are not both null or both non-null.
- */
- public static byte[] inetDiagReqV2(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags) {
- return inetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
- 0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
- }
-
- /**
- * Construct an inet_diag_req_v2 message. This method will throw
- * {@code IllegalArgumentException} if local and remote are not both null or both non-null.
- *
- * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
- * IPPROTO_UDP, or IPPROTO_UDPLITE.
- * @param local local socket address of the target socket. This will be packed into a
- * {@link StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param remote remote socket address of the target socket. This will be packed into a
- * {@link StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param family the ip family of the request message. This should be set to either AF_INET or
- * AF_INET6 for IPv4 or IPv6 sockets respectively.
- * @param flags message flags. See &lt;linux_src&gt;/include/uapi/linux/netlink.h.
- * @param pad for raw socket protocol specification.
- * @param idiagExt a set of flags defining what kind of extended information to report.
- * @param state a bit mask that defines a filter of socket states.
- *
- * @return bytes array representation of the message
- */
- public static byte[] inetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
- @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
- int state) throws IllegalArgumentException {
- // Request for all sockets if no specific socket is requested. Specify the local and remote
- // socket address information for target request socket.
- if ((local == null) != (remote == null)) {
- throw new IllegalArgumentException(
- "Local and remote must be both null or both non-null");
- }
- final StructInetDiagSockId id = ((local != null && remote != null)
- ? new StructInetDiagSockId(local, remote) : null);
- return inetDiagReqV2(protocol, id, family,
- SOCK_DIAG_BY_FAMILY, flags, pad, idiagExt, state);
- }
-
- /**
- * Construct an inet_diag_req_v2 message.
- *
- * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
- * IPPROTO_UDP, or IPPROTO_UDPLITE.
- * @param id inet_diag_sockid. See {@link StructInetDiagSockId}
- * @param family the ip family of the request message. This should be set to either AF_INET or
- * AF_INET6 for IPv4 or IPv6 sockets respectively.
- * @param type message types.
- * @param flags message flags. See &lt;linux_src&gt;/include/uapi/linux/netlink.h.
- * @param pad for raw socket protocol specification.
- * @param idiagExt a set of flags defining what kind of extended information to report.
- * @param state a bit mask that defines a filter of socket states.
- * @return bytes array representation of the message
- */
- public static byte[] inetDiagReqV2(int protocol, @Nullable StructInetDiagSockId id, int family,
- short type, short flags, int pad, int idiagExt, int state) {
- final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
- nlMsgHdr.nlmsg_len = bytes.length;
- nlMsgHdr.nlmsg_type = type;
- nlMsgHdr.nlmsg_flags = flags;
- nlMsgHdr.pack(byteBuffer);
- final StructInetDiagReqV2 inetDiagReqV2 =
- new StructInetDiagReqV2(protocol, id, family, pad, idiagExt, state);
-
- inetDiagReqV2.pack(byteBuffer);
- return bytes;
- }
-
- public StructInetDiagMsg inetDiagMsg;
-
- @VisibleForTesting
- public InetDiagMessage(@NonNull StructNlMsgHdr header) {
- super(header);
- inetDiagMsg = new StructInetDiagMsg();
- }
-
- /**
- * Parse an inet_diag_req_v2 message from buffer.
- */
- @Nullable
- public static InetDiagMessage parse(@NonNull StructNlMsgHdr header,
- @NonNull ByteBuffer byteBuffer) {
- final InetDiagMessage msg = new InetDiagMessage(header);
- msg.inetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
- if (msg.inetDiagMsg == null) {
- return null;
- }
- return msg;
- }
-
- private static void closeSocketQuietly(final FileDescriptor fd) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
-
- private static int lookupUidByFamily(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags,
- FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- byte[] msg = inetDiagReqV2(protocol, local, remote, family, flags);
- NetlinkUtils.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
- ByteBuffer response = NetlinkUtils.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
-
- final NetlinkMessage nlMsg = NetlinkMessage.parse(response, NETLINK_INET_DIAG);
- if (nlMsg == null) {
- return INVALID_UID;
- }
- final StructNlMsgHdr hdr = nlMsg.getHeader();
- if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
- return INVALID_UID;
- }
- if (nlMsg instanceof InetDiagMessage) {
- return ((InetDiagMessage) nlMsg).inetDiagMsg.idiag_uid;
- }
- return INVALID_UID;
- }
-
- private static final int[] FAMILY = {AF_INET6, AF_INET};
-
- private static int lookupUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote, FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- int uid;
-
- for (int family : FAMILY) {
- /**
- * For exact match lookup, swap local and remote for UDP lookups due to kernel
- * bug which will not be fixed. See aosp/755889 and
- * https://www.mail-archive.com/netdev@vger.kernel.org/msg248638.html
- */
- if (protocol == IPPROTO_UDP) {
- uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd);
- } else {
- uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd);
- }
- if (uid != INVALID_UID) {
- return uid;
- }
- }
-
- /**
- * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the
- * socket is not connected (and even if the socket is connected to a different destination).
- * If we want this API to work for such packets, then on miss we need to do a second lookup
- * with only the local address and port filled in.
- * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard.
- */
- if (protocol == IPPROTO_UDP) {
- try {
- InetSocketAddress wildcard = new InetSocketAddress(
- Inet6Address.getByName("::"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- } catch (UnknownHostException e) {
- Log.e(TAG, e.toString());
- }
- }
- return INVALID_UID;
- }
-
- /**
- * Use an inet_diag socket to look up the UID associated with the input local and remote
- * address/port and protocol of a connection.
- */
- public static int getConnectionOwnerUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote) {
- int uid = INVALID_UID;
- FileDescriptor fd = null;
- try {
- fd = NetlinkUtils.netlinkSocketForProto(NETLINK_INET_DIAG);
- NetlinkUtils.connectSocketToNetlink(fd);
- uid = lookupUid(protocol, local, remote, fd);
- } catch (ErrnoException | SocketException | IllegalArgumentException
- | InterruptedIOException e) {
- Log.e(TAG, e.toString());
- } finally {
- closeSocketQuietly(fd);
- }
- return uid;
- }
-
- /**
- * Construct an inet_diag_req_v2 message for querying alive TCP sockets from kernel.
- */
- public static byte[] buildInetDiagReqForAliveTcpSockets(int family) {
- return inetDiagReqV2(IPPROTO_TCP,
- null /* local addr */,
- null /* remote addr */,
- family,
- (short) (StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_DUMP) /* flag */,
- 0 /* pad */,
- 1 << NetlinkConstants.INET_DIAG_MEMINFO /* idiagExt */,
- TCP_ALIVE_STATE_FILTER);
- }
-
- private static void sendNetlinkDestroyRequest(FileDescriptor fd, int proto,
- InetDiagMessage diagMsg) throws InterruptedIOException, ErrnoException {
- final byte[] destroyMsg = InetDiagMessage.inetDiagReqV2(
- proto,
- diagMsg.inetDiagMsg.id,
- diagMsg.inetDiagMsg.idiag_family,
- SOCK_DESTROY,
- (short) (StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_ACK),
- 0 /* pad */,
- 0 /* idiagExt */,
- 1 << diagMsg.inetDiagMsg.idiag_state
- );
- NetlinkUtils.sendMessage(fd, destroyMsg, 0, destroyMsg.length, IO_TIMEOUT_MS);
- NetlinkUtils.receiveNetlinkAck(fd);
- }
-
- private static void sendNetlinkDumpRequest(FileDescriptor fd, int proto, int states, int family)
- throws InterruptedIOException, ErrnoException {
- final byte[] dumpMsg = InetDiagMessage.inetDiagReqV2(
- proto,
- null /* id */,
- family,
- SOCK_DIAG_BY_FAMILY,
- (short) (StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_DUMP),
- 0 /* pad */,
- 0 /* idiagExt */,
- states);
- NetlinkUtils.sendMessage(fd, dumpMsg, 0, dumpMsg.length, IO_TIMEOUT_MS);
- }
-
- private static int processNetlinkDumpAndDestroySockets(FileDescriptor dumpFd,
- FileDescriptor destroyFd, int proto, Predicate<InetDiagMessage> filter)
- throws InterruptedIOException, ErrnoException {
- int destroyedSockets = 0;
-
- while (true) {
- final ByteBuffer buf = NetlinkUtils.recvMessage(
- dumpFd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
-
- while (buf.remaining() > 0) {
- final int position = buf.position();
- final NetlinkMessage nlMsg = NetlinkMessage.parse(buf, NETLINK_INET_DIAG);
- if (nlMsg == null) {
- // Move to the position where parse started for error log.
- buf.position(position);
- Log.e(TAG, "Failed to parse netlink message: " + hexify(buf));
- break;
- }
-
- if (nlMsg.getHeader().nlmsg_type == NLMSG_DONE) {
- return destroyedSockets;
- }
-
- if (!(nlMsg instanceof InetDiagMessage)) {
- Log.wtf(TAG, "Received unexpected netlink message: " + nlMsg);
- continue;
- }
-
- final InetDiagMessage diagMsg = (InetDiagMessage) nlMsg;
- if (filter.test(diagMsg)) {
- try {
- sendNetlinkDestroyRequest(destroyFd, proto, diagMsg);
- destroyedSockets++;
- } catch (InterruptedIOException | ErrnoException e) {
- if (!(e instanceof ErrnoException
- && ((ErrnoException) e).errno == ENOENT)) {
- Log.e(TAG, "Failed to destroy socket: diagMsg=" + diagMsg + ", " + e);
- }
- }
- }
- }
- }
- }
-
- /**
- * Returns whether the InetDiagMessage is for adb socket or not
- */
- @VisibleForTesting
- public static boolean isAdbSocket(final InetDiagMessage msg) {
- // This is inaccurate since adb could run with ROOT_UID or other services can run with
- // SHELL_UID. But this check covers most cases and enough.
- // Note that getting service.adb.tcp.port system property is prohibited by sepolicy
- // TODO: skip the socket only if there is a listen socket owned by SHELL_UID with the same
- // source port as this socket
- return msg.inetDiagMsg.idiag_uid == Process.SHELL_UID;
- }
-
- /**
- * Returns whether the range contains the uid in the InetDiagMessage or not
- */
- @VisibleForTesting
- public static boolean containsUid(InetDiagMessage msg, Set<Range<Integer>> ranges) {
- for (final Range<Integer> range: ranges) {
- if (range.contains(msg.inetDiagMsg.idiag_uid)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isLoopbackAddress(InetAddress addr) {
- if (addr.isLoopbackAddress()) return true;
- if (!(addr instanceof Inet6Address)) return false;
-
- // Following check is for v4-mapped v6 address. StructInetDiagSockId contains v4-mapped v6
- // address as Inet6Address, See StructInetDiagSockId#parse
- final byte[] addrBytes = addr.getAddress();
- for (int i = 0; i < 10; i++) {
- if (addrBytes[i] != 0) return false;
- }
- return addrBytes[10] == (byte) 0xff
- && addrBytes[11] == (byte) 0xff
- && addrBytes[12] == 127;
- }
-
- /**
- * Returns whether the socket address in the InetDiagMessage is loopback or not
- */
- @VisibleForTesting
- public static boolean isLoopback(InetDiagMessage msg) {
- final InetAddress srcAddr = msg.inetDiagMsg.id.locSocketAddress.getAddress();
- final InetAddress dstAddr = msg.inetDiagMsg.id.remSocketAddress.getAddress();
- return isLoopbackAddress(srcAddr)
- || isLoopbackAddress(dstAddr)
- || srcAddr.equals(dstAddr);
- }
-
- private static void destroySockets(int proto, int states, Predicate<InetDiagMessage> filter)
- throws ErrnoException, SocketException, InterruptedIOException {
- FileDescriptor dumpFd = null;
- FileDescriptor destroyFd = null;
-
- try {
- dumpFd = NetlinkUtils.createNetLinkInetDiagSocket();
- destroyFd = NetlinkUtils.createNetLinkInetDiagSocket();
- connectSocketToNetlink(dumpFd);
- connectSocketToNetlink(destroyFd);
-
- for (int family : List.of(AF_INET, AF_INET6)) {
- try {
- sendNetlinkDumpRequest(dumpFd, proto, states, family);
- } catch (InterruptedIOException | ErrnoException e) {
- Log.e(TAG, "Failed to send netlink dump request: " + e);
- continue;
- }
- final int destroyedSockets = processNetlinkDumpAndDestroySockets(
- dumpFd, destroyFd, proto, filter);
- Log.d(TAG, "Destroyed " + destroyedSockets + " sockets"
- + ", proto=" + stringForProtocol(proto)
- + ", family=" + stringForAddressFamily(family)
- + ", states=" + states);
- }
- } finally {
- closeSocketQuietly(dumpFd);
- closeSocketQuietly(destroyFd);
- }
- }
-
- /**
- * Close tcp sockets that match the following condition
- * 1. TCP status is one of TCP_ESTABLISHED, TCP_SYN_SENT, and TCP_SYN_RECV
- * 2. Owner uid of socket is not in the exemptUids
- * 3. Owner uid of socket is in the ranges
- * 4. Socket is not loopback
- * 5. Socket is not adb socket
- *
- * @param ranges target uid ranges
- * @param exemptUids uids to skip close socket
- */
- public static void destroyLiveTcpSockets(Set<Range<Integer>> ranges, Set<Integer> exemptUids)
- throws SocketException, InterruptedIOException, ErrnoException {
- final long startTimeMs = SystemClock.elapsedRealtime();
- destroySockets(IPPROTO_TCP, TCP_ALIVE_STATE_FILTER,
- (diagMsg) -> !exemptUids.contains(diagMsg.inetDiagMsg.idiag_uid)
- && containsUid(diagMsg, ranges)
- && !isLoopback(diagMsg)
- && !isAdbSocket(diagMsg));
- final long durationMs = SystemClock.elapsedRealtime() - startTimeMs;
- Log.d(TAG, "Destroyed live tcp sockets for uids=" + ranges + " exemptUids=" + exemptUids
- + " in " + durationMs + "ms");
- }
-
- /**
- * Close tcp sockets that match the following condition
- * 1. TCP status is one of TCP_ESTABLISHED, TCP_SYN_SENT, and TCP_SYN_RECV
- * 2. Owner uid of socket is in the targetUids
- * 3. Socket is not loopback
- * 4. Socket is not adb socket
- *
- * @param ownerUids target uids to close sockets
- */
- public static void destroyLiveTcpSocketsByOwnerUids(Set<Integer> ownerUids)
- throws SocketException, InterruptedIOException, ErrnoException {
- final long startTimeMs = SystemClock.elapsedRealtime();
- destroySockets(IPPROTO_TCP, TCP_ALIVE_STATE_FILTER,
- (diagMsg) -> ownerUids.contains(diagMsg.inetDiagMsg.idiag_uid)
- && !isLoopback(diagMsg)
- && !isAdbSocket(diagMsg));
- final long durationMs = SystemClock.elapsedRealtime() - startTimeMs;
- Log.d(TAG, "Destroyed live tcp sockets for uids=" + ownerUids + " in " + durationMs + "ms");
- }
-
- @Override
- public String toString() {
- return "InetDiagMessage{ "
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(NETLINK_INET_DIAG)) + "}, "
- + "inet_diag_msg{"
- + (inetDiagMsg == null ? "" : inetDiagMsg.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/NdOption.java b/common/device/com/android/net/module/util/netlink/NdOption.java
deleted file mode 100644
index defc88a7..00000000
--- a/common/device/com/android/net/module/util/netlink/NdOption.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-
-import java.nio.ByteBuffer;
-
-/**
- * Base class for IPv6 neighbour discovery options.
- */
-public class NdOption {
- public static final int STRUCT_SIZE = 2;
-
- /** The option type. */
- public final byte type;
- /** The length of the option in 8-byte units. Actually an unsigned 8-bit integer */
- public final int length;
-
- /** Constructs a new NdOption. */
- NdOption(byte type, int length) {
- this.type = type;
- this.length = length;
- }
-
- /**
- * Parses a neighbour discovery option.
- *
- * Parses (and consumes) the option if it is of a known type. If the option is of an unknown
- * type, advances the buffer (so the caller can continue parsing if desired) and returns
- * {@link #UNKNOWN}. If the option claims a length of 0, returns null because parsing cannot
- * continue.
- *
- * No checks are performed on the length other than ensuring it is not 0, so if a caller wants
- * to deal with options that might overflow the structure that contains them, it must explicitly
- * set the buffer's limit to the position at which that structure ends.
- *
- * @param buf the buffer to parse.
- * @return a subclass of {@link NdOption}, or {@code null} for an unknown or malformed option.
- */
- public static NdOption parse(@NonNull ByteBuffer buf) {
- if (buf.remaining() < STRUCT_SIZE) return null;
-
- // Peek the type without advancing the buffer.
- byte type = buf.get(buf.position());
- int length = Byte.toUnsignedInt(buf.get(buf.position() + 1));
- if (length == 0) return null;
-
- switch (type) {
- case StructNdOptPref64.TYPE:
- return StructNdOptPref64.parse(buf);
-
- case StructNdOptRdnss.TYPE:
- return StructNdOptRdnss.parse(buf);
-
- default:
- int newPosition = Math.min(buf.limit(), buf.position() + length * 8);
- buf.position(newPosition);
- return UNKNOWN;
- }
- }
-
- void writeToByteBuffer(ByteBuffer buf) {
- buf.put(type);
- buf.put((byte) length);
- }
-
- @Override
- public String toString() {
- return String.format("NdOption(%d, %d)", Byte.toUnsignedInt(type), length);
- }
-
- public static final NdOption UNKNOWN = new NdOption((byte) 0, 0);
-}
diff --git a/common/device/com/android/net/module/util/netlink/NduseroptMessage.java b/common/device/com/android/net/module/util/netlink/NduseroptMessage.java
deleted file mode 100644
index bdf574db..00000000
--- a/common/device/com/android/net/module/util/netlink/NduseroptMessage.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.system.OsConstants.AF_INET6;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for RTM_NEWNDUSEROPT messages.
- */
-public class NduseroptMessage extends NetlinkMessage {
- public static final int STRUCT_SIZE = 16;
-
- static final int NDUSEROPT_SRCADDR = 1;
-
- /** The address family. Presumably always AF_INET6. */
- public final byte family;
- /**
- * The total length in bytes of the options that follow this structure.
- * Actually a 16-bit unsigned integer.
- */
- public final int opts_len;
- /** The interface index on which the options were received. */
- public final int ifindex;
- /** The ICMP type of the packet that contained the options. */
- public final byte icmp_type;
- /** The ICMP code of the packet that contained the options. */
- public final byte icmp_code;
-
- /**
- * ND option that was in this message.
- * Even though the length field is called "opts_len", the kernel only ever sends one option per
- * message. It is unlikely that this will ever change as it would break existing userspace code.
- * But if it does, we can simply update this code, since userspace is typically newer than the
- * kernel.
- */
- @Nullable
- public final NdOption option;
-
- /** The IP address that sent the packet containing the option. */
- public final InetAddress srcaddr;
-
- NduseroptMessage(@NonNull StructNlMsgHdr header, @NonNull ByteBuffer buf)
- throws UnknownHostException {
- super(header);
-
- // The structure itself.
- buf.order(ByteOrder.nativeOrder()); // Restored in the finally clause inside parse().
- final int start = buf.position();
- family = buf.get();
- buf.get(); // Skip 1 byte of padding.
- opts_len = Short.toUnsignedInt(buf.getShort());
- ifindex = buf.getInt();
- icmp_type = buf.get();
- icmp_code = buf.get();
- buf.position(buf.position() + 6); // Skip 6 bytes of padding.
-
- // The ND option.
- // Ensure we don't read past opts_len even if the option length is invalid.
- // Note that this check is not really necessary since if the option length is not valid,
- // this struct won't be very useful to the caller.
- //
- // It's safer to pass the slice of original ByteBuffer to just parse the ND option field,
- // although parsing ND option might throw exception or return null, it won't break the
- // original ByteBuffer position.
- buf.order(ByteOrder.BIG_ENDIAN);
- try {
- final ByteBuffer slice = buf.slice();
- slice.limit(opts_len);
- option = NdOption.parse(slice);
- } finally {
- // Advance buffer position according to opts_len in the header. ND option length might
- // be incorrect in the malformed packet.
- int newPosition = start + STRUCT_SIZE + opts_len;
- if (newPosition >= buf.limit()) {
- throw new IllegalArgumentException("ND option extends past end of buffer");
- }
- buf.position(newPosition);
- }
-
- // The source address attribute.
- StructNlAttr nla = StructNlAttr.parse(buf);
- if (nla == null || nla.nla_type != NDUSEROPT_SRCADDR || nla.nla_value == null) {
- throw new IllegalArgumentException("Invalid source address in ND useropt");
- }
- if (family == AF_INET6) {
- // InetAddress.getByAddress only looks at the ifindex if the address type needs one.
- srcaddr = Inet6Address.getByAddress(null /* hostname */, nla.nla_value, ifindex);
- } else {
- srcaddr = InetAddress.getByAddress(nla.nla_value);
- }
- }
-
- /**
- * Parses a StructNduseroptmsg from a {@link ByteBuffer}.
- *
- * @param header the netlink message header.
- * @param buf The buffer from which to parse the option. The buffer's byte order must be
- * {@link java.nio.ByteOrder#BIG_ENDIAN}.
- * @return the parsed option, or {@code null} if the option could not be parsed successfully
- * (for example, if it was truncated, or if the prefix length code was wrong).
- */
- @Nullable
- public static NduseroptMessage parse(@NonNull StructNlMsgHdr header, @NonNull ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
- ByteOrder oldOrder = buf.order();
- try {
- return new NduseroptMessage(header, buf);
- } catch (IllegalArgumentException | UnknownHostException | BufferUnderflowException e) {
- // Not great, but better than throwing an exception that might crash the caller.
- // Convention in this package is that null indicates that the option was truncated, so
- // callers must already handle it.
- return null;
- } finally {
- buf.order(oldOrder);
- }
- }
-
- @Override
- public String toString() {
- return String.format("Nduseroptmsg(%d, %d, %d, %d, %d, %s)",
- family, opts_len, ifindex, Byte.toUnsignedInt(icmp_type),
- Byte.toUnsignedInt(icmp_code), srcaddr.getHostAddress());
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkConstants.java b/common/device/com/android/net/module/util/netlink/NetlinkConstants.java
deleted file mode 100644
index 44c51d8a..00000000
--- a/common/device/com/android/net/module/util/netlink/NetlinkConstants.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-
-import java.nio.ByteBuffer;
-
-/**
- * Various constants and static helper methods for netlink communications.
- *
- * Values taken from:
- *
- * include/uapi/linux/netfilter/nfnetlink.h
- * include/uapi/linux/netfilter/nfnetlink_conntrack.h
- * include/uapi/linux/netlink.h
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class NetlinkConstants {
- private NetlinkConstants() {}
-
- public static final int NLA_ALIGNTO = 4;
- /**
- * Flag for dumping struct tcp_info.
- * Corresponding to enum definition in external/strace/linux/inet_diag.h.
- */
- public static final int INET_DIAG_MEMINFO = 1;
-
- public static final int SOCKDIAG_MSG_HEADER_SIZE =
- StructNlMsgHdr.STRUCT_SIZE + StructInetDiagMsg.STRUCT_SIZE;
-
- /**
- * Get the aligned length based on a Short type number.
- */
- public static final int alignedLengthOf(short length) {
- final int intLength = (int) length & 0xffff;
- return alignedLengthOf(intLength);
- }
-
- /**
- * Get the aligned length based on a Integer type number.
- */
- public static final int alignedLengthOf(int length) {
- if (length <= 0) return 0;
- return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
- }
-
- /**
- * Convert a address family type to a string.
- */
- public static String stringForAddressFamily(int family) {
- if (family == OsConstants.AF_INET) return "AF_INET";
- if (family == OsConstants.AF_INET6) return "AF_INET6";
- if (family == OsConstants.AF_NETLINK) return "AF_NETLINK";
- if (family == OsConstants.AF_UNSPEC) return "AF_UNSPEC";
- return String.valueOf(family);
- }
-
- /**
- * Convert a protocol type to a string.
- */
- public static String stringForProtocol(int protocol) {
- if (protocol == OsConstants.IPPROTO_TCP) return "IPPROTO_TCP";
- if (protocol == OsConstants.IPPROTO_UDP) return "IPPROTO_UDP";
- return String.valueOf(protocol);
- }
-
- /**
- * Convert a byte array to a hexadecimal string.
- */
- public static String hexify(byte[] bytes) {
- if (bytes == null) return "(null)";
- return toHexString(bytes, 0, bytes.length);
- }
-
- /**
- * Convert a {@link ByteBuffer} to a hexadecimal string.
- */
- public static String hexify(ByteBuffer buffer) {
- if (buffer == null) return "(null)";
- return toHexString(
- buffer.array(), buffer.position(), buffer.remaining());
- }
-
- // Known values for struct nlmsghdr nlm_type.
- public static final short NLMSG_NOOP = 1; // Nothing
- public static final short NLMSG_ERROR = 2; // Error
- public static final short NLMSG_DONE = 3; // End of a dump
- public static final short NLMSG_OVERRUN = 4; // Data lost
- public static final short NLMSG_MAX_RESERVED = 15; // Max reserved value
-
- public static final short RTM_NEWLINK = 16;
- public static final short RTM_DELLINK = 17;
- public static final short RTM_GETLINK = 18;
- public static final short RTM_SETLINK = 19;
- public static final short RTM_NEWADDR = 20;
- public static final short RTM_DELADDR = 21;
- public static final short RTM_GETADDR = 22;
- public static final short RTM_NEWROUTE = 24;
- public static final short RTM_DELROUTE = 25;
- public static final short RTM_GETROUTE = 26;
- public static final short RTM_NEWNEIGH = 28;
- public static final short RTM_DELNEIGH = 29;
- public static final short RTM_GETNEIGH = 30;
- public static final short RTM_NEWRULE = 32;
- public static final short RTM_DELRULE = 33;
- public static final short RTM_GETRULE = 34;
- public static final short RTM_NEWNDUSEROPT = 68;
-
- // Netfilter netlink message types are presented by two bytes: high byte subsystem and
- // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in
- // include/uapi/linux/netfilter/nfnetlink.h
- public static final short NFNL_SUBSYS_CTNETLINK = 1;
-
- public static final short IPCTNL_MSG_CT_NEW = 0;
- public static final short IPCTNL_MSG_CT_GET = 1;
- public static final short IPCTNL_MSG_CT_DELETE = 2;
- public static final short IPCTNL_MSG_CT_GET_CTRZERO = 3;
- public static final short IPCTNL_MSG_CT_GET_STATS_CPU = 4;
- public static final short IPCTNL_MSG_CT_GET_STATS = 5;
- public static final short IPCTNL_MSG_CT_GET_DYING = 6;
- public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7;
-
- /* see include/uapi/linux/sock_diag.h */
- public static final short SOCK_DIAG_BY_FAMILY = 20;
- public static final short SOCK_DESTROY = 21;
-
- // Netlink groups.
- public static final int RTMGRP_LINK = 1;
- public static final int RTMGRP_IPV4_IFADDR = 0x10;
- public static final int RTMGRP_IPV6_IFADDR = 0x100;
- public static final int RTMGRP_IPV6_ROUTE = 0x400;
- public static final int RTNLGRP_ND_USEROPT = 20;
- public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1);
-
- // Device flags.
- public static final int IFF_UP = 1 << 0;
- public static final int IFF_LOWER_UP = 1 << 16;
-
- // Known values for struct rtmsg rtm_protocol.
- public static final short RTPROT_KERNEL = 2;
- public static final short RTPROT_RA = 9;
-
- // Known values for struct rtmsg rtm_scope.
- public static final short RT_SCOPE_UNIVERSE = 0;
-
- // Known values for struct rtmsg rtm_type.
- public static final short RTN_UNICAST = 1;
-
- // Known values for struct rtmsg rtm_flags.
- public static final int RTM_F_CLONED = 0x200;
-
- /**
- * Convert a netlink message type to a string for control message.
- */
- @NonNull
- private static String stringForCtlMsgType(short nlmType) {
- switch (nlmType) {
- case NLMSG_NOOP: return "NLMSG_NOOP";
- case NLMSG_ERROR: return "NLMSG_ERROR";
- case NLMSG_DONE: return "NLMSG_DONE";
- case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
- default: return "unknown control message type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_ROUTE.
- */
- @NonNull
- private static String stringForRtMsgType(short nlmType) {
- switch (nlmType) {
- case RTM_NEWLINK: return "RTM_NEWLINK";
- case RTM_DELLINK: return "RTM_DELLINK";
- case RTM_GETLINK: return "RTM_GETLINK";
- case RTM_SETLINK: return "RTM_SETLINK";
- case RTM_NEWADDR: return "RTM_NEWADDR";
- case RTM_DELADDR: return "RTM_DELADDR";
- case RTM_GETADDR: return "RTM_GETADDR";
- case RTM_NEWROUTE: return "RTM_NEWROUTE";
- case RTM_DELROUTE: return "RTM_DELROUTE";
- case RTM_GETROUTE: return "RTM_GETROUTE";
- case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
- case RTM_DELNEIGH: return "RTM_DELNEIGH";
- case RTM_GETNEIGH: return "RTM_GETNEIGH";
- case RTM_NEWRULE: return "RTM_NEWRULE";
- case RTM_DELRULE: return "RTM_DELRULE";
- case RTM_GETRULE: return "RTM_GETRULE";
- case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
- default: return "unknown RTM type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_INET_DIAG.
- */
- @NonNull
- private static String stringForInetDiagMsgType(short nlmType) {
- switch (nlmType) {
- case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY";
- default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_NETFILTER.
- */
- @NonNull
- private static String stringForNfMsgType(short nlmType) {
- final byte subsysId = (byte) (nlmType >> 8);
- final byte msgType = (byte) nlmType;
- switch (subsysId) {
- case NFNL_SUBSYS_CTNETLINK:
- switch (msgType) {
- case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW";
- case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET";
- case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE";
- case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO";
- case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU";
- case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS";
- case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING";
- case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED";
- }
- break;
- }
- return "unknown NETFILTER type: " + String.valueOf(nlmType);
- }
-
- /**
- * Convert a netlink message type to a string by netlink family.
- */
- @NonNull
- public static String stringForNlMsgType(short nlmType, int nlFamily) {
- // Reserved control messages. The netlink family is ignored.
- // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
- if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType);
-
- // Netlink family messages. The netlink family is required. Note that the reason for using
- // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
- // not constant.
- if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType);
- if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType);
- if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType);
-
- return "unknown type: " + String.valueOf(nlmType);
- }
-
- private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F' };
- /**
- * Convert a byte array to a hexadecimal string.
- */
- public static String toHexString(byte[] array, int offset, int length) {
- char[] buf = new char[length * 2];
-
- int bufIndex = 0;
- for (int i = offset; i < offset + length; i++) {
- byte b = array[i];
- buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
- buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
- }
-
- return new String(buf);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java b/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java
deleted file mode 100644
index 48314323..00000000
--- a/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-/**
- * A NetlinkMessage subclass for netlink error messages.
- *
- * @hide
- */
-public class NetlinkErrorMessage extends NetlinkMessage {
-
- /**
- * Parse a netlink error message from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the netlink error message.
- * @return the parsed netlink error message, or {@code null} if the netlink error message
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static NetlinkErrorMessage parse(@NonNull StructNlMsgHdr header,
- @NonNull ByteBuffer byteBuffer) {
- final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header);
-
- errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer);
- if (errorMsg.mNlMsgErr == null) {
- return null;
- }
-
- return errorMsg;
- }
-
- private StructNlMsgErr mNlMsgErr;
-
- NetlinkErrorMessage(@NonNull StructNlMsgHdr header) {
- super(header);
- mNlMsgErr = null;
- }
-
- public StructNlMsgErr getNlMsgError() {
- return mNlMsgErr;
- }
-
- @Override
- public String toString() {
- return "NetlinkErrorMessage{ "
- + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
- + "nlmsgerr{" + (mNlMsgErr == null ? "" : mNlMsgErr.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkMessage.java b/common/device/com/android/net/module/util/netlink/NetlinkMessage.java
deleted file mode 100644
index 9e1e26e7..00000000
--- a/common/device/com/android/net/module/util/netlink/NetlinkMessage.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-/**
- * NetlinkMessage base class for other, more specific netlink message types.
- *
- * Classes that extend NetlinkMessage should:
- * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method
- * - returning either null (parse errors) or a new object of the subclass
- * type (cast-able to NetlinkMessage)
- *
- * NetlinkMessage.parse() should be updated to know which nlmsg_type values
- * correspond with which message subclasses.
- *
- * @hide
- */
-public class NetlinkMessage {
- private static final String TAG = "NetlinkMessage";
-
- /**
- * Parsing netlink messages for reserved control message or specific netlink message. The
- * netlink family is required for parsing specific netlink message. See man-pages/netlink.
- */
- @Nullable
- public static NetlinkMessage parse(@NonNull ByteBuffer byteBuffer, int nlFamily) {
- final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
- final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
- if (nlmsghdr == null) {
- return null;
- }
-
- final int messageLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
- final int payloadLength = messageLength - StructNlMsgHdr.STRUCT_SIZE;
- if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) {
- // Malformed message or runt buffer. Pretend the buffer was consumed.
- byteBuffer.position(byteBuffer.limit());
- return null;
- }
-
- // Reserved control messages. The netlink family is ignored.
- // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
- if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
- return parseCtlMessage(nlmsghdr, byteBuffer, payloadLength);
- }
-
- // Netlink family messages. The netlink family is required. Note that the reason for using
- // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
- // not constant.
- final NetlinkMessage parsed;
- if (nlFamily == OsConstants.NETLINK_ROUTE) {
- parsed = parseRtMessage(nlmsghdr, byteBuffer);
- } else if (nlFamily == OsConstants.NETLINK_INET_DIAG) {
- parsed = parseInetDiagMessage(nlmsghdr, byteBuffer);
- } else if (nlFamily == OsConstants.NETLINK_NETFILTER) {
- parsed = parseNfMessage(nlmsghdr, byteBuffer);
- } else {
- parsed = null;
- }
-
- // Advance to the end of the message, regardless of whether the parsing code consumed
- // all of it or not.
- byteBuffer.position(startPosition + messageLength);
-
- return parsed;
- }
-
- @NonNull
- protected final StructNlMsgHdr mHeader;
-
- public NetlinkMessage(@NonNull StructNlMsgHdr nlmsghdr) {
- mHeader = nlmsghdr;
- }
-
- @NonNull
- public StructNlMsgHdr getHeader() {
- return mHeader;
- }
-
- @Override
- public String toString() {
- // The netlink family is not provided to StructNlMsgHdr#toString because NetlinkMessage
- // doesn't store the information. So the netlink message type can't be transformed into
- // a string by StructNlMsgHdr#toString and just keep as an integer. The specific message
- // which inherits NetlinkMessage could override NetlinkMessage#toString and provide the
- // specific netlink family to StructNlMsgHdr#toString.
- return "NetlinkMessage{" + mHeader.toString() + "}";
- }
-
- @NonNull
- private static NetlinkMessage parseCtlMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer, int payloadLength) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.NLMSG_ERROR:
- return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
- default: {
- // Other netlink control messages. Just parse the header for now,
- // pretending the whole message was consumed.
- byteBuffer.position(byteBuffer.position() + payloadLength);
- return new NetlinkMessage(nlmsghdr);
- }
- }
- }
-
- @Nullable
- private static NetlinkMessage parseRtMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.RTM_NEWLINK:
- case NetlinkConstants.RTM_DELLINK:
- return (NetlinkMessage) RtNetlinkLinkMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.RTM_NEWADDR:
- case NetlinkConstants.RTM_DELADDR:
- return (NetlinkMessage) RtNetlinkAddressMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.RTM_NEWROUTE:
- case NetlinkConstants.RTM_DELROUTE:
- return (NetlinkMessage) RtNetlinkRouteMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.RTM_NEWNEIGH:
- case NetlinkConstants.RTM_DELNEIGH:
- case NetlinkConstants.RTM_GETNEIGH:
- return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.RTM_NEWNDUSEROPT:
- return (NetlinkMessage) NduseroptMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-
- @Nullable
- private static NetlinkMessage parseInetDiagMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
- return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-
- @Nullable
- private static NetlinkMessage parseNfMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
- | NetlinkConstants.IPCTNL_MSG_CT_NEW:
- case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
- | NetlinkConstants.IPCTNL_MSG_CT_DELETE:
- return (NetlinkMessage) ConntrackMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkUtils.java b/common/device/com/android/net/module/util/netlink/NetlinkUtils.java
deleted file mode 100644
index 33bd36d8..00000000
--- a/common/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
-import static android.system.OsConstants.AF_NETLINK;
-import static android.system.OsConstants.EIO;
-import static android.system.OsConstants.EPROTO;
-import static android.system.OsConstants.ETIMEDOUT;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-import static android.system.OsConstants.NETLINK_ROUTE;
-import static android.system.OsConstants.SOCK_CLOEXEC;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVBUF;
-import static android.system.OsConstants.SO_RCVTIMEO;
-import static android.system.OsConstants.SO_SNDTIMEO;
-
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructTimeval;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.Inet6Address;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * Utilities for netlink related class that may not be able to fit into a specific class.
- * @hide
- */
-public class NetlinkUtils {
- private static final String TAG = "NetlinkUtils";
- /** Corresponds to enum from bionic/libc/include/netinet/tcp.h. */
- private static final int TCP_ESTABLISHED = 1;
- private static final int TCP_SYN_SENT = 2;
- private static final int TCP_SYN_RECV = 3;
-
- public static final int TCP_ALIVE_STATE_FILTER =
- (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
-
- public static final int UNKNOWN_MARK = 0xffffffff;
- public static final int NULL_MASK = 0;
-
- // Initial mark value corresponds to the initValue in system/netd/include/Fwmark.h.
- public static final int INIT_MARK_VALUE = 0;
- // Corresponds to enum definition in bionic/libc/kernel/uapi/linux/inet_diag.h
- public static final int INET_DIAG_INFO = 2;
- public static final int INET_DIAG_MARK = 15;
-
- public static final long IO_TIMEOUT_MS = 300L;
-
- public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024;
- public static final int SOCKET_RECV_BUFSIZE = 64 * 1024;
-
- /**
- * Return whether the input ByteBuffer contains enough remaining bytes for
- * {@code StructNlMsgHdr}.
- */
- public static boolean enoughBytesRemainForValidNlMsg(@NonNull final ByteBuffer bytes) {
- return bytes.remaining() >= StructNlMsgHdr.STRUCT_SIZE;
- }
-
- /**
- * Parse netlink error message
- *
- * @param bytes byteBuffer to parse netlink error message
- * @return NetlinkErrorMessage if bytes contains valid NetlinkErrorMessage, else {@code null}
- */
- @Nullable
- private static NetlinkErrorMessage parseNetlinkErrorMessage(ByteBuffer bytes) {
- final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes);
- if (nlmsghdr == null || nlmsghdr.nlmsg_type != NetlinkConstants.NLMSG_ERROR) {
- return null;
- }
-
- final int messageLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
- final int payloadLength = messageLength - StructNlMsgHdr.STRUCT_SIZE;
- if (payloadLength < 0 || payloadLength > bytes.remaining()) {
- // Malformed message or runt buffer. Pretend the buffer was consumed.
- bytes.position(bytes.limit());
- return null;
- }
-
- return NetlinkErrorMessage.parse(nlmsghdr, bytes);
- }
-
- /**
- * Receive netlink ack message and check error
- *
- * @param fd fd to read netlink message
- */
- public static void receiveNetlinkAck(final FileDescriptor fd)
- throws InterruptedIOException, ErrnoException {
- final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
- // recvMessage() guaranteed to not return null if it did not throw.
- final NetlinkErrorMessage response = parseNetlinkErrorMessage(bytes);
- if (response != null && response.getNlMsgError() != null) {
- final int errno = response.getNlMsgError().error;
- if (errno != 0) {
- // TODO: consider ignoring EINVAL (-22), which appears to be
- // normal when probing a neighbor for which the kernel does
- // not already have / no longer has a link layer address.
- Log.e(TAG, "receiveNetlinkAck, errmsg=" + response.toString());
- // Note: convert kernel errnos (negative) into userspace errnos (positive).
- throw new ErrnoException(response.toString(), Math.abs(errno));
- }
- } else {
- final String errmsg;
- if (response == null) {
- bytes.position(0);
- errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
- } else {
- errmsg = response.toString();
- }
- Log.e(TAG, "receiveNetlinkAck, errmsg=" + errmsg);
- throw new ErrnoException(errmsg, EPROTO);
- }
- }
-
- /**
- * Send one netlink message to kernel via netlink socket.
- *
- * @param nlProto netlink protocol type.
- * @param msg the raw bytes of netlink message to be sent.
- */
- public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
- final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
- final FileDescriptor fd = netlinkSocketForProto(nlProto);
-
- try {
- connectSocketToNetlink(fd);
- sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT_MS);
- receiveNetlinkAck(fd);
- } catch (InterruptedIOException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, ETIMEDOUT, e);
- } catch (SocketException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, EIO, e);
- } finally {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException e) {
- // Nothing we can do here
- }
- }
- }
-
- /**
- * Send an RTM_NEWADDR message to kernel to add or update an IPv6 address.
- *
- * @param ifIndex interface index.
- * @param ip IPv6 address to be added.
- * @param prefixlen IPv6 address prefix length.
- * @param flags IPv6 address flags.
- * @param scope IPv6 address scope.
- * @param preferred The preferred lifetime of IPv6 address.
- * @param valid The valid lifetime of IPv6 address.
- */
- public static boolean sendRtmNewAddressRequest(int ifIndex, @NonNull final Inet6Address ip,
- short prefixlen, int flags, byte scope, long preferred, long valid) {
- Objects.requireNonNull(ip, "IPv6 address to be added should not be null.");
- final byte[] msg = RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqNo*/, ip,
- prefixlen, flags, scope, ifIndex, preferred, valid);
- try {
- NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
- return true;
- } catch (ErrnoException e) {
- Log.e(TAG, "Fail to send RTM_NEWADDR to add " + ip.getHostAddress(), e);
- return false;
- }
- }
-
- /**
- * Send an RTM_DELADDR message to kernel to delete an IPv6 address.
- *
- * @param ifIndex interface index.
- * @param ip IPv6 address to be deleted.
- * @param prefixlen IPv6 address prefix length.
- */
- public static boolean sendRtmDelAddressRequest(int ifIndex, final Inet6Address ip,
- short prefixlen) {
- Objects.requireNonNull(ip, "IPv6 address to be deleted should not be null.");
- final byte[] msg = RtNetlinkAddressMessage.newRtmDelAddressMessage(1 /* seqNo*/, ip,
- prefixlen, ifIndex);
- try {
- NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
- return true;
- } catch (ErrnoException e) {
- Log.e(TAG, "Fail to send RTM_DELADDR to delete " + ip.getHostAddress(), e);
- return false;
- }
- }
-
- /**
- * Create netlink socket with the given netlink protocol type.
- *
- * @return fd the fileDescriptor of the socket.
- * @throws ErrnoException if the FileDescriptor not connect to be created successfully
- */
- public static FileDescriptor netlinkSocketForProto(int nlProto) throws ErrnoException {
- final FileDescriptor fd = Os.socket(AF_NETLINK, SOCK_DGRAM, nlProto);
- Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, SOCKET_RECV_BUFSIZE);
- return fd;
- }
-
- /**
- * Construct a netlink inet_diag socket.
- */
- public static FileDescriptor createNetLinkInetDiagSocket() throws ErrnoException {
- return Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
- }
-
- /**
- * Connect the given file descriptor to the Netlink interface to the kernel.
- *
- * The fd must be a SOCK_DGRAM socket : create it with {@link #netlinkSocketForProto}
- *
- * @throws ErrnoException if the {@code fd} could not connect to kernel successfully
- * @throws SocketException if there is an error accessing a socket.
- */
- public static void connectSocketToNetlink(FileDescriptor fd)
- throws ErrnoException, SocketException {
- Os.connect(fd, makeNetlinkSocketAddress(0, 0));
- }
-
- private static void checkTimeout(long timeoutMs) {
- if (timeoutMs < 0) {
- throw new IllegalArgumentException("Negative timeouts not permitted");
- }
- }
-
- /**
- * Wait up to |timeoutMs| (or until underlying socket error) for a
- * netlink message of at most |bufsize| size.
- *
- * Multi-threaded calls with different timeouts will cause unexpected results.
- */
- public static ByteBuffer recvMessage(FileDescriptor fd, int bufsize, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
-
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs));
-
- final ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
- final int length = Os.read(fd, byteBuffer);
- if (length == bufsize) {
- Log.w(TAG, "maximum read");
- }
- byteBuffer.position(0);
- byteBuffer.limit(length);
- byteBuffer.order(ByteOrder.nativeOrder());
- return byteBuffer;
- }
-
- /**
- * Send a message to a peer to which this socket has previously connected.
- *
- * This waits at most |timeoutMs| milliseconds for the send to complete, will get the exception
- * if it times out.
- */
- public static int sendMessage(
- FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs));
- return Os.write(fd, bytes, offset, count);
- }
-
- private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK);
-
- /**
- * Convert the system time in clock ticks(clock_t type in times(), not in clock()) to
- * milliseconds. times() clock_t ticks at the kernel's USER_HZ (100) while clock() clock_t
- * ticks at CLOCKS_PER_SEC (1000000).
- *
- * See the NOTES on https://man7.org/linux/man-pages/man2/times.2.html for the difference
- * of clock_t used in clock() and times().
- */
- public static long ticksToMilliSeconds(int intClockTicks) {
- final long longClockTicks = intClockTicks & 0xffffffffL;
- return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND;
- }
-
- private NetlinkUtils() {}
-}
diff --git a/common/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java b/common/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
deleted file mode 100644
index cbe0ab0e..00000000
--- a/common/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.net.module.util.HexDump;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * A NetlinkMessage subclass for rtnetlink address messages.
- *
- * RtNetlinkAddressMessage.parse() must be called with a ByteBuffer that contains exactly one
- * netlink message.
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class RtNetlinkAddressMessage extends NetlinkMessage {
- public static final short IFA_ADDRESS = 1;
- public static final short IFA_CACHEINFO = 6;
- public static final short IFA_FLAGS = 8;
-
- private int mFlags;
- @NonNull
- private StructIfaddrMsg mIfaddrmsg;
- @NonNull
- private InetAddress mIpAddress;
- @Nullable
- private StructIfacacheInfo mIfacacheInfo;
-
- @VisibleForTesting
- public RtNetlinkAddressMessage(@NonNull final StructNlMsgHdr header,
- @NonNull final StructIfaddrMsg ifaddrMsg,
- @NonNull final InetAddress ipAddress,
- @Nullable final StructIfacacheInfo structIfacacheInfo,
- int flags) {
- super(header);
- mIfaddrmsg = ifaddrMsg;
- mIpAddress = ipAddress;
- mIfacacheInfo = structIfacacheInfo;
- mFlags = flags;
- }
- private RtNetlinkAddressMessage(@NonNull StructNlMsgHdr header) {
- this(header, null, null, null, 0);
- }
-
- public int getFlags() {
- return mFlags;
- }
-
- @NonNull
- public StructIfaddrMsg getIfaddrHeader() {
- return mIfaddrmsg;
- }
-
- @NonNull
- public InetAddress getIpAddress() {
- return mIpAddress;
- }
-
- @Nullable
- public StructIfacacheInfo getIfacacheInfo() {
- return mIfacacheInfo;
- }
-
- /**
- * Parse rtnetlink address message from {@link ByteBuffer}. This method must be called with a
- * ByteBuffer that contains exactly one netlink message.
- *
- * @param header netlink message header.
- * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
- */
- @Nullable
- public static RtNetlinkAddressMessage parse(@NonNull final StructNlMsgHdr header,
- @NonNull final ByteBuffer byteBuffer) {
- final RtNetlinkAddressMessage addrMsg = new RtNetlinkAddressMessage(header);
-
- addrMsg.mIfaddrmsg = StructIfaddrMsg.parse(byteBuffer);
- if (addrMsg.mIfaddrmsg == null) return null;
-
- // IFA_ADDRESS
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(IFA_ADDRESS, byteBuffer);
- if (nlAttr == null) return null;
- addrMsg.mIpAddress = nlAttr.getValueAsInetAddress();
- if (addrMsg.mIpAddress == null) return null;
-
- // IFA_CACHEINFO
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(IFA_CACHEINFO, byteBuffer);
- if (nlAttr != null) {
- addrMsg.mIfacacheInfo = StructIfacacheInfo.parse(nlAttr.getValueAsByteBuffer());
- }
-
- // The first 8 bits of flags are in the ifaddrmsg.
- addrMsg.mFlags = addrMsg.mIfaddrmsg.flags;
- // IFA_FLAGS. All the flags are in the IF_FLAGS attribute. This should always be present,
- // and will overwrite the flags set above.
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(IFA_FLAGS, byteBuffer);
- if (nlAttr == null) return null;
- final Integer value = nlAttr.getValueAsInteger();
- if (value == null) return null;
- addrMsg.mFlags = value;
-
- return addrMsg;
- }
-
- /**
- * Write a rtnetlink address message to {@link ByteBuffer}.
- */
- @VisibleForTesting
- protected void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer);
- mIfaddrmsg.pack(byteBuffer);
-
- final StructNlAttr address = new StructNlAttr(IFA_ADDRESS, mIpAddress);
- address.pack(byteBuffer);
-
- if (mIfacacheInfo != null) {
- final StructNlAttr cacheInfo = new StructNlAttr(IFA_CACHEINFO,
- mIfacacheInfo.writeToBytes());
- cacheInfo.pack(byteBuffer);
- }
-
- // If IFA_FLAGS attribute isn't present on the wire at parsing netlink message, it will
- // still be packed to ByteBuffer even if the flag is 0.
- final StructNlAttr flags = new StructNlAttr(IFA_FLAGS, mFlags);
- flags.pack(byteBuffer);
- }
-
- /**
- * A convenience method to create a RTM_NEWADDR message.
- */
- public static byte[] newRtmNewAddressMessage(int seqNo, @NonNull final InetAddress ip,
- short prefixlen, int flags, byte scope, int ifIndex, long preferred, long valid) {
- Objects.requireNonNull(ip, "IP address to be set via netlink message cannot be null");
-
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWADDR;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_ACK;
- nlmsghdr.nlmsg_seq = seqNo;
-
- final RtNetlinkAddressMessage msg = new RtNetlinkAddressMessage(nlmsghdr);
- final byte family =
- (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
- // IFA_FLAGS attribute is always present within this method, just set flags from
- // ifaddrmsg to 0. kernel will prefer the flags from IFA_FLAGS attribute.
- msg.mIfaddrmsg =
- new StructIfaddrMsg(family, prefixlen, (short) 0 /* flags */, scope, ifIndex);
- msg.mIpAddress = ip;
- msg.mIfacacheInfo = new StructIfacacheInfo(preferred, valid, 0 /* cstamp */,
- 0 /* tstamp */);
- msg.mFlags = flags;
-
- final byte[] bytes = new byte[msg.getRequiredSpace()];
- nlmsghdr.nlmsg_len = bytes.length;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
- msg.pack(byteBuffer);
- return bytes;
- }
-
- /**
- * A convenience method to create a RTM_DELADDR message.
- */
- public static byte[] newRtmDelAddressMessage(int seqNo, @NonNull final InetAddress ip,
- short prefixlen, int ifIndex) {
- Objects.requireNonNull(ip, "IP address to be deleted via netlink message cannot be null");
-
- final int ifaAddrAttrLength = NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + ip.getAddress().length);
- final int length = StructNlMsgHdr.STRUCT_SIZE + StructIfaddrMsg.STRUCT_SIZE
- + ifaAddrAttrLength;
- final byte[] bytes = new byte[length];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_len = length;
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_DELADDR;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- nlmsghdr.nlmsg_seq = seqNo;
- nlmsghdr.pack(byteBuffer);
-
- final byte family =
- (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
- // Actually kernel ignores scope and flags(only deal with IFA_F_MANAGETEMPADDR, it
- // indicates that all relevant IPv6 temporary addresses should be deleted as well when
- // user space intends to delete a global IPv6 address with IFA_F_MANAGETEMPADDR), so
- // far IFA_F_MANAGETEMPADDR flag isn't used in user space, it's fine to ignore it.
- // However, we need to add IFA_FLAGS attribute in RTM_DELADDR if flags parsing should
- // be supported in the future.
- final StructIfaddrMsg ifaddrmsg = new StructIfaddrMsg(family, prefixlen,
- (short) 0 /* flags */, (short) 0 /* scope */, ifIndex);
- ifaddrmsg.pack(byteBuffer);
-
- final StructNlAttr address = new StructNlAttr(IFA_ADDRESS, ip);
- address.pack(byteBuffer);
-
- return bytes;
- }
-
- // This function helper gives the required buffer size for IFA_ADDRESS, IFA_CACHEINFO and
- // IFA_FLAGS attributes encapsulation. However, that's not a mandatory requirement for all
- // RtNetlinkAddressMessage, e.g. RTM_DELADDR sent from user space to kernel to delete an
- // IP address only requires IFA_ADDRESS attribute. The caller should check if these attributes
- // are necessary to carry when constructing a RtNetlinkAddressMessage.
- private int getRequiredSpace() {
- int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructIfaddrMsg.STRUCT_SIZE;
- // IFA_ADDRESS attr
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mIpAddress.getAddress().length);
- // IFA_CACHEINFO attr
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + StructIfacacheInfo.STRUCT_SIZE);
- // IFA_FLAGS "u32" attr
- spaceRequired += StructNlAttr.NLA_HEADERLEN + 4;
- return spaceRequired;
- }
-
- @Override
- public String toString() {
- return "RtNetlinkAddressMessage{ "
- + "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, "
- + "Ifaddrmsg{" + mIfaddrmsg.toString() + "}, "
- + "IP Address{" + mIpAddress.getHostAddress() + "}, "
- + "IfacacheInfo{" + (mIfacacheInfo == null ? "" : mIfacacheInfo.toString()) + "}, "
- + "Address Flags{" + HexDump.toHexString(mFlags) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java b/common/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
deleted file mode 100644
index 92ec0c4e..00000000
--- a/common/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.net.MacAddress;
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.nio.ByteBuffer;
-
-/**
- * A NetlinkMessage subclass for rtnetlink link messages.
- *
- * RtNetlinkLinkMessage.parse() must be called with a ByteBuffer that contains exactly one netlink
- * message.
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class RtNetlinkLinkMessage extends NetlinkMessage {
- public static final short IFLA_ADDRESS = 1;
- public static final short IFLA_IFNAME = 3;
- public static final short IFLA_MTU = 4;
-
- private int mMtu;
- @NonNull
- private StructIfinfoMsg mIfinfomsg;
- @Nullable
- private MacAddress mHardwareAddress;
- @Nullable
- private String mInterfaceName;
-
- private RtNetlinkLinkMessage(@NonNull StructNlMsgHdr header) {
- super(header);
- mIfinfomsg = null;
- mMtu = 0;
- mHardwareAddress = null;
- mInterfaceName = null;
- }
-
- public int getMtu() {
- return mMtu;
- }
-
- @NonNull
- public StructIfinfoMsg getIfinfoHeader() {
- return mIfinfomsg;
- }
-
- @Nullable
- public MacAddress getHardwareAddress() {
- return mHardwareAddress;
- }
-
- @Nullable
- public String getInterfaceName() {
- return mInterfaceName;
- }
-
- /**
- * Parse rtnetlink link message from {@link ByteBuffer}. This method must be called with a
- * ByteBuffer that contains exactly one netlink message.
- *
- * @param header netlink message header.
- * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
- */
- @Nullable
- public static RtNetlinkLinkMessage parse(@NonNull final StructNlMsgHdr header,
- @NonNull final ByteBuffer byteBuffer) {
- final RtNetlinkLinkMessage linkMsg = new RtNetlinkLinkMessage(header);
-
- linkMsg.mIfinfomsg = StructIfinfoMsg.parse(byteBuffer);
- if (linkMsg.mIfinfomsg == null) return null;
-
- // IFLA_MTU
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(IFLA_MTU, byteBuffer);
- if (nlAttr != null) {
- linkMsg.mMtu = nlAttr.getValueAsInt(0 /* default value */);
- }
-
- // IFLA_ADDRESS
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(IFLA_ADDRESS, byteBuffer);
- if (nlAttr != null) {
- linkMsg.mHardwareAddress = nlAttr.getValueAsMacAddress();
- }
-
- // IFLA_IFNAME
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(IFLA_IFNAME, byteBuffer);
- if (nlAttr != null) {
- linkMsg.mInterfaceName = nlAttr.getValueAsString();
- }
-
- return linkMsg;
- }
-
- /**
- * Write a rtnetlink link message to {@link ByteBuffer}.
- */
- @VisibleForTesting
- protected void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer);
- mIfinfomsg.pack(byteBuffer);
-
- if (mMtu != 0) {
- final StructNlAttr mtu = new StructNlAttr(IFLA_MTU, mMtu);
- mtu.pack(byteBuffer);
- }
- if (mHardwareAddress != null) {
- final StructNlAttr hardwareAddress = new StructNlAttr(IFLA_ADDRESS, mHardwareAddress);
- hardwareAddress.pack(byteBuffer);
- }
- if (mInterfaceName != null) {
- final StructNlAttr ifname = new StructNlAttr(IFLA_IFNAME, mInterfaceName);
- ifname.pack(byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- return "RtNetlinkLinkMessage{ "
- + "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, "
- + "Ifinfomsg{" + mIfinfomsg.toString() + "}, "
- + "Hardware Address{" + mHardwareAddress + "}, "
- + "MTU{" + mMtu + "}, "
- + "Ifname{" + mInterfaceName + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java b/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java
deleted file mode 100644
index 4a090151..00000000
--- a/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for rtnetlink neighbor messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class RtNetlinkNeighborMessage extends NetlinkMessage {
- public static final short NDA_UNSPEC = 0;
- public static final short NDA_DST = 1;
- public static final short NDA_LLADDR = 2;
- public static final short NDA_CACHEINFO = 3;
- public static final short NDA_PROBES = 4;
- public static final short NDA_VLAN = 5;
- public static final short NDA_PORT = 6;
- public static final short NDA_VNI = 7;
- public static final short NDA_IFINDEX = 8;
- public static final short NDA_MASTER = 9;
-
- /**
- * Parse routing socket netlink neighbor message from ByteBuffer.
- *
- * @param header netlink message header.
- * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
- */
- @Nullable
- public static RtNetlinkNeighborMessage parse(@NonNull StructNlMsgHdr header,
- @NonNull ByteBuffer byteBuffer) {
- final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header);
-
- neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer);
- if (neighMsg.mNdmsg == null) {
- return null;
- }
-
- // Some of these are message-type dependent, and not always present.
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(NDA_DST, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mDestination = nlAttr.getValueAsInetAddress();
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_LLADDR, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mLinkLayerAddr = nlAttr.nla_value;
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_PROBES, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mNumProbes = nlAttr.getValueAsInt(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_CACHEINFO, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
- }
-
- final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
- neighMsg.mHeader.nlmsg_len - kMinConsumed);
- if (byteBuffer.remaining() < kAdditionalSpace) {
- byteBuffer.position(byteBuffer.limit());
- } else {
- byteBuffer.position(baseOffset + kAdditionalSpace);
- }
-
- return neighMsg;
- }
-
- /**
- * A convenience method to create an RTM_GETNEIGH request message.
- */
- public static byte[] newGetNeighborsRequest(int seqNo) {
- final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final byte[] bytes = new byte[length];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_len = length;
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- nlmsghdr.nlmsg_seq = seqNo;
- nlmsghdr.pack(byteBuffer);
-
- final StructNdMsg ndmsg = new StructNdMsg();
- ndmsg.pack(byteBuffer);
-
- return bytes;
- }
-
- /**
- * A convenience method to create an RTM_NEWNEIGH message, to modify
- * the kernel's state information for a specific neighbor.
- */
- public static byte[] newNewNeighborMessage(
- int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) {
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- nlmsghdr.nlmsg_seq = seqNo;
-
- final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr);
- msg.mNdmsg = new StructNdMsg();
- msg.mNdmsg.ndm_family =
- (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
- msg.mNdmsg.ndm_ifindex = ifIndex;
- msg.mNdmsg.ndm_state = nudState;
- msg.mDestination = ip;
- msg.mLinkLayerAddr = llAddr; // might be null
-
- final byte[] bytes = new byte[msg.getRequiredSpace()];
- nlmsghdr.nlmsg_len = bytes.length;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
- msg.pack(byteBuffer);
- return bytes;
- }
-
- private StructNdMsg mNdmsg;
- private InetAddress mDestination;
- private byte[] mLinkLayerAddr;
- private int mNumProbes;
- private StructNdaCacheInfo mCacheInfo;
-
- private RtNetlinkNeighborMessage(@NonNull StructNlMsgHdr header) {
- super(header);
- mNdmsg = null;
- mDestination = null;
- mLinkLayerAddr = null;
- mNumProbes = 0;
- mCacheInfo = null;
- }
-
- public StructNdMsg getNdHeader() {
- return mNdmsg;
- }
-
- public InetAddress getDestination() {
- return mDestination;
- }
-
- public byte[] getLinkLayerAddress() {
- return mLinkLayerAddr;
- }
-
- public int getProbes() {
- return mNumProbes;
- }
-
- public StructNdaCacheInfo getCacheInfo() {
- return mCacheInfo;
- }
-
- private int getRequiredSpace() {
- int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- if (mDestination != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length);
- }
- if (mLinkLayerAddr != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length);
- }
- // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO
- // attributes appended. Fix later, if necessary.
- return spaceRequired;
- }
-
- private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) {
- final StructNlAttr nlAttr = new StructNlAttr();
- nlAttr.nla_type = nlType;
- nlAttr.nla_value = nlValue;
- nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length);
- nlAttr.pack(byteBuffer);
- }
-
- /**
- * Write a neighbor discovery netlink message to {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer);
- mNdmsg.pack(byteBuffer);
-
- if (mDestination != null) {
- packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer);
- }
- if (mLinkLayerAddr != null) {
- packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress();
- return "RtNetlinkNeighborMessage{ "
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(OsConstants.NETLINK_ROUTE)) + "}, "
- + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, "
- + "destination{" + ipLiteral + "} "
- + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} "
- + "probes{" + mNumProbes + "} "
- + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java b/common/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
deleted file mode 100644
index 9acac69c..00000000
--- a/common/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY;
-import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ANY;
-
-import android.annotation.SuppressLint;
-import android.net.IpPrefix;
-import android.system.OsConstants;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-
-/**
- * A NetlinkMessage subclass for rtnetlink route messages.
- *
- * RtNetlinkRouteMessage.parse() must be called with a ByteBuffer that contains exactly one
- * netlink message.
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class RtNetlinkRouteMessage extends NetlinkMessage {
- public static final short RTA_DST = 1;
- public static final short RTA_OIF = 4;
- public static final short RTA_GATEWAY = 5;
- public static final short RTA_CACHEINFO = 12;
-
- private int mIfindex;
- @NonNull
- private StructRtMsg mRtmsg;
- @NonNull
- private IpPrefix mDestination;
- @Nullable
- private InetAddress mGateway;
- @Nullable
- private StructRtaCacheInfo mRtaCacheInfo;
-
- private RtNetlinkRouteMessage(StructNlMsgHdr header) {
- super(header);
- mRtmsg = null;
- mDestination = null;
- mGateway = null;
- mIfindex = 0;
- mRtaCacheInfo = null;
- }
-
- public int getInterfaceIndex() {
- return mIfindex;
- }
-
- @NonNull
- public StructRtMsg getRtMsgHeader() {
- return mRtmsg;
- }
-
- @NonNull
- public IpPrefix getDestination() {
- return mDestination;
- }
-
- @Nullable
- public InetAddress getGateway() {
- return mGateway;
- }
-
- @Nullable
- public StructRtaCacheInfo getRtaCacheInfo() {
- return mRtaCacheInfo;
- }
-
- /**
- * Check whether the address families of destination and gateway match rtm_family in
- * StructRtmsg.
- *
- * For example, IPv4-mapped IPv6 addresses as an IPv6 address will be always converted to IPv4
- * address, that's incorrect when upper layer creates a new {@link RouteInfo} class instance
- * for IPv6 route with the converted IPv4 gateway.
- */
- private static boolean matchRouteAddressFamily(@NonNull final InetAddress address,
- int family) {
- return ((address instanceof Inet4Address) && (family == AF_INET))
- || ((address instanceof Inet6Address) && (family == AF_INET6));
- }
-
- /**
- * Parse rtnetlink route message from {@link ByteBuffer}. This method must be called with a
- * ByteBuffer that contains exactly one netlink message.
- *
- * @param header netlink message header.
- * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
- */
- @SuppressLint("NewApi")
- @Nullable
- public static RtNetlinkRouteMessage parse(@NonNull final StructNlMsgHdr header,
- @NonNull final ByteBuffer byteBuffer) {
- final RtNetlinkRouteMessage routeMsg = new RtNetlinkRouteMessage(header);
-
- routeMsg.mRtmsg = StructRtMsg.parse(byteBuffer);
- if (routeMsg.mRtmsg == null) return null;
- int rtmFamily = routeMsg.mRtmsg.family;
-
- // RTA_DST
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(RTA_DST, byteBuffer);
- if (nlAttr != null) {
- final InetAddress destination = nlAttr.getValueAsInetAddress();
- // If the RTA_DST attribute is malformed, return null.
- if (destination == null) return null;
- // If the address family of destination doesn't match rtm_family, return null.
- if (!matchRouteAddressFamily(destination, rtmFamily)) return null;
- routeMsg.mDestination = new IpPrefix(destination, routeMsg.mRtmsg.dstLen);
- } else if (rtmFamily == AF_INET) {
- routeMsg.mDestination = new IpPrefix(IPV4_ADDR_ANY, 0);
- } else if (rtmFamily == AF_INET6) {
- routeMsg.mDestination = new IpPrefix(IPV6_ADDR_ANY, 0);
- } else {
- return null;
- }
-
- // RTA_GATEWAY
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(RTA_GATEWAY, byteBuffer);
- if (nlAttr != null) {
- routeMsg.mGateway = nlAttr.getValueAsInetAddress();
- // If the RTA_GATEWAY attribute is malformed, return null.
- if (routeMsg.mGateway == null) return null;
- // If the address family of gateway doesn't match rtm_family, return null.
- if (!matchRouteAddressFamily(routeMsg.mGateway, rtmFamily)) return null;
- }
-
- // RTA_OIF
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(RTA_OIF, byteBuffer);
- if (nlAttr != null) {
- // Any callers that deal with interface names are responsible for converting
- // the interface index to a name themselves. This may not succeed or may be
- // incorrect, because the interface might have been deleted, or even deleted
- // and re-added with a different index, since the netlink message was sent.
- routeMsg.mIfindex = nlAttr.getValueAsInt(0 /* 0 isn't a valid ifindex */);
- }
-
- // RTA_CACHEINFO
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(RTA_CACHEINFO, byteBuffer);
- if (nlAttr != null) {
- routeMsg.mRtaCacheInfo = StructRtaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
- }
-
- return routeMsg;
- }
-
- /**
- * Write a rtnetlink address message to {@link ByteBuffer}.
- */
- @VisibleForTesting
- protected void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer);
- mRtmsg.pack(byteBuffer);
-
- final StructNlAttr destination = new StructNlAttr(RTA_DST, mDestination.getAddress());
- destination.pack(byteBuffer);
-
- if (mGateway != null) {
- final StructNlAttr gateway = new StructNlAttr(RTA_GATEWAY, mGateway.getAddress());
- gateway.pack(byteBuffer);
- }
- if (mIfindex != 0) {
- final StructNlAttr ifindex = new StructNlAttr(RTA_OIF, mIfindex);
- ifindex.pack(byteBuffer);
- }
- if (mRtaCacheInfo != null) {
- final StructNlAttr cacheInfo = new StructNlAttr(RTA_CACHEINFO,
- mRtaCacheInfo.writeToBytes());
- cacheInfo.pack(byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- return "RtNetlinkRouteMessage{ "
- + "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, "
- + "Rtmsg{" + mRtmsg.toString() + "}, "
- + "destination{" + mDestination.getAddress().getHostAddress() + "}, "
- + "gateway{" + (mGateway == null ? "" : mGateway.getHostAddress()) + "}, "
- + "ifindex{" + mIfindex + "}, "
- + "rta_cacheinfo{" + (mRtaCacheInfo == null ? "" : mRtaCacheInfo.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructIfacacheInfo.java b/common/device/com/android/net/module/util/netlink/StructIfacacheInfo.java
deleted file mode 100644
index 360f56d2..00000000
--- a/common/device/com/android/net/module/util/netlink/StructIfacacheInfo.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct ifa_cacheinfo
- *
- * see also:
- *
- * include/uapi/linux/if_addr.h
- *
- * @hide
- */
-public class StructIfacacheInfo extends Struct {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- @Field(order = 0, type = Type.U32)
- public final long preferred;
- @Field(order = 1, type = Type.U32)
- public final long valid;
- @Field(order = 2, type = Type.U32)
- public final long cstamp; // created timestamp, hundredths of seconds.
- @Field(order = 3, type = Type.U32)
- public final long tstamp; // updated timestamp, hundredths of seconds.
-
- StructIfacacheInfo(long preferred, long valid, long cstamp, long tstamp) {
- this.preferred = preferred;
- this.valid = valid;
- this.cstamp = cstamp;
- this.tstamp = tstamp;
- }
-
- /**
- * Parse an ifa_cacheinfo struct from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the ifa_cacheinfo.
- * @return the parsed ifa_cacheinfo struct, or {@code null} if the ifa_cacheinfo struct
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructIfacacheInfo parse(@NonNull final ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) return null;
-
- // The ByteOrder must already have been set to native order.
- return Struct.parse(StructIfacacheInfo.class, byteBuffer);
- }
-
- /**
- * Write an ifa_cacheinfo struct to {@link ByteBuffer}.
- */
- public void pack(@NonNull final ByteBuffer byteBuffer) {
- // The ByteOrder must already have been set to native order.
- this.writeToByteBuffer(byteBuffer);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructIfaddrMsg.java b/common/device/com/android/net/module/util/netlink/StructIfaddrMsg.java
deleted file mode 100644
index f9781a7b..00000000
--- a/common/device/com/android/net/module/util/netlink/StructIfaddrMsg.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct ifaddrmsg
- *
- * see also:
- *
- * include/uapi/linux/if_addr.h
- *
- * @hide
- */
-public class StructIfaddrMsg extends Struct {
- // Already aligned.
- public static final int STRUCT_SIZE = 8;
-
- @Field(order = 0, type = Type.U8)
- public final short family;
- @Field(order = 1, type = Type.U8)
- public final short prefixLen;
- @Field(order = 2, type = Type.U8)
- public final short flags;
- @Field(order = 3, type = Type.U8)
- public final short scope;
- @Field(order = 4, type = Type.S32)
- public final int index;
-
- public StructIfaddrMsg(short family, short prefixLen, short flags, short scope, int index) {
- this.family = family;
- this.prefixLen = prefixLen;
- this.flags = flags;
- this.scope = scope;
- this.index = index;
- }
-
- /**
- * Parse an ifaddrmsg struct from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the ifaddrmsg.
- * @return the parsed ifaddrmsg struct, or {@code null} if the ifaddrmsg struct
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructIfaddrMsg parse(@NonNull final ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) return null;
-
- // The ByteOrder must already have been set to native order.
- return Struct.parse(StructIfaddrMsg.class, byteBuffer);
- }
-
- /**
- * Write an ifaddrmsg struct to {@link ByteBuffer}.
- */
- public void pack(@NonNull final ByteBuffer byteBuffer) {
- // The ByteOrder must already have been set to native order.
- this.writeToByteBuffer(byteBuffer);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructIfinfoMsg.java b/common/device/com/android/net/module/util/netlink/StructIfinfoMsg.java
deleted file mode 100644
index 02d1574b..00000000
--- a/common/device/com/android/net/module/util/netlink/StructIfinfoMsg.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct ifinfomsg
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class StructIfinfoMsg extends Struct {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- @Field(order = 0, type = Type.U8, padding = 1)
- public final short family;
- @Field(order = 1, type = Type.U16)
- public final int type;
- @Field(order = 2, type = Type.S32)
- public final int index;
- @Field(order = 3, type = Type.U32)
- public final long flags;
- @Field(order = 4, type = Type.U32)
- public final long change;
-
- StructIfinfoMsg(short family, int type, int index, long flags, long change) {
- this.family = family;
- this.type = type;
- this.index = index;
- this.flags = flags;
- this.change = change;
- }
-
- /**
- * Parse an ifinfomsg struct from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the ifinfomsg.
- * @return the parsed ifinfomsg struct, or {@code null} if the ifinfomsg struct
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructIfinfoMsg parse(@NonNull final ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) return null;
-
- // The ByteOrder must already have been set to native order.
- return Struct.parse(StructIfinfoMsg.class, byteBuffer);
- }
-
- /**
- * Write an ifinfomsg struct to {@link ByteBuffer}.
- */
- public void pack(@NonNull final ByteBuffer byteBuffer) {
- // The ByteOrder must already have been set to native order.
- this.writeToByteBuffer(byteBuffer);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructInetDiagMsg.java b/common/device/com/android/net/module/util/netlink/StructInetDiagMsg.java
deleted file mode 100644
index cbd895d6..00000000
--- a/common/device/com/android/net/module/util/netlink/StructInetDiagMsg.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_msg
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_msg {
- * __u8 idiag_family;
- * __u8 idiag_state;
- * __u8 idiag_timer;
- * __u8 idiag_retrans;
- * struct inet_diag_sockid id;
- * __u32 idiag_expires;
- * __u32 idiag_rqueue;
- * __u32 idiag_wqueue;
- * __u32 idiag_uid;
- * __u32 idiag_inode;
- * };
- *
- * @hide
- */
-public class StructInetDiagMsg {
- public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
- public short idiag_family;
- public short idiag_state;
- public short idiag_timer;
- public short idiag_retrans;
- @NonNull
- public StructInetDiagSockId id;
- public long idiag_expires;
- public long idiag_rqueue;
- public long idiag_wqueue;
- // Use int for uid since other code use int for uid and uid fits to int
- public int idiag_uid;
- public long idiag_inode;
-
- private static short unsignedByte(byte b) {
- return (short) (b & 0xFF);
- }
-
- /**
- * Parse inet diag netlink message from buffer.
- */
- @Nullable
- public static StructInetDiagMsg parse(@NonNull ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) {
- return null;
- }
- StructInetDiagMsg struct = new StructInetDiagMsg();
- struct.idiag_family = unsignedByte(byteBuffer.get());
- struct.idiag_state = unsignedByte(byteBuffer.get());
- struct.idiag_timer = unsignedByte(byteBuffer.get());
- struct.idiag_retrans = unsignedByte(byteBuffer.get());
- struct.id = StructInetDiagSockId.parse(byteBuffer, struct.idiag_family);
- if (struct.id == null) {
- return null;
- }
- struct.idiag_expires = Integer.toUnsignedLong(byteBuffer.getInt());
- struct.idiag_rqueue = Integer.toUnsignedLong(byteBuffer.getInt());
- struct.idiag_wqueue = Integer.toUnsignedLong(byteBuffer.getInt());
- struct.idiag_uid = byteBuffer.getInt();
- struct.idiag_inode = Integer.toUnsignedLong(byteBuffer.getInt());
- return struct;
- }
-
- @Override
- public String toString() {
- return "StructInetDiagMsg{ "
- + "idiag_family{" + idiag_family + "}, "
- + "idiag_state{" + idiag_state + "}, "
- + "idiag_timer{" + idiag_timer + "}, "
- + "idiag_retrans{" + idiag_retrans + "}, "
- + "id{" + id + "}, "
- + "idiag_expires{" + idiag_expires + "}, "
- + "idiag_rqueue{" + idiag_rqueue + "}, "
- + "idiag_wqueue{" + idiag_wqueue + "}, "
- + "idiag_uid{" + idiag_uid + "}, "
- + "idiag_inode{" + idiag_inode + "}, "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java b/common/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java
deleted file mode 100644
index 3b47008a..00000000
--- a/common/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_req_v2
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_req_v2 {
- * __u8 sdiag_family;
- * __u8 sdiag_protocol;
- * __u8 idiag_ext;
- * __u8 pad;
- * __u32 idiag_states;
- * struct inet_diag_sockid id;
- * };
- *
- * @hide
- */
-public class StructInetDiagReqV2 {
- public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
-
- private final byte mSdiagFamily;
- private final byte mSdiagProtocol;
- private final byte mIdiagExt;
- private final byte mPad;
- private final StructInetDiagSockId mId;
- private final int mState;
- public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
- public StructInetDiagReqV2(int protocol, @Nullable StructInetDiagSockId id, int family, int pad,
- int extension, int state) {
- mSdiagFamily = (byte) family;
- mSdiagProtocol = (byte) protocol;
- mId = id;
- mPad = (byte) pad;
- mIdiagExt = (byte) extension;
- mState = state;
- }
-
- /**
- * Write the int diag request v2 message to ByteBuffer.
- */
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller.
- byteBuffer.put((byte) mSdiagFamily);
- byteBuffer.put((byte) mSdiagProtocol);
- byteBuffer.put((byte) mIdiagExt);
- byteBuffer.put((byte) mPad);
- byteBuffer.putInt(mState);
- if (mId != null) mId.pack(byteBuffer);
- }
-
- @Override
- public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
- final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
-
- return "StructInetDiagReqV2{ "
- + "sdiag_family{" + familyStr + "}, "
- + "sdiag_protocol{" + protocolStr + "}, "
- + "idiag_ext{" + mIdiagExt + ")}, "
- + "pad{" + mPad + "}, "
- + "idiag_states{" + Integer.toHexString(mState) + "}, "
- + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructInetDiagSockId.java b/common/device/com/android/net/module/util/netlink/StructInetDiagSockId.java
deleted file mode 100644
index dd85934c..00000000
--- a/common/device/com/android/net/module/util/netlink/StructInetDiagSockId.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_LEN;
-import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * struct inet_diag_req_v2
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_sockid {
- * __be16 idiag_sport;
- * __be16 idiag_dport;
- * __be32 idiag_src[4];
- * __be32 idiag_dst[4];
- * __u32 idiag_if;
- * __u32 idiag_cookie[2];
- * #define INET_DIAG_NOCOOKIE (~0U)
- * };
- *
- * @hide
- */
-public class StructInetDiagSockId {
- private static final String TAG = StructInetDiagSockId.class.getSimpleName();
- public static final int STRUCT_SIZE = 48;
-
- private static final long INET_DIAG_NOCOOKIE = ~0L;
- private static final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- public final InetSocketAddress locSocketAddress;
- public final InetSocketAddress remSocketAddress;
- public final int ifIndex;
- public final long cookie;
-
- public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
- this(loc, rem, 0 /* ifIndex */, INET_DIAG_NOCOOKIE);
- }
-
- public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem,
- int ifIndex, long cookie) {
- this.locSocketAddress = loc;
- this.remSocketAddress = rem;
- this.ifIndex = ifIndex;
- this.cookie = cookie;
- }
-
- /**
- * Parse inet diag socket id from buffer.
- */
- @Nullable
- public static StructInetDiagSockId parse(final ByteBuffer byteBuffer, final short family) {
- if (byteBuffer.remaining() < STRUCT_SIZE) {
- return null;
- }
-
- byteBuffer.order(BIG_ENDIAN);
- final int srcPort = Short.toUnsignedInt(byteBuffer.getShort());
- final int dstPort = Short.toUnsignedInt(byteBuffer.getShort());
-
- final InetAddress srcAddr;
- final InetAddress dstAddr;
- if (family == AF_INET) {
- final byte[] srcAddrByte = new byte[IPV4_ADDR_LEN];
- final byte[] dstAddrByte = new byte[IPV4_ADDR_LEN];
- byteBuffer.get(srcAddrByte);
- // Address always uses IPV6_ADDR_LEN in the buffer. So if the address is IPv4, position
- // needs to be advanced to the next field.
- byteBuffer.position(byteBuffer.position() + (IPV6_ADDR_LEN - IPV4_ADDR_LEN));
- byteBuffer.get(dstAddrByte);
- byteBuffer.position(byteBuffer.position() + (IPV6_ADDR_LEN - IPV4_ADDR_LEN));
- try {
- srcAddr = Inet4Address.getByAddress(srcAddrByte);
- dstAddr = Inet4Address.getByAddress(dstAddrByte);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Failed to parse address: " + e);
- return null;
- }
- } else if (family == AF_INET6) {
- final byte[] srcAddrByte = new byte[IPV6_ADDR_LEN];
- final byte[] dstAddrByte = new byte[IPV6_ADDR_LEN];
- byteBuffer.get(srcAddrByte);
- byteBuffer.get(dstAddrByte);
- try {
- // Using Inet6Address.getByAddress to be consistent with idiag_family field since
- // InetAddress.getByAddress returns Inet4Address if the address is v4-mapped v6
- // address.
- srcAddr = Inet6Address.getByAddress(
- null /* host */, srcAddrByte, -1 /* scope_id */);
- dstAddr = Inet6Address.getByAddress(
- null /* host */, dstAddrByte, -1 /* scope_id */);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Failed to parse address: " + e);
- return null;
- }
- } else {
- Log.wtf(TAG, "Invalid address family: " + family);
- return null;
- }
-
- final InetSocketAddress srcSocketAddr = new InetSocketAddress(srcAddr, srcPort);
- final InetSocketAddress dstSocketAddr = new InetSocketAddress(dstAddr, dstPort);
-
- byteBuffer.order(ByteOrder.nativeOrder());
- final int ifIndex = byteBuffer.getInt();
- final long cookie = byteBuffer.getLong();
- return new StructInetDiagSockId(srcSocketAddr, dstSocketAddr, ifIndex, cookie);
- }
-
- /**
- * Write inet diag socket id message to ByteBuffer in big endian.
- */
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.order(BIG_ENDIAN);
- byteBuffer.putShort((short) locSocketAddress.getPort());
- byteBuffer.putShort((short) remSocketAddress.getPort());
- byteBuffer.put(locSocketAddress.getAddress().getAddress());
- if (locSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.put(remSocketAddress.getAddress().getAddress());
- if (remSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.order(ByteOrder.nativeOrder());
- byteBuffer.putInt(ifIndex);
- byteBuffer.putLong(cookie);
- }
-
- @Override
- public String toString() {
- return "StructInetDiagSockId{ "
- + "idiag_sport{" + locSocketAddress.getPort() + "}, "
- + "idiag_dport{" + remSocketAddress.getPort() + "}, "
- + "idiag_src{" + locSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_dst{" + remSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_if{" + ifIndex + "}, "
- + "idiag_cookie{"
- + (cookie == INET_DIAG_NOCOOKIE ? "INET_DIAG_NOCOOKIE" : cookie) + "}"
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNdMsg.java b/common/device/com/android/net/module/util/netlink/StructNdMsg.java
deleted file mode 100644
index 53ce8991..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNdMsg.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct ndmsg
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdMsg {
- // Already aligned.
- public static final int STRUCT_SIZE = 12;
-
- // Neighbor Cache Entry States
- public static final short NUD_NONE = 0x00;
- public static final short NUD_INCOMPLETE = 0x01;
- public static final short NUD_REACHABLE = 0x02;
- public static final short NUD_STALE = 0x04;
- public static final short NUD_DELAY = 0x08;
- public static final short NUD_PROBE = 0x10;
- public static final short NUD_FAILED = 0x20;
- public static final short NUD_NOARP = 0x40;
- public static final short NUD_PERMANENT = 0x80;
-
- /**
- * Convert neighbor cache entry state integer to string.
- */
- public static String stringForNudState(short nudState) {
- switch (nudState) {
- case NUD_NONE: return "NUD_NONE";
- case NUD_INCOMPLETE: return "NUD_INCOMPLETE";
- case NUD_REACHABLE: return "NUD_REACHABLE";
- case NUD_STALE: return "NUD_STALE";
- case NUD_DELAY: return "NUD_DELAY";
- case NUD_PROBE: return "NUD_PROBE";
- case NUD_FAILED: return "NUD_FAILED";
- case NUD_NOARP: return "NUD_NOARP";
- case NUD_PERMANENT: return "NUD_PERMANENT";
- default:
- return "unknown NUD state: " + String.valueOf(nudState);
- }
- }
-
- /**
- * Check whether a neighbor is connected or not.
- */
- public static boolean isNudStateConnected(short nudState) {
- return ((nudState & (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE)) != 0);
- }
-
- /**
- * Check whether a neighbor is in the valid NUD state or not.
- */
- public static boolean isNudStateValid(short nudState) {
- return (isNudStateConnected(nudState)
- || ((nudState & (NUD_PROBE | NUD_STALE | NUD_DELAY)) != 0));
- }
-
- // Neighbor Cache Entry Flags
- public static byte NTF_USE = (byte) 0x01;
- public static byte NTF_SELF = (byte) 0x02;
- public static byte NTF_MASTER = (byte) 0x04;
- public static byte NTF_PROXY = (byte) 0x08;
- public static byte NTF_ROUTER = (byte) 0x80;
-
- private static String stringForNudFlags(byte flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NTF_USE) != 0) {
- sb.append("NTF_USE");
- }
- if ((flags & NTF_SELF) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NTF_SELF");
- }
- if ((flags & NTF_MASTER) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NTF_MASTER");
- }
- if ((flags & NTF_PROXY) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NTF_PROXY");
- }
- if ((flags & NTF_ROUTER) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NTF_ROUTER");
- }
- return sb.toString();
- }
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- /**
- * Parse a neighbor discovery netlink message header from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the nd netlink message header.
- * @return the parsed nd netlink message header, or {@code null} if the nd netlink message
- * header could not be parsed successfully (for example, if it was truncated).
- */
- public static StructNdMsg parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdMsg struct = new StructNdMsg();
- struct.ndm_family = byteBuffer.get();
- final byte pad1 = byteBuffer.get();
- final short pad2 = byteBuffer.getShort();
- struct.ndm_ifindex = byteBuffer.getInt();
- struct.ndm_state = byteBuffer.getShort();
- struct.ndm_flags = byteBuffer.get();
- struct.ndm_type = byteBuffer.get();
- return struct;
- }
-
- public byte ndm_family;
- public int ndm_ifindex;
- public short ndm_state;
- public byte ndm_flags;
- public byte ndm_type;
-
- public StructNdMsg() {
- ndm_family = (byte) OsConstants.AF_UNSPEC;
- }
-
- /**
- * Write the neighbor discovery message header to {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- byteBuffer.put(ndm_family);
- byteBuffer.put((byte) 0); // pad1
- byteBuffer.putShort((short) 0); // pad2
- byteBuffer.putInt(ndm_ifindex);
- byteBuffer.putShort(ndm_state);
- byteBuffer.put(ndm_flags);
- byteBuffer.put(ndm_type);
- }
-
- /**
- * Check whether a neighbor is connected or not.
- */
- public boolean nudConnected() {
- return isNudStateConnected(ndm_state);
- }
-
- /**
- * Check whether a neighbor is in the valid NUD state or not.
- */
- public boolean nudValid() {
- return isNudStateValid(ndm_state);
- }
-
- @Override
- public String toString() {
- final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")";
- final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")";
- return "StructNdMsg{ "
- + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, "
- + "ifindex{" + ndm_ifindex + "}, "
- + "state{" + stateStr + "}, "
- + "flags{" + flagsStr + "}, "
- + "type{" + ndm_type + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java b/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java
deleted file mode 100644
index 82263466..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.annotation.SuppressLint;
-import android.net.IpPrefix;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-
-/**
- * The PREF64 router advertisement option. RFC 8781.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Scaled Lifetime | PLC |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | Highest 96 bits of the Prefix |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- */
-public class StructNdOptPref64 extends NdOption {
- public static final int STRUCT_SIZE = 16;
- public static final int TYPE = 38;
- public static final byte LENGTH = 2;
-
- private static final String TAG = StructNdOptPref64.class.getSimpleName();
-
- /**
- * How many seconds the prefix is expected to remain valid.
- * Valid values are from 0 to 65528 in multiples of 8.
- */
- public final int lifetime;
- /** The NAT64 prefix. */
- @NonNull public final IpPrefix prefix;
-
- static int plcToPrefixLength(int plc) {
- switch (plc) {
- case 0: return 96;
- case 1: return 64;
- case 2: return 56;
- case 3: return 48;
- case 4: return 40;
- case 5: return 32;
- default:
- throw new IllegalArgumentException("Invalid prefix length code " + plc);
- }
- }
-
- static int prefixLengthToPlc(int prefixLength) {
- switch (prefixLength) {
- case 96: return 0;
- case 64: return 1;
- case 56: return 2;
- case 48: return 3;
- case 40: return 4;
- case 32: return 5;
- default:
- throw new IllegalArgumentException("Invalid prefix length " + prefixLength);
- }
- }
-
- /**
- * Returns the 2-byte "scaled lifetime and prefix length code" field: 13-bit lifetime, 3-bit PLC
- */
- static short getScaledLifetimePlc(int lifetime, int prefixLengthCode) {
- return (short) ((lifetime & 0xfff8) | (prefixLengthCode & 0x7));
- }
-
- public StructNdOptPref64(@NonNull IpPrefix prefix, int lifetime) {
- super((byte) TYPE, LENGTH);
-
- Objects.requireNonNull(prefix, "prefix must not be null");
- if (!(prefix.getAddress() instanceof Inet6Address)) {
- throw new IllegalArgumentException("Must be an IPv6 prefix: " + prefix);
- }
- prefixLengthToPlc(prefix.getPrefixLength()); // Throw if the prefix length is invalid.
- this.prefix = prefix;
-
- if (lifetime < 0 || lifetime > 0xfff8) {
- throw new IllegalArgumentException("Invalid lifetime " + lifetime);
- }
- this.lifetime = lifetime & 0xfff8;
- }
-
- @SuppressLint("NewApi")
- private StructNdOptPref64(@NonNull ByteBuffer buf) {
- super(buf.get(), Byte.toUnsignedInt(buf.get()));
- if (type != TYPE) throw new IllegalArgumentException("Invalid type " + type);
- if (length != LENGTH) throw new IllegalArgumentException("Invalid length " + length);
-
- int scaledLifetimePlc = Short.toUnsignedInt(buf.getShort());
- lifetime = scaledLifetimePlc & 0xfff8;
-
- byte[] addressBytes = new byte[16];
- buf.get(addressBytes, 0, 12);
- InetAddress addr;
- try {
- addr = InetAddress.getByAddress(addressBytes);
- } catch (UnknownHostException e) {
- throw new AssertionError("16-byte array not valid InetAddress?");
- }
- prefix = new IpPrefix(addr, plcToPrefixLength(scaledLifetimePlc & 7));
- }
-
- /**
- * Parses an option from a {@link ByteBuffer}.
- *
- * @param buf The buffer from which to parse the option. The buffer's byte order must be
- * {@link java.nio.ByteOrder#BIG_ENDIAN}.
- * @return the parsed option, or {@code null} if the option could not be parsed successfully
- * (for example, if it was truncated, or if the prefix length code was wrong).
- */
- public static StructNdOptPref64 parse(@NonNull ByteBuffer buf) {
- if (buf.remaining() < STRUCT_SIZE) return null;
- try {
- return new StructNdOptPref64(buf);
- } catch (IllegalArgumentException e) {
- // Not great, but better than throwing an exception that might crash the caller.
- // Convention in this package is that null indicates that the option was truncated, so
- // callers must already handle it.
- Log.d(TAG, "Invalid PREF64 option: " + e);
- return null;
- }
- }
-
- protected void writeToByteBuffer(ByteBuffer buf) {
- super.writeToByteBuffer(buf);
- buf.putShort(getScaledLifetimePlc(lifetime, prefixLengthToPlc(prefix.getPrefixLength())));
- buf.put(prefix.getRawAddress(), 0, 12);
- }
-
- /** Outputs the wire format of the option to a new big-endian ByteBuffer. */
- public ByteBuffer toByteBuffer() {
- ByteBuffer buf = ByteBuffer.allocate(STRUCT_SIZE);
- writeToByteBuffer(buf);
- buf.flip();
- return buf;
- }
-
- @Override
- @NonNull
- public String toString() {
- return String.format("NdOptPref64(%s, %d)", prefix, lifetime);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java b/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java
deleted file mode 100644
index 6dee0c49..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN;
-
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.structs.RdnssOption;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-import java.util.StringJoiner;
-
-/**
- * The Recursive DNS Server Option. RFC 8106.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * : Addresses of IPv6 Recursive DNS Servers :
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class StructNdOptRdnss extends NdOption {
- private static final String TAG = StructNdOptRdnss.class.getSimpleName();
- public static final int TYPE = 25;
- // Length in 8-byte units, only if one IPv6 address included.
- public static final byte MIN_OPTION_LEN = 3;
-
- public final RdnssOption header;
- @NonNull
- public final Inet6Address[] servers;
-
- public StructNdOptRdnss(@NonNull final Inet6Address[] servers, long lifetime) {
- super((byte) TYPE, servers.length * 2 + 1);
-
- Objects.requireNonNull(servers, "Recursive DNS Servers address array must not be null");
- if (servers.length == 0) {
- throw new IllegalArgumentException("DNS server address array must not be empty");
- }
-
- this.header = new RdnssOption((byte) TYPE, (byte) (servers.length * 2 + 1),
- (short) 0 /* reserved */, lifetime);
- this.servers = servers.clone();
- }
-
- /**
- * Parses an RDNSS option from a {@link ByteBuffer}.
- *
- * @param buf The buffer from which to parse the option. The buffer's byte order must be
- * {@link java.nio.ByteOrder#BIG_ENDIAN}.
- * @return the parsed option, or {@code null} if the option could not be parsed successfully.
- */
- public static StructNdOptRdnss parse(@NonNull ByteBuffer buf) {
- if (buf == null || buf.remaining() < MIN_OPTION_LEN * 8) return null;
- try {
- final RdnssOption header = Struct.parse(RdnssOption.class, buf);
- if (header.type != TYPE) {
- throw new IllegalArgumentException("Invalid type " + header.type);
- }
- if (header.length < MIN_OPTION_LEN || (header.length % 2 == 0)) {
- throw new IllegalArgumentException("Invalid length " + header.length);
- }
-
- final int numOfDnses = (header.length - 1) / 2;
- final Inet6Address[] servers = new Inet6Address[numOfDnses];
- for (int i = 0; i < numOfDnses; i++) {
- byte[] rawAddress = new byte[IPV6_ADDR_LEN];
- buf.get(rawAddress);
- servers[i] = (Inet6Address) InetAddress.getByAddress(rawAddress);
- }
- return new StructNdOptRdnss(servers, header.lifetime);
- } catch (IllegalArgumentException | BufferUnderflowException | UnknownHostException e) {
- // Not great, but better than throwing an exception that might crash the caller.
- // Convention in this package is that null indicates that the option was truncated
- // or malformed, so callers must already handle it.
- Log.d(TAG, "Invalid RDNSS option: " + e);
- return null;
- }
- }
-
- protected void writeToByteBuffer(ByteBuffer buf) {
- header.writeToByteBuffer(buf);
- for (int i = 0; i < servers.length; i++) {
- buf.put(servers[i].getAddress());
- }
- }
-
- /** Outputs the wire format of the option to a new big-endian ByteBuffer. */
- public ByteBuffer toByteBuffer() {
- final ByteBuffer buf = ByteBuffer.allocate(Struct.getSize(RdnssOption.class)
- + servers.length * IPV6_ADDR_LEN);
- writeToByteBuffer(buf);
- buf.flip();
- return buf;
- }
-
- @Override
- @NonNull
- public String toString() {
- final StringJoiner sj = new StringJoiner(",", "[", "]");
- for (int i = 0; i < servers.length; i++) {
- sj.add(servers[i].getHostAddress());
- }
- return String.format("NdOptRdnss(%s,servers:%s)", header.toString(), sj.toString());
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNdaCacheInfo.java b/common/device/com/android/net/module/util/netlink/StructNdaCacheInfo.java
deleted file mode 100644
index 1f9bb7ec..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNdaCacheInfo.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import static com.android.net.module.util.netlink.NetlinkUtils.ticksToMilliSeconds;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct nda_cacheinfo
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdaCacheInfo {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- /**
- * Parse a nd cacheinfo netlink attribute from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the nd cacheinfo attribute.
- * @return the parsed nd cacheinfo attribute, or {@code null} if the nd cacheinfo attribute
- * could not be parsed successfully (for example, if it was truncated).
- */
- public static StructNdaCacheInfo parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdaCacheInfo struct = new StructNdaCacheInfo();
- struct.ndm_used = byteBuffer.getInt();
- struct.ndm_confirmed = byteBuffer.getInt();
- struct.ndm_updated = byteBuffer.getInt();
- struct.ndm_refcnt = byteBuffer.getInt();
- return struct;
- }
-
- /**
- * Explanatory notes, for reference.
- *
- * Before being returned to user space, the neighbor entry times are
- * converted to clock_t's like so:
- *
- * ndm_used = jiffies_to_clock_t(now - neigh->used);
- * ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
- * ndm_updated = jiffies_to_clock_t(now - neigh->updated);
- *
- * meaning that these values are expressed as "clock ticks ago". To
- * convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK).
- * When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed
- * in centiseconds.
- *
- * These values are unsigned, but fortunately being expressed as "some
- * clock ticks ago", these values are typically very small (and
- * 2^31 centiseconds = 248 days).
- *
- * By observation, it appears that:
- * ndm_used: the last time ARP/ND took place for this neighbor
- * ndm_confirmed: the last time ARP/ND succeeded for this neighbor OR
- * higher layer confirmation (TCP or MSG_CONFIRM)
- * was received
- * ndm_updated: the time when the current NUD state was entered
- */
- public int ndm_used;
- public int ndm_confirmed;
- public int ndm_updated;
- public int ndm_refcnt;
-
- public StructNdaCacheInfo() {}
-
- /**
- * The last time ARP/ND took place for this neighbor.
- */
- public long lastUsed() {
- return ticksToMilliSeconds(ndm_used);
- }
-
- /**
- * The last time ARP/ND succeeded for this neighbor or higher layer confirmation (TCP or
- * MSG_CONFIRM) was received.
- */
- public long lastConfirmed() {
- return ticksToMilliSeconds(ndm_confirmed);
- }
-
- /**
- * The time when the current NUD state was entered.
- */
- public long lastUpdated() {
- return ticksToMilliSeconds(ndm_updated);
- }
-
- @Override
- public String toString() {
- return "NdaCacheInfo{ "
- + "ndm_used{" + lastUsed() + "}, "
- + "ndm_confirmed{" + lastConfirmed() + "}, "
- + "ndm_updated{" + lastUpdated() + "}, "
- + "ndm_refcnt{" + ndm_refcnt + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNfGenMsg.java b/common/device/com/android/net/module/util/netlink/StructNfGenMsg.java
deleted file mode 100644
index 2de5490b..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNfGenMsg.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * struct nfgenmsg
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink.h
- *
- * @hide
- */
-public class StructNfGenMsg {
- public static final int STRUCT_SIZE = 2 + Short.BYTES;
-
- public static final int NFNETLINK_V0 = 0;
-
- public final byte nfgen_family;
- public final byte version;
- public final short res_id; // N.B.: this is big endian in the kernel
-
- /**
- * Parse a netfilter netlink header from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the netfilter netlink header.
- * @return the parsed netfilter netlink header, or {@code null} if the netfilter netlink header
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructNfGenMsg parse(@NonNull ByteBuffer byteBuffer) {
- Objects.requireNonNull(byteBuffer);
-
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- final byte nfgen_family = byteBuffer.get();
- final byte version = byteBuffer.get();
-
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- final short res_id = byteBuffer.getShort();
- byteBuffer.order(originalOrder);
-
- return new StructNfGenMsg(nfgen_family, version, res_id);
- }
-
- public StructNfGenMsg(byte family, byte ver, short id) {
- nfgen_family = family;
- version = ver;
- res_id = id;
- }
-
- public StructNfGenMsg(byte family) {
- nfgen_family = family;
- version = (byte) NFNETLINK_V0;
- res_id = (short) 0;
- }
-
- /**
- * Write a netfilter netlink header to a {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.put(nfgen_family);
- byteBuffer.put(version);
-
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- byteBuffer.putShort(res_id);
- byteBuffer.order(originalOrder);
- }
-
- private static boolean hasAvailableSpace(@NonNull ByteBuffer byteBuffer) {
- return byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- @Override
- public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(nfgen_family);
-
- return "NfGenMsg{ "
- + "nfgen_family{" + familyStr + "}, "
- + "version{" + Byte.toUnsignedInt(version) + "}, "
- + "res_id{" + Short.toUnsignedInt(res_id) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNlAttr.java b/common/device/com/android/net/module/util/netlink/StructNlAttr.java
deleted file mode 100644
index a9b64950..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNlAttr.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-/**
- * struct nlattr
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlAttr {
- // Already aligned.
- public static final int NLA_HEADERLEN = 4;
- public static final int NLA_F_NESTED = (1 << 15);
-
- /**
- * Set carries nested attributes bit.
- */
- public static short makeNestedType(short type) {
- return (short) (type | NLA_F_NESTED);
- }
-
- /**
- * Peek and parse the netlink attribute from {@link ByteBuffer}.
- *
- * Return a (length, type) object only, without consuming any bytes in
- * |byteBuffer| and without copying or interpreting any value bytes.
- * This is used for scanning over a packed set of struct nlattr's,
- * looking for instances of a particular type.
- */
- public static StructNlAttr peek(ByteBuffer byteBuffer) {
- if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) {
- return null;
- }
- final int baseOffset = byteBuffer.position();
-
- final StructNlAttr struct = new StructNlAttr();
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- struct.nla_len = byteBuffer.getShort();
- struct.nla_type = byteBuffer.getShort();
- } finally {
- byteBuffer.order(originalOrder);
- }
-
- byteBuffer.position(baseOffset);
- if (struct.nla_len < NLA_HEADERLEN) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- /**
- * Parse a netlink attribute from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the netlink attriute.
- * @return the parsed netlink attribute, or {@code null} if the netlink attribute
- * could not be parsed successfully (for example, if it was truncated).
- */
- public static StructNlAttr parse(ByteBuffer byteBuffer) {
- final StructNlAttr struct = peek(byteBuffer);
- if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) {
- return null;
- }
-
- final int baseOffset = byteBuffer.position();
- byteBuffer.position(baseOffset + NLA_HEADERLEN);
-
- int valueLen = ((int) struct.nla_len) & 0xffff;
- valueLen -= NLA_HEADERLEN;
- if (valueLen > 0) {
- struct.nla_value = new byte[valueLen];
- byteBuffer.get(struct.nla_value, 0, valueLen);
- byteBuffer.position(baseOffset + struct.getAlignedLength());
- }
- return struct;
- }
-
- /**
- * Find next netlink attribute with a given type from {@link ByteBuffer}.
- *
- * @param attrType The given netlink attribute type is requested for.
- * @param byteBuffer The buffer from which to find the netlink attribute.
- * @return the found netlink attribute, or {@code null} if the netlink attribute could not be
- * found or parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructNlAttr findNextAttrOfType(short attrType,
- @Nullable ByteBuffer byteBuffer) {
- while (byteBuffer != null && byteBuffer.remaining() > 0) {
- final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer);
- if (nlAttr == null) {
- break;
- }
- if (nlAttr.nla_type == attrType) {
- return StructNlAttr.parse(byteBuffer);
- }
- if (byteBuffer.remaining() < nlAttr.getAlignedLength()) {
- break;
- }
- byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength());
- }
- return null;
- }
-
- public short nla_len = (short) NLA_HEADERLEN;
- public short nla_type;
- public byte[] nla_value;
-
- public StructNlAttr() {}
-
- public StructNlAttr(short type, byte value) {
- nla_type = type;
- setValue(new byte[1]);
- nla_value[0] = value;
- }
-
- public StructNlAttr(short type, short value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, short value, ByteOrder order) {
- nla_type = type;
- setValue(new byte[Short.BYTES]);
- final ByteBuffer buf = getValueAsByteBuffer();
- final ByteOrder originalOrder = buf.order();
- try {
- buf.order(order);
- buf.putShort(value);
- } finally {
- buf.order(originalOrder);
- }
- }
-
- public StructNlAttr(short type, int value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, int value, ByteOrder order) {
- nla_type = type;
- setValue(new byte[Integer.BYTES]);
- final ByteBuffer buf = getValueAsByteBuffer();
- final ByteOrder originalOrder = buf.order();
- try {
- buf.order(order);
- buf.putInt(value);
- } finally {
- buf.order(originalOrder);
- }
- }
-
- public StructNlAttr(short type, @NonNull final byte[] value) {
- nla_type = type;
- setValue(value);
- }
-
- public StructNlAttr(short type, @NonNull final InetAddress ip) {
- nla_type = type;
- setValue(ip.getAddress());
- }
-
- public StructNlAttr(short type, @NonNull final MacAddress mac) {
- nla_type = type;
- setValue(mac.toByteArray());
- }
-
- public StructNlAttr(short type, @NonNull final String string) {
- nla_type = type;
- byte[] value = null;
- try {
- final byte[] stringBytes = string.getBytes("UTF-8");
- // Append '\0' at the end of interface name string bytes.
- value = Arrays.copyOf(stringBytes, stringBytes.length + 1);
- } catch (UnsupportedEncodingException ignored) {
- // Do nothing.
- } finally {
- setValue(value);
- }
- }
-
- public StructNlAttr(short type, StructNlAttr... nested) {
- this();
- nla_type = makeNestedType(type);
-
- int payloadLength = 0;
- for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
- setValue(new byte[payloadLength]);
-
- final ByteBuffer buf = getValueAsByteBuffer();
- for (StructNlAttr nla : nested) {
- nla.pack(buf);
- }
- }
-
- /**
- * Get aligned attribute length.
- */
- public int getAlignedLength() {
- return NetlinkConstants.alignedLengthOf(nla_len);
- }
-
- /**
- * Get attribute value as BE16.
- */
- public short getValueAsBe16(short defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Short.BYTES) {
- return defaultValue;
- }
- final ByteOrder originalOrder = byteBuffer.order();
- try {
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- return byteBuffer.getShort();
- } finally {
- byteBuffer.order(originalOrder);
- }
- }
-
- /**
- * Get attribute value as BE32.
- */
- public int getValueAsBe32(int defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
- return defaultValue;
- }
- final ByteOrder originalOrder = byteBuffer.order();
- try {
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- return byteBuffer.getInt();
- } finally {
- byteBuffer.order(originalOrder);
- }
- }
-
- /**
- * Get attribute value as ByteBuffer.
- */
- public ByteBuffer getValueAsByteBuffer() {
- if (nla_value == null) return null;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
- // By convention, all buffers in this library are in native byte order because netlink is in
- // native byte order. It's the order that is used by NetlinkSocket.recvMessage and the only
- // order accepted by NetlinkMessage.parse.
- byteBuffer.order(ByteOrder.nativeOrder());
- return byteBuffer;
- }
-
- /**
- * Get attribute value as byte.
- */
- public byte getValueAsByte(byte defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Byte.BYTES) {
- return defaultValue;
- }
- return getValueAsByteBuffer().get();
- }
-
- /**
- * Get attribute value as Integer, or null if malformed (e.g., length is not 4 bytes).
- */
- public Integer getValueAsInteger() {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
- return null;
- }
- return byteBuffer.getInt();
- }
-
- /**
- * Get attribute value as Int, default value if malformed.
- */
- public int getValueAsInt(int defaultValue) {
- final Integer value = getValueAsInteger();
- return (value != null) ? value : defaultValue;
- }
-
- /**
- * Get attribute value as InetAddress.
- *
- * @return the InetAddress instance representation of attribute value or null if IP address
- * is of illegal length.
- */
- @Nullable
- public InetAddress getValueAsInetAddress() {
- if (nla_value == null) return null;
-
- try {
- return InetAddress.getByAddress(nla_value);
- } catch (UnknownHostException ignored) {
- return null;
- }
- }
-
- /**
- * Get attribute value as MacAddress.
- *
- * @return the MacAddress instance representation of attribute value or null if the given byte
- * array is not a valid representation(e.g, not all link layers have 6-byte link-layer
- * addresses)
- */
- @Nullable
- public MacAddress getValueAsMacAddress() {
- if (nla_value == null) return null;
-
- try {
- return MacAddress.fromBytes(nla_value);
- } catch (IllegalArgumentException ignored) {
- return null;
- }
- }
-
- /**
- * Get attribute value as a unicode string.
- *
- * @return a unicode string or null if UTF-8 charset is not supported.
- */
- @Nullable
- public String getValueAsString() {
- if (nla_value == null) return null;
- // Check the attribute value length after removing string termination flag '\0'.
- // This assumes that all netlink strings are null-terminated.
- if (nla_value.length < (nla_len - NLA_HEADERLEN - 1)) return null;
-
- try {
- final byte[] array = Arrays.copyOf(nla_value, nla_len - NLA_HEADERLEN - 1);
- return new String(array, "UTF-8");
- } catch (UnsupportedEncodingException | NegativeArraySizeException ignored) {
- return null;
- }
- }
-
- /**
- * Write the netlink attribute to {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- final ByteOrder originalOrder = byteBuffer.order();
- final int originalPosition = byteBuffer.position();
-
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- byteBuffer.putShort(nla_len);
- byteBuffer.putShort(nla_type);
- if (nla_value != null) byteBuffer.put(nla_value);
- } finally {
- byteBuffer.order(originalOrder);
- }
- byteBuffer.position(originalPosition + getAlignedLength());
- }
-
- private void setValue(byte[] value) {
- nla_value = value;
- nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
- }
-
- @Override
- public String toString() {
- return "StructNlAttr{ "
- + "nla_len{" + nla_len + "}, "
- + "nla_type{" + nla_type + "}, "
- + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNlMsgErr.java b/common/device/com/android/net/module/util/netlink/StructNlMsgErr.java
deleted file mode 100644
index b6620f3b..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNlMsgErr.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct nlmsgerr
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgErr {
- public static final int STRUCT_SIZE = Integer.BYTES + StructNlMsgHdr.STRUCT_SIZE;
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- /**
- * Parse a netlink error message payload from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the netlink error message payload.
- * @return the parsed netlink error message payload, or {@code null} if the netlink error
- * message payload could not be parsed successfully (for example, if it was truncated).
- */
- public static StructNlMsgErr parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgErr struct = new StructNlMsgErr();
- struct.error = byteBuffer.getInt();
- struct.msg = StructNlMsgHdr.parse(byteBuffer);
- return struct;
- }
-
- public int error;
- public StructNlMsgHdr msg;
-
- /**
- * Write the netlink error message payload to {@link ByteBuffer}.
- */
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(error);
- if (msg != null) {
- msg.pack(byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- return "StructNlMsgErr{ "
- + "error{" + error + "}, "
- + "msg{" + (msg == null ? "" : msg.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java b/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java
deleted file mode 100644
index 5052cb8a..00000000
--- a/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct nlmsghdr
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgHdr {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- public static final short NLM_F_REQUEST = 0x0001;
- public static final short NLM_F_MULTI = 0x0002;
- public static final short NLM_F_ACK = 0x0004;
- public static final short NLM_F_ECHO = 0x0008;
- // Flags for a GET request.
- public static final short NLM_F_ROOT = 0x0100;
- public static final short NLM_F_MATCH = 0x0200;
- public static final short NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH;
- // Flags for a NEW request.
- public static final short NLM_F_REPLACE = 0x100;
- public static final short NLM_F_EXCL = 0x200;
- public static final short NLM_F_CREATE = 0x400;
- public static final short NLM_F_APPEND = 0x800;
-
- // TODO: Probably need to distinguish the flags which have the same value. For example,
- // NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200).
- private static String stringForNlMsgFlags(short flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NLM_F_REQUEST) != 0) {
- sb.append("NLM_F_REQUEST");
- }
- if ((flags & NLM_F_MULTI) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NLM_F_MULTI");
- }
- if ((flags & NLM_F_ACK) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NLM_F_ACK");
- }
- if ((flags & NLM_F_ECHO) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NLM_F_ECHO");
- }
- if ((flags & NLM_F_ROOT) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NLM_F_ROOT");
- }
- if ((flags & NLM_F_MATCH) != 0) {
- if (sb.length() > 0) {
- sb.append("|");
- }
- sb.append("NLM_F_MATCH");
- }
- return sb.toString();
- }
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- /**
- * Parse netlink message header from buffer.
- */
- @Nullable
- public static StructNlMsgHdr parse(@NonNull ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgHdr struct = new StructNlMsgHdr();
- struct.nlmsg_len = byteBuffer.getInt();
- struct.nlmsg_type = byteBuffer.getShort();
- struct.nlmsg_flags = byteBuffer.getShort();
- struct.nlmsg_seq = byteBuffer.getInt();
- struct.nlmsg_pid = byteBuffer.getInt();
-
- if (struct.nlmsg_len < STRUCT_SIZE) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- public int nlmsg_len;
- public short nlmsg_type;
- public short nlmsg_flags;
- public int nlmsg_seq;
- public int nlmsg_pid;
-
- public StructNlMsgHdr() {
- nlmsg_len = 0;
- nlmsg_type = 0;
- nlmsg_flags = 0;
- nlmsg_seq = 0;
- nlmsg_pid = 0;
- }
-
- /**
- * Write netlink message header to ByteBuffer.
- */
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(nlmsg_len);
- byteBuffer.putShort(nlmsg_type);
- byteBuffer.putShort(nlmsg_flags);
- byteBuffer.putInt(nlmsg_seq);
- byteBuffer.putInt(nlmsg_pid);
- }
-
- @Override
- public String toString() {
- return toString(null /* unknown netlink family */);
- }
-
- /**
- * Transform a netlink header into a string. The netlink family is required for transforming
- * a netlink type integer into a string.
- * @param nlFamily netlink family. Using Integer will not incur autoboxing penalties because
- * family values are small, and all Integer objects between -128 and 127 are
- * statically cached. See Integer.IntegerCache.
- * @return A list of header elements.
- */
- @NonNull
- public String toString(@Nullable Integer nlFamily) {
- final String typeStr = "" + nlmsg_type
- + "(" + (nlFamily == null
- ? "" : NetlinkConstants.stringForNlMsgType(nlmsg_type, nlFamily))
- + ")";
- final String flagsStr = "" + nlmsg_flags
- + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
- return "StructNlMsgHdr{ "
- + "nlmsg_len{" + nlmsg_len + "}, "
- + "nlmsg_type{" + typeStr + "}, "
- + "nlmsg_flags{" + flagsStr + "}, "
- + "nlmsg_seq{" + nlmsg_seq + "}, "
- + "nlmsg_pid{" + nlmsg_pid + "} "
- + "}";
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructRtMsg.java b/common/device/com/android/net/module/util/netlink/StructRtMsg.java
deleted file mode 100644
index 3cd72922..00000000
--- a/common/device/com/android/net/module/util/netlink/StructRtMsg.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct rtmsg
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class StructRtMsg extends Struct {
- // Already aligned.
- public static final int STRUCT_SIZE = 12;
-
- @Field(order = 0, type = Type.U8)
- public final short family; // Address family of route.
- @Field(order = 1, type = Type.U8)
- public final short dstLen; // Length of destination.
- @Field(order = 2, type = Type.U8)
- public final short srcLen; // Length of source.
- @Field(order = 3, type = Type.U8)
- public final short tos; // TOS filter.
- @Field(order = 4, type = Type.U8)
- public final short table; // Routing table ID.
- @Field(order = 5, type = Type.U8)
- public final short protocol; // Routing protocol.
- @Field(order = 6, type = Type.U8)
- public final short scope; // distance to the destination.
- @Field(order = 7, type = Type.U8)
- public final short type; // route type
- @Field(order = 8, type = Type.U32)
- public final long flags;
-
- StructRtMsg(short family, short dstLen, short srcLen, short tos, short table, short protocol,
- short scope, short type, long flags) {
- this.family = family;
- this.dstLen = dstLen;
- this.srcLen = srcLen;
- this.tos = tos;
- this.table = table;
- this.protocol = protocol;
- this.scope = scope;
- this.type = type;
- this.flags = flags;
- }
-
- /**
- * Parse a rtmsg struct from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the rtmsg struct.
- * @return the parsed rtmsg struct, or {@code null} if the rtmsg struct could not be
- * parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructRtMsg parse(@NonNull final ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) return null;
-
- // The ByteOrder must already have been set to native order.
- return Struct.parse(StructRtMsg.class, byteBuffer);
- }
-
- /**
- * Write the rtmsg struct to {@link ByteBuffer}.
- */
- public void pack(@NonNull final ByteBuffer byteBuffer) {
- // The ByteOrder must already have been set to native order.
- this.writeToByteBuffer(byteBuffer);
- }
-}
diff --git a/common/device/com/android/net/module/util/netlink/StructRtaCacheInfo.java b/common/device/com/android/net/module/util/netlink/StructRtaCacheInfo.java
deleted file mode 100644
index fef1f9e8..00000000
--- a/common/device/com/android/net/module/util/netlink/StructRtaCacheInfo.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.netlink;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct rta_cacheinfo
- *
- * see also:
- *
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class StructRtaCacheInfo extends Struct {
- // Already aligned.
- public static final int STRUCT_SIZE = 32;
-
- @Field(order = 0, type = Type.U32)
- public final long clntref;
- @Field(order = 1, type = Type.U32)
- public final long lastuse;
- @Field(order = 2, type = Type.S32)
- public final int expires;
- @Field(order = 3, type = Type.U32)
- public final long error;
- @Field(order = 4, type = Type.U32)
- public final long used;
- @Field(order = 5, type = Type.U32)
- public final long id;
- @Field(order = 6, type = Type.U32)
- public final long ts;
- @Field(order = 7, type = Type.U32)
- public final long tsage;
-
- StructRtaCacheInfo(long clntref, long lastuse, int expires, long error, long used, long id,
- long ts, long tsage) {
- this.clntref = clntref;
- this.lastuse = lastuse;
- this.expires = expires;
- this.error = error;
- this.used = used;
- this.id = id;
- this.ts = ts;
- this.tsage = tsage;
- }
-
- /**
- * Parse an rta_cacheinfo struct from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the rta_cacheinfo.
- * @return the parsed rta_cacheinfo struct, or {@code null} if the rta_cacheinfo struct
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructRtaCacheInfo parse(@NonNull final ByteBuffer byteBuffer) {
- if (byteBuffer.remaining() < STRUCT_SIZE) return null;
-
- // The ByteOrder must already have been set to native order.
- return Struct.parse(StructRtaCacheInfo.class, byteBuffer);
- }
-
- /**
- * Write a rta_cacheinfo struct to {@link ByteBuffer}.
- */
- public void pack(@NonNull final ByteBuffer byteBuffer) {
- // The ByteOrder must already have been set to native order.
- this.writeToByteBuffer(byteBuffer);
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/EthernetHeader.java b/common/device/com/android/net/module/util/structs/EthernetHeader.java
deleted file mode 100644
index 92ef8a7e..00000000
--- a/common/device/com/android/net/module/util/structs/EthernetHeader.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import android.net.MacAddress;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * L2 ethernet header as per IEEE 802.3. Does not include a 802.1Q tag.
- *
- * 0 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Destination |
- * +- -+
- * | Ethernet |
- * +- -+
- * | Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Source |
- * +- -+
- * | Ethernet |
- * +- -+
- * | Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | EtherType |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class EthernetHeader extends Struct {
- @Field(order = 0, type = Type.EUI48)
- public final MacAddress dstMac;
- @Field(order = 1, type = Type.EUI48)
- public final MacAddress srcMac;
- @Field(order = 2, type = Type.U16)
- public final int etherType;
-
- public EthernetHeader(final MacAddress dstMac, final MacAddress srcMac,
- final int etherType) {
- this.dstMac = dstMac;
- this.srcMac = srcMac;
- this.etherType = etherType;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/IaPdOption.java b/common/device/com/android/net/module/util/structs/IaPdOption.java
deleted file mode 100644
index dbf79dcb..00000000
--- a/common/device/com/android/net/module/util/structs/IaPdOption.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.DHCP6_OPTION_IA_PD;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * DHCPv6 IA_PD option.
- * https://tools.ietf.org/html/rfc8415. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | OPTION_IA_PD | option-len |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | IAID (4 octets) |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | T1 |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | T2 |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . .
- * . IA_PD-options .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- */
-public class IaPdOption extends Struct {
- public static final int LENGTH = 12; // option length excluding IA_PD options
-
- @Field(order = 0, type = Type.S16)
- public final short code;
- @Field(order = 1, type = Type.S16)
- public final short length;
- @Field(order = 2, type = Type.U32)
- public final long id;
- @Field(order = 3, type = Type.U32)
- public final long t1;
- @Field(order = 4, type = Type.U32)
- public final long t2;
-
- IaPdOption(final short code, final short length, final long id, final long t1,
- final long t2) {
- this.code = code;
- this.length = length;
- this.id = id;
- this.t1 = t1;
- this.t2 = t2;
- }
-
- /**
- * Build an IA_PD option from the required specific parameters.
- */
- public static ByteBuffer build(final short length, final long id, final long t1,
- final long t2) {
- final IaPdOption option = new IaPdOption((short) DHCP6_OPTION_IA_PD,
- length /* 12 + IA_PD options length */, id, t1, t2);
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/IaPrefixOption.java b/common/device/com/android/net/module/util/structs/IaPrefixOption.java
deleted file mode 100644
index f0e44098..00000000
--- a/common/device/com/android/net/module/util/structs/IaPrefixOption.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.DHCP6_OPTION_IAPREFIX;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * DHCPv6 IA Prefix Option.
- * https://tools.ietf.org/html/rfc8415. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | OPTION_IAPREFIX | option-len |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | preferred-lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | valid-lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | prefix-length | |
- * +-+-+-+-+-+-+-+-+ IPv6-prefix |
- * | (16 octets) |
- * | |
- * | |
- * | |
- * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | .
- * +-+-+-+-+-+-+-+-+ .
- * . IAprefix-options .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class IaPrefixOption extends Struct {
- public static final int LENGTH = 25; // option length excluding IAprefix-options
-
- @Field(order = 0, type = Type.S16)
- public final short code;
- @Field(order = 1, type = Type.S16)
- public final short length;
- @Field(order = 2, type = Type.U32)
- public final long preferred;
- @Field(order = 3, type = Type.U32)
- public final long valid;
- @Field(order = 4, type = Type.S8)
- public final byte prefixLen;
- @Field(order = 5, type = Type.ByteArray, arraysize = 16)
- public final byte[] prefix;
-
- @VisibleForTesting
- public IaPrefixOption(final short code, final short length, final long preferred,
- final long valid, final byte prefixLen, final byte[] prefix) {
- this.code = code;
- this.length = length;
- this.preferred = preferred;
- this.valid = valid;
- this.prefixLen = prefixLen;
- this.prefix = prefix.clone();
- }
-
- /**
- * Build an IA_PD prefix option with given specific parameters.
- */
- public static ByteBuffer build(final short length, final long preferred, final long valid,
- final byte prefixLen, final byte[] prefix) {
- final IaPrefixOption option = new IaPrefixOption((byte) DHCP6_OPTION_IAPREFIX,
- length /* 25 + IAPrefix options length */, preferred, valid, prefixLen, prefix);
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/Icmpv4Header.java b/common/device/com/android/net/module/util/structs/Icmpv4Header.java
deleted file mode 100644
index 454bb074..00000000
--- a/common/device/com/android/net/module/util/structs/Icmpv4Header.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * ICMPv4 header as per https://tools.ietf.org/html/rfc792.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class Icmpv4Header extends Struct {
- @Field(order = 0, type = Type.U8)
- public short type;
- @Field(order = 1, type = Type.U8)
- public short code;
- @Field(order = 2, type = Type.S16)
- public short checksum;
- public Icmpv4Header(final short type, final short code, final short checksum) {
- this.type = type;
- this.code = code;
- this.checksum = checksum;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/Icmpv6Header.java b/common/device/com/android/net/module/util/structs/Icmpv6Header.java
deleted file mode 100644
index c82ae02b..00000000
--- a/common/device/com/android/net/module/util/structs/Icmpv6Header.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * ICMPv6 header as per https://tools.ietf.org/html/rfc4443.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class Icmpv6Header extends Struct {
- @Field(order = 0, type = Type.U8)
- public short type;
- @Field(order = 1, type = Type.U8)
- public short code;
- @Field(order = 2, type = Type.S16)
- public short checksum;
-
- public Icmpv6Header(final short type, final short code, final short checksum) {
- this.type = type;
- this.code = code;
- this.checksum = checksum;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/Ipv4Header.java b/common/device/com/android/net/module/util/structs/Ipv4Header.java
deleted file mode 100644
index 5249454c..00000000
--- a/common/device/com/android/net/module/util/structs/Ipv4Header.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet4Address;
-
-/**
- * L3 IPv4 header as per https://tools.ietf.org/html/rfc791.
- * This class doesn't contain options field.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |Version| IHL |Type of Service| Total Length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Identification |Flags| Fragment Offset |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Time to Live | Protocol | Header Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Source Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Destination Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class Ipv4Header extends Struct {
- // IP Version=IPv4, IHL is always 5(*4bytes) because options are not supported.
- @VisibleForTesting
- public static final byte IPHDR_VERSION_IHL = 0x45;
-
- @Field(order = 0, type = Type.S8)
- // version (4 bits), IHL (4 bits)
- public final byte vi;
- @Field(order = 1, type = Type.S8)
- public final byte tos;
- @Field(order = 2, type = Type.U16)
- public final int totalLength;
- @Field(order = 3, type = Type.S16)
- public final short id;
- @Field(order = 4, type = Type.S16)
- // flags (3 bits), fragment offset (13 bits)
- public final short flagsAndFragmentOffset;
- @Field(order = 5, type = Type.U8)
- public final short ttl;
- @Field(order = 6, type = Type.S8)
- public final byte protocol;
- @Field(order = 7, type = Type.S16)
- public final short checksum;
- @Field(order = 8, type = Type.Ipv4Address)
- public final Inet4Address srcIp;
- @Field(order = 9, type = Type.Ipv4Address)
- public final Inet4Address dstIp;
-
- public Ipv4Header(final byte tos, final int totalLength, final short id,
- final short flagsAndFragmentOffset, final short ttl, final byte protocol,
- final short checksum, final Inet4Address srcIp, final Inet4Address dstIp) {
- this(IPHDR_VERSION_IHL, tos, totalLength, id, flagsAndFragmentOffset, ttl,
- protocol, checksum, srcIp, dstIp);
- }
-
- private Ipv4Header(final byte vi, final byte tos, final int totalLength, final short id,
- final short flagsAndFragmentOffset, final short ttl, final byte protocol,
- final short checksum, final Inet4Address srcIp, final Inet4Address dstIp) {
- this.vi = vi;
- this.tos = tos;
- this.totalLength = totalLength;
- this.id = id;
- this.flagsAndFragmentOffset = flagsAndFragmentOffset;
- this.ttl = ttl;
- this.protocol = protocol;
- this.checksum = checksum;
- this.srcIp = srcIp;
- this.dstIp = dstIp;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/Ipv6Header.java b/common/device/com/android/net/module/util/structs/Ipv6Header.java
deleted file mode 100644
index a14e064d..00000000
--- a/common/device/com/android/net/module/util/structs/Ipv6Header.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet6Address;
-
-/**
- * L3 IPv6 header as per https://tools.ietf.org/html/rfc8200.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |Version| Traffic Class | Flow Label |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Payload Length | Next Header | Hop Limit |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | |
- * + Source Address +
- * | |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | |
- * + Destination Address +
- * | |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class Ipv6Header extends Struct {
- @Field(order = 0, type = Type.S32)
- public int vtf;
- @Field(order = 1, type = Type.U16)
- public int payloadLength;
- @Field(order = 2, type = Type.S8)
- public byte nextHeader;
- @Field(order = 3, type = Type.U8)
- public short hopLimit;
- @Field(order = 4, type = Type.Ipv6Address)
- public Inet6Address srcIp;
- @Field(order = 5, type = Type.Ipv6Address)
- public Inet6Address dstIp;
-
- public Ipv6Header(final int vtf, final int payloadLength, final byte nextHeader,
- final short hopLimit, final Inet6Address srcIp, final Inet6Address dstIp) {
- this.vtf = vtf;
- this.payloadLength = payloadLength;
- this.nextHeader = nextHeader;
- this.hopLimit = hopLimit;
- this.srcIp = srcIp;
- this.dstIp = dstIp;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/Ipv6PktInfo.java b/common/device/com/android/net/module/util/structs/Ipv6PktInfo.java
deleted file mode 100644
index 0dccb727..00000000
--- a/common/device/com/android/net/module/util/structs/Ipv6PktInfo.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet6Address;
-
-/**
- * structure in6_pktinfo
- *
- * see also:
- *
- * include/uapi/linux/ipv6.h
- */
-public class Ipv6PktInfo extends Struct {
- @Field(order = 0, type = Type.Ipv6Address)
- public final Inet6Address addr; // IPv6 source or destination address
- @Field(order = 1, type = Type.S32)
- public final int ifindex; // interface index
-
- public Ipv6PktInfo(final Inet6Address addr, final int ifindex) {
- this.addr = addr;
- this.ifindex = ifindex;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/LlaOption.java b/common/device/com/android/net/module/util/structs/LlaOption.java
deleted file mode 100644
index fbaccabc..00000000
--- a/common/device/com/android/net/module/util/structs/LlaOption.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import android.net.MacAddress;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * ICMPv6 source/target link-layer address option, as per https://tools.ietf.org/html/rfc4861.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Link-Layer Address ...
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class LlaOption extends Struct {
- @Field(order = 0, type = Type.S8)
- public final byte type;
- @Field(order = 1, type = Type.S8)
- public final byte length; // Length in 8-byte units
- @Field(order = 2, type = Type.EUI48)
- // Link layer address length and format varies on different link layers, which is not
- // guaranteed to be a 6-byte MAC address. However, Struct only supports 6-byte MAC
- // addresses type(EUI-48) for now.
- public final MacAddress linkLayerAddress;
-
- LlaOption(final byte type, final byte length, final MacAddress linkLayerAddress) {
- this.type = type;
- this.length = length;
- this.linkLayerAddress = linkLayerAddress;
- }
-
- /**
- * Build a target link-layer address option from the required specified parameters.
- */
- public static ByteBuffer build(final byte type, final MacAddress linkLayerAddress) {
- final LlaOption option = new LlaOption(type, (byte) 1 /* option len */, linkLayerAddress);
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/MtuOption.java b/common/device/com/android/net/module/util/structs/MtuOption.java
deleted file mode 100644
index 34bc21c1..00000000
--- a/common/device/com/android/net/module/util/structs/MtuOption.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_MTU;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * ICMPv6 MTU option, as per https://tools.ietf.org/html/rfc4861.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | MTU |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class MtuOption extends Struct {
- @Field(order = 0, type = Type.S8)
- public final byte type;
- @Field(order = 1, type = Type.S8)
- public final byte length; // Length in 8-byte units
- @Field(order = 2, type = Type.S16)
- public final short reserved;
- @Field(order = 3, type = Type.U32)
- public final long mtu;
-
- MtuOption(final byte type, final byte length, final short reserved,
- final long mtu) {
- this.type = type;
- this.length = length;
- this.reserved = reserved;
- this.mtu = mtu;
- }
-
- /**
- * Build a MTU option from the required specified parameters.
- */
- public static ByteBuffer build(final long mtu) {
- final MtuOption option = new MtuOption((byte) ICMPV6_ND_OPTION_MTU,
- (byte) 1 /* option len */, (short) 0 /* reserved */, mtu);
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/NaHeader.java b/common/device/com/android/net/module/util/structs/NaHeader.java
deleted file mode 100644
index 90c078e8..00000000
--- a/common/device/com/android/net/module/util/structs/NaHeader.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet6Address;
-
-/**
- * ICMPv6 Neighbor Advertisement header, follow {@link Icmpv6Header}, as per
- * https://tools.ietf.org/html/rfc4861. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |R|S|O| Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | |
- * + Target Address +
- * | |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options ...
- * +-+-+-+-+-+-+-+-+-+-+-+-
- */
-public class NaHeader extends Struct {
- @Field(order = 0, type = Type.S32)
- public int flags; // Router flag, Solicited flag, Override flag and 29 Reserved bits.
- @Field(order = 1, type = Type.Ipv6Address)
- public Inet6Address target;
-
- public NaHeader(final int flags, final Inet6Address target) {
- this.flags = flags;
- this.target = target;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/NsHeader.java b/common/device/com/android/net/module/util/structs/NsHeader.java
deleted file mode 100644
index 2e8b77ba..00000000
--- a/common/device/com/android/net/module/util/structs/NsHeader.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet6Address;
-
-/**
- * ICMPv6 Neighbor Solicitation header, follow {@link Icmpv6Header}, as per
- * https://tools.ietf.org/html/rfc4861. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | |
- * + Target Address +
- * | |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options ...
- * +-+-+-+-+-+-+-+-+-+-+-+-
- */
-public class NsHeader extends Struct {
- @Field(order = 0, type = Type.S32)
- public int reserved; // 32 Reserved bits.
- @Field(order = 1, type = Type.Ipv6Address)
- public Inet6Address target;
-
- NsHeader(int reserved, final Inet6Address target) {
- this.reserved = reserved;
- this.target = target;
- }
-
- public NsHeader(final Inet6Address target) {
- this(0, target);
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/PrefixInformationOption.java b/common/device/com/android/net/module/util/structs/PrefixInformationOption.java
deleted file mode 100644
index 49d7654d..00000000
--- a/common/device/com/android/net/module/util/structs/PrefixInformationOption.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_PIO;
-
-import android.net.IpPrefix;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * ICMPv6 prefix information option, as per https://tools.ietf.org/html/rfc4861.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Prefix Length |L|A| Reserved1 |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Valid Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Preferred Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Reserved2 |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | |
- * + Prefix +
- * | |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class PrefixInformationOption extends Struct {
- @Field(order = 0, type = Type.S8)
- public final byte type;
- @Field(order = 1, type = Type.S8)
- public final byte length; // Length in 8-byte units
- @Field(order = 2, type = Type.S8)
- public final byte prefixLen;
- @Field(order = 3, type = Type.S8)
- // On-link flag, Autonomous address configuration flag, 6-reserved bits
- public final byte flags;
- @Field(order = 4, type = Type.U32)
- public final long validLifetime;
- @Field(order = 5, type = Type.U32)
- public final long preferredLifetime;
- @Field(order = 6, type = Type.S32)
- public final int reserved;
- @Field(order = 7, type = Type.ByteArray, arraysize = 16)
- public final byte[] prefix;
-
- PrefixInformationOption(final byte type, final byte length, final byte prefixLen,
- final byte flags, final long validLifetime, final long preferredLifetime,
- final int reserved, @NonNull final byte[] prefix) {
- this.type = type;
- this.length = length;
- this.prefixLen = prefixLen;
- this.flags = flags;
- this.validLifetime = validLifetime;
- this.preferredLifetime = preferredLifetime;
- this.reserved = reserved;
- this.prefix = prefix;
- }
-
- /**
- * Build a Prefix Information option from the required specified parameters.
- */
- public static ByteBuffer build(final IpPrefix prefix, final byte flags,
- final long validLifetime, final long preferredLifetime) {
- final PrefixInformationOption option = new PrefixInformationOption(
- (byte) ICMPV6_ND_OPTION_PIO, (byte) 4 /* option len */,
- (byte) prefix.getPrefixLength(), flags, validLifetime, preferredLifetime,
- (int) 0, prefix.getRawAddress());
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/RaHeader.java b/common/device/com/android/net/module/util/structs/RaHeader.java
deleted file mode 100644
index 31a5cb76..00000000
--- a/common/device/com/android/net/module/util/structs/RaHeader.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * ICMPv6 Router Advertisement header, follow [Icmpv6Header], as per
- * https://tools.ietf.org/html/rfc4861. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Cur Hop Limit |M|O| Reserved | Router Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Reachable Time |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Retrans Timer |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options ...
- * +-+-+-+-+-+-+-+-+-+-+-+-
- */
-public class RaHeader extends Struct {
- @Field(order = 0, type = Type.S8)
- public final byte hopLimit;
- // "Managed address configuration", "Other configuration" bits, and 6 reserved bits
- @Field(order = 1, type = Type.S8)
- public final byte flags;
- @Field(order = 2, type = Type.U16)
- public final int lifetime;
- @Field(order = 3, type = Type.U32)
- public final long reachableTime;
- @Field(order = 4, type = Type.U32)
- public final long retransTimer;
-
- public RaHeader(final byte hopLimit, final byte flags, final int lifetime,
- final long reachableTime, final long retransTimer) {
- this.hopLimit = hopLimit;
- this.flags = flags;
- this.lifetime = lifetime;
- this.reachableTime = reachableTime;
- this.retransTimer = retransTimer;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/RdnssOption.java b/common/device/com/android/net/module/util/structs/RdnssOption.java
deleted file mode 100644
index 4a5bd7e9..00000000
--- a/common/device/com/android/net/module/util/structs/RdnssOption.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_RDNSS;
-
-import android.net.InetAddresses;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet6Address;
-import java.nio.ByteBuffer;
-
-/**
- * IPv6 RA recursive DNS server option, as per https://tools.ietf.org/html/rfc8106.
- * This should be followed by a series of DNSv6 server addresses.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * : Addresses of IPv6 Recursive DNS Servers :
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class RdnssOption extends Struct {
- @Field(order = 0, type = Type.S8)
- public final byte type;
- @Field(order = 1, type = Type.S8)
- public final byte length; // Length in 8-byte units
- @Field(order = 2, type = Type.S16)
- public final short reserved;
- @Field(order = 3, type = Type.U32)
- public final long lifetime;
-
- public RdnssOption(final byte type, final byte length, final short reserved,
- final long lifetime) {
- this.type = type;
- this.length = length;
- this.reserved = reserved;
- this.lifetime = lifetime;
- }
-
- /**
- * Build a RDNSS option from the required specified Inet6Address parameters.
- */
- public static ByteBuffer build(final long lifetime, final Inet6Address... servers) {
- final byte length = (byte) (1 + 2 * servers.length);
- final RdnssOption option = new RdnssOption((byte) ICMPV6_ND_OPTION_RDNSS,
- length, (short) 0, lifetime);
- final ByteBuffer buffer = ByteBuffer.allocate(length * 8);
- option.writeToByteBuffer(buffer);
- for (Inet6Address server : servers) {
- buffer.put(server.getAddress());
- }
- buffer.flip();
- return buffer;
- }
-
- /**
- * Build a RDNSS option from the required specified String parameters.
- *
- * @throws IllegalArgumentException if {@code servers} does not contain only numeric addresses.
- */
- public static ByteBuffer build(final long lifetime, final String... servers) {
- final Inet6Address[] serverArray = new Inet6Address[servers.length];
- for (int i = 0; i < servers.length; i++) {
- serverArray[i] = (Inet6Address) InetAddresses.parseNumericAddress(servers[i]);
- }
- return build(lifetime, serverArray);
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/RouteInformationOption.java b/common/device/com/android/net/module/util/structs/RouteInformationOption.java
deleted file mode 100644
index 49bafedb..00000000
--- a/common/device/com/android/net/module/util/structs/RouteInformationOption.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_RIO;
-
-import android.net.IpPrefix;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * ICMPv6 route information option, as per https://tools.ietf.org/html/rfc4191.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Prefix Length |Resvd|Prf|Resvd|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Route Lifetime |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Prefix (Variable Length) |
- * . .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class RouteInformationOption extends Struct {
- public enum Preference {
- HIGH((byte) 0x1),
- MEDIUM((byte) 0x0),
- LOW((byte) 0x3),
- RESERVED((byte) 0x2);
-
- final byte mValue;
- Preference(byte value) {
- this.mValue = value;
- }
- }
-
- @Field(order = 0, type = Type.S8)
- public final byte type;
- @Field(order = 1, type = Type.S8)
- public final byte length; // Length in 8-byte octets
- @Field(order = 2, type = Type.U8)
- public final short prefixLen;
- @Field(order = 3, type = Type.S8)
- public final byte prf;
- @Field(order = 4, type = Type.U32)
- public final long routeLifetime;
- @Field(order = 5, type = Type.ByteArray, arraysize = 16)
- public final byte[] prefix;
-
- RouteInformationOption(final byte type, final byte length, final short prefixLen,
- final byte prf, final long routeLifetime, @NonNull final byte[] prefix) {
- this.type = type;
- this.length = length;
- this.prefixLen = prefixLen;
- this.prf = prf;
- this.routeLifetime = routeLifetime;
- this.prefix = prefix;
- }
-
- /**
- * Build a Route Information option from the required specified parameters.
- */
- public static ByteBuffer build(final IpPrefix prefix, final Preference prf,
- final long routeLifetime) {
- // The prefix field is always assumed to have 16 bytes, but the number of leading
- // bits in this prefix depends on IpPrefix#prefixLength, then we can simply set the
- // option length to 3.
- final RouteInformationOption option = new RouteInformationOption(
- (byte) ICMPV6_ND_OPTION_RIO, (byte) 3 /* option length */,
- (short) prefix.getPrefixLength(), (byte) (prf.mValue << 3), routeLifetime,
- prefix.getRawAddress());
- return ByteBuffer.wrap(option.writeToBytes(ByteOrder.BIG_ENDIAN));
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/RsHeader.java b/common/device/com/android/net/module/util/structs/RsHeader.java
deleted file mode 100644
index 0b51ff25..00000000
--- a/common/device/com/android/net/module/util/structs/RsHeader.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * ICMPv6 Router Solicitation header, follow [Icmpv6Header], as per
- * https://tools.ietf.org/html/rfc4861. This does not contain any option.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Code | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Reserved |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options ...
- * +-+-+-+-+-+-+-+-+-+-+-+-
- */
-public class RsHeader extends Struct {
- @Field(order = 0, type = Type.S32)
- public final int reserved;
-
- public RsHeader(final int reserved) {
- this.reserved = reserved;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/TcpHeader.java b/common/device/com/android/net/module/util/structs/TcpHeader.java
deleted file mode 100644
index 0c97401c..00000000
--- a/common/device/com/android/net/module/util/structs/TcpHeader.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * L4 TCP header as per https://tools.ietf.org/html/rfc793.
- * This class does not contain option and data fields.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Source Port | Destination Port |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Sequence Number |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Acknowledgment Number |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Data | |U|A|P|R|S|F| |
- * | Offset| Reserved |R|C|S|S|Y|I| Window |
- * | | |G|K|H|T|N|N| |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Checksum | Urgent Pointer |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options | Padding |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | data |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-public class TcpHeader extends Struct {
- @Field(order = 0, type = Type.U16)
- public final int srcPort;
- @Field(order = 1, type = Type.U16)
- public final int dstPort;
- @Field(order = 2, type = Type.U32)
- public final long seq;
- @Field(order = 3, type = Type.U32)
- public final long ack;
- @Field(order = 4, type = Type.S16)
- // data Offset (4 bits), reserved (6 bits), control bits (6 bits)
- // TODO: update with bitfields once class Struct supports it
- public final short dataOffsetAndControlBits;
- @Field(order = 5, type = Type.U16)
- public final int window;
- @Field(order = 6, type = Type.S16)
- public final short checksum;
- @Field(order = 7, type = Type.U16)
- public final int urgentPointer;
-
- public TcpHeader(final int srcPort, final int dstPort, final long seq, final long ack,
- final short dataOffsetAndControlBits, final int window, final short checksum,
- final int urgentPointer) {
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- this.seq = seq;
- this.ack = ack;
- this.dataOffsetAndControlBits = dataOffsetAndControlBits;
- this.window = window;
- this.checksum = checksum;
- this.urgentPointer = urgentPointer;
- }
-}
diff --git a/common/device/com/android/net/module/util/structs/UdpHeader.java b/common/device/com/android/net/module/util/structs/UdpHeader.java
deleted file mode 100644
index 8b0316bf..00000000
--- a/common/device/com/android/net/module/util/structs/UdpHeader.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.structs;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * L4 UDP header as per https://tools.ietf.org/html/rfc768.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Source Port | Destination Port |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Length | Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | data octets ...
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ...
- */
-public class UdpHeader extends Struct {
- @Field(order = 0, type = Type.U16)
- public final int srcPort;
- @Field(order = 1, type = Type.U16)
- public final int dstPort;
- @Field(order = 2, type = Type.U16)
- public final int length;
- @Field(order = 3, type = Type.S16)
- public final short checksum;
-
- public UdpHeader(final int srcPort, final int dstPort, final int length,
- final short checksum) {
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- this.length = length;
- this.checksum = checksum;
- }
-}
diff --git a/common/device/com/android/net/module/util/wear/NetPacketHelpers.java b/common/device/com/android/net/module/util/wear/NetPacketHelpers.java
deleted file mode 100644
index 341c44be..00000000
--- a/common/device/com/android/net/module/util/wear/NetPacketHelpers.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.wear;
-
-import com.android.net.module.util.async.ReadableByteBuffer;
-
-/**
- * Implements utilities for decoding parts of TCP/UDP/IP headers.
- *
- * @hide
- */
-final class NetPacketHelpers {
- static void encodeNetworkUnsignedInt16(int value, byte[] dst, final int dstPos) {
- dst[dstPos] = (byte) ((value >> 8) & 0xFF);
- dst[dstPos + 1] = (byte) (value & 0xFF);
- }
-
- static int decodeNetworkUnsignedInt16(byte[] data, final int pos) {
- return ((data[pos] & 0xFF) << 8) | (data[pos + 1] & 0xFF);
- }
-
- static int decodeNetworkUnsignedInt16(ReadableByteBuffer data, final int pos) {
- return ((data.peek(pos) & 0xFF) << 8) | (data.peek(pos + 1) & 0xFF);
- }
-
- private NetPacketHelpers() {}
-}
diff --git a/common/device/com/android/net/module/util/wear/PacketFile.java b/common/device/com/android/net/module/util/wear/PacketFile.java
deleted file mode 100644
index 7f5ed785..00000000
--- a/common/device/com/android/net/module/util/wear/PacketFile.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.wear;
-
-/**
- * Defines bidirectional file where all transmissions are made as complete packets.
- *
- * Automatically manages all readability and writeability events in EventManager:
- * - When read buffer has more space - asks EventManager to notify on more data
- * - When write buffer has more space - asks the user to provide more data
- * - When underlying file cannot accept more data - registers EventManager callback
- *
- * @hide
- */
-public interface PacketFile {
- /** @hide */
- public enum ErrorCode {
- UNEXPECTED_ERROR,
- IO_ERROR,
- INBOUND_PACKET_TOO_LARGE,
- OUTBOUND_PACKET_TOO_LARGE,
- }
-
- /**
- * Receives notifications when new data or output space is available.
- *
- * @hide
- */
- public interface Listener {
- /**
- * Handles the initial part of the stream, which on some systems provides lower-level
- * configuration data.
- *
- * Returns the number of bytes consumed, or zero if the preamble has been fully read.
- */
- int onPreambleData(byte[] data, int pos, int len);
-
- /** Handles one extracted packet. */
- void onInboundPacket(byte[] data, int pos, int len);
-
- /** Notifies on new data being added to the buffer. */
- void onInboundBuffered(int newByteCount, int totalBufferedSize);
-
- /** Notifies on data being flushed from output buffer. */
- void onOutboundPacketSpace();
-
- /** Notifies on unrecoverable error in the packet processing. */
- void onPacketFileError(ErrorCode error, String message);
- }
-
- /** Requests this file to be closed. */
- void close();
-
- /** Permanently disables reading of this file, and clears all buffered data. */
- void shutdownReading();
-
- /** Starts or resumes async read operations on this file. */
- void continueReading();
-
- /** Returns the number of bytes currently buffered as input. */
- int getInboundBufferSize();
-
- /** Returns the number of bytes currently available for buffering for output. */
- int getOutboundFreeSize();
-
- /**
- * Queues the given data for output.
- * Throws runtime exception if there is not enough space.
- */
- boolean enqueueOutboundPacket(byte[] data, int pos, int len);
-}
diff --git a/common/device/com/android/net/module/util/wear/StreamingPacketFile.java b/common/device/com/android/net/module/util/wear/StreamingPacketFile.java
deleted file mode 100644
index 52dbee47..00000000
--- a/common/device/com/android/net/module/util/wear/StreamingPacketFile.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.net.module.util.wear;
-
-import com.android.net.module.util.async.BufferedFile;
-import com.android.net.module.util.async.EventManager;
-import com.android.net.module.util.async.FileHandle;
-import com.android.net.module.util.async.Assertions;
-import com.android.net.module.util.async.ReadableByteBuffer;
-
-import java.io.IOException;
-
-/**
- * Implements PacketFile based on a streaming file descriptor.
- *
- * Packets are delineated using network-order 2-byte length indicators.
- *
- * @hide
- */
-public final class StreamingPacketFile implements PacketFile, BufferedFile.Listener {
- private static final int HEADER_SIZE = 2;
-
- private final EventManager mEventManager;
- private final Listener mListener;
- private final BufferedFile mFile;
- private final int mMaxPacketSize;
- private final ReadableByteBuffer mInboundBuffer;
- private boolean mIsInPreamble = true;
-
- private final byte[] mTempPacketReadBuffer;
- private final byte[] mTempHeaderWriteBuffer;
-
- public StreamingPacketFile(
- EventManager eventManager,
- FileHandle fileHandle,
- Listener listener,
- int maxPacketSize,
- int maxBufferedInboundPackets,
- int maxBufferedOutboundPackets) throws IOException {
- if (eventManager == null || fileHandle == null || listener == null) {
- throw new NullPointerException();
- }
-
- mEventManager = eventManager;
- mListener = listener;
- mMaxPacketSize = maxPacketSize;
-
- final int maxTotalLength = HEADER_SIZE + maxPacketSize;
-
- mFile = BufferedFile.create(eventManager, fileHandle, this,
- maxTotalLength * maxBufferedInboundPackets,
- maxTotalLength * maxBufferedOutboundPackets);
- mInboundBuffer = mFile.getInboundBuffer();
-
- mTempPacketReadBuffer = new byte[maxTotalLength];
- mTempHeaderWriteBuffer = new byte[HEADER_SIZE];
- }
-
- @Override
- public void close() {
- mFile.close();
- }
-
- public BufferedFile getUnderlyingFileForTest() {
- return mFile;
- }
-
- @Override
- public void shutdownReading() {
- mFile.shutdownReading();
- }
-
- @Override
- public void continueReading() {
- mFile.continueReading();
- }
-
- @Override
- public int getInboundBufferSize() {
- return mInboundBuffer.size();
- }
-
- @Override
- public void onBufferedFileClosed() {
- }
-
- @Override
- public void onBufferedFileInboundData(int readByteCount) {
- if (mFile.isReadingShutdown()) {
- return;
- }
-
- if (readByteCount > 0) {
- mListener.onInboundBuffered(readByteCount, mInboundBuffer.size());
- }
-
- if (extractOnePacket() && !mFile.isReadingShutdown()) {
- // There could be more packets already buffered, continue parsing next
- // packet even before another read event comes
- mEventManager.execute(() -> {
- onBufferedFileInboundData(0);
- });
- } else {
- continueReading();
- }
- }
-
- private boolean extractOnePacket() {
- while (mIsInPreamble) {
- final int directReadSize = Math.min(
- mInboundBuffer.getDirectReadSize(), mTempPacketReadBuffer.length);
- if (directReadSize == 0) {
- return false;
- }
-
- // Copy for safety, so higher-level callback cannot modify the data.
- System.arraycopy(mInboundBuffer.getDirectReadBuffer(),
- mInboundBuffer.getDirectReadPos(), mTempPacketReadBuffer, 0, directReadSize);
-
- final int preambleConsumedBytes = mListener.onPreambleData(
- mTempPacketReadBuffer, 0, directReadSize);
- if (mFile.isReadingShutdown()) {
- return false; // The callback has called shutdownReading().
- }
-
- if (preambleConsumedBytes == 0) {
- mIsInPreamble = false;
- break;
- }
-
- mInboundBuffer.accountForDirectRead(preambleConsumedBytes);
- }
-
- final int bufferedSize = mInboundBuffer.size();
- if (bufferedSize < HEADER_SIZE) {
- return false;
- }
-
- final int dataLength = NetPacketHelpers.decodeNetworkUnsignedInt16(mInboundBuffer, 0);
- if (dataLength > mMaxPacketSize) {
- mListener.onPacketFileError(
- PacketFile.ErrorCode.INBOUND_PACKET_TOO_LARGE,
- "Inbound packet length: " + dataLength);
- return false;
- }
-
- final int totalLength = HEADER_SIZE + dataLength;
- if (bufferedSize < totalLength) {
- return false;
- }
-
- mInboundBuffer.readBytes(mTempPacketReadBuffer, 0, totalLength);
-
- mListener.onInboundPacket(mTempPacketReadBuffer, HEADER_SIZE, dataLength);
- return true;
- }
-
- @Override
- public int getOutboundFreeSize() {
- final int freeSize = mFile.getOutboundBufferFreeSize();
- return (freeSize > HEADER_SIZE ? freeSize - HEADER_SIZE : 0);
- }
-
- @Override
- public boolean enqueueOutboundPacket(byte[] buffer, int pos, int len) {
- Assertions.throwsIfOutOfBounds(buffer, pos, len);
-
- if (len == 0) {
- return true;
- }
-
- if (len > mMaxPacketSize) {
- mListener.onPacketFileError(
- PacketFile.ErrorCode.OUTBOUND_PACKET_TOO_LARGE,
- "Outbound packet length: " + len);
- return false;
- }
-
- NetPacketHelpers.encodeNetworkUnsignedInt16(len, mTempHeaderWriteBuffer, 0);
-
- mFile.enqueueOutboundData(
- mTempHeaderWriteBuffer, 0, mTempHeaderWriteBuffer.length,
- buffer, pos, len);
- return true;
- }
-
- @Override
- public void onBufferedFileOutboundSpace() {
- mListener.onOutboundPacketSpace();
- }
-
- @Override
- public void onBufferedFileIoError(String message) {
- mListener.onPacketFileError(PacketFile.ErrorCode.IO_ERROR, message);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("maxPacket=");
- sb.append(mMaxPacketSize);
- sb.append(", file={");
- sb.append(mFile);
- sb.append("}");
- return sb.toString();
- }
-}