Skip to content

Commit

Permalink
Merge pull request #9 from compscidr/ipv6extensions
Browse files Browse the repository at this point in the history
WiP: ipv6 extension headers
  • Loading branch information
compscidr authored Oct 9, 2024
2 parents b3a95af + 50690e7 commit e639b78
Show file tree
Hide file tree
Showing 52 changed files with 2,468 additions and 317 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Kotlin user-space network stack. This can be used for:
- [ ] RFC 2474: https://datatracker.ietf.org/doc/html/rfc2474
- [x] IPv6:
- [X] WiP: RFC 8200: https://datatracker.ietf.org/doc/html/rfc8200
- [X] RFC 6564: https://www.rfc-editor.org/rfc/rfc6564
- [ ] RFC 7045: https://www.rfc-editor.org/rfc/rfc7045.html
- [ ] RFC: 4302: https://datatracker.ietf.org/doc/html/rfc4302
- [ ] RFC: 4303: https://datatracker.ietf.org/doc/html/rfc4303
- [x] ICMP (via https://github.com/compscidr/icmp)
- [] TCP
- [] UDP
- [ ] TCP
- [ ] UDP
12 changes: 11 additions & 1 deletion knet/src/main/kotlin/com/jasonernst/knet/ip/IpHeader.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.jasonernst.knet.ip

import com.jasonernst.knet.PacketTooShortException
import com.jasonernst.knet.ip.Ipv4Header.Companion.IP4_MIN_HEADER_LENGTH
import com.jasonernst.knet.ip.v4.Ipv4Header
import com.jasonernst.knet.ip.v4.Ipv4Header.Companion.IP4_MIN_HEADER_LENGTH
import com.jasonernst.knet.ip.v6.Ipv6Header
import org.slf4j.LoggerFactory
import java.net.Inet4Address
import java.net.Inet6Address
Expand All @@ -18,6 +20,14 @@ interface IpHeader {
const val IP4_VERSION: UByte = 4u
const val IP6_VERSION: UByte = 6u

/**
* Helper function so that we can ensure the payload length is a multiple of 8
*/
fun closestDivisibleBy(
initialValue: UInt,
divisor: UInt,
): UInt = (initialValue + divisor - 1u) / divisor * divisor

fun fromStream(stream: ByteBuffer): IpHeader {
val start = stream.position()
if (stream.remaining() < 1) {
Expand Down
75 changes: 0 additions & 75 deletions knet/src/main/kotlin/com/jasonernst/knet/ip/Ipv6ExtensionHeader.kt

This file was deleted.

121 changes: 0 additions & 121 deletions knet/src/main/kotlin/com/jasonernst/knet/ip/Ipv6Header.kt

This file was deleted.

31 changes: 0 additions & 31 deletions knet/src/main/kotlin/com/jasonernst/knet/ip/Ipv6HopByHopOption.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.jasonernst.knet.ip
package com.jasonernst.knet.ip.v4

import com.jasonernst.icmp_common.Checksum
import com.jasonernst.knet.PacketTooShortException
import com.jasonernst.knet.ip.IpHeader
import com.jasonernst.knet.ip.IpHeader.Companion.IP4_VERSION
import com.jasonernst.knet.ip.options.Ipv4Option
import com.jasonernst.knet.ip.options.Ipv4Option.Companion.parseOptions
import com.jasonernst.knet.ip.IpHeader.Companion.closestDivisibleBy
import com.jasonernst.knet.ip.IpType
import com.jasonernst.knet.ip.v4.options.Ipv4Option
import com.jasonernst.knet.ip.v4.options.Ipv4Option.Companion.parseOptions
import org.slf4j.LoggerFactory
import java.net.Inet4Address
import java.net.InetAddress
import java.nio.ByteBuffer
import java.nio.ByteOrder
import kotlin.experimental.or
import kotlin.math.ceil
import kotlin.math.min

/**
* Internet Protocol Version 4 Header Implementation.
Expand All @@ -26,8 +30,8 @@ data class Ipv4Header(
val dscp: UByte = 0u,
// 2-bits, explicit congestion notification.
val ecn: UByte = 0u,
// 16-bits, IP packet, including the header
private val totalLength: UShort = 0u,
// 16-bits, IP packet, including the header: default to a just the header with no payload
private val totalLength: UShort = IP4_MIN_HEADER_LENGTH.toUShort(),
// 16-bits, groups fragments of a single IPv4 datagram.
val id: UShort = 0u,
// if the packet is marked as don't fragment and we can't fit it in a single packet, drop it.
Expand Down Expand Up @@ -310,9 +314,12 @@ data class Ipv4Header(
*
*/
fun fragment(
maxSize: UInt,
maxSize: UInt, // max size includes the header size
payload: ByteArray,
): List<Pair<Ipv4Header, ByteArray>> {
if (maxSize.toInt() % 8 != 0) {
throw IllegalArgumentException("Fragment max size must be divisible by 8")
}
if (dontFragment) {
throw IllegalArgumentException("Cannot fragment packets marked as don't fragment")
}
Expand All @@ -325,11 +332,17 @@ data class Ipv4Header(
"The smallest fragment size is ${IP4_MIN_FRAGMENT_PAYLOAD.toInt()} bytes because it must align on a 64-bit boundary",
)
}
var payloadPerPacket = maxSize - getHeaderLength()
var lastFragment = false
var payloadPosition = 0u
var payloadPerPacket = min(payload.size - payloadPosition.toInt(), closestDivisibleBy(maxSize - getHeaderLength(), 8u).toInt())
logger.debug("PAYLOAD PER PACKET: $payloadPerPacket HEADERSIZE: ${getHeaderLength()}")
if (payloadPosition.toInt() + payloadPerPacket == payload.size) {
lastFragment = true
}

var isFirstFragment = true
while (payloadPosition < payload.size.toUInt()) {
logger.debug("$payloadPosition:${payloadPosition + payloadPerPacket}")
logger.debug("$payloadPosition:${payloadPosition + payloadPerPacket.toUInt()}")
val offsetIn64BitOctets = payloadPosition / 8u
var newOptions = options
var newIhl = ihl
Expand All @@ -353,10 +366,10 @@ data class Ipv4Header(
ihl = newIhl,
dscp = dscp,
ecn = ecn,
totalLength = (getHeaderLength() + payloadPerPacket).toUShort(),
totalLength = (getHeaderLength() + payloadPerPacket.toUInt()).toUShort(),
id = id,
dontFragment = false,
lastFragment = payloadPosition >= getHeaderLength(),
lastFragment = lastFragment,
fragmentOffset = offsetIn64BitOctets.toUShort(),
ttl = ttl,
protocol = protocol,
Expand All @@ -367,9 +380,10 @@ data class Ipv4Header(
logger.debug("payload len:${newHeader.getPayloadLength()}")
val newPayload = payload.copyOfRange(payloadPosition.toInt(), payloadPosition.toInt() + payloadPerPacket.toInt())
packetList.add(Pair(newHeader, newPayload))
payloadPosition += payloadPerPacket
if (payloadPosition + payloadPerPacket > payload.size.toUInt()) {
payloadPerPacket = payload.size.toUInt() - payloadPosition
payloadPosition += payloadPerPacket.toUInt()
if (payloadPosition + payloadPerPacket.toUInt() > payload.size.toUInt()) {
payloadPerPacket = (payload.size.toUInt() - payloadPosition).toInt()
lastFragment = true
}
}
return packetList
Expand Down
Loading

0 comments on commit e639b78

Please sign in to comment.