summaryrefslogtreecommitdiff
path: root/common/device
diff options
context:
space:
mode:
Diffstat (limited to 'common/device')
-rw-r--r--common/device/com/android/net/module/util/netlink/ConntrackMessage.java4
-rw-r--r--common/device/com/android/net/module/util/netlink/InetDiagMessage.java7
-rw-r--r--common/device/com/android/net/module/util/netlink/NdOption.java9
-rw-r--r--common/device/com/android/net/module/util/netlink/NduseroptMessage.java29
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java9
-rw-r--r--common/device/com/android/net/module/util/netlink/NetlinkMessage.java8
-rw-r--r--common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java9
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdOptPref64.java2
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java134
-rw-r--r--common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java3
-rw-r--r--common/device/com/android/net/module/util/structs/RdnssOption.java3
11 files changed, 191 insertions, 26 deletions
diff --git a/common/device/com/android/net/module/util/netlink/ConntrackMessage.java b/common/device/com/android/net/module/util/netlink/ConntrackMessage.java
index 1763c04b..dfed3efb 100644
--- a/common/device/com/android/net/module/util/netlink/ConntrackMessage.java
+++ b/common/device/com/android/net/module/util/netlink/ConntrackMessage.java
@@ -228,7 +228,9 @@ public class ConntrackMessage extends NetlinkMessage {
* @return the parsed netfilter conntrack message, or {@code null} if the netfilter conntrack
* message could not be parsed successfully (for example, if it was truncated).
*/
- public static ConntrackMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
+ @Nullable
+ public static ConntrackMessage parse(@NonNull StructNlMsgHdr header,
+ @NonNull ByteBuffer byteBuffer) {
// Just build the netlink header and netfilter header for now and pretend the whole message
// was consumed.
// TODO: Parse the conntrack attributes.
diff --git a/common/device/com/android/net/module/util/netlink/InetDiagMessage.java b/common/device/com/android/net/module/util/netlink/InetDiagMessage.java
index 7b200e75..a8aef7b4 100644
--- a/common/device/com/android/net/module/util/netlink/InetDiagMessage.java
+++ b/common/device/com/android/net/module/util/netlink/InetDiagMessage.java
@@ -31,6 +31,7 @@ import android.net.util.SocketUtils;
import android.system.ErrnoException;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.FileDescriptor;
@@ -107,7 +108,7 @@ public class InetDiagMessage extends NetlinkMessage {
public StructInetDiagMsg mStructInetDiagMsg;
- private InetDiagMessage(StructNlMsgHdr header) {
+ private InetDiagMessage(@NonNull StructNlMsgHdr header) {
super(header);
mStructInetDiagMsg = new StructInetDiagMsg();
}
@@ -115,7 +116,9 @@ public class InetDiagMessage extends NetlinkMessage {
/**
* Parse an inet_diag_req_v2 message from buffer.
*/
- public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
+ @NonNull
+ public static InetDiagMessage parse(@NonNull StructNlMsgHdr header,
+ @NonNull ByteBuffer byteBuffer) {
final InetDiagMessage msg = new InetDiagMessage(header);
msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
return msg;
diff --git a/common/device/com/android/net/module/util/netlink/NdOption.java b/common/device/com/android/net/module/util/netlink/NdOption.java
index 50a34966..defc88a7 100644
--- a/common/device/com/android/net/module/util/netlink/NdOption.java
+++ b/common/device/com/android/net/module/util/netlink/NdOption.java
@@ -16,6 +16,8 @@
package com.android.net.module.util.netlink;
+import androidx.annotation.NonNull;
+
import java.nio.ByteBuffer;
/**
@@ -50,8 +52,8 @@ public class NdOption {
* @param buf the buffer to parse.
* @return a subclass of {@link NdOption}, or {@code null} for an unknown or malformed option.
*/
- public static NdOption parse(ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
+ public static NdOption parse(@NonNull ByteBuffer buf) {
+ if (buf.remaining() < STRUCT_SIZE) return null;
// Peek the type without advancing the buffer.
byte type = buf.get(buf.position());
@@ -62,6 +64,9 @@ public class NdOption {
case StructNdOptPref64.TYPE:
return StructNdOptPref64.parse(buf);
+ case StructNdOptRdnss.TYPE:
+ return StructNdOptRdnss.parse(buf);
+
default:
int newPosition = Math.min(buf.limit(), buf.position() + length * 8);
buf.position(newPosition);
diff --git a/common/device/com/android/net/module/util/netlink/NduseroptMessage.java b/common/device/com/android/net/module/util/netlink/NduseroptMessage.java
index 4e3b9f2d..bdf574db 100644
--- a/common/device/com/android/net/module/util/netlink/NduseroptMessage.java
+++ b/common/device/com/android/net/module/util/netlink/NduseroptMessage.java
@@ -19,6 +19,7 @@ package com.android.net.module.util.netlink;
import static android.system.OsConstants.AF_INET6;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -56,6 +57,7 @@ public class NduseroptMessage extends NetlinkMessage {
* But if it does, we can simply update this code, since userspace is typically newer than the
* kernel.
*/
+ @Nullable
public final NdOption option;
/** The IP address that sent the packet containing the option. */
@@ -80,22 +82,26 @@ public class NduseroptMessage extends NetlinkMessage {
// Ensure we don't read past opts_len even if the option length is invalid.
// Note that this check is not really necessary since if the option length is not valid,
// this struct won't be very useful to the caller.
+ //
+ // It's safer to pass the slice of original ByteBuffer to just parse the ND option field,
+ // although parsing ND option might throw exception or return null, it won't break the
+ // original ByteBuffer position.
buf.order(ByteOrder.BIG_ENDIAN);
- int oldLimit = buf.limit();
- buf.limit(start + STRUCT_SIZE + opts_len);
try {
- option = NdOption.parse(buf);
+ final ByteBuffer slice = buf.slice();
+ slice.limit(opts_len);
+ option = NdOption.parse(slice);
} finally {
- buf.limit(oldLimit);
+ // Advance buffer position according to opts_len in the header. ND option length might
+ // be incorrect in the malformed packet.
+ int newPosition = start + STRUCT_SIZE + opts_len;
+ if (newPosition >= buf.limit()) {
+ throw new IllegalArgumentException("ND option extends past end of buffer");
+ }
+ buf.position(newPosition);
}
- // The source address.
- int newPosition = start + STRUCT_SIZE + opts_len;
- if (newPosition >= buf.limit()) {
- throw new IllegalArgumentException("ND options extend past end of buffer");
- }
- buf.position(newPosition);
-
+ // The source address attribute.
StructNlAttr nla = StructNlAttr.parse(buf);
if (nla == null || nla.nla_type != NDUSEROPT_SRCADDR || nla.nla_value == null) {
throw new IllegalArgumentException("Invalid source address in ND useropt");
@@ -117,6 +123,7 @@ public class NduseroptMessage extends NetlinkMessage {
* @return the parsed option, or {@code null} if the option could not be parsed successfully
* (for example, if it was truncated, or if the prefix length code was wrong).
*/
+ @Nullable
public static NduseroptMessage parse(@NonNull StructNlMsgHdr header, @NonNull ByteBuffer buf) {
if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
ByteOrder oldOrder = buf.order();
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java b/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java
index d9fb09e6..48314323 100644
--- a/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java
+++ b/common/device/com/android/net/module/util/netlink/NetlinkErrorMessage.java
@@ -16,6 +16,9 @@
package com.android.net.module.util.netlink;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.nio.ByteBuffer;
/**
@@ -32,7 +35,9 @@ public class NetlinkErrorMessage extends NetlinkMessage {
* @return the parsed netlink error message, or {@code null} if the netlink error message
* could not be parsed successfully (for example, if it was truncated).
*/
- public static NetlinkErrorMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
+ @Nullable
+ public static NetlinkErrorMessage parse(@NonNull StructNlMsgHdr header,
+ @NonNull ByteBuffer byteBuffer) {
final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header);
errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer);
@@ -45,7 +50,7 @@ public class NetlinkErrorMessage extends NetlinkMessage {
private StructNlMsgErr mNlMsgErr;
- NetlinkErrorMessage(StructNlMsgHdr header) {
+ NetlinkErrorMessage(@NonNull StructNlMsgHdr header) {
super(header);
mNlMsgErr = null;
}
diff --git a/common/device/com/android/net/module/util/netlink/NetlinkMessage.java b/common/device/com/android/net/module/util/netlink/NetlinkMessage.java
index f425384f..723d6823 100644
--- a/common/device/com/android/net/module/util/netlink/NetlinkMessage.java
+++ b/common/device/com/android/net/module/util/netlink/NetlinkMessage.java
@@ -79,12 +79,14 @@ public class NetlinkMessage {
return null;
}
- protected StructNlMsgHdr mHeader;
+ @NonNull
+ protected final StructNlMsgHdr mHeader;
- public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
+ public NetlinkMessage(@NonNull StructNlMsgHdr nlmsghdr) {
mHeader = nlmsghdr;
}
+ @NonNull
public StructNlMsgHdr getHeader() {
return mHeader;
}
@@ -96,7 +98,7 @@ public class NetlinkMessage {
// a string by StructNlMsgHdr#toString and just keep as an integer. The specific message
// which inherits NetlinkMessage could override NetlinkMessage#toString and provide the
// specific netlink family to StructNlMsgHdr#toString.
- return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
+ return "NetlinkMessage{" + mHeader.toString() + "}";
}
@NonNull
diff --git a/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java b/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java
index a75ef8dd..4a090151 100644
--- a/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java
+++ b/common/device/com/android/net/module/util/netlink/RtNetlinkNeighborMessage.java
@@ -23,6 +23,9 @@ import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import android.system.OsConstants;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
@@ -53,7 +56,9 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage {
* @param header netlink message header.
* @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
*/
- public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
+ @Nullable
+ public static RtNetlinkNeighborMessage parse(@NonNull StructNlMsgHdr header,
+ @NonNull ByteBuffer byteBuffer) {
final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header);
neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer);
@@ -154,7 +159,7 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage {
private int mNumProbes;
private StructNdaCacheInfo mCacheInfo;
- private RtNetlinkNeighborMessage(StructNlMsgHdr header) {
+ private RtNetlinkNeighborMessage(@NonNull StructNlMsgHdr header) {
super(header);
mNdmsg = null;
mDestination = null;
diff --git a/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java b/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java
index bde69831..f6b2e0e5 100644
--- a/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java
+++ b/common/device/com/android/net/module/util/netlink/StructNdOptPref64.java
@@ -135,7 +135,7 @@ public class StructNdOptPref64 extends NdOption {
* (for example, if it was truncated, or if the prefix length code was wrong).
*/
public static StructNdOptPref64 parse(@NonNull ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
+ if (buf.remaining() < STRUCT_SIZE) return null;
try {
return new StructNdOptPref64(buf);
} catch (IllegalArgumentException e) {
diff --git a/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java b/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java
new file mode 100644
index 00000000..6dee0c49
--- /dev/null
+++ b/common/device/com/android/net/module/util/netlink/StructNdOptRdnss.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util.netlink;
+
+import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.structs.RdnssOption;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+/**
+ * The Recursive DNS Server Option. RFC 8106.
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Length | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Lifetime |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * : Addresses of IPv6 Recursive DNS Servers :
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+public class StructNdOptRdnss extends NdOption {
+ private static final String TAG = StructNdOptRdnss.class.getSimpleName();
+ public static final int TYPE = 25;
+ // Length in 8-byte units, only if one IPv6 address included.
+ public static final byte MIN_OPTION_LEN = 3;
+
+ public final RdnssOption header;
+ @NonNull
+ public final Inet6Address[] servers;
+
+ public StructNdOptRdnss(@NonNull final Inet6Address[] servers, long lifetime) {
+ super((byte) TYPE, servers.length * 2 + 1);
+
+ Objects.requireNonNull(servers, "Recursive DNS Servers address array must not be null");
+ if (servers.length == 0) {
+ throw new IllegalArgumentException("DNS server address array must not be empty");
+ }
+
+ this.header = new RdnssOption((byte) TYPE, (byte) (servers.length * 2 + 1),
+ (short) 0 /* reserved */, lifetime);
+ this.servers = servers.clone();
+ }
+
+ /**
+ * Parses an RDNSS option from a {@link ByteBuffer}.
+ *
+ * @param buf The buffer from which to parse the option. The buffer's byte order must be
+ * {@link java.nio.ByteOrder#BIG_ENDIAN}.
+ * @return the parsed option, or {@code null} if the option could not be parsed successfully.
+ */
+ public static StructNdOptRdnss parse(@NonNull ByteBuffer buf) {
+ if (buf == null || buf.remaining() < MIN_OPTION_LEN * 8) return null;
+ try {
+ final RdnssOption header = Struct.parse(RdnssOption.class, buf);
+ if (header.type != TYPE) {
+ throw new IllegalArgumentException("Invalid type " + header.type);
+ }
+ if (header.length < MIN_OPTION_LEN || (header.length % 2 == 0)) {
+ throw new IllegalArgumentException("Invalid length " + header.length);
+ }
+
+ final int numOfDnses = (header.length - 1) / 2;
+ final Inet6Address[] servers = new Inet6Address[numOfDnses];
+ for (int i = 0; i < numOfDnses; i++) {
+ byte[] rawAddress = new byte[IPV6_ADDR_LEN];
+ buf.get(rawAddress);
+ servers[i] = (Inet6Address) InetAddress.getByAddress(rawAddress);
+ }
+ return new StructNdOptRdnss(servers, header.lifetime);
+ } catch (IllegalArgumentException | BufferUnderflowException | UnknownHostException e) {
+ // Not great, but better than throwing an exception that might crash the caller.
+ // Convention in this package is that null indicates that the option was truncated
+ // or malformed, so callers must already handle it.
+ Log.d(TAG, "Invalid RDNSS option: " + e);
+ return null;
+ }
+ }
+
+ protected void writeToByteBuffer(ByteBuffer buf) {
+ header.writeToByteBuffer(buf);
+ for (int i = 0; i < servers.length; i++) {
+ buf.put(servers[i].getAddress());
+ }
+ }
+
+ /** Outputs the wire format of the option to a new big-endian ByteBuffer. */
+ public ByteBuffer toByteBuffer() {
+ final ByteBuffer buf = ByteBuffer.allocate(Struct.getSize(RdnssOption.class)
+ + servers.length * IPV6_ADDR_LEN);
+ writeToByteBuffer(buf);
+ buf.flip();
+ return buf;
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ final StringJoiner sj = new StringJoiner(",", "[", "]");
+ for (int i = 0; i < servers.length; i++) {
+ sj.add(servers[i].getHostAddress());
+ }
+ return String.format("NdOptRdnss(%s,servers:%s)", header.toString(), sj.toString());
+ }
+}
diff --git a/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java b/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java
index ddf1562f..9567cce2 100644
--- a/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java
+++ b/common/device/com/android/net/module/util/netlink/StructNlMsgHdr.java
@@ -93,7 +93,8 @@ public class StructNlMsgHdr {
/**
* Parse netlink message header from buffer.
*/
- public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
+ @Nullable
+ public static StructNlMsgHdr parse(@NonNull ByteBuffer byteBuffer) {
if (!hasAvailableSpace(byteBuffer)) return null;
// The ByteOrder must have already been set by the caller. In most
diff --git a/common/device/com/android/net/module/util/structs/RdnssOption.java b/common/device/com/android/net/module/util/structs/RdnssOption.java
index b7c2b0c1..4a5bd7e9 100644
--- a/common/device/com/android/net/module/util/structs/RdnssOption.java
+++ b/common/device/com/android/net/module/util/structs/RdnssOption.java
@@ -53,7 +53,8 @@ public class RdnssOption extends Struct {
@Field(order = 3, type = Type.U32)
public final long lifetime;
- RdnssOption(final byte type, final byte length, final short reserved, final long lifetime) {
+ public RdnssOption(final byte type, final byte length, final short reserved,
+ final long lifetime) {
this.type = type;
this.length = length;
this.reserved = reserved;