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