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> { fun getMacFromIP(ip: Int): Pair<ByteArray?, Int> {
val gw = routeTable.getGateway(ip) val gw = routeTable.getGateway(ip)
if (gw == null) { if (gw == null || gw == 0) {
// not found in route table, just use the ip // 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) val value = content.get(ip)
return Pair(value?.mac, ip) return Pair(value?.mac, ip)
} else { } else {
// gw not null, try find the gw's mac // gw not null, try find the gw's mac
TerminalLogger.debugf { "ARP: IP=${ipToString(ip)} uses gateway=${ipToString(gw)}." }
val value = content.get(gw) val value = content.get(gw)
return Pair(value?.mac, gw) return Pair(value?.mac, gw)
} }
@ -128,20 +130,14 @@ class ARPWaitList {
// just skip the packet // just skip the packet
continue continue
} }
TerminalLogger.debugf { "ARP resumed flow: ${describeIpv4Packet(item.originData)}" }
val packet = formEthernetPacket(node.mac.toByteArray(), mac.toByteArray(), item.originData) val packet = formEthernetPacket(node.mac.toByteArray(), mac.toByteArray(), item.originData)
val size = packet.remaining() 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) { if (encrypted != null) {
val data = SDLData.newBuilder() sendPacketToNet(node, mac, encrypted, size.toLong())
.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())
} }
} }

View File

@ -22,7 +22,6 @@ import java.net.Inet4Address
import java.net.Socket import java.net.Socket
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.util.zip.CRC32
interface Iface { interface Iface {
suspend fun doInit() suspend fun doInit()
@ -101,24 +100,16 @@ interface IfaceTun: Iface {
arp.dipaddr = arp.sipaddr arp.dipaddr = arp.sipaddr
arp.sipaddr = node.deviceConfig.ip.netAddr arp.sipaddr = node.deviceConfig.ip.netAddr
val bytes = arp.marshalToBytes() val bytesBuf = arp.marshalToBytes()
val encrypted = node.aes.encrypt(bytes) val bytesArr = ByteArray(bytesBuf.remaining())
bytesBuf.get(bytesArr)
val encrypted = node.aes.encrypt(bytesArr)
if (encrypted != null) { if (encrypted != null) {
val dstmac = arp.dhwaddr.toByteString() 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 { TerminalLogger.debugf {
"send arp reply to ${macToString(dstmac)}" "send arp reply to ${macToString(dstmac)}"
} }
val content = encodeToUDPMessage(data, PacketType.Data) sendPacketToNet(node, dstmac, encrypted, 0)
sendPacketToNet(node, dstmac, content, 0)
} }
} }
} }
@ -166,17 +157,28 @@ interface IfaceTun: Iface {
TerminalLogger.infof { "dropping tun packet due to not authed" } TerminalLogger.infof { "dropping tun packet due to not authed" }
return 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 buffer = ByteBuffer.wrap(data, 12, 8).order(ByteOrder.BIG_ENDIAN)
val srcip = buffer.getInt() val srcip = buffer.getInt()
val dstip = buffer.getInt() val dstip = buffer.getInt()
TerminalLogger.debugf { "got ${data.size} bytes from tun" } 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)) { if (!node.config.allowRouting && (srcip != node.deviceConfig.ip.netAddr)) {
TerminalLogger.infof { "dropping routed packet from tun" } TerminalLogger.infof { "dropping routed packet from tun" }
return 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) val (arpinfo, gwip) = arpTable.getMacFromIP(dstip)
if (arpinfo == null) { if (arpinfo == null) {
println("arp info is null") println("arp info is null")
@ -190,27 +192,11 @@ interface IfaceTun: Iface {
val buffer = arpinfo + node.mac.toByteArray() + val buffer = arpinfo + node.mac.toByteArray() +
byteArrayOf((EtherType.IPV4.toInt() shr 8).toByte(), EtherType.IPV4.toByte()) + byteArrayOf((EtherType.IPV4.toInt() shr 8).toByte(), EtherType.IPV4.toByte()) +
data data
val size = buffer.size
val crc = CRC32() val encrypted = node.aes.encrypt(buffer)
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)
if (encrypted != null) { if (encrypted != null) {
val mac = arpinfo.toByteString() val mac = arpinfo.toByteString()
val data = SDLData.newBuilder() sendPacketToNet(node, mac, encrypted, size.toLong())
.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())
} }
} }
} }
@ -307,4 +293,4 @@ fun macToString(mac: Mac): String {
} }
return result.joinToString(":") return result.joinToString(":")
} }
*/ */

View File

