mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 20:44:38 +03:00
88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
package iphlpapi
|
||
|
||
import (
|
||
"fmt"
|
||
"net"
|
||
"unsafe"
|
||
)
|
||
|
||
/*
|
||
对于路由表,预期的方法是:
|
||
查询 0.0.0.0/0 获得原始默认路由
|
||
然后为 vpn 服务器添加默认路由
|
||
之后就根据需要下发vpn路由完事。
|
||
对于0.0.0.0/0 vpn 路由,可以尝试更低的跃点数,也可以尝试分为2个。
|
||
重新连接时可以删除vpn接口的所有非链路路由表。
|
||
路由表格式:
|
||
目标网络 uint32 掩码位数 byte低6位 vpn/默认网关 byte 高1位
|
||
*/
|
||
|
||
// 太低的值添加路由时会返回 106 错误
|
||
const routeMetric = 93
|
||
|
||
type RouteRow struct {
|
||
ForwardDest [4]byte //目标网络
|
||
ForwardMask [4]byte //掩码
|
||
ForwardPolicy uint32 //ForwardPolicy:0x0
|
||
ForwardNextHop [4]byte //网关
|
||
ForwardIfIndex uint32 // 网卡索引 id
|
||
ForwardType uint32 //3 本地接口 4 远端接口
|
||
ForwardProto uint32 //3静态路由 2本地接口 5EGP网关
|
||
ForwardAge uint32 //存在时间 秒
|
||
ForwardNextHopAS uint32 //下一跳自治域号码 0
|
||
ForwardMetric1 uint32 //度量衡(跃点数),根据 ForwardProto 不同意义不同。
|
||
ForwardMetric2 uint32
|
||
ForwardMetric3 uint32
|
||
ForwardMetric4 uint32
|
||
ForwardMetric5 uint32
|
||
}
|
||
|
||
func (rr *RouteRow) GetForwardDest() net.IP {
|
||
return net.IP(rr.ForwardDest[:])
|
||
}
|
||
func (rr *RouteRow) GetForwardMask() net.IP {
|
||
return net.IP(rr.ForwardMask[:])
|
||
}
|
||
func (rr *RouteRow) GetForwardNextHop() net.IP {
|
||
return net.IP(rr.ForwardNextHop[:])
|
||
}
|
||
|
||
func GetRoutes() ([]RouteRow, error) {
|
||
buf := make([]byte, 4+unsafe.Sizeof(RouteRow{}))
|
||
buf_len := uint32(len(buf))
|
||
|
||
proc_getIpForwardTable.Call(uintptr(unsafe.Pointer(&buf[0])),
|
||
uintptr(unsafe.Pointer(&buf_len)), 0)
|
||
|
||
var r1 uintptr
|
||
for i := 0; i < 5; i++ {
|
||
buf = make([]byte, buf_len)
|
||
r1, _, _ = proc_getIpForwardTable.Call(uintptr(unsafe.Pointer(&buf[0])),
|
||
uintptr(unsafe.Pointer(&buf_len)), 0)
|
||
if r1 == 122 {
|
||
continue
|
||
}
|
||
break
|
||
}
|
||
|
||
if r1 != 0 {
|
||
return nil, fmt.Errorf("Failed to get the routing table, return value:%v", r1)
|
||
}
|
||
|
||
num := *(*uint32)(unsafe.Pointer(&buf[0]))
|
||
routes := make([]RouteRow, num)
|
||
sr := uintptr(unsafe.Pointer(&buf[0])) + unsafe.Sizeof(num)
|
||
rowSize := unsafe.Sizeof(RouteRow{})
|
||
|
||
// 安全检查
|
||
if len(buf) < int((unsafe.Sizeof(num) + rowSize*uintptr(num))) {
|
||
return nil, fmt.Errorf("System error: GetIpForwardTable returns the number is too long, beyond the buffer。")
|
||
}
|
||
|
||
for i := uint32(0); i < num; i++ {
|
||
routes[i] = *((*RouteRow)(unsafe.Pointer(sr + (rowSize * uintptr(i)))))
|
||
}
|
||
|
||
return routes, nil
|
||
}
|