69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
|
package server
|
||
|
|
||
|
/**
|
||
|
* WARNING WARNING WARNING
|
||
|
* This file contains MANY DIRTY HACKS, and most of them made much assume to go internal code layout.
|
||
|
* For every new go version, you MUST try to use every function, make sure they didn't panic for you.
|
||
|
*/
|
||
|
|
||
|
// WARZONE BEGINS HERE! MIND YOUR HEAD!
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"net"
|
||
|
"golang.org/x/sys/unix"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
SO_ORIGINAL_DST = 80
|
||
|
)
|
||
|
|
||
|
func GetFDFromTCPConn(conn *net.TCPConn) int {
|
||
|
// Actual fd is stored at: (*(*TCPConn).conn.fd).sysfd
|
||
|
v := reflect.ValueOf(*conn)
|
||
|
c := v.FieldByName("conn")
|
||
|
fdp := c.FieldByName("fd")
|
||
|
fd := reflect.Indirect(fdp)
|
||
|
sysfd := fd.FieldByName("sysfd")
|
||
|
return int(sysfd.Int())
|
||
|
}
|
||
|
|
||
|
func GetAddr4FromFD(fd int) *net.TCPAddr {
|
||
|
mtuinfo, err := unix.GetsockoptIPv6MTUInfo(fd, unix.IPPROTO_IP, SO_ORIGINAL_DST)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
addr := mtuinfo.Addr
|
||
|
/*
|
||
|
RawSockaddrInet6 layout:
|
||
|
Family 2byte ignore or assert == AF_INET
|
||
|
Port 2byte ipv4 port
|
||
|
Flowinfo 4byte ipv4 address
|
||
|
Addr 16byte ignore for ipv4
|
||
|
Scope_id 4byte ignore for ipv4
|
||
|
*/
|
||
|
addr.Flowinfo = be32toh(addr.Flowinfo)
|
||
|
a, b, c, d := byte(addr.Flowinfo >> 24), byte((addr.Flowinfo >> 16) & 255), byte((addr.Flowinfo >> 8) & 255), byte(addr.Flowinfo & 255)
|
||
|
ip := net.IPv4(a, b, c, d)
|
||
|
return &net.TCPAddr{IP: ip, Port: int(be16toh(addr.Port)), Zone: ""}
|
||
|
}
|
||
|
|
||
|
func GetAddr6FromFD(fd int) *net.TCPAddr {
|
||
|
mtuinfo, err := unix.GetsockoptIPv6MTUInfo(fd, unix.IPPROTO_IPV6, SO_ORIGINAL_DST)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
addr := mtuinfo.Addr
|
||
|
/*
|
||
|
RawSockaddrInet6 layout:
|
||
|
Family 2byte ignore or assert == AF_INET6
|
||
|
Port 2byte ipv6 port
|
||
|
Flowinfo 4byte ipv6 flowinfo ignore
|
||
|
Addr 16byte ipv6 addr
|
||
|
Scope_id 4byte ipv6 scope id ignore
|
||
|
*/
|
||
|
v6addr := make(net.IP, 16)
|
||
|
// Make GC happy?
|
||
|
copy(v6addr, addr.Addr[:])
|
||
|
return &net.TCPAddr{IP: v6addr, Port: int(be16toh(addr.Port)), Zone: ""}
|
||
|
}
|