fix some warning

This commit is contained in:
stavid 2026-06-20 13:28:13 +08:00
parent 4b1bae0e55
commit 5954894102
5 changed files with 102 additions and 77 deletions

View File

@ -44,12 +44,14 @@ class ARPTable(
fun getMacFromIP(ip: Int): Pair<ByteArray?, Int> {
val gw = routeTable.getGateway(ip)
if (gw == null) {
if (gw == null || gw == 0) {
// not found in route table, just use the ip
TerminalLogger.debugf { "ARP: IP=${ipToString(ip)} has no gateway (gw=$gw), querying IP directly." }
val value = content.get(ip)
return Pair(value?.mac, ip)
} else {
// gw not null, try find the gw's mac
TerminalLogger.debugf { "ARP: IP=${ipToString(ip)} uses gateway=${ipToString(gw)}." }
val value = content.get(gw)
return Pair(value?.mac, gw)
}
@ -128,20 +130,14 @@ class ARPWaitList {
// just skip the packet
continue
}
TerminalLogger.debugf { "ARP resumed flow: ${describeIpv4Packet(item.originData)}" }
val packet = formEthernetPacket(node.mac.toByteArray(), mac.toByteArray(), item.originData)
val size = packet.remaining()
val encrypted = node.aes.encrypt(packet)
val packetBytes = ByteArray(size)
packet.get(packetBytes)
val encrypted = node.aes.encrypt(packetBytes)
if (encrypted != null) {
val data = SDLData.newBuilder()
.setIsP2P(true)
.setNetworkId(networkid)
.setTtl(2)
.setSrcMac(node.mac)
.setDstMac(mac)
.setData(encrypted.toByteString())
.build()
val msg = encodeToUDPMessage(data, PacketType.Data)
sendPacketToNet(node, mac, msg, size.toLong())
sendPacketToNet(node, mac, encrypted, size.toLong())
}
}

View File

@ -22,7 +22,6 @@ import java.net.Inet4Address
import java.net.Socket
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.zip.CRC32
interface Iface {
suspend fun doInit()
@ -101,24 +100,16 @@ interface IfaceTun: Iface {
arp.dipaddr = arp.sipaddr
arp.sipaddr = node.deviceConfig.ip.netAddr
val bytes = arp.marshalToBytes()
val encrypted = node.aes.encrypt(bytes)
val bytesBuf = arp.marshalToBytes()
val bytesArr = ByteArray(bytesBuf.remaining())
bytesBuf.get(bytesArr)
val encrypted = node.aes.encrypt(bytesArr)
if (encrypted != null) {
val dstmac = arp.dhwaddr.toByteString()
val data = SDLData.newBuilder()
.setIsP2P(true)
.setTtl(2)
.setNetworkId(node.networkID.get())
.setSrcMac(node.mac)
.setDstMac(dstmac)
.setData(encrypted.toByteString())
.build()
TerminalLogger.debugf {
"send arp reply to ${macToString(dstmac)}"
}
val content = encodeToUDPMessage(data, PacketType.Data)
sendPacketToNet(node, dstmac, content, 0)
sendPacketToNet(node, dstmac, encrypted, 0)
}
}
}
@ -166,17 +157,28 @@ interface IfaceTun: Iface {
TerminalLogger.infof { "dropping tun packet due to not authed" }
return
}
val version = (data[0].toInt() ushr 4) and 0x0f
if (version != 4) {
TerminalLogger.debugf { "dropping non-IPv4 packet from tun: version=$version, bytes=${data.size}" }
return
}
val buffer = ByteBuffer.wrap(data, 12, 8).order(ByteOrder.BIG_ENDIAN)
val srcip = buffer.getInt()
val dstip = buffer.getInt()
TerminalLogger.debugf { "got ${data.size} bytes from tun" }
TerminalLogger.debugf { "IPv4 flow from tun: ${describeIpv4Packet(data)}" }
if (!node.config.allowRouting && (srcip != node.deviceConfig.ip.netAddr)) {
TerminalLogger.infof { "dropping routed packet from tun" }
return
}
if (node.config.dropMulticast && (dstip.toUInt() shr 28) == 14u) {
TerminalLogger.debugf { "dropping multicast packet from tun: ${com.jihe.punchnet.sdlan.utils.ipToString(dstip)}" }
return
}
val (arpinfo, gwip) = arpTable.getMacFromIP(dstip)
if (arpinfo == null) {
println("arp info is null")
@ -190,27 +192,11 @@ interface IfaceTun: Iface {
val buffer = arpinfo + node.mac.toByteArray() +
byteArrayOf((EtherType.IPV4.toInt() shr 8).toByte(), EtherType.IPV4.toByte()) +
data
val crc = CRC32()
crc.update(buffer)
val cksum = ByteBuffer.allocate(4)
.putInt(crc.value.toInt())
.array()
val packet = buffer + cksum
val size = packet.size
val encrypted = node.aes.encrypt(packet)
val size = buffer.size
val encrypted = node.aes.encrypt(buffer)
if (encrypted != null) {
val mac = arpinfo.toByteString()
val data = SDLData.newBuilder()
.setIsP2P(true)
.setNetworkId(node.networkID.get())
.setTtl(2)
.setSrcMac(node.mac)
.setDstMac(mac)
.setData(encrypted.toByteString())
.build()
val msg = encodeToUDPMessage(data, PacketType.Data)
sendPacketToNet(node, mac, msg, size.toLong())
sendPacketToNet(node, mac, encrypted, size.toLong())
}
}
}

View File

@ -103,12 +103,19 @@ class RouteTable() {
fun getGateway(ip: Int): Int? {
try {
lock.readLock().lock()
var bestGw: Int? = null
var bestMaskLen = -1
for (item in routeInfo) {
if ((ip and item.mask) == item.maskedAddr) {
return item.gw
val maskLen = Integer.bitCount(item.mask)
if (maskLen > bestMaskLen) {
bestMaskLen = maskLen
bestGw = item.gw
}
}
return null
}
TerminalLogger.debugf { "RouteTable LPM: ip=${com.jihe.punchnet.sdlan.utils.ipToString(ip)} -> bestGw=${bestGw?.let { com.jihe.punchnet.sdlan.utils.ipToString(it) } ?: "null"} (maskLen=$bestMaskLen)" }
return bestGw
} finally {
lock.readLock().unlock()
}
@ -122,11 +129,17 @@ class RouteTable2(
val routeInfo: Array<RouteDetail> = initRouteInfo.toTypedArray()
fun getGeteway(ip: Int): Int? {
var bestGw: Int? = null
var bestMaskLen = -1
for (item in routeInfo) {
if ((ip and item.mask) == item.maskedAddr) {
return item.gw
val maskLen = Integer.bitCount(item.mask)
if (maskLen > bestMaskLen) {
bestMaskLen = maskLen
bestGw = item.gw
}
}
return null
}
return bestGw
}
}

View File

@ -2,7 +2,11 @@ package com.jihe.punchnet.sdlan.utils
import com.jihe.punchnet.sdlan.config.AESConfig
import com.jihe.punchnet.sdlan.logs.TerminalLogger
import org.bouncycastle.crypto.engines.ChaCha7539Engine
import org.bouncycastle.crypto.params.KeyParameter
import org.bouncycastle.crypto.params.ParametersWithIV
import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
@ -10,6 +14,8 @@ import javax.crypto.spec.SecretKeySpec
class AES private constructor () {
private var _secret: ByteArray = ByteArray(0)
private var _iv: ByteArray = ByteArray(0)
private var _algorithm: String = "aes"
private var _regionId: Long = 0
companion object {
private var instance: AES? = null
get() {
@ -29,13 +35,17 @@ class AES private constructor () {
return _secret.size != 0
}
fun setSecret(secret: ByteArray?) {
fun setSecret(secret: ByteArray?, algorithm: String = "aes", regionId: Long = 0) {
if (secret == null) {
_secret = ByteArray(0)
_iv = ByteArray(0)
_algorithm = "aes"
_regionId = 0
} else {
_secret = secret
_iv = _secret.sliceArray(0..<16)
_algorithm = algorithm.lowercase()
_regionId = regionId
}
}
@ -43,14 +53,11 @@ class AES private constructor () {
if (!isAuthorized()) {
return null
}
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv))
val output = ByteBuffer.allocate(cipher.getOutputSize(content.remaining()))
cipher.doFinal(content, output)
output.flip()
return output
val input = ByteArray(content.remaining())
content.get(input)
val encrypted = encrypt(input) ?: return null
return ByteBuffer.wrap(encrypted)
} catch (e: Exception) {
println("failed to encrypt: ${e.toString()}")
return null
@ -62,12 +69,15 @@ class AES private constructor () {
TerminalLogger.errorf { "not authed, so not encrypting" }
return null
}
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv))
try {
val encrypted = cipher.doFinal(content)
return encrypted
return when (_algorithm) {
"aes" -> aesCrypt(Cipher.ENCRYPT_MODE, content)
"chacha20" -> chacha20Crypt(content)
else -> {
TerminalLogger.errorf { "unsupported encryption algorithm: $_algorithm" }
null
}
}
} catch (e: Exception) {
TerminalLogger.errorf {"encrypt failed: $e"}
return null
@ -78,14 +88,11 @@ class AES private constructor () {
if (!isAuthorized()) {
return null
}
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
cipher.init(Cipher.DECRYPT_MODE, keyspec, IvParameterSpec(_iv))
try {
val output = ByteBuffer.allocate(cipher.getOutputSize(ciphered.remaining()))
cipher.doFinal(ciphered, output)
output.flip()
return output
val input = ByteArray(ciphered.remaining())
ciphered.get(input)
val decrypted = decrypt(input) ?: return null
return ByteBuffer.wrap(decrypted)
} catch (e: Exception) {
return null
}
@ -95,16 +102,40 @@ class AES private constructor () {
if (!isAuthorized()) {
return null
}
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
cipher.init(Cipher.DECRYPT_MODE, keyspec, IvParameterSpec(_iv))
try {
val decrypted = cipher.doFinal(ciphered)
return decrypted
return when (_algorithm) {
"aes" -> aesCrypt(Cipher.DECRYPT_MODE, ciphered)
"chacha20" -> chacha20Crypt(ciphered)
else -> null
}
} catch (e: Exception) {
return null
}
}
private fun aesCrypt(mode: Int, content: ByteArray): ByteArray {
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
cipher.init(mode, keyspec, IvParameterSpec(_iv))
return cipher.doFinal(content)
}
private fun chacha20Crypt(content: ByteArray): ByteArray {
val engine = ChaCha7539Engine()
val nonce = chacha20Nonce()
engine.init(true, ParametersWithIV(KeyParameter(_secret), nonce))
val output = ByteArray(content.size)
engine.processBytes(content, 0, content.size, output, 0)
return output
}
private fun chacha20Nonce(): ByteArray {
return ByteBuffer.allocate(12)
.order(ByteOrder.BIG_ENDIAN)
.putLong(0L)
.putInt(_regionId.toInt())
.array()
}
}
fun byteArray2Hex(array: ByteArray): String {

View File

@ -109,7 +109,6 @@ class RSA private constructor () {
}
pubkeyStr = pubFile.readText()
println("pub key is ${pubkeyStr}")
}
fun encrypt(input: ByteArray, use_private_key: Boolean = true): ByteArray {