Add tests for IpReachabilityMonitor
The first tests just verify that provisioning is lost if all IPv4/6 DNS
servers or gateways are lost.
Test: atest NetworkStackTests
Bug: 152819907
Merged-In: I8da6a8f4f237ce963c0a1610432d310160fd3f20
Change-Id: I8da6a8f4f237ce963c0a1610432d310160fd3f20
diff --git a/common/moduleutils/src/android/net/util/FdEventsReader.java b/common/moduleutils/src/android/net/util/FdEventsReader.java
index 5a1154f..ebd6c53 100644
--- a/common/moduleutils/src/android/net/util/FdEventsReader.java
+++ b/common/moduleutils/src/android/net/util/FdEventsReader.java
@@ -27,6 +27,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -92,6 +93,12 @@
mBuffer = buffer;
}
+ @VisibleForTesting
+ @NonNull
+ protected MessageQueue getMessageQueue() {
+ return mQueue;
+ }
+
/** Start this FdEventsReader. */
public boolean start() {
if (!onCorrectThread()) {
@@ -185,7 +192,7 @@
if (mFd == null) return false;
- mQueue.addOnFileDescriptorEventListener(
+ getMessageQueue().addOnFileDescriptorEventListener(
mFd,
FD_EVENTS,
(fd, events) -> {
@@ -247,7 +254,7 @@
private void unregisterAndDestroyFd() {
if (mFd == null) return;
- mQueue.removeOnFileDescriptorEventListener(mFd);
+ getMessageQueue().removeOnFileDescriptorEventListener(mFd);
closeFd(mFd);
mFd = null;
onStop();
diff --git a/src/android/net/ip/IpReachabilityMonitor.java b/src/android/net/ip/IpReachabilityMonitor.java
index 17b1f3c..e1d4548 100644
--- a/src/android/net/ip/IpReachabilityMonitor.java
+++ b/src/android/net/ip/IpReachabilityMonitor.java
@@ -27,6 +27,7 @@
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.net.ip.IpNeighborMonitor.NeighborEvent;
+import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
import android.net.netlink.StructNdMsg;
@@ -154,11 +155,12 @@
}
/**
- * Encapsulates IpReachabilityMonitor depencencies on systems that hinder unit testing.
+ * Encapsulates IpReachabilityMonitor dependencies on systems that hinder unit testing.
* TODO: consider also wrapping MultinetworkPolicyTracker in this interface.
*/
interface Dependencies {
void acquireWakeLock(long durationMs);
+ IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb);
static Dependencies makeDefault(Context context, String iface) {
final String lockName = TAG + "." + iface;
@@ -169,6 +171,11 @@
public void acquireWakeLock(long durationMs) {
lock.acquire(durationMs);
}
+
+ public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log,
+ NeighborEventConsumer cb) {
+ return new IpNeighborMonitor(h, log, cb);
+ }
};
}
}
@@ -223,7 +230,7 @@
}
setNeighbourParametersForSteadyState();
- mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
+ mIpNeighborMonitor = mDependencies.makeIpNeighborMonitor(h, mLog,
(NeighborEvent event) -> {
if (mInterfaceParams.index != event.ifindex) return;
if (!mNeighborWatchList.containsKey(event.ip)) return;
diff --git a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
deleted file mode 100644
index ba3b306..0000000
--- a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
+++ /dev/null
@@ -1,70 +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 static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.INetd;
-import android.net.util.InterfaceParams;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.Looper;
-
-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.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for IpReachabilityMonitor.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpReachabilityMonitorTest {
- @Mock IpReachabilityMonitor.Callback mCallback;
- @Mock IpReachabilityMonitor.Dependencies mDependencies;
- @Mock SharedLog mLog;
- @Mock Context mContext;
- @Mock INetd mNetd;
- Handler mHandler;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- when(mLog.forSubComponent(anyString())).thenReturn(mLog);
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- IpReachabilityMonitor makeMonitor() {
- final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
- return new IpReachabilityMonitor(
- mContext, ifParams, mHandler, mLog, mCallback, false, mDependencies, mNetd);
- }
-
- @Test
- public void testNothing() {
- // make sure the unit test runs in the same thread with main looper.
- // Otherwise, throwing IllegalStateException would cause test fails.
- mHandler.post(() -> makeMonitor());
- }
-}
diff --git a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
new file mode 100644
index 0000000..ac50651
--- /dev/null
+++ b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
@@ -0,0 +1,247 @@
+/*
+ * 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.content.Context
+import android.net.INetd
+import android.net.InetAddresses.parseNumericAddress
+import android.net.IpPrefix
+import android.net.LinkAddress
+import android.net.LinkProperties
+import android.net.RouteInfo
+import android.net.netlink.StructNdMsg.NUD_FAILED
+import android.net.netlink.StructNdMsg.NUD_STALE
+import android.net.netlink.makeNewNeighMessage
+import android.net.util.InterfaceParams
+import android.net.util.SharedLog
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.MessageQueue
+import android.os.MessageQueue.OnFileDescriptorEventListener
+import android.system.ErrnoException
+import android.system.OsConstants.EAGAIN
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.timeout
+import org.mockito.Mockito.verify
+import java.io.FileDescriptor
+import java.net.Inet4Address
+import java.net.Inet6Address
+import java.net.InetAddress
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ConcurrentLinkedQueue
+import java.util.concurrent.TimeUnit
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+private const val TEST_TIMEOUT_MS = 10_000L
+
+private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address
+private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address
+
+private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24")
+private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64")
+
+// DNSes inside IP prefix
+private val TEST_IPV4_DNS = parseNumericAddress("192.168.222.1") as Inet4Address
+private val TEST_IPV6_DNS = parseNumericAddress("2001:db8::321") as Inet6Address
+
+private val TEST_IFACE = InterfaceParams("fake0", 21, null)
+private val TEST_LINK_PROPERTIES = LinkProperties().apply {
+ interfaceName = TEST_IFACE.name
+ addLinkAddress(TEST_IPV4_LINKADDR)
+ addLinkAddress(TEST_IPV6_LINKADDR)
+
+ // Add on link routes
+ addRoute(RouteInfo(TEST_IPV4_LINKADDR, null /* gateway */, TEST_IFACE.name))
+ addRoute(RouteInfo(TEST_IPV6_LINKADDR, null /* gateway */, TEST_IFACE.name))
+
+ // Add default routes
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY))
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_GATEWAY))
+
+ addDnsServer(TEST_IPV4_DNS)
+ addDnsServer(TEST_IPV6_DNS)
+}
+
+/**
+ * Tests for IpReachabilityMonitor.
+ */
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpReachabilityMonitorTest {
+ private val callback = mock(IpReachabilityMonitor.Callback::class.java)
+ private val dependencies = mock(IpReachabilityMonitor.Dependencies::class.java)
+ private val log = mock(SharedLog::class.java)
+ private val context = mock(Context::class.java)
+ private val netd = mock(INetd::class.java)
+ private val fd = mock(FileDescriptor::class.java)
+
+ private val handlerThread = HandlerThread(IpReachabilityMonitorTest::class.simpleName)
+ private val handler by lazy { Handler(handlerThread.looper) }
+
+ private lateinit var reachabilityMonitor: IpReachabilityMonitor
+ private lateinit var neighborMonitor: TestIpNeighborMonitor
+
+ /**
+ * A version of [IpNeighborMonitor] that overrides packet reading from a socket, and instead
+ * allows the test to enqueue test packets via [enqueuePacket].
+ */
+ private class TestIpNeighborMonitor(
+ handler: Handler,
+ log: SharedLog,
+ cb: NeighborEventConsumer,
+ private val fd: FileDescriptor
+ ) : IpNeighborMonitor(handler, log, cb) {
+
+ private val pendingPackets = ConcurrentLinkedQueue<ByteArray>()
+ val msgQueue = mock(MessageQueue::class.java)
+
+ private var eventListener: OnFileDescriptorEventListener? = null
+
+ override fun createFd() = fd
+ override fun getMessageQueue() = msgQueue
+
+ fun enqueuePacket(packet: ByteArray) {
+ val listener = eventListener ?: fail("IpNeighborMonitor was not yet started")
+ pendingPackets.add(packet)
+ handler.post {
+ listener.onFileDescriptorEvents(fd, OnFileDescriptorEventListener.EVENT_INPUT)
+ }
+ }
+
+ override fun readPacket(fd: FileDescriptor, packetBuffer: ByteArray): Int {
+ val packet = pendingPackets.poll() ?: throw ErrnoException("No pending packet", EAGAIN)
+ if (packet.size > packetBuffer.size) {
+ fail("Buffer (${packetBuffer.size}) is too small for packet (${packet.size})")
+ }
+ System.arraycopy(packet, 0, packetBuffer, 0, packet.size)
+ return packet.size
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ // Find the file descriptor listener that was registered on the instrumented queue
+ val captor = ArgumentCaptor.forClass(OnFileDescriptorEventListener::class.java)
+ verify(msgQueue).addOnFileDescriptorEventListener(
+ eq(fd), anyInt(), captor.capture())
+ eventListener = captor.value
+ }
+ }
+
+ @Before
+ fun setUp() {
+ doReturn(log).`when`(log).forSubComponent(anyString())
+ doReturn(true).`when`(fd).valid()
+ handlerThread.start()
+
+ doAnswer { inv ->
+ val handler = inv.getArgument<Handler>(0)
+ val log = inv.getArgument<SharedLog>(1)
+ val cb = inv.getArgument<IpNeighborMonitor.NeighborEventConsumer>(2)
+ neighborMonitor = TestIpNeighborMonitor(handler, log, cb, fd)
+ neighborMonitor
+ }.`when`(dependencies).makeIpNeighborMonitor(any(), any(), any())
+
+ val monitorFuture = CompletableFuture<IpReachabilityMonitor>()
+ // IpReachabilityMonitor needs to be started from the handler thread
+ handler.post {
+ monitorFuture.complete(IpReachabilityMonitor(
+ context,
+ TEST_IFACE,
+ handler,
+ log,
+ callback,
+ false /* useMultinetworkPolicyTracker */,
+ dependencies,
+ netd))
+ }
+ reachabilityMonitor = monitorFuture.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+ assertTrue(::neighborMonitor.isInitialized,
+ "IpReachabilityMonitor did not call makeIpNeighborMonitor")
+ }
+
+ @After
+ fun tearDown() {
+ doReturn(false).`when`(fd).valid()
+ handlerThread.quitSafely()
+ }
+
+ // TODO: fix this bug
+ @Test
+ fun testLoseProvisioning_CrashIfFirstProbeIsFailed() {
+ reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES)
+
+ doAnswer {
+ // Set the fd as invalid when the event listener is removed, to avoid a crash when the
+ // reader tries to close the mock fd.
+ // This does not exactly reflect behavior on close, but this test is only demonstrating
+ // a bug that causes the close, and it will be removed when the bug fixed.
+ doReturn(false).`when`(fd).valid()
+ }.`when`(neighborMonitor.msgQueue).removeOnFileDescriptorEventListener(any())
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_DNS, NUD_FAILED))
+ verify(neighborMonitor.msgQueue, timeout(TEST_TIMEOUT_MS))
+ .removeOnFileDescriptorEventListener(any())
+ verify(callback, never()).notifyLost(eq(TEST_IPV4_DNS), anyString())
+ }
+
+ private fun runLoseProvisioningTest(lostNeighbor: InetAddress) {
+ reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES)
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_GATEWAY, NUD_STALE))
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_GATEWAY, NUD_STALE))
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_DNS, NUD_STALE))
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_DNS, NUD_STALE))
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(lostNeighbor, NUD_FAILED))
+ verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(lostNeighbor), anyString())
+ }
+
+ @Test
+ fun testLoseProvisioning_Ipv4DnsLost() {
+ runLoseProvisioningTest(TEST_IPV4_DNS)
+ }
+
+ @Test
+ fun testLoseProvisioning_Ipv6DnsLost() {
+ runLoseProvisioningTest(TEST_IPV6_DNS)
+ }
+
+ @Test
+ fun testLoseProvisioning_Ipv4GatewayLost() {
+ runLoseProvisioningTest(TEST_IPV4_GATEWAY)
+ }
+
+ @Test
+ fun testLoseProvisioning_Ipv6GatewayLost() {
+ runLoseProvisioningTest(TEST_IPV6_GATEWAY)
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt
new file mode 100644
index 0000000..6655e96
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.netlink
+
+import android.net.netlink.NetlinkConstants.RTM_DELNEIGH
+import android.net.netlink.NetlinkConstants.RTM_NEWNEIGH
+import libcore.util.HexEncoding
+import libcore.util.HexEncoding.encodeToString
+import java.net.Inet6Address
+import java.net.InetAddress
+
+/**
+ * Make a RTM_NEWNEIGH netlink message.
+ */
+fun makeNewNeighMessage(
+ neighAddr: InetAddress,
+ nudState: Short
+) = makeNeighborMessage(
+ neighAddr = neighAddr,
+ type = RTM_NEWNEIGH,
+ nudState = nudState
+)
+
+/**
+ * Make a RTM_DELNEIGH netlink message.
+ */
+fun makeDelNeighMessage(
+ neighAddr: InetAddress,
+ nudState: Short
+) = makeNeighborMessage(
+ neighAddr = neighAddr,
+ type = RTM_DELNEIGH,
+ nudState = nudState
+)
+
+private fun makeNeighborMessage(
+ neighAddr: InetAddress,
+ type: Short,
+ nudState: Short
+) = HexEncoding.decode(
+ /* ktlint-disable indent */
+ // -- struct nlmsghdr --
+ // length = 88 or 76:
+ (if (neighAddr is Inet6Address) "58000000" else "4c000000") +
+ type.toLEHex() + // type
+ "0000" + // flags
+ "00000000" + // seqno
+ "00000000" + // pid (0 == kernel)
+ // struct ndmsg
+ // family (AF_INET6 or AF_INET)
+ (if (neighAddr is Inet6Address) "0a" else "02") +
+ "00" + // pad1
+ "0000" + // pad2
+ "15000000" + // interface index (21 == wlan0, on test device)
+ nudState.toLEHex() + // NUD state
+ "00" + // flags
+ "01" + // type
+ // -- struct nlattr: NDA_DST --
+ // length = 20 or 8:
+ (if (neighAddr is Inet6Address) "1400" else "0800") +
+ "0100" + // type (1 == NDA_DST, for neighbor messages)
+ // IP address:
+ encodeToString(neighAddr.address, false /* upperCase */) +
+ // -- 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
+ false /* allowSingleChar */)
+ /* ktlint-enable indent */
+
+/**
+ * Convert a [Short] to a little-endian hex string.
+ */
+private fun Short.toLEHex() = String.format("%04x", java.lang.Short.reverseBytes(this))
diff --git a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
index 72e6bca..34257b8 100644
--- a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -16,10 +16,15 @@
package android.net.netlink;
+import static android.net.netlink.NetlinkTestUtilsKt.makeDelNeighMessage;
+import static android.net.netlink.NetlinkTestUtilsKt.makeNewNeighMessage;
+import static android.net.netlink.StructNdMsg.NUD_STALE;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.net.InetAddresses;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.RtNetlinkNeighborMessage;
@@ -46,83 +51,11 @@
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);
+ public static final byte[] RTM_DELNEIGH = makeDelNeighMessage(
+ InetAddresses.parseNumericAddress("192.168.159.254"), NUD_STALE);
- // 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);
+ public static final byte[] RTM_NEWNEIGH = makeNewNeighMessage(
+ InetAddresses.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), NUD_STALE);
// An example of the full response from an RTM_GETNEIGH query.
private static final String RTM_GETNEIGH_RESPONSE_HEX =
@@ -165,7 +98,7 @@
assertNotNull(ndmsgHdr);
assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family);
assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
+ assertEquals(NUD_STALE, ndmsgHdr.ndm_state);
final InetAddress destination = neighMsg.getDestination();
assertNotNull(destination);
assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
@@ -192,7 +125,7 @@
assertNotNull(ndmsgHdr);
assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family);
assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
+ assertEquals(NUD_STALE, ndmsgHdr.ndm_state);
final InetAddress destination = neighMsg.getDestination();
assertNotNull(destination);
assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);