@ -103,12 +103,19 @@ class RouteTable() {
fun getGateway(ip: Int): Int? { fun getGateway(ip: Int): Int? {
try { try {
lock.readLock().lock() lock.readLock().lock()
var bestGw: Int? = null
var bestMaskLen = -1
for (item in routeInfo) { for (item in routeInfo) {
if ((ip and item.mask) == item.maskedAddr) { 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 { } finally {
lock.readLock().unlock() lock.readLock().unlock()
} }
@ -122,11 +129,17 @@ class RouteTable2(
val routeInfo: Array<RouteDetail> = initRouteInfo.toTypedArray() val routeInfo: Array<RouteDetail> = initRouteInfo.toTypedArray()
fun getGeteway(ip: Int): Int? { fun getGeteway(ip: Int): Int? {
var bestGw: Int? = null
var bestMaskLen = -1
for (item in routeInfo) { for (item in routeInfo) {
if ((ip and item.mask) == item.maskedAddr) { 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.config.AESConfig
import com.jihe.punchnet.sdlan.logs.TerminalLogger 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.ByteBuffer
import java.nio.ByteOrder
import javax.crypto.Cipher import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
@ -10,6 +14,8 @@ import javax.crypto.spec.SecretKeySpec
class AES private constructor () { class AES private constructor () {
private var _secret: ByteArray = ByteArray(0) private var _secret: ByteArray = ByteArray(0)
private var _iv: ByteArray = ByteArray(0) private var _iv: ByteArray = ByteArray(0)
private var _algorithm: String = "aes"
private var _regionId: Long = 0
companion object { companion object {
private var instance: AES? = null private var instance: AES? = null
get() { get() {
@ -29,13 +35,17 @@ class AES private constructor () {
return _secret.size != 0 return _secret.size != 0
} }
fun setSecret(secret: ByteArray?) { fun setSecret(secret: ByteArray?, algorithm: String = "aes", regionId: Long = 0) {
if (secret == null) { if (secret == null) {
_secret = ByteArray(0) _secret = ByteArray(0)
_iv = ByteArray(0) _iv = ByteArray(0)
_algorithm = "aes"
_regionId = 0
} else { } else {
_secret = secret _secret = secret
_iv = _secret.sliceArray(0..<16) _iv = _secret.sliceArray(0..<16)
_algorithm = algorithm.lowercase()
_regionId = regionId
} }
} }
@ -43,14 +53,11 @@ class AES private constructor () {
if (!isAuthorized()) { if (!isAuthorized()) {
return null return null
} }
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
try { try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv)) val input = ByteArray(content.remaining())
val output = ByteBuffer.allocate(cipher.getOutputSize(content.remaining())) content.get(input)
cipher.doFinal(content, output) val encrypted = encrypt(input) ?: return null
output.flip() return ByteBuffer.wrap(encrypted)
return output
} catch (e: Exception) { } catch (e: Exception) {
println("failed to encrypt: ${e.toString()}") println("failed to encrypt: ${e.toString()}")
return null return null
@ -62,12 +69,15 @@ class AES private constructor () {
TerminalLogger.errorf { "not authed, so not encrypting" } TerminalLogger.errorf { "not authed, so not encrypting" }
return null 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 { try {
val encrypted = cipher.doFinal(content) return when (_algorithm) {
return encrypted "aes" -> aesCrypt(Cipher.ENCRYPT_MODE, content)
"chacha20" -> chacha20Crypt(content)
else -> {
TerminalLogger.errorf { "unsupported encryption algorithm: $_algorithm" }
null
}
}
} catch (e: Exception) { } catch (e: Exception) {
TerminalLogger.errorf {"encrypt failed: $e"} TerminalLogger.errorf {"encrypt failed: $e"}
return null return null
@ -78,14 +88,11 @@ class AES private constructor () {
if (!isAuthorized()) { if (!isAuthorized()) {
return null 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 { try {
val output = ByteBuffer.allocate(cipher.getOutputSize(ciphered.remaining())) val input = ByteArray(ciphered.remaining())
cipher.doFinal(ciphered, output) ciphered.get(input)
output.flip() val decrypted = decrypt(input) ?: return null
return output return ByteBuffer.wrap(decrypted)
} catch (e: Exception) { } catch (e: Exception) {
return null return null
} }
@ -95,16 +102,40 @@ class AES private constructor () {
if (!isAuthorized()) { if (!isAuthorized()) {
return null 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 { try {
val decrypted = cipher.doFinal(ciphered) return when (_algorithm) {
return decrypted "aes" -> aesCrypt(Cipher.DECRYPT_MODE, ciphered)
"chacha20" -> chacha20Crypt(ciphered)
else -> null
}
} catch (e: Exception) { } catch (e: Exception) {
return null 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 { fun byteArray2Hex(array: ByteArray): String {
@ -113,4 +144,4 @@ fun byteArray2Hex(array: ByteArray): String {
result.add(String.format("0x%02x", item.toInt() and 0xff)) result.add(String.format("0x%02x", item.toInt() and 0xff))
} }
return result.joinToString(" ") return result.joinToString(" ")
} }

View File

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