summaryrefslogtreecommitdiffhomepage
path: root/server/sockopt_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/sockopt_linux.go')
-rw-r--r--server/sockopt_linux.go24
1 files changed, 22 insertions, 2 deletions
diff --git a/server/sockopt_linux.go b/server/sockopt_linux.go
index d238823c..436591e9 100644
--- a/server/sockopt_linux.go
+++ b/server/sockopt_linux.go
@@ -24,14 +24,21 @@ import (
"unsafe"
)
-func DialTCPTimeoutWithMD5Sig(host string, port int, key string, msec int) (*net.TCPConn, error) {
+func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) {
var family int
- var ra syscall.Sockaddr
+ var ra, la syscall.Sockaddr
ip := net.ParseIP(host)
if ip == nil {
return nil, fmt.Errorf("invalid ip: %s", host)
}
+ l := net.ParseIP(localAddr)
+ if l == nil {
+ return nil, fmt.Errorf("invalid local ip: %s", localAddr)
+ }
+ if (ip.To4() != nil) != (l.To4() != nil) {
+ return nil, fmt.Errorf("remote and local ip address family is not same")
+ }
switch {
case ip.To4() != nil:
family = syscall.AF_INET
@@ -42,6 +49,11 @@ func DialTCPTimeoutWithMD5Sig(host string, port int, key string, msec int) (*net
i.Addr[idx] = ip.To4()[idx]
}
ra = i
+ j := &syscall.SockaddrInet4{}
+ for idx, _ := range j.Addr {
+ j.Addr[idx] = l.To4()[idx]
+ }
+ la = j
default:
family = syscall.AF_INET6
i := &syscall.SockaddrInet6{
@@ -51,6 +63,11 @@ func DialTCPTimeoutWithMD5Sig(host string, port int, key string, msec int) (*net
i.Addr[idx] = ip[idx]
}
ra = i
+ j := &syscall.SockaddrInet6{}
+ for idx, _ := range j.Addr {
+ j.Addr[idx] = l[idx]
+ }
+ la = j
}
sotype := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC
proto := 0
@@ -73,6 +90,9 @@ func DialTCPTimeoutWithMD5Sig(host string, port int, key string, msec int) (*net
if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil {
return nil, os.NewSyscallError("setsockopt", err)
}
+ if err = syscall.Bind(fd, la); err != nil {
+ return nil, os.NewSyscallError("bind", err)
+ }
tcpconn := func(fd uintptr) (*net.TCPConn, error) {
fi := os.NewFile(uintptr(fd), "")