Commit
This commit is contained in:
parent
007a5ddfc1
commit
7664bd2092
2 changed files with 79 additions and 12 deletions
|
|
@ -4,6 +4,7 @@ import mrt.MrtExport
|
|||
import mrt.PeerIndexTable
|
||||
import mrt.RoutingInformationBase
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
fun main() {
|
||||
runBlocking {
|
||||
|
|
@ -31,7 +32,7 @@ fun main() {
|
|||
|
||||
println(" For ${export.message.prefix} (#${export.message.sequenceNumber}) (${export.message.entries.size} entries):")
|
||||
export.message.entries.forEach { entry ->
|
||||
println(" #${entry.peerIndex} | Since ${entry.originatedTime} | ${entry.attributes}")
|
||||
println(" #${entry.peerIndex} | Since ${entry.originatedTime} | ${entry.attributes.size}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ package mrt
|
|||
|
||||
import InetPrefix
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.discard
|
||||
import io.ktor.utils.io.discardExact
|
||||
import io.ktor.utils.io.readByte
|
||||
import io.ktor.utils.io.readByteArray
|
||||
import io.ktor.utils.io.readInt
|
||||
|
|
@ -11,6 +9,7 @@ import io.ktor.utils.io.readShort
|
|||
import java.net.Inet6Address
|
||||
import java.time.Instant
|
||||
import kotlin.experimental.and
|
||||
import kotlin.math.sign
|
||||
|
||||
data class RoutingInformationBase(
|
||||
val sequenceNumber: Int,
|
||||
|
|
@ -22,9 +21,9 @@ data class RoutingInformationBase(
|
|||
val sequenceNumber = channel.readInt()
|
||||
|
||||
val prefixLength = channel.readByte()
|
||||
// TODO do this immedialtyl check out prefix length if it pads
|
||||
//channel.discardExact(3)
|
||||
val address = Inet6Address.getByAddress(channel.readByteArray(if (ipv6) 16 else 4))
|
||||
// TODO trim bits if prefix length is not multiple of 8
|
||||
val addressBytes = channel.readByteArray(Math.ceilDiv(prefixLength.toInt(), 8)).copyOf(if (ipv6) 16 else 4)
|
||||
val address = Inet6Address.getByAddress(addressBytes)
|
||||
|
||||
val entryCount = channel.readShort()
|
||||
val entries = List(entryCount.toInt()) { _ -> Entry.read(channel) }
|
||||
|
|
@ -40,26 +39,93 @@ data class RoutingInformationBase(
|
|||
data class Entry(
|
||||
val peerIndex: UShort,
|
||||
val originatedTime: Instant,
|
||||
val attributes: ByteArray
|
||||
val attributes: List<BgpAttribute>
|
||||
) {
|
||||
companion object {
|
||||
suspend fun read(channel: ByteReadChannel): Entry {
|
||||
val peerIndex = channel.readShort().toUShort()
|
||||
channel.discardExact(2)
|
||||
//channel.discardExact(2)
|
||||
|
||||
val originatedTime = Instant.ofEpochSecond(channel.readInt().toLong())
|
||||
|
||||
val attributesLength = channel.readShort()
|
||||
channel.discardExact(2)
|
||||
var attributesLength = channel.readShort().toInt()
|
||||
//channel.discardExact(2)
|
||||
|
||||
val attributes = mutableListOf<BgpAttribute>()
|
||||
|
||||
while (attributesLength > 0) {
|
||||
val (attribute, bytesRead) = BgpAttribute.read(channel)
|
||||
attributes.add(attribute)
|
||||
attributesLength -= bytesRead
|
||||
//println("Attribute length: $attributesLength (-$bytesRead)")
|
||||
}
|
||||
|
||||
val attributes = channel.readByteArray(attributesLength.toInt())
|
||||
|
||||
return Entry(
|
||||
peerIndex = peerIndex,
|
||||
originatedTime = originatedTime,
|
||||
attributes = attributes
|
||||
attributes = attributes.toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class BgpAttribute(
|
||||
val optional: Boolean,
|
||||
val transitive: Boolean,
|
||||
val partial: Boolean,
|
||||
val type: Type,
|
||||
val value: ByteArray
|
||||
) {
|
||||
companion object {
|
||||
suspend fun read(channel: ByteReadChannel): Pair<BgpAttribute, Int> {
|
||||
val flags = channel.readByte()
|
||||
val optional = flags.rotateRight(7).and(0x1) == 1.toByte()
|
||||
val transitive = flags.rotateRight(6).and(0x1) == 1.toByte()
|
||||
val partial = flags.rotateRight(5).and(0x1) == 1.toByte()
|
||||
val extendedLength = flags.rotateRight(4).and(0x1) == 1.toByte()
|
||||
|
||||
//println("Flags: 0x${flags.toHexString()}")
|
||||
|
||||
val typeCode = channel.readByte()
|
||||
//println("Type: 0x${typeCode.toHexString()}")
|
||||
val type = Type.fromCode(typeCode)
|
||||
|
||||
//println("Ext length: $extendedLength")
|
||||
val length = if (extendedLength) channel.readShort().toUShort().toInt() else channel.readByte().toUByte().toInt()
|
||||
//println("Length: $length")
|
||||
|
||||
val value = channel.readByteArray(length)
|
||||
|
||||
return Pair(BgpAttribute(
|
||||
optional = optional,
|
||||
transitive = transitive,
|
||||
partial = partial,
|
||||
type = type,
|
||||
value = value
|
||||
), 3 + (if (extendedLength) 1 else 0) + length)
|
||||
}
|
||||
}
|
||||
|
||||
enum class Type(val code: Byte) {
|
||||
Origin(1),
|
||||
AsPath(2),
|
||||
NextHop(3),
|
||||
MultiExitDisc(4),
|
||||
LocalPref(5),
|
||||
AtomicAggregate(6),
|
||||
Aggregator(7),
|
||||
Community(8),
|
||||
MpReachNlri(14),
|
||||
ExtendedCommunity(16),
|
||||
LargeCommunity(32),
|
||||
OnlyToCustomer(35);
|
||||
|
||||
companion object {
|
||||
fun fromCode(code: Byte): Type {
|
||||
return Type.entries.first { it.code == code }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue