added authentication to map notify and map reply, and moved the serialization process...
[lispflowmapping.git] / mappingservice / southbound / src / test / java / org / opendaylight / lispflowmapping / southbound / lisp / LispSouthboundServiceTest.java
1 /*
2  * Copyright (c) 2013 Contextream, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.lispflowmapping.southbound.lisp;
10
11 import static junit.framework.Assert.assertEquals;
12 import static junit.framework.Assert.assertFalse;
13 import static junit.framework.Assert.assertTrue;
14
15 import java.net.DatagramPacket;
16 import java.util.Arrays;
17 import java.util.List;
18
19 import junitx.framework.ArrayAssert;
20 import junitx.framework.Assert;
21
22 import org.apache.commons.lang3.ArrayUtils;
23 import org.jmock.api.Invocation;
24 import org.junit.Before;
25 import org.junit.Ignore;
26 import org.junit.Test;
27 import org.opendaylight.lispflowmapping.implementation.serializer.LispMessage;
28 import org.opendaylight.lispflowmapping.implementation.serializer.LispMessageEnum;
29 import org.opendaylight.lispflowmapping.implementation.util.ByteUtil;
30 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolver;
31 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServer;
32 import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
33 import org.opendaylight.lispflowmapping.tools.junit.BaseTestCase;
34 import org.opendaylight.lispflowmapping.type.AddressFamilyNumberEnum;
35 import org.opendaylight.lispflowmapping.type.lisp.EidRecord;
36 import org.opendaylight.lispflowmapping.type.lisp.EidToLocatorRecord;
37 import org.opendaylight.lispflowmapping.type.lisp.LocatorRecord;
38 import org.opendaylight.lispflowmapping.type.lisp.MapNotify;
39 import org.opendaylight.lispflowmapping.type.lisp.MapRegister;
40 import org.opendaylight.lispflowmapping.type.lisp.MapReply;
41 import org.opendaylight.lispflowmapping.type.lisp.MapRequest;
42 import org.opendaylight.lispflowmapping.type.lisp.address.LispAddress;
43 import org.opendaylight.lispflowmapping.type.lisp.address.LispIpv4Address;
44 import org.opendaylight.lispflowmapping.type.lisp.address.LispIpv6Address;
45
46 public class LispSouthboundServiceTest extends BaseTestCase {
47
48     private LispSouthboundService testedLispService;
49     private IMapResolver mapResolver;
50     private IMapServer mapServer;
51     private byte[] mapRequestPacket;
52     private byte[] mapRegisterPacket;
53     private ValueSaverAction<MapRegister> mapRegisterSaver;
54     private ValueSaverAction<MapRequest> mapRequestSaver;
55     private MapNotify mapNotify;
56     private MapReply mapReply;
57     private EidToLocatorRecord eidToLocator;
58
59     private interface MapReplyIpv4SingleLocatorPos {
60         int RECORD_COUNT = 3;
61         int NONCE = 4;
62         int LOCATOR_COUNT = 16;
63         int EID_MASK_LEN = 17;
64         int AFI_TYPE = 22;
65         int EID_PREFIX = 24;
66         int LOC_AFI = 34;
67         int LOCATOR_RBIT = 33;
68         int LOCATOR = 36;
69     }
70
71     private interface MapReplyIpv4SecondLocatorPos {
72         int FIRST_LOCATOR_IPV4_LENGTH = 12;
73         int LOC_AFI = MapReplyIpv4SingleLocatorPos.LOC_AFI + FIRST_LOCATOR_IPV4_LENGTH;
74         int LOCATOR_RBIT = MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT + FIRST_LOCATOR_IPV4_LENGTH;
75         int LOCATOR = MapReplyIpv4SingleLocatorPos.LOCATOR + FIRST_LOCATOR_IPV4_LENGTH;
76     }
77
78     @Override
79     @Before
80     public void before() throws Exception {
81         super.before();
82         mapResolver = context.mock(IMapResolver.class);
83         mapServer = context.mock(IMapServer.class);
84         testedLispService = new LispSouthboundService(mapResolver, mapServer);
85
86         mapRegisterSaver = new ValueSaverAction<MapRegister>();
87         mapRequestSaver = new ValueSaverAction<MapRequest>();
88         // SRC: 127.0.0.1:58560 to 127.0.0.1:4342
89         // LISP(Type = 8 - Encapsulated)
90         // IP: 192.168.136.10 -> 1.2.3.4
91         // UDP: 56756
92         // LISP(Type = 1 Map-Request
93         // Record Count: 1
94         // ITR-RLOC count: 0
95         // Source EID AFI: 0
96         // Source EID not present
97         // Nonce: 0x3d8d2acd39c8d608
98         // ITR-RLOC AFI=1 Address=192.168.136.10
99         // Record 1: 1.2.3.4/32
100         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
101                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
102                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
103                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 "
104                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "
105                 + "0050   2a cd 39 c8 d6 08 00 00 00 01 c0 a8 88 0a 00 20 " //
106                 + "0060   00 01 01 02 03 04"));
107         mapReply = new MapReply();
108         eidToLocator = new EidToLocatorRecord();
109         eidToLocator.setPrefix(new LispIpv4Address(0));
110         mapReply.addEidToLocator(eidToLocator);
111
112         // IP: 192.168.136.10 -> 128.223.156.35
113         // UDP: 49289 -> 4342
114         // LISP(Type = 3 Map-Register, P=1, M=1
115         // Record Counter: 1
116         // Nonce: 0
117         // Key ID: 0x0001
118         // AuthDataLength: 20 Data:
119         // e8:f5:0b:c5:c5:f2:b0:21:27:a8:21:41:04:f3:46:5a:a5:68:89:ec
120         // EID prefix: 153.16.254.1/32 (EID=0x9910FE01), TTL: 10, Authoritative,
121         // No-Action
122         // Local RLOC: 192.168.136.10 (RLOC=0xC0A8880A), Reachable,
123         // Priority/Weight: 1/100, Multicast Priority/Weight:
124         // 255/0
125         //
126
127         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
128                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
129                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 01 01 00 00 "
130                 + "0030   00 00 00 00 00 00 00 01 00 14 0e a4 c6 d8 a4 06 "
131                 + "0040   71 7c 33 a4 5c 4a 83 1c de 74 53 03 0c ad 00 00 "
132                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
133                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
134         mapNotify = new MapNotify();
135     }
136
137     @Test
138     @Ignore
139     public void todos() throws Exception {
140
141         // TODO: MapRequest: usage of Map-Reply-Record in MapRequest packet.
142         // TODO: Non-Encapsulated packets
143     }
144
145     @Test(expected = LispMalformedPacketException.class)
146     public void mapRegister__IllegalPacket() throws Exception {
147         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
148                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " //
149                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 "));
150
151         handlePacket(mapRegisterPacket);
152     }
153
154     @Test(expected = LispMalformedPacketException.class)
155     public void mapRequest__IllegalPacket() throws Exception {
156         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
157                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
158                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
159                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 " //
160                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "));
161         handlePacket(mapRequestPacket);
162     }
163
164     @Test(expected = LispMalformedPacketException.class)
165     public void mapRequest__IllegalEncapsulatedPacket() throws Exception {
166         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
167                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 " //
168                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "));
169         handlePacket(mapRequestPacket);
170     }
171
172     @Test
173     public void mapRegister__TwoRlocs() throws Exception {
174         // P Bit & M Bit set
175         // EID prefix: 172.1.1.2/32, TTL: 10, Authoritative, No-Action
176         // Local RLOC: 10.1.0.110, Reachable, Priority/Weight: 1/100, Multicast
177         // Priority/Weight: 255/0
178         // Local RLOC: 192.168.136.51, Reachable, Priority/Weight: 6/100,
179         // Multicast Priority/Weight: 255/0
180         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
181                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " //
182                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 " //
183                 + "0030   00 00 00 00 00 00 00 01 00 14 ae d8 7b d4 9c 59 " //
184                 + "0040   e9 35 75 6e f1 29 27 a3 45 20 96 06 c2 e1 00 00 " //
185                 + "0050   00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 01 64 " //
186                 + "0060   ff 00 00 05 00 01 0a 01 00 6e 06 64 ff 00 00 05 " //
187                 + "0070   00 01 c0 a8 88 33"));
188
189         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
190         ret(null);
191
192         handlePacket(mapRegisterPacket);
193
194         List<EidToLocatorRecord> eidRecords = mapRegisterSaver.lastValue.getEidToLocatorRecords();
195         assertEquals(1, eidRecords.size());
196         EidToLocatorRecord eidRecord = eidRecords.get(0);
197         assertEquals(2, eidRecord.getLocators().size());
198         assertEquals(new LispIpv4Address("10.1.0.110"), eidRecord.getLocators().get(0).getLocator());
199         assertEquals(new LispIpv4Address("192.168.136.51"), eidRecord.getLocators().get(1).getLocator());
200     }
201
202     @Test
203     public void mapRegister__Ipv6Rloc() throws Exception {
204         // P bit (Proxy-Map-Reply): Set
205         // M bit (Want-Map-Notify): Set
206         // Record Counter: 1
207         // Nonce: 0
208         // Key ID: 1
209         // AuthLength: 20
210         // Authentication Data: 5bc4d44a57e2a55d577a6f89779c004f5da713fb
211         // EID prefix: 2610:d0:ffff:192::1/128, TTL: 10, Authoritative,
212         // No-Action
213         // Local RLOC: 10.0.58.156, Reachable, Priority/Weight: 1/100, Multicast
214         // Priority/Weight: 255/0
215
216         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
217                 + "0010   00 68 00 00 40 00 40 11 ea c3 0a 00 3a 9c 0a 00 " //
218                 + "0020   01 26 10 f6 10 f6 00 54 f5 9a 38 00 03 01 00 00 " //
219                 + "0030   00 00 00 00 00 00 00 01 00 14 22 97 ff 61 ec d8 " //
220                 + "0040   0f 91 c6 c4 01 ef 7f bb 77 58 39 5c 92 23 00 00 " //
221                 + "0050   00 0a 01 80 10 00 00 00 00 02 26 10 00 d0 ff ff " //
222                 + "0060   01 92 00 00 00 00 00 00 00 01 01 64 ff 00 00 05 " //
223                 + "0070   00 01 0a 00 3a 9c"));
224
225         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
226         ret(null);
227
228         handlePacket(mapRegisterPacket);
229         byte[] expectedIpv6Address = new byte[] { 0x26, 0x10, 0x00, (byte) 0xd0, (byte) 0xff, (byte) 0xff, 0x01, (byte) 0x92, 0x00, 0x00, 0x00, 0x00,
230                 0x00, 0x00, 0x00, 0x01 };
231
232         EidToLocatorRecord eidToLocatorRecord = mapRegisterSaver.lastValue.getEidToLocatorRecords().get(0);
233         assertEquals(new LispIpv6Address(expectedIpv6Address), eidToLocatorRecord.getPrefix());
234         assertEquals(AddressFamilyNumberEnum.IP6, eidToLocatorRecord.getPrefix().getAfi());
235
236         assertEquals(new LispIpv4Address(0x0A003A9C), eidToLocatorRecord.getLocators().get(0).getLocator());
237     }
238
239     @Test
240     public void mapRegister__VerifyBasicFields() throws Exception {
241         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
242         ret(null);
243         handlePacket(mapRegisterPacket);
244
245         EidToLocatorRecord eidToLocator = mapRegisterSaver.lastValue.getEidToLocatorRecords().get(0);
246         assertEquals(new LispIpv4Address(0x9910FE01), eidToLocator.getPrefix());
247
248         assertEquals(1, eidToLocator.getLocators().size());
249         assertEquals(new LispIpv4Address(0xC0A8880A), eidToLocator.getLocators().get(0).getLocator());
250     }
251
252     @Test
253     public void mapRegister__NoResponseFromMapServerShouldReturnNullPacket() throws Exception {
254         allowing(mapServer).handleMapRegister(with(mapRegisterSaver));
255         ret(null);
256
257         assertNull(handlePacket(mapRegisterPacket));
258     }
259
260     @Test
261     public void mapRegister__NonSetMBit() throws Exception {
262         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
263                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " //
264                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 00 01 00 00 "
265                 + "0030   00 00 00 00 00 00 00 01 00 14 79 d1 44 66 19 99 "
266                 + "0040   83 63 a7 79 6e f0 40 97 54 26 3a 44 b4 eb 00 00 " //
267                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
268                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
269         stubMapRegister(true);
270
271         handlePacket(registerWithNonSetMBit);
272
273         assertFalse(mapRegisterSaver.lastValue.isWantMapNotify());
274     }
275
276     @Test
277     public void mapRegister__NonSetMBitWithNonZeroReservedBits() throws Exception {
278         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
279                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
280                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 02 01 00 00 "
281                 + "0030   00 00 00 00 00 00 00 01 00 14 c0 c7 c5 2f 57 f6 "
282                 + "0040   e7 20 25 3d e8 b2 07 e2 63 de 62 2b 7a 20 00 00 "
283                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
284                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
285         stubMapRegister(true);
286
287         handlePacket(registerWithNonSetMBit);
288         assertFalse(mapRegisterSaver.lastValue.isWantMapNotify());
289     }
290
291     @Test
292     public void mapRegister__SetMBitWithNonZeroReservedBits() throws Exception {
293         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
294                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
295                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 03 01 00 00 "
296                 + "0030   00 00 00 00 00 00 00 01 00 14 a2 72 40 7b 1a ae "
297                 + "0040   4e 6b e2 e5 e1 01 40 8a c9 e1 d1 80 cb 72 00 00 "
298                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
299                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
300         stubMapRegister(true);
301
302         handlePacket(registerWithNonSetMBit);
303         assertTrue(mapRegisterSaver.lastValue.isWantMapNotify());
304     }
305
306     @Test
307     public void mapRegisterAndNotify__ValidExtraDataParsedSuccessfully() throws Exception {
308         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
309                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
310                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
311                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 "
312                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "
313                 + "0050   2a cd 39 c8 d6 08 00 00 00 01 c0 a8 88 0a 00 20 " //
314                 + "0060   00 01 01 02 03 04"));
315         byte[] extraDataPacket = new byte[mapRegisterPacket.length + 3];
316         extraDataPacket[mapRegisterPacket.length] = 0x9;
317         System.arraycopy(mapRegisterPacket, 0, extraDataPacket, 0, mapRegisterPacket.length);
318         stubMapRegister(true);
319
320         DatagramPacket dp = new DatagramPacket(extraDataPacket, extraDataPacket.length);
321         dp.setLength(mapRegisterPacket.length);
322         byte[] notifyResult = testedLispService.handlePacket(dp).getData();
323
324         assertEquals(mapRegisterPacket.length, notifyResult.length);
325
326     }
327
328     @Test
329     public void mapNotify__VerifyBasicFields() throws Exception {
330         byte registerType = mapRegisterPacket[0];
331         assertEquals(LispMessageEnum.MapRegister.getValue(), registerType >> 4);
332
333         stubMapRegister(true);
334
335         byte[] result = handlePacketAsByteArray(mapRegisterPacket);
336
337         assertEquals(mapRegisterPacket.length, result.length);
338
339         byte expectedType = (byte) (LispMessageEnum.MapNotify.getValue() << 4);
340         assertHexEquals(expectedType, result[0]);
341         assertHexEquals((byte) 0x00, result[1]);
342         assertHexEquals((byte) 0x00, result[2]);
343
344         byte[] registerWithoutTypeWithoutAuthenticationData = ArrayUtils.addAll(Arrays.copyOfRange(mapRegisterPacket, 3, 16),Arrays.copyOfRange(mapRegisterPacket, 36, mapRegisterPacket.length));
345         byte[] notifyWithoutTypeWithOutAuthenticationData = ArrayUtils.addAll(Arrays.copyOfRange(result, 3, 16), Arrays.copyOfRange(result, 36, result.length));
346         ArrayAssert.assertEquals(registerWithoutTypeWithoutAuthenticationData, notifyWithoutTypeWithOutAuthenticationData);
347     }
348
349     @Test
350     public void mapNotify__VerifyPort() throws Exception {
351         stubMapRegister(true);
352
353         DatagramPacket notifyPacket = handlePacket(mapRegisterPacket);
354         assertEquals(LispMessage.PORT_NUM, notifyPacket.getPort());
355     }
356
357     @Test
358     public void mapRequest__VerifyBasicFields() throws Exception {
359         oneOf(mapResolver).handleMapRequest(with(mapRequestSaver));
360         ret(mapReply);
361
362         handlePacketAsByteArray(mapRequestPacket);
363         List<EidRecord> eids = mapRequestSaver.lastValue.getEids();
364         assertEquals(1, eids.size());
365         LispAddress lispAddress = eids.get(0).getPrefix();
366         assertTrue(lispAddress instanceof LispIpv4Address);
367         assertEquals(asInet(0x01020304), ((LispIpv4Address) lispAddress).getAddress());
368         assertEquals((byte) 0x20, eids.get(0).getMaskLength());
369         assertEquals(0x3d8d2acd39c8d608L, mapRequestSaver.lastValue.getNonce());
370         assertEquals(AddressFamilyNumberEnum.RESERVED, mapRequestSaver.lastValue.getSourceEid().getAfi());
371     }
372
373     @Test
374     public void mapRequest__Ipv6Eid() throws Exception {
375         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
376         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
377         // (2610:d0:ffff:192::2)
378         // MBIT: SET
379         // EID AFI: 2
380         // Source EID: 2610:d0:ffff:192::1 (2610:d0:ffff:192::1)
381         // ITR-RLOC 1: 10.0.58.156
382         // Record 1: 2610:d0:ffff:192::2/128
383         // Map-Reply Record: EID prefix: 2610:d0:ffff:192::1/128, TTL: 10,
384         // Authoritative, No-Action
385
386         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
387                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
388                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
389                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
390                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
391                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 "
392                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
393                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
394                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
395                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " //
396                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " //
397                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c"));
398
399         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
400         ret(mapReply);
401
402         handlePacketAsByteArray(mapRequestPacket);
403         assertEquals(new LispIpv6Address("2610:d0:ffff:192::1"), mapRequestSaver.lastValue.getSourceEid());
404         assertEquals(new LispIpv6Address("2610:d0:ffff:192::2"), mapRequestSaver.lastValue.getEids().get(0).getPrefix());
405     }
406
407     @Test
408     public void mapRequest__UsesIpv6EncapsulatedUdpPort() throws Exception {
409         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
410         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
411         // (2610:d0:ffff:192::2)
412         // encapsulated UDP source port: 4342
413
414         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
415                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
416                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
417                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
418                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
419                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 "
420                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
421                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
422                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
423                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " //
424                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " //
425                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c"));
426
427         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
428         ret(mapReply);
429
430         DatagramPacket replyPacket = handlePacket(mapRequestPacket);
431         assertEquals(4342, replyPacket.getPort());
432     }
433
434     @Test
435     public void mapRequest__WithSourceEid() throws Exception {
436         // encapsulated LISP packet
437         // Source EID = 153.16.254.1
438
439         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 83 00 15 17 c6 4a c9 08 00 45 00 " //
440                 + "0010   00 78 00 00 40 00 3e 11 ec b1 0a 00 01 26 0a 00 "
441                 + "0020   3a 9e 10 f6 10 f6 00 64 c3 a5 80 00 00 00 45 00 "
442                 + "0030   00 58 d4 31 00 00 ff 11 31 89 99 10 fe 01 0a 00 "
443                 + "0040   14 c8 10 f6 10 f6 00 44 84 ee 14 00 00 01 ba f9 "
444                 + "0050   ff 53 27 36 38 3a 00 01 99 10 fe 01 00 01 0a 00 "
445                 + "0060   01 26 00 20 00 01 0a 00 14 c8 00 00 00 0a 01 20 "
446                 + "0070   10 00 00 00 00 01 99 10 fe 01 01 64 ff 00 00 05 " //
447                 + "0080   00 01 0a 00 01 26"));
448
449         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
450         ret(mapReply);
451
452         handlePacketAsByteArray(mapRequestPacket);
453         Assert.assertNotEquals(AddressFamilyNumberEnum.RESERVED, mapRequestSaver.lastValue.getSourceEid().getAfi());
454
455     }
456
457     @Test
458     public void mapReply__VerifyBasicIPv4Fields() throws Exception {
459         eidToLocator.setMaskLength((byte) 0x20)//
460                 .setPrefix(new LispIpv4Address(0x0a0014c8));
461         mapReply.setNonce(0x3d8d2acd39c8d608L);
462
463         stubHandleRequest();
464
465         byte[] result = handlePacketAsByteArray(mapRequestPacket);
466
467         assertEquals(28, result.length);
468
469         byte expectedLispMessageType = 2;
470         assertEquals(expectedLispMessageType, (byte) (result[LispMessage.Pos.TYPE] >> 4));
471         assertEquals(0x3d8d2acd39c8d608L, ByteUtil.getLong(result, MapReplyIpv4SingleLocatorPos.NONCE));
472
473         byte expectedRecordCount = (byte) 1;
474         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
475
476         assertEquals(eidToLocator.getMaskLength(), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
477         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
478         assertEquals(0x0a0014c8, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.EID_PREFIX));
479     }
480
481     @Test
482     public void mapReply__VerifyBasicIPv6() throws Exception {
483         eidToLocator.setMaskLength((byte) 0x80)//
484                 .setPrefix(new LispIpv6Address("::1"));
485
486         stubHandleRequest();
487
488         byte[] result = handlePacketAsByteArray(mapRequestPacket);
489
490         assertEquals(40, result.length);
491
492         byte expectedRecordCount = (byte) 1;
493         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
494
495         assertEquals(eidToLocator.getMaskLength(), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
496         assertEquals(AddressFamilyNumberEnum.IP6.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
497         byte[] expectedIpv6 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
498
499         ArrayAssert.assertEquals(expectedIpv6, Arrays.copyOfRange(result, 24, 40));
500     }
501
502     @Test
503     public void mapReply__VerifyIPv6EidAndLocator() throws Exception {
504         eidToLocator.setPrefix(new LispIpv6Address("::1"));
505         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv6Address("::2")));
506
507         stubHandleRequest();
508
509         byte[] result = handlePacketAsByteArray(mapRequestPacket);
510
511         assertEquals(64, result.length);
512
513         byte[] expectedIpv6Eid = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
514         ArrayAssert.assertEquals(expectedIpv6Eid, Arrays.copyOfRange(result, 24, 40));
515
516         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
517         ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, 48, 64));
518     }
519
520     @Test
521     public void mapReply__UseEncapsulatedUdpPort() throws Exception {
522         stubHandleRequest();
523
524         assertEquals(56756, handlePacket(mapRequestPacket).getPort());
525     }
526
527     @Test
528     public void mapReply__WithNonRoutableSingleLocator() throws Exception {
529         eidToLocator.setMaskLength((byte) 0x20)//
530                 .setPrefix(new LispIpv4Address(0x0a0014c8));
531         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(false));
532         stubHandleRequest();
533
534         byte[] result = handlePacketAsByteArray(mapRequestPacket);
535         assertEquals(0x00, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
536     }
537
538     @Test
539     public void mapReply__WithSingleLocator() throws Exception {
540         eidToLocator.setMaskLength((byte) 0x20)//
541                 .setPrefix(new LispIpv4Address(0x0a0014c8));
542         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(true));
543         stubHandleRequest();
544
545         byte[] result = handlePacketAsByteArray(mapRequestPacket);
546         assertEquals(40, result.length);
547
548         byte expectedLocCount = 1;
549         assertEquals(expectedLocCount, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
550
551         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
552
553         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
554         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
555     }
556
557     @Test
558     public void mapReply__WithMultipleLocator() throws Exception {
559         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(true));
560         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv6Address("::1")).setRouted(true));
561         stubHandleRequest();
562
563         byte[] result = handlePacketAsByteArray(mapRequestPacket);
564         assertEquals(64, result.length);
565
566         assertEquals(2, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
567
568         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
569         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
570         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
571
572         assertEquals(AddressFamilyNumberEnum.IP6.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SecondLocatorPos.LOC_AFI));
573
574         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
575         ArrayAssert.assertEquals(expectedIpv6Rloc,
576                 Arrays.copyOfRange(result, MapReplyIpv4SecondLocatorPos.LOCATOR, MapReplyIpv4SecondLocatorPos.LOCATOR + 16));
577
578         assertEquals(0x01, result[MapReplyIpv4SecondLocatorPos.LOCATOR_RBIT] & 0x01);
579     }
580
581     @Test
582     public void handleUnknownLispMessage() throws Exception {
583         // IP: 192.168.136.10 -> 128.223.156.35
584         // UDP: 49289 -> 4342
585         // LISP(Type = 14 UNKNOWN!!!, P=1, M=1
586
587         byte[] unknownTypePacket = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
588                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
589                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 F8 00 01 01 00 00 "
590                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
591                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
592                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
593                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
594         assertNull(handlePacket(unknownTypePacket));
595     }
596
597     @Test
598     public void mapRequest__MultipleItrRlocs() throws Exception {
599         // this is what LISPmob sends when configured multiple RLOCs for single
600         // EID.
601         // ITR-RLOC 1: 10.1.0.111
602         // ITR-RLOC 2: 192.168.136.51
603         //
604         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
605                 + "0010   00 8a 00 00 40 00 40 11 25 f2 0a 01 00 6f 0a 01 " //
606                 + "0020   00 01 10 f6 10 f6 00 76 06 1f 80 00 00 00 45 00 " //
607                 + "0030   00 6a d4 31 00 00 ff 11 2a 3e ac 01 01 02 08 08 " //
608                 + "0040   08 08 10 f6 10 f6 00 56 63 14 14 00 01 01 79 67 " //
609                 + "0050   ff 75 a0 61 66 19 00 01 ac 01 01 02 00 01 0a 01 " //
610                 + "0060   00 6f 00 01 c0 a8 88 33 00 20 00 01 08 08 08 08 " //
611                 + "0070   00 00 00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 " //
612                 + "0080   01 64 ff 00 00 05 00 01 0a 01 00 6f 06 64 ff 00 " //
613                 + "0090   00 05 00 01 c0 a8 88 33"));
614
615         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
616         ret(mapReply);
617
618         handlePacketAsByteArray(mapRequestPacket);
619
620         // assertEquals(2, mapRequestSaver.lastValue.getItrRlocs().size());
621         // assertEquals(new LispIpv4Address("10.1.0.111"),
622         // mapRequestSaver.lastValue.getItrRlocs().get(0));
623         // assertEquals(new LispIpv4Address("192.168.136.51"),
624         // mapRequestSaver.lastValue.getItrRlocs().get(1));
625     }
626
627     private void stubMapRegister(final boolean setNotifyFromRegister) {
628         allowing(mapServer).handleMapRegister(with(mapRegisterSaver));
629         will(new SimpleAction() {
630
631             @Override
632             public Object invoke(Invocation invocation) throws Throwable {
633                 if (setNotifyFromRegister) {
634                     mapNotify.setFromMapRegister(mapRegisterSaver.lastValue);
635                 }
636                 return mapNotify;
637             }
638         });
639     }
640
641     private void stubHandleRequest() {
642         allowing(mapResolver).handleMapRequest(wany(MapRequest.class));
643         ret(mapReply);
644     }
645
646     private byte[] handlePacketAsByteArray(byte[] inPacket) {
647         return handlePacket(inPacket).getData();
648     }
649
650     private DatagramPacket handlePacket(byte[] inPacket) {
651         return testedLispService.handlePacket(new DatagramPacket(inPacket, inPacket.length));
652     }
653
654     private byte[] extractWSUdpByteArray(String wiresharkHex) {
655         final int HEADER_LEN = 42;
656         byte[] res = new byte[1000];
657         String[] split = wiresharkHex.split(" ");
658         int counter = 0;
659         for (String cur : split) {
660             cur = cur.trim();
661             if (cur.length() == 2) {
662                 ++counter;
663                 if (counter > HEADER_LEN) {
664                     res[counter - HEADER_LEN - 1] = (byte) Integer.parseInt(cur, 16);
665                 }
666
667             }
668         }
669         return Arrays.copyOf(res, counter - HEADER_LEN);
670     }
671 }