1 /* 2 * Copyright (C) 2023 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.dhcp6 18 19 import androidx.test.filters.SmallTest 20 import androidx.test.runner.AndroidJUnit4 21 import com.android.net.module.util.HexDump 22 import com.android.testutils.assertThrows 23 import kotlin.test.assertEquals 24 import kotlin.test.assertTrue 25 import org.junit.Test 26 import org.junit.runner.RunWith 27 28 @RunWith(AndroidJUnit4::class) 29 @SmallTest 30 class Dhcp6PacketTest { 31 @Test testDecodeDhcp6SolicitPacketnull32 fun testDecodeDhcp6SolicitPacket() { 33 val solicitHex = 34 // Solicit, Transaction ID 35 "01000F51" + 36 // client identifier option(option_len=12) 37 "0001000C0003001B024CCBFFFE5F6EA9" + 38 // elapsed time option(option_len=2) 39 "000800020000" + 40 // IA_PD option(option_len=41, including IA prefix option) 41 "00190029DE3570F50000000000000000" + 42 // IA prefix option(option_len=25) 43 "001A001900000000000000004000000000000000000000000000000000" 44 val bytes = HexDump.hexStringToByteArray(solicitHex) 45 val packet = Dhcp6Packet.decode(bytes, bytes.size) 46 assertTrue(packet is Dhcp6SolicitPacket) 47 } 48 49 @Test testDecodeDhcp6SolicitPacket_incorrectOptionLengthnull50 fun testDecodeDhcp6SolicitPacket_incorrectOptionLength() { 51 val solicitHex = 52 // Solicit, Transaction ID 53 "01000F51" + 54 // client identifier option(option_len=12) 55 "0001000C0003001B024CCBFFFE5F6EA9" + 56 // elapsed time option(wrong option_len=4) 57 "000800040000" + 58 // IA_PD option(option_len=41, including IA prefix option) 59 "00190029DE3570F50000000000000000" + 60 // IA prefix option(option_len=25) 61 "001A001900000000000000004000000000000000000000000000000000" 62 val bytes = HexDump.hexStringToByteArray(solicitHex) 63 assertThrows(Dhcp6Packet.ParseException::class.java) { 64 Dhcp6Packet.decode(bytes, bytes.size) 65 } 66 } 67 68 @Test testDecodeDhcp6SolicitPacket_lastTruncatedOptionnull69 fun testDecodeDhcp6SolicitPacket_lastTruncatedOption() { 70 val solicitHex = 71 // Solicit, Transaction ID 72 "01000F51" + 73 // client identifier option(option_len=12) 74 "0001000C0003001B024CCBFFFE5F6EA9" + 75 // elapsed time option(option_len=2) 76 "000800020000" + 77 // IA_PD option(option_len=41, including IA prefix option) 78 "00190029DE3570F50000000000000000" + 79 // IA prefix option(option_len=25, missing one byte) 80 "001A0019000000000000000040000000000000000000000000000000" 81 val bytes = HexDump.hexStringToByteArray(solicitHex) 82 assertThrows(Dhcp6Packet.ParseException::class.java) { 83 Dhcp6Packet.decode(bytes, bytes.size) 84 } 85 } 86 87 @Test testDecodeDhcp6SolicitPacket_middleTruncatedOptionnull88 fun testDecodeDhcp6SolicitPacket_middleTruncatedOption() { 89 val solicitHex = 90 // Solicit, Transaction ID 91 "01000F51" + 92 // client identifier option(option_len=12, missing one byte) 93 "0001000C0003001B024CCBFFFE5F6E" + 94 // elapsed time option(option_len=2) 95 "000800020000" + 96 // IA_PD option(option_len=41, including IA prefix option) 97 "00190029DE3570F50000000000000000" + 98 // IA prefix option(option_len=25) 99 "001A001900000000000000004000000000000000000000000000000000" 100 val bytes = HexDump.hexStringToByteArray(solicitHex) 101 assertThrows(Dhcp6Packet.ParseException::class.java) { 102 Dhcp6Packet.decode(bytes, bytes.size) 103 } 104 } 105 106 @Test testDecodeDhcp6AdvertisePacketnull107 fun testDecodeDhcp6AdvertisePacket() { 108 val advertiseHex = 109 // Advertise, Transaction ID 110 "0200078A" + 111 // server identifier option(option_len=10) 112 "0002000A0003000186C9B26AED4D" + 113 // client identifier option(option_len=12) 114 "0001000C0003001B024CCBFFFE5F6EA9" + 115 // IA_PD option(option_len=70, including IA prefix option) 116 "001900460CDDCA0C000000CF0000014C" + 117 // IA prefix option(option_len=25, prefix="2401:fa00:49c:412::/64") 118 "001A00190000019F0000064F402401FA00049C04810000000000000000" + 119 // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64") 120 "001A00190000019F0000A8C040FDFD9ED6795000010000000000000000" 121 val bytes = HexDump.hexStringToByteArray(advertiseHex) 122 val packet = Dhcp6Packet.decode(bytes, bytes.size) 123 assertTrue(packet is Dhcp6AdvertisePacket) 124 } 125 126 @Test testDecodeDhcp6SolicitPacket_unsupportedOptionnull127 fun testDecodeDhcp6SolicitPacket_unsupportedOption() { 128 val advertiseHex = 129 // Advertise, Transaction ID 130 "0200078A" + 131 // server identifier option(option_len=10) 132 "0002000A0003000186C9B26AED4D" + 133 // client identifier option(option_len=12) 134 "0001000C0003001B024CCBFFFE5F6EA9" + 135 // SOL_MAX_RT (don't support this option yet) 136 "005200040000003C" + 137 // IA_PD option(option_len=70, including IA prefix option) 138 "001900460CDDCA0C000000CF0000014C" + 139 // IA prefix option(option_len=25, prefix="2401:fa00:49c:412::/64") 140 "001A00190000019F0000064F402401FA00049C04810000000000000000" + 141 // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64") 142 "001A00190000019F0000A8C040FDFD9ED6795000010000000000000000" 143 val bytes = HexDump.hexStringToByteArray(advertiseHex) 144 // The unsupported option will be skipped normally and won't throw ParseException. 145 val packet = Dhcp6Packet.decode(bytes, bytes.size) 146 assertTrue(packet is Dhcp6AdvertisePacket) 147 } 148 149 @Test testDecodeDhcp6ReplyPacketnull150 fun testDecodeDhcp6ReplyPacket() { 151 val replyHex = 152 // Reply, Transaction ID 153 "07000A47" + 154 // server identifier option(option_len=10) 155 "0002000A0003000186C9B26AED4D" + 156 // client identifier option(option_len=12) 157 "0001000C0003001B02FBBAFFFEB7BC71" + 158 // SOL_MAX_RT (don't support this option yet) 159 "005200040000003c" + 160 // Rapid Commit 161 "000e0000" + 162 // DNS recursive server (don't support this opton yet) 163 "00170010fdfd9ed6795000000000000000000001" + 164 // IA_PD option(option_len=70, including IA prefix option) 165 "0019004629cc56c7000000d300000152" + 166 // IA prefix option(option_len=25, prefix="2401:fa00:49c:412::/64", preferred=400, 167 // valid=1623) 168 "001a00190000019000000657402401fa00049c04120000000000000000" + 169 // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64", preferred=423, 170 // valid=43200) 171 "001a0019000001a70000a8c040fdfd9ed6795000020000000000000000" 172 val bytes = HexDump.hexStringToByteArray(replyHex) 173 val packet = Dhcp6Packet.decode(bytes, bytes.size) 174 assertTrue(packet is Dhcp6ReplyPacket) 175 assertEquals(400, packet.prefixDelegation.minimalPreferredLifetime) 176 assertEquals(1623, packet.prefixDelegation.minimalValidLifetime) 177 } 178 179 @Test testGetMinimalPreferredValidLifetimenull180 fun testGetMinimalPreferredValidLifetime() { 181 val replyHex = 182 // Reply, Transaction ID 183 "07000A47" + 184 // server identifier option(option_len=10) 185 "0002000A0003000186C9B26AED4D" + 186 // client identifier option(option_len=12) 187 "0001000C0003001B02FBBAFFFEB7BC71" + 188 // SOL_MAX_RT (don't support this option yet) 189 "005200040000003c" + 190 // Rapid Commit 191 "000e0000" + 192 // DNS recursive server (don't support this opton yet) 193 "00170010fdfd9ed6795000000000000000000001" + 194 // IA_PD option(option_len=70, including IA prefix option) 195 "0019004629cc56c7000000d300000152" + 196 // IA prefix option(option_len=25, prefix="2401:fa00:49c:412::/64", preferred=0, 197 // valid=0) 198 "001a00190000000000000000402401fa00049c04120000000000000000" + 199 // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64", preferred=423, 200 // valid=43200) 201 "001a0019000001a70000a8c040fdfd9ed6795000020000000000000000" 202 val bytes = HexDump.hexStringToByteArray(replyHex) 203 val packet = Dhcp6Packet.decode(bytes, bytes.size) 204 assertTrue(packet is Dhcp6ReplyPacket) 205 assertEquals(423, packet.prefixDelegation.minimalPreferredLifetime) 206 assertEquals(43200, packet.prefixDelegation.minimalValidLifetime) 207 } 208 209 @Test testStatusCodeOptionWithStatusMessagenull210 fun testStatusCodeOptionWithStatusMessage() { 211 val replyHex = 212 // Reply, Transaction ID 213 "07000A47" + 214 // server identifier option(option_len=10) 215 "0002000A0003000186C9B26AED4D" + 216 // client identifier option(option_len=12) 217 "0001000C0003001B02FBBAFFFEB7BC71" + 218 // SOL_MAX_RT (don't support this option yet) 219 "005200040000003c" + 220 // Rapid Commit 221 "000e0000" + 222 // DNS recursive server (don't support this opton yet) 223 "00170010fdfd9ed6795000000000000000000001" + 224 // IA_PD option (t1=t2=0, empty prefix) 225 "0019000c000000000000000000000000" + 226 // Status code option: status code=NoPrefixAvail 227 "000d00150006" + 228 // Status code option: status message="no prefix available" 229 "6e6f2070726566697820617661696c61626c65" 230 val bytes = HexDump.hexStringToByteArray(replyHex) 231 val packet = Dhcp6Packet.decode(bytes, bytes.size) 232 assertTrue(packet is Dhcp6ReplyPacket) 233 assertEquals(0, packet.mPrefixDelegation.iaid) 234 assertEquals(0, packet.mPrefixDelegation.t1) 235 assertEquals(0, packet.mPrefixDelegation.t2) 236 assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAIL, packet.mStatusCode) 237 } 238 239 @Test testStatusCodeOptionWithoutStatusMessagenull240 fun testStatusCodeOptionWithoutStatusMessage() { 241 val replyHex = 242 // Reply, Transaction ID 243 "07000A47" + 244 // server identifier option(option_len=10) 245 "0002000A0003000186C9B26AED4D" + 246 // client identifier option(option_len=12) 247 "0001000C0003001B02FBBAFFFEB7BC71" + 248 // SOL_MAX_RT (don't support this option yet) 249 "005200040000003c" + 250 // Rapid Commit 251 "000e0000" + 252 // DNS recursive server (don't support this opton yet) 253 "00170010fdfd9ed6795000000000000000000001" + 254 // IA_PD option (t1=t2=0, empty prefix) 255 "0019000c000000000000000000000000" + 256 // Status code option: status code=NoPrefixAvail 257 "000d00020006" 258 val bytes = HexDump.hexStringToByteArray(replyHex) 259 val packet = Dhcp6Packet.decode(bytes, bytes.size) 260 assertTrue(packet is Dhcp6ReplyPacket) 261 assertEquals(0, packet.mPrefixDelegation.iaid) 262 assertEquals(0, packet.mPrefixDelegation.t1) 263 assertEquals(0, packet.mPrefixDelegation.t2) 264 assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAIL, packet.mStatusCode) 265 } 266 267 @Test testStatusCodeOptionInIaPdWithStatusMessagenull268 fun testStatusCodeOptionInIaPdWithStatusMessage() { 269 val replyHex = 270 // Reply, Transaction ID 271 "07000A47" + 272 // server identifier option(option_len=10) 273 "0002000A0003000186C9B26AED4D" + 274 // client identifier option(option_len=12) 275 "0001000C0003001B02FBBAFFFEB7BC71" + 276 // SOL_MAX_RT (don't support this option yet) 277 "005200040000003c" + 278 // Rapid Commit 279 "000e0000" + 280 // DNS recursive server (don't support this opton yet) 281 "00170010fdfd9ed6795000000000000000000001" + 282 // IA_PD option (t1=t2=0, status code=NoPrefixAvail, 283 // status message="no prefix available") 284 "00190025000000000000000000000000000d00150006" + 285 "6e6f2070726566697820617661696c61626c65" 286 val bytes = HexDump.hexStringToByteArray(replyHex) 287 val packet = Dhcp6Packet.decode(bytes, bytes.size) 288 assertTrue(packet is Dhcp6ReplyPacket) 289 assertEquals(0, packet.mPrefixDelegation.iaid) 290 assertEquals(0, packet.mPrefixDelegation.t1) 291 assertEquals(0, packet.mPrefixDelegation.t2) 292 assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAIL, packet.mPrefixDelegation.statusCode) 293 } 294 295 @Test testStatusCodeOptionInIaPdWithoutStatusMessagenull296 fun testStatusCodeOptionInIaPdWithoutStatusMessage() { 297 val replyHex = 298 // Reply, Transaction ID 299 "07000A47" + 300 // server identifier option(option_len=10) 301 "0002000A0003000186C9B26AED4D" + 302 // client identifier option(option_len=12) 303 "0001000C0003001B02FBBAFFFEB7BC71" + 304 // SOL_MAX_RT (don't support this option yet) 305 "005200040000003c" + 306 // Rapid Commit 307 "000e0000" + 308 // DNS recursive server (don't support this opton yet) 309 "00170010fdfd9ed6795000000000000000000001" + 310 // IA_PD option (t1=t2=0, status code=NoPrefixAvail) 311 "00190012000000000000000000000000000d00020006" 312 val bytes = HexDump.hexStringToByteArray(replyHex) 313 val packet = Dhcp6Packet.decode(bytes, bytes.size) 314 assertTrue(packet is Dhcp6ReplyPacket) 315 assertEquals(0, packet.mPrefixDelegation.iaid) 316 assertEquals(0, packet.mPrefixDelegation.t1) 317 assertEquals(0, packet.mPrefixDelegation.t2) 318 assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAIL, packet.mPrefixDelegation.statusCode) 319 } 320 321 @Test testStatusCodeOptionWithTruncatedStatusMessagenull322 fun testStatusCodeOptionWithTruncatedStatusMessage() { 323 val replyHex = 324 // Reply, Transaction ID 325 "07000A47" + 326 // server identifier option(option_len=10) 327 "0002000A0003000186C9B26AED4D" + 328 // client identifier option(option_len=12) 329 "0001000C0003001B02FBBAFFFEB7BC71" + 330 // SOL_MAX_RT (don't support this option yet) 331 "005200040000003c" + 332 // Rapid Commit 333 "000e0000" + 334 // DNS recursive server (don't support this opton yet) 335 "00170010fdfd9ed6795000000000000000000001" + 336 // Status code option: len=21, status code=NoPrefixAvail 337 "000d00150006" + 338 // Status code option: truncated status message="no prefix available" 339 "6e6f2070726566697820617661696c6162" 340 val bytes = HexDump.hexStringToByteArray(replyHex) 341 assertThrows(Dhcp6Packet.ParseException::class.java) { 342 Dhcp6Packet.decode(bytes, bytes.size) 343 } 344 } 345 346 @Test testStatusCodeOptionInIaPdWithTruncatedStatusMessagenull347 fun testStatusCodeOptionInIaPdWithTruncatedStatusMessage() { 348 val replyHex = 349 // Reply, Transaction ID 350 "07000A47" + 351 // server identifier option(option_len=10) 352 "0002000A0003000186C9B26AED4D" + 353 // client identifier option(option_len=12) 354 "0001000C0003001B02FBBAFFFEB7BC71" + 355 // SOL_MAX_RT (don't support this option yet) 356 "005200040000003c" + 357 // Rapid Commit 358 "000e0000" + 359 // DNS recursive server (don't support this opton yet) 360 "00170010fdfd9ed6795000000000000000000001" + 361 // IA_PD option (t1=t2=0, empty prefix) 362 "00190025000000000000000000000000" + 363 // Status code option: len=21, status code=NoPrefixAvail 364 "000d00150006" + 365 // truncated status message="no prefix available") 366 "6e6f2070726566697820617661696c6162" 367 val bytes = HexDump.hexStringToByteArray(replyHex) 368 assertThrows(Dhcp6Packet.ParseException::class.java) { 369 Dhcp6Packet.decode(bytes, bytes.size) 370 } 371 } 372 } 373