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.PeerIndexTable
|
||||||
import mrt.RoutingInformationBase
|
import mrt.RoutingInformationBase
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
|
@ -31,7 +32,7 @@ fun main() {
|
||||||
|
|
||||||
println(" For ${export.message.prefix} (#${export.message.sequenceNumber}) (${export.message.entries.size} entries):")
|
println(" For ${export.message.prefix} (#${export.message.sequenceNumber}) (${export.message.entries.size} entries):")
|
||||||
export.message.entries.forEach { entry ->
|
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 InetPrefix
|
||||||
import io.ktor.utils.io.ByteReadChannel
|
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.readByte
|
||||||
import io.ktor.utils.io.readByteArray
|
import io.ktor.utils.io.readByteArray
|
||||||
import io.ktor.utils.io.readInt
|
import io.ktor.utils.io.readInt
|
||||||
|
|
@ -11,6 +9,7 @@ import io.ktor.utils.io.readShort
|
||||||
import java.net.Inet6Address
|
import java.net.Inet6Address
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
data class RoutingInformationBase(
|
data class RoutingInformationBase(
|
||||||
val sequenceNumber: Int,
|
val sequenceNumber: Int,
|
||||||
|
|
@ -22,9 +21,9 @@ data class RoutingInformationBase(
|
||||||
val sequenceNumber = channel.readInt()
|
val sequenceNumber = channel.readInt()
|
||||||
|
|
||||||
val prefixLength = channel.readByte()
|
val prefixLength = channel.readByte()
|
||||||
// TODO do this immedialtyl check out prefix length if it pads
|
// TODO trim bits if prefix length is not multiple of 8
|
||||||
//channel.discardExact(3)
|
val addressBytes = channel.readByteArray(Math.ceilDiv(prefixLength.toInt(), 8)).copyOf(if (ipv6) 16 else 4)
|
||||||
val address = Inet6Address.getByAddress(channel.readByteArray(if (ipv6) 16 else 4))
|
val address = Inet6Address.getByAddress(addressBytes)
|
||||||
|
|
||||||
val entryCount = channel.readShort()
|
val entryCount = channel.readShort()
|
||||||
val entries = List(entryCount.toInt()) { _ -> Entry.read(channel) }
|
val entries = List(entryCount.toInt()) { _ -> Entry.read(channel) }
|
||||||
|
|
@ -40,26 +39,93 @@ data class RoutingInformationBase(
|
||||||
data class Entry(
|
data class Entry(
|
||||||
val peerIndex: UShort,
|
val peerIndex: UShort,
|
||||||
val originatedTime: Instant,
|
val originatedTime: Instant,
|
||||||
val attributes: ByteArray
|
val attributes: List<BgpAttribute>
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun read(channel: ByteReadChannel): Entry {
|
suspend fun read(channel: ByteReadChannel): Entry {
|
||||||
val peerIndex = channel.readShort().toUShort()
|
val peerIndex = channel.readShort().toUShort()
|
||||||
channel.discardExact(2)
|
//channel.discardExact(2)
|
||||||
|
|
||||||
val originatedTime = Instant.ofEpochSecond(channel.readInt().toLong())
|
val originatedTime = Instant.ofEpochSecond(channel.readInt().toLong())
|
||||||
|
|
||||||
val attributesLength = channel.readShort()
|
var attributesLength = channel.readShort().toInt()
|
||||||
channel.discardExact(2)
|
//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(
|
return Entry(
|
||||||
peerIndex = peerIndex,
|
peerIndex = peerIndex,
|
||||||
originatedTime = originatedTime,
|
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