Merge "Move shared packages to NetworkStack project"

This commit is contained in:
Remi NGUYEN VAN
2019-11-22 06:50:22 +00:00
committed by Gerrit Code Review
40 changed files with 4 additions and 5268 deletions

View File

@@ -20,12 +20,14 @@ java_defaults {
srcs: [
"src/**/*.java",
":framework-tethering-shared-srcs",
":net-module-utils-srcs",
":services-tethering-shared-srcs",
":servicescore-tethering-src",
],
static_libs: [
"androidx.annotation_annotation",
"netd_aidl_interface-java",
"netlink-client",
"networkstack-aidl-interfaces-java",
"android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",

View File

@@ -1,38 +1,26 @@
java_library_static {
name: "services.net",
srcs: [
":net-module-utils-srcs",
":tethering-servicesnet-srcs",
"java/**/*.java",
],
static_libs: [
"dnsresolver_aidl_interface-V2-java",
"netd_aidl_interface-unstable-java",
"netlink-client",
"networkstack-client",
"tethering-client",
],
}
filegroup {
name: "services-networkstack-shared-srcs",
srcs: [
"java/android/net/ip/InterfaceController.java", // TODO: move to NetworkStack with tethering
"java/android/net/util/InterfaceParams.java", // TODO: move to NetworkStack with IpServer
"java/android/net/shared/*.java",
"java/android/net/netlink/*.java",
],
}
filegroup {
name: "services-tethering-shared-srcs",
srcs: [
":framework-annotations",
"java/android/net/ConnectivityModuleConnector.java",
"java/android/net/NetworkStackClient.java",
"java/android/net/ip/InterfaceController.java",
"java/android/net/netlink/*.java",
"java/android/net/util/InterfaceParams.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
"java/android/net/util/SharedLog.java"
],
}

View File

@@ -1,193 +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 android.net.ip;
import android.net.INetd;
import android.net.InterfaceConfigurationParcel;
import android.net.LinkAddress;
import android.net.util.SharedLog;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.system.OsConstants;
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 final static 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;
}
private boolean setInterfaceAddress(LinkAddress addr) {
final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
ifConfig.ifName = mIfName;
ifConfig.ipv4Addr = addr.getAddress().getHostAddress();
ifConfig.prefixLength = addr.getPrefixLength();
ifConfig.hwAddr = "";
ifConfig.flags = new String[0];
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(LinkAddress address) {
if (!(address.getAddress() instanceof Inet4Address)) {
return false;
}
return setInterfaceAddress(address);
}
/**
* Clear the IPv4Address of the interface.
*/
public boolean clearIPv4Address() {
return setInterfaceAddress(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));
}
}

View File

@@ -1,109 +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 android.net.netlink;
import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static java.nio.ByteOrder.BIG_ENDIAN;
import android.system.OsConstants;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* 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;
public static final short NFNL_SUBSYS_CTNETLINK = 1;
public static final short IPCTNL_MSG_CT_NEW = 0;
// enum ctattr_type
public static final short CTA_TUPLE_ORIG = 1;
public static final short CTA_TUPLE_REPLY = 2;
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;
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 = (NFNL_SUBSYS_CTNETLINK << 8) | 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;
}
protected StructNfGenMsg mNfGenMsg;
private ConntrackMessage() {
super(new StructNlMsgHdr());
mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
}
public void pack(ByteBuffer byteBuffer) {
mHeader.pack(byteBuffer);
mNfGenMsg.pack(byteBuffer);
}
}

View File

@@ -1,221 +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 android.net.netlink;
import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
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.IPPROTO_UDP;
import static android.system.OsConstants.NETLINK_INET_DIAG;
import android.annotation.Nullable;
import android.net.util.SocketUtils;
import android.system.ErrnoException;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* 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;
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 NullPointerException}
* 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
* {@Code 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
* {@Code 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 NullPointerException {
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 = SOCK_DIAG_BY_FAMILY;
nlMsgHdr.nlmsg_flags = flags;
nlMsgHdr.pack(byteBuffer);
final StructInetDiagReqV2 inetDiagReqV2 =
new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
inetDiagReqV2.pack(byteBuffer);
return bytes;
}
public StructInetDiagMsg mStructInetDiagMsg;
private InetDiagMessage(StructNlMsgHdr header) {
super(header);
mStructInetDiagMsg = new StructInetDiagMsg();
}
public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
final InetDiagMessage msg = new InetDiagMessage(header);
msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
return msg;
}
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);
NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
final NetlinkMessage nlMsg = NetlinkMessage.parse(response);
final StructNlMsgHdr hdr = nlMsg.getHeader();
if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
return INVALID_UID;
}
if (nlMsg instanceof InetDiagMessage) {
return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.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 = NetlinkSocket.forProto(NETLINK_INET_DIAG);
NetlinkSocket.connectToKernel(fd);
uid = lookupUid(protocol, local, remote, fd);
} catch (ErrnoException | SocketException | IllegalArgumentException
| InterruptedIOException e) {
Log.e(TAG, e.toString());
} finally {
if (fd != null) {
try {
SocketUtils.closeSocket(fd);
} catch (IOException e) {
Log.e(TAG, e.toString());
}
}
}
return uid;
}
@Override
public String toString() {
return "InetDiagMessage{ "
+ "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
+ "inet_diag_msg{"
+ (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} "
+ "}";
}
}

View File

@@ -1,129 +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 android.net.netlink;
import android.system.OsConstants;
import com.android.internal.util.HexDump;
import java.nio.ByteBuffer;
/**
* Various constants and static helper methods for netlink communications.
*
* Values taken from:
*
* &lt;linux_src&gt;/include/uapi/linux/netlink.h
* &lt;linux_src&gt;/include/uapi/linux/rtnetlink.h
*
* @hide
*/
public class NetlinkConstants {
private NetlinkConstants() {}
public static final int NLA_ALIGNTO = 4;
public static final int alignedLengthOf(short length) {
final int intLength = (int) length & 0xffff;
return alignedLengthOf(intLength);
}
public static final int alignedLengthOf(int length) {
if (length <= 0) { return 0; }
return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
}
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"; }
return String.valueOf(family);
}
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);
}
public static String hexify(byte[] bytes) {
if (bytes == null) { return "(null)"; }
return HexDump.toHexString(bytes);
}
public static String hexify(ByteBuffer buffer) {
if (buffer == null) { return "(null)"; }
return HexDump.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;
/* see &lt;linux_src&gt;/include/uapi/linux/sock_diag.h */
public static final short SOCK_DIAG_BY_FAMILY = 20;
public static String stringForNlMsgType(short nlm_type) {
switch (nlm_type) {
case NLMSG_NOOP: return "NLMSG_NOOP";
case NLMSG_ERROR: return "NLMSG_ERROR";
case NLMSG_DONE: return "NLMSG_DONE";
case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
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(nlm_type);
}
}
}

View File

@@ -1,61 +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 android.net.netlink;
import android.net.netlink.StructNlMsgHdr;
import android.net.netlink.NetlinkMessage;
import java.nio.ByteBuffer;
/**
* A NetlinkMessage subclass for netlink error messages.
*
* @hide
*/
public class NetlinkErrorMessage extends NetlinkMessage {
public static NetlinkErrorMessage parse(StructNlMsgHdr header, 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(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()) + "} "
+ "}";
}
}

View File

@@ -1,99 +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 android.net.netlink;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNlAttr;
import android.net.netlink.StructNlMsgHdr;
import android.util.Log;
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 final static String TAG = "NetlinkMessage";
public static NetlinkMessage parse(ByteBuffer byteBuffer) {
final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
if (nlmsghdr == null) {
return null;
}
int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
payloadLength -= 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;
}
switch (nlmsghdr.nlmsg_type) {
//case NetlinkConstants.NLMSG_NOOP:
case NetlinkConstants.NLMSG_ERROR:
return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
case NetlinkConstants.NLMSG_DONE:
byteBuffer.position(byteBuffer.position() + payloadLength);
return new NetlinkMessage(nlmsghdr);
//case NetlinkConstants.NLMSG_OVERRUN:
case NetlinkConstants.RTM_NEWNEIGH:
case NetlinkConstants.RTM_DELNEIGH:
case NetlinkConstants.RTM_GETNEIGH:
return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
default:
if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
// Netlink control message. Just parse the header for now,
// pretending the whole message was consumed.
byteBuffer.position(byteBuffer.position() + payloadLength);
return new NetlinkMessage(nlmsghdr);
}
return null;
}
}
protected StructNlMsgHdr mHeader;
public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
mHeader = nlmsghdr;
}
public StructNlMsgHdr getHeader() {
return mHeader;
}
@Override
public String toString() {
return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
}
}

View File

@@ -1,158 +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 android.net.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.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.StructTimeval;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* NetlinkSocket
*
* A small static class to assist with AF_NETLINK socket operations.
*
* @hide
*/
public class NetlinkSocket {
private static final String TAG = "NetlinkSocket";
public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024;
public static final int SOCKET_RECV_BUFSIZE = 64 * 1024;
public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
final long IO_TIMEOUT = 300L;
final FileDescriptor fd = forProto(nlProto);
try {
connectToKernel(fd);
sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
// recvMessage() guaranteed to not return null if it did not throw.
final NetlinkMessage response = NetlinkMessage.parse(bytes);
if (response != null && response instanceof NetlinkErrorMessage &&
(((NetlinkErrorMessage) response).getNlMsgError() != null)) {
final int errno = ((NetlinkErrorMessage) 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, errPrefix + ", 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, errPrefix + ", errmsg=" + errmsg);
throw new ErrnoException(errmsg, EPROTO);
}
} 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
}
}
}
public static FileDescriptor forProto(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;
}
public static void connectToKernel(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));
ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
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,
* waiting at most |timeoutMs| milliseconds for the send to complete.
*
* Multi-threaded calls with different timeouts will cause unexpected results.
*/
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);
}
}

View File

@@ -1,251 +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 android.net.netlink;
import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import android.net.netlink.StructNdaCacheInfo;
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlAttr;
import android.net.netlink.StructNlMsgHdr;
import android.net.netlink.NetlinkMessage;
import android.system.OsConstants;
import android.util.Log;
import java.net.InetAddress;
import java.net.Inet6Address;
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;
private static StructNlAttr findNextAttrOfType(short attrType, 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 static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, 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 = findNextAttrOfType(NDA_DST, byteBuffer);
if (nlAttr != null) {
neighMsg.mDestination = nlAttr.getValueAsInetAddress();
}
byteBuffer.position(baseOffset);
nlAttr = findNextAttrOfType(NDA_LLADDR, byteBuffer);
if (nlAttr != null) {
neighMsg.mLinkLayerAddr = nlAttr.nla_value;
}
byteBuffer.position(baseOffset);
nlAttr = findNextAttrOfType(NDA_PROBES, byteBuffer);
if (nlAttr != null) {
neighMsg.mNumProbes = nlAttr.getValueAsInt(0);
}
byteBuffer.position(baseOffset);
nlAttr = 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(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;
}
public 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);
}
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()) + "}, "
+ "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, "
+ "destination{" + ipLiteral + "} "
+ "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} "
+ "probes{" + mNumProbes + "} "
+ "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} "
+ "}";
}
}

View File

@@ -1,67 +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 android.net.netlink;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import android.util.Log;
/**
* 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;
private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 +
StructInetDiagSockId.STRUCT_SIZE + 12;
public int idiag_uid;
public static StructInetDiagMsg parse(ByteBuffer byteBuffer) {
StructInetDiagMsg struct = new StructInetDiagMsg();
struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET);
return struct;
}
@Override
public String toString() {
return "StructInetDiagMsg{ "
+ "idiag_uid{" + idiag_uid + "}, "
+ "}";
}
}

View File

@@ -1,97 +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 android.net.netlink;
import android.annotation.Nullable;
import java.net.InetSocketAddress;
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, InetSocketAddress local, InetSocketAddress remote,
int family) {
this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
INET_DIAG_REQ_V2_ALL_STATES);
}
public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
@Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
throws NullPointerException {
mSdiagFamily = (byte) family;
mSdiagProtocol = (byte) protocol;
// 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 NullPointerException("Local and remote must be both null or both non-null");
}
mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
mPad = (byte) pad;
mIdiagExt = (byte) extension;
mState = state;
}
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")
+ "}";
}
}

View File

@@ -1,86 +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 android.net.netlink;
import static java.nio.ByteOrder.BIG_ENDIAN;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
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 {
public static final int STRUCT_SIZE = 48;
private final InetSocketAddress mLocSocketAddress;
private final InetSocketAddress mRemSocketAddress;
private final byte[] INET_DIAG_NOCOOKIE = new byte[]{
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
mLocSocketAddress = loc;
mRemSocketAddress = rem;
}
public void pack(ByteBuffer byteBuffer) {
byteBuffer.order(BIG_ENDIAN);
byteBuffer.putShort((short) mLocSocketAddress.getPort());
byteBuffer.putShort((short) mRemSocketAddress.getPort());
byteBuffer.put(mLocSocketAddress.getAddress().getAddress());
if (mLocSocketAddress.getAddress() instanceof Inet4Address) {
byteBuffer.put(IPV4_PADDING);
}
byteBuffer.put(mRemSocketAddress.getAddress().getAddress());
if (mRemSocketAddress.getAddress() instanceof Inet4Address) {
byteBuffer.put(IPV4_PADDING);
}
byteBuffer.order(ByteOrder.nativeOrder());
byteBuffer.putInt(0);
byteBuffer.put(INET_DIAG_NOCOOKIE);
}
@Override
public String toString() {
return "StructInetDiagSockId{ "
+ "idiag_sport{" + mLocSocketAddress.getPort() + "}, "
+ "idiag_dport{" + mRemSocketAddress.getPort() + "}, "
+ "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, "
+ "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, "
+ "idiag_if{" + 0 + "} "
+ "idiag_cookie{INET_DIAG_NOCOOKIE}"
+ "}";
}
}

View File

@@ -1,166 +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 android.net.netlink;
import android.net.netlink.NetlinkConstants;
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;
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);
}
}
public static boolean isNudStateConnected(short nudState) {
return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0);
}
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;
public 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;
}
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;
}
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);
}
public boolean nudConnected() {
return isNudStateConnected(ndm_state);
}
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 + "} "
+ "}";
}
}

View File

@@ -1,117 +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 android.net.netlink;
import android.system.Os;
import android.system.OsConstants;
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;
}
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;
}
// TODO: investigate whether this can change during device runtime and
// decide what (if anything) should be done about that.
private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK);
private static long ticksToMilliSeconds(int intClockTicks) {
final long longClockTicks = (long) intClockTicks & 0xffffffff;
return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND;
}
/**
* 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() {}
public long lastUsed() {
return ticksToMilliSeconds(ndm_used);
}
public long lastConfirmed() {
return ticksToMilliSeconds(ndm_confirmed);
}
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 + "} "
+ "}";
}
}

View File

@@ -1,49 +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 android.net.netlink;
import java.nio.ByteBuffer;
/**
* 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;
final public byte nfgen_family;
final public byte version;
final public short res_id; // N.B.: this is big endian in the kernel
public StructNfGenMsg(byte family) {
nfgen_family = family;
version = (byte) NFNETLINK_V0;
res_id = (short) 0;
}
public void pack(ByteBuffer byteBuffer) {
byteBuffer.put(nfgen_family);
byteBuffer.put(version);
byteBuffer.putShort(res_id);
}
}

View File

@@ -1,210 +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 android.net.netlink;
import android.net.netlink.NetlinkConstants;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
/**
* 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);
public static short makeNestedType(short type) {
return (short) (type | NLA_F_NESTED);
}
// 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();
// Assume the byte order of the buffer is the expected byte order of the value.
final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
// The byte order of nla_len and nla_type is always native.
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;
}
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;
}
public short nla_len = (short) NLA_HEADERLEN;
public short nla_type;
public byte[] nla_value;
// The byte order used to read/write the value member. Netlink length and
// type members are always read/written in native order.
private ByteOrder mByteOrder = ByteOrder.nativeOrder();
public StructNlAttr() {}
public StructNlAttr(ByteOrder byteOrder) {
mByteOrder = byteOrder;
}
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) {
this(order);
nla_type = type;
setValue(new byte[Short.BYTES]);
getValueAsByteBuffer().putShort(value);
}
public StructNlAttr(short type, int value) {
this(type, value, ByteOrder.nativeOrder());
}
public StructNlAttr(short type, int value, ByteOrder order) {
this(order);
nla_type = type;
setValue(new byte[Integer.BYTES]);
getValueAsByteBuffer().putInt(value);
}
public StructNlAttr(short type, InetAddress ip) {
nla_type = type;
setValue(ip.getAddress());
}
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);
}
}
public int getAlignedLength() {
return NetlinkConstants.alignedLengthOf(nla_len);
}
public ByteBuffer getValueAsByteBuffer() {
if (nla_value == null) { return null; }
final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
byteBuffer.order(mByteOrder);
return byteBuffer;
}
public int getValueAsInt(int defaultValue) {
final ByteBuffer byteBuffer = getValueAsByteBuffer();
if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
return defaultValue;
}
return getValueAsByteBuffer().getInt();
}
public InetAddress getValueAsInetAddress() {
if (nla_value == null) { return null; }
try {
return InetAddress.getByAddress(nla_value);
} catch (UnknownHostException ignored) {
return null;
}
}
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) + "}, "
+ "}";
}
}

View File

@@ -1,71 +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 android.net.netlink;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.StructNlMsgHdr;
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;
public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
}
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;
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()) + "} "
+ "}";
}
}

View File

@@ -1,140 +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 android.net.netlink;
import android.net.netlink.NetlinkConstants;
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;
public 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();
}
public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
}
public static StructNlMsgHdr 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 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;
}
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() {
final String typeStr = "" + nlmsg_type
+ "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
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 + "} "
+ "}";
}
}

View File

@@ -1,240 +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 android.net.shared;
import static android.net.shared.ParcelableUtil.fromParcelableArray;
import static android.net.shared.ParcelableUtil.toParcelableArray;
import static android.text.TextUtils.join;
import android.net.InetAddresses;
import android.net.InitialConfigurationParcelable;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.RouteInfo;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
/** @hide */
public class InitialConfiguration {
public final Set<LinkAddress> ipAddresses = new HashSet<>();
public final Set<IpPrefix> directlyConnectedRoutes = new HashSet<>();
public final Set<InetAddress> dnsServers = new HashSet<>();
private static final int RFC6177_MIN_PREFIX_LENGTH = 48;
private static final int RFC7421_PREFIX_LENGTH = 64;
public static final InetAddress INET6_ANY = InetAddresses.parseNumericAddress("::");
/**
* Create a InitialConfiguration that is a copy of the specified configuration.
*/
public static InitialConfiguration copy(InitialConfiguration config) {
if (config == null) {
return null;
}
InitialConfiguration configCopy = new InitialConfiguration();
configCopy.ipAddresses.addAll(config.ipAddresses);
configCopy.directlyConnectedRoutes.addAll(config.directlyConnectedRoutes);
configCopy.dnsServers.addAll(config.dnsServers);
return configCopy;
}
@Override
public String toString() {
return String.format(
"InitialConfiguration(IPs: {%s}, prefixes: {%s}, DNS: {%s})",
join(", ", ipAddresses), join(", ", directlyConnectedRoutes),
join(", ", dnsServers));
}
/**
* Tests whether the contents of this IpConfiguration represent a valid configuration.
*/
public boolean isValid() {
if (ipAddresses.isEmpty()) {
return false;
}
// For every IP address, there must be at least one prefix containing that address.
for (LinkAddress addr : ipAddresses) {
if (!any(directlyConnectedRoutes, (p) -> p.contains(addr.getAddress()))) {
return false;
}
}
// For every dns server, there must be at least one prefix containing that address.
for (InetAddress addr : dnsServers) {
if (!any(directlyConnectedRoutes, (p) -> p.contains(addr))) {
return false;
}
}
// All IPv6 LinkAddresses have an RFC7421-suitable prefix length
// (read: compliant with RFC4291#section2.5.4).
if (any(ipAddresses, not(InitialConfiguration::isPrefixLengthCompliant))) {
return false;
}
// If directlyConnectedRoutes contains an IPv6 default route
// then ipAddresses MUST contain at least one non-ULA GUA.
if (any(directlyConnectedRoutes, InitialConfiguration::isIPv6DefaultRoute)
&& all(ipAddresses, not(InitialConfiguration::isIPv6GUA))) {
return false;
}
// The prefix length of routes in directlyConnectedRoutes be within reasonable
// bounds for IPv6: /48-/64 just as wed accept in RIOs.
if (any(directlyConnectedRoutes, not(InitialConfiguration::isPrefixLengthCompliant))) {
return false;
}
// There no more than one IPv4 address
if (ipAddresses.stream().filter(InitialConfiguration::isIPv4).count() > 1) {
return false;
}
return true;
}
/**
* @return true if the given list of addressess and routes satisfies provisioning for this
* InitialConfiguration. LinkAddresses and RouteInfo objects are not compared with equality
* because addresses and routes seen by Netlink will contain additional fields like flags,
* interfaces, and so on. If this InitialConfiguration has no IP address specified, the
* provisioning check always fails.
*
* If the given list of routes is null, only addresses are taken into considerations.
*/
public boolean isProvisionedBy(List<LinkAddress> addresses, List<RouteInfo> routes) {
if (ipAddresses.isEmpty()) {
return false;
}
for (LinkAddress addr : ipAddresses) {
if (!any(addresses, (addrSeen) -> addr.isSameAddressAs(addrSeen))) {
return false;
}
}
if (routes != null) {
for (IpPrefix prefix : directlyConnectedRoutes) {
if (!any(routes, (routeSeen) -> isDirectlyConnectedRoute(routeSeen, prefix))) {
return false;
}
}
}
return true;
}
/**
* Convert this configuration to a {@link InitialConfigurationParcelable}.
*/
public InitialConfigurationParcelable toStableParcelable() {
final InitialConfigurationParcelable p = new InitialConfigurationParcelable();
p.ipAddresses = ipAddresses.toArray(new LinkAddress[0]);
p.directlyConnectedRoutes = directlyConnectedRoutes.toArray(new IpPrefix[0]);
p.dnsServers = toParcelableArray(
dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class);
return p;
}
/**
* Create an instance of {@link InitialConfiguration} based on the contents of the specified
* {@link InitialConfigurationParcelable}.
*/
public static InitialConfiguration fromStableParcelable(InitialConfigurationParcelable p) {
if (p == null) return null;
final InitialConfiguration config = new InitialConfiguration();
config.ipAddresses.addAll(Arrays.asList(p.ipAddresses));
config.directlyConnectedRoutes.addAll(Arrays.asList(p.directlyConnectedRoutes));
config.dnsServers.addAll(
fromParcelableArray(p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress));
return config;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof InitialConfiguration)) return false;
final InitialConfiguration other = (InitialConfiguration) obj;
return ipAddresses.equals(other.ipAddresses)
&& directlyConnectedRoutes.equals(other.directlyConnectedRoutes)
&& dnsServers.equals(other.dnsServers);
}
private static boolean isDirectlyConnectedRoute(RouteInfo route, IpPrefix prefix) {
return !route.hasGateway() && prefix.equals(route.getDestination());
}
private static boolean isPrefixLengthCompliant(LinkAddress addr) {
return isIPv4(addr) || isCompliantIPv6PrefixLength(addr.getPrefixLength());
}
private static boolean isPrefixLengthCompliant(IpPrefix prefix) {
return isIPv4(prefix) || isCompliantIPv6PrefixLength(prefix.getPrefixLength());
}
private static boolean isCompliantIPv6PrefixLength(int prefixLength) {
return (RFC6177_MIN_PREFIX_LENGTH <= prefixLength)
&& (prefixLength <= RFC7421_PREFIX_LENGTH);
}
private static boolean isIPv4(IpPrefix prefix) {
return prefix.getAddress() instanceof Inet4Address;
}
private static boolean isIPv4(LinkAddress addr) {
return addr.getAddress() instanceof Inet4Address;
}
private static boolean isIPv6DefaultRoute(IpPrefix prefix) {
return prefix.getAddress().equals(INET6_ANY);
}
private static boolean isIPv6GUA(LinkAddress addr) {
return addr.isIpv6() && addr.isGlobalPreferred();
}
// TODO: extract out into CollectionUtils.
/**
* Indicate whether any element of the specified iterable verifies the specified predicate.
*/
public static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
for (T t : coll) {
if (fn.test(t)) {
return true;
}
}
return false;
}
/**
* Indicate whether all elements of the specified iterable verifies the specified predicate.
*/
public static <T> boolean all(Iterable<T> coll, Predicate<T> fn) {
return !any(coll, not(fn));
}
/**
* Create a predicate that returns the opposite value of the specified predicate.
*/
public static <T> Predicate<T> not(Predicate<T> fn) {
return (t) -> !fn.test(t);
}
}

View File

@@ -1,79 +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 android.net.shared;
import android.annotation.Nullable;
import android.net.DhcpResults;
import android.net.DhcpResultsParcelable;
import android.net.InetAddresses;
import java.net.Inet4Address;
import java.net.InetAddress;
/**
* Collection of utility methods to convert to and from stable AIDL parcelables for IpClient
* configuration classes.
* @hide
*/
public final class IpConfigurationParcelableUtil {
/**
* Convert DhcpResults to a DhcpResultsParcelable.
*/
public static DhcpResultsParcelable toStableParcelable(@Nullable DhcpResults results) {
if (results == null) return null;
final DhcpResultsParcelable p = new DhcpResultsParcelable();
p.baseConfiguration = results.toStaticIpConfiguration();
p.leaseDuration = results.leaseDuration;
p.mtu = results.mtu;
p.serverAddress = parcelAddress(results.serverAddress);
p.vendorInfo = results.vendorInfo;
p.serverHostName = results.serverHostName;
return p;
}
/**
* Convert a DhcpResultsParcelable to DhcpResults.
*/
public static DhcpResults fromStableParcelable(@Nullable DhcpResultsParcelable p) {
if (p == null) return null;
final DhcpResults results = new DhcpResults(p.baseConfiguration);
results.leaseDuration = p.leaseDuration;
results.mtu = p.mtu;
results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
results.vendorInfo = p.vendorInfo;
results.serverHostName = p.serverHostName;
return results;
}
/**
* Convert InetAddress to String.
* TODO: have an InetAddressParcelable
*/
public static String parcelAddress(@Nullable InetAddress addr) {
if (addr == null) return null;
return addr.getHostAddress();
}
/**
* Convert String to InetAddress.
* TODO: have an InetAddressParcelable
*/
public static InetAddress unparcelAddress(@Nullable String addr) {
if (addr == null) return null;
return InetAddresses.parseNumericAddress(addr);
}
}

View File

@@ -1,47 +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 android.net.shared;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.ProxyInfo;
/**
* Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties
* and its attributes.
* @hide
*/
public final class LinkPropertiesParcelableUtil {
// Temporary methods to facilitate migrating clients away from LinkPropertiesParcelable
// TODO: remove the following methods after migrating clients.
/**
* @deprecated conversion to stable parcelable is no longer necessary.
*/
@Deprecated
public static LinkProperties toStableParcelable(@Nullable LinkProperties lp) {
return lp;
}
/**
* @deprecated conversion to stable parcelable is no longer necessary.
*/
@Deprecated
public static ProxyInfo toStableParcelable(@Nullable ProxyInfo info) {
return info;
}
}

View File

@@ -1,65 +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 android.net.shared;
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_TRUSTED;
import android.net.NetworkCapabilities;
/** @hide */
public class NetworkMonitorUtils {
// 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(NetworkCapabilities nc) {
// TODO: Consider requiring validation for DUN networks.
return nc != null
&& nc.hasCapability(NET_CAPABILITY_INTERNET)
&& nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
&& nc.hasCapability(NET_CAPABILITY_TRUSTED);
}
/**
* Return whether validation is required for a network.
* @param nc Network capabilities of the network to test.
*/
public static boolean isValidationRequired(NetworkCapabilities nc) {
// TODO: Consider requiring validation for DUN networks.
return isPrivateDnsValidationRequired(nc) && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
}
}

View File

@@ -1,63 +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 android.net.shared;
import android.annotation.NonNull;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
/**
* Utility methods to help convert to/from stable parcelables.
* @hide
*/
public final class ParcelableUtil {
// Below methods could be implemented easily with streams, but streams are frowned upon in
// frameworks code.
/**
* Convert a list of BaseType items to an array of ParcelableType items using the specified
* converter function.
*/
public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray(
@NonNull Collection<BaseType> base,
@NonNull Function<BaseType, ParcelableType> conv,
@NonNull Class<ParcelableType> parcelClass) {
final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size());
int i = 0;
for (BaseType b : base) {
out[i] = conv.apply(b);
i++;
}
return out;
}
/**
* Convert an array of ParcelableType items to a list of BaseType items using the specified
* converter function.
*/
public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray(
@NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) {
final ArrayList<BaseType> out = new ArrayList<>(parceled.length);
for (ParcelableType t : parceled) {
out.add(conv.apply(t));
}
return out;
}
}

View File

@@ -1,90 +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 android.net.shared;
import static android.net.shared.ParcelableUtil.fromParcelableArray;
import static android.net.shared.ParcelableUtil.toParcelableArray;
import android.net.PrivateDnsConfigParcel;
import android.text.TextUtils;
import java.net.InetAddress;
import java.util.Arrays;
/** @hide */
public class PrivateDnsConfig {
public final boolean useTls;
public final String hostname;
public final InetAddress[] ips;
public PrivateDnsConfig() {
this(false);
}
public PrivateDnsConfig(boolean useTls) {
this.useTls = useTls;
this.hostname = "";
this.ips = new InetAddress[0];
}
public PrivateDnsConfig(String hostname, InetAddress[] ips) {
this.useTls = !TextUtils.isEmpty(hostname);
this.hostname = useTls ? hostname : "";
this.ips = (ips != null) ? ips : new InetAddress[0];
}
public PrivateDnsConfig(PrivateDnsConfig cfg) {
useTls = cfg.useTls;
hostname = cfg.hostname;
ips = cfg.ips;
}
/**
* Indicates whether this is a strict mode private DNS configuration.
*/
public boolean inStrictMode() {
return useTls && !TextUtils.isEmpty(hostname);
}
@Override
public String toString() {
return PrivateDnsConfig.class.getSimpleName()
+ "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
}
/**
* Create a stable AIDL-compatible parcel from the current instance.
*/
public PrivateDnsConfigParcel toParcel() {
final PrivateDnsConfigParcel parcel = new PrivateDnsConfigParcel();
parcel.hostname = hostname;
parcel.ips = toParcelableArray(
Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class);
return parcel;
}
/**
* Build a configuration from a stable AIDL-compatible parcel.
*/
public static PrivateDnsConfig fromParcel(PrivateDnsConfigParcel parcel) {
InetAddress[] ips = new InetAddress[parcel.ips.length];
ips = fromParcelableArray(parcel.ips, IpConfigurationParcelableUtil::unparcelAddress)
.toArray(ips);
return new PrivateDnsConfig(parcel.hostname, ips);
}
}

View File

@@ -1,312 +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 android.net.shared;
import android.annotation.Nullable;
import android.net.INetd;
import android.net.Network;
import android.net.ProvisioningConfigurationParcelable;
import android.net.StaticIpConfiguration;
import android.net.apf.ApfCapabilities;
import android.net.ip.IIpClient;
import java.util.Objects;
import java.util.StringJoiner;
/**
* This class encapsulates parameters to be passed to
* IpClient#startProvisioning(). A defensive copy is made by IpClient
* and the values specified herein are in force until IpClient#stop()
* is called.
*
* Example use:
*
* final ProvisioningConfiguration config =
* new ProvisioningConfiguration.Builder()
* .withPreDhcpAction()
* .withProvisioningTimeoutMs(36 * 1000)
* .build();
* mIpClient.startProvisioning(config.toStableParcelable());
* ...
* mIpClient.stop();
*
* The specified provisioning configuration will only be active until
* IIpClient#stop() is called. Future calls to IIpClient#startProvisioning()
* must specify the configuration again.
* @hide
*/
public class ProvisioningConfiguration {
// TODO: Delete this default timeout once those callers that care are
// fixed to pass in their preferred timeout.
//
// We pick 36 seconds so we can send DHCP requests at
//
// t=0, t=2, t=6, t=14, t=30
//
// allowing for 10% jitter.
private static final int DEFAULT_TIMEOUT_MS = 36 * 1000;
/**
* Builder to create a {@link ProvisioningConfiguration}.
*/
public static class Builder {
protected ProvisioningConfiguration mConfig = new ProvisioningConfiguration();
/**
* Specify that the configuration should not enable IPv4. It is enabled by default.
*/
public Builder withoutIPv4() {
mConfig.mEnableIPv4 = false;
return this;
}
/**
* Specify that the configuration should not enable IPv6. It is enabled by default.
*/
public Builder withoutIPv6() {
mConfig.mEnableIPv6 = false;
return this;
}
/**
* Specify that the configuration should not use a MultinetworkPolicyTracker. It is used
* by default.
*/
public Builder withoutMultinetworkPolicyTracker() {
mConfig.mUsingMultinetworkPolicyTracker = false;
return this;
}
/**
* Specify that the configuration should not use a IpReachabilityMonitor. It is used by
* default.
*/
public Builder withoutIpReachabilityMonitor() {
mConfig.mUsingIpReachabilityMonitor = false;
return this;
}
/**
* Identical to {@link #withPreDhcpAction(int)}, using a default timeout.
* @see #withPreDhcpAction(int)
*/
public Builder withPreDhcpAction() {
mConfig.mRequestedPreDhcpActionMs = DEFAULT_TIMEOUT_MS;
return this;
}
/**
* Specify that {@link IpClientCallbacks#onPreDhcpAction()} should be called. Clients must
* call {@link IIpClient#completedPreDhcpAction()} when the callback called. This behavior
* is disabled by default.
* @param dhcpActionTimeoutMs Timeout for clients to call completedPreDhcpAction().
*/
public Builder withPreDhcpAction(int dhcpActionTimeoutMs) {
mConfig.mRequestedPreDhcpActionMs = dhcpActionTimeoutMs;
return this;
}
/**
* Specify the initial provisioning configuration.
*/
public Builder withInitialConfiguration(InitialConfiguration initialConfig) {
mConfig.mInitialConfig = initialConfig;
return this;
}
/**
* Specify a static configuration for provisioning.
*/
public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
mConfig.mStaticIpConfig = staticConfig;
return this;
}
/**
* Specify ApfCapabilities.
*/
public Builder withApfCapabilities(ApfCapabilities apfCapabilities) {
mConfig.mApfCapabilities = apfCapabilities;
return this;
}
/**
* Specify the timeout to use for provisioning.
*/
public Builder withProvisioningTimeoutMs(int timeoutMs) {
mConfig.mProvisioningTimeoutMs = timeoutMs;
return this;
}
/**
* Specify that IPv6 address generation should use a random MAC address.
*/
public Builder withRandomMacAddress() {
mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
return this;
}
/**
* Specify that IPv6 address generation should use a stable MAC address.
*/
public Builder withStableMacAddress() {
mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
return this;
}
/**
* Specify the network to use for provisioning.
*/
public Builder withNetwork(Network network) {
mConfig.mNetwork = network;
return this;
}
/**
* Specify the display name that the IpClient should use.
*/
public Builder withDisplayName(String displayName) {
mConfig.mDisplayName = displayName;
return this;
}
/**
* Build the configuration using previously specified parameters.
*/
public ProvisioningConfiguration build() {
return new ProvisioningConfiguration(mConfig);
}
}
public boolean mEnableIPv4 = true;
public boolean mEnableIPv6 = true;
public boolean mUsingMultinetworkPolicyTracker = true;
public boolean mUsingIpReachabilityMonitor = true;
public int mRequestedPreDhcpActionMs;
public InitialConfiguration mInitialConfig;
public StaticIpConfiguration mStaticIpConfig;
public ApfCapabilities mApfCapabilities;
public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
public Network mNetwork = null;
public String mDisplayName = null;
public ProvisioningConfiguration() {} // used by Builder
public ProvisioningConfiguration(ProvisioningConfiguration other) {
mEnableIPv4 = other.mEnableIPv4;
mEnableIPv6 = other.mEnableIPv6;
mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker;
mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs;
mInitialConfig = InitialConfiguration.copy(other.mInitialConfig);
mStaticIpConfig = other.mStaticIpConfig == null
? null
: new StaticIpConfiguration(other.mStaticIpConfig);
mApfCapabilities = other.mApfCapabilities;
mProvisioningTimeoutMs = other.mProvisioningTimeoutMs;
mIPv6AddrGenMode = other.mIPv6AddrGenMode;
mNetwork = other.mNetwork;
mDisplayName = other.mDisplayName;
}
/**
* Create a ProvisioningConfigurationParcelable from this ProvisioningConfiguration.
*/
public ProvisioningConfigurationParcelable toStableParcelable() {
final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
p.enableIPv4 = mEnableIPv4;
p.enableIPv6 = mEnableIPv6;
p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker;
p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor;
p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs;
p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable();
p.staticIpConfig = mStaticIpConfig == null
? null
: new StaticIpConfiguration(mStaticIpConfig);
p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable
p.provisioningTimeoutMs = mProvisioningTimeoutMs;
p.ipv6AddrGenMode = mIPv6AddrGenMode;
p.network = mNetwork;
p.displayName = mDisplayName;
return p;
}
/**
* Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable.
*/
public static ProvisioningConfiguration fromStableParcelable(
@Nullable ProvisioningConfigurationParcelable p) {
if (p == null) return null;
final ProvisioningConfiguration config = new ProvisioningConfiguration();
config.mEnableIPv4 = p.enableIPv4;
config.mEnableIPv6 = p.enableIPv6;
config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker;
config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor;
config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs;
config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig);
config.mStaticIpConfig = p.staticIpConfig == null
? null
: new StaticIpConfiguration(p.staticIpConfig);
config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable
config.mProvisioningTimeoutMs = p.provisioningTimeoutMs;
config.mIPv6AddrGenMode = p.ipv6AddrGenMode;
config.mNetwork = p.network;
config.mDisplayName = p.displayName;
return config;
}
@Override
public String toString() {
return new StringJoiner(", ", getClass().getSimpleName() + "{", "}")
.add("mEnableIPv4: " + mEnableIPv4)
.add("mEnableIPv6: " + mEnableIPv6)
.add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker)
.add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor)
.add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs)
.add("mInitialConfig: " + mInitialConfig)
.add("mStaticIpConfig: " + mStaticIpConfig)
.add("mApfCapabilities: " + mApfCapabilities)
.add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs)
.add("mIPv6AddrGenMode: " + mIPv6AddrGenMode)
.add("mNetwork: " + mNetwork)
.add("mDisplayName: " + mDisplayName)
.toString();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ProvisioningConfiguration)) return false;
final ProvisioningConfiguration other = (ProvisioningConfiguration) obj;
return mEnableIPv4 == other.mEnableIPv4
&& mEnableIPv6 == other.mEnableIPv6
&& mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker
&& mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor
&& mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs
&& Objects.equals(mInitialConfig, other.mInitialConfig)
&& Objects.equals(mStaticIpConfig, other.mStaticIpConfig)
&& Objects.equals(mApfCapabilities, other.mApfCapabilities)
&& mProvisioningTimeoutMs == other.mProvisioningTimeoutMs
&& mIPv6AddrGenMode == other.mIPv6AddrGenMode
&& Objects.equals(mNetwork, other.mNetwork)
&& Objects.equals(mDisplayName, other.mDisplayName);
}
public boolean isValid() {
return (mInitialConfig == null) || mInitialConfig.isValid();
}
}

View File

@@ -1,97 +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 android.net.util;
import static com.android.internal.util.Preconditions.checkArgument;
import android.net.MacAddress;
import android.text.TextUtils;
import java.net.NetworkInterface;
import java.net.SocketException;
/**
* Encapsulate the interface parameters common to IpClient/IpServer components.
*
* Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
* and IpServer (sub)components need most or all of this information at some
* point during their lifecycles, so pass only this simplified object around
* which can be created once when IpClient/IpServer are told to start.
*
* @hide
*/
public class InterfaceParams {
public final String name;
public final int index;
public final MacAddress macAddr;
public final int defaultMtu;
// TODO: move the below to NetworkStackConstants when this class is moved to the NetworkStack.
private static final int ETHER_MTU = 1500;
private static final int IPV6_MIN_MTU = 1280;
public static InterfaceParams getByName(String name) {
final NetworkInterface netif = getNetworkInterfaceByName(name);
if (netif == null) return null;
// Not all interfaces have MAC addresses, e.g. rmnet_data0.
final MacAddress macAddr = getMacAddress(netif);
try {
return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
} catch (IllegalArgumentException|SocketException e) {
return null;
}
}
public InterfaceParams(String name, int index, MacAddress macAddr) {
this(name, index, macAddr, ETHER_MTU);
}
public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
checkArgument((index > 0), "invalid interface index");
this.name = name;
this.index = index;
this.macAddr = (macAddr != null) ? macAddr : MacAddress.fromBytes(new byte[] {
0x02, 0x00, 0x00, 0x00, 0x00, 0x00 });
this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
}
@Override
public String toString() {
return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
}
private static NetworkInterface getNetworkInterfaceByName(String name) {
try {
return NetworkInterface.getByName(name);
} catch (NullPointerException|SocketException e) {
return null;
}
}
private static MacAddress getMacAddress(NetworkInterface netif) {
try {
return MacAddress.fromBytes(netif.getHardwareAddress());
} catch (IllegalArgumentException|NullPointerException|SocketException e) {
return null;
}
}
}

View File

@@ -1,202 +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 android.net.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.PrintWriter;
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.
*
* TODO: this is a copy of SharedLog in the NetworkStack. Remove after Tethering is migrated.
* @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,
};
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.readOnlyLocalLog().dump(fd, writer, args);
}
//////
// 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));
}
//////
// 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.log(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);
}
}

