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: ""} }