45 lines
1.2 KiB
Go
45 lines
1.2 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.
|
|
|
|
package tcp
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net"
|
|
"unsafe"
|
|
)
|
|
|
|
func (c *Conn) originalDst(la, _ *net.TCPAddr) (net.Addr, error) {
|
|
var level, name int
|
|
var b []byte
|
|
if la.IP.To4() != nil {
|
|
level = ianaProtocolIP
|
|
name = sysSO_ORIGINAL_DST
|
|
b = make([]byte, sizeofSockaddrInet)
|
|
}
|
|
if la.IP.To16() != nil && la.IP.To4() == nil {
|
|
level = ianaProtocolIPv6
|
|
name = sysIP6T_SO_ORIGINAL_DST
|
|
b = make([]byte, sizeofSockaddrInet6)
|
|
}
|
|
if _, err := c.option(level, name, b); err != nil {
|
|
return nil, err
|
|
}
|
|
od := new(net.TCPAddr)
|
|
switch len(b) {
|
|
case sizeofSockaddrInet:
|
|
sa := (*sockaddrInet)(unsafe.Pointer(&b[0]))
|
|
od.IP = make(net.IP, net.IPv4len)
|
|
copy(od.IP, sa.Addr[:])
|
|
od.Port = int(binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&sa.Port))[:]))
|
|
case sizeofSockaddrInet6:
|
|
sa := (*sockaddrInet6)(unsafe.Pointer(&b[0]))
|
|
od.IP = make(net.IP, net.IPv6len)
|
|
copy(od.IP, sa.Addr[:])
|
|
od.Port = int(binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&sa.Port))[:]))
|
|
od.Zone = zoneCache.name(int(sa.Scope_id))
|
|
}
|
|
return od, nil
|
|
}
|