View File

@@ -1,89 +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 android.net.ip;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.net.INetd;
import android.net.InetAddresses;
import android.net.InterfaceConfigurationParcel;
import android.net.LinkAddress;
import android.net.util.SharedLog;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class InterfaceControllerTest {
private static final String TEST_IFACE = "testif";
private static final String TEST_IPV4_ADDR = "192.168.123.28";
private static final int TEST_PREFIXLENGTH = 31;
@Mock private INetd mNetd;
@Mock private SharedLog mLog;
@Captor private ArgumentCaptor<InterfaceConfigurationParcel> mConfigCaptor;
private InterfaceController mController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mController = new InterfaceController(TEST_IFACE, mNetd, mLog);
doNothing().when(mNetd).interfaceSetCfg(mConfigCaptor.capture());
}
@Test
public void testSetIPv4Address() throws Exception {
mController.setIPv4Address(
new LinkAddress(InetAddresses.parseNumericAddress(TEST_IPV4_ADDR),
TEST_PREFIXLENGTH));
verify(mNetd, times(1)).interfaceSetCfg(any());
final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
assertEquals(TEST_IFACE, parcel.ifName);
assertEquals(TEST_IPV4_ADDR, parcel.ipv4Addr);
assertEquals(TEST_PREFIXLENGTH, parcel.prefixLength);
assertEquals("", parcel.hwAddr);
assertArrayEquals(new String[0], parcel.flags);
}
@Test
public void testClearIPv4Address() throws Exception {
mController.clearIPv4Address();
verify(mNetd, times(1)).interfaceSetCfg(any());
final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
assertEquals(TEST_IFACE, parcel.ifName);
assertEquals("0.0.0.0", parcel.ipv4Addr);
assertEquals(0, parcel.prefixLength);
assertEquals("", parcel.hwAddr);
assertArrayEquals(new String[0], parcel.flags);
}
}

View File

@@ -1,130 +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 android.net.netlink;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assume.assumeTrue;
import android.system.OsConstants;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import libcore.util.HexEncoding;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteOrder;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConntrackMessageTest {
private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
// Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
public static final String CT_V4UPDATE_TCP_HEX =
// struct nlmsghdr
"50000000" + // length = 80
"0001" + // type = (1 << 8) | 0
"0501" + // flags
"01000000" + // seqno = 1
"00000000" + // pid = 0
// struct nfgenmsg
"02" + // nfgen_family = AF_INET
"00" + // version = NFNETLINK_V0
"0000" + // res_id
// struct nlattr
"3400" + // nla_len = 52
"0180" + // nla_type = nested CTA_TUPLE_ORIG
// struct nlattr
"1400" + // nla_len = 20
"0180" + // nla_type = nested CTA_TUPLE_IP
"0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
"0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
// struct nlattr
"1C00" + // nla_len = 28
"0280" + // nla_type = nested CTA_TUPLE_PROTO
"0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6
"0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
"0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
// struct nlattr
"0800" + // nla_len = 8
"0700" + // nla_type = CTA_TIMEOUT
"00069780"; // nla_value = 432000 (big endian)
public static final byte[] CT_V4UPDATE_TCP_BYTES =
HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
// Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
public static final String CT_V4UPDATE_UDP_HEX =
// struct nlmsghdr
"50000000" + // length = 80
"0001" + // type = (1 << 8) | 0
"0501" + // flags
"01000000" + // seqno = 1
"00000000" + // pid = 0
// struct nfgenmsg
"02" + // nfgen_family = AF_INET
"00" + // version = NFNETLINK_V0
"0000" + // res_id
// struct nlattr
"3400" + // nla_len = 52
"0180" + // nla_type = nested CTA_TUPLE_ORIG
// struct nlattr
"1400" + // nla_len = 20
"0180" + // nla_type = nested CTA_TUPLE_IP
"0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
"0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
// struct nlattr
"1C00" + // nla_len = 28
"0280" + // nla_type = nested CTA_TUPLE_PROTO
"0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17
"0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
"0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
// struct nlattr
"0800" + // nla_len = 8
"0700" + // nla_type = CTA_TIMEOUT
"000000B4"; // nla_value = 180 (big endian)
public static final byte[] CT_V4UPDATE_UDP_BYTES =
HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
@Test
public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
assumeTrue(USING_LE);
final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
OsConstants.IPPROTO_TCP,
(Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
(Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
432000);
assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
}
@Test
public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
assumeTrue(USING_LE);
final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
OsConstants.IPPROTO_UDP,
(Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
(Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
180);
assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
}
}

View File

@@ -1,448 +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 android.net.netlink;
import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
import static android.system.OsConstants.SOCK_STREAM;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.Instrumentation;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.netlink.StructNlMsgHdr;
import android.os.Process;
import android.system.Os;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import libcore.util.HexEncoding;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class InetDiagSocketTest {
private final String TAG = "InetDiagSocketTest";
private ConnectivityManager mCm;
private Context mContext;
private final static int SOCKET_TIMEOUT_MS = 100;
@Before
public void setUp() throws Exception {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
mContext = instrumentation.getTargetContext();
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private class Connection {
public int socketDomain;
public int socketType;
public InetAddress localAddress;
public InetAddress remoteAddress;
public InetAddress localhostAddress;
public InetSocketAddress local;
public InetSocketAddress remote;
public int protocol;
public FileDescriptor localFd;
public FileDescriptor remoteFd;
public FileDescriptor createSocket() throws Exception {
return Os.socket(socketDomain, socketType, protocol);
}
public Connection(String to, String from) throws Exception {
remoteAddress = InetAddress.getByName(to);
if (from != null) {
localAddress = InetAddress.getByName(from);
} else {
localAddress = (remoteAddress instanceof Inet4Address) ?
Inet4Address.getByName("localhost") : Inet6Address.getByName("::");
}
if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) {
socketDomain = AF_INET;
localhostAddress = Inet4Address.getByName("localhost");
} else {
socketDomain = AF_INET6;
localhostAddress = Inet6Address.getByName("::");
}
}
public void close() throws Exception {
Os.close(localFd);
}
}
private class TcpConnection extends Connection {
public TcpConnection(String to, String from) throws Exception {
super(to, from);
protocol = IPPROTO_TCP;
socketType = SOCK_STREAM;
remoteFd = createSocket();
Os.bind(remoteFd, remoteAddress, 0);
Os.listen(remoteFd, 10);
int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort();
localFd = createSocket();
Os.bind(localFd, localAddress, 0);
Os.connect(localFd, remoteAddress, remotePort);
local = (InetSocketAddress) Os.getsockname(localFd);
remote = (InetSocketAddress) Os.getpeername(localFd);
}
public void close() throws Exception {
super.close();
Os.close(remoteFd);
}
}
private class UdpConnection extends Connection {
public UdpConnection(String to, String from) throws Exception {
super(to, from);
protocol = IPPROTO_UDP;
socketType = SOCK_DGRAM;
remoteFd = null;
localFd = createSocket();
Os.bind(localFd, localAddress, 0);
Os.connect(localFd, remoteAddress, 7);
local = (InetSocketAddress) Os.getsockname(localFd);
remote = new InetSocketAddress(remoteAddress, 7);
}
}
private void checkConnectionOwnerUid(int protocol, InetSocketAddress local,
InetSocketAddress remote, boolean expectSuccess) {
final int uid = mCm.getConnectionOwnerUid(protocol, local, remote);
if (expectSuccess) {
assertEquals(Process.myUid(), uid);
} else {
assertNotEquals(Process.myUid(), uid);
}
}
private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception {
UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(),
conn.localAddress.getHostAddress());
final int localPort = udp.local.getPort();
udp.close();
return localPort;
}
/**
* Create a test connection for UDP and TCP sockets and verify that this
* {protocol, local, remote} socket result in receiving a valid UID.
*/
public void checkGetConnectionOwnerUid(String to, String from) throws Exception {
TcpConnection tcp = new TcpConnection(to, from);
checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true);
checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false);
checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false);
checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false);
tcp.close();
UdpConnection udp = new UdpConnection(to,from);
checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true);
checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false);
checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)),
udp.remote, false);
udp.close();
}
@Test
public void testGetConnectionOwnerUid() throws Exception {
checkGetConnectionOwnerUid("::", null);
checkGetConnectionOwnerUid("::", "::");
checkGetConnectionOwnerUid("0.0.0.0", null);
checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0");
checkGetConnectionOwnerUid("127.0.0.1", null);
checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2");
checkGetConnectionOwnerUid("::1", null);
checkGetConnectionOwnerUid("::1", "::1");
}
/* Verify fix for b/141603906 */
@Test
public void testB141603906() throws Exception {
final InetSocketAddress src = new InetSocketAddress(0);
final InetSocketAddress dst = new InetSocketAddress(0);
final int numThreads = 8;
final int numSockets = 5000;
final Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < numSockets; j++) {
mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst);
}
});
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
}
// Hexadecimal representation of InetDiagReqV2 request.
private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
// struct nlmsghdr
"48000000" + // length = 72
"1400" + // type = SOCK_DIAG_BY_FAMILY
"0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct inet_diag_req_v2
"02" + // family = AF_INET
"11" + // protcol = IPPROTO_UDP
"00" + // idiag_ext
"00" + // pad
"ffffffff" + // idiag_states
// inet_diag_sockid
"a5de" + // idiag_sport = 42462
"b971" + // idiag_dport = 47473
"0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
"08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
"00000000" + // idiag_if
"ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES =
HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false);
@Test
public void testInetDiagReqV2UdpInet4() throws Exception {
InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"),
42462);
InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
47473);
final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET,
(short) (NLM_F_REQUEST | NLM_F_DUMP));
assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg);
}
// Hexadecimal representation of InetDiagReqV2 request.
private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX =
// struct nlmsghdr
"48000000" + // length = 72
"1400" + // type = SOCK_DIAG_BY_FAMILY
"0100" + // flags = NLM_F_REQUEST
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct inet_diag_req_v2
"0a" + // family = AF_INET6
"06" + // protcol = IPPROTO_TCP
"00" + // idiag_ext
"00" + // pad
"ffffffff" + // idiag_states
// inet_diag_sockid
"a5de" + // idiag_sport = 42462
"b971" + // idiag_dport = 47473
"fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
"08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
"00000000" + // idiag_if
"ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES =
HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false);
@Test
public void testInetDiagReqV2TcpInet6() throws Exception {
InetSocketAddress local = new InetSocketAddress(
InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
47473);
byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
NLM_F_REQUEST);
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
}
// Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
// struct nlmsghdr
"48000000" + // length = 72
"1400" + // type = SOCK_DIAG_BY_FAMILY
"0100" + // flags = NLM_F_REQUEST
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct inet_diag_req_v2
"02" + // family = AF_INET
"06" + // protcol = IPPROTO_TCP
"02" + // idiag_ext = INET_DIAG_INFO
"00" + // pad
"ffffffff" + // idiag_states
// inet_diag_sockid
"3039" + // idiag_sport = 12345
"d431" + // idiag_dport = 54321
"01020304000000000000000000000000" + // idiag_src = 1.2.3.4
"08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
"00000000" + // idiag_if
"ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
private static final int TCP_ALL_STATES = 0xffffffff;
@Test
public void testInetDiagReqV2TcpInetWithExt() throws Exception {
InetSocketAddress local = new InetSocketAddress(
InetAddress.getByName("1.2.3.4"), 12345);
InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
54321);
byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
local = new InetSocketAddress(
InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
47473);
msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
}
// Hexadecimal representation of InetDiagReqV2 request with no socket specified.
private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
// struct nlmsghdr
"48000000" + // length = 72
"1400" + // type = SOCK_DIAG_BY_FAMILY
"0100" + // flags = NLM_F_REQUEST
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct inet_diag_req_v2
"0a" + // family = AF_INET6
"06" + // protcol = IPPROTO_TCP
"00" + // idiag_ext
"00" + // pad
"ffffffff" + // idiag_states
// inet_diag_sockid
"0000" + // idiag_sport
"0000" + // idiag_dport
"00000000000000000000000000000000" + // idiag_src
"00000000000000000000000000000000" + // idiag_dst
"00000000" + // idiag_if
"0000000000000000"; // idiag_cookie
private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
@Test
public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
InetSocketAddress local = new InetSocketAddress(
InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
54321);
// Verify no socket specified if either local or remote socket address is null.
byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
byte[] msg;
try {
msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
NLM_F_REQUEST);
fail("Both remote and local should be null, expected UnknownHostException");
} catch (NullPointerException e) {
}
try {
msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
fail("Both remote and local should be null, expected UnknownHostException");
} catch (NullPointerException e) {
}
msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
}
// Hexadecimal representation of InetDiagReqV2 request.
private static final String INET_DIAG_MSG_HEX =
// struct nlmsghdr
"58000000" + // length = 88
"1400" + // type = SOCK_DIAG_BY_FAMILY
"0200" + // flags = NLM_F_MULTI
"00000000" + // seqno
"f5220000" + // pid (0 == kernel)
// struct inet_diag_msg
"0a" + // family = AF_INET6
"01" + // idiag_state
"00" + // idiag_timer
"00" + // idiag_retrans
// inet_diag_sockid
"a817" + // idiag_sport = 43031
"960f" + // idiag_dport = 38415
"fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
"00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8
"00000000" + // idiag_if
"ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE
"00000000" + // idiag_expires
"00000000" + // idiag_rqueue
"00000000" + // idiag_wqueue
"a3270000" + // idiag_uid
"A57E1900"; // idiag_inode
private static final byte[] INET_DIAG_MSG_BYTES =
HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false);
@Test
public void testParseInetDiagResponse() throws Exception {
final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
assertNotNull(msg);
assertTrue(msg instanceof InetDiagMessage);
final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid);
final StructNlMsgHdr hdr = inetDiagMsg.getHeader();
assertNotNull(hdr);
assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type);
assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
assertEquals(0, hdr.nlmsg_seq);
assertEquals(8949, hdr.nlmsg_pid);
}
}

View File

@@ -1,94 +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 android.net.netlink;
import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.StructNlMsgErr;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import libcore.util.HexEncoding;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetlinkErrorMessageTest {
private final String TAG = "NetlinkErrorMessageTest";
// Hexadecimal representation of packet capture.
public static final String NLM_ERROR_OK_HEX =
// struct nlmsghdr
"24000000" + // length = 36
"0200" + // type = 2 (NLMSG_ERROR)
"0000" + // flags
"26350000" + // seqno
"64100000" + // pid = userspace process
// error integer
"00000000" + // "errno" (0 == OK)
// struct nlmsghdr
"30000000" + // length (48) of original request
"1C00" + // type = 28 (RTM_NEWNEIGH)
"0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
"26350000" + // seqno
"00000000"; // pid = kernel
public static final byte[] NLM_ERROR_OK =
HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
@Test
public void testParseNlmErrorOk() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
assertNotNull(msg);
assertTrue(msg instanceof NetlinkErrorMessage);
final NetlinkErrorMessage errorMsg = (NetlinkErrorMessage) msg;
final StructNlMsgHdr hdr = errorMsg.getHeader();
assertNotNull(hdr);
assertEquals(36, hdr.nlmsg_len);
assertEquals(NetlinkConstants.NLMSG_ERROR, hdr.nlmsg_type);
assertEquals(0, hdr.nlmsg_flags);
assertEquals(13606, hdr.nlmsg_seq);
assertEquals(4196, hdr.nlmsg_pid);
final StructNlMsgErr err = errorMsg.getNlMsgError();
assertNotNull(err);
assertEquals(0, err.error);
assertNotNull(err.msg);
assertEquals(48, err.msg.nlmsg_len);
assertEquals(NetlinkConstants.RTM_NEWNEIGH, err.msg.nlmsg_type);
assertEquals((NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE), err.msg.nlmsg_flags);
assertEquals(13606, err.msg.nlmsg_seq);
assertEquals(0, err.msg.nlmsg_pid);
}
}

View File

@@ -1,106 +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 android.net.netlink;
import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
import static android.system.OsConstants.NETLINK_ROUTE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.net.netlink.NetlinkSocket;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNlMsgHdr;
import android.system.NetlinkSocketAddress;
import android.system.Os;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import libcore.io.IoUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetlinkSocketTest {
private final String TAG = "NetlinkSocketTest";
@Test
public void testBasicWorkingGetNeighborsQuery() throws Exception {
final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE);
assertNotNull(fd);
NetlinkSocket.connectToKernel(fd);
final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd);
assertNotNull(localAddr);
assertEquals(0, localAddr.getGroupsMask());
assertTrue(0 != localAddr.getPortId());
final int TEST_SEQNO = 5;
final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO);
assertNotNull(req);
final long TIMEOUT = 500;
assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT));
int neighMessageCount = 0;
int doneMessageCount = 0;
while (doneMessageCount == 0) {
ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
assertNotNull(response);
assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit());
assertEquals(0, response.position());
assertEquals(ByteOrder.nativeOrder(), response.order());
// Verify the messages at least appears minimally reasonable.
while (response.remaining() > 0) {
final NetlinkMessage msg = NetlinkMessage.parse(response);
assertNotNull(msg);
final StructNlMsgHdr hdr = msg.getHeader();
assertNotNull(hdr);
if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
doneMessageCount++;
continue;
}
assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
assertTrue(msg instanceof RtNetlinkNeighborMessage);
assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0);
assertEquals(TEST_SEQNO, hdr.nlmsg_seq);
assertEquals(localAddr.getPortId(), hdr.nlmsg_pid);
neighMessageCount++;
}
}
assertEquals(1, doneMessageCount);
// TODO: make sure this test passes sanely in airplane mode.
assertTrue(neighMessageCount > 0);
IoUtils.closeQuietly(fd);
}
}

View File

