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;
18 
19 import static android.system.OsConstants.AF_INET6;
20 import static android.system.OsConstants.IPPROTO_ICMPV6;
21 import static android.system.OsConstants.SOCK_DGRAM;
22 import static android.system.OsConstants.SOL_SOCKET;
23 import static android.system.OsConstants.SO_RCVTIMEO;
24 
25 import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel;
26 
27 import static junit.framework.Assert.assertEquals;
28 
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assume.assumeTrue;
31 
32 import android.os.Build;
33 import android.system.ErrnoException;
34 import android.system.Os;
35 import android.system.StructTimeval;
36 
37 import androidx.test.filters.SmallTest;
38 
39 import com.android.net.module.util.SocketUtils;
40 import com.android.testutils.DevSdkIgnoreRule;
41 import com.android.testutils.DevSdkIgnoreRunner;
42 
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 
46 import java.io.FileDescriptor;
47 import java.math.BigInteger;
48 import java.nio.ByteBuffer;
49 import java.nio.ByteOrder;
50 import java.util.TreeSet;
51 
52 @RunWith(DevSdkIgnoreRunner.class)
53 @SmallTest
54 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
55 public class NetworkUtilsTest {
56     @Test
testRoutedIPv4AddressCount()57     public void testRoutedIPv4AddressCount() {
58         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
59         // No routes routes to no addresses.
60         assertEquals(0, NetworkUtils.routedIPv4AddressCount(set));
61 
62         set.add(new IpPrefix("0.0.0.0/0"));
63         assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
64 
65         set.add(new IpPrefix("20.18.0.0/16"));
66         set.add(new IpPrefix("20.18.0.0/24"));
67         set.add(new IpPrefix("20.18.0.0/8"));
68         // There is a default route, still covers everything
69         assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
70 
71         set.clear();
72         set.add(new IpPrefix("20.18.0.0/24"));
73         set.add(new IpPrefix("20.18.0.0/8"));
74         // The 8-length includes the 24-length prefix
75         assertEquals(1l << 24, NetworkUtils.routedIPv4AddressCount(set));
76 
77         set.add(new IpPrefix("10.10.10.126/25"));
78         // The 8-length does not include this 25-length prefix
79         assertEquals((1l << 24) + (1 << 7), NetworkUtils.routedIPv4AddressCount(set));
80 
81         set.clear();
82         set.add(new IpPrefix("1.2.3.4/32"));
83         set.add(new IpPrefix("1.2.3.4/32"));
84         set.add(new IpPrefix("1.2.3.4/32"));
85         set.add(new IpPrefix("1.2.3.4/32"));
86         assertEquals(1l, NetworkUtils.routedIPv4AddressCount(set));
87 
88         set.add(new IpPrefix("1.2.3.5/32"));
89         set.add(new IpPrefix("1.2.3.6/32"));
90 
91         set.add(new IpPrefix("1.2.3.7/32"));
92         set.add(new IpPrefix("1.2.3.8/32"));
93         set.add(new IpPrefix("1.2.3.9/32"));
94         set.add(new IpPrefix("1.2.3.0/32"));
95         assertEquals(7l, NetworkUtils.routedIPv4AddressCount(set));
96 
97         // 1.2.3.4/30 eats 1.2.3.{4-7}/32
98         set.add(new IpPrefix("1.2.3.4/30"));
99         set.add(new IpPrefix("6.2.3.4/28"));
100         set.add(new IpPrefix("120.2.3.4/16"));
101         assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set));
102     }
103 
104     @Test
testRoutedIPv6AddressCount()105     public void testRoutedIPv6AddressCount() {
106         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
107         // No routes routes to no addresses.
108         assertEquals(BigInteger.ZERO, NetworkUtils.routedIPv6AddressCount(set));
109 
110         set.add(new IpPrefix("::/0"));
111         assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
112 
113         set.add(new IpPrefix("1234:622a::18/64"));
114         set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
115         set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
116         // There is a default route, still covers everything
117         assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
118 
119         set.clear();
120         set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
121         set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
122         // The 8-length includes the 96-length prefix
123         assertEquals(BigInteger.ONE.shiftLeft(120), NetworkUtils.routedIPv6AddressCount(set));
124 
125         set.add(new IpPrefix("10::26/64"));
126         // The 8-length does not include this 64-length prefix
127         assertEquals(BigInteger.ONE.shiftLeft(120).add(BigInteger.ONE.shiftLeft(64)),
128                 NetworkUtils.routedIPv6AddressCount(set));
129 
130         set.clear();
131         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
132         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
133         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
134         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
135         assertEquals(BigInteger.ONE, NetworkUtils.routedIPv6AddressCount(set));
136 
137         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad5/128"));
138         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad6/128"));
139         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad7/128"));
140         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad8/128"));
141         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad9/128"));
142         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad0/128"));
143         assertEquals(BigInteger.valueOf(7), NetworkUtils.routedIPv6AddressCount(set));
144 
145         // add4:f00:80:f7:1111::6ad4/126 eats add4:f00:8[:f7:1111::6ad{4-7}/128
146         set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/126"));
147         set.add(new IpPrefix("d00d:f00:80:f7:1111::6ade/124"));
148         set.add(new IpPrefix("f00b:a33::/112"));
149         assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
150                 NetworkUtils.routedIPv6AddressCount(set));
151     }
152 
getTimevalBytes(StructTimeval tv)153     private byte[] getTimevalBytes(StructTimeval tv) {
154         byte[] timeval = new byte[16];
155         ByteBuffer buf = ByteBuffer.wrap(timeval);
156         buf.order(ByteOrder.nativeOrder());
157         buf.putLong(tv.tv_sec);
158         buf.putLong(tv.tv_usec);
159         return timeval;
160     }
161 
testSetSockOptBytes(FileDescriptor sock, long timeValMillis)162     private void testSetSockOptBytes(FileDescriptor sock, long timeValMillis)
163             throws ErrnoException {
164         final StructTimeval writeTimeval = StructTimeval.fromMillis(timeValMillis);
165         byte[] timeval = getTimevalBytes(writeTimeval);
166         final StructTimeval readTimeval;
167 
168         NetworkUtils.setsockoptBytes(sock, SOL_SOCKET, SO_RCVTIMEO, timeval);
169         readTimeval = Os.getsockoptTimeval(sock, SOL_SOCKET, SO_RCVTIMEO);
170 
171         assertEquals(writeTimeval, readTimeval);
172     }
173 
174     @Test
testSetSockOptBytes()175     public void testSetSockOptBytes() throws ErrnoException {
176         final FileDescriptor sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
177 
178         testSetSockOptBytes(sock, 3000);
179 
180         testSetSockOptBytes(sock, 5000);
181 
182         SocketUtils.closeSocketQuietly(sock);
183     }
184 
185     @Test
testIsKernel64Bit()186     public void testIsKernel64Bit() {
187         assumeTrue(getVsrApiLevel() > Build.VERSION_CODES.TIRAMISU);
188         assertTrue(NetworkUtils.isKernel64Bit());
189     }
190 }
191