blob: 9f3897f19f5ca1a6f397623be138bee9da52ba57 [file] [log] [blame]
Lorenzo Colitti174bab22014-06-12 13:41:17 +09001/*
2 * Copyright (C) 2014 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
17package android.net;
18
Chalard Jean39175f22020-06-26 00:41:26 +090019import static com.android.testutils.MiscAsserts.assertEqualBothWays;
Chalard Jean39175f22020-06-26 00:41:26 +090020import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
21import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
Chalard Jeanaf718362019-05-30 17:11:14 +090022
Hugo Benichif9c61862016-11-10 22:45:56 +090023import static org.junit.Assert.assertArrayEquals;
24import static org.junit.Assert.assertEquals;
Hugo Benichi8253be92017-08-08 13:06:04 +090025import static org.junit.Assert.assertFalse;
26import static org.junit.Assert.assertNotEquals;
Hugo Benichi8253be92017-08-08 13:06:04 +090027import static org.junit.Assert.assertTrue;
28import static org.junit.Assert.fail;
Lorenzo Colitti174bab22014-06-12 13:41:17 +090029
Brett Chabot147f6cf2019-03-04 14:14:56 -080030import androidx.test.filters.SmallTest;
31import androidx.test.runner.AndroidJUnit4;
32
33import org.junit.Test;
34import org.junit.runner.RunWith;
Hugo Benichi8253be92017-08-08 13:06:04 +090035
36import java.net.InetAddress;
37import java.util.Random;
38
Hugo Benichi8253be92017-08-08 13:06:04 +090039@RunWith(AndroidJUnit4.class)
40@SmallTest
41public class IpPrefixTest {
Lorenzo Colitti174bab22014-06-12 13:41:17 +090042
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090043 private static InetAddress address(String addr) {
Erik Klineb98afb02015-04-13 15:33:34 +090044 return InetAddress.parseNumericAddress(addr);
45 }
46
Lorenzo Colitti174bab22014-06-12 13:41:17 +090047 // Explicitly cast everything to byte because "error: possible loss of precision".
48 private static final byte[] IPV4_BYTES = { (byte) 192, (byte) 0, (byte) 2, (byte) 4};
49 private static final byte[] IPV6_BYTES = {
50 (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
51 (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef,
52 (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00,
53 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
54 };
55
Hugo Benichi8253be92017-08-08 13:06:04 +090056 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +090057 public void testConstructor() {
58 IpPrefix p;
59 try {
60 p = new IpPrefix((byte[]) null, 9);
61 fail("Expected NullPointerException: null byte array");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090062 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090063
64 try {
65 p = new IpPrefix((InetAddress) null, 10);
66 fail("Expected NullPointerException: null InetAddress");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090067 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090068
69 try {
70 p = new IpPrefix((String) null);
71 fail("Expected NullPointerException: null String");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090072 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090073
74
75 try {
76 byte[] b2 = {1, 2, 3, 4, 5};
77 p = new IpPrefix(b2, 29);
78 fail("Expected IllegalArgumentException: invalid array length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090079 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090080
81 try {
82 p = new IpPrefix("1.2.3.4");
83 fail("Expected IllegalArgumentException: no prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090084 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090085
86 try {
87 p = new IpPrefix("1.2.3.4/");
88 fail("Expected IllegalArgumentException: empty prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090089 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090090
91 try {
92 p = new IpPrefix("foo/32");
93 fail("Expected IllegalArgumentException: invalid address");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090094 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +090095
96 try {
97 p = new IpPrefix("1/32");
98 fail("Expected IllegalArgumentException: deprecated IPv4 format");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +090099 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900100
101 try {
102 p = new IpPrefix("1.2.3.256/32");
103 fail("Expected IllegalArgumentException: invalid IPv4 address");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900104 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900105
106 try {
107 p = new IpPrefix("foo/32");
108 fail("Expected IllegalArgumentException: non-address");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900109 } catch (IllegalArgumentException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900110
111 try {
112 p = new IpPrefix("f00:::/32");
113 fail("Expected IllegalArgumentException: invalid IPv6 address");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900114 } catch (IllegalArgumentException expected) { }
paulhu1013c812021-03-03 22:15:11 +0800115
116 p = new IpPrefix("/64");
117 assertEquals("::/64", p.toString());
118
119 p = new IpPrefix("/128");
120 assertEquals("::1/128", p.toString());
121
122 p = new IpPrefix("[2001:db8::123]/64");
123 assertEquals("2001:db8::/64", p.toString());
Taras Antoshchuk3bbbffe2021-12-19 11:54:56 +0000124
125 p = new IpPrefix(InetAddresses.parseNumericAddress("::128"), 64);
126 assertEquals("::/64", p.toString());
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900127 }
128
Hugo Benichi8253be92017-08-08 13:06:04 +0900129 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900130 public void testTruncation() {
131 IpPrefix p;
132
133 p = new IpPrefix(IPV4_BYTES, 32);
134 assertEquals("192.0.2.4/32", p.toString());
135
136 p = new IpPrefix(IPV4_BYTES, 29);
137 assertEquals("192.0.2.0/29", p.toString());
138
139 p = new IpPrefix(IPV4_BYTES, 8);
140 assertEquals("192.0.0.0/8", p.toString());
141
142 p = new IpPrefix(IPV4_BYTES, 0);
143 assertEquals("0.0.0.0/0", p.toString());
144
145 try {
146 p = new IpPrefix(IPV4_BYTES, 33);
147 fail("Expected IllegalArgumentException: invalid prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900148 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900149
150 try {
151 p = new IpPrefix(IPV4_BYTES, 128);
152 fail("Expected IllegalArgumentException: invalid prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900153 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900154
155 try {
156 p = new IpPrefix(IPV4_BYTES, -1);
157 fail("Expected IllegalArgumentException: negative prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900158 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900159
160 p = new IpPrefix(IPV6_BYTES, 128);
161 assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
162
163 p = new IpPrefix(IPV6_BYTES, 122);
164 assertEquals("2001:db8:dead:beef:f00::80/122", p.toString());
165
166 p = new IpPrefix(IPV6_BYTES, 64);
167 assertEquals("2001:db8:dead:beef::/64", p.toString());
168
169 p = new IpPrefix(IPV6_BYTES, 3);
170 assertEquals("2000::/3", p.toString());
171
172 p = new IpPrefix(IPV6_BYTES, 0);
173 assertEquals("::/0", p.toString());
174
175 try {
176 p = new IpPrefix(IPV6_BYTES, -1);
177 fail("Expected IllegalArgumentException: negative prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900178 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900179
180 try {
181 p = new IpPrefix(IPV6_BYTES, 129);
182 fail("Expected IllegalArgumentException: negative prefix length");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900183 } catch (RuntimeException expected) { }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900184
185 }
186
Hugo Benichi8253be92017-08-08 13:06:04 +0900187 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900188 public void testEquals() {
189 IpPrefix p1, p2;
190
191 p1 = new IpPrefix("192.0.2.251/23");
192 p2 = new IpPrefix(new byte[]{(byte) 192, (byte) 0, (byte) 2, (byte) 251}, 23);
Chalard Jeanaf718362019-05-30 17:11:14 +0900193 assertEqualBothWays(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900194
195 p1 = new IpPrefix("192.0.2.5/23");
Chalard Jeanaf718362019-05-30 17:11:14 +0900196 assertEqualBothWays(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900197
198 p1 = new IpPrefix("192.0.2.5/24");
Chalard Jeanaf718362019-05-30 17:11:14 +0900199 assertNotEqualEitherWay(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900200
201 p1 = new IpPrefix("192.0.4.5/23");
Chalard Jeanaf718362019-05-30 17:11:14 +0900202 assertNotEqualEitherWay(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900203
204
205 p1 = new IpPrefix("2001:db8:dead:beef:f00::80/122");
206 p2 = new IpPrefix(IPV6_BYTES, 122);
207 assertEquals("2001:db8:dead:beef:f00::80/122", p2.toString());
Chalard Jeanaf718362019-05-30 17:11:14 +0900208 assertEqualBothWays(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900209
210 p1 = new IpPrefix("2001:db8:dead:beef:f00::bf/122");
Chalard Jeanaf718362019-05-30 17:11:14 +0900211 assertEqualBothWays(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900212
213 p1 = new IpPrefix("2001:db8:dead:beef:f00::8:0/123");
Chalard Jeanaf718362019-05-30 17:11:14 +0900214 assertNotEqualEitherWay(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900215
216 p1 = new IpPrefix("2001:db8:dead:beef::/122");
Chalard Jeanaf718362019-05-30 17:11:14 +0900217 assertNotEqualEitherWay(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900218
219 // 192.0.2.4/32 != c000:0204::/32.
220 byte[] ipv6bytes = new byte[16];
221 System.arraycopy(IPV4_BYTES, 0, ipv6bytes, 0, IPV4_BYTES.length);
222 p1 = new IpPrefix(ipv6bytes, 32);
Chalard Jeanaf718362019-05-30 17:11:14 +0900223 assertEqualBothWays(p1, new IpPrefix("c000:0204::/32"));
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900224
225 p2 = new IpPrefix(IPV4_BYTES, 32);
Chalard Jeanaf718362019-05-30 17:11:14 +0900226 assertNotEqualEitherWay(p1, p2);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900227 }
228
Hugo Benichi8253be92017-08-08 13:06:04 +0900229 @Test
Chalard Jean9cbc8822018-02-26 11:52:46 +0900230 public void testContainsInetAddress() {
Erik Klineb98afb02015-04-13 15:33:34 +0900231 IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900232 assertTrue(p.contains(address("2001:db8:f00::ace:d00c")));
233 assertTrue(p.contains(address("2001:db8:f00::ace:d00d")));
234 assertFalse(p.contains(address("2001:db8:f00::ace:d00e")));
235 assertFalse(p.contains(address("2001:db8:f00::bad:d00d")));
236 assertFalse(p.contains(address("2001:4868:4860::8888")));
237 assertFalse(p.contains(address("8.8.8.8")));
Erik Klineb98afb02015-04-13 15:33:34 +0900238
239 p = new IpPrefix("192.0.2.0/23");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900240 assertTrue(p.contains(address("192.0.2.43")));
241 assertTrue(p.contains(address("192.0.3.21")));
242 assertFalse(p.contains(address("192.0.0.21")));
243 assertFalse(p.contains(address("8.8.8.8")));
244 assertFalse(p.contains(address("2001:4868:4860::8888")));
Erik Klineb98afb02015-04-13 15:33:34 +0900245
246 IpPrefix ipv6Default = new IpPrefix("::/0");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900247 assertTrue(ipv6Default.contains(address("2001:db8::f00")));
248 assertFalse(ipv6Default.contains(address("192.0.2.1")));
Erik Klineb98afb02015-04-13 15:33:34 +0900249
250 IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0");
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900251 assertTrue(ipv4Default.contains(address("255.255.255.255")));
252 assertTrue(ipv4Default.contains(address("192.0.2.1")));
253 assertFalse(ipv4Default.contains(address("2001:db8::f00")));
Erik Klineb98afb02015-04-13 15:33:34 +0900254 }
255
Hugo Benichi8253be92017-08-08 13:06:04 +0900256 @Test
Chalard Jean9cbc8822018-02-26 11:52:46 +0900257 public void testContainsIpPrefix() {
258 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0")));
259 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0")));
260 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8")));
261 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24")));
262 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23")));
263
264 assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8")));
265 assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8")));
266 assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21")));
267 assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32")));
268
269 assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24")));
270
271 assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32")));
272 assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8")));
273 assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15")));
274 assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8")));
275
276 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0")));
277 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1")));
278 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8")));
279 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8")));
280 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64")));
281 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113")));
282 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128")));
283
284 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
285 new IpPrefix("2001:db8:f00::ace:d00d/64")));
286 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
287 new IpPrefix("2001:db8:f00::ace:d00d/120")));
288 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
289 new IpPrefix("2001:db8:f00::ace:d00d/32")));
290 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
291 new IpPrefix("2006:db8:f00::ace:d00d/96")));
292
293 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
294 new IpPrefix("2001:db8:f00::ace:d00d/128")));
295 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix(
296 new IpPrefix("2001:db8:f00::ace:ccaf/110")));
297
298 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
299 new IpPrefix("2001:db8:f00::ace:d00e/128")));
300 assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29")));
301 }
302
303 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900304 public void testHashCode() {
Hugo Benichif9c61862016-11-10 22:45:56 +0900305 IpPrefix p = new IpPrefix(new byte[4], 0);
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900306 Random random = new Random();
307 for (int i = 0; i < 100; i++) {
Hugo Benichif9c61862016-11-10 22:45:56 +0900308 final IpPrefix oldP = p;
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900309 if (random.nextBoolean()) {
310 // IPv4.
311 byte[] b = new byte[4];
312 random.nextBytes(b);
313 p = new IpPrefix(b, random.nextInt(33));
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900314 } else {
315 // IPv6.
316 byte[] b = new byte[16];
317 random.nextBytes(b);
318 p = new IpPrefix(b, random.nextInt(129));
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900319 }
Hugo Benichif9c61862016-11-10 22:45:56 +0900320 if (p.equals(oldP)) {
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900321 assertEquals(p.hashCode(), oldP.hashCode());
Hugo Benichif9c61862016-11-10 22:45:56 +0900322 }
323 if (p.hashCode() != oldP.hashCode()) {
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900324 assertNotEquals(p, oldP);
Hugo Benichif9c61862016-11-10 22:45:56 +0900325 }
326 }
327 }
328
Hugo Benichi8253be92017-08-08 13:06:04 +0900329 @Test
Hugo Benichif9c61862016-11-10 22:45:56 +0900330 public void testHashCodeIsNotConstant() {
331 IpPrefix[] prefixes = {
332 new IpPrefix("2001:db8:f00::ace:d00d/127"),
333 new IpPrefix("192.0.2.0/23"),
334 new IpPrefix("::/0"),
335 new IpPrefix("0.0.0.0/0"),
336 };
337 for (int i = 0; i < prefixes.length; i++) {
Remi NGUYEN VAN49b15872019-04-03 17:21:41 +0900338 for (int j = i + 1; j < prefixes.length; j++) {
339 assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
340 }
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900341 }
342 }
343
Hugo Benichi8253be92017-08-08 13:06:04 +0900344 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900345 public void testMappedAddressesAreBroken() {
346 // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
347 // we are unable to comprehend that.
348 byte[] ipv6bytes = {
349 (byte) 0, (byte) 0, (byte) 0, (byte) 0,
350 (byte) 0, (byte) 0, (byte) 0, (byte) 0,
351 (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff,
352 (byte) 192, (byte) 0, (byte) 2, (byte) 0};
353 IpPrefix p = new IpPrefix(ipv6bytes, 120);
354 assertEquals(16, p.getRawAddress().length); // Fine.
355 assertArrayEquals(ipv6bytes, p.getRawAddress()); // Fine.
356
357 // Broken.
358 assertEquals("192.0.2.0/120", p.toString());
359 assertEquals(InetAddress.parseNumericAddress("192.0.2.0"), p.getAddress());
360 }
361
Hugo Benichi8253be92017-08-08 13:06:04 +0900362 @Test
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900363 public void testParceling() {
364 IpPrefix p;
365
366 p = new IpPrefix("2001:4860:db8::/64");
367 assertParcelingIsLossless(p);
Hugo Benichi8253be92017-08-08 13:06:04 +0900368 assertTrue(p.isIPv6());
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900369
370 p = new IpPrefix("192.0.2.0/25");
371 assertParcelingIsLossless(p);
Hugo Benichi8253be92017-08-08 13:06:04 +0900372 assertTrue(p.isIPv4());
Lorenzo Colitti174bab22014-06-12 13:41:17 +0900373 }
374}