@@ -1,270 +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 android.net.netlink;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlMsgHdr;
import android.system.OsConstants;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import libcore.util.HexEncoding;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class RtNetlinkNeighborMessageTest {
private final String TAG = "RtNetlinkNeighborMessageTest";
// Hexadecimal representation of packet capture.
public static final String RTM_DELNEIGH_HEX =
// struct nlmsghdr
"4c000000" + // length = 76
"1d00" + // type = 29 (RTM_DELNEIGH)
"0000" + // flags
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct ndmsg
"02" + // family
"00" + // pad1
"0000" + // pad2
"15000000" + // interface index (21 == wlan0, on test device)
"0400" + // NUD state (0x04 == NUD_STALE)
"00" + // flags
"01" + // type
// struct nlattr: NDA_DST
"0800" + // length = 8
"0100" + // type (1 == NDA_DST, for neighbor messages)
"c0a89ffe" + // IPv4 address (== 192.168.159.254)
// struct nlattr: NDA_LLADDR
"0a00" + // length = 10
"0200" + // type (2 == NDA_LLADDR, for neighbor messages)
"00005e000164" + // MAC Address (== 00:00:5e:00:01:64)
"0000" + // padding, for 4 byte alignment
// struct nlattr: NDA_PROBES
"0800" + // length = 8
"0400" + // type (4 == NDA_PROBES, for neighbor messages)
"01000000" + // number of probes
// struct nlattr: NDA_CACHEINFO
"1400" + // length = 20
"0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
"05190000" + // ndm_used, as "clock ticks ago"
"05190000" + // ndm_confirmed, as "clock ticks ago"
"190d0000" + // ndm_updated, as "clock ticks ago"
"00000000"; // ndm_refcnt
public static final byte[] RTM_DELNEIGH =
HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false);
// Hexadecimal representation of packet capture.
public static final String RTM_NEWNEIGH_HEX =
// struct nlmsghdr
"58000000" + // length = 88
"1c00" + // type = 28 (RTM_NEWNEIGH)
"0000" + // flags
"00000000" + // seqno
"00000000" + // pid (0 == kernel)
// struct ndmsg
"0a" + // family
"00" + // pad1
"0000" + // pad2
"15000000" + // interface index (21 == wlan0, on test device)
"0400" + // NUD state (0x04 == NUD_STALE)
"80" + // flags
"01" + // type
// struct nlattr: NDA_DST
"1400" + // length = 20
"0100" + // type (1 == NDA_DST, for neighbor messages)
"fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b)
// struct nlattr: NDA_LLADDR
"0a00" + // length = 10
"0200" + // type (2 == NDA_LLADDR, for neighbor messages)
"84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b)
"0000" + // padding, for 4 byte alignment
// struct nlattr: NDA_PROBES
"0800" + // length = 8
"0400" + // type (4 == NDA_PROBES, for neighbor messages)
"01000000" + // number of probes
// struct nlattr: NDA_CACHEINFO
"1400" + // length = 20
"0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
"eb0e0000" + // ndm_used, as "clock ticks ago"
"861f0000" + // ndm_confirmed, as "clock ticks ago"
"00000000" + // ndm_updated, as "clock ticks ago"
"05000000"; // ndm_refcnt
public static final byte[] RTM_NEWNEIGH =
HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false);
// An example of the full response from an RTM_GETNEIGH query.
private static final String RTM_GETNEIGH_RESPONSE_HEX =
// <-- struct nlmsghr -->|<-- struct ndmsg -->|<-- struct nlattr: NDA_DST -->|<-- NDA_LLADDR -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO -->|
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000001 0a00 0200 333300000001 0000 0800 0400 00000000 1400 0300 a2280000 32110000 32110000 01000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff000001 0a00 0200 3333ff000001 0000 0800 0400 00000000 1400 0300 0d280000 9d100000 9d100000 00000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0400 80 01 1400 0100 20010db800040ca00000000000000001 0a00 0200 84c9b26aed4b 0000 0800 0400 04000000 1400 0300 90100000 90100000 90080000 01000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff47da19 0a00 0200 3333ff47da19 0000 0800 0400 00000000 1400 0300 a1280000 31110000 31110000 01000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 912a0000 21130000 21130000 00000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 922a0000 22130000 22130000 00000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff5c2a83 0a00 0200 3333ff5c2a83 0000 0800 0400 00000000 1400 0300 391c0000 c9040000 c9040000 01000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 01000000 4000 00 02 1400 0100 00000000000000000000000000000000 0a00 0200 000000000000 0000 0800 0400 00000000 1400 0300 cd180200 5d010200 5d010200 08000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 352a0000 c5120000 c5120000 00000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 982a0000 28130000 28130000 00000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0800 80 01 1400 0100 fe8000000000000086c9b2fffe6aed4b 0a00 0200 84c9b26aed4b 0000 0800 0400 00000000 1400 0300 23000000 24000000 57000000 13000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 992a0000 29130000 29130000 01000000" +
"58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 2e2a0000 be120000 be120000 00000000" +
"44000000 1c00 0200 00000000 3e2b0000 02 00 0000 18000000 4000 00 03 0800 0100 00000000 0400 0200 0800 0400 00000000 1400 0300 75280000 05110000 05110000 22000000";
public static final byte[] RTM_GETNEIGH_RESPONSE =
HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
@Test
public void testParseRtmDelNeigh() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
assertNotNull(msg);
assertTrue(msg instanceof RtNetlinkNeighborMessage);
final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
final StructNlMsgHdr hdr = neighMsg.getHeader();
assertNotNull(hdr);
assertEquals(76, hdr.nlmsg_len);
assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type);
assertEquals(0, hdr.nlmsg_flags);
assertEquals(0, hdr.nlmsg_seq);
assertEquals(0, hdr.nlmsg_pid);
final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
assertNotNull(ndmsgHdr);
assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family);
assertEquals(21, ndmsgHdr.ndm_ifindex);
assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
final InetAddress destination = neighMsg.getDestination();
assertNotNull(destination);
assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
}
@Test
public void testParseRtmNewNeigh() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
assertNotNull(msg);
assertTrue(msg instanceof RtNetlinkNeighborMessage);
final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
final StructNlMsgHdr hdr = neighMsg.getHeader();
assertNotNull(hdr);
assertEquals(88, hdr.nlmsg_len);
assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
assertEquals(0, hdr.nlmsg_flags);
assertEquals(0, hdr.nlmsg_seq);
assertEquals(0, hdr.nlmsg_pid);
final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
assertNotNull(ndmsgHdr);
assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family);
assertEquals(21, ndmsgHdr.ndm_ifindex);
assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
final InetAddress destination = neighMsg.getDestination();
assertNotNull(destination);
assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
}
@Test
public void testParseRtmGetNeighResponse() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
int messageCount = 0;
while (byteBuffer.remaining() > 0) {
final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
assertNotNull(msg);
assertTrue(msg instanceof RtNetlinkNeighborMessage);
final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
final StructNlMsgHdr hdr = neighMsg.getHeader();
assertNotNull(hdr);
assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
assertEquals(0, hdr.nlmsg_seq);
assertEquals(11070, hdr.nlmsg_pid);
messageCount++;
}
// TODO: add more detailed spot checks.
assertEquals(14, messageCount);
}
@Test
public void testCreateRtmNewNeighMessage() {
final int seqNo = 2635;
final int ifIndex = 14;
final byte[] llAddr =
new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 };
// Hexadecimal representation of our created packet.
final String expectedNewNeighHex =
// struct nlmsghdr
"30000000" + // length = 48
"1c00" + // type = 28 (RTM_NEWNEIGH)
"0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
"4b0a0000" + // seqno
"00000000" + // pid (0 == kernel)
// struct ndmsg
"02" + // family
"00" + // pad1
"0000" + // pad2
"0e000000" + // interface index (14)
"0800" + // NUD state (0x08 == NUD_DELAY)
"00" + // flags
"00" + // type
// struct nlattr: NDA_DST
"0800" + // length = 8
"0100" + // type (1 == NDA_DST, for neighbor messages)
"7f000001" + // IPv4 address (== 127.0.0.1)
// struct nlattr: NDA_LLADDR
"0a00" + // length = 10
"0200" + // type (2 == NDA_LLADDR, for neighbor messages)
"010203040506" + // MAC Address (== 01:02:03:04:05:06)
"0000"; // padding, for 4 byte alignment
final byte[] expectedNewNeigh =
HexEncoding.decode(expectedNewNeighHex.toCharArray(), false);
final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage(
seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr);
if (!Arrays.equals(expectedNewNeigh, bytes)) {
assertEquals(expectedNewNeigh.length, bytes.length);
for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) {
assertEquals(expectedNewNeigh[i], bytes[i]);
}
}
}
}

View File

@@ -1,210 +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 android.net.shared;
import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
import static android.net.shared.Inet4AddressUtils.getImplicitNetmask;
import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL;
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTL;
import static android.net.shared.Inet4AddressUtils.netmaskToPrefixLength;
import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.fail;
import android.net.InetAddresses;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.Inet4Address;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class Inet4AddressUtilsTest {
@Test
public void testInet4AddressToIntHTL() {
assertEquals(0, inet4AddressToIntHTL(ipv4Address("0.0.0.0")));
assertEquals(0x000080ff, inet4AddressToIntHTL(ipv4Address("255.128.0.0")));
assertEquals(0x0080ff0a, inet4AddressToIntHTL(ipv4Address("10.255.128.0")));
assertEquals(0x00feff0a, inet4AddressToIntHTL(ipv4Address("10.255.254.0")));
assertEquals(0xfeffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.254")));
assertEquals(0xffffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.255")));
}
@Test
public void testIntToInet4AddressHTL() {
assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTL(0));
assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff));
assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a));
assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a));
assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0));
assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0));
}
@Test
public void testInet4AddressToIntHTH() {
assertEquals(0, inet4AddressToIntHTH(ipv4Address("0.0.0.0")));
assertEquals(0xff800000, inet4AddressToIntHTH(ipv4Address("255.128.0.0")));
assertEquals(0x0aff8000, inet4AddressToIntHTH(ipv4Address("10.255.128.0")));
assertEquals(0x0afffe00, inet4AddressToIntHTH(ipv4Address("10.255.254.0")));
assertEquals(0xc0a8fffe, inet4AddressToIntHTH(ipv4Address("192.168.255.254")));
assertEquals(0xc0a8ffff, inet4AddressToIntHTH(ipv4Address("192.168.255.255")));
}
@Test
public void testIntToInet4AddressHTH() {
assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTH(0));
assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000));
assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000));
assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00));
assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe));
assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff));
}
@Test
public void testPrefixLengthToV4NetmaskIntHTL() {
assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9));
assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17));
assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23));
assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31));
assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32));
}
@Test
public void testPrefixLengthToV4NetmaskIntHTH() {
assertEquals(0, prefixLengthToV4NetmaskIntHTH(0));
assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9));
assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17));
assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23));
assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31));
assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32));
}
@Test(expected = IllegalArgumentException.class)
public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() {
prefixLengthToV4NetmaskIntHTH(-1);
}
@Test(expected = IllegalArgumentException.class)
public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() {
prefixLengthToV4NetmaskIntHTH(33);
}
private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) {
final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength);
final int addrInt = inet4AddressToIntHTH(ipv4Address(addr));
assertEquals(ipv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt));
}
@Test
public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() {
checkAddressMasking("192.168.0.0", "192.168.128.1", 16);
checkAddressMasking("255.240.0.0", "255.255.255.255", 12);
checkAddressMasking("255.255.255.255", "255.255.255.255", 32);
checkAddressMasking("0.0.0.0", "255.255.255.255", 0);
}
@Test
public void testGetImplicitNetmask() {
assertEquals(8, getImplicitNetmask(ipv4Address("4.2.2.2")));
assertEquals(8, getImplicitNetmask(ipv4Address("10.5.6.7")));
assertEquals(16, getImplicitNetmask(ipv4Address("173.194.72.105")));
assertEquals(16, getImplicitNetmask(ipv4Address("172.23.68.145")));
assertEquals(24, getImplicitNetmask(ipv4Address("192.0.2.1")));
assertEquals(24, getImplicitNetmask(ipv4Address("192.168.5.1")));
assertEquals(32, getImplicitNetmask(ipv4Address("224.0.0.1")));
assertEquals(32, getImplicitNetmask(ipv4Address("255.6.7.8")));
}
private void assertInvalidNetworkMask(Inet4Address addr) {
try {
netmaskToPrefixLength(addr);
fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
} catch (IllegalArgumentException expected) {
}
}
@Test
public void testNetmaskToPrefixLength() {
assertEquals(0, netmaskToPrefixLength(ipv4Address("0.0.0.0")));
assertEquals(9, netmaskToPrefixLength(ipv4Address("255.128.0.0")));
assertEquals(17, netmaskToPrefixLength(ipv4Address("255.255.128.0")));
assertEquals(23, netmaskToPrefixLength(ipv4Address("255.255.254.0")));
assertEquals(31, netmaskToPrefixLength(ipv4Address("255.255.255.254")));
assertEquals(32, netmaskToPrefixLength(ipv4Address("255.255.255.255")));
assertInvalidNetworkMask(ipv4Address("0.0.0.1"));
assertInvalidNetworkMask(ipv4Address("255.255.255.253"));
assertInvalidNetworkMask(ipv4Address("255.255.0.255"));
}
@Test
public void testGetPrefixMaskAsAddress() {
assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
}
@Test
public void testGetBroadcastAddress() {
assertEquals("192.168.15.255",
getBroadcastAddress(ipv4Address("192.168.0.123"), 20).getHostAddress());
assertEquals("192.255.255.255",
getBroadcastAddress(ipv4Address("192.168.0.123"), 8).getHostAddress());
assertEquals("192.168.0.123",
getBroadcastAddress(ipv4Address("192.168.0.123"), 32).getHostAddress());
assertEquals("255.255.255.255",
getBroadcastAddress(ipv4Address("192.168.0.123"), 0).getHostAddress());
}
@Test(expected = IllegalArgumentException.class)
public void testGetBroadcastAddress_PrefixTooLarge() {
getBroadcastAddress(ipv4Address("192.168.0.123"), 33);
}
@Test(expected = IllegalArgumentException.class)
public void testGetBroadcastAddress_NegativePrefix() {
getBroadcastAddress(ipv4Address("192.168.0.123"), -1);
}
@Test(expected = IllegalArgumentException.class)
public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
getPrefixMaskAsInet4Address(33);
}
@Test(expected = IllegalArgumentException.class)
public void testGetPrefixMaskAsAddress_NegativePrefix() {
getPrefixMaskAsInet4Address(-1);
}
private Inet4Address ipv4Address(String addr) {
return (Inet4Address) InetAddresses.parseNumericAddress(addr);
}
}

View File

@@ -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 android.net.shared;
import static android.net.InetAddresses.parseNumericAddress;
import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.net.IpPrefix;
import android.net.LinkAddress;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.function.Consumer;
/**
* Tests for {@link InitialConfiguration}
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
public class InitialConfigurationTest {
private InitialConfiguration mConfig;
@Before
public void setUp() {
mConfig = new InitialConfiguration();
mConfig.ipAddresses.addAll(Arrays.asList(
new LinkAddress(parseNumericAddress("192.168.45.45"), 16),
new LinkAddress(parseNumericAddress("2001:db8::45"), 33)));
mConfig.directlyConnectedRoutes.addAll(Arrays.asList(
new IpPrefix(parseNumericAddress("192.168.46.46"), 17),
new IpPrefix(parseNumericAddress("2001:db8::46"), 34)));
mConfig.dnsServers.addAll(Arrays.asList(
parseNumericAddress("192.168.47.47"),
parseNumericAddress("2001:db8::47")));
// Any added InitialConfiguration field must be included in equals() to be tested properly
assertFieldCountEquals(3, InitialConfiguration.class);
}
@Test
public void testParcelUnparcelInitialConfiguration() {
final InitialConfiguration unparceled =
InitialConfiguration.fromStableParcelable(mConfig.toStableParcelable());
assertEquals(mConfig, unparceled);
}
@Test
public void testEquals() {
assertEquals(mConfig, InitialConfiguration.copy(mConfig));
assertNotEqualsAfterChange(c -> c.ipAddresses.add(
new LinkAddress(parseNumericAddress("192.168.47.47"), 24)));
assertNotEqualsAfterChange(c -> c.directlyConnectedRoutes.add(
new IpPrefix(parseNumericAddress("192.168.46.46"), 32)));
assertNotEqualsAfterChange(c -> c.dnsServers.add(parseNumericAddress("2001:db8::49")));
assertFieldCountEquals(3, InitialConfiguration.class);
}
private void assertNotEqualsAfterChange(Consumer<InitialConfiguration> mutator) {
final InitialConfiguration newConfig = InitialConfiguration.copy(mConfig);
mutator.accept(newConfig);
assertNotEquals(mConfig, newConfig);
}
}

View File

@@ -1,115 +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 android.net.shared;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable;
import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
import android.net.DhcpResults;
import android.net.LinkAddress;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.Inet4Address;
/**
* Tests for {@link IpConfigurationParcelableUtil}.
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpConfigurationParcelableUtilTest {
private DhcpResults mDhcpResults;
@Before
public void setUp() {
mDhcpResults = new DhcpResults();
mDhcpResults.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64);
mDhcpResults.gateway = parseNumericAddress("192.168.42.42");
mDhcpResults.dnsServers.add(parseNumericAddress("2001:db8::43"));
mDhcpResults.dnsServers.add(parseNumericAddress("192.168.43.43"));
mDhcpResults.domains = "example.com";
mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44");
mDhcpResults.vendorInfo = "TEST_VENDOR_INFO";
mDhcpResults.leaseDuration = 3600;
mDhcpResults.serverHostName = "dhcp.example.com";
mDhcpResults.mtu = 1450;
// Any added DhcpResults field must be included in equals() to be tested properly
assertFieldCountEquals(9, DhcpResults.class);
}
@Test
public void testParcelUnparcelDhcpResults() {
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullIpAddress() {
mDhcpResults.ipAddress = null;
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullGateway() {
mDhcpResults.gateway = null;
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullDomains() {
mDhcpResults.domains = null;
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_EmptyDomains() {
mDhcpResults.domains = "";
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullServerAddress() {
mDhcpResults.serverAddress = null;
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullVendorInfo() {
mDhcpResults.vendorInfo = null;
doDhcpResultsParcelUnparcelTest();
}
@Test
public void testParcelUnparcelDhcpResults_NullServerHostName() {
mDhcpResults.serverHostName = null;
doDhcpResultsParcelUnparcelTest();
}
private void doDhcpResultsParcelUnparcelTest() {
final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults));
assertEquals(mDhcpResults, unparceled);
}
}

View File

@@ -1,139 +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 android.net.shared;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.net.LinkAddress;
import android.net.Network;
import android.net.StaticIpConfiguration;
import android.net.apf.ApfCapabilities;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.function.Consumer;
/**
* Tests for {@link ProvisioningConfiguration}.
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ProvisioningConfigurationTest {
private ProvisioningConfiguration mConfig;
@Before
public void setUp() {
mConfig = new ProvisioningConfiguration();
mConfig.mEnableIPv4 = true;
mConfig.mEnableIPv6 = true;
mConfig.mUsingMultinetworkPolicyTracker = true;
mConfig.mUsingIpReachabilityMonitor = true;
mConfig.mRequestedPreDhcpActionMs = 42;
mConfig.mInitialConfig = new InitialConfiguration();
mConfig.mInitialConfig.ipAddresses.add(
new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
mConfig.mStaticIpConfig = new StaticIpConfiguration();
mConfig.mStaticIpConfig.ipAddress =
new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
// Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3);
mConfig.mProvisioningTimeoutMs = 4200;
mConfig.mIPv6AddrGenMode = 123;
mConfig.mNetwork = new Network(321);
mConfig.mDisplayName = "test_config";
// Any added field must be included in equals() to be tested properly
assertFieldCountEquals(12, ProvisioningConfiguration.class);
}
@Test
public void testParcelUnparcel() {
doParcelUnparcelTest();
}
@Test
public void testParcelUnparcel_NullInitialConfiguration() {
mConfig.mInitialConfig = null;
doParcelUnparcelTest();
}
@Test
public void testParcelUnparcel_NullStaticConfiguration() {
mConfig.mStaticIpConfig = null;
doParcelUnparcelTest();
}
@Test
public void testParcelUnparcel_NullApfCapabilities() {
mConfig.mApfCapabilities = null;
doParcelUnparcelTest();
}
@Test
public void testParcelUnparcel_NullNetwork() {
mConfig.mNetwork = null;
doParcelUnparcelTest();
}
private void doParcelUnparcelTest() {
final ProvisioningConfiguration unparceled =
fromStableParcelable(mConfig.toStableParcelable());
assertEquals(mConfig, unparceled);
}
@Test
public void testEquals() {
assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false);
assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false);
assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add(
new LinkAddress(parseNumericAddress("192.168.47.47"), 16)));
assertNotEqualsAfterChange(c -> c.mInitialConfig = null);
assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress =
new LinkAddress(parseNumericAddress("2001:db8::47"), 64));
assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null);
assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6));
assertNotEqualsAfterChange(c -> c.mApfCapabilities = null);
assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++);
assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++);
assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123));
assertNotEqualsAfterChange(c -> c.mNetwork = null);
assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
assertNotEqualsAfterChange(c -> c.mDisplayName = null);
assertFieldCountEquals(12, ProvisioningConfiguration.class);
}
private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {
final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig);
mutator.accept(newConfig);
assertNotEquals(mConfig, newConfig);
}
}

View File

@@ -1,52 +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 android.net.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class InterfaceParamsTest {
@Test
public void testNullInterfaceReturnsNull() {
assertNull(InterfaceParams.getByName(null));
}
@Test
public void testNonExistentInterfaceReturnsNull() {
assertNull(InterfaceParams.getByName("doesnotexist0"));
}
@Test
public void testLoopback() {
final InterfaceParams ifParams = InterfaceParams.getByName("lo");
assertNotNull(ifParams);
assertEquals("lo", ifParams.name);
assertTrue(ifParams.index > 0);
assertNotNull(ifParams.macAddr);
assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
}
}

View File

@@ -1,95 +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 android.net.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SharedLogTest {
private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
private static final String TIMESTAMP = "HH:MM:SS";
@Test
public void testBasicOperation() {
final SharedLog logTop = new SharedLog("top");
logTop.mark("first post!");
final SharedLog logLevel2a = logTop.forSubComponent("twoA");
final SharedLog logLevel2b = logTop.forSubComponent("twoB");
logLevel2b.e("2b or not 2b");
logLevel2b.e("No exception", null);
logLevel2b.e("Wait, here's one", new Exception("Test"));
logLevel2a.w("second post?");
final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
logTop.log("still logging");
logLevel3.log("3 >> 2");
logLevel2a.mark("ok: last post");
final String[] expected = {
" - MARK first post!",
" - [twoB] ERROR 2b or not 2b",
" - [twoB] ERROR No exception",
// No stacktrace in shared log, only in logcat
" - [twoB] ERROR Wait, here's one: Test",
" - [twoA] WARN second post?",
" - still logging",
" - [twoA.three] 3 >> 2",
" - [twoA] MARK ok: last post",
};
// Verify the logs are all there and in the correct order.
verifyLogLines(expected, logTop);
// In fact, because they all share the same underlying LocalLog,
// every subcomponent SharedLog's dump() is identical.
verifyLogLines(expected, logLevel2a);
verifyLogLines(expected, logLevel2b);
verifyLogLines(expected, logLevel3);
}
private static void verifyLogLines(String[] expected, SharedLog log) {
final ByteArrayOutputStream ostream = new ByteArrayOutputStream();
final PrintWriter pw = new PrintWriter(ostream, true);
log.dump(null, pw, null);
final String dumpOutput = ostream.toString();
assertTrue(dumpOutput != null);
assertTrue(!"".equals(dumpOutput));
final String[] lines = dumpOutput.split("\n");
assertEquals(expected.length, lines.length);
for (int i = 0; i < expected.length; i++) {
String got = lines[i];
String want = expected[i];
assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
}
}
}