1 /*
2  * Copyright (C) 2019 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 com.android.networkstack.arp;
18 
19 import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST;
20 import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN;
21 import static com.android.testutils.MiscAsserts.assertThrows;
22 
23 import static org.junit.Assert.assertArrayEquals;
24 import static org.junit.Assert.assertEquals;
25 
26 import android.net.InetAddresses;
27 import android.net.MacAddress;
28 import android.net.dhcp.DhcpPacket;
29 
30 import androidx.test.filters.SmallTest;
31 import androidx.test.runner.AndroidJUnit4;
32 
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 
36 import java.net.Inet4Address;
37 import java.nio.ByteBuffer;
38 
39 @RunWith(AndroidJUnit4.class)
40 @SmallTest
41 public final class ArpPacketTest {
42 
43     private static final Inet4Address TEST_IPV4_ADDR =
44             (Inet4Address) InetAddresses.parseNumericAddress("192.168.1.2");
45     private static final Inet4Address INADDR_ANY =
46             (Inet4Address) InetAddresses.parseNumericAddress("0.0.0.0");
47     private static final byte[] TEST_SENDER_MAC_ADDR = new byte[] {
48             0x00, 0x1a, 0x11, 0x22, 0x33, 0x33 };
49     private static final byte[] TEST_TARGET_MAC_ADDR = new byte[] {
50             0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
51     private static final byte[] TEST_ARP_PROBE = new byte[] {
52         // dst mac address
53         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
54         // src mac address
55         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
56         // ether type
57         (byte) 0x08, (byte) 0x06,
58         // hardware type
59         (byte) 0x00, (byte) 0x01,
60         // protocol type
61         (byte) 0x08, (byte) 0x00,
62         // hardware address size
63         (byte) 0x06,
64         // protocol address size
65         (byte) 0x04,
66         // opcode
67         (byte) 0x00, (byte) 0x01,
68         // sender mac address
69         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
70         // sender IP address
71         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
72         // target mac address
73         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
74         // target IP address
75         (byte) 0xc0, (byte) 0xa8, (byte) 0x01, (byte) 0x02,
76     };
77 
78     private static final byte[] TEST_ARP_ANNOUNCE = new byte[] {
79         // dst mac address
80         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
81         // src mac address
82         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
83         // ether type
84         (byte) 0x08, (byte) 0x06,
85         // hardware type
86         (byte) 0x00, (byte) 0x01,
87         // protocol type
88         (byte) 0x08, (byte) 0x00,
89         // hardware address size
90         (byte) 0x06,
91         // protocol address size
92         (byte) 0x04,
93         // opcode
94         (byte) 0x00, (byte) 0x01,
95         // sender mac address
96         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
97         // sender IP address
98         (byte) 0xc0, (byte) 0xa8, (byte) 0x01, (byte) 0x02,
99         // target mac address
100         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
101         // target IP address
102         (byte) 0xc0, (byte) 0xa8, (byte) 0x01, (byte) 0x02,
103     };
104 
105     private static final byte[] TEST_ARP_PROBE_TRUNCATED = new byte[] {
106         // dst mac address
107         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
108         // src mac address
109         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
110         // ether type
111         (byte) 0x08, (byte) 0x06,
112         // hardware type
113         (byte) 0x00, (byte) 0x01,
114         // protocol type
115         (byte) 0x08, (byte) 0x00,
116         // hardware address size
117         (byte) 0x06,
118         // protocol address size
119         (byte) 0x04,
120         // opcode
121         (byte) 0x00,
122     };
123 
124     private static final byte[] TEST_ARP_PROBE_TRUNCATED_MAC = new byte[] {
125          // dst mac address
126         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
127         // src mac address
128         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x33,
129         // ether type
130         (byte) 0x08, (byte) 0x06,
131         // hardware type
132         (byte) 0x00, (byte) 0x01,
133         // protocol type
134         (byte) 0x08, (byte) 0x00,
135         // hardware address size
136         (byte) 0x06,
137         // protocol address size
138         (byte) 0x04,
139         // opcode
140         (byte) 0x00, (byte) 0x01,
141         // sender mac address
142         (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33,
143     };
144 
145     @Test
testBuildArpProbePacket()146     public void testBuildArpProbePacket() throws Exception {
147         final ByteBuffer arpProbe = ArpPacket.buildArpPacket(DhcpPacket.ETHER_BROADCAST,
148                 TEST_SENDER_MAC_ADDR, TEST_IPV4_ADDR.getAddress(), new byte[ETHER_ADDR_LEN],
149                 INADDR_ANY.getAddress(), (short) ARP_REQUEST);
150         assertArrayEquals(arpProbe.array(), TEST_ARP_PROBE);
151     }
152 
153     @Test
testBuildArpAnnouncePacket()154     public void testBuildArpAnnouncePacket() throws Exception {
155         final ByteBuffer arpAnnounce = ArpPacket.buildArpPacket(DhcpPacket.ETHER_BROADCAST,
156                 TEST_SENDER_MAC_ADDR, TEST_IPV4_ADDR.getAddress(), new byte[ETHER_ADDR_LEN],
157                 TEST_IPV4_ADDR.getAddress(), (short) ARP_REQUEST);
158         assertArrayEquals(arpAnnounce.array(), TEST_ARP_ANNOUNCE);
159     }
160 
161     @Test
testParseArpProbePacket()162     public void testParseArpProbePacket() throws Exception {
163         final ArpPacket packet = ArpPacket.parseArpPacket(TEST_ARP_PROBE, TEST_ARP_PROBE.length);
164         assertEquals(packet.opCode, ARP_REQUEST);
165         assertEquals(packet.senderHwAddress, MacAddress.fromBytes(TEST_SENDER_MAC_ADDR));
166         assertEquals(packet.targetHwAddress, MacAddress.fromBytes(TEST_TARGET_MAC_ADDR));
167         assertEquals(packet.senderIp, INADDR_ANY);
168         assertEquals(packet.targetIp, TEST_IPV4_ADDR);
169     }
170 
171     @Test
testParseArpAnnouncePacket()172     public void testParseArpAnnouncePacket() throws Exception {
173         final ArpPacket packet = ArpPacket.parseArpPacket(TEST_ARP_ANNOUNCE,
174                 TEST_ARP_ANNOUNCE.length);
175         assertEquals(packet.opCode, ARP_REQUEST);
176         assertEquals(packet.senderHwAddress, MacAddress.fromBytes(TEST_SENDER_MAC_ADDR));
177         assertEquals(packet.targetHwAddress, MacAddress.fromBytes(TEST_TARGET_MAC_ADDR));
178         assertEquals(packet.senderIp, TEST_IPV4_ADDR);
179         assertEquals(packet.targetIp, TEST_IPV4_ADDR);
180     }
181 
182     @Test
testParseArpPacket_invalidByteBufferParameters()183     public void testParseArpPacket_invalidByteBufferParameters() throws Exception {
184         assertThrows(ArpPacket.ParseException.class, () -> ArpPacket.parseArpPacket(
185                 TEST_ARP_PROBE, 0));
186     }
187 
188     @Test
testParseArpPacket_truncatedPacket()189     public void testParseArpPacket_truncatedPacket() throws Exception {
190         assertThrows(ArpPacket.ParseException.class, () -> ArpPacket.parseArpPacket(
191                 TEST_ARP_PROBE_TRUNCATED, TEST_ARP_PROBE_TRUNCATED.length));
192     }
193 
194     @Test
testParseArpPacket_truncatedMacAddress()195     public void testParseArpPacket_truncatedMacAddress() throws Exception {
196         assertThrows(ArpPacket.ParseException.class, () -> ArpPacket.parseArpPacket(
197                 TEST_ARP_PROBE_TRUNCATED_MAC, TEST_ARP_PROBE_TRUNCATED.length));
198     }
199 }
200