1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.netlink; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.net.netlink.NetlinkConstants; 24 import android.net.netlink.NetlinkMessage; 25 import android.net.netlink.RtNetlinkNeighborMessage; 26 import android.net.netlink.StructNdMsg; 27 import android.net.netlink.StructNlMsgHdr; 28 import android.system.OsConstants; 29 30 import androidx.test.filters.SmallTest; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import libcore.util.HexEncoding; 34 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.net.Inet4Address; 39 import java.net.InetAddress; 40 import java.nio.ByteBuffer; 41 import java.nio.ByteOrder; 42 import java.util.Arrays; 43 44 @RunWith(AndroidJUnit4.class) 45 @SmallTest 46 public class RtNetlinkNeighborMessageTest { 47 private final String TAG = "RtNetlinkNeighborMessageTest"; 48 49 // Hexadecimal representation of packet capture. 50 public static final String RTM_DELNEIGH_HEX = 51 // struct nlmsghdr 52 "4c000000" + // length = 76 53 "1d00" + // type = 29 (RTM_DELNEIGH) 54 "0000" + // flags 55 "00000000" + // seqno 56 "00000000" + // pid (0 == kernel) 57 // struct ndmsg 58 "02" + // family 59 "00" + // pad1 60 "0000" + // pad2 61 "15000000" + // interface index (21 == wlan0, on test device) 62 "0400" + // NUD state (0x04 == NUD_STALE) 63 "00" + // flags 64 "01" + // type 65 // struct nlattr: NDA_DST 66 "0800" + // length = 8 67 "0100" + // type (1 == NDA_DST, for neighbor messages) 68 "c0a89ffe" + // IPv4 address (== 192.168.159.254) 69 // struct nlattr: NDA_LLADDR 70 "0a00" + // length = 10 71 "0200" + // type (2 == NDA_LLADDR, for neighbor messages) 72 "00005e000164" + // MAC Address (== 00:00:5e:00:01:64) 73 "0000" + // padding, for 4 byte alignment 74 // struct nlattr: NDA_PROBES 75 "0800" + // length = 8 76 "0400" + // type (4 == NDA_PROBES, for neighbor messages) 77 "01000000" + // number of probes 78 // struct nlattr: NDA_CACHEINFO 79 "1400" + // length = 20 80 "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) 81 "05190000" + // ndm_used, as "clock ticks ago" 82 "05190000" + // ndm_confirmed, as "clock ticks ago" 83 "190d0000" + // ndm_updated, as "clock ticks ago" 84 "00000000"; // ndm_refcnt 85 public static final byte[] RTM_DELNEIGH = 86 HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false); 87 88 // Hexadecimal representation of packet capture. 89 public static final String RTM_NEWNEIGH_HEX = 90 // struct nlmsghdr 91 "58000000" + // length = 88 92 "1c00" + // type = 28 (RTM_NEWNEIGH) 93 "0000" + // flags 94 "00000000" + // seqno 95 "00000000" + // pid (0 == kernel) 96 // struct ndmsg 97 "0a" + // family 98 "00" + // pad1 99 "0000" + // pad2 100 "15000000" + // interface index (21 == wlan0, on test device) 101 "0400" + // NUD state (0x04 == NUD_STALE) 102 "80" + // flags 103 "01" + // type 104 // struct nlattr: NDA_DST 105 "1400" + // length = 20 106 "0100" + // type (1 == NDA_DST, for neighbor messages) 107 "fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b) 108 // struct nlattr: NDA_LLADDR 109 "0a00" + // length = 10 110 "0200" + // type (2 == NDA_LLADDR, for neighbor messages) 111 "84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b) 112 "0000" + // padding, for 4 byte alignment 113 // struct nlattr: NDA_PROBES 114 "0800" + // length = 8 115 "0400" + // type (4 == NDA_PROBES, for neighbor messages) 116 "01000000" + // number of probes 117 // struct nlattr: NDA_CACHEINFO 118 "1400" + // length = 20 119 "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) 120 "eb0e0000" + // ndm_used, as "clock ticks ago" 121 "861f0000" + // ndm_confirmed, as "clock ticks ago" 122 "00000000" + // ndm_updated, as "clock ticks ago" 123 "05000000"; // ndm_refcnt 124 public static final byte[] RTM_NEWNEIGH = 125 HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false); 126 127 // An example of the full response from an RTM_GETNEIGH query. 128 private static final String RTM_GETNEIGH_RESPONSE_HEX = 129 // <-- struct nlmsghr -->|<-- struct ndmsg -->|<-- struct nlattr: NDA_DST -->|<-- NDA_LLADDR -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO -->| 130 "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" + 131 "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" + 132 "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" + 133 "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" + 134 "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" + 135 "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" + 136 "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" + 137 "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" + 138 "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" + 139 "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" + 140 "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" + 141 "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" + 142 "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" + 143 "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"; 144 public static final byte[] RTM_GETNEIGH_RESPONSE = 145 HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false); 146 147 @Test testParseRtmDelNeigh()148 public void testParseRtmDelNeigh() { 149 final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH); 150 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. 151 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); 152 assertNotNull(msg); 153 assertTrue(msg instanceof RtNetlinkNeighborMessage); 154 final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; 155 156 final StructNlMsgHdr hdr = neighMsg.getHeader(); 157 assertNotNull(hdr); 158 assertEquals(76, hdr.nlmsg_len); 159 assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type); 160 assertEquals(0, hdr.nlmsg_flags); 161 assertEquals(0, hdr.nlmsg_seq); 162 assertEquals(0, hdr.nlmsg_pid); 163 164 final StructNdMsg ndmsgHdr = neighMsg.getNdHeader(); 165 assertNotNull(ndmsgHdr); 166 assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family); 167 assertEquals(21, ndmsgHdr.ndm_ifindex); 168 assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); 169 final InetAddress destination = neighMsg.getDestination(); 170 assertNotNull(destination); 171 assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination); 172 } 173 174 @Test testParseRtmNewNeigh()175 public void testParseRtmNewNeigh() { 176 final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH); 177 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. 178 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); 179 assertNotNull(msg); 180 assertTrue(msg instanceof RtNetlinkNeighborMessage); 181 final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; 182 183 final StructNlMsgHdr hdr = neighMsg.getHeader(); 184 assertNotNull(hdr); 185 assertEquals(88, hdr.nlmsg_len); 186 assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type); 187 assertEquals(0, hdr.nlmsg_flags); 188 assertEquals(0, hdr.nlmsg_seq); 189 assertEquals(0, hdr.nlmsg_pid); 190 191 final StructNdMsg ndmsgHdr = neighMsg.getNdHeader(); 192 assertNotNull(ndmsgHdr); 193 assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family); 194 assertEquals(21, ndmsgHdr.ndm_ifindex); 195 assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); 196 final InetAddress destination = neighMsg.getDestination(); 197 assertNotNull(destination); 198 assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination); 199 } 200 201 @Test testParseRtmGetNeighResponse()202 public void testParseRtmGetNeighResponse() { 203 final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE); 204 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. 205 206 int messageCount = 0; 207 while (byteBuffer.remaining() > 0) { 208 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); 209 assertNotNull(msg); 210 assertTrue(msg instanceof RtNetlinkNeighborMessage); 211 final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; 212 213 final StructNlMsgHdr hdr = neighMsg.getHeader(); 214 assertNotNull(hdr); 215 assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type); 216 assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags); 217 assertEquals(0, hdr.nlmsg_seq); 218 assertEquals(11070, hdr.nlmsg_pid); 219 220 messageCount++; 221 } 222 // TODO: add more detailed spot checks. 223 assertEquals(14, messageCount); 224 } 225 226 @Test testCreateRtmNewNeighMessage()227 public void testCreateRtmNewNeighMessage() { 228 final int seqNo = 2635; 229 final int ifIndex = 14; 230 final byte[] llAddr = 231 new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 }; 232 233 // Hexadecimal representation of our created packet. 234 final String expectedNewNeighHex = 235 // struct nlmsghdr 236 "30000000" + // length = 48 237 "1c00" + // type = 28 (RTM_NEWNEIGH) 238 "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE) 239 "4b0a0000" + // seqno 240 "00000000" + // pid (0 == kernel) 241 // struct ndmsg 242 "02" + // family 243 "00" + // pad1 244 "0000" + // pad2 245 "0e000000" + // interface index (14) 246 "0800" + // NUD state (0x08 == NUD_DELAY) 247 "00" + // flags 248 "00" + // type 249 // struct nlattr: NDA_DST 250 "0800" + // length = 8 251 "0100" + // type (1 == NDA_DST, for neighbor messages) 252 "7f000001" + // IPv4 address (== 127.0.0.1) 253 // struct nlattr: NDA_LLADDR 254 "0a00" + // length = 10 255 "0200" + // type (2 == NDA_LLADDR, for neighbor messages) 256 "010203040506" + // MAC Address (== 01:02:03:04:05:06) 257 "0000"; // padding, for 4 byte alignment 258 final byte[] expectedNewNeigh = 259 HexEncoding.decode(expectedNewNeighHex.toCharArray(), false); 260 261 final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage( 262 seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr); 263 if (!Arrays.equals(expectedNewNeigh, bytes)) { 264 assertEquals(expectedNewNeigh.length, bytes.length); 265 for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) { 266 assertEquals(expectedNewNeigh[i], bytes[i]); 267 } 268 } 269 } 270 } 271