Skip to content

Commit

Permalink
Added more ipv4 option tests
Browse files Browse the repository at this point in the history
  • Loading branch information
compscidr committed Sep 17, 2024
1 parent 14b2c2b commit b12ab64
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 20 deletions.
34 changes: 20 additions & 14 deletions knet/src/main/kotlin/com/jasonernst/knet/ip/options/Ipv4Option.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,28 @@ abstract class Ipv4Option(
// we don't apply it directly to length because we want to construct the option
// with the correct length which includes the first two fields
val length = stream.get().toUByte()
if (kind == Ipv4OptionType.Security.kind) {
options.add(Ipv4OptionSecurity.fromStream(stream, isCopied, optionClass, length))
} else {
if (stream.remaining() < length.toInt() - 2) {
throw PacketTooShortException("Can't parse ipv4 option because we don't have enough bytes left for the data")
if (stream.remaining() < length.toInt() - 2) {
throw PacketTooShortException("Can't parse ipv4 option because we don't have enough bytes left for the data")
}
when (kind) {
Ipv4OptionType.Security.kind -> {
options.add(Ipv4OptionSecurity.fromStream(stream, isCopied, optionClass, length))
}
Ipv4OptionType.LooseSourceRouting.kind -> {
options.add(Ipv4OptionLooseSourceAndRecordRoute.fromStream(stream, isCopied, optionClass, length))
}
val data = ByteArray(length.toInt() - 2)
stream.get(data)
else -> {
val data = ByteArray(length.toInt() - 2)
stream.get(data)

val type =
try {
Ipv4OptionType.fromKind(kind)
} catch (e: NoSuchElementException) {
Ipv4OptionType.Unknown
}
options.add(Ipv4OptionUnknown(isCopied, optionClass, type, length, data))
val type =
try {
Ipv4OptionType.fromKind(kind)
} catch (e: NoSuchElementException) {
Ipv4OptionType.Unknown
}
options.add(Ipv4OptionUnknown(isCopied, optionClass, type, length, data))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jasonernst.knet.ip.options

import com.jasonernst.knet.PacketTooShortException
import org.slf4j.LoggerFactory
import java.nio.ByteBuffer
import java.nio.ByteOrder

Expand All @@ -21,32 +22,38 @@ import java.nio.ByteOrder
* recorded route full) and the routing is to be based on the
* destination address field.
*/
class Ipv4OptionLooseSourceAndRecordRoute(
data class Ipv4OptionLooseSourceAndRecordRoute(
override val isCopied: Boolean = true,
override val optionClass: Ipv4OptionClassType = Ipv4OptionClassType.Control,
override val type: Ipv4OptionType = Ipv4OptionType.LooseSourceRouting,
override val size: UByte = MIN_OPTION_SIZE,
val pointer: UByte,
val routeData: ByteArray = ByteArray(0),
) : Ipv4Option(isCopied, optionClass, type, size) {
) : Ipv4Option(isCopied, optionClass, type, size = (routeData.size.toUByte() + MIN_OPTION_SIZE).toUByte()) {
companion object {
val MIN_OPTION_SIZE: UByte = 3u
private val logger = LoggerFactory.getLogger(Ipv4OptionLooseSourceAndRecordRoute::class.java)

fun fromStream(
stream: ByteBuffer,
dataLength: Int,
isCopied: Boolean,
optionClass: Ipv4OptionClassType,
size: UByte,
): Ipv4OptionLooseSourceAndRecordRoute {
if (stream.remaining() < MIN_OPTION_SIZE.toInt() - 2) {
logger.debug("SIZE: $size, remaining: ${stream.remaining()}")
if (stream.remaining() < (size - 2u).toInt()) {
throw PacketTooShortException(
"Stream must have at least ${MIN_OPTION_SIZE - 2u} " +
"Stream must have at least ${size - 2u} " +
"remaining bytes remaining to parse Ipv4OptionLooseSourceAndRecordRoute, we only have " +
"${stream.remaining()} bytes",
)
}
val pointer = stream.get().toUByte()
val dataLength = size.toInt() - MIN_OPTION_SIZE.toInt()
val routingData = ByteArray(dataLength)
stream.get(routingData)
return Ipv4OptionLooseSourceAndRecordRoute(
isCopied = isCopied,
optionClass = optionClass,
pointer = pointer,
routeData = routingData,
)
Expand All @@ -63,4 +70,28 @@ class Ipv4OptionLooseSourceAndRecordRoute(
.put(routeData)
return buffer.array()
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as Ipv4OptionLooseSourceAndRecordRoute

if (isCopied != other.isCopied) return false
if (optionClass != other.optionClass) return false
if (type != other.type) return false
if (pointer != other.pointer) return false
if (!routeData.contentEquals(other.routeData)) return false

return true
}

override fun hashCode(): Int {
var result = isCopied.hashCode()
result = 31 * result + optionClass.hashCode()
result = 31 * result + type.hashCode()
result = 31 * result + pointer.hashCode()
result = 31 * result + routeData.contentHashCode()
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ data class Ipv4OptionSecurity(
override fun toByteArray(order: ByteOrder): ByteArray {
logger.debug("SIZE: $size")
val buffer = ByteBuffer.allocate(size.toInt())
buffer.order(order)
buffer.put(super.toByteArray(order))
buffer.putShort(security.kind.toShort())
buffer.putShort(compartment.toShort())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,43 @@ class Ipv4OptionTest {
Ipv4Option.parseOptions(stream)
}
}

@Test
fun ipv4OptionLooseSourceAndRecordRoute() {
val option = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x02))
val stream = ByteBuffer.wrap(option.toByteArray())
logger.debug("Stream length: ${stream.limit()}")
val parsedOptions = Ipv4Option.parseOptions(stream)
assertEquals(1, parsedOptions.size)
assertEquals(option, parsedOptions[0])
}

@Test fun ipv4OptionLooseSourceAndRecordRouteTooShort() {
val option = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x02))
val stream = ByteBuffer.wrap(option.toByteArray())
stream.limit(stream.limit() - 1)
stream.position(2)
assertThrows<PacketTooShortException> {
Ipv4OptionLooseSourceAndRecordRoute.fromStream(stream, true, Ipv4OptionClassType.DebuggingAndMeasurement, 6u)
}
}

@Test fun ipv4OptionLooseSourceAndRecordRouteEquals() {
val option1 = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x02))
val option2 = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x02))
assertEquals(option1, option2)

val option3 = Ipv4OptionLooseSourceAndRecordRoute(pointer = 1u, routeData = byteArrayOf(0x00, 0x01, 0x02))
assertNotEquals(option1, option3)

val option4 = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x03))
assertNotEquals(option1, option4)
}

@Test fun ipv4OptionLooseSourceAndRecordRouteHashCode() {
val map: MutableMap<Ipv4OptionLooseSourceAndRecordRoute, String> = mutableMapOf()
val option1 = Ipv4OptionLooseSourceAndRecordRoute(pointer = 0u, routeData = byteArrayOf(0x00, 0x01, 0x02))
map[option1] = "test"
assertTrue(map.containsKey(option1))
}
}

0 comments on commit b12ab64

Please sign in to comment.