Skip to content

Instantly share code, notes, and snippets.

@Oppodelldog
Created August 10, 2022 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Oppodelldog/84c4b5b7ac051b36895bf5d618efe368 to your computer and use it in GitHub Desktop.
Save Oppodelldog/84c4b5b7ac051b36895bf5d618efe368 to your computer and use it in GitHub Desktop.
win routing - find intersecting routing entries (IPv4)
package main
import (
"fmt"
"net"
"reflect"
"syscall"
"unsafe"
)
func main() {
var routes, err = NewRouteTable().GetRoutes()
if err != nil {
panic(err)
}
var nets []net.IPNet
for _, route := range routes {
ipNet := net.IPNet{
IP: route.GetForwardDest(),
Mask: route.GetForwardMask(),
}
nets = append(nets, ipNet)
}
for i1 := 0; i1 < len(nets); i1++ {
for i2 := 0; i2 < len(nets); i2++ {
if i1 == i2 {
continue
}
if reflect.DeepEqual(nets[i1].IP, net.IP([]byte{0, 0, 0, 0})) {
continue
}
if reflect.DeepEqual(nets[i2].IP, net.IP([]byte{0, 0, 0, 0})) {
continue
}
if reflect.DeepEqual(nets[i1].Mask, net.IPMask([]byte{255, 255, 255, 255})) {
continue
}
if reflect.DeepEqual(nets[i2].Mask, net.IPMask([]byte{255, 255, 255, 255})) {
continue
}
if reflect.DeepEqual(nets[i1].IP, nets[i2].IP) {
continue
}
if netsIntersect(nets[i1], nets[i2]) {
fmt.Println("network intersection between ", nets[i1], " and ", nets[i2])
}
}
}
}
func netsIntersect(n1, n2 net.IPNet) bool {
return n1.Contains(n2.IP) || n2.Contains(n1.IP)
}
type Table struct {
iphlpapi *syscall.LazyDLL
getIpForwardTable *syscall.LazyProc
createIpForwardEntry *syscall.LazyProc
deleteIpForwardEntry *syscall.LazyProc
}
type TableRow struct {
ForwardDest [4]byte
ForwardMask [4]byte
ForwardPolicy uint32
ForwardNextHop [4]byte
ForwardIfIndex uint32
ForwardType uint32
ForwardProto uint32
ForwardAge uint32
ForwardNextHopAS uint32
ForwardMetric1 uint32
ForwardMetric2 uint32
ForwardMetric3 uint32
ForwardMetric4 uint32
ForwardMetric5 uint32
}
func (rr *TableRow) GetForwardDest() net.IP {
var ip = make(net.IP, 4)
copy(ip, rr.ForwardDest[:])
return ip
}
func (rr *TableRow) GetForwardMask() net.IPMask {
var ip = make(net.IPMask, 4)
copy(ip, rr.ForwardMask[:])
return ip
}
func (rr *TableRow) GetForwardNextHop() net.IP {
var ip = make(net.IP, 4)
copy(ip, rr.ForwardNextHop[:])
return ip
}
func NewRouteTable() *Table {
iphlpapi := syscall.NewLazyDLL("iphlpapi.dll")
getIpForwardTable := iphlpapi.NewProc("GetIpForwardTable")
return &Table{
iphlpapi: iphlpapi,
getIpForwardTable: getIpForwardTable,
}
}
func (rt *Table) GetRoutes() ([]TableRow, error) {
var bufLen uint32
rt.getIpForwardTable.Call(uintptr(0), uintptr(unsafe.Pointer(&bufLen)), 0)
var r1 uintptr
var buf = make([]byte, bufLen)
r1, _, _ = rt.getIpForwardTable.Call(uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&bufLen)), 0)
if r1 != 0 {
return nil, fmt.Errorf("failed to get the routing table, return value:%v", r1)
}
var (
num = *(*uint32)(unsafe.Pointer(&buf[0]))
routes = make([]TableRow, num)
sr = uintptr(unsafe.Pointer(&buf[0])) + unsafe.Sizeof(num)
rowSize = unsafe.Sizeof(TableRow{})
expectedBufferSize = int(bufLen)
actualBufferSize = int(unsafe.Sizeof(num) + rowSize*uintptr(num))
)
if expectedBufferSize < actualBufferSize {
return nil, fmt.Errorf("buffer exceeded the expected size, expected: %v, actual: %v", expectedBufferSize, actualBufferSize)
}
for i := 0; i < int(num); i++ {
routes[i] = *((*TableRow)(unsafe.Pointer(sr + (rowSize * uintptr(i)))))
}
return routes, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment