60 lines
1.3 KiB
Go
60 lines
1.3 KiB
Go
// Copyright 2016 Mikio Hara. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build darwin dragonfly freebsd openbsd
|
|
|
|
package tcp
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
func (*Conn) originalDst(la, ra *net.TCPAddr) (net.Addr, error) {
|
|
f, err := os.Open("/dev/pf")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
fd := f.Fd()
|
|
b := make([]byte, sizeofPfiocNatlook)
|
|
nl := (*pfiocNatlook)(unsafe.Pointer(&b[0]))
|
|
if ra.IP.To4() != nil {
|
|
copy(nl.Saddr[:net.IPv4len], ra.IP.To4())
|
|
copy(nl.Daddr[:net.IPv4len], la.IP.To4())
|
|
nl.Af = sysAF_INET
|
|
}
|
|
if ra.IP.To16() != nil && ra.IP.To4() == nil {
|
|
copy(nl.Saddr[:], ra.IP)
|
|
copy(nl.Daddr[:], la.IP)
|
|
nl.Af = sysAF_INET6
|
|
}
|
|
nl.setPort(ra.Port, la.Port)
|
|
nl.Proto = ianaProtocolTCP
|
|
ioc := uintptr(sysDIOCNATLOOK)
|
|
for _, dir := range []byte{sysPF_OUT, sysPF_IN} {
|
|
nl.Direction = dir
|
|
err = ioctl(fd, int(ioc), b)
|
|
if err == nil || err != syscall.ENOENT {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
return nil, os.NewSyscallError("ioctl", err)
|
|
}
|
|
od := new(net.TCPAddr)
|
|
od.Port = nl.rdPort()
|
|
switch nl.Af {
|
|
case sysAF_INET:
|
|
od.IP = make(net.IP, net.IPv4len)
|
|
copy(od.IP, nl.Rdaddr[:net.IPv4len])
|
|
case sysAF_INET6:
|
|
od.IP = make(net.IP, net.IPv6len)
|
|
copy(od.IP, nl.Rdaddr[:])
|
|
}
|
|
return od, nil
|
|
}
|